Merge tag 'amd-drm-next-6.1-2022-09-30' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.1-2022-09-30:

amdgpu:
- RLC FW code cleanup
- RLC fixes for GC 11.x
- SMU 13.x fixes
- CP FW code cleanup
- SDMA FW code cleanup
- GC 11.x fixes
- DCN 3.2.x fixes
- DCN 3.1.4 fixes
- Misc fixes
- RAS fixes
- SR-IOV fixes
- VCN 4.x fixes

amdkfd:
- GC 11.x fixes
- Xnack fixes
- UBSAN warning fix

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220930162012.5823-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2022-10-04 09:42:23 +10:00
commit 65898687cf
82 changed files with 2131 additions and 2002 deletions

View File

@ -1053,6 +1053,10 @@ bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
{
if (adev->flags & AMD_IS_APU)
return false;
if (amdgpu_sriov_vf(adev))
return false;
return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
}

View File

@ -756,11 +756,7 @@ void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bo
{
struct ras_err_data err_data = {0, 0, 0, NULL};
/* CPU MCA will handle page retirement if connected_to_cpu is 1 */
if (!adev->gmc.xgmi.connected_to_cpu)
amdgpu_umc_poison_handler(adev, &err_data, reset);
else if (reset)
amdgpu_amdkfd_gpu_reset(adev);
amdgpu_umc_poison_handler(adev, &err_data, reset);
}
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)

View File

@ -3154,7 +3154,8 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
continue;
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP && amdgpu_sriov_vf(adev))) {
r = adev->ip_blocks[i].version->funcs->resume(adev);
if (r) {
@ -4069,12 +4070,20 @@ static void amdgpu_device_evict_resources(struct amdgpu_device *adev)
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
{
struct amdgpu_device *adev = drm_to_adev(dev);
int r = 0;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
adev->in_suspend = true;
if (amdgpu_sriov_vf(adev)) {
amdgpu_virt_fini_data_exchange(adev);
r = amdgpu_virt_request_full_gpu(adev, false);
if (r)
return r;
}
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
DRM_WARN("smart shift update failed\n");
@ -4098,6 +4107,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
amdgpu_device_ip_suspend_phase2(adev);
if (amdgpu_sriov_vf(adev))
amdgpu_virt_release_full_gpu(adev, false);
return 0;
}
@ -4116,6 +4128,12 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
struct amdgpu_device *adev = drm_to_adev(dev);
int r = 0;
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_request_full_gpu(adev, true);
if (r)
return r;
}
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
@ -4130,6 +4148,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
}
r = amdgpu_device_ip_resume(adev);
/* no matter what r is, always need to properly release full GPU */
if (amdgpu_sriov_vf(adev)) {
amdgpu_virt_init_data_exchange(adev);
amdgpu_virt_release_full_gpu(adev, true);
}
if (r) {
dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
return r;
@ -5576,9 +5601,9 @@ bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
resource_size_t aper_limit =
adev->gmc.aper_base + adev->gmc.aper_size - 1;
bool p2p_access = !adev->gmc.xgmi.connected_to_cpu &&
!(pci_p2pdma_distance_many(adev->pdev,
&peer_adev->dev, 1, true) < 0);
bool p2p_access =
!adev->gmc.xgmi.connected_to_cpu &&
!(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
adev->gmc.real_vram_size == adev->gmc.visible_vram_size &&

View File

@ -229,7 +229,7 @@ static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, ui
return r;
}
memcpy((u8 *)binary, (u8 *)fw->data, adev->mman.discovery_tmr_size);
memcpy((u8 *)binary, (u8 *)fw->data, fw->size);
release_firmware(fw);
return 0;

View File

@ -58,7 +58,7 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r;
if (pci_p2pdma_distance_many(adev->pdev, &attach->dev, 1, true) < 0)
if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
attach->peer2peer = false;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);

View File

@ -400,7 +400,6 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring)
/* We are not protected by ring lock when reading the last sequence
* but it's ok to report slightly wrong fence count here.
*/
amdgpu_fence_process(ring);
emitted = 0x100000000ull;
emitted -= atomic_read(&ring->fence_drv.last_seq);
emitted += READ_ONCE(ring->fence_drv.sync_seq);

View File

@ -23,6 +23,7 @@
*
*/
#include <linux/firmware.h>
#include "amdgpu.h"
#include "amdgpu_gfx.h"
#include "amdgpu_rlc.h"
@ -865,3 +866,142 @@ int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev)
}
return amdgpu_num_kcq;
}
void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev,
uint32_t ucode_id)
{
const struct gfx_firmware_header_v1_0 *cp_hdr;
const struct gfx_firmware_header_v2_0 *cp_hdr_v2_0;
struct amdgpu_firmware_info *info = NULL;
const struct firmware *ucode_fw;
unsigned int fw_size;
switch (ucode_id) {
case AMDGPU_UCODE_ID_CP_PFP:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.pfp_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
ucode_fw = adev->gfx.pfp_fw;
fw_size = le32_to_cpu(cp_hdr->header.ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_RS64_PFP:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version =
le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.pfp_feature_version =
le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
ucode_fw = adev->gfx.pfp_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK:
case AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.pfp_fw->data;
ucode_fw = adev->gfx.pfp_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->data_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_ME:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.me_fw->data;
adev->gfx.me_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.me_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
ucode_fw = adev->gfx.me_fw;
fw_size = le32_to_cpu(cp_hdr->header.ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_RS64_ME:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.me_fw->data;
adev->gfx.me_fw_version =
le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.me_feature_version =
le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
ucode_fw = adev->gfx.me_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK:
case AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.me_fw->data;
ucode_fw = adev->gfx.me_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->data_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_CE:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.ce_fw->data;
adev->gfx.ce_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.ce_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
ucode_fw = adev->gfx.ce_fw;
fw_size = le32_to_cpu(cp_hdr->header.ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_MEC1:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
ucode_fw = adev->gfx.mec_fw;
fw_size = le32_to_cpu(cp_hdr->header.ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4;
break;
case AMDGPU_UCODE_ID_CP_MEC1_JT:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec_fw->data;
ucode_fw = adev->gfx.mec_fw;
fw_size = le32_to_cpu(cp_hdr->jt_size) * 4;
break;
case AMDGPU_UCODE_ID_CP_MEC2:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec2_fw->data;
adev->gfx.mec2_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec2_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
ucode_fw = adev->gfx.mec2_fw;
fw_size = le32_to_cpu(cp_hdr->header.ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4;
break;
case AMDGPU_UCODE_ID_CP_MEC2_JT:
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec2_fw->data;
ucode_fw = adev->gfx.mec2_fw;
fw_size = le32_to_cpu(cp_hdr->jt_size) * 4;
break;
case AMDGPU_UCODE_ID_CP_RS64_MEC:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version =
le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.mec_feature_version =
le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
ucode_fw = adev->gfx.mec_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes);
break;
case AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK:
case AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK:
case AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK:
case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK:
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)
adev->gfx.mec_fw->data;
ucode_fw = adev->gfx.mec_fw;
fw_size = le32_to_cpu(cp_hdr_v2_0->data_size_bytes);
break;
default:
break;
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[ucode_id];
info->ucode_id = ucode_id;
info->fw = ucode_fw;
adev->firmware.fw_size += ALIGN(fw_size, PAGE_SIZE);
}
}

View File

@ -426,4 +426,6 @@ int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev);
void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev, uint32_t ucode_id);
#endif

View File

@ -572,45 +572,15 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
{
struct amdgpu_gmc *gmc = &adev->gmc;
uint32_t gc_ver = adev->ip_versions[GC_HWIP][0];
bool noretry_default = (gc_ver == IP_VERSION(9, 0, 1) ||
gc_ver == IP_VERSION(9, 3, 0) ||
gc_ver == IP_VERSION(9, 4, 0) ||
gc_ver == IP_VERSION(9, 4, 1) ||
gc_ver == IP_VERSION(9, 4, 2) ||
gc_ver >= IP_VERSION(10, 3, 0));
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
case IP_VERSION(9, 3, 0):
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
case IP_VERSION(10, 3, 3):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
case IP_VERSION(10, 3, 6):
case IP_VERSION(10, 3, 7):
/*
* noretry = 0 will cause kfd page fault tests fail
* for some ASICs, so set default to 1 for these ASICs.
*/
if (amdgpu_noretry == -1)
gmc->noretry = 1;
else
gmc->noretry = amdgpu_noretry;
break;
default:
/* Raven currently has issues with noretry
* regardless of what we decide for other
* asics, we should leave raven with
* noretry = 0 until we root cause the
* issues.
*
* default this to 0 for now, but we may want
* to change this in the future for certain
* GPUs as it can increase performance in
* certain cases.
*/
if (amdgpu_noretry == -1)
gmc->noretry = 0;
else
gmc->noretry = amdgpu_noretry;
break;
}
gmc->noretry = (amdgpu_noretry == -1) ? noretry_default : amdgpu_noretry;
}
void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type,

View File

@ -222,6 +222,8 @@ struct mes_add_queue_input {
uint64_t tba_addr;
uint64_t tma_addr;
uint32_t is_kfd_process;
uint32_t is_aql_queue;
uint32_t queue_size;
};
struct mes_remove_queue_input {

View File

@ -2720,7 +2720,8 @@ int amdgpu_ras_pre_fini(struct amdgpu_device *adev)
/* Need disable ras on all IPs here before ip [hw/sw]fini */
amdgpu_ras_disable_all_features(adev, 0);
if (con->features)
amdgpu_ras_disable_all_features(adev, 0);
amdgpu_ras_recovery_fini(adev);
return 0;
}
@ -2833,11 +2834,8 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
struct mce *m = (struct mce *)data;
struct amdgpu_device *adev = NULL;
uint32_t gpu_id = 0;
uint32_t umc_inst = 0;
uint32_t ch_inst, channel_index = 0;
uint32_t umc_inst = 0, ch_inst = 0;
struct ras_err_data err_data = {0, 0, 0, NULL};
struct eeprom_table_record err_rec;
uint64_t retired_page;
/*
* If the error was generated in UMC_V2, which belongs to GPU UMCs,
@ -2876,21 +2874,22 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d",
umc_inst, ch_inst);
err_data.err_addr =
kcalloc(adev->umc.max_ras_err_cnt_per_query,
sizeof(struct eeprom_table_record), GFP_KERNEL);
if(!err_data.err_addr) {
dev_warn(adev->dev, "Failed to alloc memory for "
"umc error address record in mca notifier!\n");
return NOTIFY_DONE;
}
/*
* Translate UMC channel address to Physical address
*/
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num
+ ch_inst];
retired_page = ADDR_OF_8KB_BLOCK(m->addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(m->addr);
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
err_data.err_addr = &err_rec;
amdgpu_umc_fill_error_record(&err_data, m->addr,
retired_page, channel_index, umc_inst);
if (adev->umc.ras &&
adev->umc.ras->convert_ras_error_address)
adev->umc.ras->convert_ras_error_address(adev,
&err_data, 0, ch_inst, umc_inst, m->addr);
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
@ -2898,6 +2897,7 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
amdgpu_ras_save_bad_pages(adev);
}
kfree(err_data.err_addr);
return NOTIFY_OK;
}

View File

@ -113,7 +113,8 @@ static inline bool amdgpu_reset_get_reset_domain(struct amdgpu_reset_domain *dom
static inline void amdgpu_reset_put_reset_domain(struct amdgpu_reset_domain *domain)
{
kref_put(&domain->refcount, amdgpu_reset_destroy_reset_domain);
if (domain)
kref_put(&domain->refcount, amdgpu_reset_destroy_reset_domain);
}
static inline bool amdgpu_reset_domain_schedule(struct amdgpu_reset_domain *domain,

View File

@ -272,3 +272,275 @@ void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev)
&adev->gfx.rlc.cp_table_gpu_addr,
(void **)&adev->gfx.rlc.cp_table_ptr);
}
static int amdgpu_gfx_rlc_init_microcode_v2_0(struct amdgpu_device *adev)
{
const struct common_firmware_header *common_hdr;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
struct amdgpu_firmware_info *info;
unsigned int *tmp;
unsigned int i;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
adev->gfx.rlc.save_and_restore_offset =
le32_to_cpu(rlc_hdr->save_and_restore_offset);
adev->gfx.rlc.clear_state_descriptor_offset =
le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
adev->gfx.rlc.avail_scratch_ram_locations =
le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
adev->gfx.rlc.reg_restore_list_size =
le32_to_cpu(rlc_hdr->reg_restore_list_size);
adev->gfx.rlc.reg_list_format_start =
le32_to_cpu(rlc_hdr->reg_list_format_start);
adev->gfx.rlc.reg_list_format_separate_start =
le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
adev->gfx.rlc.starting_offsets_start =
le32_to_cpu(rlc_hdr->starting_offsets_start);
adev->gfx.rlc.reg_list_format_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
adev->gfx.rlc.reg_list_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_size_bytes);
adev->gfx.rlc.register_list_format =
kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
if (!adev->gfx.rlc.register_list_format) {
dev_err(adev->dev, "failed to allocate memory for rlc register_list_format\n");
return -ENOMEM;
}
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
info->fw = adev->gfx.rlc_fw;
if (info->fw) {
common_hdr = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(common_hdr->ucode_size_bytes), PAGE_SIZE);
}
}
return 0;
}
static void amdgpu_gfx_rlc_init_microcode_v2_1(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_1 *rlc_hdr;
struct amdgpu_firmware_info *info;
rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
adev->gfx.rlc.reg_list_format_direct_reg_list_length =
le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
if (adev->gfx.rlc.save_restore_list_cntl_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_cntl_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.save_restore_list_gpm_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.save_restore_list_srm_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
}
}
}
static void amdgpu_gfx_rlc_init_microcode_v2_2(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_2 *rlc_hdr;
struct amdgpu_firmware_info *info;
rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
if (adev->gfx.rlc.rlc_iram_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
}
}
}
static void amdgpu_gfx_rlc_init_microcode_v2_3(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_3 *rlc_hdr;
struct amdgpu_firmware_info *info;
rlc_hdr = (const struct rlc_firmware_header_v2_3 *)adev->gfx.rlc_fw->data;
adev->gfx.rlcp_ucode_version = le32_to_cpu(rlc_hdr->rlcp_ucode_version);
adev->gfx.rlcp_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcp_ucode_feature_version);
adev->gfx.rlc.rlcp_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcp_ucode_size_bytes);
adev->gfx.rlc.rlcp_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcp_ucode_offset_bytes);
adev->gfx.rlcv_ucode_version = le32_to_cpu(rlc_hdr->rlcv_ucode_version);
adev->gfx.rlcv_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcv_ucode_feature_version);
adev->gfx.rlc.rlcv_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcv_ucode_size_bytes);
adev->gfx.rlc.rlcv_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcv_ucode_offset_bytes);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
if (adev->gfx.rlc.rlcp_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_P];
info->ucode_id = AMDGPU_UCODE_ID_RLC_P;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlcp_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.rlcv_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_V];
info->ucode_id = AMDGPU_UCODE_ID_RLC_V;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlcv_ucode_size_bytes, PAGE_SIZE);
}
}
}
static void amdgpu_gfx_rlc_init_microcode_v2_4(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_4 *rlc_hdr;
struct amdgpu_firmware_info *info;
rlc_hdr = (const struct rlc_firmware_header_v2_4 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc.global_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->global_tap_delays_ucode_size_bytes);
adev->gfx.rlc.global_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->global_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se0_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se0_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se1_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se1_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se2_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se2_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se3_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se3_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_offset_bytes);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
if (adev->gfx.rlc.global_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se0_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se1_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se2_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se3_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
}
}
int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
uint16_t version_major,
uint16_t version_minor)
{
int err;
if (version_major < 2) {
/* only support rlc_hdr v2.x and onwards */
dev_err(adev->dev, "unsupported rlc fw hdr\n");
return -EINVAL;
}
/* is_rlc_v2_1 is still used in APU code path */
if (version_major == 2 && version_minor == 1)
adev->gfx.rlc.is_rlc_v2_1 = true;
if (version_minor >= 0) {
err = amdgpu_gfx_rlc_init_microcode_v2_0(adev);
if (err) {
dev_err(adev->dev, "fail to init rlc v2_0 microcode\n");
return err;
}
}
if (version_minor >= 1)
amdgpu_gfx_rlc_init_microcode_v2_1(adev);
if (version_minor >= 2)
amdgpu_gfx_rlc_init_microcode_v2_2(adev);
if (version_minor == 3)
amdgpu_gfx_rlc_init_microcode_v2_3(adev);
if (version_minor == 4)
amdgpu_gfx_rlc_init_microcode_v2_4(adev);
return 0;
}

View File

@ -267,5 +267,7 @@ int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev);
int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev);
void amdgpu_gfx_rlc_setup_cp_table(struct amdgpu_device *adev);
void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev);
int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
uint16_t version_major,
uint16_t version_minor);
#endif

View File

@ -21,6 +21,7 @@
*
*/
#include <linux/firmware.h>
#include "amdgpu.h"
#include "amdgpu_sdma.h"
#include "amdgpu_ras.h"
@ -150,3 +151,135 @@ int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
amdgpu_ras_interrupt_dispatch(adev, &ih_data);
return 0;
}
static int amdgpu_sdma_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
int err = 0;
uint16_t version_major;
const struct common_firmware_header *header = NULL;
const struct sdma_firmware_header_v1_0 *hdr;
const struct sdma_firmware_header_v2_0 *hdr_v2;
err = amdgpu_ucode_validate(sdma_inst->fw);
if (err)
return err;
header = (const struct common_firmware_header *)
sdma_inst->fw->data;
version_major = le16_to_cpu(header->header_version_major);
switch (version_major) {
case 1:
hdr = (const struct sdma_firmware_header_v1_0 *)sdma_inst->fw->data;
sdma_inst->fw_version = le32_to_cpu(hdr->header.ucode_version);
sdma_inst->feature_version = le32_to_cpu(hdr->ucode_feature_version);
break;
case 2:
hdr_v2 = (const struct sdma_firmware_header_v2_0 *)sdma_inst->fw->data;
sdma_inst->fw_version = le32_to_cpu(hdr_v2->header.ucode_version);
sdma_inst->feature_version = le32_to_cpu(hdr_v2->ucode_feature_version);
break;
default:
return -EINVAL;
}
if (sdma_inst->feature_version >= 20)
sdma_inst->burst_nop = true;
return 0;
}
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate)
{
int i;
for (i = 0; i < adev->sdma.num_instances; i++) {
release_firmware(adev->sdma.instance[i].fw);
if (duplicate)
break;
}
memset((void *)adev->sdma.instance, 0,
sizeof(struct amdgpu_sdma_instance) * AMDGPU_MAX_SDMA_INSTANCES);
}
int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
char *fw_name, u32 instance,
bool duplicate)
{
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
int err = 0, i;
const struct sdma_firmware_header_v2_0 *sdma_hdr;
uint16_t version_major;
err = request_firmware(&adev->sdma.instance[instance].fw, fw_name, adev->dev);
if (err)
goto out;
header = (const struct common_firmware_header *)
adev->sdma.instance[instance].fw->data;
version_major = le16_to_cpu(header->header_version_major);
if ((duplicate && instance) || (!duplicate && version_major > 1))
return -EINVAL;
err = amdgpu_sdma_init_inst_ctx(&adev->sdma.instance[instance]);
if (err)
goto out;
if (duplicate) {
for (i = 1; i < adev->sdma.num_instances; i++)
memcpy((void *)&adev->sdma.instance[i],
(void *)&adev->sdma.instance[0],
sizeof(struct amdgpu_sdma_instance));
}
if (amdgpu_sriov_vf(adev))
return 0;
DRM_DEBUG("psp_load == '%s'\n",
adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
switch (version_major) {
case 1:
for (i = 0; i < adev->sdma.num_instances; i++) {
if (!duplicate && (instance != i))
continue;
else {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
info->fw = adev->sdma.instance[i].fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
}
break;
case 2:
sdma_hdr = (const struct sdma_firmware_header_v2_0 *)
adev->sdma.instance[0].fw->data;
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA_UCODE_TH0];
info->ucode_id = AMDGPU_UCODE_ID_SDMA_UCODE_TH0;
info->fw = adev->sdma.instance[0].fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(sdma_hdr->ctx_ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA_UCODE_TH1];
info->ucode_id = AMDGPU_UCODE_ID_SDMA_UCODE_TH1;
info->fw = adev->sdma.instance[0].fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(sdma_hdr->ctl_ucode_size_bytes), PAGE_SIZE);
break;
default:
return -EINVAL;
}
}
out:
if (err) {
DRM_ERROR("SDMA: Failed to init firmware \"%s\"\n", fw_name);
amdgpu_sdma_destroy_inst_ctx(adev, duplicate);
}
return err;
}

View File

@ -124,4 +124,8 @@ int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
char *fw_name, u32 instance, bool duplicate);
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate);
#endif

View File

@ -22,6 +22,8 @@
#define __AMDGPU_UMC_H__
#include "amdgpu_ras.h"
#define UMC_INVALID_ADDR 0x1ULL
/*
* (addr / 256) * 4096, the higher 26 bits in ErrorAddr
* is the index of 4KB block
@ -51,6 +53,10 @@ struct amdgpu_umc_ras {
struct amdgpu_ras_block_object ras_block;
void (*err_cnt_init)(struct amdgpu_device *adev);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
void (*convert_ras_error_address)(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t umc_reg_offset, uint32_t ch_inst,
uint32_t umc_inst, uint64_t mca_addr);
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev,

View File

@ -191,7 +191,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
fw_name = FIRMWARE_VCN4_0_2;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = false;
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(4, 0, 4):
fw_name = FIRMWARE_VCN4_0_4;

View File

@ -161,7 +161,8 @@
#define AMDGPU_VCN_SW_RING_FLAG (1 << 9)
#define AMDGPU_VCN_FW_LOGGING_FLAG (1 << 10)
#define AMDGPU_VCN_SMU_VERSION_INFO_FLAG (1 << 11)
#define AMDGPU_VCN_VF_RB_SETUP_FLAG (1 << 12)
#define AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG (1 << 11)
#define AMDGPU_VCN_VF_RB_SETUP_FLAG (1 << 14)
#define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER 0x00000001
#define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER 0x00000001
@ -171,6 +172,9 @@
#define VCN_CODEC_DISABLE_MASK_HEVC (1 << 2)
#define VCN_CODEC_DISABLE_MASK_H264 (1 << 3)
#define AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU (0)
#define AMDGPU_VCN_SMU_DPM_INTERFACE_APU (1)
enum fw_queue_mode {
FW_QUEUE_RING_RESET = 1,
FW_QUEUE_DPG_HOLD_OFF = 2,
@ -335,7 +339,9 @@ struct amdgpu_vcn4_fw_shared {
struct amdgpu_fw_shared_unified_queue_struct sq;
uint8_t pad1[8];
struct amdgpu_fw_shared_fw_logging fw_log;
uint8_t pad2[20];
struct amdgpu_fw_shared_rb_setup rb_setup;
struct amdgpu_fw_shared_smu_interface_info smu_dpm_interface;
};
struct amdgpu_vcn_fwlog {

View File

@ -3943,56 +3943,6 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
DRM_WARN_ONCE("CP firmware version too old, please update!");
}
static void gfx_v10_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_1 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
adev->gfx.rlc.reg_list_format_direct_reg_list_length =
le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
}
static void gfx_v10_0_init_rlc_iram_dram_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_2 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
}
static void gfx_v10_0_init_tap_delays_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_4 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_4 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc.global_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->global_tap_delays_ucode_size_bytes);
adev->gfx.rlc.global_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->global_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se0_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se0_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se1_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se1_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se2_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se2_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_offset_bytes);
adev->gfx.rlc.se3_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_size_bytes);
adev->gfx.rlc.se3_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_offset_bytes);
}
static bool gfx_v10_0_navi10_gfxoff_should_enable(struct amdgpu_device *adev)
{
bool ret = false;
@ -4028,12 +3978,7 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
char fw_name[40];
char *wks = "";
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
unsigned int *tmp = NULL;
unsigned int i = 0;
uint16_t version_major;
uint16_t version_minor;
@ -4091,9 +4036,7 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me%s.bin", chip_name, wks);
err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
@ -4102,9 +4045,7 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = amdgpu_ucode_validate(adev->gfx.me_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce%s.bin", chip_name, wks);
err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
@ -4113,69 +4054,27 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = amdgpu_ucode_validate(adev->gfx.ce_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
if (!amdgpu_sriov_vf(adev)) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
if (err)
goto out;
/* don't check this. There are apparently firmwares in the wild with
* incorrect size in the header
*/
err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
if (err)
dev_dbg(adev->dev,
"gfx10: amdgpu_ucode_validate() failed \"%s\"\n",
fw_name);
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
adev->gfx.rlc.save_and_restore_offset =
le32_to_cpu(rlc_hdr->save_and_restore_offset);
adev->gfx.rlc.clear_state_descriptor_offset =
le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
adev->gfx.rlc.avail_scratch_ram_locations =
le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
adev->gfx.rlc.reg_restore_list_size =
le32_to_cpu(rlc_hdr->reg_restore_list_size);
adev->gfx.rlc.reg_list_format_start =
le32_to_cpu(rlc_hdr->reg_list_format_start);
adev->gfx.rlc.reg_list_format_separate_start =
le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
adev->gfx.rlc.starting_offsets_start =
le32_to_cpu(rlc_hdr->starting_offsets_start);
adev->gfx.rlc.reg_list_format_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
adev->gfx.rlc.reg_list_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_size_bytes);
adev->gfx.rlc.register_list_format =
kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
if (!adev->gfx.rlc.register_list_format) {
err = -ENOMEM;
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
if (err)
goto out;
}
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
if (version_major == 2) {
if (version_minor >= 1)
gfx_v10_0_init_rlc_ext_microcode(adev);
if (version_minor >= 2)
gfx_v10_0_init_rlc_iram_dram_microcode(adev);
if (version_minor == 4) {
gfx_v10_0_init_tap_delays_microcode(adev);
}
}
}
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", chip_name, wks);
@ -4185,9 +4084,8 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = amdgpu_ucode_validate(adev->gfx.mec_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2%s.bin", chip_name, wks);
err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
@ -4195,164 +4093,18 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec2_fw->data;
adev->gfx.mec2_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec2_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
} else {
err = 0;
adev->gfx.mec2_fw = NULL;
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_ME];
info->ucode_id = AMDGPU_UCODE_ID_CP_ME;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_CE];
info->ucode_id = AMDGPU_UCODE_ID_CP_CE;
info->fw = adev->gfx.ce_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
info->fw = adev->gfx.rlc_fw;
if (info->fw) {
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
if (adev->gfx.rlc.save_restore_list_cntl_size_bytes &&
adev->gfx.rlc.save_restore_list_gpm_size_bytes &&
adev->gfx.rlc.save_restore_list_srm_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_cntl_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
if (adev->gfx.rlc.rlc_iram_ucode_size_bytes &&
adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
}
}
if (adev->gfx.rlc.global_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se0_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se1_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se2_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.se3_tap_delays_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
}
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1_JT];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1_JT;
info->fw = adev->gfx.mec_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
if (adev->gfx.mec2_fw) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
info->fw = adev->gfx.mec2_fw;
header = (const struct common_firmware_header *)info->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4,
PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2_JT];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2_JT;
info->fw = adev->gfx.mec2_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4,
PAGE_SIZE);
}
}
gfx_v10_0_check_fw_write_wait(adev);
out:
if (err) {
dev_err(adev->dev,
"gfx10: Failed to load firmware \"%s\"\n",
"gfx10: Failed to init firmware \"%s\"\n",
fw_name);
release_firmware(adev->gfx.pfp_fw);
adev->gfx.pfp_fw = NULL;

View File

@ -438,66 +438,12 @@ static void gfx_v11_0_free_microcode(struct amdgpu_device *adev)
kfree(adev->gfx.rlc.register_list_format);
}
static void gfx_v11_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_1 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
adev->gfx.rlc.reg_list_format_direct_reg_list_length =
le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
}
static void gfx_v11_0_init_rlc_iram_dram_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_2 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
}
static void gfx_v11_0_init_rlcp_rlcv_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_3 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_3 *)adev->gfx.rlc_fw->data;
adev->gfx.rlcp_ucode_version = le32_to_cpu(rlc_hdr->rlcp_ucode_version);
adev->gfx.rlcp_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcp_ucode_feature_version);
adev->gfx.rlc.rlcp_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcp_ucode_size_bytes);
adev->gfx.rlc.rlcp_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcp_ucode_offset_bytes);
adev->gfx.rlcv_ucode_version = le32_to_cpu(rlc_hdr->rlcv_ucode_version);
adev->gfx.rlcv_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcv_ucode_feature_version);
adev->gfx.rlc.rlcv_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcv_ucode_size_bytes);
adev->gfx.rlc.rlcv_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcv_ucode_offset_bytes);
}
static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
{
char fw_name[40];
char ucode_prefix[30];
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr;
const struct gfx_firmware_header_v2_0 *cp_hdr_v2_0;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
unsigned int *tmp = NULL;
unsigned int i = 0;
uint16_t version_major;
uint16_t version_minor;
@ -518,14 +464,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.pfp_fw->data, 2, 0);
if (adev->gfx.rs64_enable) {
dev_info(adev->dev, "CP RS64 enable\n");
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK);
} else {
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
}
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix);
@ -536,14 +479,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
if (err)
goto out;
if (adev->gfx.rs64_enable) {
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK);
} else {
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
}
if (!amdgpu_sriov_vf(adev)) {
@ -552,58 +492,14 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
if (err)
goto out;
err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
adev->gfx.rlc.save_and_restore_offset =
le32_to_cpu(rlc_hdr->save_and_restore_offset);
adev->gfx.rlc.clear_state_descriptor_offset =
le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
adev->gfx.rlc.avail_scratch_ram_locations =
le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
adev->gfx.rlc.reg_restore_list_size =
le32_to_cpu(rlc_hdr->reg_restore_list_size);
adev->gfx.rlc.reg_list_format_start =
le32_to_cpu(rlc_hdr->reg_list_format_start);
adev->gfx.rlc.reg_list_format_separate_start =
le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
adev->gfx.rlc.starting_offsets_start =
le32_to_cpu(rlc_hdr->starting_offsets_start);
adev->gfx.rlc.reg_list_format_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
adev->gfx.rlc.reg_list_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_size_bytes);
adev->gfx.rlc.register_list_format =
kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
if (!adev->gfx.rlc.register_list_format) {
err = -ENOMEM;
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
if (err)
goto out;
}
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
if (version_major == 2) {
if (version_minor >= 1)
gfx_v11_0_init_rlc_ext_microcode(adev);
if (version_minor >= 2)
gfx_v11_0_init_rlc_iram_dram_microcode(adev);
if (version_minor == 3)
gfx_v11_0_init_rlcp_rlcv_microcode(adev);
}
}
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
@ -614,190 +510,23 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
if (err)
goto out;
if (adev->gfx.rs64_enable) {
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr_v2_0->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr_v2_0->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK);
} else {
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
}
/* only one MEC for gfx 11.0.0. */
adev->gfx.mec2_fw = NULL;
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
if (adev->gfx.rs64_enable) {
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.pfp_fw->data;
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_PFP];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_PFP;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.me_fw->data;
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_ME];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_ME;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
cp_hdr_v2_0 = (const struct gfx_firmware_header_v2_0 *)adev->gfx.mec_fw->data;
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_MEC];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_MEC;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK];
info->ucode_id = AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr_v2_0->data_size_bytes), PAGE_SIZE);
} else {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_ME];
info->ucode_id = AMDGPU_UCODE_ID_CP_ME;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes) -
le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1_JT];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1_JT;
info->fw = adev->gfx.mec_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
}
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
info->fw = adev->gfx.rlc_fw;
if (info->fw) {
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
if (adev->gfx.rlc.save_restore_list_gpm_size_bytes &&
adev->gfx.rlc.save_restore_list_srm_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.rlc_iram_ucode_size_bytes &&
adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.rlcp_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_P];
info->ucode_id = AMDGPU_UCODE_ID_RLC_P;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlcp_ucode_size_bytes, PAGE_SIZE);
}
if (adev->gfx.rlc.rlcv_ucode_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_V];
info->ucode_id = AMDGPU_UCODE_ID_RLC_V;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.rlcv_ucode_size_bytes, PAGE_SIZE);
}
}
out:
if (err) {
dev_err(adev->dev,
"gfx11: Failed to load firmware \"%s\"\n",
"gfx11: Failed to init firmware \"%s\"\n",
fw_name);
release_firmware(adev->gfx.pfp_fw);
adev->gfx.pfp_fw = NULL;
@ -5245,6 +4974,8 @@ static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
{
u32 reg, data;
amdgpu_gfx_off_ctrl(adev, false);
reg = SOC15_REG_OFFSET(GC, 0, regRLC_SPM_MC_CNTL);
if (amdgpu_sriov_is_pp_one_vf(adev))
data = RREG32_NO_KIQ(reg);
@ -5258,6 +4989,8 @@ static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
else
WREG32_SOC15(GC, 0, regRLC_SPM_MC_CNTL, data);
amdgpu_gfx_off_ctrl(adev, true);
}
static const struct amdgpu_rlc_funcs gfx_v11_0_rlc_funcs = {

View File

@ -1091,27 +1091,6 @@ static void gfx_v9_0_free_microcode(struct amdgpu_device *adev)
kfree(adev->gfx.rlc.register_list_format);
}
static void gfx_v9_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
{
const struct rlc_firmware_header_v2_1 *rlc_hdr;
rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
adev->gfx.rlc.reg_list_format_direct_reg_list_length =
le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
}
static void gfx_v9_0_check_fw_write_wait(struct amdgpu_device *adev)
{
adev->gfx.me_fw_write_wait = false;
@ -1273,9 +1252,6 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
{
char fw_name[30];
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr;
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
@ -1284,9 +1260,7 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
@ -1295,9 +1269,7 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
err = amdgpu_ucode_validate(adev->gfx.me_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
@ -1306,37 +1278,12 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
err = amdgpu_ucode_validate(adev->gfx.ce_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
info->fw = adev->gfx.pfp_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_ME];
info->ucode_id = AMDGPU_UCODE_ID_CP_ME;
info->fw = adev->gfx.me_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_CE];
info->ucode_id = AMDGPU_UCODE_ID_CP_CE;
info->fw = adev->gfx.ce_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
out:
if (err) {
dev_err(adev->dev,
"gfx9: Failed to load firmware \"%s\"\n",
"gfx9: Failed to init firmware \"%s\"\n",
fw_name);
release_firmware(adev->gfx.pfp_fw);
adev->gfx.pfp_fw = NULL;
@ -1353,11 +1300,7 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
{
char fw_name[30];
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
unsigned int *tmp = NULL;
unsigned int i = 0;
uint16_t version_major;
uint16_t version_minor;
uint32_t smu_version;
@ -1386,92 +1329,17 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
if (err)
goto out;
err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
if (version_major == 2 && version_minor == 1)
adev->gfx.rlc.is_rlc_v2_1 = true;
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
adev->gfx.rlc.save_and_restore_offset =
le32_to_cpu(rlc_hdr->save_and_restore_offset);
adev->gfx.rlc.clear_state_descriptor_offset =
le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
adev->gfx.rlc.avail_scratch_ram_locations =
le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
adev->gfx.rlc.reg_restore_list_size =
le32_to_cpu(rlc_hdr->reg_restore_list_size);
adev->gfx.rlc.reg_list_format_start =
le32_to_cpu(rlc_hdr->reg_list_format_start);
adev->gfx.rlc.reg_list_format_separate_start =
le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
adev->gfx.rlc.starting_offsets_start =
le32_to_cpu(rlc_hdr->starting_offsets_start);
adev->gfx.rlc.reg_list_format_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
adev->gfx.rlc.reg_list_size_bytes =
le32_to_cpu(rlc_hdr->reg_list_size_bytes);
adev->gfx.rlc.register_list_format =
kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
if (!adev->gfx.rlc.register_list_format) {
err = -ENOMEM;
goto out;
}
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
for (i = 0 ; i < (adev->gfx.rlc.reg_list_format_size_bytes >> 2); i++)
adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
tmp = (unsigned int *)((uintptr_t)rlc_hdr +
le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
for (i = 0 ; i < (adev->gfx.rlc.reg_list_size_bytes >> 2); i++)
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
if (adev->gfx.rlc.is_rlc_v2_1)
gfx_v9_0_init_rlc_ext_microcode(adev);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
info->fw = adev->gfx.rlc_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
if (adev->gfx.rlc.is_rlc_v2_1 &&
adev->gfx.rlc.save_restore_list_cntl_size_bytes &&
adev->gfx.rlc.save_restore_list_gpm_size_bytes &&
adev->gfx.rlc.save_restore_list_srm_size_bytes) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_cntl_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
info->fw = adev->gfx.rlc_fw;
adev->firmware.fw_size +=
ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
}
}
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
out:
if (err) {
dev_err(adev->dev,
"gfx9: Failed to load firmware \"%s\"\n",
"gfx9: Failed to init firmware \"%s\"\n",
fw_name);
release_firmware(adev->gfx.rlc_fw);
adev->gfx.rlc_fw = NULL;
@ -1494,9 +1362,6 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
{
char fw_name[30];
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr;
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sjt_mec.bin", chip_name);
@ -1509,10 +1374,8 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
err = amdgpu_ucode_validate(adev->gfx.mec_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
if (gfx_v9_0_load_mec2_fw_bin_support(adev)) {
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
@ -1525,12 +1388,8 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec2_fw->data;
adev->gfx.mec2_fw_version =
le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec2_feature_version =
le32_to_cpu(cp_hdr->ucode_feature_version);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
} else {
err = 0;
adev->gfx.mec2_fw = NULL;
@ -1540,49 +1399,12 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
adev->gfx.mec2_feature_version = adev->gfx.mec_feature_version;
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
info->fw = adev->gfx.mec_fw;
header = (const struct common_firmware_header *)info->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes) - le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1_JT];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1_JT;
info->fw = adev->gfx.mec_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
if (adev->gfx.mec2_fw) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
info->fw = adev->gfx.mec2_fw;
header = (const struct common_firmware_header *)info->fw->data;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes) - le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
/* TODO: Determine if MEC2 JT FW loading can be removed
for all GFX V9 asic and above */
if (gfx_v9_0_load_mec2_fw_bin_support(adev)) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2_JT];
info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2_JT;
info->fw = adev->gfx.mec2_fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4,
PAGE_SIZE);
}
}
}
out:
gfx_v9_0_check_if_need_gfxoff(adev);
gfx_v9_0_check_fw_write_wait(adev);
if (err) {
dev_err(adev->dev,
"gfx9: Failed to load firmware \"%s\"\n",
"gfx9: Failed to init firmware \"%s\"\n",
fw_name);
release_firmware(adev->gfx.mec_fw);
adev->gfx.mec_fw = NULL;
@ -5607,7 +5429,7 @@ static void gfx_v9_0_ring_emit_patch_cond_exec(struct amdgpu_ring *ring, unsigne
BUG_ON(offset > ring->buf_mask);
BUG_ON(ring->ring[offset] != 0x55aa55aa);
cur = (ring->wptr & ring->buf_mask) - 1;
cur = (ring->wptr - 1) & ring->buf_mask;
if (likely(cur > offset))
ring->ring[offset] = cur - offset;
else

View File

@ -185,7 +185,15 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
mes_add_queue_pkt.tma_addr = input->tma_addr;
mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;
mes_add_queue_pkt.trap_en = 1;
if (!(((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 4) &&
(adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0)) &&
(adev->ip_versions[GC_HWIP][0] <= IP_VERSION(11, 0, 3))))
mes_add_queue_pkt.trap_en = 1;
/* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
mes_add_queue_pkt.gds_size = input->queue_size;
return mes_v11_0_submit_pkt_and_poll_completion(mes,
&mes_add_queue_pkt, sizeof(mes_add_queue_pkt),

View File

@ -561,44 +561,6 @@ static void sdma_v4_0_setup_ulv(struct amdgpu_device *adev)
}
}
static int sdma_v4_0_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
int err = 0;
const struct sdma_firmware_header_v1_0 *hdr;
err = amdgpu_ucode_validate(sdma_inst->fw);
if (err)
return err;
hdr = (const struct sdma_firmware_header_v1_0 *)sdma_inst->fw->data;
sdma_inst->fw_version = le32_to_cpu(hdr->header.ucode_version);
sdma_inst->feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (sdma_inst->feature_version >= 20)
sdma_inst->burst_nop = true;
return 0;
}
static void sdma_v4_0_destroy_inst_ctx(struct amdgpu_device *adev)
{
int i;
for (i = 0; i < adev->sdma.num_instances; i++) {
release_firmware(adev->sdma.instance[i].fw);
adev->sdma.instance[i].fw = NULL;
/* arcturus shares the same FW memory across
all SDMA isntances */
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) ||
adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0))
break;
}
memset((void *)adev->sdma.instance, 0,
sizeof(struct amdgpu_sdma_instance) * AMDGPU_MAX_SDMA_INSTANCES);
}
/**
* sdma_v4_0_init_microcode - load ucode images from disk
*
@ -615,9 +577,7 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[30];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
int ret, i;
DRM_DEBUG("\n");
@ -656,58 +616,25 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
BUG();
}
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
err = request_firmware(&adev->sdma.instance[0].fw, fw_name, adev->dev);
if (err)
goto out;
err = sdma_v4_0_init_inst_ctx(&adev->sdma.instance[0]);
if (err)
goto out;
for (i = 1; i < adev->sdma.num_instances; i++) {
for (i = 0; i < adev->sdma.num_instances; i++) {
if (i == 0)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma%d.bin", chip_name, i);
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) ||
adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0)) {
/* Acturus & Aldebaran will leverage the same FW memory
for every SDMA instance */
memcpy((void *)&adev->sdma.instance[i],
(void *)&adev->sdma.instance[0],
sizeof(struct amdgpu_sdma_instance));
}
else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma%d.bin", chip_name, i);
err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
if (err)
goto out;
err = sdma_v4_0_init_inst_ctx(&adev->sdma.instance[i]);
if (err)
goto out;
ret = amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
break;
} else {
ret = amdgpu_sdma_init_microcode(adev, fw_name, i, false);
if (ret)
return ret;
}
}
DRM_DEBUG("psp_load == '%s'\n",
adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
for (i = 0; i < adev->sdma.num_instances; i++) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
info->fw = adev->sdma.instance[i].fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
}
out:
if (err) {
DRM_ERROR("sdma_v4_0: Failed to load firmware \"%s\"\n", fw_name);
sdma_v4_0_destroy_inst_ctx(adev);
}
return err;
return ret;
}
/**
@ -2000,7 +1927,11 @@ static int sdma_v4_0_sw_fini(void *handle)
amdgpu_ring_fini(&adev->sdma.instance[i].page);
}
sdma_v4_0_destroy_inst_ctx(adev);
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 0) ||
adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0))
amdgpu_sdma_destroy_inst_ctx(adev, true);
else
amdgpu_sdma_destroy_inst_ctx(adev, false);
return 0;
}

View File

@ -240,10 +240,7 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[40];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
const struct sdma_firmware_header_v1_0 *hdr;
int ret, i;
if (amdgpu_sriov_vf(adev) && (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(5, 0, 5)))
return 0;
@ -272,38 +269,12 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
if (err)
goto out;
err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
if (err)
goto out;
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (adev->sdma.instance[i].feature_version >= 20)
adev->sdma.instance[i].burst_nop = true;
DRM_DEBUG("psp_load == '%s'\n",
adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
info->fw = adev->sdma.instance[i].fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
ret = amdgpu_sdma_init_microcode(adev, fw_name, i, false);
if (ret)
return ret;
}
out:
if (err) {
DRM_ERROR("sdma_v5_0: Failed to load firmware \"%s\"\n", fw_name);
for (i = 0; i < adev->sdma.num_instances; i++) {
release_firmware(adev->sdma.instance[i].fw);
adev->sdma.instance[i].fw = NULL;
}
}
return err;
return ret;
}
static unsigned sdma_v5_0_ring_init_cond_exec(struct amdgpu_ring *ring)
@ -1465,12 +1436,10 @@ static int sdma_v5_0_sw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i;
for (i = 0; i < adev->sdma.num_instances; i++) {
release_firmware(adev->sdma.instance[i].fw);
adev->sdma.instance[i].fw = NULL;
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
}
amdgpu_sdma_destroy_inst_ctx(adev, false);
return 0;
}

View File

@ -89,33 +89,6 @@ static u32 sdma_v5_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
return base + internal_offset;
}
static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
int err = 0;
const struct sdma_firmware_header_v1_0 *hdr;
err = amdgpu_ucode_validate(sdma_inst->fw);
if (err)
return err;
hdr = (const struct sdma_firmware_header_v1_0 *)sdma_inst->fw->data;
sdma_inst->fw_version = le32_to_cpu(hdr->header.ucode_version);
sdma_inst->feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (sdma_inst->feature_version >= 20)
sdma_inst->burst_nop = true;
return 0;
}
static void sdma_v5_2_destroy_inst_ctx(struct amdgpu_device *adev)
{
release_firmware(adev->sdma.instance[0].fw);
memset((void *)adev->sdma.instance, 0,
sizeof(struct amdgpu_sdma_instance) * AMDGPU_MAX_SDMA_INSTANCES);
}
/**
* sdma_v5_2_init_microcode - load ucode images from disk
*
@ -132,9 +105,6 @@ static int sdma_v5_2_init_microcode(struct amdgpu_device *adev)
{
const char *chip_name;
char fw_name[40];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
DRM_DEBUG("\n");
@ -169,42 +139,7 @@ static int sdma_v5_2_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name);
err = request_firmware(&adev->sdma.instance[0].fw, fw_name, adev->dev);
if (err)
goto out;
err = sdma_v5_2_init_inst_ctx(&adev->sdma.instance[0]);
if (err)
goto out;
for (i = 1; i < adev->sdma.num_instances; i++)
memcpy((void *)&adev->sdma.instance[i],
(void *)&adev->sdma.instance[0],
sizeof(struct amdgpu_sdma_instance));
if (amdgpu_sriov_vf(adev) && (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(5, 2, 0)))
return 0;
DRM_DEBUG("psp_load == '%s'\n",
adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
for (i = 0; i < adev->sdma.num_instances; i++) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
info->fw = adev->sdma.instance[i].fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
}
}
out:
if (err) {
DRM_ERROR("sdma_v5_2: Failed to load firmware \"%s\"\n", fw_name);
sdma_v5_2_destroy_inst_ctx(adev);
}
return err;
return amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
}
static unsigned sdma_v5_2_ring_init_cond_exec(struct amdgpu_ring *ring)
@ -1406,7 +1341,7 @@ static int sdma_v5_2_sw_fini(void *handle)
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
sdma_v5_2_destroy_inst_ctx(adev);
amdgpu_sdma_destroy_inst_ctx(adev, true);
return 0;
}

View File

@ -78,33 +78,6 @@ static u32 sdma_v6_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
return base + internal_offset;
}
static int sdma_v6_0_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
int err = 0;
const struct sdma_firmware_header_v2_0 *hdr;
err = amdgpu_ucode_validate(sdma_inst->fw);
if (err)
return err;
hdr = (const struct sdma_firmware_header_v2_0 *)sdma_inst->fw->data;
sdma_inst->fw_version = le32_to_cpu(hdr->header.ucode_version);
sdma_inst->feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (sdma_inst->feature_version >= 20)
sdma_inst->burst_nop = true;
return 0;
}
static void sdma_v6_0_destroy_inst_ctx(struct amdgpu_device *adev)
{
release_firmware(adev->sdma.instance[0].fw);
memset((void*)adev->sdma.instance, 0,
sizeof(struct amdgpu_sdma_instance) * AMDGPU_MAX_SDMA_INSTANCES);
}
/**
* sdma_v6_0_init_microcode - load ucode images from disk
*
@ -114,16 +87,10 @@ static void sdma_v6_0_destroy_inst_ctx(struct amdgpu_device *adev)
* the driver (not loaded into hw).
* Returns 0 on success, error on failure.
*/
// emulation only, won't work on real chip
// sdma 6.0.0 real chip need to use PSP to load firmware
static int sdma_v6_0_init_microcode(struct amdgpu_device *adev)
{
char fw_name[30];
char ucode_prefix[30];
int err = 0, i;
struct amdgpu_firmware_info *info = NULL;
const struct sdma_firmware_header_v2_0 *sdma_hdr;
DRM_DEBUG("\n");
@ -131,43 +98,7 @@ static int sdma_v6_0_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
err = request_firmware(&adev->sdma.instance[0].fw, fw_name, adev->dev);
if (err)
goto out;
err = sdma_v6_0_init_inst_ctx(&adev->sdma.instance[0]);
if (err)
goto out;
for (i = 1; i < adev->sdma.num_instances; i++) {
memcpy((void*)&adev->sdma.instance[i],
(void*)&adev->sdma.instance[0],
sizeof(struct amdgpu_sdma_instance));
}
DRM_DEBUG("psp_load == '%s'\n",
adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
sdma_hdr = (const struct sdma_firmware_header_v2_0 *)adev->sdma.instance[0].fw->data;
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA_UCODE_TH0];
info->ucode_id = AMDGPU_UCODE_ID_SDMA_UCODE_TH0;
info->fw = adev->sdma.instance[0].fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(sdma_hdr->ctx_ucode_size_bytes), PAGE_SIZE);
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA_UCODE_TH1];
info->ucode_id = AMDGPU_UCODE_ID_SDMA_UCODE_TH1;
info->fw = adev->sdma.instance[0].fw;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(sdma_hdr->ctl_ucode_size_bytes), PAGE_SIZE);
}
out:
if (err) {
DRM_ERROR("sdma_v6_0: Failed to load firmware \"%s\"\n", fw_name);
sdma_v6_0_destroy_inst_ctx(adev);
}
return err;
return amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
}
static unsigned sdma_v6_0_ring_init_cond_exec(struct amdgpu_ring *ring)
@ -1370,7 +1301,7 @@ static int sdma_v6_0_sw_fini(void *handle)
for (i = 0; i < adev->sdma.num_instances; i++)
amdgpu_ring_fini(&adev->sdma.instance[i].ring);
sdma_v6_0_destroy_inst_ctx(adev);
amdgpu_sdma_destroy_inst_ctx(adev, true);
return 0;
}

View File

@ -629,6 +629,7 @@ static int soc21_common_early_init(void *handle)
AMD_CG_SUPPORT_JPEG_MGCG;
adev->pg_flags =
AMD_PG_SUPPORT_GFX_PG |
AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0x1;
break;

View File

@ -452,41 +452,47 @@ static void umc_v6_7_query_ras_error_count(struct amdgpu_device *adev,
static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t umc_reg_offset,
uint32_t ch_inst,
uint32_t umc_inst)
uint32_t umc_reg_offset, uint32_t ch_inst,
uint32_t umc_inst, uint64_t mca_addr)
{
uint32_t mc_umc_status_addr;
uint32_t channel_index;
uint64_t mc_umc_status, mc_umc_addrt0;
uint64_t mc_umc_status = 0, mc_umc_addrt0;
uint64_t err_addr, soc_pa, retired_page, column;
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
if (mca_addr == UMC_INVALID_ADDR) {
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
if (mc_umc_status == 0)
return;
if (mc_umc_status == 0)
return;
if (!err_data->err_addr) {
/* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
return;
if (!err_data->err_addr) {
/* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
return;
}
}
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
/* calculate error address if ue/ce error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) ||
mca_addr != UMC_INVALID_ADDR) {
if (mca_addr == UMC_INVALID_ADDR) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
err_addr =
REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
} else {
err_addr = mca_addr;
}
/* translate umc channel address to soc pa, 3 parts are included */
soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
@ -501,7 +507,8 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1) {
== 1 ||
mca_addr != UMC_INVALID_ADDR) {
/* loop for all possibilities of [C4 C3 C2] */
for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) {
retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT);
@ -519,7 +526,8 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
}
/* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
if (mca_addr == UMC_INVALID_ADDR)
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
}
static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
@ -540,9 +548,8 @@ static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
ch_inst);
umc_v6_7_query_error_address(adev,
err_data,
umc_reg_offset,
ch_inst,
umc_inst);
umc_reg_offset, ch_inst,
umc_inst, UMC_INVALID_ADDR);
}
}
@ -583,4 +590,5 @@ struct amdgpu_umc_ras umc_v6_7_ras = {
.query_ras_poison_mode = umc_v6_7_query_ras_poison_mode,
.ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count,
.ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address,
.convert_ras_error_address = umc_v6_7_query_error_address,
};

View File

@ -150,6 +150,10 @@ static int vcn_v4_0_sw_init(void *handle)
fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
fw_shared->sq.is_enabled = 1;
fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);
fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
if (amdgpu_sriov_vf(adev))
fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);

View File

@ -742,7 +742,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
0xbf88fffe, 0x877aff7f,
0x04000000, 0x8f7a857a,
0x886d7a6d, 0xb97b02dc,
0x8f7b997b, 0xb97a2a05,
0x8f7b997b, 0xb97a3a05,
0x807a817a, 0xbf0d997b,
0xbf850002, 0x8f7a897a,
0xbf820001, 0x8f7a8a7a,
@ -819,7 +819,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
0xbefe037c, 0xbefc0370,
0xf4611c7a, 0xf8000000,
0x80708470, 0xbefc037e,
0xb9702a05, 0x80708170,
0xb9703a05, 0x80708170,
0xbf0d9973, 0xbf850002,
0x8f708970, 0xbf820001,
0x8f708a70, 0xb97a1e06,
@ -1069,7 +1069,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
0xb9f9f816, 0x876f7bff,
0xfffff800, 0x906f8b6f,
0xb9efa2c3, 0xb9f3f801,
0xb96e2a05, 0x806e816e,
0xb96e3a05, 0x806e816e,
0xbf0d9972, 0xbf850002,
0x8f6e896e, 0xbf820001,
0x8f6e8a6e, 0xb96f1e06,
@ -2114,7 +2114,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0x007a0000, 0x7e000280,
0xbefe037a, 0xbeff037b,
0xb97b02dc, 0x8f7b997b,
0xb97a2a05, 0x807a817a,
0xb97a3a05, 0x807a817a,
0xbf0d997b, 0xbf850002,
0x8f7a897a, 0xbf820001,
0x8f7a8a7a, 0xb97b1e06,
@ -2157,7 +2157,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0x01000000, 0xe0704100,
0x705d0100, 0xe0704200,
0x705d0200, 0xe0704300,
0x705d0300, 0xb9702a05,
0x705d0300, 0xb9703a05,
0x80708170, 0xbf0d9973,
0xbf850002, 0x8f708970,
0xbf820001, 0x8f708a70,
@ -2189,7 +2189,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xbefe03ff, 0x0000ffff,
0xbeff0380, 0xe0704000,
0x705d0200, 0xbefe03c1,
0xb9702a05, 0x80708170,
0xb9703a05, 0x80708170,
0xbf0d9973, 0xbf850002,
0x8f708970, 0xbf820001,
0x8f708a70, 0xb97a1e06,
@ -2475,7 +2475,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xb9ef4803, 0x876f7bff,
0xfffff800, 0x906f8b6f,
0xb9efa2c3, 0xb9f3f801,
0xb96e2a05, 0x806e816e,
0xb96e3a05, 0x806e816e,
0xbf0d9972, 0xbf850002,
0x8f6e896e, 0xbf820001,
0x8f6e8a6e, 0xb96f1e06,
@ -2494,438 +2494,441 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
0xbf9f0000, 0xbf9f0000,
0xbf9f0000, 0x00000000,
};
static const uint32_t cwsr_trap_gfx11_hex[] = {
0xbfa00001, 0xbfa0021b,
0xbfa00001, 0xbfa0021e,
0xb0804006, 0xb8f8f802,
0x91788678, 0xb8fbf803,
0x8b6eff78, 0x00002000,
0xbfa10009, 0x8b6eff6d,
0x00ff0000, 0xbfa2001e,
0x8b6eff7b, 0x00000400,
0xbfa20041, 0xbf830010,
0xb8fbf803, 0xbfa0fffa,
0x8b6eff7b, 0x00000900,
0xbfa20015, 0x8b6eff7b,
0x000071ff, 0xbfa10008,
0x8b6fff7b, 0x00007080,
0xbfa10001, 0xbeee1287,
0xb8eff801, 0x846e8c6e,
0x8b6e6f6e, 0xbfa2000a,
0x9178ff78, 0x00020006,
0xb8fbf803, 0xbf0d9f6d,
0xbfa20006, 0x8b6eff78,
0x00002000, 0xbfa10009,
0x8b6eff6d, 0x00ff0000,
0xbfa20007, 0xb8eef801,
0x8b6eff6e, 0x00000800,
0xbfa20003, 0x8b6eff7b,
0x00000400, 0xbfa20026,
0xbefa4d82, 0xbf89fc07,
0x84fa887a, 0xf4005bbd,
0xf8000010, 0xbf89fc07,
0x846e976e, 0x9177ff77,
0x00800000, 0x8c776e77,
0xf4045bbd, 0xf8000000,
0xbf89fc07, 0xf4045ebd,
0xf8000008, 0xbf89fc07,
0x8bee6e6e, 0xbfa10001,
0xbe80486e, 0x8b6eff6d,
0x01ff0000, 0xbfa20005,
0x8c78ff78, 0x00002000,
0x80ec886c, 0x82ed806d,
0xbfa00005, 0x8b6eff6d,
0x01000000, 0xbfa20002,
0x806c846c, 0x826d806d,
0x8b6dff6d, 0x0000ffff,
0x8bfe7e7e, 0x8bea6a6a,
0xb978f802, 0xbe804a6c,
0x8b6dff6d, 0x0000ffff,
0xbefa0080, 0xb97a0283,
0xbeee007e, 0xbeef007f,
0xbefe0180, 0xbefe4d84,
0xbf89fc07, 0x8b7aff7f,
0x04000000, 0x847a857a,
0x8c6d7a6d, 0xbefa007e,
0x8b7bff7f, 0x0000ffff,
0xbefe00c1, 0xbeff00c1,
0xdca6c000, 0x007a0000,
0x7e000280, 0xbefe007a,
0xbeff007b, 0xb8fb02dc,
0x847b997b, 0xb8fa3b05,
0x807a817a, 0xbf0d997b,
0xbfa20002, 0x847a897a,
0xbfa00001, 0x847a8a7a,
0xb8fb1e06, 0x847b8a7b,
0x807a7b7a, 0x8b7bff7f,
0x0000ffff, 0x807aff7a,
0x00000200, 0x807a7e7a,
0x827b807b, 0xd7610000,
0x00010870, 0xd7610000,
0x00010a71, 0xd7610000,
0x00010c72, 0xd7610000,
0x00010e73, 0xd7610000,
0x00011074, 0xd7610000,
0x00011275, 0xd7610000,
0x00011476, 0xd7610000,
0x00011677, 0xd7610000,
0x00011a79, 0xd7610000,
0x00011c7e, 0xd7610000,
0x00011e7f, 0xbefe00ff,
0x00003fff, 0xbeff0080,
0xdca6c040, 0x007a0000,
0xd760007a, 0x00011d00,
0xd760007b, 0x00011f00,
0xbfa2001e, 0x8b6eff7b,
0x00000400, 0xbfa20041,
0xbf830010, 0xb8fbf803,
0xbfa0fffa, 0x8b6eff7b,
0x00000900, 0xbfa20015,
0x8b6eff7b, 0x000071ff,
0xbfa10008, 0x8b6fff7b,
0x00007080, 0xbfa10001,
0xbeee1287, 0xb8eff801,
0x846e8c6e, 0x8b6e6f6e,
0xbfa2000a, 0x8b6eff6d,
0x00ff0000, 0xbfa20007,
0xb8eef801, 0x8b6eff6e,
0x00000800, 0xbfa20003,
0x8b6eff7b, 0x00000400,
0xbfa20026, 0xbefa4d82,
0xbf89fc07, 0x84fa887a,
0xf4005bbd, 0xf8000010,
0xbf89fc07, 0x846e976e,
0x9177ff77, 0x00800000,
0x8c776e77, 0xf4045bbd,
0xf8000000, 0xbf89fc07,
0xf4045ebd, 0xf8000008,
0xbf89fc07, 0x8bee6e6e,
0xbfa10001, 0xbe80486e,
0x8b6eff6d, 0x01ff0000,
0xbfa20005, 0x8c78ff78,
0x00002000, 0x80ec886c,
0x82ed806d, 0xbfa00005,
0x8b6eff6d, 0x01000000,
0xbfa20002, 0x806c846c,
0x826d806d, 0x8b6dff6d,
0x0000ffff, 0x8bfe7e7e,
0x8bea6a6a, 0xb978f802,
0xbe804a6c, 0x8b6dff6d,
0x0000ffff, 0xbefa0080,
0xb97a0283, 0xbeee007e,
0xbeef007f, 0xbefe0180,
0xbefe4d84, 0xbf89fc07,
0x8b7aff7f, 0x04000000,
0x847a857a, 0x8c6d7a6d,
0xbefa007e, 0x8b7bff7f,
0x0000ffff, 0xbefe00c1,
0xbeff00c1, 0xdca6c000,
0x007a0000, 0x7e000280,
0xbefe007a, 0xbeff007b,
0xbef4007e, 0x8b75ff7f,
0x0000ffff, 0x8c75ff75,
0x00040000, 0xbef60080,
0xbef700ff, 0x10807fac,
0xbef1007d, 0xbef00080,
0xb8f302dc, 0x84739973,
0xbefe00c1, 0x857d9973,
0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080,
0xbfa00002, 0xbeff00c1,
0xbfa00009, 0xbef600ff,
0x01000000, 0xe0685080,
0x701d0100, 0xe0685100,
0x701d0200, 0xe0685180,
0x701d0300, 0xbfa00008,
0xb8fb02dc, 0x847b997b,
0xb8fa3b05, 0x807a817a,
0xbf0d997b, 0xbfa20002,
0x847a897a, 0xbfa00001,
0x847a8a7a, 0xb8fb1e06,
0x847b8a7b, 0x807a7b7a,
0x8b7bff7f, 0x0000ffff,
0x807aff7a, 0x00000200,
0x807a7e7a, 0x827b807b,
0xd7610000, 0x00010870,
0xd7610000, 0x00010a71,
0xd7610000, 0x00010c72,
0xd7610000, 0x00010e73,
0xd7610000, 0x00011074,
0xd7610000, 0x00011275,
0xd7610000, 0x00011476,
0xd7610000, 0x00011677,
0xd7610000, 0x00011a79,
0xd7610000, 0x00011c7e,
0xd7610000, 0x00011e7f,
0xbefe00ff, 0x00003fff,
0xbeff0080, 0xdca6c040,
0x007a0000, 0xd760007a,
0x00011d00, 0xd760007b,
0x00011f00, 0xbefe007a,
0xbeff007b, 0xbef4007e,
0x8b75ff7f, 0x0000ffff,
0x8c75ff75, 0x00040000,
0xbef60080, 0xbef700ff,
0x10807fac, 0xbef1007d,
0xbef00080, 0xb8f302dc,
0x84739973, 0xbefe00c1,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00002,
0xbeff00c1, 0xbfa00009,
0xbef600ff, 0x01000000,
0xe0685100, 0x701d0100,
0xe0685200, 0x701d0200,
0xe0685300, 0x701d0300,
0xb8f03b05, 0x80708170,
0xbf0d9973, 0xbfa20002,
0x84708970, 0xbfa00001,
0x84708a70, 0xb8fa1e06,
0x847a8a7a, 0x80707a70,
0x8070ff70, 0x00000200,
0xbef600ff, 0x01000000,
0x7e000280, 0x7e020280,
0x7e040280, 0xbefd0080,
0xd7610002, 0x0000fa71,
0x807d817d, 0xd7610002,
0x0000fa6c, 0x807d817d,
0x917aff6d, 0x80000000,
0xd7610002, 0x0000fa7a,
0x807d817d, 0xd7610002,
0x0000fa6e, 0x807d817d,
0xd7610002, 0x0000fa6f,
0x807d817d, 0xd7610002,
0x0000fa78, 0x807d817d,
0xb8faf803, 0xd7610002,
0x0000fa7a, 0x807d817d,
0xd7610002, 0x0000fa7b,
0x807d817d, 0xb8f1f801,
0xd7610002, 0x0000fa71,
0x807d817d, 0xb8f1f814,
0xd7610002, 0x0000fa71,
0x807d817d, 0xb8f1f815,
0xd7610002, 0x0000fa71,
0x807d817d, 0xbefe00ff,
0x0000ffff, 0xbeff0080,
0xe0685000, 0x701d0200,
0xbefe00c1, 0xb8f03b05,
0xe0685080, 0x701d0100,
0xe0685100, 0x701d0200,
0xe0685180, 0x701d0300,
0xbfa00008, 0xbef600ff,
0x01000000, 0xe0685100,
0x701d0100, 0xe0685200,
0x701d0200, 0xe0685300,
0x701d0300, 0xb8f03b05,
0x80708170, 0xbf0d9973,
0xbfa20002, 0x84708970,
0xbfa00001, 0x84708a70,
0xb8fa1e06, 0x847a8a7a,
0x80707a70, 0xbef600ff,
0x01000000, 0xbef90080,
0xbefd0080, 0xbf800000,
0xbe804100, 0xbe824102,
0xbe844104, 0xbe864106,
0xbe884108, 0xbe8a410a,
0xbe8c410c, 0xbe8e410e,
0xd7610002, 0x0000f200,
0x80798179, 0xd7610002,
0x0000f201, 0x80798179,
0xd7610002, 0x0000f202,
0x80798179, 0xd7610002,
0x0000f203, 0x80798179,
0xd7610002, 0x0000f204,
0x80798179, 0xd7610002,
0x0000f205, 0x80798179,
0xd7610002, 0x0000f206,
0x80798179, 0xd7610002,
0x0000f207, 0x80798179,
0xd7610002, 0x0000f208,
0x80798179, 0xd7610002,
0x0000f209, 0x80798179,
0xd7610002, 0x0000f20a,
0x80798179, 0xd7610002,
0x0000f20b, 0x80798179,
0xd7610002, 0x0000f20c,
0x80798179, 0xd7610002,
0x0000f20d, 0x80798179,
0xd7610002, 0x0000f20e,
0x80798179, 0xd7610002,
0x0000f20f, 0x80798179,
0xbf06a079, 0xbfa10006,
0xe0685000, 0x701d0200,
0x8070ff70, 0x00000080,
0xbef90080, 0x7e040280,
0x807d907d, 0xbf0aff7d,
0x00000060, 0xbfa2ffbc,
0xbe804100, 0xbe824102,
0xbe844104, 0xbe864106,
0xbe884108, 0xbe8a410a,
0xd7610002, 0x0000f200,
0x80798179, 0xd7610002,
0x0000f201, 0x80798179,
0xd7610002, 0x0000f202,
0x80798179, 0xd7610002,
0x0000f203, 0x80798179,
0xd7610002, 0x0000f204,
0x80798179, 0xd7610002,
0x0000f205, 0x80798179,
0xd7610002, 0x0000f206,
0x80798179, 0xd7610002,
0x0000f207, 0x80798179,
0xd7610002, 0x0000f208,
0x80798179, 0xd7610002,
0x0000f209, 0x80798179,
0xd7610002, 0x0000f20a,
0x80798179, 0xd7610002,
0x0000f20b, 0x80798179,
0xe0685000, 0x701d0200,
0xbefe00c1, 0x857d9973,
0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080,
0xbfa00001, 0xbeff00c1,
0xb8fb4306, 0x8b7bc17b,
0xbfa10044, 0xbfbd0000,
0x8b7aff6d, 0x80000000,
0xbfa10040, 0x847b867b,
0x847b827b, 0xbef6007b,
0x80707a70, 0x8070ff70,
0x00000200, 0xbef600ff,
0x01000000, 0x7e000280,
0x7e020280, 0x7e040280,
0xbefd0080, 0xd7610002,
0x0000fa71, 0x807d817d,
0xd7610002, 0x0000fa6c,
0x807d817d, 0x917aff6d,
0x80000000, 0xd7610002,
0x0000fa7a, 0x807d817d,
0xd7610002, 0x0000fa6e,
0x807d817d, 0xd7610002,
0x0000fa6f, 0x807d817d,
0xd7610002, 0x0000fa78,
0x807d817d, 0xb8faf803,
0xd7610002, 0x0000fa7a,
0x807d817d, 0xd7610002,
0x0000fa7b, 0x807d817d,
0xb8f1f801, 0xd7610002,
0x0000fa71, 0x807d817d,
0xb8f1f814, 0xd7610002,
0x0000fa71, 0x807d817d,
0xb8f1f815, 0xd7610002,
0x0000fa71, 0x807d817d,
0xbefe00ff, 0x0000ffff,
0xbeff0080, 0xe0685000,
0x701d0200, 0xbefe00c1,
0xb8f03b05, 0x80708170,
0xbf0d9973, 0xbfa20002,
0x84708970, 0xbfa00001,
0x84708a70, 0xb8fa1e06,
0x847a8a7a, 0x80707a70,
0x8070ff70, 0x00000200,
0x8070ff70, 0x00000080,
0xbef600ff, 0x01000000,
0xd71f0000, 0x000100c1,
0xd7200000, 0x000200c1,
0x16000084, 0x857d9973,
0xbef90080, 0xbefd0080,
0xbf800000, 0xbe804100,
0xbe824102, 0xbe844104,
0xbe864106, 0xbe884108,
0xbe8a410a, 0xbe8c410c,
0xbe8e410e, 0xd7610002,
0x0000f200, 0x80798179,
0xd7610002, 0x0000f201,
0x80798179, 0xd7610002,
0x0000f202, 0x80798179,
0xd7610002, 0x0000f203,
0x80798179, 0xd7610002,
0x0000f204, 0x80798179,
0xd7610002, 0x0000f205,
0x80798179, 0xd7610002,
0x0000f206, 0x80798179,
0xd7610002, 0x0000f207,
0x80798179, 0xd7610002,
0x0000f208, 0x80798179,
0xd7610002, 0x0000f209,
0x80798179, 0xd7610002,
0x0000f20a, 0x80798179,
0xd7610002, 0x0000f20b,
0x80798179, 0xd7610002,
0x0000f20c, 0x80798179,
0xd7610002, 0x0000f20d,
0x80798179, 0xd7610002,
0x0000f20e, 0x80798179,
0xd7610002, 0x0000f20f,
0x80798179, 0xbf06a079,
0xbfa10006, 0xe0685000,
0x701d0200, 0x8070ff70,
0x00000080, 0xbef90080,
0x7e040280, 0x807d907d,
0xbf0aff7d, 0x00000060,
0xbfa2ffbc, 0xbe804100,
0xbe824102, 0xbe844104,
0xbe864106, 0xbe884108,
0xbe8a410a, 0xd7610002,
0x0000f200, 0x80798179,
0xd7610002, 0x0000f201,
0x80798179, 0xd7610002,
0x0000f202, 0x80798179,
0xd7610002, 0x0000f203,
0x80798179, 0xd7610002,
0x0000f204, 0x80798179,
0xd7610002, 0x0000f205,
0x80798179, 0xd7610002,
0x0000f206, 0x80798179,
0xd7610002, 0x0000f207,
0x80798179, 0xd7610002,
0x0000f208, 0x80798179,
0xd7610002, 0x0000f209,
0x80798179, 0xd7610002,
0x0000f20a, 0x80798179,
0xd7610002, 0x0000f20b,
0x80798179, 0xe0685000,
0x701d0200, 0xbefe00c1,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00001,
0xbeff00c1, 0xb8fb4306,
0x8b7bc17b, 0xbfa10044,
0xbfbd0000, 0x8b7aff6d,
0x80000000, 0xbfa10040,
0x847b867b, 0x847b827b,
0xbef6007b, 0xb8f03b05,
0x80708170, 0xbf0d9973,
0xbfa20002, 0x84708970,
0xbfa00001, 0x84708a70,
0xb8fa1e06, 0x847a8a7a,
0x80707a70, 0x8070ff70,
0x00000200, 0x8070ff70,
0x00000080, 0xbef600ff,
0x01000000, 0xd71f0000,
0x000100c1, 0xd7200000,
0x000200c1, 0x16000084,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbefd0080,
0xbfa20012, 0xbe8300ff,
0x00000080, 0xbf800000,
0xbf800000, 0xbf800000,
0xd8d80000, 0x01000000,
0xbf890000, 0xe0685000,
0x701d0100, 0x807d037d,
0x80700370, 0xd5250000,
0x0001ff00, 0x00000080,
0xbf0a7b7d, 0xbfa2fff4,
0xbfa00011, 0xbe8300ff,
0x00000100, 0xbf800000,
0xbf800000, 0xbf800000,
0xd8d80000, 0x01000000,
0xbf890000, 0xe0685000,
0x701d0100, 0x807d037d,
0x80700370, 0xd5250000,
0x0001ff00, 0x00000100,
0xbf0a7b7d, 0xbfa2fff4,
0xbefe00c1, 0x857d9973,
0x8b7d817d, 0xbf06817d,
0xbefd0080, 0xbfa20012,
0xbe8300ff, 0x00000080,
0xbf800000, 0xbf800000,
0xbf800000, 0xd8d80000,
0x01000000, 0xbf890000,
0xe0685000, 0x701d0100,
0x807d037d, 0x80700370,
0xd5250000, 0x0001ff00,
0x00000080, 0xbf0a7b7d,
0xbfa2fff4, 0xbfa00011,
0xbe8300ff, 0x00000100,
0xbf800000, 0xbf800000,
0xbf800000, 0xd8d80000,
0x01000000, 0xbf890000,
0xe0685000, 0x701d0100,
0x807d037d, 0x80700370,
0xd5250000, 0x0001ff00,
0x00000100, 0xbf0a7b7d,
0xbfa2fff4, 0xbefe00c1,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20004,
0xbef000ff, 0x00000200,
0xbeff0080, 0xbfa00003,
0xbef000ff, 0x00000400,
0xbeff00c1, 0xb8fb3b05,
0x807b817b, 0x847b827b,
0x857d9973, 0x8b7d817d,
0xbf06817d, 0xbfa20017,
0xbef600ff, 0x01000000,
0xbefd0084, 0xbf0a7b7d,
0xbfa10037, 0x7e008700,
0x7e028701, 0x7e048702,
0x7e068703, 0xe0685000,
0x701d0000, 0xe0685080,
0x701d0100, 0xe0685100,
0x701d0200, 0xe0685180,
0x701d0300, 0x807d847d,
0x8070ff70, 0x00000200,
0xbf0a7b7d, 0xbfa2ffef,
0xbfa00025, 0xbef600ff,
0xbfa20004, 0xbef000ff,
0x00000200, 0xbeff0080,
0xbfa00003, 0xbef000ff,
0x00000400, 0xbeff00c1,
0xb8fb3b05, 0x807b817b,
0x847b827b, 0x857d9973,
0x8b7d817d, 0xbf06817d,
0xbfa20017, 0xbef600ff,
0x01000000, 0xbefd0084,
0xbf0a7b7d, 0xbfa10011,
0xbf0a7b7d, 0xbfa10037,
0x7e008700, 0x7e028701,
0x7e048702, 0x7e068703,
0xe0685000, 0x701d0000,
0xe0685100, 0x701d0100,
0xe0685200, 0x701d0200,
0xe0685300, 0x701d0300,
0xe0685080, 0x701d0100,
0xe0685100, 0x701d0200,
0xe0685180, 0x701d0300,
0x807d847d, 0x8070ff70,
0x00000400, 0xbf0a7b7d,
0xbfa2ffef, 0xb8fb1e06,
0x8b7bc17b, 0xbfa1000c,
0x847b837b, 0x807b7d7b,
0xbefe00c1, 0xbeff0080,
0x7e008700, 0xe0685000,
0x701d0000, 0x807d817d,
0x8070ff70, 0x00000080,
0xbf0a7b7d, 0xbfa2fff8,
0xbfa00141, 0xbef4007e,
0x8b75ff7f, 0x0000ffff,
0x8c75ff75, 0x00040000,
0xbef60080, 0xbef700ff,
0x10807fac, 0xb8f202dc,
0x84729972, 0x8b6eff7f,
0x04000000, 0xbfa1003a,
0xbefe00c1, 0x857d9972,
0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080,
0xbfa00001, 0xbeff00c1,
0xb8ef4306, 0x8b6fc16f,
0xbfa1002f, 0x846f866f,
0x846f826f, 0xbef6006f,
0xb8f83b05, 0x80788178,
0xbf0d9972, 0xbfa20002,
0x84788978, 0xbfa00001,
0x84788a78, 0xb8ee1e06,
0x846e8a6e, 0x80786e78,
0x8078ff78, 0x00000200,
0x8078ff78, 0x00000080,
0x00000200, 0xbf0a7b7d,
0xbfa2ffef, 0xbfa00025,
0xbef600ff, 0x01000000,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbefd0080,
0xbfa2000c, 0xe0500000,
0x781d0000, 0xbf8903f7,
0xdac00000, 0x00000000,
0x807dff7d, 0x00000080,
0x8078ff78, 0x00000080,
0xbf0a6f7d, 0xbfa2fff5,
0xbfa0000b, 0xe0500000,
0x781d0000, 0xbf8903f7,
0xdac00000, 0x00000000,
0x807dff7d, 0x00000100,
0x8078ff78, 0x00000100,
0xbf0a6f7d, 0xbfa2fff5,
0xbef80080, 0xbefe00c1,
0xbefd0084, 0xbf0a7b7d,
0xbfa10011, 0x7e008700,
0x7e028701, 0x7e048702,
0x7e068703, 0xe0685000,
0x701d0000, 0xe0685100,
0x701d0100, 0xe0685200,
0x701d0200, 0xe0685300,
0x701d0300, 0x807d847d,
0x8070ff70, 0x00000400,
0xbf0a7b7d, 0xbfa2ffef,
0xb8fb1e06, 0x8b7bc17b,
0xbfa1000c, 0x847b837b,
0x807b7d7b, 0xbefe00c1,
0xbeff0080, 0x7e008700,
0xe0685000, 0x701d0000,
0x807d817d, 0x8070ff70,
0x00000080, 0xbf0a7b7d,
0xbfa2fff8, 0xbfa00146,
0xbef4007e, 0x8b75ff7f,
0x0000ffff, 0x8c75ff75,
0x00040000, 0xbef60080,
0xbef700ff, 0x10807fac,
0xb8f202dc, 0x84729972,
0x8b6eff7f, 0x04000000,
0xbfa1003a, 0xbefe00c1,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbfa20002,
0xbeff0080, 0xbfa00001,
0xbeff00c1, 0xb8ef3b05,
0x806f816f, 0x846f826f,
0x857d9972, 0x8b7d817d,
0xbf06817d, 0xbfa20024,
0xbef600ff, 0x01000000,
0xbeee0078, 0x8078ff78,
0x00000200, 0xbefd0084,
0xbf0a6f7d, 0xbfa10050,
0xe0505000, 0x781d0000,
0xe0505080, 0x781d0100,
0xe0505100, 0x781d0200,
0xe0505180, 0x781d0300,
0xbf8903f7, 0x7e008500,
0x7e028501, 0x7e048502,
0x7e068503, 0x807d847d,
0x8078ff78, 0x00000200,
0xbf0a6f7d, 0xbfa2ffee,
0xe0505000, 0x6e1d0000,
0xe0505080, 0x6e1d0100,
0xe0505100, 0x6e1d0200,
0xe0505180, 0x6e1d0300,
0xbf8903f7, 0xbfa00034,
0xbef600ff, 0x01000000,
0xbeee0078, 0x8078ff78,
0x00000400, 0xbefd0084,
0xbf0a6f7d, 0xbfa10012,
0xe0505000, 0x781d0000,
0xe0505100, 0x781d0100,
0xe0505200, 0x781d0200,
0xe0505300, 0x781d0300,
0xbf8903f7, 0x7e008500,
0x7e028501, 0x7e048502,
0x7e068503, 0x807d847d,
0x8078ff78, 0x00000400,
0xbf0a6f7d, 0xbfa2ffee,
0xb8ef1e06, 0x8b6fc16f,
0xbfa1000e, 0x846f836f,
0x806f7d6f, 0xbefe00c1,
0xbeff0080, 0xe0505000,
0x781d0000, 0xbf8903f7,
0x7e008500, 0x807d817d,
0x8078ff78, 0x00000080,
0xbf0a6f7d, 0xbfa2fff7,
0xbeff00c1, 0xe0505000,
0x6e1d0000, 0xe0505100,
0x6e1d0100, 0xe0505200,
0x6e1d0200, 0xe0505300,
0x6e1d0300, 0xbf8903f7,
0xb8f83b05, 0x80788178,
0xbf0d9972, 0xbfa20002,
0x84788978, 0xbfa00001,
0x84788a78, 0xb8ee1e06,
0x846e8a6e, 0x80786e78,
0x8078ff78, 0x00000200,
0x80f8ff78, 0x00000050,
0xbef600ff, 0x01000000,
0xbefd00ff, 0x0000006c,
0x80f89078, 0xf428403a,
0xf0000000, 0xbf89fc07,
0x80fd847d, 0xbf800000,
0xbe804300, 0xbe824302,
0x80f8a078, 0xf42c403a,
0xf0000000, 0xbf89fc07,
0x80fd887d, 0xbf800000,
0xbe804300, 0xbe824302,
0xbe844304, 0xbe864306,
0x80f8c078, 0xf430403a,
0xf0000000, 0xbf89fc07,
0x80fd907d, 0xbf800000,
0xbe804300, 0xbe824302,
0xbe844304, 0xbe864306,
0xbe884308, 0xbe8a430a,
0xbe8c430c, 0xbe8e430e,
0xbf06807d, 0xbfa1fff0,
0xb980f801, 0x00000000,
0xbfbd0000, 0xb8f83b05,
0xbeff00c1, 0xb8ef4306,
0x8b6fc16f, 0xbfa1002f,
0x846f866f, 0x846f826f,
0xbef6006f, 0xb8f83b05,
0x80788178, 0xbf0d9972,
0xbfa20002, 0x84788978,
0xbfa00001, 0x84788a78,
0xb8ee1e06, 0x846e8a6e,
0x80786e78, 0x8078ff78,
0x00000200, 0xbef600ff,
0x01000000, 0xf4205bfa,
0x00000200, 0x8078ff78,
0x00000080, 0xbef600ff,
0x01000000, 0x857d9972,
0x8b7d817d, 0xbf06817d,
0xbefd0080, 0xbfa2000c,
0xe0500000, 0x781d0000,
0xbf8903f7, 0xdac00000,
0x00000000, 0x807dff7d,
0x00000080, 0x8078ff78,
0x00000080, 0xbf0a6f7d,
0xbfa2fff5, 0xbfa0000b,
0xe0500000, 0x781d0000,
0xbf8903f7, 0xdac00000,
0x00000000, 0x807dff7d,
0x00000100, 0x8078ff78,
0x00000100, 0xbf0a6f7d,
0xbfa2fff5, 0xbef80080,
0xbefe00c1, 0x857d9972,
0x8b7d817d, 0xbf06817d,
0xbfa20002, 0xbeff0080,
0xbfa00001, 0xbeff00c1,
0xb8ef3b05, 0x806f816f,
0x846f826f, 0x857d9972,
0x8b7d817d, 0xbf06817d,
0xbfa20024, 0xbef600ff,
0x01000000, 0xbeee0078,
0x8078ff78, 0x00000200,
0xbefd0084, 0xbf0a6f7d,
0xbfa10050, 0xe0505000,
0x781d0000, 0xe0505080,
0x781d0100, 0xe0505100,
0x781d0200, 0xe0505180,
0x781d0300, 0xbf8903f7,
0x7e008500, 0x7e028501,
0x7e048502, 0x7e068503,
0x807d847d, 0x8078ff78,
0x00000200, 0xbf0a6f7d,
0xbfa2ffee, 0xe0505000,
0x6e1d0000, 0xe0505080,
0x6e1d0100, 0xe0505100,
0x6e1d0200, 0xe0505180,
0x6e1d0300, 0xbf8903f7,
0xbfa00034, 0xbef600ff,
0x01000000, 0xbeee0078,
0x8078ff78, 0x00000400,
0xbefd0084, 0xbf0a6f7d,
0xbfa10012, 0xe0505000,
0x781d0000, 0xe0505100,
0x781d0100, 0xe0505200,
0x781d0200, 0xe0505300,
0x781d0300, 0xbf8903f7,
0x7e008500, 0x7e028501,
0x7e048502, 0x7e068503,
0x807d847d, 0x8078ff78,
0x00000400, 0xbf0a6f7d,
0xbfa2ffee, 0xb8ef1e06,
0x8b6fc16f, 0xbfa1000e,
0x846f836f, 0x806f7d6f,
0xbefe00c1, 0xbeff0080,
0xe0505000, 0x781d0000,
0xbf8903f7, 0x7e008500,
0x807d817d, 0x8078ff78,
0x00000080, 0xbf0a6f7d,
0xbfa2fff7, 0xbeff00c1,
0xe0505000, 0x6e1d0000,
0xe0505100, 0x6e1d0100,
0xe0505200, 0x6e1d0200,
0xe0505300, 0x6e1d0300,
0xbf8903f7, 0xb8f83b05,
0x80788178, 0xbf0d9972,
0xbfa20002, 0x84788978,
0xbfa00001, 0x84788a78,
0xb8ee1e06, 0x846e8a6e,
0x80786e78, 0x8078ff78,
0x00000200, 0x80f8ff78,
0x00000050, 0xbef600ff,
0x01000000, 0xbefd00ff,
0x0000006c, 0x80f89078,
0xf428403a, 0xf0000000,
0xbf89fc07, 0x80fd847d,
0xbf800000, 0xbe804300,
0xbe824302, 0x80f8a078,
0xf42c403a, 0xf0000000,
0xbf89fc07, 0x80fd887d,
0xbf800000, 0xbe804300,
0xbe824302, 0xbe844304,
0xbe864306, 0x80f8c078,
0xf430403a, 0xf0000000,
0xbf89fc07, 0x80fd907d,
0xbf800000, 0xbe804300,
0xbe824302, 0xbe844304,
0xbe864306, 0xbe884308,
0xbe8a430a, 0xbe8c430c,
0xbe8e430e, 0xbf06807d,
0xbfa1fff0, 0xb980f801,
0x00000000, 0xbfbd0000,
0xb8f83b05, 0x80788178,
0xbf0d9972, 0xbfa20002,
0x84788978, 0xbfa00001,
0x84788a78, 0xb8ee1e06,
0x846e8a6e, 0x80786e78,
0x8078ff78, 0x00000200,
0xbef600ff, 0x01000000,
0xf4205bfa, 0xf0000000,
0x80788478, 0xf4205b3a,
0xf0000000, 0x80788478,
0xf4205b3a, 0xf0000000,
0x80788478, 0xf4205b7a,
0xf4205b7a, 0xf0000000,
0x80788478, 0xf4205c3a,
0xf0000000, 0x80788478,
0xf4205c3a, 0xf0000000,
0x80788478, 0xf4205c7a,
0xf4205c7a, 0xf0000000,
0x80788478, 0xf4205eba,
0xf0000000, 0x80788478,
0xf4205eba, 0xf0000000,
0x80788478, 0xf4205efa,
0xf4205efa, 0xf0000000,
0x80788478, 0xf4205e7a,
0xf0000000, 0x80788478,
0xf4205e7a, 0xf0000000,
0x80788478, 0xf4205cfa,
0xf4205cfa, 0xf0000000,
0x80788478, 0xf4205bba,
0xf0000000, 0x80788478,
0xbf89fc07, 0xb96ef814,
0xf4205bba, 0xf0000000,
0x80788478, 0xbf89fc07,
0xb96ef814, 0xf4205bba,
0xf0000000, 0x80788478,
0xbf89fc07, 0xb96ef815,
0xbefd006f, 0xbefe0070,
0xbeff0071, 0x8b6f7bff,
0x000003ff, 0xb96f4803,
0x8b6f7bff, 0xfffff800,
0x856f8b6f, 0xb96fa2c3,
0xb973f801, 0xb8ee3b05,
0x806e816e, 0xbf0d9972,
0xbfa20002, 0x846e896e,
0xbfa00001, 0x846e8a6e,
0xb8ef1e06, 0x846f8a6f,
0x806e6f6e, 0x806eff6e,
0x00000200, 0x806e746e,
0x826f8075, 0x8b6fff6f,
0x0000ffff, 0xf4085c37,
0xf8000050, 0xf4085d37,
0xf8000060, 0xf4005e77,
0xf8000074, 0xbf89fc07,
0x8b6dff6d, 0x0000ffff,
0x8bfe7e7e, 0x8bea6a6a,
0xb96ef815, 0xbefd006f,
0xbefe0070, 0xbeff0071,
0x8b6f7bff, 0x000003ff,
0xb96f4803, 0x8b6f7bff,
0xfffff800, 0x856f8b6f,
0xb96fa2c3, 0xb973f801,
0xb8ee3b05, 0x806e816e,
0xbf0d9972, 0xbfa20002,
0x846e896e, 0xbfa00001,
0x846e8a6e, 0xb8ef1e06,
0x846f8a6f, 0x806e6f6e,
0x806eff6e, 0x00000200,
0x806e746e, 0x826f8075,
0x8b6fff6f, 0x0000ffff,
0xf4085c37, 0xf8000050,
0xf4085d37, 0xf8000060,
0xf4005e77, 0xf8000074,
0xbf89fc07, 0x8b6dff6d,
0x0000ffff, 0x8bfe7e7e,
0x8bea6a6a, 0xb8eef802,
0xbf0d866e, 0xbfa20002,
0xb97af802, 0xbe80486c,
0xb97af802, 0xbe804a6c,
0xbfb00000, 0xbf9f0000,
0xbf9f0000, 0xbf9f0000,

View File

@ -43,12 +43,14 @@
#define HAVE_XNACK (ASIC_FAMILY < CHIP_SIENNA_CICHLID)
#define HAVE_SENDMSG_RTN (ASIC_FAMILY >= CHIP_PLUM_BONITO)
#define HAVE_BUFFER_LDS_LOAD (ASIC_FAMILY < CHIP_PLUM_BONITO)
#define SW_SA_TRAP (ASIC_FAMILY >= CHIP_PLUM_BONITO)
var SINGLE_STEP_MISSED_WORKAROUND = 1 //workaround for lost MODE.DEBUG_EN exception when SAVECTX raised
var SQ_WAVE_STATUS_SPI_PRIO_MASK = 0x00000006
var SQ_WAVE_STATUS_HALT_MASK = 0x2000
var SQ_WAVE_STATUS_ECC_ERR_MASK = 0x20000
var SQ_WAVE_STATUS_TRAP_EN_SHIFT = 6
var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT = 12
var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SIZE = 9
@ -183,6 +185,13 @@ L_SKIP_RESTORE:
s_getreg_b32 s_save_trapsts, hwreg(HW_REG_TRAPSTS)
#if SW_SA_TRAP
// If ttmp1[31] is set then trap may occur early.
// Spin wait until SAVECTX exception is raised.
s_bitcmp1_b32 s_save_pc_hi, 31
s_cbranch_scc1 L_CHECK_SAVE
#endif
s_and_b32 ttmp2, s_save_status, SQ_WAVE_STATUS_HALT_MASK
s_cbranch_scc0 L_NOT_HALTED
@ -1061,8 +1070,20 @@ L_RESTORE_HWREG:
s_and_b32 s_restore_pc_hi, s_restore_pc_hi, 0x0000ffff //pc[47:32] //Do it here in order not to affect STATUS
s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32
s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32
s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu
#if SW_SA_TRAP
// If traps are enabled then return to the shader with PRIV=0.
// Otherwise retain PRIV=1 for subsequent context save requests.
s_getreg_b32 s_restore_tmp, hwreg(HW_REG_STATUS)
s_bitcmp1_b32 s_restore_tmp, SQ_WAVE_STATUS_TRAP_EN_SHIFT
s_cbranch_scc1 L_RETURN_WITHOUT_PRIV
s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu
s_setpc_b64 [s_restore_pc_lo, s_restore_pc_hi]
L_RETURN_WITHOUT_PRIV:
#endif
s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu
s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution
L_END_PGM:

View File

@ -1584,6 +1584,8 @@ static int kfd_ioctl_smi_events(struct file *filep,
return kfd_smi_event_open(pdd->dev, &args->anon_fd);
}
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
static int kfd_ioctl_set_xnack_mode(struct file *filep,
struct kfd_process *p, void *data)
{
@ -1594,22 +1596,29 @@ static int kfd_ioctl_set_xnack_mode(struct file *filep,
if (args->xnack_enabled >= 0) {
if (!list_empty(&p->pqm.queues)) {
pr_debug("Process has user queues running\n");
mutex_unlock(&p->mutex);
return -EBUSY;
r = -EBUSY;
goto out_unlock;
}
if (args->xnack_enabled && !kfd_process_xnack_mode(p, true))
if (p->xnack_enabled == args->xnack_enabled)
goto out_unlock;
if (args->xnack_enabled && !kfd_process_xnack_mode(p, true)) {
r = -EPERM;
else
p->xnack_enabled = args->xnack_enabled;
goto out_unlock;
}
r = svm_range_switch_xnack_reserve_mem(p, args->xnack_enabled);
} else {
args->xnack_enabled = p->xnack_enabled;
}
out_unlock:
mutex_unlock(&p->mutex);
return r;
}
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
{
struct kfd_ioctl_svm_args *args = data;
@ -1629,6 +1638,11 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
return r;
}
#else
static int kfd_ioctl_set_xnack_mode(struct file *filep,
struct kfd_process *p, void *data)
{
return -EPERM;
}
static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
{
return -EPERM;

View File

@ -205,6 +205,8 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
}
queue_input.is_kfd_process = 1;
queue_input.is_aql_queue = (q->properties.format == KFD_QUEUE_FORMAT_AQL);
queue_input.queue_size = q->properties.queue_size >> 2;
queue_input.paging = false;
queue_input.tba_addr = qpd->tba_addr;
@ -1240,6 +1242,24 @@ static void init_interrupts(struct device_queue_manager *dqm)
dqm->dev->kfd2kgd->init_interrupts(dqm->dev->adev, i);
}
static void init_sdma_bitmaps(struct device_queue_manager *dqm)
{
unsigned int num_sdma_queues =
min_t(unsigned int, sizeof(dqm->sdma_bitmap)*8,
get_num_sdma_queues(dqm));
unsigned int num_xgmi_sdma_queues =
min_t(unsigned int, sizeof(dqm->xgmi_sdma_bitmap)*8,
get_num_xgmi_sdma_queues(dqm));
if (num_sdma_queues)
dqm->sdma_bitmap = GENMASK_ULL(num_sdma_queues-1, 0);
if (num_xgmi_sdma_queues)
dqm->xgmi_sdma_bitmap = GENMASK_ULL(num_xgmi_sdma_queues-1, 0);
dqm->sdma_bitmap &= ~get_reserved_sdma_queues_bitmap(dqm);
pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap);
}
static int initialize_nocpsch(struct device_queue_manager *dqm)
{
int pipe, queue;
@ -1268,11 +1288,7 @@ static int initialize_nocpsch(struct device_queue_manager *dqm)
memset(dqm->vmid_pasid, 0, sizeof(dqm->vmid_pasid));
dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm));
dqm->sdma_bitmap &= ~(get_reserved_sdma_queues_bitmap(dqm));
pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap);
dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm));
init_sdma_bitmaps(dqm);
return 0;
}
@ -1450,9 +1466,6 @@ static int set_sched_resources(struct device_queue_manager *dqm)
static int initialize_cpsch(struct device_queue_manager *dqm)
{
uint64_t num_sdma_queues;
uint64_t num_xgmi_sdma_queues;
pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm));
mutex_init(&dqm->lock_hidden);
@ -1461,24 +1474,10 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
dqm->active_cp_queue_count = 0;
dqm->gws_queue_count = 0;
dqm->active_runlist = false;
num_sdma_queues = get_num_sdma_queues(dqm);
if (num_sdma_queues >= BITS_PER_TYPE(dqm->sdma_bitmap))
dqm->sdma_bitmap = ULLONG_MAX;
else
dqm->sdma_bitmap = (BIT_ULL(num_sdma_queues) - 1);
dqm->sdma_bitmap &= ~(get_reserved_sdma_queues_bitmap(dqm));
pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap);
num_xgmi_sdma_queues = get_num_xgmi_sdma_queues(dqm);
if (num_xgmi_sdma_queues >= BITS_PER_TYPE(dqm->xgmi_sdma_bitmap))
dqm->xgmi_sdma_bitmap = ULLONG_MAX;
else
dqm->xgmi_sdma_bitmap = (BIT_ULL(num_xgmi_sdma_queues) - 1);
INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception);
init_sdma_bitmaps(dqm);
return 0;
}

View File

@ -350,11 +350,11 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
print_sq_intr_info_inst(context_id0, context_id1);
sq_int_priv = REG_GET_FIELD(context_id0,
SQ_INTERRUPT_WORD_WAVE_CTXID0, PRIV);
if (sq_int_priv /*&& (kfd_set_dbg_ev_from_interrupt(dev, pasid,
/*if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(dev, pasid,
KFD_CTXID0_DOORBELL_ID(context_id0),
KFD_CTXID0_TRAP_CODE(context_id0),
NULL, 0))*/)
return;
NULL, 0)))
return;*/
break;
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
print_sq_intr_info_error(context_id0, context_id1);

View File

@ -126,6 +126,10 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se4 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se5 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se6 = 0xFFFFFFFF;
m->compute_static_thread_mgmt_se7 = 0xFFFFFFFF;
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;

View File

@ -278,7 +278,7 @@ static void svm_range_free(struct svm_range *prange, bool update_mem_usage)
svm_range_free_dma_mappings(prange);
if (update_mem_usage && !p->xnack_enabled) {
pr_debug("unreserve mem limit: %lld\n", size);
pr_debug("unreserve prange 0x%p size: 0x%llx\n", prange, size);
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
}
@ -2956,6 +2956,64 @@ out:
return r;
}
int
svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled)
{
struct svm_range *prange, *pchild;
uint64_t reserved_size = 0;
uint64_t size;
int r = 0;
pr_debug("switching xnack from %d to %d\n", p->xnack_enabled, xnack_enabled);
mutex_lock(&p->svms.lock);
list_for_each_entry(prange, &p->svms.list, list) {
svm_range_lock(prange);
list_for_each_entry(pchild, &prange->child_list, child_list) {
size = (pchild->last - pchild->start + 1) << PAGE_SHIFT;
if (xnack_enabled) {
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
} else {
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
if (r)
goto out_unlock;
reserved_size += size;
}
}
size = (prange->last - prange->start + 1) << PAGE_SHIFT;
if (xnack_enabled) {
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
} else {
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
if (r)
goto out_unlock;
reserved_size += size;
}
out_unlock:
svm_range_unlock(prange);
if (r)
break;
}
if (r)
amdgpu_amdkfd_unreserve_mem_limit(NULL, reserved_size,
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
else
/* Change xnack mode must be inside svms lock, to avoid race with
* svm_range_deferred_list_work unreserve memory in parallel.
*/
p->xnack_enabled = xnack_enabled;
mutex_unlock(&p->svms.lock);
return r;
}
void svm_range_list_fini(struct kfd_process *p)
{
struct svm_range *prange;

View File

@ -203,6 +203,7 @@ void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_s
void svm_range_bo_unref_async(struct svm_range_bo *svm_bo);
void svm_range_set_max_pages(struct amdgpu_device *adev);
int svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled);
#else

View File

@ -170,7 +170,13 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
&stream, 1,
&params);
power_opt |= psr_power_opt_z10_static_screen;
/*
* Only enable static-screen optimizations for PSR1. For PSR SU, this
* causes vstartup interrupt issues, used by amdgpu_dm to send vblank
* events.
*/
if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
power_opt |= psr_power_opt_z10_static_screen;
return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
}

View File

@ -24,6 +24,7 @@
*/
#include "dm_services.h"
#include "core_types.h"
#include "ObjectID.h"
#include "atomfirmware.h"
@ -1374,7 +1375,7 @@ static enum bp_result bios_parser_get_lttpr_interop(
default:
break;
}
DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
return result;
}
@ -1390,6 +1391,7 @@ static enum bp_result bios_parser_get_lttpr_caps(
if (!DATA_TABLES(dce_info))
return BP_RESULT_UNSUPPORTED;
*dce_caps = 0;
header = GET_IMAGE(struct atom_common_table_header,
DATA_TABLES(dce_info));
get_atom_data_table_revision(header, &tbl_revision);
@ -1423,7 +1425,11 @@ static enum bp_result bios_parser_get_lttpr_caps(
default:
break;
}
DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {
*dce_caps = 1;
DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");
}
return result;
}
@ -2994,13 +3000,22 @@ static enum bp_result construct_integrated_info(
info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
info->ext_disp_conn_info.path[i].caps
);
if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
}
}
// Log the Checksum and Voltage Swing
DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
"Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
info->ext_disp_conn_info.checksum,
info->ext_disp_conn_info.fixdpvoltageswing);
if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
}
}
/* Sort voltage table from low to high*/
for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {

View File

@ -137,11 +137,20 @@ static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state
if (pipe->top_pipe || pipe->prev_odm_pipe)
continue;
if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) {
struct stream_encoder *stream_enc = pipe->stream_res.stream_enc;
if (disable) {
if (stream_enc && stream_enc->funcs->disable_fifo)
pipe->stream_res.stream_enc->funcs->disable_fifo(stream_enc);
pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
reset_sync_context_for_pipe(dc, context, i);
} else
} else {
pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
if (stream_enc && stream_enc->funcs->enable_fifo)
pipe->stream_res.stream_enc->funcs->enable_fifo(stream_enc);
}
}
}
}

View File

@ -156,12 +156,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels;
unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels;
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true;
clk_mgr_base->clks.prev_p_state_change_support = true;
clk_mgr_base->clks.fclk_prev_p_state_change_support = true;
clk_mgr->smu_present = false;
clk_mgr->dpm_present = false;
if (!clk_mgr_base->bw_params)
return;
@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
&num_levels);
num_dcfclk_levels = num_levels;
/* SOCCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
&num_levels);
num_dtbclk_levels = num_levels;
/* DISPCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
&num_levels);
num_dispclk_levels = num_levels;
if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
clk_mgr->dpm_present = true;
if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
unsigned int i;
@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
&num_levels);
clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
if (clk_mgr->dpm_present && !num_levels)
clk_mgr->dpm_present = false;
if (!clk_mgr->dpm_present)
dcn32_patch_dpm_table(clk_mgr_base->bw_params);
DC_FP_START();
/* Refresh bounding box */
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(

View File

@ -1201,7 +1201,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
int count = 0;
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->plane_state)
if (!pipe->plane_state || pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
/* Timeout 100 ms */
@ -1750,6 +1750,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
context->stream_count == 0)
dc->hwss.prepare_bandwidth(dc, context);
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, false);
disable_dangling_plane(dc, context);
/* re-program planes for existing stream, in case we need to
* free up plane resource for later use
@ -1840,6 +1843,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc->hwss.optimize_bandwidth(dc, context);
}
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, true);
if (dc->ctx->dce_version >= DCE_VERSION_MAX)
TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk);
else
@ -2003,6 +2009,9 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
dc->hwss.optimize_bandwidth(dc, context);
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, true);
dc->optimized_required = false;
dc->wm_optimized_required = false;
}
@ -2322,9 +2331,13 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
type = get_scaling_info_update_type(u);
elevate_update_type(&overall_type, type);
if (u->flip_addr)
if (u->flip_addr) {
update_flags->bits.addr_update = 1;
if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) {
update_flags->bits.tmz_changed = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FULL);
}
}
if (u->in_transfer_func)
update_flags->bits.in_transfer_func_change = 1;
@ -2759,11 +2772,8 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->abm_level)
stream->abm_level = *update->abm_level;
if (update->periodic_interrupt0)
stream->periodic_interrupt0 = *update->periodic_interrupt0;
if (update->periodic_interrupt1)
stream->periodic_interrupt1 = *update->periodic_interrupt1;
if (update->periodic_interrupt)
stream->periodic_interrupt = *update->periodic_interrupt;
if (update->gamut_remap)
stream->gamut_remap_matrix = *update->gamut_remap;
@ -2983,13 +2993,8 @@ static void commit_planes_do_stream_update(struct dc *dc,
if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) {
if (stream_update->periodic_interrupt0 &&
dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0);
if (stream_update->periodic_interrupt1 &&
dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1);
if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
stream_update->vrr_infopacket ||
@ -3198,6 +3203,9 @@ static void commit_planes_for_stream(struct dc *dc,
if (get_seamless_boot_stream_count(context) == 0)
dc->hwss.prepare_bandwidth(dc, context);
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, false);
context_clock_trace(dc, context);
}
@ -3521,11 +3529,59 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
/* Determines if the incoming context requires a applying transition state with unnecessary
* pipe splitting and ODM disabled, due to hardware limitations. In a case where
* the OPP associated with an MPCC might change due to plane additions, this function
* returns true.
*/
static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_state *stream,
int surface_count,
bool *is_plane_addition)
{
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false;
*is_plane_addition = false;
if (cur_stream_status &&
dc->current_state->stream_count > 0 &&
dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) {
/* determine if minimal transition is required due to MPC*/
if (surface_count > 0) {
if (cur_stream_status->plane_count > surface_count) {
force_minimal_pipe_splitting = true;
} else if (cur_stream_status->plane_count < surface_count) {
force_minimal_pipe_splitting = true;
*is_plane_addition = true;
}
}
}
if (cur_stream_status &&
dc->current_state->stream_count == 1 &&
dc->debug.enable_single_display_2to1_odm_policy) {
/* determine if minimal transition is required due to dynamic ODM*/
if (surface_count > 0) {
if (cur_stream_status->plane_count > 2 && cur_stream_status->plane_count > surface_count) {
force_minimal_pipe_splitting = true;
} else if (surface_count > 2 && cur_stream_status->plane_count < surface_count) {
force_minimal_pipe_splitting = true;
*is_plane_addition = true;
}
}
}
return force_minimal_pipe_splitting;
}
static bool commit_minimal_transition_state(struct dc *dc,
struct dc_state *transition_base_context)
{
struct dc_state *transition_context = dc_create_state(dc);
enum pipe_split_policy tmp_policy;
enum pipe_split_policy tmp_mpc_policy;
bool temp_dynamic_odm_policy;
enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j;
@ -3533,10 +3589,13 @@ static bool commit_minimal_transition_state(struct dc *dc,
return false;
if (!dc->config.is_vmin_only_asic) {
tmp_policy = dc->debug.pipe_split_policy;
tmp_mpc_policy = dc->debug.pipe_split_policy;
dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
}
temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
dc->debug.enable_single_display_2to1_odm_policy = false;
dc_resource_state_copy_construct(transition_base_context, transition_context);
//commit minimal state
@ -3557,20 +3616,22 @@ static bool commit_minimal_transition_state(struct dc *dc,
ret = dc_commit_state_no_check(dc, transition_context);
}
//always release as dc_commit_state_no_check retains in good case
/*always release as dc_commit_state_no_check retains in good case*/
dc_release_state(transition_context);
//restore previous pipe split policy
/*restore previous pipe split and odm policy*/
if (!dc->config.is_vmin_only_asic)
dc->debug.pipe_split_policy = tmp_policy;
dc->debug.pipe_split_policy = tmp_mpc_policy;
dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_policy;
if (ret != DC_OK) {
//this should never happen
/*this should never happen*/
BREAK_TO_DEBUGGER();
return false;
}
//force full surface update
/*force full surface update*/
for (i = 0; i < dc->current_state->stream_count; i++) {
for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF;
@ -3593,24 +3654,14 @@ bool dc_update_planes_and_stream(struct dc *dc,
* cause underflow. Apply stream configuration with minimal pipe
* split first to avoid unsupported transitions for active pipes.
*/
bool force_minimal_pipe_splitting = false;
bool is_plane_addition = false;
bool force_minimal_pipe_splitting;
bool is_plane_addition;
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
if (cur_stream_status &&
dc->current_state->stream_count > 0 &&
dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) {
/* determine if minimal transition is required */
if (surface_count > 0) {
if (cur_stream_status->plane_count > surface_count) {
force_minimal_pipe_splitting = true;
} else if (cur_stream_status->plane_count < surface_count) {
force_minimal_pipe_splitting = true;
is_plane_addition = true;
}
}
}
force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes(
dc,
stream,
surface_count,
&is_plane_addition);
/* on plane addition, minimal state is the current one */
if (force_minimal_pipe_splitting && is_plane_addition &&
@ -3627,7 +3678,7 @@ bool dc_update_planes_and_stream(struct dc *dc,
&context))
return false;
/* on plane addition, minimal state is the new one */
/* on plane removal, minimal state is the new one */
if (force_minimal_pipe_splitting && !is_plane_addition) {
if (!commit_minimal_transition_state(dc, context)) {
dc_release_state(context);
@ -4014,7 +4065,7 @@ struct dc_sink *dc_link_add_remote_sink(
* Treat device as no EDID device if EDID
* parsing fails
*/
if (edid_status != EDID_OK) {
if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) {
dc_sink->dc_edid.length = 0;
dm_error("Bad EDID, status%d!\n", edid_status);
}

View File

@ -35,6 +35,8 @@
#include "dc_link_ddc.h"
#include "dce/dce_aux.h"
#include "dmub/inc/dmub_cmd.h"
#include "link_dpcd.h"
#include "include/dal_asic_id.h"
#define DC_LOGGER_INIT(logger)
@ -683,6 +685,21 @@ bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc,
bool result = false;
struct ddc *ddc_pin = ddc->ddc_pin;
if ((ddc->link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
!ddc->link->dc->debug.disable_fixed_vs_aux_timeout_wa &&
ASICREV_IS_YELLOW_CARP(ddc->ctx->asic_id.hw_internal_rev)) {
/* Fixed VS workaround for AUX timeout */
const uint32_t fixed_vs_address = 0xF004F;
const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc};
core_link_write_dpcd(ddc->link,
fixed_vs_address,
fixed_vs_data,
sizeof(fixed_vs_data));
timeout = 3072;
}
/* Do not try to access nonexistent DDC pin. */
if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY)
return true;
@ -691,6 +708,7 @@ bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc,
ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
result = true;
}
return result;
}

View File

@ -526,9 +526,9 @@ uint8_t dc_dp_initialize_scrambling_data_symbols(
return disable_scrabled_data_symbols;
}
static inline bool is_repeater(struct dc_link *link, uint32_t offset)
static inline bool is_repeater(const struct link_training_settings *lt_settings, uint32_t offset)
{
return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
return (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
}
static void dpcd_set_lt_pattern_and_lane_settings(
@ -545,7 +545,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
bool edp_workaround = false; /* TODO link_prop.INTERNAL */
dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
if (is_repeater(link, offset))
if (is_repeater(lt_settings, offset))
dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
@ -561,7 +561,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
= dpcd_pattern.raw;
if (is_repeater(link, offset)) {
if (is_repeater(lt_settings, offset)) {
DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
__func__,
offset,
@ -584,7 +584,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
lt_settings->dpcd_lane_settings,
size_in_bytes);
if (is_repeater(link, offset)) {
if (is_repeater(lt_settings, offset)) {
if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
@ -873,7 +873,7 @@ enum dc_status dp_get_lane_status_and_lane_adjust(
uint32_t lane;
enum dc_status status;
if (is_repeater(link, offset)) {
if (is_repeater(link_training_setting, offset)) {
lane01_status_address =
DP_LANE0_1_STATUS_PHY_REPEATER1 +
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
@ -906,7 +906,7 @@ enum dc_status dp_get_lane_status_and_lane_adjust(
ln_align->raw = dpcd_buf[2];
if (is_repeater(link, offset)) {
if (is_repeater(link_training_setting, offset)) {
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
" 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
__func__,
@ -954,7 +954,7 @@ enum dc_status dpcd_set_lane_settings(
lane0_set_address = DP_TRAINING_LANE0_SET;
if (is_repeater(link, offset))
if (is_repeater(link_training_setting, offset))
lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
@ -963,7 +963,7 @@ enum dc_status dpcd_set_lane_settings(
(uint8_t *)(link_training_setting->dpcd_lane_settings),
link_training_setting->link_settings.lane_count);
if (is_repeater(link, offset)) {
if (is_repeater(link_training_setting, offset)) {
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
@ -1172,7 +1172,7 @@ static enum link_training_result perform_channel_equalization_sequence(
/* Note: also check that TPS4 is a supported feature*/
tr_pattern = lt_settings->pattern_for_eq;
if (is_repeater(link, offset) && dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
if (is_repeater(lt_settings, offset) && dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
@ -1198,7 +1198,7 @@ static enum link_training_result perform_channel_equalization_sequence(
/* 3. wait for receiver to lock-on*/
wait_time_microsec = lt_settings->eq_pattern_time;
if (is_repeater(link, offset))
if (is_repeater(lt_settings, offset))
wait_time_microsec =
dp_translate_training_aux_read_interval(
link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
@ -1469,7 +1469,6 @@ static inline void decide_8b_10b_training_settings(
*/
lt_settings->link_settings.link_spread = link->dp_ss_off ?
LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
lt_settings->lttpr_mode = link->lttpr_mode;
lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
@ -1478,6 +1477,7 @@ static inline void decide_8b_10b_training_settings(
lt_settings->should_set_fec_ready = true;
lt_settings->disallow_per_lane_settings = true;
lt_settings->always_match_dpcd_with_hw_lane_settings = true;
lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link);
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
}
@ -1501,9 +1501,8 @@ static inline void decide_128b_132b_training_settings(struct dc_link *link,
lt_settings->cds_pattern_time = 2500;
lt_settings->cds_wait_time_limit = (dp_convert_to_count(
link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
lt_settings->disallow_per_lane_settings = true;
lt_settings->lttpr_mode = dp_decide_128b_132b_lttpr_mode(link);
dp_hw_to_dpcd_lane_settings(lt_settings,
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
}
@ -1543,7 +1542,7 @@ static void override_training_settings(
lt_settings->ffe_preset = overrides->ffe_preset;
/* Override HW lane settings with BIOS forced values if present */
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
lt_settings->always_match_dpcd_with_hw_lane_settings = false;
@ -1584,6 +1583,15 @@ static void override_training_settings(
if (link->preferred_training_settings.fec_enable != NULL)
lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Check DP tunnel LTTPR mode debug option. */
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr)
lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR;
#endif
dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
}
uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
@ -1649,7 +1657,7 @@ static enum dc_status configure_lttpr_mode_non_transparent(
link->dpcd_caps.lttpr_caps.mode = repeater_mode;
}
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
@ -2099,7 +2107,7 @@ static enum link_training_result dp_perform_8b_10b_link_training(
/* 1. set link rate, lane count and spread. */
dpcd_set_link_settings(link, lt_settings);
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
/* 2. perform link training (set link training done
* to false is done as well)
@ -2216,7 +2224,7 @@ static enum link_training_result perform_fixed_vs_pe_nontransparent_training_seq
link->vendor_specific_lttpr_link_rate_wa = target_rate;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
/* 2. perform link training (set link training done
* to false is done as well)
@ -2288,7 +2296,7 @@ static enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
ASSERT(dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING);
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
return status;
}
@ -2635,6 +2643,7 @@ enum link_training_result dc_link_dp_perform_link_training(
link,
link_settings,
&lt_settings);
override_training_settings(
link,
&link->preferred_training_settings,
@ -2652,7 +2661,7 @@ enum link_training_result dc_link_dp_perform_link_training(
* Per DP specs starting from here, DPTX device shall not issue
* Non-LT AUX transactions inside training mode.
*/
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && encoding == DP_8b_10b_ENCODING)
status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
else if (encoding == DP_8b_10b_ENCODING)
status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
@ -3086,7 +3095,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
* account for lttpr repeaters cap
* notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
*/
if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) {
if (dp_is_lttpr_present(link)) {
if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
lttpr_max_link_rate = get_lttpr_max_link_rate(link);
@ -3240,7 +3249,7 @@ static bool dp_verify_link_cap(
cur_link_settings = max_link_settings;
/* Grant extended timeout request */
if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
if (dp_is_lttpr_present(link) && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) {
uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
@ -4101,8 +4110,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
&dpcd_lane_adjustment[0].raw,
sizeof(dpcd_lane_adjustment));
/* prepare link training settings */
link_training_settings.link_settings = link->cur_link_settings;
link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings);
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
dp_fixed_vs_pe_read_lane_adjust(
link,
link_training_settings.dpcd_lane_settings);
@ -4209,9 +4223,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
test_pattern_size);
}
/* prepare link training settings */
link_training_settings.link_settings = link->cur_link_settings;
for (lane = 0; lane <
(unsigned int)(link->cur_link_settings.lane_count);
lane++) {
@ -5021,135 +5032,138 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
return true;
}
/* Logic to determine LTTPR mode */
static void determine_lttpr_mode(struct dc_link *link)
{
bool allow_lttpr_non_transparent_mode = 0;
bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
if (link->ctx->dc->debug.lttpr_mode_override != 0) {
link->lttpr_mode = link->ctx->dc->debug.lttpr_mode_override;
return;
}
if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
allow_lttpr_non_transparent_mode = 1;
} else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
allow_lttpr_non_transparent_mode = 1;
}
link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
if (vbios_lttpr_enable && vbios_lttpr_interop)
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
if (allow_lttpr_non_transparent_mode)
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
else
link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
} else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support)
link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
else
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Check DP tunnel LTTPR mode debug option. */
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
link->dc->debug.dpia_debug.bits.force_non_lttpr)
link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
#endif
}
bool dp_retrieve_lttpr_cap(struct dc_link *link)
{
uint8_t lttpr_dpcd_data[8];
enum dc_status status = DC_ERROR_UNEXPECTED;
bool is_lttpr_present = false;
memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
/* Logic to determine LTTPR support*/
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
/* Logic to determine LTTPR mode*/
determine_lttpr_mode(link);
if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support)
return false;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
!link->dc->debug.disable_fixed_vs_aux_timeout_wa) {
/* Fixed VS workaround for AUX timeout */
const uint32_t fixed_vs_address = 0xF004F;
const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc};
/* By reading LTTPR capability, RX assumes that we will enable
* LTTPR extended aux timeout if LTTPR is present.
*/
status = core_link_read_dpcd(link,
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
lttpr_dpcd_data,
sizeof(lttpr_dpcd_data));
core_link_write_dpcd(
link,
fixed_vs_address,
fixed_vs_data,
sizeof(fixed_vs_data));
}
link->dpcd_caps.lttpr_caps.revision.raw =
lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
/* By reading LTTPR capability, RX assumes that we will enable
* LTTPR extended aux timeout if LTTPR is present.
*/
status = core_link_read_dpcd(
link,
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
lttpr_dpcd_data,
sizeof(lttpr_dpcd_data));
link->dpcd_caps.lttpr_caps.max_link_rate =
lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.revision.raw =
lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.max_link_rate =
lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.max_lane_count =
lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.mode =
lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.max_lane_count =
lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.max_ext_timeout =
lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.mode =
lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.max_ext_timeout =
lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
/* If this chip cap is set, at least one retimer must exist in the chain
* Override count to 1 if we receive a known bad count (0 or an invalid value) */
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
(dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
ASSERT(0);
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
}
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
if (is_lttpr_present) {
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
configure_lttpr_mode_transparent(link);
} else
link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
/* If this chip cap is set, at least one retimer must exist in the chain
* Override count to 1 if we receive a known bad count (0 or an invalid value)
*/
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
(dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
ASSERT(0);
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
}
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
is_lttpr_present = dp_is_lttpr_present(link);
if (is_lttpr_present)
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
return is_lttpr_present;
}
bool dp_is_lttpr_present(struct dc_link *link)
{
return (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
}
enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting)
{
enum dp_link_encoding encoding = dp_get_link_encoding_format(link_setting);
if (encoding == DP_8b_10b_ENCODING)
return dp_decide_8b_10b_lttpr_mode(link);
else if (encoding == DP_128b_132b_ENCODING)
return dp_decide_128b_132b_lttpr_mode(link);
ASSERT(0);
return LTTPR_MODE_NON_LTTPR;
}
void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override)
{
if (!dp_is_lttpr_present(link))
return;
if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_TRANSPARENT) {
*override = LTTPR_MODE_TRANSPARENT;
} else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_TRANSPARENT) {
*override = LTTPR_MODE_NON_TRANSPARENT;
} else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) {
*override = LTTPR_MODE_NON_LTTPR;
}
}
enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
{
bool is_lttpr_present = dp_is_lttpr_present(link);
bool vbios_lttpr_force_non_transparent = link->dc->caps.vbios_lttpr_enable;
bool vbios_lttpr_aware = link->dc->caps.vbios_lttpr_aware;
if (!is_lttpr_present)
return LTTPR_MODE_NON_LTTPR;
if (vbios_lttpr_aware) {
if (vbios_lttpr_force_non_transparent)
return LTTPR_MODE_NON_TRANSPARENT;
else
return LTTPR_MODE_TRANSPARENT;
}
if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
link->dc->caps.extended_aux_timeout_support)
return LTTPR_MODE_NON_TRANSPARENT;
return LTTPR_MODE_NON_LTTPR;
}
enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link)
{
return dp_is_lttpr_present(link) ? LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_NON_LTTPR;
}
static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
{
union dmub_rb_cmd cmd;
@ -5209,13 +5223,16 @@ static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout
uint64_t current_ts = 0;
uint64_t time_taken_ms = 0;
enum dc_connection_type type = dc_connection_none;
bool lttpr_present;
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
determine_lttpr_mode(link);
lttpr_present = dp_is_lttpr_present(link) ||
(!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support);
/* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
* be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
*/
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT)
if (lttpr_present)
status = core_link_read_dpcd(
link,
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
@ -5345,6 +5362,10 @@ static bool retrieve_link_cap(struct dc_link *link)
}
is_lttpr_present = dp_retrieve_lttpr_cap(link);
if (is_lttpr_present)
configure_lttpr_mode_transparent(link);
/* Read DP tunneling information. */
status = dpcd_get_tunneling_device_data(link);
@ -6096,7 +6117,7 @@ bool dc_link_dp_set_test_pattern(
/* Set DPCD Lane Settings before running test pattern */
if (p_link_settings != NULL) {
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
dp_fixed_vs_pe_set_retimer_lane_settings(
link,
p_link_settings->dpcd_lane_settings,
@ -7218,7 +7239,7 @@ void dp_set_hw_lane_settings(
{
const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
if ((link_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset))
return;
if (link_hwss->ext.set_dp_lane_settings)

View File

@ -115,12 +115,14 @@ static enum link_training_result dpia_configure_link(
DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) configuring\n - LTTPR mode(%d)\n",
__func__,
link->link_id.enum_id - ENUM_ID_1,
link->lttpr_mode);
lt_settings->lttpr_mode);
dp_decide_training_settings(link,
link_setting,
lt_settings);
dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
status = dpcd_configure_channel_coding(link, lt_settings);
if (status != DC_OK && link->is_hpd_pending)
return LINK_TRAINING_ABORT;
@ -178,7 +180,7 @@ static uint8_t dpia_build_set_config_data(enum dpia_set_config_type type,
switch (type) {
case DPIA_SET_CFG_SET_LINK:
data.set_link.mode = link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT ? 1 : 0;
data.set_link.mode = lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT ? 1 : 0;
break;
case DPIA_SET_CFG_SET_PHY_TEST_MODE:
break;
@ -553,7 +555,7 @@ static enum link_training_result dpia_training_cr_phase(
{
enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
result = dpia_training_cr_non_transparent(link, link_res, lt_settings, hop);
else
result = dpia_training_cr_transparent(link, link_res, lt_settings);
@ -830,7 +832,7 @@ static enum link_training_result dpia_training_eq_phase(
{
enum link_training_result result;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
result = dpia_training_eq_non_transparent(link, link_res, lt_settings, hop);
else
result = dpia_training_eq_transparent(link, link_res, lt_settings);
@ -870,13 +872,14 @@ static enum dc_status dpcd_clear_lt_pattern(struct dc_link *link, uint32_t hop)
* @param hop The Hop in display path. DPRX = 0.
*/
static enum link_training_result dpia_training_end(struct dc_link *link,
struct link_training_settings *lt_settings,
uint32_t hop)
{
enum link_training_result result = LINK_TRAINING_SUCCESS;
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
enum dc_status status;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
if (hop == repeater_cnt) { /* DPTX-to-DPIA */
@ -916,7 +919,7 @@ static enum link_training_result dpia_training_end(struct dc_link *link,
link->link_id.enum_id - ENUM_ID_1,
hop,
result,
link->lttpr_mode);
lt_settings->lttpr_mode);
return result;
}
@ -928,7 +931,9 @@ static enum link_training_result dpia_training_end(struct dc_link *link,
* @param link DPIA link being trained.
* @param hop The Hop in display path. DPRX = 0.
*/
static void dpia_training_abort(struct dc_link *link, uint32_t hop)
static void dpia_training_abort(struct dc_link *link,
struct link_training_settings *lt_settings,
uint32_t hop)
{
uint8_t data = 0;
uint32_t dpcd_tps_offset = DP_TRAINING_PATTERN_SET;
@ -936,7 +941,7 @@ static void dpia_training_abort(struct dc_link *link, uint32_t hop)
DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) aborting\n - LTTPR mode(%d)\n - HPD(%d)\n",
__func__,
link->link_id.enum_id - ENUM_ID_1,
link->lttpr_mode,
lt_settings->lttpr_mode,
link->is_hpd_pending);
/* Abandon clean-up if sink unplugged. */
@ -964,12 +969,16 @@ enum link_training_result dc_link_dpia_perform_link_training(
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
int8_t repeater_id; /* Current hop. */
struct dc_link_settings link_settings = *link_setting; // non-const copy to pass in
lt_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link_settings);
/* Configure link as prescribed in link_setting and set LTTPR mode. */
result = dpia_configure_link(link, link_res, link_setting, &lt_settings);
if (result != LINK_TRAINING_SUCCESS)
return result;
if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
if (lt_settings.lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
/* Train each hop in turn starting with the one closest to DPTX.
@ -987,7 +996,7 @@ enum link_training_result dc_link_dpia_perform_link_training(
break;
/* Stop training hop. */
result = dpia_training_end(link, repeater_id);
result = dpia_training_end(link, &lt_settings, repeater_id);
if (result != LINK_TRAINING_SUCCESS)
break;
}
@ -1001,9 +1010,9 @@ enum link_training_result dc_link_dpia_perform_link_training(
msleep(5);
result = dp_check_link_loss_status(link, &lt_settings);
} else if (result == LINK_TRAINING_ABORT) {
dpia_training_abort(link, repeater_id);
dpia_training_abort(link, &lt_settings, repeater_id);
} else {
dpia_training_end(link, repeater_id);
dpia_training_end(link, &lt_settings, repeater_id);
}
return result;
}

View File

@ -30,6 +30,7 @@
#include "resource.h"
#include "ipp.h"
#include "timing_generator.h"
#include "dc_dmub_srv.h"
#define DC_LOGGER dc->ctx->logger
@ -519,7 +520,7 @@ bool dc_stream_remove_writeback(struct dc *dc,
}
/* remove writeback info for disabled writeback pipes from stream */
for (i = 0, j = 0; i < stream->num_wb_info; i++) {
for (i = 0, j = 0; i < stream->num_wb_info && j < MAX_DWB_PIPES; i++) {
if (stream->writeback_info[i].wb_enabled) {
if (i != j)
/* trim the array */

View File

@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
#define DC_VER "3.2.204"
#define DC_VER "3.2.205"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@ -406,6 +406,9 @@ struct dc_config {
bool ignore_dpref_ss;
bool enable_mipi_converter_optimization;
bool use_default_clock_table;
bool force_bios_enable_lttpr;
uint8_t force_bios_fixed_vs;
};
enum visual_confirm {
@ -832,6 +835,7 @@ struct dc_debug_options {
bool force_subvp_mclk_switch;
bool allow_sw_cursor_fallback;
unsigned int force_subvp_num_ways;
unsigned int force_mall_ss_num_ways;
bool alloc_extra_way_for_cursor;
bool force_usr_allow;
/* uses value at boot and disables switch */
@ -846,6 +850,7 @@ struct dc_debug_options {
bool use_legacy_soc_bb_mechanism;
bool exit_idle_opt_for_cursor_updates;
bool enable_single_display_2to1_odm_policy;
bool enable_double_buffered_dsc_pg_support;
bool enable_dp_dig_pixel_rate_div_policy;
enum lttpr_mode lttpr_mode_override;
};
@ -1117,6 +1122,7 @@ union surface_update_flags {
uint32_t clock_change:1;
uint32_t stereo_format_change:1;
uint32_t lut_3d:1;
uint32_t tmz_changed:1;
uint32_t full_update:1;
} bits;

View File

@ -127,6 +127,12 @@ struct dc_panel_config {
unsigned int extra_t12_ms;
unsigned int extra_post_OUI_ms;
} pps;
// ABM
struct varib {
unsigned int varibright_feature_enable;
unsigned int def_varibright_level;
unsigned int abm_config_setting;
} varib;
// edp DSC
struct dsc {
bool disable_dsc_edp;
@ -151,7 +157,6 @@ struct dc_link {
bool link_state_valid;
bool aux_access_disabled;
bool sync_lt_in_progress;
enum lttpr_mode lttpr_mode;
bool is_internal_display;
/* TODO: Rename. Flag an endpoint as having a programmable mapping to a

View File

@ -212,8 +212,7 @@ struct dc_stream_state {
/* DMCU info */
unsigned int abm_level;
struct periodic_interrupt_config periodic_interrupt0;
struct periodic_interrupt_config periodic_interrupt1;
struct periodic_interrupt_config periodic_interrupt;
/* from core_stream struct */
struct dc_context *ctx;
@ -281,8 +280,7 @@ struct dc_stream_update {
struct dc_info_packet *hdr_static_metadata;
unsigned int *abm_level;
struct periodic_interrupt_config *periodic_interrupt0;
struct periodic_interrupt_config *periodic_interrupt1;
struct periodic_interrupt_config *periodic_interrupt;
struct dc_info_packet *vrr_infopacket;
struct dc_info_packet *vsc_infopacket;

View File

@ -2178,8 +2178,7 @@ static void dce110_setup_audio_dto(
continue;
if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
continue;
if (pipe_ctx->stream_res.audio != NULL &&
pipe_ctx->stream_res.audio->enabled == false) {
if (pipe_ctx->stream_res.audio != NULL) {
struct audio_output audio_output;
build_audio_output(context, pipe_ctx, &audio_output);
@ -2219,8 +2218,7 @@ static void dce110_setup_audio_dto(
if (!dc_is_dp_signal(pipe_ctx->stream->signal))
continue;
if (pipe_ctx->stream_res.audio != NULL &&
pipe_ctx->stream_res.audio->enabled == false) {
if (pipe_ctx->stream_res.audio != NULL) {
struct audio_output audio_output;
build_audio_output(context, pipe_ctx, &audio_output);

View File

@ -3812,7 +3812,7 @@ void dcn10_calc_vupdate_position(
{
const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
int vline_int_offset_from_vupdate =
pipe_ctx->stream->periodic_interrupt0.lines_offset;
pipe_ctx->stream->periodic_interrupt.lines_offset;
int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
int start_position;
@ -3837,18 +3837,10 @@ void dcn10_calc_vupdate_position(
static void dcn10_cal_vline_position(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum vline_select vline,
uint32_t *start_line,
uint32_t *end_line)
{
enum vertical_interrupt_ref_point ref_point = INVALID_POINT;
if (vline == VLINE0)
ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point;
else if (vline == VLINE1)
ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point;
switch (ref_point) {
switch (pipe_ctx->stream->periodic_interrupt.ref_point) {
case START_V_UPDATE:
dcn10_calc_vupdate_position(
dc,
@ -3857,7 +3849,9 @@ static void dcn10_cal_vline_position(
end_line);
break;
case START_V_SYNC:
// Suppose to do nothing because vsync is 0;
// vsync is line 0 so start_line is just the requested line offset
*start_line = pipe_ctx->stream->periodic_interrupt.lines_offset;
*end_line = *start_line + 2;
break;
default:
ASSERT(0);
@ -3867,24 +3861,15 @@ static void dcn10_cal_vline_position(
void dcn10_setup_periodic_interrupt(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum vline_select vline)
struct pipe_ctx *pipe_ctx)
{
struct timing_generator *tg = pipe_ctx->stream_res.tg;
uint32_t start_line = 0;
uint32_t end_line = 0;
if (vline == VLINE0) {
uint32_t start_line = 0;
uint32_t end_line = 0;
dcn10_cal_vline_position(dc, pipe_ctx, &start_line, &end_line);
dcn10_cal_vline_position(dc, pipe_ctx, vline, &start_line, &end_line);
tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
} else if (vline == VLINE1) {
pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1(
tg,
pipe_ctx->stream->periodic_interrupt1.lines_offset);
}
tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
}
void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)

View File

@ -175,8 +175,7 @@ void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx);
void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx);
void dcn10_setup_periodic_interrupt(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum vline_select vline);
struct pipe_ctx *pipe_ctx);
enum dc_status dcn10_set_clock(struct dc *dc,
enum dc_clock_type clock_type,
uint32_t clk_khz,

View File

@ -724,7 +724,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
.disable_psr = false,
.use_max_lb = true
.use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true
};
static const struct dc_debug_options debug_defaults_diags = {

View File

@ -700,6 +700,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true,
.use_max_lb = false,
.exit_idle_opt_for_cursor_updates = true
};
static const struct dc_debug_options debug_defaults_diags = {

View File

@ -93,7 +93,8 @@ static const struct dc_debug_options debug_defaults_drv = {
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
.use_max_lb = true
.use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true
};
static const struct dc_debug_options debug_defaults_diags = {

View File

@ -77,6 +77,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
.exit_idle_opt_for_cursor_updates = true,
.disable_idle_power_optimizations = false,
};

View File

@ -150,9 +150,9 @@ static void dcn31_hpo_dp_stream_enc_dp_blank(
* 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode +
* a little more because we may not trust delay accuracy.
*/
//REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL,
// VID_STREAM_STATUS, 0,
// 10, 5000);
REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL,
VID_STREAM_STATUS, 0,
10, 5000);
/* Disable SDP tranmission */
REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL,

View File

@ -45,6 +45,48 @@
#define DC_LOGGER \
dccg->ctx->logger
static void dccg314_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *k1,
enum pixel_rate_div *k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
*k1 = PIXEL_RATE_DIV_NA;
*k2 = PIXEL_RATE_DIV_NA;
switch (otg_inst) {
case 0:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG0_PIXEL_RATE_DIVK1, &val_k1,
OTG0_PIXEL_RATE_DIVK2, &val_k2);
break;
case 1:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG1_PIXEL_RATE_DIVK1, &val_k1,
OTG1_PIXEL_RATE_DIVK2, &val_k2);
break;
case 2:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG2_PIXEL_RATE_DIVK1, &val_k1,
OTG2_PIXEL_RATE_DIVK2, &val_k2);
break;
case 3:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG3_PIXEL_RATE_DIVK1, &val_k1,
OTG3_PIXEL_RATE_DIVK2, &val_k2);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
*k1 = (enum pixel_rate_div)val_k1;
*k2 = (enum pixel_rate_div)val_k2;
}
static void dccg314_set_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
@ -52,6 +94,11 @@ static void dccg314_set_pixel_rate_div(
enum pixel_rate_div k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2))
return;
switch (otg_inst) {
case 0:

View File

@ -56,7 +56,8 @@ static void enc314_enable_fifo(struct stream_encoder *enc)
/* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */
REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000);
REG_UPDATE_2(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1, DIG_FIFO_READ_START_LEVEL, 0x7);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000);
@ -261,6 +262,16 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
void enc314_stream_encoder_dp_blank(
struct dc_link *link,
struct stream_encoder *enc)
{
/* New to DCN314 - disable the FIFO before VID stream disable. */
enc314_disable_fifo(enc);
enc1_stream_encoder_dp_blank(link, enc);
}
static void enc314_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
@ -316,15 +327,11 @@ static void enc314_stream_encoder_dp_unblank(
/* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
* that it overflows during mode transition, and sometimes doesn't recover.
*/
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
udelay(10);
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
/* DIG Resync FIFO now needs to be explicitly enabled. */
enc314_enable_fifo(enc);
/* wait 100us for DIG/DP logic to prime
* (i.e. a few video lines)
*/
@ -340,6 +347,12 @@ static void enc314_stream_encoder_dp_unblank(
REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
/*
* DIG Resync FIFO now needs to be explicitly enabled.
* This should come after DP_VID_STREAM_ENABLE per HW docs.
*/
enc314_enable_fifo(enc);
dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
}
@ -408,7 +421,7 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = {
.stop_dp_info_packets =
enc1_stream_encoder_stop_dp_info_packets,
.dp_blank =
enc1_stream_encoder_dp_blank,
enc314_stream_encoder_dp_blank,
.dp_unblank =
enc314_stream_encoder_dp_unblank,
.audio_mute_control = enc3_audio_mute_control,

View File

@ -42,6 +42,48 @@
#define DC_LOGGER \
dccg->ctx->logger
static void dccg32_get_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
enum pixel_rate_div *k1,
enum pixel_rate_div *k2)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
*k1 = PIXEL_RATE_DIV_NA;
*k2 = PIXEL_RATE_DIV_NA;
switch (otg_inst) {
case 0:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG0_PIXEL_RATE_DIVK1, &val_k1,
OTG0_PIXEL_RATE_DIVK2, &val_k2);
break;
case 1:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG1_PIXEL_RATE_DIVK1, &val_k1,
OTG1_PIXEL_RATE_DIVK2, &val_k2);
break;
case 2:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG2_PIXEL_RATE_DIVK1, &val_k1,
OTG2_PIXEL_RATE_DIVK2, &val_k2);
break;
case 3:
REG_GET_2(OTG_PIXEL_RATE_DIV,
OTG3_PIXEL_RATE_DIVK1, &val_k1,
OTG3_PIXEL_RATE_DIVK2, &val_k2);
break;
default:
BREAK_TO_DEBUGGER();
return;
}
*k1 = (enum pixel_rate_div)val_k1;
*k2 = (enum pixel_rate_div)val_k2;
}
static void dccg32_set_pixel_rate_div(
struct dccg *dccg,
uint32_t otg_inst,
@ -50,6 +92,17 @@ static void dccg32_set_pixel_rate_div(
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
// Don't program 0xF into the register field. Not valid since
// K1 / K2 field is only 1 / 2 bits wide
if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA)
return;
dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
if (k1 == cur_k1 && k2 == cur_k2)
return;
switch (otg_inst) {
case 0:
REG_UPDATE_2(OTG_PIXEL_RATE_DIV,

View File

@ -98,9 +98,13 @@ void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int d
default:
break;
}
/* Should never be hit, if it is we have an erroneous hw config*/
ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+ hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);
if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+ hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) {
/* This may happen during seamless transition from ODM 2:1 to ODM4:1 */
DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) > CRB segments (%d)\n",
hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size,
hubbub2->compbuf_size_segments, hubbub2->crb_size_segs);
}
}
static void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)

View File

@ -49,6 +49,7 @@
#include "dcn20/dcn20_optc.h"
#include "dmub_subvp_state.h"
#include "dce/dmub_hw_lock_mgr.h"
#include "dcn32_resource.h"
#include "dc_link_dp.h"
#include "dmub/inc/dmub_subvp_state.h"
@ -198,42 +199,6 @@ static bool dcn32_check_no_memory_request_for_cab(struct dc *dc)
return false;
}
/* This function takes in the start address and surface size to be cached in CAB
* and calculates the total number of cache lines required to store the surface.
* The number of cache lines used for each surface is calculated independently of
* one another. For example, if there is a primary surface(1), meta surface(2), and
* cursor(3), this function should be called 3 times to calculate the number of cache
* lines used for each of those surfaces.
*/
static uint32_t dcn32_cache_lines_for_surface(struct dc *dc, uint32_t surface_size, uint64_t start_address)
{
uint32_t lines_used = 1;
uint32_t num_cached_bytes = 0;
uint32_t remaining_size = 0;
uint32_t cache_line_size = dc->caps.cache_line_size;
uint32_t remainder = 0;
/* 1. Calculate surface size minus the number of bytes stored
* in the first cache line (all bytes in first cache line might
* not be fully used).
*/
div_u64_rem(start_address, cache_line_size, &remainder);
num_cached_bytes = cache_line_size - remainder;
remaining_size = surface_size - num_cached_bytes;
/* 2. Calculate number of cache lines that will be fully used with
* the remaining number of bytes to be stored.
*/
lines_used += (remaining_size / cache_line_size);
/* 3. Check if we need an extra line due to the remaining size not being
* a multiple of CACHE_LINE_SIZE.
*/
if (remaining_size % cache_line_size > 0)
lines_used++;
return lines_used;
}
/* This function loops through every surface that needs to be cached in CAB for SS,
* and calculates the total number of ways required to store all surfaces (primary,
@ -241,96 +206,116 @@ static uint32_t dcn32_cache_lines_for_surface(struct dc *dc, uint32_t surface_si
*/
static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx)
{
uint8_t i, j;
uint8_t i;
int j;
struct dc_stream_state *stream = NULL;
struct dc_plane_state *plane = NULL;
uint32_t surface_size = 0;
uint32_t cursor_size = 0;
uint32_t cache_lines_used = 0;
uint32_t total_lines = 0;
uint32_t lines_per_way = 0;
uint32_t num_ways = 0;
uint32_t prev_addr_low = 0;
uint8_t num_ways = 0;
uint8_t bytes_per_pixel = 0;
uint8_t cursor_bpp = 0;
uint16_t mblk_width = 0;
uint16_t mblk_height = 0;
uint16_t mall_alloc_width_blk_aligned = 0;
uint16_t mall_alloc_height_blk_aligned = 0;
uint16_t num_mblks = 0;
uint32_t bytes_in_mall = 0;
uint32_t cache_lines_used = 0;
uint32_t cache_lines_per_plane = 0;
for (i = 0; i < ctx->stream_count; i++) {
stream = ctx->streams[i];
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
// Don't include PSR surface in the total surface size for CAB allocation
if (stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED)
if (!pipe->stream || !pipe->plane_state ||
pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED ||
pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
if (ctx->stream_status[i].plane_count == 0)
continue;
bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4;
mblk_width = DCN3_2_MBLK_WIDTH;
mblk_height = bytes_per_pixel == 4 ? DCN3_2_MBLK_HEIGHT_4BPE : DCN3_2_MBLK_HEIGHT_8BPE;
// For each stream, loop through each plane to calculate the number of cache
// lines required to store the surface in CAB
for (j = 0; j < ctx->stream_status[i].plane_count; j++) {
plane = ctx->stream_status[i].plane_states[j];
/* full_vp_width_blk_aligned = FLOOR(vp_x_start + full_vp_width + blk_width - 1, blk_width) -
* FLOOR(vp_x_start, blk_width)
*
* mall_alloc_width_blk_aligned_l/c = full_vp_width_blk_aligned_l/c
*/
mall_alloc_width_blk_aligned = ((pipe->plane_res.scl_data.viewport.x +
pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) -
(pipe->plane_res.scl_data.viewport.x / mblk_width * mblk_width);
// Calculate total surface size
if (prev_addr_low != plane->address.grph.addr.u.low_part) {
/* if plane address are different from prev FB, then userspace allocated separate FBs*/
surface_size += plane->plane_size.surface_pitch *
plane->plane_size.surface_size.height *
(plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
/* full_vp_height_blk_aligned = FLOOR(vp_y_start + full_vp_height + blk_height - 1, blk_height) -
* FLOOR(vp_y_start, blk_height)
*
* mall_alloc_height_blk_aligned_l/c = full_vp_height_blk_aligned_l/c
*/
mall_alloc_height_blk_aligned = ((pipe->plane_res.scl_data.viewport.y +
pipe->plane_res.scl_data.viewport.height + mblk_height - 1) / mblk_height * mblk_height) -
(pipe->plane_res.scl_data.viewport.y / mblk_height * mblk_height);
prev_addr_low = plane->address.grph.addr.u.low_part;
} else {
/* We have the same fb for all the planes.
* Xorg always creates one giant fb that holds all surfaces,
* so allocating it once is sufficient.
* */
continue;
}
// Convert surface size + starting address to number of cache lines required
// (alignment accounted for)
cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size,
plane->address.grph.addr.quad_part);
num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) *
((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height);
if (plane->address.grph.meta_addr.quad_part) {
// Meta surface
cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size,
plane->address.grph.meta_addr.quad_part);
}
}
/* For DCC:
* meta_num_mblk = CEILING(full_mblk_width_ub_l*full_mblk_height_ub_l*Bpe/256/mblk_bytes, 1)
*/
if (pipe->plane_state->dcc.enable)
num_mblks += (mall_alloc_width_blk_aligned * mall_alloc_width_blk_aligned * bytes_per_pixel +
(256 * DCN3_2_MALL_MBLK_SIZE_BYTES) - 1) / (256 * DCN3_2_MALL_MBLK_SIZE_BYTES);
// Include cursor size for CAB allocation
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[j];
struct hubp *hubp = pipe->plane_res.hubp;
bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
if (pipe->stream && pipe->plane_state && hubp)
/* Find the cursor plane and use the exact size instead of
* using the max for calculation
*/
if (hubp->curs_attr.width > 0) {
// Round cursor width to next multiple of 64
cursor_size = (((hubp->curs_attr.width + 63) / 64) * 64) * hubp->curs_attr.height;
/* (cache lines used is total bytes / cache_line size. Add +2 for worst case alignment
* (MALL is 64-byte aligned)
*/
cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2;
cache_lines_used += cache_lines_per_plane;
}
// Include cursor size for CAB allocation
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[j];
struct hubp *hubp = pipe->plane_res.hubp;
if (pipe->stream && pipe->plane_state && hubp)
/* Find the cursor plane and use the exact size instead of
using the max for calculation */
if (hubp->curs_attr.width > 0) {
// Round cursor width to next multiple of 64
cursor_size = (((hubp->curs_attr.width + 63) / 64) * 64) * hubp->curs_attr.height;
switch (pipe->stream->cursor_attributes.color_format) {
case CURSOR_MODE_MONO:
cursor_size /= 2;
cursor_bpp = 4;
break;
case CURSOR_MODE_COLOR_1BIT_AND:
case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
cursor_size *= 4;
cursor_bpp = 4;
break;
case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
cursor_size *= 8;
cursor_bpp = 8;
break;
}
}
switch (stream->cursor_attributes.color_format) {
case CURSOR_MODE_MONO:
cursor_size /= 2;
break;
case CURSOR_MODE_COLOR_1BIT_AND:
case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
cursor_size *= 4;
break;
case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
cursor_size *= 8;
break;
}
if (stream->cursor_position.enable && !dc->debug.alloc_extra_way_for_cursor &&
cursor_size > 16384) {
cache_lines_used += dcn32_cache_lines_for_surface(dc, cursor_size,
plane->address.grph.cursor_cache_addr.quad_part);
}
if (pipe->stream->cursor_position.enable && !dc->debug.alloc_extra_way_for_cursor &&
cursor_size > 16384) {
/* cursor_num_mblk = CEILING(num_cursors*cursor_width*cursor_width*cursor_Bpe/mblk_bytes, 1)
*/
cache_lines_used += (((hubp->curs_attr.width * hubp->curs_attr.height * cursor_bpp +
DCN3_2_MALL_MBLK_SIZE_BYTES - 1) / DCN3_2_MALL_MBLK_SIZE_BYTES) *
DCN3_2_MALL_MBLK_SIZE_BYTES) / dc->caps.cache_line_size + 2;
}
break;
}
}
// Convert number of cache lines required to number of ways
@ -360,7 +345,9 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
}
}
}
if (dc->debug.force_mall_ss_num_ways > 0) {
num_ways = dc->debug.force_mall_ss_num_ways;
}
return num_ways;
}
@ -369,7 +356,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
union dmub_rb_cmd cmd;
uint8_t ways, i;
int j;
bool stereo_in_use = false;
bool mall_ss_unsupported = false;
struct dc_plane_state *plane = NULL;
if (!dc->ctx->dmub_srv)
@ -400,22 +387,23 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
*/
ways = dcn32_calculate_cab_allocation(dc, dc->current_state);
/* MALL not supported with Stereo3D. If any plane is using stereo,
* don't try to enter MALL.
/* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo,
* or TMZ surface, don't try to enter MALL.
*/
for (i = 0; i < dc->current_state->stream_count; i++) {
for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
plane = dc->current_state->stream_status[i].plane_states[j];
if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO) {
stereo_in_use = true;
if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO ||
plane->address.tmz_surface) {
mall_ss_unsupported = true;
break;
}
}
if (stereo_in_use)
if (mall_ss_unsupported)
break;
}
if (ways <= dc->caps.cache_num_ways && !stereo_in_use) {
if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) {
memset(&cmd, 0, sizeof(cmd));
cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB;
@ -773,7 +761,8 @@ void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context)
hubp->funcs->hubp_update_mall_sel(hubp,
num_ways <= dc->caps.cache_num_ways &&
pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO ? 2 : 0,
pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO &&
!pipe->plane_state->address.tmz_surface ? 2 : 0,
cache_cursor);
}
}
@ -1303,7 +1292,7 @@ static void apply_symclk_on_tx_off_wa(struct dc_link *link)
if (link->phy_state.symclk_ref_cnts.otg > 0) {
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
pipe_ctx->clock_source->funcs->program_pix_clk(
pipe_ctx->clock_source,
&pipe_ctx->stream_res.pix_clk_params,
@ -1375,3 +1364,58 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
}
}
}
bool dcn32_dsc_pg_status(
struct dce_hwseq *hws,
unsigned int dsc_inst)
{
uint32_t pwr_status = 0;
switch (dsc_inst) {
case 0: /* DSC0 */
REG_GET(DOMAIN16_PG_STATUS,
DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
break;
case 1: /* DSC1 */
REG_GET(DOMAIN17_PG_STATUS,
DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
break;
case 2: /* DSC2 */
REG_GET(DOMAIN18_PG_STATUS,
DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
break;
case 3: /* DSC3 */
REG_GET(DOMAIN19_PG_STATUS,
DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
break;
default:
BREAK_TO_DEBUGGER();
break;
}
return pwr_status == 0 ? true : false;
}
void dcn32_update_dsc_pg(struct dc *dc,
struct dc_state *context,
bool safe_to_disable)
{
struct dce_hwseq *hws = dc->hwseq;
int i;
for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
struct display_stream_compressor *dsc = dc->res_pool->dscs[i];
bool is_dsc_ungated = hws->funcs.dsc_pg_status(hws, dsc->inst);
if (context->res_ctx.is_dsc_acquired[i]) {
if (!is_dsc_ungated) {
hws->funcs.dsc_pg_control(hws, dsc->inst, true);
}
} else if (safe_to_disable) {
if (is_dsc_ungated) {
hws->funcs.dsc_pg_control(hws, dsc->inst, false);
}
}
}
}

View File

@ -92,4 +92,12 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
struct dc_state *context,
struct pipe_ctx *phantom_pipe);
bool dcn32_dsc_pg_status(
struct dce_hwseq *hws,
unsigned int dsc_inst);
void dcn32_update_dsc_pg(struct dc *dc,
struct dc_state *context,
bool safe_to_disable);
#endif /* __DC_HWSS_DCN32_H__ */

View File

@ -109,6 +109,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
.update_visual_confirm_color = dcn20_update_visual_confirm_color,
.update_phantom_vp_position = dcn32_update_phantom_vp_position,
.update_dsc_pg = dcn32_update_dsc_pg,
};
static const struct hwseq_private_funcs dcn32_private_funcs = {
@ -138,6 +139,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
.program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
.update_odm = dcn32_update_odm,
.dsc_pg_control = dcn32_dsc_pg_control,
.dsc_pg_status = dcn32_dsc_pg_status,
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,

View File

@ -718,6 +718,9 @@ static const struct dc_debug_options debug_defaults_drv = {
.force_disable_subvp = false,
.exit_idle_opt_for_cursor_updates = true,
.enable_single_display_2to1_odm_policy = true,
/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
.enable_double_buffered_dsc_pg_support = true,
.enable_dp_dig_pixel_rate_div_policy = 1,
.allow_sw_cursor_fallback = false,
.alloc_extra_way_for_cursor = true,
@ -1846,7 +1849,7 @@ int dcn32_populate_dml_pipes_from_context(
struct resource_context *res_ctx = &context->res_ctx;
struct pipe_ctx *pipe;
bool subvp_in_use = false;
int plane_count = 0;
uint8_t is_pipe_split_expected[MAX_PIPES] = {0};
struct dc_crtc_timing *timing;
dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
@ -1865,12 +1868,13 @@ int dcn32_populate_dml_pipes_from_context(
timing = &pipe->stream->timing;
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
if (context->stream_count == 1 && !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream)) {
if (dc->debug.enable_single_display_2to1_odm_policy) {
if (!((plane_count > 2) && pipe->top_pipe))
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
}
if (context->stream_count == 1 &&
context->stream_status[0].plane_count <= 1 &&
!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
dc->debug.enable_single_display_2to1_odm_policy) {
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
}
pipe_cnt++;
}
@ -1927,12 +1931,10 @@ int dcn32_populate_dml_pipes_from_context(
}
}
/* Calculate the number of planes we have so we can determine
* whether to apply ODM 2to1 policy or not
*/
if (pipe->stream && !pipe->prev_odm_pipe &&
(!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state))
++plane_count;
DC_FP_START();
is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, &pipes[pipe_cnt]);
DC_FP_END();
pipe_cnt++;
}

View File

@ -37,6 +37,7 @@
#define DCN3_2_MBLK_WIDTH 128
#define DCN3_2_MBLK_HEIGHT_4BPE 128
#define DCN3_2_MBLK_HEIGHT_8BPE 64
#define DCN3_2_VMIN_DISPCLK_HZ 717000000
#define TO_DCN32_RES_POOL(pool)\
container_of(pool, struct dcn32_resource_pool, base)

View File

@ -278,7 +278,7 @@ void dcn32_determine_det_override(struct dc *dc,
}
}
if (context->stream_count > 0) {
if (stream_count > 0) {
stream_segments = 18 / stream_count;
for (i = 0; i < context->stream_count; i++) {
if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM)

View File

@ -718,6 +718,9 @@ static const struct dc_debug_options debug_defaults_drv = {
.force_disable_subvp = false,
.exit_idle_opt_for_cursor_updates = true,
.enable_single_display_2to1_odm_policy = true,
/*must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
.enable_double_buffered_dsc_pg_support = true,
.enable_dp_dig_pixel_rate_div_policy = 1,
.allow_sw_cursor_fallback = false,
.alloc_extra_way_for_cursor = true,

View File

@ -121,8 +121,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc = {
},
},
.num_states = 1,
.sr_exit_time_us = 20.16,
.sr_enter_plus_exit_time_us = 27.13,
.sr_exit_time_us = 42.97,
.sr_enter_plus_exit_time_us = 49.94,
.sr_exit_z8_time_us = 285.0,
.sr_enter_plus_exit_z8_time_us = 320,
.writeback_latency_us = 12.0,
@ -674,9 +674,10 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
* - Not able to switch in vactive naturally (switching in active means the
* DET provides enough buffer to hide the P-State switch latency -- trying
* to combine this with SubVP can cause issues with the scheduling).
* - Not TMZ surface
*/
if (pipe->plane_state && !pipe->top_pipe &&
pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 &&
pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface &&
vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) {
while (pipe) {
num_pipes++;
@ -1119,7 +1120,9 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
dc->debug.force_subvp_mclk_switch)) {
dcn32_merge_pipes_for_subvp(dc, context);
// to re-initialize viewport after the pipe merge
memset(merge, 0, MAX_PIPES * sizeof(bool));
/* to re-initialize viewport after the pipe merge */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
@ -1588,6 +1591,28 @@ bool dcn32_internal_validate_bw(struct dc *dc,
if (pipe->next_odm_pipe)
pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
/*2:1ODM+MPC Split MPO to Single Pipe + MPC Split MPO*/
if (pipe->bottom_pipe) {
if (pipe->bottom_pipe->prev_odm_pipe || pipe->bottom_pipe->next_odm_pipe) {
/*MPC split rules will handle this case*/
pipe->bottom_pipe->top_pipe = NULL;
} else {
if (pipe->prev_odm_pipe->bottom_pipe) {
/* 3 plane MPO*/
pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe;
pipe->prev_odm_pipe->bottom_pipe->bottom_pipe = pipe->bottom_pipe;
} else {
/* 2 plane MPO*/
pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe;
pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_pipe;
}
}
}
if (pipe->top_pipe) {
pipe->top_pipe->bottom_pipe = NULL;
}
pipe->bottom_pipe = NULL;
pipe->next_odm_pipe = NULL;
pipe->plane_state = NULL;
@ -2019,6 +2044,45 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st
memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st));
}
void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
{
int i;
unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
}
/* Scan through clock values we currently have and if they are 0,
* then populate it with dcn3_2_soc.clock_limits[] value.
*
* Do it for DCFCLK, DISPCLK, DTBCLK and UCLK as any of those being
* 0, will cause it to skip building the clock table.
*/
if (max_dcfclk_mhz == 0)
bw_params->clk_table.entries[0].dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
if (max_dispclk_mhz == 0)
bw_params->clk_table.entries[0].dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz;
if (max_dtbclk_mhz == 0)
bw_params->clk_table.entries[0].dtbclk_mhz = dcn3_2_soc.clock_limits[0].dtbclk_mhz;
if (max_uclk_mhz == 0)
bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
}
static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
{

View File

@ -71,4 +71,6 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
int pipe_cnt,
int vlevel);
void dcn32_patch_dpm_table(struct clk_bw_params *bw_params);
#endif

View File

@ -194,6 +194,11 @@ enum dc_status dpcd_configure_lttpr_mode(
enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings);
bool dp_retrieve_lttpr_cap(struct dc_link *link);
bool dp_is_lttpr_present(struct dc_link *link);
enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting);
void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override);
enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link);
enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link);
bool dpcd_write_128b_132b_sst_payload_allocation_table(
const struct dc_stream_state *stream,
struct dc_link *link,

View File

@ -340,6 +340,8 @@ struct clk_mgr_internal {
bool smu_present;
void *wm_range_table;
long long wm_range_table_addr;
bool dpm_present;
};
struct clk_mgr_internal_funcs {

View File

@ -32,11 +32,6 @@
#include "inc/hw/link_encoder.h"
#include "core_status.h"
enum vline_select {
VLINE0,
VLINE1
};
struct pipe_ctx;
struct dc_state;
struct dc_stream_status;
@ -89,6 +84,7 @@ struct hw_sequencer_funcs {
struct pipe_ctx *pipe_ctx, bool enableTripleBuffer);
void (*update_pending_status)(struct pipe_ctx *pipe_ctx);
void (*power_down)(struct dc *dc);
void (*update_dsc_pg)(struct dc *dc, struct dc_state *context, bool safe_to_disable);
/* Pipe Lock Related */
void (*pipe_control_lock)(struct dc *dc,
@ -117,8 +113,7 @@ struct hw_sequencer_funcs {
int group_index, int group_size,
struct pipe_ctx *grouped_pipes[]);
void (*setup_periodic_interrupt)(struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum vline_select vline);
struct pipe_ctx *pipe_ctx);
void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes,
struct dc_crtc_timing_adjust adjust);
void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,

View File

@ -124,6 +124,8 @@ struct hwseq_private_funcs {
void (*dsc_pg_control)(struct dce_hwseq *hws,
unsigned int dsc_inst,
bool power_on);
bool (*dsc_pg_status)(struct dce_hwseq *hws,
unsigned int dsc_inst);
void (*update_odm)(struct dc *dc, struct dc_state *context,
struct pipe_ctx *pipe_ctx);
void (*program_all_writeback_pipes_in_tree)(struct dc *dc,

View File

@ -760,6 +760,11 @@ enum dmub_cmd_dpia_type {
DMUB_CMD__DPIA_MST_ALLOC_SLOTS = 2,
};
enum dmub_cmd_header_sub_type {
DMUB_CMD__SUB_TYPE_GENERAL = 0,
DMUB_CMD__SUB_TYPE_CURSOR_POSITION = 1
};
#pragma pack(push, 1)
/**

View File

@ -83,6 +83,7 @@ enum link_training_result {
};
enum lttpr_mode {
LTTPR_MODE_UNKNOWN,
LTTPR_MODE_NON_LTTPR,
LTTPR_MODE_TRANSPARENT,
LTTPR_MODE_NON_TRANSPARENT,

View File

@ -4409,6 +4409,10 @@
#define mmVMSHAREDPF0_MC_VM_XGMI_LFB_SIZE_BASE_IDX 1
#define mmVMSHAREDPF0_MC_VM_CACHEABLE_DRAM_CNTL 0x0af9
#define mmVMSHAREDPF0_MC_VM_CACHEABLE_DRAM_CNTL_BASE_IDX 1
#define mmMC_VM_XGMI_LFB_CNTL 0x0823
#define mmMC_VM_XGMI_LFB_CNTL_BASE_IDX 0
#define mmMC_VM_XGMI_LFB_SIZE 0x0824
#define mmMC_VM_XGMI_LFB_SIZE_BASE_IDX 0
// addressBlock: mmhub_utcl2_vmsharedvcdec

View File

@ -26728,6 +26728,14 @@
//VMSHAREDPF0_MC_VM_CACHEABLE_DRAM_CNTL
#define VMSHAREDPF0_MC_VM_CACHEABLE_DRAM_CNTL__ENABLE_CACHEABLE_DRAM_ADDRESS_APERTURE__SHIFT 0x0
#define VMSHAREDPF0_MC_VM_CACHEABLE_DRAM_CNTL__ENABLE_CACHEABLE_DRAM_ADDRESS_APERTURE_MASK 0x00000001L
//MC_VM_XGMI_LFB_CNTL
#define MC_VM_XGMI_LFB_CNTL__PF_LFB_REGION__SHIFT 0x0
#define MC_VM_XGMI_LFB_CNTL__PF_MAX_REGION__SHIFT 0x3
#define MC_VM_XGMI_LFB_CNTL__PF_LFB_REGION_MASK 0x00000007L
#define MC_VM_XGMI_LFB_CNTL__PF_MAX_REGION_MASK 0x00000038L
//MC_VM_XGMI_LFB_SIZE
#define MC_VM_XGMI_LFB_SIZE__PF_LFB_SIZE__SHIFT 0x0
#define MC_VM_XGMI_LFB_SIZE__PF_LFB_SIZE_MASK 0x0000FFFFL
// addressBlock: mmhub_utcl2_vmsharedvcdec

View File

@ -269,7 +269,8 @@ union MESAPI__ADD_QUEUE {
uint32_t map_kiq_utility_queue : 1;
uint32_t is_kfd_process : 1;
uint32_t trap_en : 1;
uint32_t reserved : 21;
uint32_t is_aql_queue : 1;
uint32_t reserved : 20;
};
struct MES_API_STATUS api_status;
uint64_t tma_addr;

View File

@ -1485,6 +1485,7 @@ static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)
{
struct pp_hwmgr *hwmgr = handle;
struct amdgpu_device *adev = hwmgr->adev;
int err;
if (!addr || !size)
return -EINVAL;
@ -1492,7 +1493,9 @@ static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)
*addr = NULL;
*size = 0;
if (adev->pm.smu_prv_buffer) {
amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);
err = amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);
if (err)
return err;
*size = adev->pm.smu_prv_buffer_size;
}

View File

@ -239,82 +239,47 @@ smu_v13_0_0_get_allowed_feature_mask(struct smu_context *smu,
uint32_t *feature_mask, uint32_t num)
{
struct amdgpu_device *adev = smu->adev;
u32 smu_version;
if (num > 2)
return -EINVAL;
memset(feature_mask, 0, sizeof(uint32_t) * num);
memset(feature_mask, 0xff, sizeof(uint32_t) * num);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
if (!(adev->pm.pp_feature & PP_SCLK_DPM_MASK)) {
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_IMU_BIT);
}
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
if (!(adev->pg_flags & AMD_PG_SUPPORT_ATHUB) ||
!(adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
(adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
if (!(adev->pm.pp_feature & PP_SOCCLK_DPM_MASK))
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
/* PMFW 78.58 contains a critical fix for gfxoff feature */
smu_cmn_get_smc_version(smu, NULL, &smu_version);
if ((smu_version < 0x004e3a00) ||
!(adev->pm.pp_feature & PP_GFXOFF_MASK))
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFXOFF_BIT);
#if 0
if (adev->pm.pp_feature & PP_GFXOFF_MASK)
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
#endif
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
if (!(adev->pm.pp_feature & PP_MCLK_DPM_MASK)) {
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
}
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
if (!(adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK))
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_DCFCLK_BIT);
if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) {
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_LINK_BIT);
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_LCLK_BIT);
}
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_CG_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_FCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_CTF_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_UCLK_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VR0HOT_BIT);
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT);
if (adev->pm.pp_feature & PP_ULV_MASK)
*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
if (!(adev->pm.pp_feature & PP_ULV_MASK))
*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_ULV_BIT);
return 0;
}