Merge tag 'amd-drm-next-5.16-2021-10-22' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-5.16-2021-10-22:

amdgpu:
- PSP fix for resume
- XGMI fixes
- Interrupt fix in device tear down
- Renoir USB-C DP alt mode fix for resume
- DP 2.0 fixes
- Yellow Carp display fixes
- Misc display fixes
- RAS fixes
- IP Discovery enumeration fixes
- VGH fixes
- SR-IOV fixes
- Revert ChromeOS workaround in display code
- Cyan Skillfish fixes

amdkfd:
- Fix error handling in gpu memory allocation
- Fix build warnings with some configs
- SVM fixes

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211022183112.4574-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2021-10-27 10:38:38 +10:00
89 changed files with 1337 additions and 1541 deletions

View File

@@ -902,6 +902,7 @@ F: include/uapi/linux/psp-sev.h
AMD DISPLAY CORE
M: Harry Wentland <harry.wentland@amd.com>
M: Leo Li <sunpeng.li@amd.com>
M: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
L: amd-gfx@lists.freedesktop.org
S: Supported
T: git https://gitlab.freedesktop.org/agd5f/linux.git

View File

@@ -73,10 +73,8 @@ amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce
amdgpu-y += \
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \
nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \
beige_goby_reg_init.o yellow_carp_reg_init.o cyan_skillfish_reg_init.o
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o
# add DF block
amdgpu-y += \

View File

@@ -307,6 +307,8 @@ static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev)
adev->ip_blocks[i].status.late_initialized = true;
}
amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);

View File

@@ -1503,7 +1503,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
err_node_allow:
amdgpu_bo_unref(&bo);
drm_gem_object_put(gobj);
/* Don't unreserve system mem limit twice */
goto err_reserve_limit;
err_bo_create:

View File

@@ -2398,10 +2398,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (!adev->gmc.xgmi.pending_reset)
amdgpu_amdkfd_device_init(adev);
r = amdgpu_amdkfd_resume_iommu(adev);
if (r)
goto init_failed;
amdgpu_fru_get_product_info(adev);
init_failed:
@@ -3839,10 +3835,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
amdgpu_fbdev_fini(adev);
amdgpu_irq_fini_hw(adev);
amdgpu_device_ip_fini_early(adev);
amdgpu_irq_fini_hw(adev);
ttm_device_clear_dma_mappings(&adev->mman.bdev);
amdgpu_gart_dummy_page_fini(adev);

View File

@@ -108,6 +108,8 @@ static const char *hw_id_names[HW_ID_MAX] = {
[HDP_HWID] = "HDP",
[SDMA0_HWID] = "SDMA0",
[SDMA1_HWID] = "SDMA1",
[SDMA2_HWID] = "SDMA2",
[SDMA3_HWID] = "SDMA3",
[ISP_HWID] = "ISP",
[DBGU_IO_HWID] = "DBGU_IO",
[DF_HWID] = "DF",
@@ -505,6 +507,10 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
break;
}
}
/* some IP discovery tables on Navy Flounder don't have this set correctly */
if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) &&
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2)))
adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1;
if (vcn_harvest_count == adev->vcn.num_vcn_inst) {
adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
@@ -736,6 +742,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(1, 0, 1):
case IP_VERSION(2, 0, 2):
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 3):
case IP_VERSION(2, 1, 0):
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 2):
@@ -745,8 +752,6 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 3):
amdgpu_device_ip_block_add(adev, &dm_ip_block);
break;
case IP_VERSION(2, 0, 3):
break;
default:
return -EINVAL;
}
@@ -1120,10 +1125,13 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
case IP_VERSION(7, 4, 0):
case IP_VERSION(7, 4, 1):
case IP_VERSION(7, 4, 4):
adev->nbio.funcs = &nbio_v7_4_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;
break;
case IP_VERSION(7, 4, 4):
adev->nbio.funcs = &nbio_v7_4_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg_ald;
break;
case IP_VERSION(7, 2, 0):
case IP_VERSION(7, 2, 1):
case IP_VERSION(7, 5, 0):
@@ -1134,12 +1142,15 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 3, 1):
case IP_VERSION(2, 3, 2):
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
break;
case IP_VERSION(3, 3, 0):
case IP_VERSION(3, 3, 1):
case IP_VERSION(3, 3, 2):
case IP_VERSION(3, 3, 3):
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg_sc;
break;
default:
break;

View File

@@ -65,7 +65,6 @@ static int psp_securedisplay_terminate(struct psp_context *psp);
*
* This new sequence is required for
* - Arcturus and onwards
* - Navi12 and onwards
*/
static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp)
{
@@ -77,7 +76,9 @@ static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp
}
switch (adev->ip_versions[MP0_HWIP][0]) {
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 4):
case IP_VERSION(11, 0, 5):
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 9):
case IP_VERSION(11, 0, 11):
@@ -1291,6 +1292,29 @@ static int psp_ras_unload(struct psp_context *psp)
return psp_ta_unload(psp, &psp->ras_context.context);
}
static void psp_ras_ta_check_status(struct psp_context *psp)
{
struct ta_ras_shared_memory *ras_cmd =
(struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
switch (ras_cmd->ras_status) {
case TA_RAS_STATUS__ERROR_UNSUPPORTED_IP:
dev_warn(psp->adev->dev,
"RAS WARNING: cmd failed due to unsupported ip\n");
break;
case TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ:
dev_warn(psp->adev->dev,
"RAS WARNING: cmd failed due to unsupported error injection\n");
break;
case TA_RAS_STATUS__SUCCESS:
break;
default:
dev_warn(psp->adev->dev,
"RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
break;
}
}
int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
{
struct ta_ras_shared_memory *ras_cmd;
@@ -1325,10 +1349,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
dev_warn(psp->adev->dev,
"RAS internal register access blocked\n");
if (ras_cmd->ras_status == TA_RAS_STATUS__ERROR_UNSUPPORTED_IP)
dev_warn(psp->adev->dev, "RAS WARNING: cmd failed due to unsupported ip\n");
else if (ras_cmd->ras_status)
dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
psp_ras_ta_check_status(psp);
}
return ret;
@@ -2622,6 +2643,12 @@ static int psp_resume(void *handle)
goto failed;
}
ret = psp_rl_load(adev);
if (ret) {
dev_err(adev->dev, "PSP load RL failed!\n");
goto failed;
}
if (adev->gmc.xgmi.num_physical_nodes > 1) {
ret = psp_xgmi_initialize(psp, false, true);
/* Warning the XGMI seesion initialize failure

View File

@@ -112,7 +112,12 @@ static bool amdgpu_ras_check_bad_page_unlock(struct amdgpu_ras *con,
static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
uint64_t addr);
#ifdef CONFIG_X86_MCE_AMD
static void amdgpu_register_bad_pages_mca_notifier(void);
static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev);
struct mce_notifier_adev_list {
struct amdgpu_device *devs[MAX_GPU_INSTANCE];
int num_gpu;
};
static struct mce_notifier_adev_list mce_adev_list;
#endif
void amdgpu_ras_set_error_query_ready(struct amdgpu_device *adev, bool ready)
@@ -2108,7 +2113,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
#ifdef CONFIG_X86_MCE_AMD
if ((adev->asic_type == CHIP_ALDEBARAN) &&
(adev->gmc.xgmi.connected_to_cpu))
amdgpu_register_bad_pages_mca_notifier();
amdgpu_register_bad_pages_mca_notifier(adev);
#endif
return 0;
@@ -2605,24 +2610,18 @@ void amdgpu_release_ras_context(struct amdgpu_device *adev)
#ifdef CONFIG_X86_MCE_AMD
static struct amdgpu_device *find_adev(uint32_t node_id)
{
struct amdgpu_gpu_instance *gpu_instance;
int i;
struct amdgpu_device *adev = NULL;
mutex_lock(&mgpu_info.mutex);
for (i = 0; i < mce_adev_list.num_gpu; i++) {
adev = mce_adev_list.devs[i];
for (i = 0; i < mgpu_info.num_gpu; i++) {
gpu_instance = &(mgpu_info.gpu_ins[i]);
adev = gpu_instance->adev;
if (adev->gmc.xgmi.connected_to_cpu &&
if (adev && adev->gmc.xgmi.connected_to_cpu &&
adev->gmc.xgmi.physical_node_id == node_id)
break;
adev = NULL;
}
mutex_unlock(&mgpu_info.mutex);
return adev;
}
@@ -2718,8 +2717,18 @@ static struct notifier_block amdgpu_bad_page_nb = {
.priority = MCE_PRIO_UC,
};
static void amdgpu_register_bad_pages_mca_notifier(void)
static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev)
{
/*
* Add the adev to the mce_adev_list.
* During mode2 reset, amdgpu device is temporarily
* removed from the mgpu_info list which can cause
* page retirement to fail.
* Use this list instead of mgpu_info to find the amdgpu
* device on which the UMC error was reported.
*/
mce_adev_list.devs[mce_adev_list.num_gpu++] = adev;
/*
* Register the x86 notifier only once
* with MCE subsystem.

View File

@@ -1101,7 +1101,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
*exceed_err_limit = true;
dev_err(adev->dev,
"RAS records:%d exceed threshold:%d, "
"maybe retire this GPU?",
"GPU will not be initialized. Replace this GPU or increase the threshold",
control->ras_num_recs, ras->bad_page_cnt_threshold);
}
} else {

View File

@@ -1235,7 +1235,7 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm)
*
*/
bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
unsigned long end)
unsigned long end, unsigned long *userptr)
{
struct amdgpu_ttm_tt *gtt = (void *)ttm;
unsigned long size;
@@ -1250,6 +1250,8 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
if (gtt->userptr > end || gtt->userptr + size <= start)
return false;
if (userptr)
*userptr = gtt->userptr;
return true;
}

View File

@@ -182,7 +182,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm);
bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
unsigned long end);
unsigned long end, unsigned long *userptr);
bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm,
int *last_invalidated);
bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm);

View File

@@ -509,7 +509,7 @@ static ssize_t show_##name(struct device *dev, \
struct drm_device *ddev = dev_get_drvdata(dev); \
struct amdgpu_device *adev = drm_to_adev(ddev); \
\
return snprintf(buf, PAGE_SIZE, "0x%08x\n", adev->field); \
return sysfs_emit(buf, "0x%08x\n", adev->field); \
} \
static DEVICE_ATTR(name, mode, show_##name, NULL)

View File

@@ -949,3 +949,30 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)
return AMDGPU_RING_PRIO_0;
}
}
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
{
int i;
unsigned int idx;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
/* currently only support 2 FW instances */
if (i >= 2) {
dev_info(adev->dev, "More then 2 VCN FW instances!\n");
break;
}
idx = AMDGPU_UCODE_ID_VCN + i;
adev->firmware.ucode[idx].ucode_id = idx;
adev->firmware.ucode[idx].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
}

View File

@@ -310,4 +310,6 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);
void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);
#endif

View File

@@ -584,6 +584,7 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
vf2pf_info->encode_usage = 0;
vf2pf_info->decode_usage = 0;
vf2pf_info->dummy_page_addr = (uint64_t)adev->dummy_page_addr;
vf2pf_info->checksum =
amd_sriov_msg_checksum(
vf2pf_info, vf2pf_info->header.size, 0, 0);

View File

@@ -261,9 +261,10 @@ struct amd_sriov_msg_vf2pf_info {
uint8_t id;
uint32_t version;
} ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE];
uint64_t dummy_page_addr;
/* reserved */
uint32_t reserved[256-68];
uint32_t reserved[256-70];
};
/* mailbox message send from guest to host */

View File

@@ -1,54 +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.
*
*/
#include "amdgpu.h"
#include "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "beige_goby_ip_offset.h"
int beige_goby_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialize the block needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA2_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA3_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
}
return 0;
}

View File

@@ -1,51 +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 "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "cyan_skillfish_ip_offset.h"
int cyan_skillfish_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the blocke needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
}
return 0;
}

View File

@@ -270,25 +270,6 @@ MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin");
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin");
MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin");
static const struct soc15_reg_golden golden_settings_gc_10_0[] =
{
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_INDEX, 0xffffffff, 0x00000000),
/* TA_GRAD_ADJ_UCONFIG -> TA_GRAD_ADJ */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2544c382),
/* VGT_TF_RING_SIZE_UMD -> VGT_TF_RING_SIZE */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2262c24e),
/* VGT_HS_OFFCHIP_PARAM_UMD -> VGT_HS_OFFCHIP_PARAM */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226cc24f),
/* VGT_TF_MEMORY_BASE_UMD -> VGT_TF_MEMORY_BASE */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226ec250),
/* VGT_TF_MEMORY_BASE_HI_UMD -> VGT_TF_MEMORY_BASE_HI */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2278c261),
/* VGT_ESGS_RING_SIZE_UMD -> VGT_ESGS_RING_SIZE */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2232c240),
/* VGT_GSVS_RING_SIZE_UMD -> VGT_GSVS_RING_SIZE */
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2233c241),
};
static const struct soc15_reg_golden golden_settings_gc_10_1[] =
{
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
@@ -3809,9 +3790,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
(const u32)ARRAY_SIZE(golden_settings_gc_10_3_5));
break;
case IP_VERSION(10, 1, 3):
soc15_program_register_sequence(adev,
golden_settings_gc_10_0,
(const u32)ARRAY_SIZE(golden_settings_gc_10_0));
soc15_program_register_sequence(adev,
golden_settings_gc_10_0_cyan_skillfish,
(const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish));
@@ -8238,8 +8216,9 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
/* === CGCG + CGLS === */
gfx_v10_0_update_coarse_grain_clock_gating(adev, enable);
if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 1, 10)) &&
(adev->ip_versions[GC_HWIP][0] <= IP_VERSION(10, 1, 2)))
if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 10)) ||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1)) ||
(adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 2)))
gfx_v10_0_apply_medium_grain_clock_gating_workaround(adev);
} else {
/* CGCG/CGLS should be disabled before MGCG/MGLS

View File

@@ -1,55 +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 "nv.h"
#include "soc15_common.h"
#include "navi10_ip_offset.h"
int navi10_reg_base_init(struct amdgpu_device *adev)
{
int i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
}
return 0;
}

View File

@@ -1,52 +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 "nv.h"
#include "soc15_common.h"
#include "navi12_ip_offset.h"
int navi12_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the blocks needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIF0_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
}
return 0;
}

View File

@@ -1,53 +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 "nv.h"
#include "soc15_common.h"
#include "navi14_ip_offset.h"
int navi14_reg_base_init(struct amdgpu_device *adev)
{
int i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIF0_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));
}
return 0;
}

View File

@@ -53,6 +53,16 @@
#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L /* Don't use. Firmware uses this bit internally */
#define GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK 0x00002000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK 0x00004000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK 0x00008000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK 0x00010000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK 0x00020000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK 0x00040000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK 0x00080000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK 0x00100000L
static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev)
{
WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
@@ -318,6 +328,27 @@ const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg = {
.ref_and_mask_sdma1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__SDMA1_MASK,
};
const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg_sc = {
.ref_and_mask_cp0 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP0_MASK,
.ref_and_mask_cp1 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP1_MASK,
.ref_and_mask_cp2 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP2_MASK,
.ref_and_mask_cp3 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP3_MASK,
.ref_and_mask_cp4 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP4_MASK,
.ref_and_mask_cp5 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP5_MASK,
.ref_and_mask_cp6 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP6_MASK,
.ref_and_mask_cp7 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP7_MASK,
.ref_and_mask_cp8 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP8_MASK,
.ref_and_mask_cp9 = BIF_BX_PF_GPU_HDP_FLUSH_DONE__CP9_MASK,
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK,
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK,
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK,
};
static void nbio_v2_3_init_registers(struct amdgpu_device *adev)
{
uint32_t def, data;

View File

@@ -27,6 +27,7 @@
#include "soc15_common.h"
extern const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg;
extern const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg_sc;
extern const struct amdgpu_nbio_funcs nbio_v2_3_funcs;
#endif

View File

@@ -56,12 +56,15 @@
* These are nbio v7_4_1 registers mask. Temporarily define these here since
* nbio v7_4_1 header is incomplete.
*/
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK 0x00001000L /* Don't use. Firmware uses this bit internally */
#define GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK 0x00002000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK 0x00004000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK 0x00008000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK 0x00010000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK 0x00020000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK 0x00040000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK 0x00080000L
#define GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK 0x00100000L
#define mmBIF_MMSCH1_DOORBELL_RANGE 0x01dc
#define mmBIF_MMSCH1_DOORBELL_RANGE_BASE_IDX 2
@@ -334,12 +337,27 @@ const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg = {
.ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK,
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__SDMA0_MASK,
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK,
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG0_MASK,
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
};
const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald = {
.ref_and_mask_cp0 = GPU_HDP_FLUSH_DONE__CP0_MASK,
.ref_and_mask_cp1 = GPU_HDP_FLUSH_DONE__CP1_MASK,
.ref_and_mask_cp2 = GPU_HDP_FLUSH_DONE__CP2_MASK,
.ref_and_mask_cp3 = GPU_HDP_FLUSH_DONE__CP3_MASK,
.ref_and_mask_cp4 = GPU_HDP_FLUSH_DONE__CP4_MASK,
.ref_and_mask_cp5 = GPU_HDP_FLUSH_DONE__CP5_MASK,
.ref_and_mask_cp6 = GPU_HDP_FLUSH_DONE__CP6_MASK,
.ref_and_mask_cp7 = GPU_HDP_FLUSH_DONE__CP7_MASK,
.ref_and_mask_cp8 = GPU_HDP_FLUSH_DONE__CP8_MASK,
.ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK,
.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__RSVD_ENG1_MASK,
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__RSVD_ENG2_MASK,
.ref_and_mask_sdma2 = GPU_HDP_FLUSH_DONE__RSVD_ENG3_MASK,
.ref_and_mask_sdma3 = GPU_HDP_FLUSH_DONE__RSVD_ENG4_MASK,
.ref_and_mask_sdma4 = GPU_HDP_FLUSH_DONE__RSVD_ENG5_MASK,
.ref_and_mask_sdma5 = GPU_HDP_FLUSH_DONE__RSVD_ENG6_MASK,
.ref_and_mask_sdma6 = GPU_HDP_FLUSH_DONE__RSVD_ENG7_MASK,
.ref_and_mask_sdma7 = GPU_HDP_FLUSH_DONE__RSVD_ENG8_MASK,
};
static void nbio_v7_4_init_registers(struct amdgpu_device *adev)

View File

@@ -27,6 +27,7 @@
#include "soc15_common.h"
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg;
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald;
extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs;
extern const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs;

View File

@@ -607,304 +607,11 @@ const struct amdgpu_ip_block_version nv_common_ip_block =
.funcs = &nv_common_ip_funcs,
};
static int nv_reg_base_init(struct amdgpu_device *adev)
{
int r;
if (amdgpu_discovery) {
r = amdgpu_discovery_reg_base_init(adev);
if (r) {
DRM_WARN("failed to init reg base from ip discovery table, "
"fallback to legacy init method\n");
goto legacy_init;
}
amdgpu_discovery_harvest_ip(adev);
return 0;
}
legacy_init:
switch (adev->asic_type) {
case CHIP_NAVI10:
navi10_reg_base_init(adev);
break;
case CHIP_NAVI14:
navi14_reg_base_init(adev);
break;
case CHIP_NAVI12:
navi12_reg_base_init(adev);
break;
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
sienna_cichlid_reg_base_init(adev);
break;
case CHIP_VANGOGH:
vangogh_reg_base_init(adev);
break;
case CHIP_DIMGREY_CAVEFISH:
dimgrey_cavefish_reg_base_init(adev);
break;
case CHIP_BEIGE_GOBY:
beige_goby_reg_base_init(adev);
break;
case CHIP_YELLOW_CARP:
yellow_carp_reg_base_init(adev);
break;
case CHIP_CYAN_SKILLFISH:
cyan_skillfish_reg_base_init(adev);
break;
default:
return -EINVAL;
}
return 0;
}
void nv_set_virt_ops(struct amdgpu_device *adev)
{
adev->virt.ops = &xgpu_nv_virt_ops;
}
int nv_set_ip_blocks(struct amdgpu_device *adev)
{
int r;
if (adev->asic_type == CHIP_CYAN_SKILLFISH) {
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
} else if (adev->flags & AMD_IS_APU) {
adev->nbio.funcs = &nbio_v7_2_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg;
} else {
adev->nbio.funcs = &nbio_v2_3_funcs;
adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
}
adev->hdp.funcs = &hdp_v5_0_funcs;
if (adev->asic_type >= CHIP_SIENNA_CICHLID)
adev->smuio.funcs = &smuio_v11_0_6_funcs;
else
adev->smuio.funcs = &smuio_v11_0_funcs;
if (adev->asic_type == CHIP_SIENNA_CICHLID)
adev->gmc.xgmi.supported = true;
/* Set IP register base before any HW register access */
r = nv_reg_base_init(adev);
if (r)
return r;
switch (adev->asic_type) {
case CHIP_NAVI10:
case CHIP_NAVI14:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
if (adev->enable_mes)
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
break;
case CHIP_NAVI12:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
if (!amdgpu_sriov_vf(adev)) {
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
} else {
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
break;
case CHIP_SIENNA_CICHLID:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
if (!amdgpu_sriov_vf(adev)) {
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
} else {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
if (adev->enable_mes)
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
break;
case CHIP_NAVY_FLOUNDER:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
break;
case CHIP_VANGOGH:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
break;
case CHIP_DIMGREY_CAVEFISH:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
break;
case CHIP_BEIGE_GOBY:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
break;
case CHIP_YELLOW_CARP:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block);
break;
case CHIP_CYAN_SKILLFISH:
amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
{
return adev->nbio.funcs->get_rev_id(adev);
@@ -1248,7 +955,7 @@ static int nv_common_early_init(void *handle)
AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG;
if (adev->pdev->device == 0x1681)
adev->external_rev_id = adev->rev_id + 0x19;
adev->external_rev_id = 0x20;
else
adev->external_rev_id = adev->rev_id + 0x01;
break;

View File

@@ -31,15 +31,5 @@ extern const struct amdgpu_ip_block_version nv_common_ip_block;
void nv_grbm_select(struct amdgpu_device *adev,
u32 me, u32 pipe, u32 queue, u32 vmid);
void nv_set_virt_ops(struct amdgpu_device *adev);
int nv_set_ip_blocks(struct amdgpu_device *adev);
int navi10_reg_base_init(struct amdgpu_device *adev);
int navi14_reg_base_init(struct amdgpu_device *adev);
int navi12_reg_base_init(struct amdgpu_device *adev);
int sienna_cichlid_reg_base_init(struct amdgpu_device *adev);
void vangogh_reg_base_init(struct amdgpu_device *adev);
int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev);
int beige_goby_reg_base_init(struct amdgpu_device *adev);
int yellow_carp_reg_base_init(struct amdgpu_device *adev);
int cyan_skillfish_reg_base_init(struct amdgpu_device *adev);
#endif

View File

@@ -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.
*
*/
#include "amdgpu.h"
#include "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "sienna_cichlid_ip_offset.h"
int sienna_cichlid_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the blocke needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA2_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SDMA3_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
}
return 0;
}

View File

@@ -780,185 +780,6 @@ void soc15_set_virt_ops(struct amdgpu_device *adev)
soc15_reg_base_init(adev);
}
int soc15_set_ip_blocks(struct amdgpu_device *adev)
{
/* for bare metal case */
if (!amdgpu_sriov_vf(adev))
soc15_reg_base_init(adev);
if (adev->flags & AMD_IS_APU) {
adev->nbio.funcs = &nbio_v7_0_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_0_hdp_flush_reg;
} else if (adev->asic_type == CHIP_VEGA20 ||
adev->asic_type == CHIP_ARCTURUS ||
adev->asic_type == CHIP_ALDEBARAN) {
adev->nbio.funcs = &nbio_v7_4_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;
} else {
adev->nbio.funcs = &nbio_v6_1_funcs;
adev->nbio.hdp_flush_reg = &nbio_v6_1_hdp_flush_reg;
}
adev->hdp.funcs = &hdp_v4_0_funcs;
if (adev->asic_type == CHIP_VEGA20 ||
adev->asic_type == CHIP_ARCTURUS ||
adev->asic_type == CHIP_ALDEBARAN)
adev->df.funcs = &df_v3_6_funcs;
else
adev->df.funcs = &df_v1_7_funcs;
if (adev->asic_type == CHIP_VEGA20 ||
adev->asic_type == CHIP_ARCTURUS)
adev->smuio.funcs = &smuio_v11_0_funcs;
else if (adev->asic_type == CHIP_ALDEBARAN)
adev->smuio.funcs = &smuio_v13_0_funcs;
else
adev->smuio.funcs = &smuio_v9_0_funcs;
adev->rev_id = soc15_get_rev_id(adev);
switch (adev->asic_type) {
case CHIP_VEGA10:
case CHIP_VEGA12:
case CHIP_VEGA20:
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
/* For Vega10 SR-IOV, PSP need to be initialized before IH */
if (amdgpu_sriov_vf(adev)) {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
if (adev->asic_type == CHIP_VEGA20)
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
else
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
}
if (adev->asic_type == CHIP_VEGA20)
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
else
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
} else {
if (adev->asic_type == CHIP_VEGA20)
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
else
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
if (adev->asic_type == CHIP_VEGA20)
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
else
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
}
}
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (is_support_sw_smu(adev)) {
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
} else {
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev))) {
amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block);
}
break;
case CHIP_RAVEN:
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
break;
case CHIP_ARCTURUS:
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
if (amdgpu_sriov_vf(adev)) {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
} else {
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (amdgpu_sriov_vf(adev)) {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
} else {
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
}
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &jpeg_v2_5_ip_block);
break;
case CHIP_RENOIR:
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v12_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v12_0_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
#endif
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
break;
case CHIP_ALDEBARAN:
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
if (amdgpu_sriov_vf(adev)) {
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
} else {
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
}
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v2_6_ip_block);
amdgpu_device_ip_block_add(adev, &jpeg_v2_6_ip_block);
break;
default:
return -EINVAL;
}
return 0;
}
static bool soc15_need_full_reset(struct amdgpu_device *adev)
{
/* change this when we implement soft reset */

View File

@@ -102,7 +102,6 @@ struct soc15_ras_field_entry {
void soc15_grbm_select(struct amdgpu_device *adev,
u32 me, u32 pipe, u32 queue, u32 vmid);
void soc15_set_virt_ops(struct amdgpu_device *adev);
int soc15_set_ip_blocks(struct amdgpu_device *adev);
void soc15_program_register_sequence(struct amdgpu_device *adev,
const struct soc15_reg_golden *registers,

View File

@@ -59,7 +59,12 @@ enum ta_ras_status {
TA_RAS_STATUS__ERROR_SYS_DRV_REG_ACCESS = 0xA011,
TA_RAS_STATUS__ERROR_RAS_READ_WRITE = 0xA012,
TA_RAS_STATUS__ERROR_NULL_PTR = 0xA013,
TA_RAS_STATUS__ERROR_UNSUPPORTED_IP = 0xA014
TA_RAS_STATUS__ERROR_UNSUPPORTED_IP = 0xA014,
TA_RAS_STATUS__ERROR_PCS_STATE_QUIET = 0xA015,
TA_RAS_STATUS__ERROR_PCS_STATE_ERROR = 0xA016,
TA_RAS_STATUS__ERROR_PCS_STATE_HANG = 0xA017,
TA_RAS_STATUS__ERROR_PCS_STATE_UNKNOWN = 0xA018,
TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ = 0xA019
};
enum ta_ras_block {

View File

@@ -1,50 +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 "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "vangogh_ip_offset.h"
void vangogh_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the blocke needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
}
}

View File

@@ -111,15 +111,7 @@ static int vcn_v1_0_sw_init(void *handle)
/* Override the work func */
adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
amdgpu_vcn_setup_ucode(adev);
r = amdgpu_vcn_resume(adev);
if (r)

View File

@@ -115,15 +115,7 @@ static int vcn_v2_0_sw_init(void *handle)
if (r)
return r;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
amdgpu_vcn_setup_ucode(adev);
r = amdgpu_vcn_resume(adev);
if (r)
@@ -1884,15 +1876,14 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device *adev)
/* mc resume*/
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
tmp = AMDGPU_UCODE_ID_VCN;
MMSCH_V2_0_INSERT_DIRECT_WT(
SOC15_REG_OFFSET(UVD, i,
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
adev->firmware.ucode[tmp].tmr_mc_addr_lo);
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo);
MMSCH_V2_0_INSERT_DIRECT_WT(
SOC15_REG_OFFSET(UVD, i,
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
adev->firmware.ucode[tmp].tmr_mc_addr_hi);
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi);
offset = 0;
} else {
MMSCH_V2_0_INSERT_DIRECT_WT(

View File

@@ -139,22 +139,7 @@ static int vcn_v2_5_sw_init(void *handle)
if (r)
return r;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
if (adev->vcn.num_vcn_inst == VCN25_MAX_HW_INSTANCES_ARCTURUS) {
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
amdgpu_vcn_setup_ucode(adev);
r = amdgpu_vcn_resume(adev);
if (r)

View File

@@ -60,11 +60,6 @@ static int amdgpu_ih_clientid_vcns[] = {
SOC15_IH_CLIENTID_VCN1
};
static int amdgpu_ucode_id_vcns[] = {
AMDGPU_UCODE_ID_VCN,
AMDGPU_UCODE_ID_VCN1
};
static int vcn_v3_0_start_sriov(struct amdgpu_device *adev);
static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev);
@@ -130,22 +125,7 @@ static int vcn_v3_0_sw_init(void *handle)
if (r)
return r;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
const struct common_firmware_header *hdr;
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].ucode_id = AMDGPU_UCODE_ID_VCN;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) {
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
}
dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
}
amdgpu_vcn_setup_ucode(adev);
r = amdgpu_vcn_resume(adev);
if (r)
@@ -1293,7 +1273,6 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
uint32_t param, resp, expected;
uint32_t offset, cache_size;
uint32_t tmp, timeout;
uint32_t id;
struct amdgpu_mm_table *table = &adev->virt.mm_table;
uint32_t *table_loc;
@@ -1337,13 +1316,12 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
cache_size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
id = amdgpu_ucode_id_vcns[i];
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
adev->firmware.ucode[id].tmr_mc_addr_lo);
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_lo);
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
adev->firmware.ucode[id].tmr_mc_addr_hi);
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + i].tmr_mc_addr_hi);
offset = 0;
MMSCH_V3_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCN, i,
mmUVD_VCPU_CACHE_OFFSET0),

View File

@@ -1,51 +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 "nv.h"
#include "soc15_common.h"
#include "soc15_hw_ip.h"
#include "yellow_carp_offset.h"
int yellow_carp_reg_base_init(struct amdgpu_device *adev)
{
/* HW has more IP blocks, only initialized the block needed by driver */
uint32_t i;
for (i = 0 ; i < MAX_INSTANCE ; ++i) {
adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i]));
adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i]));
adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i]));
adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i]));
adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DCN_BASE.instance[i]));
adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i]));
adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(SDMA0_BASE.instance[i]));
adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
}
return 0;
}

View File

@@ -1259,6 +1259,23 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
if (args->size == 0)
return -EINVAL;
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
/* Flush pending deferred work to avoid racing with deferred actions
* from previous memory map changes (e.g. munmap).
*/
svm_range_list_lock_and_flush_work(&p->svms, current->mm);
mutex_lock(&p->svms.lock);
mmap_write_unlock(current->mm);
if (interval_tree_iter_first(&p->svms.objects,
args->va_addr >> PAGE_SHIFT,
(args->va_addr + args->size - 1) >> PAGE_SHIFT)) {
pr_err("Address: 0x%llx already allocated by SVM\n",
args->va_addr);
mutex_unlock(&p->svms.lock);
return -EADDRINUSE;
}
mutex_unlock(&p->svms.lock);
#endif
dev = kfd_device_by_id(args->gpu_id);
if (!dev)
return -EINVAL;

View File

@@ -93,7 +93,6 @@ 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,
@@ -113,7 +112,9 @@ static const struct kfd_device_info raven_device_info = {
.num_xgmi_sdma_engines = 0,
.num_sdma_queues_per_engine = 2,
};
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
static const struct kfd_device_info hawaii_device_info = {
.asic_family = CHIP_HAWAII,
.asic_name = "hawaii",
@@ -133,6 +134,7 @@ static const struct kfd_device_info hawaii_device_info = {
.num_xgmi_sdma_engines = 0,
.num_sdma_queues_per_engine = 2,
};
#endif
static const struct kfd_device_info tonga_device_info = {
.asic_family = CHIP_TONGA,
@@ -1021,6 +1023,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd_double_confirm_iommu_support(kfd);
if (kfd_iommu_device_init(kfd)) {
kfd->use_iommu_v2 = false;
dev_err(kfd_device, "Error initializing iommuv2\n");
goto device_iommu_error;
}
@@ -1029,6 +1032,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
svm_migrate_init((struct amdgpu_device *)kfd->kgd);
if(kgd2kfd_resume_iommu(kfd))
goto device_iommu_error;
if (kfd_resume(kfd))
goto kfd_resume_error;

View File

@@ -20,7 +20,6 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <linux/types.h>
#include <linux/hmm.h>
#include <linux/dma-direction.h>
@@ -34,6 +33,11 @@
#include "kfd_svm.h"
#include "kfd_migrate.h"
#ifdef dev_fmt
#undef dev_fmt
#endif
#define dev_fmt(fmt) "kfd_migrate: %s: " fmt, __func__
static uint64_t
svm_migrate_direct_mapping_addr(struct amdgpu_device *adev, uint64_t addr)
{
@@ -151,14 +155,14 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys,
gart_d = svm_migrate_direct_mapping_addr(adev, *vram);
}
if (r) {
pr_debug("failed %d to create gart mapping\n", r);
dev_err(adev->dev, "fail %d create gart mapping\n", r);
goto out_unlock;
}
r = amdgpu_copy_buffer(ring, gart_s, gart_d, size * PAGE_SIZE,
NULL, &next, false, true, false);
if (r) {
pr_debug("failed %d to copy memory\n", r);
dev_err(adev->dev, "fail %d to copy memory\n", r);
goto out_unlock;
}
@@ -264,6 +268,19 @@ static void svm_migrate_put_sys_page(unsigned long addr)
put_page(page);
}
static unsigned long svm_migrate_successful_pages(struct migrate_vma *migrate)
{
unsigned long cpages = 0;
unsigned long i;
for (i = 0; i < migrate->npages; i++) {
if (migrate->src[i] & MIGRATE_PFN_VALID &&
migrate->src[i] & MIGRATE_PFN_MIGRATE)
cpages++;
}
return cpages;
}
static int
svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct migrate_vma *migrate, struct dma_fence **mfence,
@@ -285,7 +302,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
r = svm_range_vram_node_new(adev, prange, true);
if (r) {
pr_debug("failed %d get 0x%llx pages from vram\n", r, npages);
dev_err(adev->dev, "fail %d to alloc vram\n", r);
goto out;
}
@@ -305,7 +322,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
DMA_TO_DEVICE);
r = dma_mapping_error(dev, src[i]);
if (r) {
pr_debug("failed %d dma_map_page\n", r);
dev_err(adev->dev, "fail %d dma_map_page\n", r);
goto out_free_vram_pages;
}
} else {
@@ -325,8 +342,8 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
continue;
}
pr_debug("dma mapping src to 0x%llx, page_to_pfn 0x%lx\n",
src[i] >> PAGE_SHIFT, page_to_pfn(spage));
pr_debug_ratelimited("dma mapping src to 0x%llx, pfn 0x%lx\n",
src[i] >> PAGE_SHIFT, page_to_pfn(spage));
if (j >= (cursor.size >> PAGE_SHIFT) - 1 && i < npages - 1) {
r = svm_migrate_copy_memory_gart(adev, src + i - j,
@@ -372,7 +389,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
return r;
}
static int
static long
svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start,
uint64_t end)
@@ -381,6 +398,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct kfd_process_device *pdd;
struct dma_fence *mfence = NULL;
struct migrate_vma migrate;
unsigned long cpages = 0;
dma_addr_t *scratch;
size_t size;
void *buf;
@@ -405,23 +423,31 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
r = migrate_vma_setup(&migrate);
if (r) {
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
r, prange->svms, prange->start, prange->last);
dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r,
prange->start, prange->last);
goto out_free;
}
if (migrate.cpages != npages) {
pr_debug("Partial migration. 0x%lx/0x%llx pages can be migrated\n",
migrate.cpages,
npages);
}
if (migrate.cpages) {
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence,
scratch);
migrate_vma_pages(&migrate);
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
cpages = migrate.cpages;
if (!cpages) {
pr_debug("failed collect migrate sys pages [0x%lx 0x%lx]\n",
prange->start, prange->last);
goto out_free;
}
if (cpages != npages)
pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n",
cpages, npages);
else
pr_debug("0x%lx pages migrated\n", cpages);
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch);
migrate_vma_pages(&migrate);
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
svm_migrate_successful_pages(&migrate), cpages, migrate.npages);
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
svm_range_free_dma_mappings(prange);
@@ -429,12 +455,13 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
out_free:
kvfree(buf);
out:
if (!r) {
if (!r && cpages) {
pdd = svm_range_get_pdd_by_adev(prange, adev);
if (pdd)
WRITE_ONCE(pdd->page_in, pdd->page_in + migrate.cpages);
}
WRITE_ONCE(pdd->page_in, pdd->page_in + cpages);
return cpages;
}
return r;
}
@@ -456,7 +483,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
unsigned long addr, start, end;
struct vm_area_struct *vma;
struct amdgpu_device *adev;
int r = 0;
unsigned long cpages = 0;
long r = 0;
if (prange->actual_loc == best_loc) {
pr_debug("svms 0x%p [0x%lx 0x%lx] already on best_loc 0x%x\n",
@@ -488,17 +516,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
next = min(vma->vm_end, end);
r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next);
if (r) {
pr_debug("failed to migrate\n");
if (r < 0) {
pr_debug("failed %ld to migrate\n", r);
break;
} else {
cpages += r;
}
addr = next;
}
if (!r)
if (cpages)
prange->actual_loc = best_loc;
return r;
return r < 0 ? r : 0;
}
static void svm_migrate_page_free(struct page *page)
@@ -506,7 +536,7 @@ static void svm_migrate_page_free(struct page *page)
struct svm_range_bo *svm_bo = page->zone_device_data;
if (svm_bo) {
pr_debug("svm_bo ref left: %d\n", kref_read(&svm_bo->kref));
pr_debug_ratelimited("ref: %d\n", kref_read(&svm_bo->kref));
svm_range_bo_unref(svm_bo);
}
}
@@ -572,12 +602,12 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE);
r = dma_mapping_error(dev, dst[i]);
if (r) {
pr_debug("failed %d dma_map_page\n", r);
dev_err(adev->dev, "fail %d dma_map_page\n", r);
goto out_oom;
}
pr_debug("dma mapping dst to 0x%llx, page_to_pfn 0x%lx\n",
dst[i] >> PAGE_SHIFT, page_to_pfn(dpage));
pr_debug_ratelimited("dma mapping dst to 0x%llx, pfn 0x%lx\n",
dst[i] >> PAGE_SHIFT, page_to_pfn(dpage));
migrate->dst[i] = migrate_pfn(page_to_pfn(dpage));
migrate->dst[i] |= MIGRATE_PFN_LOCKED;
@@ -599,7 +629,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
return r;
}
static int
static long
svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start, uint64_t end)
{
@@ -607,6 +637,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
struct kfd_process_device *pdd;
struct dma_fence *mfence = NULL;
struct migrate_vma migrate;
unsigned long cpages = 0;
dma_addr_t *scratch;
size_t size;
void *buf;
@@ -631,34 +662,43 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
r = migrate_vma_setup(&migrate);
if (r) {
pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n",
r, prange->svms, prange->start, prange->last);
dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r,
prange->start, prange->last);
goto out_free;
}
pr_debug("cpages %ld\n", migrate.cpages);
if (migrate.cpages) {
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
scratch, npages);
migrate_vma_pages(&migrate);
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
} else {
cpages = migrate.cpages;
if (!cpages) {
pr_debug("failed collect migrate device pages [0x%lx 0x%lx]\n",
prange->start, prange->last);
goto out_free;
}
if (cpages != npages)
pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n",
cpages, npages);
else
pr_debug("0x%lx pages migrated\n", cpages);
r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence,
scratch, npages);
migrate_vma_pages(&migrate);
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
svm_migrate_successful_pages(&migrate), cpages, migrate.npages);
svm_migrate_copy_done(adev, mfence);
migrate_vma_finalize(&migrate);
svm_range_dma_unmap(adev->dev, scratch, 0, npages);
out_free:
kvfree(buf);
out:
if (!r) {
if (!r && cpages) {
pdd = svm_range_get_pdd_by_adev(prange, adev);
if (pdd)
WRITE_ONCE(pdd->page_out,
pdd->page_out + migrate.cpages);
WRITE_ONCE(pdd->page_out, pdd->page_out + cpages);
return cpages;
}
return r;
}
@@ -680,7 +720,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm)
unsigned long addr;
unsigned long start;
unsigned long end;
int r = 0;
unsigned long cpages = 0;
long r = 0;
if (!prange->actual_loc) {
pr_debug("[0x%lx 0x%lx] already migrated to ram\n",
@@ -711,18 +752,21 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm)
next = min(vma->vm_end, end);
r = svm_migrate_vma_to_ram(adev, prange, vma, addr, next);
if (r) {
pr_debug("failed %d to migrate\n", r);
if (r < 0) {
pr_debug("failed %ld to migrate\n", r);
break;
} else {
cpages += r;
}
addr = next;
}
if (!r) {
if (cpages) {
svm_range_vram_node_free(prange);
prange->actual_loc = 0;
}
return r;
return r < 0 ? r : 0;
}
/**

View File

@@ -33,6 +33,11 @@
#include "kfd_svm.h"
#include "kfd_migrate.h"
#ifdef dev_fmt
#undef dev_fmt
#endif
#define dev_fmt(fmt) "kfd_svm: %s: " fmt, __func__
#define AMDGPU_SVM_RANGE_RESTORE_DELAY_MS 1
/* Long enough to ensure no retry fault comes after svm range is restored and
@@ -45,7 +50,9 @@ static bool
svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
unsigned long cur_seq);
static int
svm_range_check_vm(struct kfd_process *p, uint64_t start, uint64_t last,
uint64_t *bo_s, uint64_t *bo_l);
static const struct mmu_interval_notifier_ops svm_range_mn_ops = {
.invalidate = svm_range_cpu_invalidate_pagetables,
};
@@ -158,17 +165,17 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
bo_adev->vm_manager.vram_base_offset -
bo_adev->kfd.dev->pgmap.range.start;
addr[i] |= SVM_RANGE_VRAM_DOMAIN;
pr_debug("vram address detected: 0x%llx\n", addr[i]);
pr_debug_ratelimited("vram address: 0x%llx\n", addr[i]);
continue;
}
addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
r = dma_mapping_error(dev, addr[i]);
if (r) {
pr_debug("failed %d dma_map_page\n", r);
dev_err(dev, "failed %d dma_map_page\n", r);
return r;
}
pr_debug("dma mapping 0x%llx for page addr 0x%lx\n",
addr[i] >> PAGE_SHIFT, page_to_pfn(page));
pr_debug_ratelimited("dma mapping 0x%llx for page addr 0x%lx\n",
addr[i] >> PAGE_SHIFT, page_to_pfn(page));
}
return 0;
}
@@ -217,7 +224,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
for (i = offset; i < offset + npages; i++) {
if (!svm_is_valid_dma_mapping_addr(dev, dma_addr[i]))
continue;
pr_debug("dma unmapping 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);
pr_debug_ratelimited("unmap 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);
dma_unmap_page(dev, dma_addr[i], PAGE_SIZE, dir);
dma_addr[i] = 0;
}
@@ -1454,7 +1461,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
/* This should never happen. actual_loc gets set by
* svm_migrate_ram_to_vram after allocating a BO.
*/
WARN(1, "VRAM BO missing during validation\n");
WARN_ONCE(1, "VRAM BO missing during validation\n");
return -EINVAL;
}
@@ -1547,7 +1554,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
* Context: Returns with mmap write lock held, pending deferred work flushed
*
*/
static void
void
svm_range_list_lock_and_flush_work(struct svm_range_list *svms,
struct mm_struct *mm)
{
@@ -2303,6 +2310,7 @@ svm_range_best_restore_location(struct svm_range *prange,
return -1;
}
static int
svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
unsigned long *start, unsigned long *last)
@@ -2350,8 +2358,59 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
vma->vm_end >> PAGE_SHIFT, *last);
return 0;
}
static int
svm_range_check_vm_userptr(struct kfd_process *p, uint64_t start, uint64_t last,
uint64_t *bo_s, uint64_t *bo_l)
{
struct amdgpu_bo_va_mapping *mapping;
struct interval_tree_node *node;
struct amdgpu_bo *bo = NULL;
unsigned long userptr;
uint32_t i;
int r;
for (i = 0; i < p->n_pdds; i++) {
struct amdgpu_vm *vm;
if (!p->pdds[i]->drm_priv)
continue;
vm = drm_priv_to_vm(p->pdds[i]->drm_priv);
r = amdgpu_bo_reserve(vm->root.bo, false);
if (r)
return r;
/* Check userptr by searching entire vm->va interval tree */
node = interval_tree_iter_first(&vm->va, 0, ~0ULL);
while (node) {
mapping = container_of((struct rb_node *)node,
struct amdgpu_bo_va_mapping, rb);
bo = mapping->bo_va->base.bo;
if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
start << PAGE_SHIFT,
last << PAGE_SHIFT,
&userptr)) {
node = interval_tree_iter_next(node, 0, ~0ULL);
continue;
}
pr_debug("[0x%llx 0x%llx] already userptr mapped\n",
start, last);
if (bo_s && bo_l) {
*bo_s = userptr >> PAGE_SHIFT;
*bo_l = *bo_s + bo->tbo.ttm->num_pages - 1;
}
amdgpu_bo_unreserve(vm->root.bo);
return -EADDRINUSE;
}
amdgpu_bo_unreserve(vm->root.bo);
}
return 0;
}
static struct
svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
struct kfd_process *p,
@@ -2361,10 +2420,26 @@ svm_range *svm_range_create_unregistered_range(struct amdgpu_device *adev,
struct svm_range *prange = NULL;
unsigned long start, last;
uint32_t gpuid, gpuidx;
uint64_t bo_s = 0;
uint64_t bo_l = 0;
int r;
if (svm_range_get_range_boundaries(p, addr, &start, &last))
return NULL;
r = svm_range_check_vm(p, start, last, &bo_s, &bo_l);
if (r != -EADDRINUSE)
r = svm_range_check_vm_userptr(p, start, last, &bo_s, &bo_l);
if (r == -EADDRINUSE) {
if (addr >= bo_s && addr <= bo_l)
return NULL;
/* Create one page svm range if 2MB range overlapping */
start = addr;
last = addr;
}
prange = svm_range_new(&p->svms, start, last);
if (!prange) {
pr_debug("Failed to create prange in address [0x%llx]\n", addr);
@@ -2662,9 +2737,68 @@ int svm_range_list_init(struct kfd_process *p)
return 0;
}
/**
* svm_range_check_vm - check if virtual address range mapped already
* @p: current kfd_process
* @start: range start address, in pages
* @last: range last address, in pages
* @bo_s: mapping start address in pages if address range already mapped
* @bo_l: mapping last address in pages if address range already mapped
*
* The purpose is to avoid virtual address ranges already allocated by
* kfd_ioctl_alloc_memory_of_gpu ioctl.
* It looks for each pdd in the kfd_process.
*
* Context: Process context
*
* Return 0 - OK, if the range is not mapped.
* Otherwise error code:
* -EADDRINUSE - if address is mapped already by kfd_ioctl_alloc_memory_of_gpu
* -ERESTARTSYS - A wait for the buffer to become unreserved was interrupted by
* a signal. Release all buffer reservations and return to user-space.
*/
static int
svm_range_check_vm(struct kfd_process *p, uint64_t start, uint64_t last,
uint64_t *bo_s, uint64_t *bo_l)
{
struct amdgpu_bo_va_mapping *mapping;
struct interval_tree_node *node;
uint32_t i;
int r;
for (i = 0; i < p->n_pdds; i++) {
struct amdgpu_vm *vm;
if (!p->pdds[i]->drm_priv)
continue;
vm = drm_priv_to_vm(p->pdds[i]->drm_priv);
r = amdgpu_bo_reserve(vm->root.bo, false);
if (r)
return r;
node = interval_tree_iter_first(&vm->va, start, last);
if (node) {
pr_debug("range [0x%llx 0x%llx] already TTM mapped\n",
start, last);
mapping = container_of((struct rb_node *)node,
struct amdgpu_bo_va_mapping, rb);
if (bo_s && bo_l) {
*bo_s = mapping->start;
*bo_l = mapping->last;
}
amdgpu_bo_unreserve(vm->root.bo);
return -EADDRINUSE;
}
amdgpu_bo_unreserve(vm->root.bo);
}
return 0;
}
/**
* svm_range_is_valid - check if virtual address range is valid
* @mm: current process mm_struct
* @p: current kfd_process
* @start: range start address, in pages
* @size: range size, in pages
*
@@ -2673,28 +2807,28 @@ int svm_range_list_init(struct kfd_process *p)
* Context: Process context
*
* Return:
* true - valid svm range
* false - invalid svm range
* 0 - OK, otherwise error code
*/
static bool
svm_range_is_valid(struct mm_struct *mm, uint64_t start, uint64_t size)
static int
svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size)
{
const unsigned long device_vma = VM_IO | VM_PFNMAP | VM_MIXEDMAP;
struct vm_area_struct *vma;
unsigned long end;
unsigned long start_unchg = start;
start <<= PAGE_SHIFT;
end = start + (size << PAGE_SHIFT);
do {
vma = find_vma(mm, start);
vma = find_vma(p->mm, start);
if (!vma || start < vma->vm_start ||
(vma->vm_flags & device_vma))
return false;
return -EFAULT;
start = min(end, vma->vm_end);
} while (start < end);
return true;
return svm_range_check_vm(p, start_unchg, (end - 1) >> PAGE_SHIFT, NULL,
NULL);
}
/**
@@ -2997,9 +3131,9 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size,
svm_range_list_lock_and_flush_work(svms, mm);
if (!svm_range_is_valid(mm, start, size)) {
pr_debug("invalid range\n");
r = -EFAULT;
r = svm_range_is_valid(p, start, size);
if (r) {
pr_debug("invalid range r=%d\n", r);
mmap_write_unlock(mm);
goto out;
}
@@ -3101,6 +3235,7 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
uint32_t flags_or = 0;
int gpuidx;
uint32_t i;
int r = 0;
pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
start + size - 1, nattr);
@@ -3114,12 +3249,12 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
flush_work(&p->svms.deferred_list_work);
mmap_read_lock(mm);
if (!svm_range_is_valid(mm, start, size)) {
pr_debug("invalid range\n");
mmap_read_unlock(mm);
return -EINVAL;
}
r = svm_range_is_valid(p, start, size);
mmap_read_unlock(mm);
if (r) {
pr_debug("invalid range r=%d\n", r);
return r;
}
for (i = 0; i < nattr; i++) {
switch (attrs[i].type) {

View File

@@ -188,6 +188,7 @@ void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm,
void *owner);
struct kfd_process_device *
svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev);
void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm);
/* SVM API and HMM page migration work together, device memory type
* is initialized to not 0 when page migration register device memory.

View File

@@ -1296,6 +1296,24 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
proximity_domain = atomic_inc_return(&topology_crat_proximity_domain);
adev = (struct amdgpu_device *)(gpu->kgd);
/* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */
if (gpu->hive_id && adev->gmc.xgmi.connected_to_cpu) {
struct kfd_topology_device *top_dev;
down_read(&topology_lock);
list_for_each_entry(top_dev, &topology_device_list, list) {
if (top_dev->gpu)
break;
top_dev->node_props.hive_id = gpu->hive_id;
}
up_read(&topology_lock);
}
/* Check to see if this gpu device exists in the topology_device_list.
* If so, assign the gpu to that device,
* else create a Virtual CRAT for this gpu device and then parse that
@@ -1457,7 +1475,6 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
dev->node_props.max_waves_per_simd = 10;
}
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_enabled & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0) ?

View File

@@ -1356,8 +1356,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(2, 1, 0):
init_data.flags.gpu_vm_support = true;
if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
init_data.flags.disable_dmcu = true;
init_data.flags.disable_dmcu = true;
break;
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
@@ -4031,6 +4030,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
int32_t primary_planes;
enum dc_connection_type new_connection_type = dc_connection_none;
const struct dc_plane_cap *plane;
bool psr_feature_enabled = false;
dm->display_indexes_num = dm->dc->caps.max_streams;
/* Update the actual used number of crtc */
@@ -4113,6 +4113,19 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n",
adev->ip_versions[DCE_HWIP][0]);
}
/* Determine whether to enable PSR support by default. */
if (!(amdgpu_dc_debug_mask & DC_DISABLE_PSR)) {
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
psr_feature_enabled = true;
break;
default:
psr_feature_enabled = amdgpu_dc_feature_mask & DC_PSR_MASK;
break;
}
}
#endif
/* loops over all connectors on the board */
@@ -4156,7 +4169,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link);
if (amdgpu_dc_feature_mask & DC_PSR_MASK)
if (psr_feature_enabled)
amdgpu_dm_set_psr_caps(link);
}
@@ -10535,18 +10549,18 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
struct drm_crtc *crtc,
struct drm_crtc_state *new_crtc_state)
{
struct drm_plane_state *new_cursor_state, *new_primary_state;
int cursor_scale_w, cursor_scale_h, primary_scale_w, primary_scale_h;
struct drm_plane *cursor = crtc->cursor, *underlying;
struct drm_plane_state *new_cursor_state, *new_underlying_state;
int i;
int cursor_scale_w, cursor_scale_h, underlying_scale_w, underlying_scale_h;
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
* cursor per pipe but it's going to inherit the scaling and
* positioning from the underlying pipe. Check the cursor plane's
* blending properties match the primary plane's. */
* blending properties match the underlying planes'. */
new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
new_primary_state = drm_atomic_get_new_plane_state(state, crtc->primary);
if (!new_cursor_state || !new_primary_state ||
!new_cursor_state->fb || !new_primary_state->fb) {
new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
if (!new_cursor_state || !new_cursor_state->fb) {
return 0;
}
@@ -10555,15 +10569,34 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
cursor_scale_h = new_cursor_state->crtc_h * 1000 /
(new_cursor_state->src_h >> 16);
primary_scale_w = new_primary_state->crtc_w * 1000 /
(new_primary_state->src_w >> 16);
primary_scale_h = new_primary_state->crtc_h * 1000 /
(new_primary_state->src_h >> 16);
for_each_new_plane_in_state_reverse(state, underlying, new_underlying_state, i) {
/* Narrow down to non-cursor planes on the same CRTC as the cursor */
if (new_underlying_state->crtc != crtc || underlying == crtc->cursor)
continue;
if (cursor_scale_w != primary_scale_w ||
cursor_scale_h != primary_scale_h) {
drm_dbg_atomic(crtc->dev, "Cursor plane scaling doesn't match primary plane\n");
return -EINVAL;
/* Ignore disabled planes */
if (!new_underlying_state->fb)
continue;
underlying_scale_w = new_underlying_state->crtc_w * 1000 /
(new_underlying_state->src_w >> 16);
underlying_scale_h = new_underlying_state->crtc_h * 1000 /
(new_underlying_state->src_h >> 16);
if (cursor_scale_w != underlying_scale_w ||
cursor_scale_h != underlying_scale_h) {
drm_dbg_atomic(crtc->dev,
"Cursor [PLANE:%d:%s] scaling doesn't match underlying [PLANE:%d:%s]\n",
cursor->base.id, cursor->name, underlying->base.id, underlying->name);
return -EINVAL;
}
/* If this plane covers the whole CRTC, no need to check planes underneath */
if (new_underlying_state->crtc_x <= 0 &&
new_underlying_state->crtc_y <= 0 &&
new_underlying_state->crtc_x + new_underlying_state->crtc_w >= new_crtc_state->mode.hdisplay &&
new_underlying_state->crtc_y + new_underlying_state->crtc_h >= new_crtc_state->mode.vdisplay)
break;
}
return 0;
@@ -10594,53 +10627,6 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
}
#endif
static int validate_overlay(struct drm_atomic_state *state)
{
int i;
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;
struct drm_plane_state *primary_state, *overlay_state = NULL;
/* Check if primary plane is contained inside overlay */
for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) {
if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
if (drm_atomic_plane_disabling(plane->state, new_plane_state))
return 0;
overlay_state = new_plane_state;
continue;
}
}
/* check if we're making changes to the overlay plane */
if (!overlay_state)
return 0;
/* check if overlay plane is enabled */
if (!overlay_state->crtc)
return 0;
/* find the primary plane for the CRTC that the overlay is enabled on */
primary_state = drm_atomic_get_plane_state(state, overlay_state->crtc->primary);
if (IS_ERR(primary_state))
return PTR_ERR(primary_state);
/* check if primary plane is enabled */
if (!primary_state->crtc)
return 0;
/* Perform the bounds check to ensure the overlay plane covers the primary */
if (primary_state->crtc_x < overlay_state->crtc_x ||
primary_state->crtc_y < overlay_state->crtc_y ||
primary_state->crtc_x + primary_state->crtc_w > overlay_state->crtc_x + overlay_state->crtc_w ||
primary_state->crtc_y + primary_state->crtc_h > overlay_state->crtc_y + overlay_state->crtc_h) {
DRM_DEBUG_ATOMIC("Overlay plane is enabled with hardware cursor but does not fully cover primary plane\n");
return -EINVAL;
}
return 0;
}
/**
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
* @dev: The DRM device
@@ -10822,10 +10808,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail;
}
ret = validate_overlay(state);
if (ret)
goto fail;
/* Add new/modified planes */
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
ret = dm_update_plane_state(dc, state, plane,

View File

@@ -264,7 +264,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
if (!wr_buf)
return -ENOSPC;
if (parse_write_buffer_into_params(wr_buf, size,
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
(long *)param, buf,
max_param_num,
&param_nums)) {

View File

@@ -99,6 +99,10 @@ static enum bp_result get_firmware_info_v3_2(
struct bios_parser *bp,
struct dc_firmware_info *info);
static enum bp_result get_firmware_info_v3_4(
struct bios_parser *bp,
struct dc_firmware_info *info);
static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
struct atom_display_object_path_v2 *object);
@@ -1426,8 +1430,10 @@ static enum bp_result bios_parser_get_firmware_info(
break;
case 2:
case 3:
case 4:
result = get_firmware_info_v3_2(bp, info);
break;
case 4:
result = get_firmware_info_v3_4(bp, info);
break;
default:
break;
@@ -1575,6 +1581,88 @@ static enum bp_result get_firmware_info_v3_2(
return BP_RESULT_OK;
}
static enum bp_result get_firmware_info_v3_4(
struct bios_parser *bp,
struct dc_firmware_info *info)
{
struct atom_firmware_info_v3_4 *firmware_info;
struct atom_common_table_header *header;
struct atom_data_revision revision;
struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
if (!info)
return BP_RESULT_BADINPUT;
firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
DATA_TABLES(firmwareinfo));
if (!firmware_info)
return BP_RESULT_BADBIOSTABLE;
memset(info, 0, sizeof(*info));
header = GET_IMAGE(struct atom_common_table_header,
DATA_TABLES(dce_info));
get_atom_data_table_revision(header, &revision);
switch (revision.major) {
case 4:
switch (revision.minor) {
case 4:
dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
DATA_TABLES(dce_info));
if (!dce_info_v4_4)
return BP_RESULT_BADBIOSTABLE;
/* 100MHz expected */
info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;
/* 50MHz expected */
info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
/* Get SMU Display PLL VCO Frequency in KHz*/
info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;
break;
default:
/* should not come here, keep as backup, as was before */
dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
DATA_TABLES(dce_info));
if (!dce_info_v4_1)
return BP_RESULT_BADBIOSTABLE;
info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;
info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
break;
}
break;
default:
ASSERT(0);
break;
}
header = GET_IMAGE(struct atom_common_table_header,
DATA_TABLES(smu_info));
get_atom_data_table_revision(header, &revision);
// We need to convert from 10KHz units into KHz units.
info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
if (firmware_info->board_i2c_feature_id == 0x2) {
info->oem_i2c_present = true;
info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
} else {
info->oem_i2c_present = false;
}
return BP_RESULT_OK;
}
static enum bp_result bios_parser_get_encoder_cap_info(
struct dc_bios *dcb,
struct graphics_object_id object_id,

View File

@@ -219,14 +219,17 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
update_dispclk = true;
}
/* TODO: add back DTO programming when DPPCLK restore is fixed in FSDL*/
if (dpp_clock_lowered) {
// increase per DPP DTO before lowering global dppclk
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
dcn31_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
} else {
// increase global DPPCLK before lowering per DPP DTO
if (update_dppclk || update_dispclk)
dcn31_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
// 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);
}
// notify DMCUB of latest clocks
@@ -368,32 +371,32 @@ static struct wm_table lpddr5_wm_table = {
.wm_inst = WM_A,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
.sr_exit_time_us = 5.32,
.sr_enter_plus_exit_time_us = 6.38,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
},
{
.wm_inst = WM_B,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
.sr_exit_time_us = 9.82,
.sr_enter_plus_exit_time_us = 11.196,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
},
{
.wm_inst = WM_C,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
.sr_exit_time_us = 9.89,
.sr_enter_plus_exit_time_us = 11.24,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
},
{
.wm_inst = WM_D,
.wm_type = WM_TYPE_PSTATE_CHG,
.pstate_latency_us = 11.65333,
.sr_exit_time_us = 9.748,
.sr_enter_plus_exit_time_us = 11.102,
.sr_exit_time_us = 11.5,
.sr_enter_plus_exit_time_us = 14.5,
.valid = true,
},
}

View File

@@ -71,8 +71,6 @@
#include "dmub/dmub_srv.h"
#include "dcn30/dcn30_vpg.h"
#include "i2caux_interface.h"
#include "dce/dmub_hw_lock_mgr.h"
@@ -2674,9 +2672,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
enum surface_update_type update_type,
struct dc_state *context)
{
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct vpg *vpg;
#endif
int j;
// Stream updates
@@ -2697,11 +2692,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
stream_update->vrr_infopacket ||
stream_update->vsc_infopacket ||
stream_update->vsp_infopacket) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
vpg = pipe_ctx->stream_res.stream_enc->vpg;
if (vpg && vpg->funcs->vpg_poweron)
vpg->funcs->vpg_poweron(vpg);
#endif
resource_build_info_frame(pipe_ctx);
dc->hwss.update_info_frame(pipe_ctx);
}
@@ -3118,8 +3108,13 @@ void dc_commit_updates_for_stream(struct dc *dc,
if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state)
new_pipe->plane_state->force_full_update = true;
}
} else if (update_type == UPDATE_TYPE_FAST) {
/* Previous frame finished and HW is ready for optimization. */
} else if (update_type == UPDATE_TYPE_FAST && dc_ctx->dce_version >= DCE_VERSION_MAX) {
/*
* Previous frame finished and HW is ready for optimization.
*
* Only relevant for DCN behavior where we can guarantee the optimization
* is safe to apply - retain the legacy behavior for DCE.
*/
dc_post_update_surfaces_to_stream(dc);
}
@@ -3178,6 +3173,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
}
}
/* Legacy optimization path for DCE. */
if (update_type >= UPDATE_TYPE_FULL && dc_ctx->dce_version < DCE_VERSION_MAX) {
dc_post_update_surfaces_to_stream(dc);
TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce);
}
return;
}

View File

@@ -674,13 +674,13 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link)
static void read_current_link_settings_on_detect(struct dc_link *link)
{
union lane_count_set lane_count_set = { {0} };
union lane_count_set lane_count_set = {0};
uint8_t link_bw_set;
uint8_t link_rate_set;
uint32_t read_dpcd_retry_cnt = 10;
enum dc_status status = DC_ERROR_UNEXPECTED;
int i;
union max_down_spread max_down_spread = { {0} };
union max_down_spread max_down_spread = {0};
// Read DPCD 00101h to find out the number of lanes currently set
for (i = 0; i < read_dpcd_retry_cnt; i++) {
@@ -1869,8 +1869,13 @@ static enum dc_status enable_link_dp(struct dc_state *state,
do_fallback = true;
#if defined(CONFIG_DRM_AMD_DC_DCN)
/*
* Temporary w/a to get DP2.0 link rates to work with SST.
* TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.
*/
if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING &&
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
link->dc->debug.set_mst_en_for_sst) {
dp_enable_mst_on_sink(link, true);
}
#endif
@@ -1983,51 +1988,6 @@ static enum dc_status enable_link_dp_mst(
return enable_link_dp(state, pipe_ctx);
}
void blank_all_dp_displays(struct dc *dc, bool hw_init)
{
unsigned int i, j, fe;
uint8_t dpcd_power_state = '\0';
enum dc_status status = DC_ERROR_UNEXPECTED;
for (i = 0; i < dc->link_count; i++) {
enum signal_type signal = dc->links[i]->connector_signal;
if ((signal == SIGNAL_TYPE_EDP) ||
(signal == SIGNAL_TYPE_DISPLAY_PORT)) {
if (hw_init && signal != SIGNAL_TYPE_EDP && dc->links[i]->priv != NULL) {
/* DP 2.0 spec requires that we read LTTPR caps first */
dp_retrieve_lttpr_cap(dc->links[i]);
/* if any of the displays are lit up turn them off */
status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
&dpcd_power_state, sizeof(dpcd_power_state));
}
if ((signal != SIGNAL_TYPE_EDP && status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) ||
(!hw_init && dc->links[i]->link_enc &&
dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc))) {
if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
fe = dc->links[i]->link_enc->funcs->get_dig_frontend(dc->links[i]->link_enc);
if (fe == ENGINE_ID_UNKNOWN)
continue;
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
}
}
if (!dc->links[i]->wa_flags.dp_keep_receiver_powered ||
(hw_init && signal != SIGNAL_TYPE_EDP && dc->links[i]->priv != NULL))
dp_receiver_power_ctrl(dc->links[i], false);
}
}
}
}
static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
enum engine_id eng_id,
struct ext_hdmi_settings *settings)
@@ -3274,8 +3234,7 @@ static void update_mst_stream_alloc_table(
struct stream_encoder *stream_enc,
const struct dp_mst_stream_allocation_table *proposed_table)
{
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
{ 0 } };
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };
struct link_mst_stream_allocation *dc_alloc;
int i;
@@ -3434,7 +3393,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
uint8_t i;
int i;
enum act_return_status ret;
DC_LOGGER_INIT(link->ctx->logger);
@@ -3526,7 +3485,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
struct dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
uint8_t i;
int i;
bool mst_mode = (link->type == dc_connection_mst_branch);
DC_LOGGER_INIT(link->ctx->logger);

View File

@@ -763,7 +763,7 @@ void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
sizeof(offset), &tmds_config, sizeof(tmds_config));
if (tmds_config & 0x1) {
union hdmi_scdc_status_flags_data status_data = { {0} };
union hdmi_scdc_status_flags_data status_data = {0};
uint8_t scramble_status = 0;
offset = HDMI_SCDC_SCRAMBLER_STATUS;

View File

@@ -259,7 +259,7 @@ static void dpcd_set_training_pattern(
struct dc_link *link,
enum dc_dp_training_pattern training_pattern)
{
union dpcd_training_pattern dpcd_pattern = { {0} };
union dpcd_training_pattern dpcd_pattern = {0};
dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
dc_dp_training_pattern_to_dpcd_training_pattern(
@@ -401,8 +401,8 @@ enum dc_status dpcd_set_link_settings(
uint8_t rate;
enum dc_status status;
union down_spread_ctrl downspread = { {0} };
union lane_count_set lane_count_set = { {0} };
union down_spread_ctrl downspread = {0};
union lane_count_set lane_count_set = {0};
downspread.raw = (uint8_t)
(lt_settings->link_settings.link_spread);
@@ -520,7 +520,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
uint32_t dpcd_base_lt_offset;
uint8_t dpcd_lt_buffer[5] = {0};
union dpcd_training_pattern dpcd_pattern = { {0} };
union dpcd_training_pattern dpcd_pattern = { 0 };
uint32_t size_in_bytes;
bool edp_workaround = false; /* TODO link_prop.INTERNAL */
dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
@@ -1266,8 +1266,8 @@ static enum link_training_result perform_channel_equalization_sequence(
uint32_t retries_ch_eq;
uint32_t wait_time_microsec;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_align_status_updated dpcd_lane_status_updated = {0};
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
/* Note: also check that TPS4 is a supported feature*/
@@ -1487,7 +1487,7 @@ static inline enum link_training_result dp_transition_to_video_idle(
struct link_training_settings *lt_settings,
enum link_training_result status)
{
union lane_count_set lane_count_set = { {0} };
union lane_count_set lane_count_set = {0};
/* 4. mainlink output idle pattern*/
dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
@@ -1800,7 +1800,7 @@ static enum dc_status configure_lttpr_mode_non_transparent(
static void repeater_training_done(struct dc_link *link, uint32_t offset)
{
union dpcd_training_pattern dpcd_pattern = { {0} };
union dpcd_training_pattern dpcd_pattern = {0};
const uint32_t dpcd_base_lt_offset =
DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
@@ -2078,8 +2078,8 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
uint32_t aux_rd_interval = 0;
uint32_t wait_time = 0;
struct link_training_settings req_settings;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_align_status_updated dpcd_lane_status_updated = {0};
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
enum link_training_result status = LINK_TRAINING_SUCCESS;
/* Transmit 128b/132b_TPS1 over Main-Link and Set TRAINING_PATTERN_SET to 01h */
@@ -2149,8 +2149,8 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
/* Assumption: assume hardware has transmitted eq pattern */
enum link_training_result status = LINK_TRAINING_SUCCESS;
struct link_training_settings req_settings;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_align_status_updated dpcd_lane_status_updated = {0};
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
uint32_t wait_time = 0;
/* initiate CDS done sequence */
@@ -2863,7 +2863,7 @@ bool dp_verify_link_cap(
link->verified_link_cap = *known_limit_link_setting;
return true;
} else if (link->link_enc && link->dc->res_pool->funcs->link_encs_assign &&
!link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine)) {
!link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine, link)) {
link->verified_link_cap = initial_link_settings;
return true;
}
@@ -4065,8 +4065,8 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
bool defer_handling, bool *has_left_work)
{
union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
union device_service_irq device_service_clear = { { 0 } };
union hpd_irq_data hpd_irq_dpcd_data = {0};
union device_service_irq device_service_clear = {0};
enum dc_status result;
bool status = false;
@@ -5939,7 +5939,7 @@ bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timin
uint8_t link_bw_set;
uint8_t link_rate_set;
uint32_t req_bw;
union lane_count_set lane_count_set = { {0} };
union lane_count_set lane_count_set = {0};
ASSERT(link || crtc_timing); // invalid input

View File

@@ -488,16 +488,19 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
return link_enc;
}
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id)
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link)
{
bool is_avail = true;
int i;
/* Add assigned encoders to list. */
/* An encoder is not available if it has already been assigned to a different endpoint. */
for (i = 0; i < MAX_PIPES; i++) {
struct link_enc_assignment assignment = get_assignment(dc, i);
struct display_endpoint_id ep_id = (struct display_endpoint_id) {
.link_id = link->link_id,
.ep_type = link->ep_type};
if (assignment.valid && assignment.eng_id == eng_id) {
if (assignment.valid && assignment.eng_id == eng_id && !are_ep_ids_equal(&ep_id, &assignment.ep_id)) {
is_avail = false;
break;
}

View File

@@ -3009,6 +3009,11 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
{
enum dc_status res = DC_OK;
/* check if surface has invalid dimensions */
if (plane_state->src_rect.width == 0 || plane_state->src_rect.height == 0 ||
plane_state->dst_rect.width == 0 || plane_state->dst_rect.height == 0)
return DC_FAIL_SURFACE_VALIDATE;
/* TODO For now validates pixel format only */
if (dc->res_pool->funcs->validate_plane)
return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);

View File

@@ -202,6 +202,10 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
new_stream->stream_id = new_stream->ctx->dc_stream_id_count;
new_stream->ctx->dc_stream_id_count++;
/* If using dynamic encoder assignment, wait till stream committed to assign encoder. */
if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign)
new_stream->link_enc = NULL;
kref_init(&new_stream->refcount);
return new_stream;

View File

@@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
#define DC_VER "3.2.156"
#define DC_VER "3.2.157"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -664,6 +664,7 @@ struct dc_debug_options {
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* TODO - remove once tested */
bool legacy_dp2_lt;
bool set_mst_en_for_sst;
#endif
union mem_low_power_enable_options enable_mem_low_power;
union root_clock_optimization_options root_clock_optimization;

View File

@@ -277,7 +277,6 @@ bool dc_link_setup_psr(struct dc_link *dc_link,
struct psr_context *psr_context);
void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency);
void blank_all_dp_displays(struct dc *dc, bool hw_init);
/* Request DC to detect if there is a Panel connected.
* boot - If this call is during initial boot.

View File

@@ -653,6 +653,7 @@ enum dc_psr_state {
PSR_STATE1a,
PSR_STATE2,
PSR_STATE2a,
PSR_STATE2b,
PSR_STATE3,
PSR_STATE3Init,
PSR_STATE4,

View File

@@ -50,6 +50,8 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state)
state = PSR_STATE2;
else if (raw_state == 0x21)
state = PSR_STATE2a;
else if (raw_state == 0x22)
state = PSR_STATE2b;
else if (raw_state == 0x30)
state = PSR_STATE3;
else if (raw_state == 0x31)

View File

@@ -1649,13 +1649,31 @@ static enum dc_status apply_single_controller_ctx_to_hw(
static void power_down_encoders(struct dc *dc)
{
int i;
blank_all_dp_displays(dc, false);
int i, j;
for (i = 0; i < dc->link_count; i++) {
enum signal_type signal = dc->links[i]->connector_signal;
if ((signal == SIGNAL_TYPE_EDP) ||
(signal == SIGNAL_TYPE_DISPLAY_PORT)) {
if (dc->links[i]->link_enc->funcs->get_dig_frontend &&
dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc)) {
unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
dc->links[i]->link_enc);
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
}
}
if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
dp_receiver_power_ctrl(dc->links[i], false);
}
if (signal != SIGNAL_TYPE_EDP)
signal = SIGNAL_TYPE_NONE;

View File

@@ -1366,7 +1366,7 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
void dcn10_init_hw(struct dc *dc)
{
int i;
int i, j;
struct abm *abm = dc->res_pool->abm;
struct dmcu *dmcu = dc->res_pool->dmcu;
struct dce_hwseq *hws = dc->hwseq;
@@ -1462,8 +1462,43 @@ void dcn10_init_hw(struct dc *dc)
dmub_enable_outbox_notification(dc);
/* we want to turn off all dp displays before doing detection */
if (dc->config.power_down_display_on_boot)
blank_all_dp_displays(dc, true);
if (dc->config.power_down_display_on_boot) {
uint8_t dpcd_power_state = '\0';
enum dc_status status = DC_ERROR_UNEXPECTED;
for (i = 0; i < dc->link_count; i++) {
if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
continue;
/* DP 2.0 requires that LTTPR Caps be read first */
dp_retrieve_lttpr_cap(dc->links[i]);
/*
* If any of the displays are lit up turn them off.
* The reason is that some MST hubs cannot be turned off
* completely until we tell them to do so.
* If not turned off, then displays connected to MST hub
* won't light up.
*/
status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
&dpcd_power_state, sizeof(dpcd_power_state));
if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
/* blank dp stream before power off receiver*/
if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend(dc->links[i]->link_enc);
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
}
}
dp_receiver_power_ctrl(dc->links[i], false);
}
}
}
/* If taking control over from VBIOS, we may want to optimize our first
* mode set, so we need to skip powering down pipes until we know which
@@ -2304,8 +2339,8 @@ static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
{
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
struct vm_system_aperture_param apt = { {{ 0 } } };
struct vm_context0_param vm0 = { { { 0 } } };
struct vm_system_aperture_param apt = {0};
struct vm_context0_param vm0 = {0};
mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
@@ -2478,7 +2513,7 @@ void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx,
void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct mpcc_blnd_cfg blnd_cfg = {{0}};
struct mpcc_blnd_cfg blnd_cfg = {0};
bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
int mpcc_id;
struct mpcc *new_mpcc;
@@ -3635,7 +3670,7 @@ void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings)
{
struct encoder_unblank_param params = { { 0 } };
struct encoder_unblank_param params = {0};
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq;

View File

@@ -169,7 +169,29 @@
type DTBCLK_DTO_DIV[MAX_PIPES];\
type DCCG_AUDIO_DTO_SEL;\
type DCCG_AUDIO_DTO0_SOURCE_SEL;\
type DENTIST_DISPCLK_CHG_MODE;
type DENTIST_DISPCLK_CHG_MODE;\
type DSCCLK0_DTO_PHASE;\
type DSCCLK0_DTO_MODULO;\
type DSCCLK1_DTO_PHASE;\
type DSCCLK1_DTO_MODULO;\
type DSCCLK2_DTO_PHASE;\
type DSCCLK2_DTO_MODULO;\
type DSCCLK0_DTO_ENABLE;\
type DSCCLK1_DTO_ENABLE;\
type DSCCLK2_DTO_ENABLE;\
type SYMCLK32_ROOT_SE0_GATE_DISABLE;\
type SYMCLK32_ROOT_SE1_GATE_DISABLE;\
type SYMCLK32_ROOT_SE2_GATE_DISABLE;\
type SYMCLK32_ROOT_SE3_GATE_DISABLE;\
type SYMCLK32_ROOT_LE0_GATE_DISABLE;\
type SYMCLK32_ROOT_LE1_GATE_DISABLE;\
type DPSTREAMCLK_ROOT_GATE_DISABLE;\
type DPSTREAMCLK_GATE_DISABLE;\
type HDMISTREAMCLK0_DTO_PHASE;\
type HDMISTREAMCLK0_DTO_MODULO;\
type HDMICHARCLK0_GATE_DISABLE;\
type HDMICHARCLK0_ROOT_GATE_DISABLE;
struct dccg_shift {
DCCG_REG_FIELD_LIST(uint8_t)
@@ -205,6 +227,16 @@ struct dccg_registers {
uint32_t SYMCLK32_SE_CNTL;
uint32_t SYMCLK32_LE_CNTL;
uint32_t DENTIST_DISPCLK_CNTL;
uint32_t DSCCLK_DTO_CTRL;
uint32_t DSCCLK0_DTO_PARAM;
uint32_t DSCCLK1_DTO_PARAM;
uint32_t DSCCLK2_DTO_PARAM;
uint32_t DPSTREAMCLK_ROOT_GATE_DISABLE;
uint32_t DPSTREAMCLK_GATE_DISABLE;
uint32_t DCCG_GATE_DISABLE_CNTL3;
uint32_t HDMISTREAMCLK0_DTO_PARAM;
uint32_t DCCG_GATE_DISABLE_CNTL4;
};
struct dcn_dccg {

View File

@@ -2123,7 +2123,7 @@ void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings)
{
struct encoder_unblank_param params = { { 0 } };
struct encoder_unblank_param params = {0};
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq;
@@ -2298,7 +2298,7 @@ void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx,
void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct mpcc_blnd_cfg blnd_cfg = { {0} };
struct mpcc_blnd_cfg blnd_cfg = {0};
bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
int mpcc_id;
struct mpcc *new_mpcc;

View File

@@ -437,7 +437,7 @@ void dcn30_init_hw(struct dc *dc)
struct dce_hwseq *hws = dc->hwseq;
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
int i, j;
int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
@@ -534,8 +534,41 @@ void dcn30_init_hw(struct dc *dc)
hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
/* we want to turn off all dp displays before doing detection */
if (dc->config.power_down_display_on_boot)
blank_all_dp_displays(dc, true);
if (dc->config.power_down_display_on_boot) {
uint8_t dpcd_power_state = '\0';
enum dc_status status = DC_ERROR_UNEXPECTED;
for (i = 0; i < dc->link_count; i++) {
if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
continue;
/* DP 2.0 states that LTTPR regs must be read first */
dp_retrieve_lttpr_cap(dc->links[i]);
/* if any of the displays are lit up turn them off */
status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
&dpcd_power_state, sizeof(dpcd_power_state));
if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
/* blank dp stream before power off receiver*/
if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
unsigned int fe;
fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
dc->links[i]->link_enc);
if (fe == ENGINE_ID_UNKNOWN)
continue;
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
}
}
dp_receiver_power_ctrl(dc->links[i], false);
}
}
}
/* If taking control over from VBIOS, we may want to optimize our first
* mode set, so we need to skip powering down pipes until we know which
@@ -969,7 +1002,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
/* turning off DPG */
pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false);
for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false);
if (mpcc_pipe->plane_res.hubp)
mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false);
stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space,
color_depth, solid_color, width, height, offset);

View File

@@ -129,7 +129,7 @@ static void apg31_se_audio_setup(
/* When running in "pair mode", pairs of audio channels have their own enable
* this is for really old audio drivers */
REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, 0xF);
REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, 0xFF);
// REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, channels);
/* Disable forced mem power off */

View File

@@ -26,6 +26,7 @@
#include "reg_helper.h"
#include "core_types.h"
#include "dcn31_dccg.h"
#include "dal_asic_id.h"
#define TO_DCN_DCCG(dccg)\
container_of(dccg, struct dcn_dccg, base)
@@ -42,10 +43,58 @@
#define DC_LOGGER \
dccg->ctx->logger
void dccg31_set_dpstreamclk(
struct dccg *dccg,
enum hdmistreamclk_source src,
int otg_inst)
static void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (dccg->ref_dppclk && req_dppclk) {
int ref_dppclk = dccg->ref_dppclk;
int modulo, phase;
// phase / modulo = dpp pipe clk / dpp global clk
modulo = 0xff; // use FF at the end
phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
if (phase > 0xff) {
ASSERT(false);
phase = 0xff;
}
REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
DPPCLK0_DTO_PHASE, phase,
DPPCLK0_DTO_MODULO, modulo);
REG_UPDATE(DPPCLK_DTO_CTRL,
DPPCLK_DTO_ENABLE[dpp_inst], 1);
} else {
//DTO must be enabled to generate a 0Hz clock output
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
REG_UPDATE(DPPCLK_DTO_CTRL,
DPPCLK_DTO_ENABLE[dpp_inst], 1);
REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
DPPCLK0_DTO_PHASE, 0,
DPPCLK0_DTO_MODULO, 1);
} else {
REG_UPDATE(DPPCLK_DTO_CTRL,
DPPCLK_DTO_ENABLE[dpp_inst], 0);
}
}
dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
}
static enum phyd32clk_clock_source get_phy_mux_symclk(
struct dcn_dccg *dccg_dcn,
enum phyd32clk_clock_source src)
{
if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
if (src == PHYD32CLKC)
src = PHYD32CLKF;
if (src == PHYD32CLKD)
src = PHYD32CLKG;
}
return src;
}
static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
@@ -53,24 +102,69 @@ void dccg31_set_dpstreamclk(
switch (otg_inst) {
case 0:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE0_EN, (src == REFCLK) ? 0 : 1);
DPSTREAMCLK_PIPE0_EN, 1);
break;
case 1:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE1_EN, (src == REFCLK) ? 0 : 1);
DPSTREAMCLK_PIPE1_EN, 1);
break;
case 2:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE2_EN, (src == REFCLK) ? 0 : 1);
DPSTREAMCLK_PIPE2_EN, 1);
break;
case 3:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE3_EN, (src == REFCLK) ? 0 : 1);
DPSTREAMCLK_PIPE3_EN, 1);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
}
static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
DPSTREAMCLK_ROOT_GATE_DISABLE, 0);
switch (otg_inst) {
case 0:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE0_EN, 0);
break;
case 1:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE1_EN, 0);
break;
case 2:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE2_EN, 0);
break;
case 3:
REG_UPDATE(DPSTREAMCLK_CNTL,
DPSTREAMCLK_PIPE3_EN, 0);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
void dccg31_set_dpstreamclk(
struct dccg *dccg,
enum hdmistreamclk_source src,
int otg_inst)
{
if (src == REFCLK)
dccg31_disable_dpstreamclk(dccg, otg_inst);
else
dccg31_enable_dpstreamclk(dccg, otg_inst);
}
void dccg31_enable_symclk32_se(
@@ -80,24 +174,38 @@ void dccg31_enable_symclk32_se(
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
/* select one of the PHYD32CLKs as the source for symclk32_se */
switch (hpo_se_inst) {
case 0:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE0_SRC_SEL, phyd32clk,
SYMCLK32_SE0_EN, 1);
break;
case 1:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE1_SRC_SEL, phyd32clk,
SYMCLK32_SE1_EN, 1);
break;
case 2:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE2_SRC_SEL, phyd32clk,
SYMCLK32_SE2_EN, 1);
break;
case 3:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE3_SRC_SEL, phyd32clk,
SYMCLK32_SE3_EN, 1);
@@ -120,21 +228,33 @@ void dccg31_disable_symclk32_se(
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE0_SRC_SEL, 0,
SYMCLK32_SE0_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
break;
case 1:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE1_SRC_SEL, 0,
SYMCLK32_SE1_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
break;
case 2:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE2_SRC_SEL, 0,
SYMCLK32_SE2_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
break;
case 3:
REG_UPDATE_2(SYMCLK32_SE_CNTL,
SYMCLK32_SE3_SRC_SEL, 0,
SYMCLK32_SE3_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
break;
default:
BREAK_TO_DEBUGGER();
@@ -149,14 +269,22 @@ void dccg31_enable_symclk32_le(
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
/* select one of the PHYD32CLKs as the source for symclk32_le */
switch (hpo_le_inst) {
case 0:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE0_SRC_SEL, phyd32clk,
SYMCLK32_LE0_EN, 1);
break;
case 1:
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE1_SRC_SEL, phyd32clk,
SYMCLK32_LE1_EN, 1);
@@ -179,11 +307,87 @@ void dccg31_disable_symclk32_le(
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE0_SRC_SEL, 0,
SYMCLK32_LE0_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
break;
case 1:
REG_UPDATE_2(SYMCLK32_LE_CNTL,
SYMCLK32_LE1_SRC_SEL, 0,
SYMCLK32_LE1_EN, 0);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
static void dccg31_disable_dscclk(struct dccg *dccg, int inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
return;
//DTO must be enabled to generate a 0 Hz clock output
switch (inst) {
case 0:
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK0_DTO_ENABLE, 1);
REG_UPDATE_2(DSCCLK0_DTO_PARAM,
DSCCLK0_DTO_PHASE, 0,
DSCCLK0_DTO_MODULO, 1);
break;
case 1:
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK1_DTO_ENABLE, 1);
REG_UPDATE_2(DSCCLK1_DTO_PARAM,
DSCCLK1_DTO_PHASE, 0,
DSCCLK1_DTO_MODULO, 1);
break;
case 2:
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK2_DTO_ENABLE, 1);
REG_UPDATE_2(DSCCLK2_DTO_PARAM,
DSCCLK2_DTO_PHASE, 0,
DSCCLK2_DTO_MODULO, 1);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
}
static void dccg31_enable_dscclk(struct dccg *dccg, int inst)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
return;
//Disable DTO
switch (inst) {
case 0:
REG_UPDATE_2(DSCCLK0_DTO_PARAM,
DSCCLK0_DTO_PHASE, 0,
DSCCLK0_DTO_MODULO, 0);
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK0_DTO_ENABLE, 0);
break;
case 1:
REG_UPDATE_2(DSCCLK1_DTO_PARAM,
DSCCLK1_DTO_PHASE, 0,
DSCCLK1_DTO_MODULO, 0);
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK1_DTO_ENABLE, 0);
break;
case 2:
REG_UPDATE_2(DSCCLK2_DTO_PARAM,
DSCCLK2_DTO_PHASE, 0,
DSCCLK2_DTO_MODULO, 0);
REG_UPDATE(DSCCLK_DTO_CTRL,
DSCCLK2_DTO_ENABLE, 0);
break;
default:
BREAK_TO_DEBUGGER();
@@ -398,10 +602,23 @@ void dccg31_init(struct dccg *dccg)
dccg31_disable_symclk32_se(dccg, 1);
dccg31_disable_symclk32_se(dccg, 2);
dccg31_disable_symclk32_se(dccg, 3);
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
dccg31_disable_symclk32_le(dccg, 0);
dccg31_disable_symclk32_le(dccg, 1);
}
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
dccg31_disable_dpstreamclk(dccg, 0);
dccg31_disable_dpstreamclk(dccg, 1);
dccg31_disable_dpstreamclk(dccg, 2);
dccg31_disable_dpstreamclk(dccg, 3);
}
}
static const struct dccg_funcs dccg31_funcs = {
.update_dpp_dto = dccg2_update_dpp_dto,
.update_dpp_dto = dccg31_update_dpp_dto,
.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
.dccg_init = dccg31_init,
.set_dpstreamclk = dccg31_set_dpstreamclk,
@@ -413,6 +630,8 @@ static const struct dccg_funcs dccg31_funcs = {
.set_dtbclk_dto = dccg31_set_dtbclk_dto,
.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
.disable_dsc = dccg31_disable_dscclk,
.enable_dsc = dccg31_enable_dscclk,
};
struct dccg *dccg31_create(

View File

@@ -61,7 +61,13 @@
SR(DCCG_AUDIO_DTBCLK_DTO_MODULO),\
SR(DCCG_AUDIO_DTBCLK_DTO_PHASE),\
SR(DCCG_AUDIO_DTO_SOURCE),\
SR(DENTIST_DISPCLK_CNTL)
SR(DENTIST_DISPCLK_CNTL),\
SR(DSCCLK0_DTO_PARAM),\
SR(DSCCLK1_DTO_PARAM),\
SR(DSCCLK2_DTO_PARAM),\
SR(DSCCLK_DTO_CTRL),\
SR(DCCG_GATE_DISABLE_CNTL3),\
SR(HDMISTREAMCLK0_DTO_PARAM)
#define DCCG_MASK_SH_LIST_DCN31(mask_sh) \
@@ -119,7 +125,26 @@
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, DIV, 3, mask_sh),\
DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh)
DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh), \
DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\
DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\
DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\
DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\
DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\
DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_DTO_ENABLE, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_DTO_ENABLE, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_DTO_ENABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\
DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\
DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh)
struct dccg *dccg31_create(
@@ -130,6 +155,11 @@ struct dccg *dccg31_create(
void dccg31_init(struct dccg *dccg);
void dccg31_set_dpstreamclk(
struct dccg *dccg,
enum hdmistreamclk_source src,
int otg_inst);
void dccg31_enable_symclk32_se(
struct dccg *dccg,
int hpo_se_inst,

View File

@@ -49,6 +49,7 @@
#include "inc/link_dpcd.h"
#include "dcn10/dcn10_hw_sequencer.h"
#include "inc/link_enc_cfg.h"
#include "dcn30/dcn30_vpg.h"
#define DC_LOGGER_INIT(logger)
@@ -71,16 +72,11 @@ void dcn31_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
int i;
int edp_num;
int i, j;
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
// Initialize the dccg
if (res_pool->dccg->funcs->dccg_init)
res_pool->dccg->funcs->dccg_init(res_pool->dccg);
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
REG_WRITE(REFCLK_CNTL, 0);
@@ -107,6 +103,9 @@ void dcn31_init_hw(struct dc *dc)
hws->funcs.bios_golden_init(dc);
hws->funcs.disable_vga(dc->hwseq);
}
// Initialize the dccg
if (res_pool->dccg->funcs->dccg_init)
res_pool->dccg->funcs->dccg_init(res_pool->dccg);
if (dc->debug.enable_mem_low_power.bits.dmcu) {
// Force ERAM to shutdown if DMCU is not enabled
@@ -126,6 +125,18 @@ void dcn31_init_hw(struct dc *dc)
REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc->debug.enable_mem_low_power.bits.vpg && dc->res_pool->stream_enc[0]->vpg->funcs->vpg_powerdown) {
// Power down VPGs
for (i = 0; i < dc->res_pool->stream_enc_count; i++)
dc->res_pool->stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->stream_enc[i]->vpg);
#if defined(CONFIG_DRM_AMD_DC_DP2_0)
for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++)
dc->res_pool->hpo_dp_stream_enc[i]->vpg->funcs->vpg_powerdown(dc->res_pool->hpo_dp_stream_enc[i]->vpg);
#endif
}
#endif
if (dc->ctx->dc_bios->fw_info_valid) {
res_pool->ref_clocks.xtalin_clock_inKhz =
dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
@@ -179,9 +190,40 @@ void dcn31_init_hw(struct dc *dc)
dmub_enable_outbox_notification(dc);
/* we want to turn off all dp displays before doing detection */
if (dc->config.power_down_display_on_boot)
blank_all_dp_displays(dc, true);
if (dc->config.power_down_display_on_boot) {
uint8_t dpcd_power_state = '\0';
enum dc_status status = DC_ERROR_UNEXPECTED;
for (i = 0; i < dc->link_count; i++) {
if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
continue;
/* if any of the displays are lit up turn them off */
status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
&dpcd_power_state, sizeof(dpcd_power_state));
if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
/* blank dp stream before power off receiver*/
if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY &&
dc->links[i]->link_enc->funcs->get_dig_frontend) {
unsigned int fe;
fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
dc->links[i]->link_enc);
if (fe == ENGINE_ID_UNKNOWN)
continue;
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
}
}
dp_receiver_power_ctrl(dc->links[i], false);
}
}
}
/* If taking control over from VBIOS, we may want to optimize our first
* mode set, so we need to skip powering down pipes until we know which
@@ -196,48 +238,6 @@ void dcn31_init_hw(struct dc *dc)
!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
}
/* In headless boot cases, DIG may be turned
* on which causes HW/SW discrepancies.
* To avoid this, power down hardware on boot
* if DIG is turned on and seamless boot not enabled
*/
if (dc->config.power_down_display_on_boot) {
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link;
bool power_down = false;
get_edp_links(dc, edp_links, &edp_num);
if (edp_num) {
for (i = 0; i < edp_num; i++) {
edp_link = edp_links[i];
if (edp_link->link_enc->funcs->is_dig_enabled &&
edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
dc->hwss.edp_backlight_control &&
dc->hwss.power_down &&
dc->hwss.edp_power_control) {
dc->hwss.edp_backlight_control(edp_link, false);
dc->hwss.power_down(dc);
dc->hwss.edp_power_control(edp_link, false);
power_down = true;
}
}
}
if (!power_down) {
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
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;
}
}
}
}
for (i = 0; i < res_pool->audio_count; i++) {
struct audio *audio = res_pool->audios[i];
@@ -300,6 +300,12 @@ void dcn31_dsc_pg_control(
if (hws->ctx->dc->debug.disable_dsc_power_gate)
return;
if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc &&
hws->ctx->dc->res_pool->dccg->funcs->enable_dsc &&
power_on)
hws->ctx->dc->res_pool->dccg->funcs->enable_dsc(
hws->ctx->dc->res_pool->dccg, dsc_inst);
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
if (org_ip_request_cntl == 0)
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
@@ -336,6 +342,13 @@ void dcn31_dsc_pg_control(
if (org_ip_request_cntl == 0)
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc) {
if (hws->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on)
hws->ctx->dc->res_pool->dccg->funcs->disable_dsc(
hws->ctx->dc->res_pool->dccg, dsc_inst);
}
}

View File

@@ -222,8 +222,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = {
.num_states = 5,
.sr_exit_time_us = 9.0,
.sr_enter_plus_exit_time_us = 11.0,
.sr_exit_z8_time_us = 402.0,
.sr_enter_plus_exit_z8_time_us = 520.0,
.sr_exit_z8_time_us = 442.0,
.sr_enter_plus_exit_z8_time_us = 560.0,
.writeback_latency_us = 12.0,
.dram_channel_width_bytes = 4,
.round_trip_ping_latency_dcfclk_cycles = 106,
@@ -998,7 +998,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.disable_dcc = DCC_ENABLE,
.vsr_support = true,
.performance_trace = false,
.max_downscale_src_width = 3840,/*upto 4K*/
.max_downscale_src_width = 4096,/*upto true 4K*/
.disable_pplib_wm_range = false,
.scl_reset_length10 = true,
.sanity_checks = false,
@@ -1312,10 +1312,6 @@ static struct vpg *dcn31_vpg_create(
&vpg_shift,
&vpg_mask);
// Will re-enable hw block when we enable stream
// Check for enabled stream before powering down?
vpg31_powerdown(&vpg31->base);
return &vpg31->base;
}
@@ -1782,6 +1778,13 @@ static int dcn31_populate_dml_pipes_from_context(
pipe = &res_ctx->pipe_ctx[i];
timing = &pipe->stream->timing;
/*
* Immediate flip can be set dynamically after enabling the plane.
* We need to require support for immediate flip or underflow can be
* intermittently experienced depending on peak b/w requirements.
*/
pipes[pipe_cnt].pipe.src.immediate_flip = true;
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
pipes[pipe_cnt].pipe.src.gpuvm = true;
pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0;

View File

@@ -5398,9 +5398,9 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->MaximumReadBandwidthWithPrefetch =
v->MaximumReadBandwidthWithPrefetch
+ dml_max4(
v->VActivePixelBandwidth[i][j][k],
v->VActiveCursorBandwidth[i][j][k]
+ dml_max3(
v->VActivePixelBandwidth[i][j][k]
+ v->VActiveCursorBandwidth[i][j][k]
+ v->NoOfDPP[i][j][k]
* (v->meta_row_bandwidth[i][j][k]
+ v->dpte_row_bandwidth[i][j][k]),

View File

@@ -123,6 +123,15 @@ struct dccg_funcs {
void (*set_dispclk_change_mode)(
struct dccg *dccg,
enum dentist_dispclk_change_mode change_mode);
void (*disable_dsc)(
struct dccg *dccg,
int inst);
void (*enable_dsc)(
struct dccg *dccg,
int inst);
};
#endif //__DAL_DCCG_H__

View File

@@ -97,7 +97,7 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
const struct dc_stream_state *stream);
/* Return true if encoder available to use. */
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id);
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link);
/* Returns true if encoder assignments in supplied state pass validity checks. */
bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state);

View File

@@ -46,10 +46,10 @@
/* Firmware versioning. */
#ifdef DMUB_EXPOSE_VERSION
#define DMUB_FW_VERSION_GIT_HASH 0xf0c64c97
#define DMUB_FW_VERSION_GIT_HASH 0xd146258f
#define DMUB_FW_VERSION_MAJOR 0
#define DMUB_FW_VERSION_MINOR 0
#define DMUB_FW_VERSION_REVISION 87
#define DMUB_FW_VERSION_REVISION 88
#define DMUB_FW_VERSION_TEST 0
#define DMUB_FW_VERSION_VBIOS 0
#define DMUB_FW_VERSION_HOTFIX 0

View File

@@ -228,7 +228,7 @@ enum {
#define FAMILY_YELLOW_CARP 146
#define YELLOW_CARP_A0 0x01
#define YELLOW_CARP_B0 0x1A
#define YELLOW_CARP_B0 0x20
#define YELLOW_CARP_UNKNOWN 0xFF
#ifndef ASICREV_IS_YELLOW_CARP

View File

@@ -228,7 +228,7 @@ enum DC_FEATURE_MASK {
DC_FBC_MASK = (1 << 0), //0x1, disabled by default
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = (1 << 1), //0x2, enabled by default
DC_DISABLE_FRACTIONAL_PWM_MASK = (1 << 2), //0x4, disabled by default
DC_PSR_MASK = (1 << 3), //0x8, disabled by default
DC_PSR_MASK = (1 << 3), //0x8, disabled by default for dcn < 3.1
DC_EDP_NO_POWER_SEQUENCING = (1 << 4), //0x10, disabled by default
};
@@ -236,7 +236,8 @@ enum DC_DEBUG_MASK {
DC_DISABLE_PIPE_SPLIT = 0x1,
DC_DISABLE_STUTTER = 0x2,
DC_DISABLE_DSC = 0x4,
DC_DISABLE_CLOCK_GATING = 0x8
DC_DISABLE_CLOCK_GATING = 0x8,
DC_DISABLE_PSR = 0x10,
};
enum amd_dpm_forced_level;

View File

@@ -436,6 +436,8 @@
#define regPHYESYMCLK_CLOCK_CNTL_BASE_IDX 2
#define regDCCG_GATE_DISABLE_CNTL3 0x005a
#define regDCCG_GATE_DISABLE_CNTL3_BASE_IDX 2
#define regHDMISTREAMCLK0_DTO_PARAM 0x005b
#define regHDMISTREAMCLK0_DTO_PARAM_BASE_IDX 2
#define regDCCG_AUDIO_DTBCLK_DTO_PHASE 0x0061
#define regDCCG_AUDIO_DTBCLK_DTO_PHASE_BASE_IDX 2
#define regDCCG_AUDIO_DTBCLK_DTO_MODULO 0x0062

View File

@@ -1438,6 +1438,14 @@
#define DCCG_GATE_DISABLE_CNTL3__SYMCLK32_LE0_GATE_DISABLE_MASK 0x00200000L
#define DCCG_GATE_DISABLE_CNTL3__SYMCLK32_ROOT_LE1_GATE_DISABLE_MASK 0x00400000L
#define DCCG_GATE_DISABLE_CNTL3__SYMCLK32_LE1_GATE_DISABLE_MASK 0x00800000L
//HDMISTREAMCLK0_DTO_PARAM
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_PHASE__SHIFT 0x0
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_MODULO__SHIFT 0x8
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_EN__SHIFT 0x10
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_PHASE_MASK 0x000000FFL
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_MODULO_MASK 0x0000FF00L
#define HDMISTREAMCLK0_DTO_PARAM__HDMISTREAMCLK0_DTO_EN_MASK 0x00010000L
//DCCG_AUDIO_DTBCLK_DTO_PHASE
#define DCCG_AUDIO_DTBCLK_DTO_PHASE__DCCG_AUDIO_DTBCLK_DTO_PHASE__SHIFT 0x0
#define DCCG_AUDIO_DTBCLK_DTO_PHASE__DCCG_AUDIO_DTBCLK_DTO_PHASE_MASK 0xFFFFFFFFL

View File

@@ -2019,15 +2019,15 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = {
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_power_profile_mode, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
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(gpu_busy_percent, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
AMDGPU_DEVICE_ATTR_RO(mem_busy_percent, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
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),
AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
AMDGPU_DEVICE_ATTR_RO(gpu_metrics, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF),
AMDGPU_DEVICE_ATTR_RO(smartshift_apu_power, ATTR_FLAG_BASIC,
.attr_update = ss_power_attr_update),
AMDGPU_DEVICE_ATTR_RO(smartshift_dgpu_power, ATTR_FLAG_BASIC,

View File

@@ -1008,7 +1008,9 @@ struct pptable_funcs {
/**
* @set_power_limit: Set power limit in watts.
*/
int (*set_power_limit)(struct smu_context *smu, uint32_t n);
int (*set_power_limit)(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit);
/**
* @init_max_sustainable_clocks: Populate max sustainable clock speed

View File

@@ -197,7 +197,9 @@ int smu_v11_0_notify_display_change(struct smu_context *smu);
int smu_v11_0_get_current_power_limit(struct smu_context *smu,
uint32_t *power_limit);
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n);
int smu_v11_0_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit);
int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu);

View File

@@ -163,7 +163,9 @@ int smu_v13_0_notify_display_change(struct smu_context *smu);
int smu_v13_0_get_current_power_limit(struct smu_context *smu,
uint32_t *power_limit);
int smu_v13_0_set_power_limit(struct smu_context *smu, uint32_t n);
int smu_v13_0_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit);
int smu_v13_0_init_max_sustainable_clocks(struct smu_context *smu);

View File

@@ -455,6 +455,10 @@ static int smu_get_power_num_states(void *handle,
bool is_support_sw_smu(struct amdgpu_device *adev)
{
/* vega20 is 11.0.2, but it's supported via the powerplay code */
if (adev->asic_type == CHIP_VEGA20)
return false;
if (adev->ip_versions[MP1_HWIP][0] >= IP_VERSION(11, 0, 0))
return true;
@@ -2344,9 +2348,10 @@ static int smu_set_power_limit(void *handle, uint32_t limit)
mutex_lock(&smu->mutex);
limit &= (1<<24)-1;
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
if (smu->ppt_funcs->set_power_limit) {
ret = smu->ppt_funcs->set_power_limit(smu, limit);
ret = smu->ppt_funcs->set_power_limit(smu, limit_type, limit);
goto out;
}
@@ -2362,7 +2367,7 @@ static int smu_set_power_limit(void *handle, uint32_t limit)
limit = smu->current_power_limit;
if (smu->ppt_funcs->set_power_limit) {
ret = smu->ppt_funcs->set_power_limit(smu, limit);
ret = smu->ppt_funcs->set_power_limit(smu, limit_type, limit);
if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE))
smu->user_dpm_profile.power_limit = limit;
}

View File

@@ -436,6 +436,19 @@ static void arcturus_check_bxco_support(struct smu_context *smu)
}
}
static void arcturus_check_fan_support(struct smu_context *smu)
{
struct smu_table_context *table_context = &smu->smu_table;
PPTable_t *pptable = table_context->driver_pptable;
/* No sort of fan control possible if PPTable has it disabled */
smu->adev->pm.no_fan =
!(pptable->FeaturesToRun[0] & FEATURE_FAN_CONTROL_MASK);
if (smu->adev->pm.no_fan)
dev_info_once(smu->adev->dev,
"PMFW based fan control disabled");
}
static int arcturus_check_powerplay_table(struct smu_context *smu)
{
struct smu_table_context *table_context = &smu->smu_table;
@@ -443,6 +456,7 @@ static int arcturus_check_powerplay_table(struct smu_context *smu)
table_context->power_play_table;
arcturus_check_bxco_support(smu);
arcturus_check_fan_support(smu);
table_context->thermal_controller_type =
powerplay_table->thermal_controller_type;

View File

@@ -47,7 +47,6 @@
/* unit: MHz */
#define CYAN_SKILLFISH_SCLK_MIN 1000
#define CYAN_SKILLFISH_SCLK_MAX 2000
#define CYAN_SKILLFISH_SCLK_DEFAULT 1800
/* unit: mV */
#define CYAN_SKILLFISH_VDDC_MIN 700
@@ -59,6 +58,8 @@ static struct gfx_user_settings {
uint32_t vddc;
} cyan_skillfish_user_settings;
static uint32_t cyan_skillfish_sclk_default;
#define FEATURE_MASK(feature) (1ULL << feature)
#define SMC_DPM_FEATURE ( \
FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \
@@ -365,13 +366,19 @@ static bool cyan_skillfish_is_dpm_running(struct smu_context *smu)
return false;
ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
if (ret)
return false;
feature_enabled = (uint64_t)feature_mask[0] |
((uint64_t)feature_mask[1] << 32);
/*
* cyan_skillfish specific, query default sclk inseted of hard code.
*/
if (!cyan_skillfish_sclk_default)
cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK,
&cyan_skillfish_sclk_default);
return !!(feature_enabled & SMC_DPM_FEATURE);
}
@@ -444,14 +451,14 @@ static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu,
return -EINVAL;
}
if (input[1] <= CYAN_SKILLFISH_SCLK_MIN ||
if (input[1] < CYAN_SKILLFISH_SCLK_MIN ||
input[1] > CYAN_SKILLFISH_SCLK_MAX) {
dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
return -EINVAL;
}
if (input[2] <= CYAN_SKILLFISH_VDDC_MIN ||
if (input[2] < CYAN_SKILLFISH_VDDC_MIN ||
input[2] > CYAN_SKILLFISH_VDDC_MAX) {
dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
@@ -468,7 +475,7 @@ static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu,
return -EINVAL;
}
cyan_skillfish_user_settings.sclk = CYAN_SKILLFISH_SCLK_DEFAULT;
cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default;
cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC;
break;

View File

@@ -670,7 +670,7 @@ 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;
struct smu_11_0_dpm_table *dpm_table;
struct amdgpu_device *adev = smu->adev;
int ret = 0;
int i, ret = 0;
DpmDescriptor_t *table_member;
/* socclk dpm table setup */
@@ -746,78 +746,45 @@ static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu)
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 =
!table_member[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;
}
/* vclk0/1 dpm table setup */
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
/* vclk1 dpm table setup */
if (adev->vcn.num_vcn_inst > 1) {
dpm_table = &dpm_context->dpm_tables.vclk1_table;
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_VCLK1,
i ? SMU_VCLK1 : SMU_VCLK,
dpm_table);
if (ret)
return ret;
dpm_table->is_fine_grained =
!table_member[PPCLK_VCLK_1].SnapToDiscrete;
!table_member[i ? PPCLK_VCLK_1 : 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].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 =
!table_member[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;
/* dclk0/1 dpm table setup */
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
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_DCLK1,
i ? SMU_DCLK1 : SMU_DCLK,
dpm_table);
if (ret)
return ret;
dpm_table->is_fine_grained =
!table_member[PPCLK_DCLK_1].SnapToDiscrete;
!table_member[i ? PPCLK_DCLK_1 : 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].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;
@@ -902,32 +869,18 @@ 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 amdgpu_device *adev = smu->adev;
int ret = 0;
int i, ret = 0;
if (enable) {
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
if (adev->vcn.harvest_config & (1 << i))
continue;
/* 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);
ret = smu_cmn_send_smc_msg_with_param(smu, enable ?
SMU_MSG_PowerUpVcn : SMU_MSG_PowerDownVcn,
0x10000 * i, NULL);
if (ret)
return ret;
if (adev->vcn.num_vcn_inst > 1) {
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->vcn.num_vcn_inst > 1) {
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn,
0x10000, NULL);
if (ret)
return ret;
}
}
}

View File

@@ -255,7 +255,7 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
case IP_VERSION(11, 0, 11):
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
break;
case CHIP_VANGOGH:
case IP_VERSION(11, 5, 0):
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH;
break;
case IP_VERSION(11, 0, 12):
@@ -755,6 +755,7 @@ int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count)
*/
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 11) ||
adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 5, 0) ||
adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 12) ||
adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 13))
return 0;
@@ -978,10 +979,16 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
return ret;
}
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
int smu_v11_0_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit)
{
int power_src;
int ret = 0;
uint32_t limit_param;
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
return -EINVAL;
if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
@@ -1001,16 +1008,16 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
* BIT 16-23: PowerSource
* BIT 0-15: PowerLimit
*/
n &= 0xFFFF;
n |= 0 << 24;
n |= (power_src) << 16;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL);
limit_param = (limit & 0xFFFF);
limit_param |= 0 << 24;
limit_param |= (power_src) << 16;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit_param, NULL);
if (ret) {
dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
return ret;
}
smu->current_power_limit = n;
smu->current_power_limit = limit;
return 0;
}

View File

@@ -1386,52 +1386,38 @@ static int vangogh_set_performance_level(struct smu_context *smu,
uint32_t soc_mask, mclk_mask, fclk_mask;
uint32_t vclk_mask = 0, dclk_mask = 0;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_hard_min_freq = smu->gfx_default_soft_max_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = vangogh_force_dpm_limit_value(smu, true);
if (ret)
return ret;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
ret = vangogh_force_dpm_limit_value(smu, false);
if (ret)
return ret;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = vangogh_unforce_dpm_levels(smu);
if (ret)
return ret;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetHardMinGfxClk,
VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL);
if (ret)
return ret;
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_SetSoftMaxGfxClk,
VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL);
if (ret)
return ret;
smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
ret = vangogh_get_profiling_clk_mask(smu, level,
&vclk_mask,
@@ -1446,32 +1432,15 @@ static int vangogh_set_performance_level(struct smu_context *smu,
vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask);
vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn,
VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL);
if (ret)
return ret;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn,
VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL);
if (ret)
return ret;
smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = vangogh_get_profiling_clk_mask(smu, level,
NULL,
NULL,
@@ -1484,29 +1453,29 @@ static int vangogh_set_performance_level(struct smu_context *smu,
vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL);
if (ret)
return ret;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL);
if (ret)
return ret;
smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
ret = vangogh_set_peak_clock_by_device(smu);
if (ret)
return ret;
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
default:
break;
return 0;
}
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
smu->gfx_actual_hard_min_freq, NULL);
if (ret)
return ret;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
smu->gfx_actual_soft_max_freq, NULL);
if (ret)
return ret;
return ret;
}
@@ -2144,11 +2113,12 @@ static int vangogh_get_ppt_limit(struct smu_context *smu,
return 0;
}
static int vangogh_set_power_limit(struct smu_context *smu, uint32_t ppt_limit)
static int vangogh_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t ppt_limit)
{
struct smu_11_5_power_context *power_context =
smu->smu_power.power_context;
uint32_t limit_type = ppt_limit >> 24;
smu->smu_power.power_context;
int ret = 0;
if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {

View File

@@ -1241,11 +1241,13 @@ static int aldebaran_get_power_limit(struct smu_context *smu,
return 0;
}
static int aldebaran_set_power_limit(struct smu_context *smu, uint32_t n)
static int aldebaran_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit)
{
/* Power limit can be set only through primary die */
if (aldebaran_is_primary(smu))
return smu_v13_0_set_power_limit(smu, n);
return smu_v13_0_set_power_limit(smu, limit_type, limit);
return -EINVAL;
}

View File

@@ -945,22 +945,27 @@ int smu_v13_0_get_current_power_limit(struct smu_context *smu,
return ret;
}
int smu_v13_0_set_power_limit(struct smu_context *smu, uint32_t n)
int smu_v13_0_set_power_limit(struct smu_context *smu,
enum smu_ppt_limit_type limit_type,
uint32_t limit)
{
int ret = 0;
if (limit_type != SMU_DEFAULT_PPT_LIMIT)
return -EINVAL;
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);
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit, NULL);
if (ret) {
dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
return ret;
}
smu->current_power_limit = n;
smu->current_power_limit = limit;
return 0;
}