mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
amd-drm-next-7.2-2026-06-03:
amdgpu: - BT.2020 fix for DCE - DC bounds checking fixes - SDMA 7.1 fix - UserQ fixes - SI fix - SMU 13 fixes - SMU 14 fixes - GC 12.1 fix - Userptr fix - GC 10.1 fix - GART fix for non-4K pages - DCN 4.x fixes - DCN 4.2 updates - More DC KUnit tests - PSR cleanup - Support for connectors without DDC pins - Initial DCN 4.2.1 support - Initial HDMI 2.1 FRL support - Misc bounds check fixes - RAS fixes - GC 11.5.6 support - SDMA 6.4.0 support - NBIO 7.11.5 support - IH 6.4.0 support - HDP 6.4.0 support - MMHUB 3.4.2 support - SMU 15.0.5 support - ATHUB 3.4.2 support - VPE 2.2 support - Devcoredump fixes - _PR3 fix amdkfd: - UAF race fix - Fix a potential NULL pointer dereference - GC 11 buffer overflow fix for SDMA - Profiler locking order fix -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaiDUrgAKCRC93/aFa7yZ 2ADAAQDmTEPxVsj/ZDw8K/Kl4GYh43TbafwN6M9oqOD2PiCd/QEAgWJLmUB/yE0p d0oA1awDA9jogEaTT4PE7J1VFaLwYAk= =tPRP -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-7.2-2026-06-03' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-7.2-2026-06-03: amdgpu: - BT.2020 fix for DCE - DC bounds checking fixes - SDMA 7.1 fix - UserQ fixes - SI fix - SMU 13 fixes - SMU 14 fixes - GC 12.1 fix - Userptr fix - GC 10.1 fix - GART fix for non-4K pages - DCN 4.x fixes - DCN 4.2 updates - More DC KUnit tests - PSR cleanup - Support for connectors without DDC pins - Initial DCN 4.2.1 support - Initial HDMI 2.1 FRL support - Misc bounds check fixes - RAS fixes - GC 11.5.6 support - SDMA 6.4.0 support - NBIO 7.11.5 support - IH 6.4.0 support - HDP 6.4.0 support - MMHUB 3.4.2 support - SMU 15.0.5 support - ATHUB 3.4.2 support - VPE 2.2 support - Devcoredump fixes - _PR3 fix amdkfd: - UAF race fix - Fix a potential NULL pointer dereference - GC 11 buffer overflow fix for SDMA - Profiler locking order fix Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260604013527.2373534-1-alexander.deucher@amd.com
This commit is contained in:
commit
527b3f2a48
|
|
@ -553,7 +553,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
|
||||
coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
|
||||
if (coredump->rings && coredump->rings_dw) {
|
||||
for (i = 0, off = 0, idx = 0; i < adev->num_rings; i++) {
|
||||
for (i = 0, off = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) {
|
||||
ring = adev->rings[i];
|
||||
|
||||
if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
|
||||
|
|
|
|||
|
|
@ -1921,6 +1921,7 @@ static struct pci_dev *amdgpu_device_find_parent(struct amdgpu_device *adev)
|
|||
while ((parent = pci_upstream_bridge(parent))) {
|
||||
if (parent->vendor == PCI_VENDOR_ID_ATI)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
return parent;
|
||||
|
|
@ -2027,7 +2028,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
adev->flags |= AMD_IS_PX;
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU)) {
|
||||
parent = pcie_find_root_port(adev->pdev);
|
||||
parent = amdgpu_device_find_parent(adev);
|
||||
adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -396,6 +396,26 @@ static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev,
|
|||
return r;
|
||||
}
|
||||
|
||||
if (fw->size > adev->discovery.size) {
|
||||
dev_err(adev->dev,
|
||||
"ip discovery firmware \"%s\" too large (%zu > %u)\n",
|
||||
fw_name, fw->size, adev->discovery.size);
|
||||
release_firmware(fw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Ensure the firmware is at least large enough to contain the
|
||||
* binary header fields.
|
||||
*/
|
||||
if (fw->size < offsetof(struct binary_header, binary_size) +
|
||||
sizeof(((struct binary_header *)0)->binary_size)) {
|
||||
dev_err(adev->dev,
|
||||
"ip discovery firmware \"%s\" too small (%zu)\n",
|
||||
fw_name, fw->size);
|
||||
release_firmware(fw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy((u8 *)binary, (u8 *)fw->data, fw->size);
|
||||
release_firmware(fw);
|
||||
|
||||
|
|
@ -820,42 +840,44 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
|
|||
harvest_info = (struct harvest_table *)(discovery_bin + offset);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (le16_to_cpu(harvest_info->list[i].hw_id) == 0)
|
||||
u16 hw_id = le16_to_cpu(harvest_info->list[i].hw_id);
|
||||
u8 inst = harvest_info->list[i].number_instance;
|
||||
|
||||
if (hw_id == 0)
|
||||
break;
|
||||
|
||||
switch (le16_to_cpu(harvest_info->list[i].hw_id)) {
|
||||
if (inst >= 32) {
|
||||
dev_warn(adev->dev,
|
||||
"bogus harvest instance %u for hw_id %u\n",
|
||||
inst, hw_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (hw_id) {
|
||||
case VCN_HWID:
|
||||
(*vcn_harvest_count)++;
|
||||
adev->vcn.harvest_config |=
|
||||
(1 << harvest_info->list[i].number_instance);
|
||||
adev->jpeg.harvest_config |=
|
||||
(1 << harvest_info->list[i].number_instance);
|
||||
adev->vcn.harvest_config |= BIT(inst);
|
||||
adev->jpeg.harvest_config |= BIT(inst);
|
||||
|
||||
adev->vcn.inst_mask &=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
adev->jpeg.inst_mask &=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
adev->vcn.inst_mask &= ~BIT(inst);
|
||||
adev->jpeg.inst_mask &= ~BIT(inst);
|
||||
break;
|
||||
case DMU_HWID:
|
||||
adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
|
||||
break;
|
||||
case UMC_HWID:
|
||||
umc_harvest_config |=
|
||||
1 << (le16_to_cpu(harvest_info->list[i].number_instance));
|
||||
umc_harvest_config |= BIT_ULL(inst);
|
||||
(*umc_harvest_count)++;
|
||||
break;
|
||||
case GC_HWID:
|
||||
adev->gfx.xcc_mask &=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
adev->gfx.xcc_mask &= ~BIT(inst);
|
||||
break;
|
||||
case SDMA0_HWID:
|
||||
adev->sdma.sdma_mask &=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
adev->sdma.sdma_mask &= ~BIT(inst);
|
||||
break;
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
case ISP_HWID:
|
||||
adev->isp.harvest_config |=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
adev->isp.harvest_config |= ~BIT(inst);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
|
@ -2096,6 +2118,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
amdgpu_device_ip_block_add(adev, &soc21_common_ip_block);
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
|
|
@ -2156,6 +2179,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
|
|
@ -2203,6 +2227,7 @@ static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
|
|||
break;
|
||||
case IP_VERSION(6, 1, 0):
|
||||
case IP_VERSION(6, 1, 1):
|
||||
case IP_VERSION(6, 4, 0):
|
||||
amdgpu_device_ip_block_add(adev, &ih_v6_1_ip_block);
|
||||
break;
|
||||
case IP_VERSION(7, 0, 0):
|
||||
|
|
@ -2344,6 +2369,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 5):
|
||||
case IP_VERSION(15, 0, 8):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v15_0_ip_block);
|
||||
break;
|
||||
|
|
@ -2399,6 +2425,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 1, 0):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
/* TODO: Fix IP version. DC code expects version 4.0.1 */
|
||||
if (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(4, 1, 0))
|
||||
adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 0, 1);
|
||||
|
|
@ -2478,6 +2505,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
|
|
@ -2538,6 +2566,7 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(6, 1, 2):
|
||||
case IP_VERSION(6, 1, 3):
|
||||
case IP_VERSION(6, 1, 4):
|
||||
case IP_VERSION(6, 4, 0):
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v6_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(7, 0, 0):
|
||||
|
|
@ -2689,6 +2718,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block);
|
||||
adev->enable_mes = true;
|
||||
adev->enable_mes_kiq = true;
|
||||
|
|
@ -2739,6 +2769,7 @@ static int amdgpu_discovery_set_vpe_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &vpe_v6_1_ip_block);
|
||||
break;
|
||||
case IP_VERSION(2, 0, 0):
|
||||
case IP_VERSION(2, 2, 0):
|
||||
amdgpu_device_ip_block_add(adev, &vpe_v2_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -3095,6 +3126,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
|
|
@ -3123,6 +3155,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->flags |= AMD_IS_APU;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -3194,6 +3227,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
break;
|
||||
case IP_VERSION(6, 3, 1):
|
||||
case IP_VERSION(7, 11, 4):
|
||||
case IP_VERSION(7, 11, 5):
|
||||
adev->nbio.funcs = &nbif_v6_3_1_funcs;
|
||||
adev->nbio.hdp_flush_reg = &nbif_v6_3_1_hdp_flush_reg;
|
||||
break;
|
||||
|
|
@ -3232,6 +3266,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(6, 0, 1):
|
||||
case IP_VERSION(6, 1, 0):
|
||||
case IP_VERSION(6, 1, 1):
|
||||
case IP_VERSION(6, 4, 0):
|
||||
adev->hdp.funcs = &hdp_v6_0_funcs;
|
||||
break;
|
||||
case IP_VERSION(7, 0, 0):
|
||||
|
|
@ -3314,6 +3349,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
adev->smuio.funcs = &smuio_v14_0_2_funcs;
|
||||
break;
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 5):
|
||||
adev->smuio.funcs = &smuio_v15_0_0_funcs;
|
||||
break;
|
||||
case IP_VERSION(15, 0, 8):
|
||||
|
|
|
|||
|
|
@ -115,6 +115,43 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IPMI FRU Product Info Area fields are TLV: one type/length byte
|
||||
* (low 6 bits = data length) followed by that many data bytes. These
|
||||
* helpers walk the cursor and copy a single field while bounding all
|
||||
* accesses to the actual buffer length read from the EEPROM.
|
||||
*/
|
||||
#define FRU_FIELD_LEN(p, a) ((p)[a] & 0x3F)
|
||||
|
||||
/* Advance cursor past the current TLV. Returns false if no more data. */
|
||||
static bool fru_pia_advance(u32 *addr, const unsigned char *pia, int len)
|
||||
{
|
||||
if (*addr >= (u32)len)
|
||||
return false;
|
||||
*addr += 1 + FRU_FIELD_LEN(pia, *addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the current TLV's data into dst (NUL-terminated). Returns false if
|
||||
* the TLV header or data would read past the end of pia.
|
||||
*/
|
||||
static bool fru_pia_copy_field(char *dst, size_t dst_size,
|
||||
const unsigned char *pia, u32 addr, int len)
|
||||
{
|
||||
size_t fl;
|
||||
|
||||
if (addr + 1 >= (u32)len)
|
||||
return false;
|
||||
|
||||
fl = min3((size_t)FRU_FIELD_LEN(pia, addr),
|
||||
dst_size - 1,
|
||||
(size_t)(len - addr - 1));
|
||||
memcpy(dst, pia + addr + 1, fl);
|
||||
dst[fl] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_fru_info *fru_info;
|
||||
|
|
@ -223,52 +260,46 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
|||
* Read Manufacturer Name field whose length is [3].
|
||||
*/
|
||||
addr = 3;
|
||||
if (addr + 1 >= len)
|
||||
if (!fru_pia_copy_field(fru_info->manufacturer_name,
|
||||
sizeof(fru_info->manufacturer_name),
|
||||
pia, addr, len))
|
||||
goto Out;
|
||||
memcpy(fru_info->manufacturer_name, pia + addr + 1,
|
||||
min_t(size_t, sizeof(fru_info->manufacturer_name),
|
||||
pia[addr] & 0x3F));
|
||||
fru_info->manufacturer_name[sizeof(fru_info->manufacturer_name) - 1] =
|
||||
'\0';
|
||||
|
||||
/* Read Product Name field. */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
if (addr + 1 >= len)
|
||||
if (!fru_pia_advance(&addr, pia, len) ||
|
||||
!fru_pia_copy_field(fru_info->product_name,
|
||||
sizeof(fru_info->product_name),
|
||||
pia, addr, len))
|
||||
goto Out;
|
||||
memcpy(fru_info->product_name, pia + addr + 1,
|
||||
min_t(size_t, sizeof(fru_info->product_name), pia[addr] & 0x3F));
|
||||
fru_info->product_name[sizeof(fru_info->product_name) - 1] = '\0';
|
||||
|
||||
/* Go to the Product Part/Model Number field. */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
if (addr + 1 >= len)
|
||||
if (!fru_pia_advance(&addr, pia, len) ||
|
||||
!fru_pia_copy_field(fru_info->product_number,
|
||||
sizeof(fru_info->product_number),
|
||||
pia, addr, len))
|
||||
goto Out;
|
||||
memcpy(fru_info->product_number, pia + addr + 1,
|
||||
min_t(size_t, sizeof(fru_info->product_number),
|
||||
pia[addr] & 0x3F));
|
||||
fru_info->product_number[sizeof(fru_info->product_number) - 1] = '\0';
|
||||
|
||||
/* Go to the Product Version field. */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
|
||||
/* Go to the Product Serial Number field. */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
if (addr + 1 >= len)
|
||||
/* Skip the Product Version field. */
|
||||
if (!fru_pia_advance(&addr, pia, len))
|
||||
goto Out;
|
||||
memcpy(fru_info->serial, pia + addr + 1,
|
||||
min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
|
||||
fru_info->serial[sizeof(fru_info->serial) - 1] = '\0';
|
||||
|
||||
/* Asset Tag field */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
/* Read the Product Serial Number field. */
|
||||
if (!fru_pia_advance(&addr, pia, len) ||
|
||||
!fru_pia_copy_field(fru_info->serial,
|
||||
sizeof(fru_info->serial),
|
||||
pia, addr, len))
|
||||
goto Out;
|
||||
|
||||
/* Skip the Asset Tag field. */
|
||||
if (!fru_pia_advance(&addr, pia, len))
|
||||
goto Out;
|
||||
|
||||
/* FRU File Id field. This could be 'null'. */
|
||||
addr += 1 + (pia[addr] & 0x3F);
|
||||
if ((addr + 1 >= len) || !(pia[addr] & 0x3F))
|
||||
if (!fru_pia_advance(&addr, pia, len) ||
|
||||
!fru_pia_copy_field(fru_info->fru_id,
|
||||
sizeof(fru_info->fru_id),
|
||||
pia, addr, len))
|
||||
goto Out;
|
||||
memcpy(fru_info->fru_id, pia + addr + 1,
|
||||
min_t(size_t, sizeof(fru_info->fru_id), pia[addr] & 0x3F));
|
||||
fru_info->fru_id[sizeof(fru_info->fru_id) - 1] = '\0';
|
||||
|
||||
Out:
|
||||
kfree(pia);
|
||||
|
|
|
|||
|
|
@ -394,7 +394,8 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
uint64_t start_page, uint64_t num_pages,
|
||||
uint64_t flags, void *dst)
|
||||
{
|
||||
u32 i, idx;
|
||||
u32 i, j, t, idx;
|
||||
u64 page_base;
|
||||
|
||||
/* The SYSTEM flag indicates the pages aren't in VRAM. */
|
||||
WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM);
|
||||
|
|
@ -402,9 +403,12 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst,
|
||||
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
|
||||
page_base = pa;
|
||||
for (i = 0, t = 0; i < num_pages; i++) {
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj,
|
|||
|
||||
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
r = drm_exec_prepare_obj(&exec, &abo->tbo.base, 1);
|
||||
r = drm_exec_prepare_obj(&exec, &abo->tbo.base, TTM_NUM_MOVE_FENCES + 1);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(r))
|
||||
goto out_unlock;
|
||||
|
|
|
|||
|
|
@ -990,10 +990,7 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return r;
|
||||
|
||||
if (adev->gfx.cp_ecc_error_irq.funcs) {
|
||||
if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs) {
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
|
|
@ -1008,6 +1005,21 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
|
|||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_gfx_ras_suspend(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs)
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
}
|
||||
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(adev) && adev->gfx.cp_ecc_error_irq.funcs)
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
amdgpu_ras_block_late_fini(adev, ras_block);
|
||||
}
|
||||
|
||||
int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
@ -1036,6 +1048,12 @@ int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev)
|
|||
if (!ras->ras_block.ras_late_init)
|
||||
ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init;
|
||||
|
||||
if (!ras->ras_block.ras_suspend)
|
||||
ras->ras_block.ras_suspend = amdgpu_gfx_ras_suspend;
|
||||
|
||||
if (!ras->ras_block.ras_fini)
|
||||
ras->ras_block.ras_fini = amdgpu_gfx_ras_fini;
|
||||
|
||||
/* If not defined special ras_cb function, use default ras_cb */
|
||||
if (!ras->ras_block.ras_cb)
|
||||
ras->ras_block.ras_cb = amdgpu_gfx_process_ras_data_cb;
|
||||
|
|
|
|||
|
|
@ -615,7 +615,8 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
|
|||
void amdgpu_gfx_off_ctrl_immediate(struct amdgpu_device *adev, bool enable);
|
||||
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value);
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_ras_suspend(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
int amdgpu_get_gfx_off_entrycount(struct amdgpu_device *adev, u64 *value);
|
||||
int amdgpu_get_gfx_off_residency(struct amdgpu_device *adev, u32 *residency);
|
||||
int amdgpu_set_gfx_off_residency(struct amdgpu_device *adev, bool value);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
|||
/*
|
||||
* The following is for PTE only. GART does not have PDEs.
|
||||
*/
|
||||
value = addr & 0x0000FFFFFFFFF000ULL;
|
||||
value = addr & adev->gmc.pte_addr_mask;
|
||||
value |= flags;
|
||||
writeq(value, ptr + (gpu_page_idx * 8));
|
||||
|
||||
|
|
@ -976,6 +976,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
/* Don't enable it by default yet.
|
||||
*/
|
||||
if (amdgpu_tmz < 1) {
|
||||
|
|
@ -1014,7 +1015,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
|||
gc_ver == IP_VERSION(9, 4, 3) ||
|
||||
gc_ver == IP_VERSION(9, 4, 4) ||
|
||||
gc_ver == IP_VERSION(9, 5, 0) ||
|
||||
gc_ver >= IP_VERSION(10, 3, 0));
|
||||
gc_ver >= IP_VERSION(10, 1, 0));
|
||||
|
||||
/* For GFX12.1 B0, set xnack (retry) on as default */
|
||||
if (gc_ver == IP_VERSION(12, 1, 0) && (adev->rev_id & 0xf) == 0x1)
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ struct amdgpu_gmc {
|
|||
u64 real_vram_size;
|
||||
int vram_mtrr;
|
||||
u64 mc_mask;
|
||||
uint64_t pte_addr_mask;
|
||||
const struct firmware *fw; /* MC firmware */
|
||||
uint32_t fw_version;
|
||||
struct amdgpu_irq_src vm_fault;
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ int amdgpu_gtt_mgr_alloc_entries(struct amdgpu_gtt_mgr *mgr,
|
|||
int r;
|
||||
|
||||
/* Align to TLB L2 cache entry size to work around "V bit HW bug" */
|
||||
if (adev->asic_type == CHIP_TAHITI) {
|
||||
if (adev->family == AMDGPU_FAMILY_SI) {
|
||||
alignment = 32 * 1024 / AMDGPU_GPU_PAGE_SIZE;
|
||||
num_pages = ALIGN(num_pages, alignment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
|||
{
|
||||
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
|
||||
long r;
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
|
|
@ -77,8 +78,9 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
|||
mmu_interval_set_seq(mni, cur_seq);
|
||||
|
||||
amdgpu_vm_bo_invalidate(bo, false);
|
||||
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
|
||||
false, MAX_SCHEDULE_TIMEOUT);
|
||||
r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
|
||||
DMA_RESV_USAGE_BOOKKEEP, false,
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
mutex_unlock(&adev->notifier_lock);
|
||||
if (r <= 0)
|
||||
DRM_ERROR("(%ld) failed to wait for user bo\n", r);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev)
|
|||
|
||||
strcpy(ras->ras_block.ras_comm.name, "mca.mp0");
|
||||
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
|
||||
ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP0;
|
||||
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->mca.mp0.ras_if = &ras->ras_block.ras_comm;
|
||||
|
||||
|
|
@ -123,6 +124,7 @@ int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev)
|
|||
|
||||
strcpy(ras->ras_block.ras_comm.name, "mca.mp1");
|
||||
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
|
||||
ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP1;
|
||||
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->mca.mp1.ras_if = &ras->ras_block.ras_comm;
|
||||
|
||||
|
|
@ -147,6 +149,7 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev)
|
|||
|
||||
strcpy(ras->ras_block.ras_comm.name, "mca.mpio");
|
||||
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
|
||||
ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MPIO;
|
||||
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
|
||||
adev->mca.mpio.ras_if = &ras->ras_block.ras_comm;
|
||||
|
||||
|
|
|
|||
|
|
@ -4651,14 +4651,17 @@ static ssize_t amdgpu_psp_vbflash_write(struct file *filp, struct kobject *kobj,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&adev->psp.mutex);
|
||||
|
||||
/* TODO Just allocate max for now and optimize to realloc later if needed */
|
||||
if (!adev->psp.vbflash_tmp_buf) {
|
||||
adev->psp.vbflash_tmp_buf = kvmalloc(AMD_VBIOS_FILE_MAX_SIZE_B, GFP_KERNEL);
|
||||
if (!adev->psp.vbflash_tmp_buf)
|
||||
if (!adev->psp.vbflash_tmp_buf) {
|
||||
mutex_unlock(&adev->psp.mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&adev->psp.mutex);
|
||||
memcpy(adev->psp.vbflash_tmp_buf + pos, buffer, count);
|
||||
adev->psp.vbflash_image_size += count;
|
||||
mutex_unlock(&adev->psp.mutex);
|
||||
|
|
@ -4723,7 +4726,7 @@ static ssize_t amdgpu_psp_vbflash_read(struct file *filp, struct kobject *kobj,
|
|||
*/
|
||||
static const struct bin_attribute psp_vbflash_bin_attr = {
|
||||
.attr = {.name = "psp_vbflash", .mode = 0660},
|
||||
.size = 0,
|
||||
.size = AMD_VBIOS_FILE_MAX_SIZE_B,
|
||||
.write = amdgpu_psp_vbflash_write,
|
||||
.read = amdgpu_psp_vbflash_read,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ struct amdgpu_ras_block_list {
|
|||
struct list_head node;
|
||||
|
||||
struct amdgpu_ras_block_object *ras_obj;
|
||||
|
||||
/* set by ras_late_init, cleared by ras_suspend/ras_fini */
|
||||
bool active;
|
||||
};
|
||||
|
||||
const char *get_ras_block_str(struct ras_common_if *ras_block)
|
||||
|
|
@ -4637,10 +4640,23 @@ void amdgpu_ras_resume(struct amdgpu_device *adev)
|
|||
void amdgpu_ras_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct amdgpu_ras_block_list *node;
|
||||
struct amdgpu_ras_block_object *obj;
|
||||
|
||||
if (!adev->ras_enabled || !con)
|
||||
return;
|
||||
|
||||
/* run per-block ras_suspend before tearing down the RAS context */
|
||||
list_for_each_entry(node, &adev->ras_list, node) {
|
||||
if (!node->active)
|
||||
continue;
|
||||
|
||||
obj = node->ras_obj;
|
||||
if (obj && obj->ras_suspend)
|
||||
obj->ras_suspend(adev, &obj->ras_comm);
|
||||
node->active = false;
|
||||
}
|
||||
|
||||
amdgpu_ras_disable_all_features(adev, 0);
|
||||
/* Make sure all ras objects are disabled. */
|
||||
if (AMDGPU_RAS_GET_FEATURES(con->features))
|
||||
|
|
@ -4694,8 +4710,15 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
|
|||
obj->ras_comm.name, r);
|
||||
return r;
|
||||
}
|
||||
} else
|
||||
amdgpu_ras_block_late_init_default(adev, &obj->ras_comm);
|
||||
} else {
|
||||
r = amdgpu_ras_block_late_init_default(adev, &obj->ras_comm);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "%s failed to execute ras_block_late_init_default! ret:%d\n",
|
||||
obj->ras_comm.name, r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
node->active = true;
|
||||
}
|
||||
|
||||
amdgpu_ras_check_bad_page_status(adev);
|
||||
|
|
@ -4734,11 +4757,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
|
|||
list_for_each_entry_safe(ras_node, tmp, &adev->ras_list, node) {
|
||||
if (ras_node->ras_obj) {
|
||||
obj = ras_node->ras_obj;
|
||||
if (amdgpu_ras_is_supported(adev, obj->ras_comm.block) &&
|
||||
obj->ras_fini)
|
||||
/* fall back to default cleanup if ras_suspend already ran */
|
||||
if (ras_node->active && obj->ras_fini)
|
||||
obj->ras_fini(adev, &obj->ras_comm);
|
||||
else
|
||||
amdgpu_ras_block_late_fini_default(adev, &obj->ras_comm);
|
||||
ras_node->active = false;
|
||||
}
|
||||
|
||||
/* Clear ras blocks from ras_list and free ras block list node */
|
||||
|
|
|
|||
|
|
@ -762,6 +762,7 @@ struct amdgpu_ras_block_object {
|
|||
int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj,
|
||||
enum amdgpu_ras_block block, uint32_t sub_block_index);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
void (*ras_suspend)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
void (*ras_fini)(struct amdgpu_device *adev, struct ras_common_if *ras_block);
|
||||
ras_ih_cb ras_cb;
|
||||
const struct amdgpu_ras_block_hw_ops *hw_ops;
|
||||
|
|
|
|||
|
|
@ -145,12 +145,15 @@
|
|||
#define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \
|
||||
(_C)->ras_max_record_count)
|
||||
|
||||
#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
|
||||
RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)
|
||||
#define RAS_NUM_RECS(_tbl_hdr) \
|
||||
(((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE) ? 0u : \
|
||||
(((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE))
|
||||
|
||||
#define RAS_NUM_RECS_V2_1(_tbl_hdr) (((_tbl_hdr)->tbl_size - \
|
||||
RAS_TABLE_HEADER_SIZE - \
|
||||
RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE)
|
||||
#define RAS_NUM_RECS_V2_1(_tbl_hdr) \
|
||||
(((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE + \
|
||||
RAS_TABLE_V2_1_INFO_SIZE) ? 0u : \
|
||||
(((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE - \
|
||||
RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE))
|
||||
|
||||
#define to_amdgpu_device(x) ((container_of(x, struct amdgpu_ras, eeprom_control))->adev)
|
||||
|
||||
|
|
@ -1610,11 +1613,24 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
switch (hdr->version) {
|
||||
case RAS_TABLE_VER_V2_1:
|
||||
case RAS_TABLE_VER_V3:
|
||||
if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE) {
|
||||
dev_err(adev->dev,
|
||||
"RAS header invalid, tbl_size %u smaller than minimum %u, resetting table\n",
|
||||
hdr->tbl_size,
|
||||
RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE);
|
||||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
|
||||
control->ras_record_offset = RAS_RECORD_START_V2_1;
|
||||
control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
|
||||
break;
|
||||
case RAS_TABLE_VER_V1:
|
||||
if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE) {
|
||||
dev_err(adev->dev,
|
||||
"RAS header invalid, tbl_size %u smaller than minimum %u, resetting table\n",
|
||||
hdr->tbl_size, RAS_TABLE_HEADER_SIZE);
|
||||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
control->ras_num_recs = RAS_NUM_RECS(hdr);
|
||||
control->ras_record_offset = RAS_RECORD_START;
|
||||
control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ bool amdgpu_ring_soft_recovery(struct amdgpu_ring *ring, unsigned int vmid,
|
|||
static ssize_t amdgpu_ras_cper_debugfs_read(struct file *f, char __user *buf,
|
||||
size_t size, loff_t *offset)
|
||||
{
|
||||
const uint8_t ring_header_size = 12;
|
||||
const u8 ring_header_size = 12;
|
||||
struct amdgpu_ring *ring = file_inode(f)->i_private;
|
||||
struct ras_cmd_cper_snapshot_req *snapshot_req __free(kfree) =
|
||||
kzalloc_obj(struct ras_cmd_cper_snapshot_req);
|
||||
|
|
@ -494,49 +494,103 @@ static ssize_t amdgpu_ras_cper_debugfs_read(struct file *f, char __user *buf,
|
|||
kzalloc_obj(struct ras_cmd_cper_record_req);
|
||||
struct ras_cmd_cper_record_rsp *record_rsp __free(kfree) =
|
||||
kzalloc_obj(struct ras_cmd_cper_record_rsp);
|
||||
uint8_t *ring_header __free(kfree) =
|
||||
u32 *ring_header __free(kfree) =
|
||||
kzalloc(ring_header_size, GFP_KERNEL);
|
||||
uint32_t total_cper_num;
|
||||
uint64_t start_cper_id;
|
||||
char __user *data_buf = buf;
|
||||
size_t data_size = size;
|
||||
u32 total_cper_num;
|
||||
u64 start_cper_id;
|
||||
u64 cper_offset;
|
||||
size_t chunk_size;
|
||||
size_t total_data_size = 0;
|
||||
bool read_header;
|
||||
int r;
|
||||
|
||||
if (!snapshot_req || !snapshot_rsp || !record_req || !record_rsp ||
|
||||
!ring_header)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(*offset)) {
|
||||
read_header = !(*offset);
|
||||
cper_offset = read_header ? 0 : *offset - 1;
|
||||
|
||||
if (read_header) {
|
||||
/* Need at least 12 bytes for the header on the first read */
|
||||
if (size < ring_header_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_to_user(buf, ring_header, ring_header_size))
|
||||
return -EFAULT;
|
||||
buf += ring_header_size;
|
||||
size -= ring_header_size;
|
||||
data_buf += ring_header_size;
|
||||
data_size -= ring_header_size;
|
||||
}
|
||||
|
||||
r = amdgpu_ras_mgr_handle_ras_cmd(ring->adev,
|
||||
RAS_CMD__GET_CPER_SNAPSHOT,
|
||||
snapshot_req, sizeof(struct ras_cmd_cper_snapshot_req),
|
||||
snapshot_rsp, sizeof(struct ras_cmd_cper_snapshot_rsp));
|
||||
if (r || !snapshot_rsp->total_cper_num)
|
||||
return r;
|
||||
|
||||
start_cper_id = snapshot_rsp->start_cper_id;
|
||||
total_cper_num = snapshot_rsp->total_cper_num;
|
||||
|
||||
record_req->buf_ptr = (uint64_t)(uintptr_t)buf;
|
||||
record_req->buf_size = size;
|
||||
record_req->cper_start_id = start_cper_id + *offset;
|
||||
record_req->cper_num = total_cper_num;
|
||||
r = amdgpu_ras_mgr_handle_ras_cmd(ring->adev, RAS_CMD__GET_CPER_RECORD,
|
||||
record_req, sizeof(struct ras_cmd_cper_record_req),
|
||||
record_rsp, sizeof(struct ras_cmd_cper_record_rsp));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = *offset ? record_rsp->real_data_size : record_rsp->real_data_size + ring_header_size;
|
||||
(*offset) += record_rsp->real_cper_num;
|
||||
if (!snapshot_rsp->total_cper_num) {
|
||||
if (!read_header)
|
||||
return 0;
|
||||
|
||||
if (copy_to_user(buf, ring_header, ring_header_size))
|
||||
return -EFAULT;
|
||||
|
||||
*offset = 1;
|
||||
return ring_header_size;
|
||||
}
|
||||
|
||||
start_cper_id = snapshot_rsp->start_cper_id;
|
||||
total_cper_num = snapshot_rsp->total_cper_num;
|
||||
if (read_header && !data_size) {
|
||||
if (copy_to_user(buf, ring_header, ring_header_size))
|
||||
return -EFAULT;
|
||||
|
||||
*offset = cper_offset + 1;
|
||||
return ring_header_size;
|
||||
}
|
||||
|
||||
if (!data_size)
|
||||
return 0;
|
||||
|
||||
while (data_size && cper_offset < total_cper_num) {
|
||||
memset(record_req, 0, sizeof(*record_req));
|
||||
memset(record_rsp, 0, sizeof(*record_rsp));
|
||||
chunk_size = min_t(size_t, data_size, RAS_CMD_MAX_CPER_BUF_SZ);
|
||||
|
||||
record_req->buf_ptr = (u64)(uintptr_t)data_buf;
|
||||
record_req->buf_size = chunk_size;
|
||||
record_req->cper_start_id = start_cper_id + cper_offset;
|
||||
record_req->cper_num = total_cper_num - cper_offset;
|
||||
r = amdgpu_ras_mgr_handle_ras_cmd(ring->adev,
|
||||
RAS_CMD__GET_CPER_RECORD,
|
||||
record_req,
|
||||
sizeof(struct ras_cmd_cper_record_req),
|
||||
record_rsp,
|
||||
sizeof(struct ras_cmd_cper_record_rsp));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!record_rsp->real_data_size || !record_rsp->real_cper_num)
|
||||
break;
|
||||
if (record_rsp->real_data_size > data_size)
|
||||
return -EIO;
|
||||
|
||||
data_buf += record_rsp->real_data_size;
|
||||
data_size -= record_rsp->real_data_size;
|
||||
total_data_size += record_rsp->real_data_size;
|
||||
cper_offset += record_rsp->real_cper_num;
|
||||
}
|
||||
|
||||
if (read_header) {
|
||||
ring_header[1] = total_data_size >> 2;
|
||||
ring_header[2] = ring_header[1];
|
||||
|
||||
if (copy_to_user(buf, ring_header, ring_header_size))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
r = read_header ? total_data_size + ring_header_size : total_data_size;
|
||||
*offset = cper_offset + 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,15 +98,18 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
|||
uint32_t phy_id;
|
||||
uint32_t op;
|
||||
char str[64];
|
||||
int ret;
|
||||
long len;
|
||||
ssize_t write_ret = size;
|
||||
int ret, nargs;
|
||||
|
||||
if (*pos || size > sizeof(str) - 1)
|
||||
if (*pos)
|
||||
return -EINVAL;
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
ret = copy_from_user(str, buf, size);
|
||||
if (ret)
|
||||
len = strncpy_from_user(str, buf, sizeof(str));
|
||||
if (len < 0)
|
||||
return -EFAULT;
|
||||
if (len == 0 || len >= sizeof(str))
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_runtime_get_sync(dev->dev);
|
||||
if (ret < 0) {
|
||||
|
|
@ -114,10 +117,14 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (size < 3)
|
||||
sscanf(str, "%u ", &op);
|
||||
if (len < 3)
|
||||
nargs = sscanf(str, "%u", &op);
|
||||
else
|
||||
sscanf(str, "%u %u", &op, &phy_id);
|
||||
nargs = sscanf(str, "%u %u", &op, &phy_id);
|
||||
if (nargs < 1) {
|
||||
write_ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case 1:
|
||||
|
|
@ -135,9 +142,10 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
|||
mutex_unlock(&psp->securedisplay_context.mutex);
|
||||
break;
|
||||
case 2:
|
||||
if (size < 3 || phy_id >= TA_SECUREDISPLAY_MAX_PHY) {
|
||||
if (nargs < 2 || phy_id >= TA_SECUREDISPLAY_MAX_PHY) {
|
||||
dev_err(adev->dev, "Invalid input: %s\n", str);
|
||||
return -EINVAL;
|
||||
write_ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_lock(&psp->securedisplay_context.mutex);
|
||||
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
|
||||
|
|
@ -157,11 +165,14 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
|||
break;
|
||||
default:
|
||||
dev_err(adev->dev, "Invalid input: %s\n", str);
|
||||
write_ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
|
||||
return size;
|
||||
return write_ret;
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_securedisplay_debugfs_ops = {
|
||||
|
|
|
|||
|
|
@ -173,16 +173,17 @@ void amdgpu_seq64_unmap(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv)
|
|||
int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *va,
|
||||
u64 *gpu_addr, u64 **cpu_addr)
|
||||
{
|
||||
unsigned long bit_pos;
|
||||
unsigned long bit_pos = 0;
|
||||
|
||||
for (;;) {
|
||||
bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem);
|
||||
do {
|
||||
bit_pos = find_next_zero_bit(adev->seq64.used,
|
||||
adev->seq64.num_sem, bit_pos);
|
||||
if (bit_pos >= adev->seq64.num_sem)
|
||||
return -ENOSPC;
|
||||
|
||||
if (!test_and_set_bit(bit_pos, adev->seq64.used))
|
||||
break;
|
||||
}
|
||||
bit_pos++;
|
||||
} while (1);
|
||||
|
||||
*va = bit_pos * sizeof(u64) + amdgpu_seq64_get_va_base(adev);
|
||||
|
||||
|
|
|
|||
|
|
@ -532,10 +532,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
amdgpu_bo_unreserve(queue->db_obj.obj);
|
||||
amdgpu_bo_unref(&queue->db_obj.obj);
|
||||
|
||||
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
|
||||
amdgpu_bo_unpin(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unref(&queue->wptr_obj.obj);
|
||||
kfree(queue);
|
||||
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
|
|
@ -887,7 +883,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
continue;
|
||||
}
|
||||
|
||||
r = amdgpu_userq_restore_helper(queue);
|
||||
r = amdgpu_userq_map_helper(queue);
|
||||
if (r)
|
||||
ret = r;
|
||||
|
||||
|
|
@ -975,7 +971,7 @@ amdgpu_userq_vm_validate(struct amdgpu_userq_mgr *uq_mgr)
|
|||
if (unlikely(ret))
|
||||
goto unlock_all;
|
||||
|
||||
ret = amdgpu_vm_lock_individual(vm, &exec, 1);
|
||||
ret = amdgpu_vm_lock_individual(vm, &exec, TTM_NUM_MOVE_FENCES + 1);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(ret))
|
||||
goto unlock_all;
|
||||
|
|
@ -1124,7 +1120,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
|
||||
/* Try to unmap all the queues in this process ctx */
|
||||
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
|
||||
r = amdgpu_userq_preempt_helper(queue);
|
||||
r = amdgpu_userq_unmap_helper(queue);
|
||||
if (r)
|
||||
ret = r;
|
||||
}
|
||||
|
|
@ -1344,8 +1340,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *mapping,
|
||||
uint64_t saddr)
|
||||
struct amdgpu_bo_va_mapping *mapping)
|
||||
{
|
||||
u32 ip_mask = amdgpu_userq_get_supported_ip_mask(adev);
|
||||
struct amdgpu_bo_va *bo_va = mapping->bo_va;
|
||||
|
|
@ -1354,12 +1349,9 @@ void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
|||
if (!ip_mask)
|
||||
return;
|
||||
|
||||
dev_warn_once(adev->dev, "now unmapping a vital queue va:%llx\n", saddr);
|
||||
/**
|
||||
* The userq VA mapping reservation should include the eviction fence,
|
||||
* if the eviction fence can't signal successfully during unmapping,
|
||||
* then driver will warn to flag this improper unmap of the userq VA.
|
||||
* Note: The eviction fence may be attached to different BOs, and this
|
||||
* The userq VA mapping reservation should include the eviction fence.
|
||||
* Note: The eviction fence may be attached to different BOs and this
|
||||
* unmap is only for one kind of userq VAs, so at this point suppose
|
||||
* the eviction fence is always unsignaled.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -182,6 +182,5 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
|||
u64 addr, u64 expected_size, u64 *va_out);
|
||||
|
||||
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *mapping,
|
||||
uint64_t saddr);
|
||||
struct amdgpu_bo_va_mapping *mapping);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -283,14 +283,66 @@ unsigned int amd_sriov_msg_checksum(void *obj,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_INIT_CAPACITY 512
|
||||
/* Max bad page slots allowed for SRIOV*/
|
||||
#define AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY 10665U
|
||||
|
||||
/**
|
||||
* amdgpu_virt_ras_realloc_eh_data_space - alloc/realloc VF bad-page @data->bps and @data->bps_bo
|
||||
* @adev: amdgpu device
|
||||
* @data: VF RAS error-handler data
|
||||
* @pages: minimum number of new slots to add beyond @data->capacity
|
||||
*
|
||||
* Return: 0 on success, %-ENOMEM on failure.
|
||||
*/
|
||||
static int amdgpu_virt_ras_realloc_eh_data_space(struct amdgpu_device *adev,
|
||||
struct amdgpu_virt_ras_err_handler_data *data,
|
||||
int pages)
|
||||
{
|
||||
struct eeprom_table_record *new_bps;
|
||||
struct amdgpu_bo **new_bo;
|
||||
unsigned int old_space;
|
||||
unsigned int new_space;
|
||||
unsigned int align_space;
|
||||
|
||||
old_space = (unsigned int)data->capacity;
|
||||
new_space = old_space + max_t(unsigned int, (unsigned int)pages,
|
||||
(unsigned int)AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_INIT_CAPACITY);
|
||||
if (new_space < old_space || new_space > AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY)
|
||||
return -ENOMEM;
|
||||
|
||||
align_space = ALIGN(new_space, AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_INIT_CAPACITY);
|
||||
if (align_space > AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY)
|
||||
return -ENOMEM;
|
||||
|
||||
new_bps = kmalloc_array(align_space, sizeof(*data->bps), GFP_KERNEL);
|
||||
new_bo = kcalloc(align_space, sizeof(*data->bps_bo), GFP_KERNEL);
|
||||
if (!new_bps || !new_bo) {
|
||||
kfree(new_bps);
|
||||
kfree(new_bo);
|
||||
dev_warn_ratelimited(adev->dev,
|
||||
"RAS WARN: failed to grow bad page table to %u slots\n",
|
||||
align_space);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(new_bps, data->bps, data->count * sizeof(*data->bps));
|
||||
memcpy(new_bo, data->bps_bo, data->count * sizeof(*data->bps_bo));
|
||||
|
||||
kfree(data->bps);
|
||||
kfree(data->bps_bo);
|
||||
data->bps = new_bps;
|
||||
data->bps_bo = new_bo;
|
||||
data->capacity = (int)align_space;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_virt_init_ras_err_handler_data(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
struct amdgpu_virt_ras_err_handler_data **data = &virt->virt_eh_data;
|
||||
/* GPU will be marked bad on host if bp count more then 10,
|
||||
* so alloc 512 is enough.
|
||||
*/
|
||||
unsigned int align_space = 512;
|
||||
unsigned int align_space = AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_INIT_CAPACITY;
|
||||
void *bps = NULL;
|
||||
struct amdgpu_bo **bps_bo = NULL;
|
||||
|
||||
|
|
@ -302,12 +354,13 @@ static int amdgpu_virt_init_ras_err_handler_data(struct amdgpu_device *adev)
|
|||
if (!bps)
|
||||
goto bps_failure;
|
||||
|
||||
bps_bo = kmalloc_objs(*(*data)->bps_bo, align_space);
|
||||
bps_bo = kcalloc(align_space, sizeof(*(*data)->bps_bo), GFP_KERNEL);
|
||||
if (!bps_bo)
|
||||
goto bps_bo_failure;
|
||||
|
||||
(*data)->bps = bps;
|
||||
(*data)->bps_bo = bps_bo;
|
||||
(*data)->capacity = align_space;
|
||||
(*data)->count = 0;
|
||||
(*data)->last_reserved = 0;
|
||||
|
||||
|
|
@ -361,17 +414,33 @@ void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev)
|
|||
virt->virt_eh_data = NULL;
|
||||
}
|
||||
|
||||
static void amdgpu_virt_ras_add_bps(struct amdgpu_device *adev,
|
||||
struct eeprom_table_record *bps, int pages)
|
||||
static bool amdgpu_virt_ras_add_bps(struct amdgpu_device *adev,
|
||||
const struct eeprom_table_record *bps, int pages)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
struct amdgpu_virt_ras_err_handler_data *data = virt->virt_eh_data;
|
||||
int need;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
if (!data || pages <= 0)
|
||||
return false;
|
||||
|
||||
if (pages > AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY - data->count) {
|
||||
dev_warn_ratelimited(adev->dev,
|
||||
"RAS WARN: bad page table at capacity (count=%d pages=%d max=%u)\n",
|
||||
data->count, pages,
|
||||
AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY);
|
||||
return false;
|
||||
}
|
||||
|
||||
need = data->count + pages;
|
||||
if (need > data->capacity &&
|
||||
amdgpu_virt_ras_realloc_eh_data_space(adev, data, need - data->capacity))
|
||||
return false;
|
||||
|
||||
memcpy(&data->bps[data->count], bps, pages * sizeof(*data->bps));
|
||||
data->count += pages;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void amdgpu_virt_ras_reserve_bps(struct amdgpu_device *adev)
|
||||
|
|
@ -443,20 +512,22 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev,
|
|||
|
||||
memset(&bp, 0, sizeof(bp));
|
||||
|
||||
if (bp_block_size) {
|
||||
bp_cnt = bp_block_size / sizeof(uint64_t);
|
||||
for (bp_idx = 0; bp_idx < bp_cnt; bp_idx++) {
|
||||
retired_page = *(uint64_t *)(vram_usage_va +
|
||||
bp_block_offset + bp_idx * sizeof(uint64_t));
|
||||
bp.retired_page = retired_page;
|
||||
if (!bp_block_size)
|
||||
return;
|
||||
|
||||
if (amdgpu_virt_ras_check_bad_page(adev, retired_page))
|
||||
continue;
|
||||
bp_cnt = bp_block_size / sizeof(uint64_t);
|
||||
for (bp_idx = 0; bp_idx < bp_cnt; bp_idx++) {
|
||||
retired_page = *(uint64_t *)(vram_usage_va +
|
||||
bp_block_offset + bp_idx * sizeof(uint64_t));
|
||||
bp.retired_page = retired_page;
|
||||
|
||||
amdgpu_virt_ras_add_bps(adev, &bp, 1);
|
||||
if (amdgpu_virt_ras_check_bad_page(adev, retired_page))
|
||||
continue;
|
||||
|
||||
amdgpu_virt_ras_reserve_bps(adev);
|
||||
}
|
||||
if (!amdgpu_virt_ras_add_bps(adev, &bp, 1))
|
||||
break;
|
||||
|
||||
amdgpu_virt_ras_reserve_bps(adev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ struct amdgpu_virt_ras_err_handler_data {
|
|||
struct eeprom_table_record *bps;
|
||||
/* point to reserved bo array */
|
||||
struct amdgpu_bo **bps_bo;
|
||||
/* number of slots in bps[] / bps_bo[] (always >= count) */
|
||||
int capacity;
|
||||
/* the count of entries */
|
||||
int count;
|
||||
/* last reserved entry's index + 1 */
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ int amdgpu_vm_lock_individual(struct amdgpu_vm *vm, struct drm_exec *exec,
|
|||
amdgpu_bo_ref(bo);
|
||||
spin_unlock(&vm->individual_lock);
|
||||
|
||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 1);
|
||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, num_fences);
|
||||
amdgpu_bo_unref(&bo);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
|
@ -1982,7 +1982,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
|||
* from user space.
|
||||
*/
|
||||
if (unlikely(bo_va->userq_va_mapped))
|
||||
amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr);
|
||||
amdgpu_userq_gem_va_unmap_validate(adev, mapping);
|
||||
|
||||
list_del(&mapping->list);
|
||||
amdgpu_vm_it_remove(mapping, &vm->va);
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ static int vpe_early_init(struct amdgpu_ip_block *ip_block)
|
|||
vpe->collaborate_mode = true;
|
||||
break;
|
||||
case IP_VERSION(2, 0, 0):
|
||||
case IP_VERSION(2, 2, 0):
|
||||
vpe_v2_0_set_funcs(vpe);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ static uint32_t athub_v3_0_get_cg_cntl(struct amdgpu_device *adev)
|
|||
data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1);
|
||||
break;
|
||||
case IP_VERSION(3, 3, 0):
|
||||
case IP_VERSION(3, 4, 2):
|
||||
data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_3_0);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -59,6 +60,7 @@ static void athub_v3_0_set_cg_cntl(struct amdgpu_device *adev, uint32_t data)
|
|||
WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1, data);
|
||||
break;
|
||||
case IP_VERSION(3, 3, 0):
|
||||
case IP_VERSION(3, 4, 2):
|
||||
WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_3_0, data);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -112,6 +114,7 @@ int athub_v3_0_set_clockgating(struct amdgpu_device *adev,
|
|||
case IP_VERSION(3, 0, 1):
|
||||
case IP_VERSION(3, 0, 2):
|
||||
case IP_VERSION(3, 3, 0):
|
||||
case IP_VERSION(3, 4, 2):
|
||||
athub_v3_0_update_medium_grain_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE);
|
||||
athub_v3_0_update_medium_grain_light_sleep(adev,
|
||||
|
|
|
|||
|
|
@ -129,6 +129,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_4_pfp.bin");
|
|||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_me.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_rlc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_me.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_rlc.bin");
|
||||
|
||||
static const struct amdgpu_hwip_reg_entry gc_reg_list_11_0[] = {
|
||||
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS),
|
||||
|
|
@ -1123,6 +1127,7 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
|
|
@ -1606,6 +1611,7 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->gfx.me.num_me = 1;
|
||||
adev->gfx.me.num_pipe_per_me = 1;
|
||||
adev->gfx.me.num_queue_per_pipe = 2;
|
||||
|
|
@ -3078,7 +3084,8 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev)
|
|||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 1) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 2) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 3) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 4))
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 4) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 6))
|
||||
bootload_status = RREG32_SOC15(GC, 0,
|
||||
regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1);
|
||||
else
|
||||
|
|
@ -5721,6 +5728,7 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -5760,6 +5768,7 @@ static int gfx_v11_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
if (!enable)
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
|
||||
|
|
@ -5795,6 +5804,7 @@ static int gfx_v11_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
gfx_v11_0_update_gfx_clock_gating(adev,
|
||||
state == AMD_CG_STATE_GATE);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -4057,8 +4057,6 @@ static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
|
|||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.bad_op_irq, 0);
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ static void gfxhub_v11_5_0_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
@ -449,12 +449,10 @@ static void gfxhub_v11_5_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ static void gfxhub_v12_0_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
@ -454,12 +454,10 @@ static void gfxhub_v12_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -633,19 +633,17 @@ static void gfxhub_v12_1_xcc_set_fault_enable_default(struct amdgpu_device *adev
|
|||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
OTHER_CLIENT_ID_NO_RETRY_FAULT_INTERRUPT, value);
|
||||
if (!value)
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_LO32, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32);
|
||||
if (!value)
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32, tmp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -403,12 +403,10 @@ static void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -516,12 +516,10 @@ static void gfxhub_v1_2_xcc_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,12 +418,10 @@ static void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -449,12 +449,10 @@ static void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ static void gfxhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
@ -446,12 +446,10 @@ static void gfxhub_v3_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ static void gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
@ -434,12 +434,10 @@ static void gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -843,6 +843,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ static void gmc_v11_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 3, 1):
|
||||
case IP_VERSION(3, 3, 2):
|
||||
case IP_VERSION(3, 4, 0):
|
||||
case IP_VERSION(3, 4, 2):
|
||||
adev->mmhub.funcs = &mmhub_v3_3_funcs;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -604,6 +605,7 @@ static void gmc_v11_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->gfxhub.funcs = &gfxhub_v11_5_0_funcs;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -778,6 +780,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
|
||||
set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
|
||||
/*
|
||||
|
|
@ -818,6 +821,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -811,8 +811,9 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev)
|
|||
|
||||
static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
|
||||
int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
uint64_t pte_addr_mask = 0;
|
||||
int i;
|
||||
|
||||
adev->mmhub.funcs->init(adev);
|
||||
|
|
@ -842,6 +843,8 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* block size 512 (9bit)
|
||||
*/
|
||||
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
|
||||
pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
dma_addr_bits = 44;
|
||||
break;
|
||||
case IP_VERSION(12, 1, 0):
|
||||
bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0),
|
||||
|
|
@ -854,9 +857,13 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* block size 512 (9bit)
|
||||
*/
|
||||
amdgpu_vm_adjust_size(adev, 128 * 1024 * 1024, 9, 4, 57);
|
||||
pte_addr_mask = 0x000FFFFFFFFFF000ULL; /* 52 bit PA */
|
||||
dma_addr_bits = 52;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
dev_warn(adev->dev, "Unrecognized GC IP version: 0x%08x\n",
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This interrupt is VMC page fault.*/
|
||||
|
|
@ -910,14 +917,15 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = AMDGPU_GMC_HOLE_MASK;
|
||||
adev->gmc.pte_addr_mask = pte_addr_mask;
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
|
||||
if (r) {
|
||||
drm_warn(adev_to_drm(adev), "No suitable DMA available.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->need_swiotlb = drm_need_swiotlb(44);
|
||||
adev->need_swiotlb = drm_need_swiotlb(dma_addr_bits);
|
||||
|
||||
r = gmc_v12_0_mc_init(adev);
|
||||
if (r)
|
||||
|
|
|
|||
|
|
@ -830,6 +830,7 @@ static int gmc_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
amdgpu_vm_adjust_size(adev, 64, 9, 1, 40);
|
||||
|
||||
adev->gmc.mc_mask = 0xffffffffffULL;
|
||||
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL;
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -1010,6 +1010,7 @@ static int gmc_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -1125,6 +1125,7 @@ static int gmc_v8_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x000000FFFFFFF000ULL; /* 40 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -1983,6 +1983,7 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
|
||||
dma_addr_bits = amdgpu_ip_version(adev, GC_HWIP, 0) >=
|
||||
IP_VERSION(9, 4, 2) ?
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_1_imu.bin");
|
|||
MODULE_FIRMWARE("amdgpu/gc_11_5_2_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_3_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_imu.bin");
|
||||
|
||||
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -467,6 +467,11 @@ static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
|
|||
kfree(queue->userq_prop);
|
||||
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
|
||||
&queue->mqd.cpu_ptr);
|
||||
|
||||
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
|
||||
amdgpu_bo_unpin(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unref(&queue->wptr_obj.obj);
|
||||
}
|
||||
|
||||
static int mes_userq_preempt(struct amdgpu_usermode_queue *queue)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_3_mes_2.bin");
|
|||
MODULE_FIRMWARE("amdgpu/gc_11_5_3_mes1.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_mes_2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_4_mes1.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mes_2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mes1.bin");
|
||||
|
||||
static int mes_v11_0_hw_init(struct amdgpu_ip_block *ip_block);
|
||||
static int mes_v11_0_hw_fini(struct amdgpu_ip_block *ip_block);
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ static void mmhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ static void mmhub_v3_0_1_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ static void mmhub_v3_0_2_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ static void mmhub_v3_3_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
@ -636,6 +636,7 @@ static void mmhub_v3_3_init_client_info(struct amdgpu_device *adev)
|
|||
ARRAY_SIZE(mmhub_client_ids_v3_3_1));
|
||||
break;
|
||||
case IP_VERSION(3, 4, 0):
|
||||
case IP_VERSION(3, 4, 2):
|
||||
amdgpu_mmhub_init_client_info(&adev->mmhub,
|
||||
mmhub_client_ids_v3_4,
|
||||
ARRAY_SIZE(mmhub_client_ids_v3_4));
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ static void mmhub_v4_1_0_setup_vmid_config(struct amdgpu_device *adev)
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ static void mmhub_v4_2_0_mid_setup_vmid_config(struct amdgpu_device *adev,
|
|||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
!adev->gmc.noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, GET_INST(MMHUB, j), regMMVM_CONTEXT1_CNTL,
|
||||
i * hub->ctx_distance, tmp);
|
||||
WREG32_SOC15_OFFSET(MMHUB, GET_INST(MMHUB, j), regMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
|
||||
|
|
|
|||
|
|
@ -57,12 +57,50 @@
|
|||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
|
||||
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5 0x8e13
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_HIGH_nbio_7_11_5_BASE_IDX 5
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5 0x8e14
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_BASE_LOW_nbio_7_11_5_BASE_IDX 5
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5 0x8e15
|
||||
#define regBIF_BX_PF0_DOORBELL_SELFRING_GPA_APER_CNTL_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5 0x8e4d
|
||||
#define regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
|
||||
#define regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5 0x8e4e
|
||||
#define regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5 0xd000
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regBIF_BX0_BIF_FB_EN_nbio_7_11_5 0x8e20
|
||||
#define regBIF_BX0_BIF_FB_EN_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5 0x8e11
|
||||
#define regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5_BASE_IDX 5
|
||||
#define regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5 0x8e12
|
||||
#define regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5 0x8e26
|
||||
#define regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5_BASE_IDX 5
|
||||
#define regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5 0x8e27
|
||||
#define regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
#define regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5 0x8e17
|
||||
#define regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5_BASE_IDX 5
|
||||
|
||||
static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5)) {
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL_nbio_7_11_5,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL_nbio_7_11_5,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
|
||||
} else {
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL,
|
||||
adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
|
||||
|
|
@ -71,6 +109,8 @@ static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
|
|||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10);
|
||||
else if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbio_7_11_5);
|
||||
else
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
|
||||
|
|
@ -82,12 +122,21 @@ static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
|
|||
|
||||
static void nbif_v6_3_1_mc_access_enable(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN,
|
||||
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5)) {
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_nbio_7_11_5,
|
||||
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_nbio_7_11_5, 0);
|
||||
} else {
|
||||
if (enable)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN,
|
||||
BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK |
|
||||
BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 nbif_v6_3_1_get_memsize(struct amdgpu_device *adev)
|
||||
|
|
@ -100,8 +149,14 @@ static void nbif_v6_3_1_sdma_doorbell_range(struct amdgpu_device *adev,
|
|||
int doorbell_index,
|
||||
int doorbell_size)
|
||||
{
|
||||
u32 doorbell_range;
|
||||
if (instance == 0) {
|
||||
u32 doorbell_range = RREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
doorbell_range = RREG32_SOC15(NBIO, 0,
|
||||
regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10);
|
||||
else
|
||||
doorbell_range = RREG32_SOC15(NBIO, 0,
|
||||
regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL);
|
||||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range,
|
||||
|
|
@ -130,11 +185,10 @@ static void nbif_v6_3_1_sdma_doorbell_range(struct amdgpu_device *adev,
|
|||
S2A_DOORBELL_PORT2_RANGE_SIZE,
|
||||
0);
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4)) {
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL_nbif_4_10, doorbell_range);
|
||||
} else {
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, doorbell_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,14 +233,15 @@ static void nbif_v6_3_1_vcn_doorbell_range(struct amdgpu_device *adev,
|
|||
S2A_DOORBELL_PORT4_RANGE_SIZE,
|
||||
0);
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4)) {
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10, doorbell_range);
|
||||
} else {
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
WREG32_SOC15(NBIO, 0,
|
||||
regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL_nbif_4_10,
|
||||
doorbell_range);
|
||||
else
|
||||
if (instance)
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL, doorbell_range);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL, doorbell_range);
|
||||
}
|
||||
}
|
||||
|
||||
static void nbif_v6_3_1_vpe_doorbell_range(struct amdgpu_device *adev,
|
||||
|
|
@ -227,16 +282,18 @@ static void nbif_v6_3_1_vpe_doorbell_range(struct amdgpu_device *adev,
|
|||
0);
|
||||
}
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4) ||
|
||||
amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5)) {
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10, doorbell_range);
|
||||
else
|
||||
} else {
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL, doorbell_range);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void nbif_v6_3_1_gc_doorbell_init(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4)) {
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4)) {
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL_nbif_4_10, 0x30000007);
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL_nbif_4_10, 0x3000000d);
|
||||
} else {
|
||||
|
|
@ -278,7 +335,13 @@ nbif_v6_3_1_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
|
|||
static void nbif_v6_3_1_ih_doorbell_range(struct amdgpu_device *adev,
|
||||
bool use_doorbell, int doorbell_index)
|
||||
{
|
||||
u32 ih_doorbell_range = RREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL);
|
||||
u32 ih_doorbell_range;
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
ih_doorbell_range = RREG32_SOC15(NBIO, 0,
|
||||
regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10);
|
||||
else
|
||||
ih_doorbell_range = RREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL);
|
||||
|
||||
if (use_doorbell) {
|
||||
ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
|
||||
|
|
@ -307,11 +370,11 @@ static void nbif_v6_3_1_ih_doorbell_range(struct amdgpu_device *adev,
|
|||
S2A_DOORBELL_PORT1_RANGE_SIZE,
|
||||
0);
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4)) {
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10, ih_doorbell_range);
|
||||
} else {
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL_nbif_4_10,
|
||||
ih_doorbell_range);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, ih_doorbell_range);
|
||||
}
|
||||
}
|
||||
|
||||
static void nbif_v6_3_1_ih_control(struct amdgpu_device *adev)
|
||||
|
|
@ -319,9 +382,13 @@ static void nbif_v6_3_1_ih_control(struct amdgpu_device *adev)
|
|||
u32 interrupt_cntl;
|
||||
|
||||
/* setup interrupt control */
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2_nbio_7_11_5,
|
||||
adev->dummy_page_addr >> 8);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
|
||||
|
||||
interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL);
|
||||
interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5);
|
||||
/*
|
||||
* BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi
|
||||
* BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN
|
||||
|
|
@ -333,7 +400,10 @@ static void nbif_v6_3_1_ih_control(struct amdgpu_device *adev)
|
|||
interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX0_INTERRUPT_CNTL,
|
||||
IH_REQ_NONSNOOP_EN, 0);
|
||||
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL, interrupt_cntl);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL_nbio_7_11_5, interrupt_cntl);
|
||||
else
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL, interrupt_cntl);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -356,27 +426,31 @@ nbif_v6_3_1_get_clockgating_state(struct amdgpu_device *adev,
|
|||
|
||||
static u32 nbif_v6_3_1_get_hdp_flush_req_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_REQ);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_REQ_nbio_7_11_5);
|
||||
else
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_REQ);
|
||||
}
|
||||
|
||||
static u32 nbif_v6_3_1_get_hdp_flush_done_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_DONE);
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_DONE_nbio_7_11_5);
|
||||
else
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_GPU_HDP_FLUSH_DONE);
|
||||
}
|
||||
|
||||
static u32 nbif_v6_3_1_get_pcie_index_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4)) {
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_INDEX);
|
||||
}
|
||||
else {
|
||||
else
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_RSMU_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 nbif_v6_3_1_get_pcie_data_offset(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) >= IP_VERSION(7, 11, 4))
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_DATA);
|
||||
else
|
||||
return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX_PF0_RSMU_DATA);
|
||||
|
|
@ -546,8 +620,12 @@ static void nbif_v6_3_1_set_reg_remap(struct amdgpu_device *adev)
|
|||
adev->rmmio_remap.reg_offset = MMIO_REG_HOLE_OFFSET;
|
||||
adev->rmmio_remap.bus_addr = adev->rmmio_base + MMIO_REG_HOLE_OFFSET;
|
||||
} else {
|
||||
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
|
||||
regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 5))
|
||||
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
|
||||
regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL_nbio_7_11_5) << 2;
|
||||
else
|
||||
adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
|
||||
regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;
|
||||
adev->rmmio_remap.bus_addr = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ MODULE_FIRMWARE("amdgpu/sdma_6_1_1.bin");
|
|||
MODULE_FIRMWARE("amdgpu/sdma_6_1_2.bin");
|
||||
MODULE_FIRMWARE("amdgpu/sdma_6_1_3.bin");
|
||||
MODULE_FIRMWARE("amdgpu/sdma_6_1_4.bin");
|
||||
MODULE_FIRMWARE("amdgpu/sdma_6_4_0.bin");
|
||||
|
||||
#define SDMA1_REG_OFFSET 0x600
|
||||
#define SDMA0_HYP_DEC_REG_START 0x5880
|
||||
|
|
|
|||
|
|
@ -1315,6 +1315,7 @@ static int sdma_v7_1_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
ring->ring_obj = NULL;
|
||||
ring->use_doorbell = true;
|
||||
ring->me = i;
|
||||
ring->no_user_submission = adev->sdma.no_user_submission;
|
||||
|
||||
for (xcc_id = 0; xcc_id < fls(adev->gfx.xcc_mask); xcc_id++) {
|
||||
if (adev->sdma.instance[i].xcc_id == GET_INST(GC, xcc_id))
|
||||
|
|
|
|||
|
|
@ -833,6 +833,11 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
|
|||
AMD_PG_SUPPORT_GFX_PG;
|
||||
adev->external_rev_id = adev->rev_id + 0x1;
|
||||
break;
|
||||
case IP_VERSION(11, 5, 6):
|
||||
adev->cg_flags = 0;
|
||||
adev->pg_flags = 0;
|
||||
adev->external_rev_id = adev->rev_id + 0xd0;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "vpe/vpe_2_0_0_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/vpe_2_0_0.bin");
|
||||
MODULE_FIRMWARE("amdgpu/vpe_2_2_0.bin");
|
||||
|
||||
#define VPE_THREAD1_UCODE_OFFSET 0x8000
|
||||
|
||||
|
|
|
|||
|
|
@ -1706,6 +1706,7 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
/* Cacheline size not available in IP discovery for gc11.
|
||||
* kfd_fill_gpu_cache_info_from_gfx_config to hard code it
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
|
|||
case IP_VERSION(6, 1, 2):
|
||||
case IP_VERSION(6, 1, 3):
|
||||
case IP_VERSION(6, 1, 4):
|
||||
case IP_VERSION(6, 4, 0):
|
||||
case IP_VERSION(7, 0, 0):
|
||||
case IP_VERSION(7, 0, 1):
|
||||
case IP_VERSION(7, 1, 0):
|
||||
|
|
@ -167,6 +168,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
|
|||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
kfd->device_info.event_interrupt_class = &event_interrupt_class_v11;
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
|
|
@ -445,6 +447,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
|
|||
f2g = &gfx_v11_kfd2kgd;
|
||||
break;
|
||||
case IP_VERSION(11, 5, 4):
|
||||
case IP_VERSION(11, 5, 6):
|
||||
gfx_target_version = 110504;
|
||||
f2g = &gfx_v11_kfd2kgd;
|
||||
break;
|
||||
|
|
@ -736,6 +739,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
|||
int partition_mode;
|
||||
int xcp_idx;
|
||||
|
||||
kfd->profiler_process = NULL;
|
||||
mutex_init(&kfd->profiler_lock);
|
||||
|
||||
kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
|
||||
KGD_ENGINE_MEC1);
|
||||
kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
|
||||
|
|
@ -936,9 +942,6 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
|||
|
||||
svm_range_set_max_pages(kfd->adev);
|
||||
|
||||
kfd->profiler_process = NULL;
|
||||
mutex_init(&kfd->profiler_lock);
|
||||
|
||||
kfd->init_complete = true;
|
||||
dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor,
|
||||
kfd->adev->pdev->device);
|
||||
|
|
|
|||
|
|
@ -2669,6 +2669,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
|
|||
if (pdd->qpd.is_debug)
|
||||
return ret;
|
||||
|
||||
if (q->properties.is_being_destroyed)
|
||||
return -EBUSY;
|
||||
|
||||
q->properties.is_being_destroyed = true;
|
||||
|
||||
if (pdd->process->debug_trap_enabled && q->properties.is_suspended) {
|
||||
|
|
@ -2681,6 +2684,9 @@ static int wait_on_destroy_queue(struct device_queue_manager *dqm,
|
|||
dqm_lock(dqm);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
q->properties.is_being_destroyed = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2774,7 +2780,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
|
|||
return retval;
|
||||
|
||||
failed_try_destroy_debugged_queue:
|
||||
|
||||
q->properties.is_being_destroyed = false;
|
||||
dqm_unlock(dqm);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -3478,7 +3484,7 @@ static void copy_context_work_handler(struct work_struct *work)
|
|||
static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
|
||||
{
|
||||
if (!usr_queue_id_array)
|
||||
return NULL;
|
||||
return num_queues ? ERR_PTR(-EINVAL) : NULL;
|
||||
|
||||
if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
|
|||
|
|
@ -330,8 +330,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
|
|||
|
||||
static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
struct queue_properties *qp, const void *mqd_src,
|
||||
const void *ctl_stack_src, const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
|
|
@ -347,14 +346,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
|||
*gart_addr = addr;
|
||||
|
||||
m->cp_hqd_pq_doorbell_control =
|
||||
qp->doorbell_off <<
|
||||
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
|
||||
m->cp_hqd_pq_doorbell_control);
|
||||
qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control);
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void checkpoint_mqd_sdma(struct mqd_manager *mm,
|
||||
void *mqd,
|
||||
void *mqd_dst,
|
||||
void *ctl_stack_dst)
|
||||
{
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
|
||||
memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd));
|
||||
}
|
||||
|
||||
static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
const void *ctl_stack_src,
|
||||
const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
|
||||
addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
memcpy(m, mqd_src, sizeof(*m));
|
||||
|
||||
m->sdmax_rlcx_doorbell_offset =
|
||||
qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
|
||||
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
|
|
@ -539,8 +572,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
|
|||
mqd->update_mqd = update_mqd_sdma;
|
||||
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
|
||||
mqd->is_occupied = kfd_is_occupied_sdma;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd;
|
||||
mqd->restore_mqd = restore_mqd;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
|
||||
mqd->restore_mqd = restore_mqd_sdma;
|
||||
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
|
||||
mqd->mqd_stride = kfd_mqd_stride;
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev)
|
|||
{
|
||||
struct platform_device *pdev;
|
||||
struct xcp_device *pxcp_dev;
|
||||
char dev_name[20];
|
||||
char *dev_name;
|
||||
int ret, i;
|
||||
|
||||
guard(mutex)(&xcp_mutex);
|
||||
|
|
@ -68,8 +69,12 @@ int amdgpu_xcp_drm_dev_alloc(struct drm_device **ddev)
|
|||
if (i >= MAX_XCP_PLATFORM_DEVICE)
|
||||
return -ENODEV;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), "amdgpu_xcp_%d", i);
|
||||
dev_name = kasprintf(GFP_KERNEL, "amdgpu_xcp_%d", i);
|
||||
if (!dev_name)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev = platform_device_register_simple(dev_name, -1, NULL, 0);
|
||||
kfree(dev_name);
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ config DRM_AMD_SECURE_DISPLAY
|
|||
|
||||
config DRM_AMD_DC_KUNIT_TEST
|
||||
tristate "KUnit tests for the AMD DC display driver" if !KUNIT_ALL_TESTS
|
||||
depends on DRM_AMD_DC && KUNIT && DEBUG_FS
|
||||
depends on DRM_AMD_DC && KUNIT && DEBUG_FS && DRM_KUNIT_TEST_HELPERS
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This option enables KUnit tests for the AMD Display Core driver.
|
||||
|
|
|
|||
|
|
@ -63,4 +63,7 @@ endif
|
|||
# KUnit tests as separate module
|
||||
ifneq ($(CONFIG_DRM_AMD_DC_KUNIT_TEST),)
|
||||
obj-y += $(AMDDALPATH)/amdgpu_dm/tests/
|
||||
|
||||
# Enable gcov for amdgpu_dm KUnit builds
|
||||
GCOV_PROFILE := y
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -158,6 +158,9 @@ MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
|
|||
#define FIRMWARE_DCN_42_DMUB "amdgpu/dcn_4_2_dmcub.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
|
||||
|
||||
#define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
|
|
@ -1375,6 +1378,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 5, 1):
|
||||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
hw_params.ips_sequential_ono = adev->external_rev_id > 0x10;
|
||||
hw_params.lower_hbr3_phy_ssc = true;
|
||||
break;
|
||||
|
|
@ -1823,6 +1827,7 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
|
|||
bb_size = sizeof(struct dml2_soc_bb);
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
bb_size = sizeof(struct dml2_soc_bb);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1870,6 +1875,7 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode(
|
|||
ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
ret = DMUB_IPS_ENABLE;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1946,6 +1952,40 @@ static int amdgpu_dm_init_power_module(struct amdgpu_display_manager *dm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void hdmi_frl_status_polling_work(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_display_manager *dm =
|
||||
container_of(to_delayed_work(work), struct amdgpu_display_manager,
|
||||
hdmi_frl_status_polling_work);
|
||||
struct dc *dc = dm->dc;
|
||||
struct dc_link *dc_link;
|
||||
bool link_update = false;
|
||||
|
||||
for (int i = 0; i < MAX_LINKS; i++) {
|
||||
dc_link = dc->links[i];
|
||||
|
||||
if (!dc_link || !dc_link->local_sink)
|
||||
continue;
|
||||
|
||||
if (!dc_is_hdmi_signal(dc_link->connector_signal))
|
||||
continue;
|
||||
|
||||
if (dc_link->connector_signal != SIGNAL_TYPE_HDMI_FRL)
|
||||
continue;
|
||||
|
||||
link_update = dc_link_frl_poll_status_flag(dc_link);
|
||||
if (link_update) {
|
||||
mutex_lock(&dm->dc_lock);
|
||||
dc_link_detect(dc_link, DETECT_REASON_RETRAIN);
|
||||
mutex_unlock(&dm->dc_lock);
|
||||
}
|
||||
}
|
||||
|
||||
queue_delayed_work(dm->hdmi_frl_status_polling_wq,
|
||||
&dm->hdmi_frl_status_polling_work,
|
||||
msecs_to_jiffies(dm->hdmi_frl_status_polling_delay_ms));
|
||||
}
|
||||
|
||||
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dc_init_data init_data;
|
||||
|
|
@ -2050,6 +2090,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_dc_feature_mask & DC_DISABLE_LTTPR_DP2_0)
|
||||
init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true;
|
||||
|
||||
if (amdgpu_dc_feature_mask & DC_FRL_MASK)
|
||||
init_data.flags.enable_frl = true;
|
||||
|
||||
init_data.flags.seamless_boot_edp_requested = false;
|
||||
|
||||
if (amdgpu_device_seamless_boot_supported(adev)) {
|
||||
|
|
@ -2217,6 +2260,14 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
|
||||
dc_init_callbacks(adev->dm.dc, &init_params);
|
||||
}
|
||||
if (adev->dm.dc->caps.max_links > 0) {
|
||||
adev->dm.hdmi_frl_status_polling_wq =
|
||||
create_singlethread_workqueue("hdmi_frl_status_polling_workqueue");
|
||||
if (!adev->dm.hdmi_frl_status_polling_wq)
|
||||
drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_workqueue\n");
|
||||
adev->dm.hdmi_frl_status_polling_delay_ms = 200;
|
||||
INIT_DELAYED_WORK(&adev->dm.hdmi_frl_status_polling_work, hdmi_frl_status_polling_work);
|
||||
}
|
||||
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
|
||||
init_completion(&adev->dm.dmub_aux_transfer_done);
|
||||
adev->dm.dmub_notify = kzalloc_obj(struct dmub_notification);
|
||||
|
|
@ -2483,6 +2534,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 0, 1):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -2621,6 +2673,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|||
case IP_VERSION(4, 2, 0):
|
||||
dmub_asic = DMUB_ASIC_DCN42;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 1):
|
||||
dmub_asic = DMUB_ASIC_DCN42B;
|
||||
break;
|
||||
default:
|
||||
/* ASIC doesn't support DMUB. */
|
||||
return 0;
|
||||
|
|
@ -5741,6 +5796,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 0, 1):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
if (register_outbox_irq_handlers(dm->adev)) {
|
||||
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
|
||||
goto fail;
|
||||
|
|
@ -5766,6 +5822,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 0, 1):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
psr_feature_enabled = true;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -5784,6 +5841,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 5, 1):
|
||||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
replay_feature_enabled = true;
|
||||
break;
|
||||
|
||||
|
|
@ -5945,6 +6003,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 0, 1):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
if (dcn10_register_irq_handlers(dm->adev)) {
|
||||
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
|
||||
goto fail;
|
||||
|
|
@ -6096,6 +6155,9 @@ static int dm_init_microcode(struct amdgpu_device *adev)
|
|||
case IP_VERSION(4, 2, 0):
|
||||
fw_name_dmub = FIRMWARE_DCN_42_DMUB;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 1):
|
||||
fw_name_dmub = FIRMWARE_DCN_42B_DMUB;
|
||||
break;
|
||||
default:
|
||||
/* ASIC doesn't support DMUB. */
|
||||
return 0;
|
||||
|
|
@ -6224,6 +6286,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block)
|
|||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 0, 1):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
case IP_VERSION(4, 2, 1):
|
||||
adev->mode_info.num_crtc = 4;
|
||||
adev->mode_info.num_hpd = 4;
|
||||
adev->mode_info.num_dig = 4;
|
||||
|
|
@ -6918,18 +6981,26 @@ static void fill_stream_properties_from_drm_display_mode(
|
|||
timing_out->v_border_bottom = 0;
|
||||
/* TODO: un-hardcode */
|
||||
if (drm_mode_is_420_only(info, mode_in)
|
||||
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
&& (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
stream->signal == SIGNAL_TYPE_HDMI_FRL)
|
||||
&& aconnector
|
||||
&& aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420)
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
|
||||
else if (drm_mode_is_420_also(info, mode_in)
|
||||
&& aconnector
|
||||
&& aconnector->force_yuv420_output)
|
||||
&& (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420
|
||||
|| aconnector->force_yuv420_output))
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
|
||||
else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
|
||||
&& aconnector
|
||||
&& aconnector->force_yuv422_output)
|
||||
&& (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR422
|
||||
|| aconnector->force_yuv422_output))
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
|
||||
else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
|
||||
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
&& (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
stream->signal == SIGNAL_TYPE_HDMI_FRL)
|
||||
&& aconnector
|
||||
&& aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR444)
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
|
||||
else
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
|
||||
|
|
@ -6954,7 +7025,8 @@ static void fill_stream_properties_from_drm_display_mode(
|
|||
timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
|
||||
}
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
stream->signal == SIGNAL_TYPE_HDMI_FRL) {
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame,
|
||||
(struct drm_connector *)connector,
|
||||
mode_in);
|
||||
|
|
@ -7299,12 +7371,30 @@ static void update_dsc_caps(struct amdgpu_dm_connector *aconnector,
|
|||
|
||||
if (aconnector->dc_link && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
sink->sink_signal == SIGNAL_TYPE_EDP)) {
|
||||
if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE ||
|
||||
sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
|
||||
if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE)
|
||||
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
|
||||
dsc_caps);
|
||||
else if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
|
||||
if (aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT &&
|
||||
!aconnector->dsc_settings.dsc_force_disable_passthrough &&
|
||||
aconnector->dc_link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0 &&
|
||||
sink->edid_caps.frl_dsc_support &&
|
||||
sink->edid_caps.max_frl_rate > 0 &&
|
||||
sink->edid_caps.frl_dsc_max_frl_rate > 0)
|
||||
dc_dsc_parse_dsc_edid(aconnector->dc_link->ctx->dc, &sink->edid_caps, dsc_caps);
|
||||
else
|
||||
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
|
||||
dsc_caps);
|
||||
}
|
||||
} else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL) {
|
||||
if (sink->edid_caps.frl_dsc_support &&
|
||||
sink->edid_caps.max_frl_rate > 0 &&
|
||||
sink->edid_caps.frl_dsc_max_frl_rate > 0)
|
||||
dc_dsc_parse_dsc_edid(aconnector->dc_link->ctx->dc, &sink->edid_caps, dsc_caps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7378,6 +7468,10 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
|
|||
struct drm_connector *drm_connector = &aconnector->base;
|
||||
u32 link_bandwidth_kbps;
|
||||
struct dc *dc = sink->ctx->dc;
|
||||
const struct dc_hdmi_frl_link_settings *frl_verified_link_cap = NULL;
|
||||
u32 converter_bw_in_kbps;
|
||||
u32 sink_bw_in_kbps;
|
||||
u32 dsc_sink_bw_in_kbps;
|
||||
u32 max_supported_bw_in_kbps, timing_bw_in_kbps;
|
||||
u32 dsc_max_supported_bw_in_kbps;
|
||||
u32 max_dsc_target_bpp_limit_override =
|
||||
|
|
@ -7416,8 +7510,18 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
|
|||
} else if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
|
||||
timing_bw_in_kbps = dc_bandwidth_in_kbps_from_timing(&stream->timing,
|
||||
dc_link_get_highest_encoding_format(aconnector->dc_link));
|
||||
max_supported_bw_in_kbps = link_bandwidth_kbps;
|
||||
dsc_max_supported_bw_in_kbps = link_bandwidth_kbps;
|
||||
converter_bw_in_kbps = aconnector->dc_link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps;
|
||||
sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.max_frl_rate);
|
||||
dsc_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.frl_dsc_max_frl_rate);
|
||||
|
||||
if (dsc_caps->is_frl) {
|
||||
max_supported_bw_in_kbps = min(link_bandwidth_kbps, converter_bw_in_kbps);
|
||||
max_supported_bw_in_kbps = min(max_supported_bw_in_kbps, sink_bw_in_kbps);
|
||||
dsc_max_supported_bw_in_kbps = min(max_supported_bw_in_kbps, dsc_sink_bw_in_kbps);
|
||||
} else {
|
||||
max_supported_bw_in_kbps = link_bandwidth_kbps;
|
||||
dsc_max_supported_bw_in_kbps = link_bandwidth_kbps;
|
||||
}
|
||||
|
||||
if (timing_bw_in_kbps > max_supported_bw_in_kbps &&
|
||||
max_supported_bw_in_kbps > 0 &&
|
||||
|
|
@ -7430,11 +7534,41 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
|
|||
dc_link_get_highest_encoding_format(aconnector->dc_link),
|
||||
&stream->timing.dsc_cfg)) {
|
||||
stream->timing.flags.DSC = 1;
|
||||
drm_dbg_driver(drm_connector->dev, "%s: SST_DSC [%s] DSC is selected from DP-HDMI PCON\n",
|
||||
__func__, drm_connector->name);
|
||||
drm_dbg_driver(drm_connector->dev, "%s: SST_DSC [%s] DSC is selected from %s\n",
|
||||
__func__, drm_connector->name,
|
||||
(dsc_caps->is_frl == 1) ? "HDMI FRL RX" : "DP-HDMI PCON");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL) {
|
||||
struct dc_dsc_policy dsc_policy = {0};
|
||||
|
||||
frl_verified_link_cap = dc_link_get_frl_link_cap(stream->link);
|
||||
if (frl_verified_link_cap->frl_link_rate != HDMI_FRL_LINK_RATE_DISABLE &&
|
||||
aconnector->dc_link->frl_flags.force_frl_dsc) {
|
||||
dc_dsc_policy_set_enable_dsc_when_not_needed(true);
|
||||
dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy, dc_link_get_highest_encoding_format(stream->link));
|
||||
}
|
||||
|
||||
timing_bw_in_kbps = dc_bandwidth_in_kbps_from_timing(&stream->timing, DC_LINK_ENCODING_HDMI_FRL);
|
||||
link_bandwidth_kbps = dc_link_frl_bandwidth_kbps(stream->link, frl_verified_link_cap->frl_link_rate);
|
||||
dsc_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(dc, sink->edid_caps.frl_dsc_max_frl_rate);
|
||||
|
||||
if ((timing_bw_in_kbps > link_bandwidth_kbps && dsc_sink_bw_in_kbps > 0) ||
|
||||
(dsc_policy.enable_dsc_when_not_needed || dsc_options.force_dsc_when_not_needed)) {
|
||||
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
|
||||
dsc_caps,
|
||||
&dsc_options,
|
||||
dsc_sink_bw_in_kbps,
|
||||
&stream->timing,
|
||||
dc_link_get_highest_encoding_format(aconnector->dc_link),
|
||||
&stream->timing.dsc_cfg)) {
|
||||
stream->timing.flags.DSC = 1;
|
||||
drm_dbg_driver(drm_connector->dev, "%s: HDMI_FRL_DSC [%s] DSC is selected from HDMI FRL RX\n",
|
||||
__func__, drm_connector->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Overwrite the stream flag if DSC is enabled through debugfs */
|
||||
if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE)
|
||||
|
|
@ -7601,8 +7735,9 @@ create_stream_for_sink(struct drm_connector *connector,
|
|||
|
||||
update_stream_signal(stream, sink);
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
stream->signal == SIGNAL_TYPE_HDMI_FRL)
|
||||
mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false);
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
|
||||
|
|
@ -8304,6 +8439,7 @@ create_validate_stream_for_sink(struct drm_connector *connector,
|
|||
|
||||
if (aconnector &&
|
||||
(aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_FRL ||
|
||||
aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER))
|
||||
bpc_limit = 8;
|
||||
|
||||
|
|
@ -10871,6 +11007,25 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_commit *state,
|
|||
dc_exit_ips_for_hw_access(dm->dc);
|
||||
WARN_ON(!dc_commit_streams(dm->dc, ¶ms));
|
||||
|
||||
bool frl_stream_found = false;
|
||||
|
||||
for (i = 0; i < params.stream_count; i++) {
|
||||
struct dc_stream_state *stream = params.streams[i];
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_FRL) {
|
||||
frl_stream_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (frl_stream_found) {
|
||||
if (queue_delayed_work(dm->hdmi_frl_status_polling_wq,
|
||||
&dm->hdmi_frl_status_polling_work,
|
||||
msecs_to_jiffies(dm->hdmi_frl_status_polling_delay_ms)))
|
||||
drm_dbg_kms(dev, "200ms frl status polling starts ...\n");
|
||||
} else {
|
||||
if (cancel_delayed_work_sync(&dm->hdmi_frl_status_polling_work))
|
||||
drm_dbg_kms(dev, "200ms frl status polling stops ...\n");
|
||||
}
|
||||
/* Allow idle optimization when vblank count is 0 for display off */
|
||||
if ((dm->active_vblank_irq_count == 0) && amdgpu_dm_is_headless(dm->adev))
|
||||
dc_allow_idle_optimizations(dm->dc, true);
|
||||
|
|
@ -12655,7 +12810,8 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
|||
* as previous DCN generations, so enable native mode on DCN401/420
|
||||
*/
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1) ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)) {
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1)) {
|
||||
*cursor_mode = DM_CURSOR_NATIVE_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -13091,9 +13247,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
continue;
|
||||
|
||||
/* Check if rotation or scaling is enabled on DCN401 */
|
||||
if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) &&
|
||||
(amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1))) {
|
||||
if ((drm_plane_mask(crtc->cursor) &
|
||||
new_crtc_state->plane_mask) &&
|
||||
(amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1) ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1))) {
|
||||
new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
|
||||
|
||||
is_rotated = new_cursor_state &&
|
||||
|
|
|
|||
|
|
@ -704,6 +704,14 @@ struct amdgpu_display_manager {
|
|||
struct completion replied;
|
||||
char reply_data[0x40]; // Cannot include dmub_cmd here
|
||||
} fused_io[8];
|
||||
/**
|
||||
* @hdmi_frl_status_polling_work:
|
||||
*
|
||||
* workqueue for 200ms frl status polling
|
||||
*/
|
||||
struct workqueue_struct *hdmi_frl_status_polling_wq;
|
||||
struct delayed_work hdmi_frl_status_polling_work;
|
||||
unsigned int hdmi_frl_status_polling_delay_ms;
|
||||
|
||||
/**
|
||||
* @dm_boot_time_crc_info:
|
||||
|
|
@ -840,6 +848,7 @@ struct amdgpu_dm_connector {
|
|||
bool fake_enable;
|
||||
bool force_yuv420_output;
|
||||
bool force_yuv422_output;
|
||||
uint8_t force_yuv_pixel_format;
|
||||
struct dsc_preferred_settings dsc_settings;
|
||||
struct psr_caps psr_caps;
|
||||
union dp_downstream_port_present mst_downstream_port_present;
|
||||
|
|
@ -850,6 +859,8 @@ struct amdgpu_dm_connector {
|
|||
bool disallow_edp_enter_psr;
|
||||
bool disallow_edp_enter_replay;
|
||||
|
||||
union dwnstream_portxcaps mst_downstream_port_caps;
|
||||
|
||||
/* Record progress status of mst*/
|
||||
uint8_t mst_status;
|
||||
|
||||
|
|
@ -1105,7 +1116,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
|
|||
void amdgpu_dm_update_connector_after_detect(
|
||||
struct amdgpu_dm_connector *aconnector);
|
||||
|
||||
void populate_hdmi_info_from_connector(struct drm_hdmi_info *info,
|
||||
void populate_hdmi_info_from_connector(bool enable_frl, struct drm_hdmi_info *info,
|
||||
struct dc_edid_caps *edid_caps);
|
||||
|
||||
extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
|
||||
|
|
|
|||
|
|
@ -759,8 +759,23 @@ static int __set_output_tf_32(struct dc_transfer_func *func,
|
|||
return res ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
STATIC_IFN_KUNIT void __set_tf_bypass(struct dc_transfer_func *tf)
|
||||
{
|
||||
tf->type = TF_TYPE_BYPASS;
|
||||
tf->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
}
|
||||
EXPORT_IF_KUNIT(__set_tf_bypass);
|
||||
|
||||
static int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
|
||||
STATIC_IFN_KUNIT void __set_tf_distributed_points(struct dc_transfer_func *tf,
|
||||
enum dc_transfer_func_predefined predefined_tf)
|
||||
{
|
||||
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
|
||||
tf->tf = predefined_tf;
|
||||
tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
|
||||
}
|
||||
EXPORT_IF_KUNIT(__set_tf_distributed_points);
|
||||
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
|
||||
const struct drm_color_lut *regamma_lut,
|
||||
uint32_t regamma_size, bool has_rom,
|
||||
enum dc_transfer_func_predefined tf)
|
||||
|
|
@ -779,22 +794,19 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
|
|||
* pre-defined TF and the custom LUT values into the LUT that's
|
||||
* actually programmed.
|
||||
*/
|
||||
out_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
|
||||
out_tf->tf = tf;
|
||||
out_tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
|
||||
|
||||
__set_tf_distributed_points(out_tf, tf);
|
||||
ret = __set_output_tf(out_tf, regamma_lut, regamma_size, has_rom);
|
||||
} else {
|
||||
/*
|
||||
* No CRTC RGM means we can just put the block into bypass
|
||||
* since we don't have any plane level adjustments using it.
|
||||
*/
|
||||
out_tf->type = TF_TYPE_BYPASS;
|
||||
out_tf->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
__set_tf_bypass(out_tf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_set_atomic_regamma);
|
||||
|
||||
/**
|
||||
* __set_input_tf - calculates the input transfer function based on expected
|
||||
|
|
@ -1044,9 +1056,9 @@ EXPORT_IF_KUNIT(__drm_3dlut32_to_dc_3dlut);
|
|||
* Map user 3D LUT data to DC 3D LUT and all necessary bits to program it
|
||||
* on DCN accordingly.
|
||||
*/
|
||||
static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut)
|
||||
STATIC_IFN_KUNIT void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut)
|
||||
{
|
||||
if (!drm_lut3d_size) {
|
||||
lut->state.bits.initialized = 0;
|
||||
|
|
@ -1062,8 +1074,9 @@ static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
|
|||
MAX_COLOR_3DLUT_BITDEPTH);
|
||||
}
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_atomic_lut3d);
|
||||
|
||||
static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
|
||||
bool has_rom,
|
||||
enum dc_transfer_func_predefined tf,
|
||||
uint32_t shaper_size,
|
||||
|
|
@ -1076,20 +1089,17 @@ static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
|
|||
* If user shaper LUT is set, we assume a linear color space
|
||||
* (linearized by degamma 1D LUT or not).
|
||||
*/
|
||||
func_shaper->type = TF_TYPE_DISTRIBUTED_POINTS;
|
||||
func_shaper->tf = tf;
|
||||
func_shaper->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
|
||||
|
||||
__set_tf_distributed_points(func_shaper, tf);
|
||||
ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, has_rom);
|
||||
} else {
|
||||
func_shaper->type = TF_TYPE_BYPASS;
|
||||
func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
__set_tf_bypass(func_shaper);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_atomic_shaper_lut);
|
||||
|
||||
static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
|
||||
bool has_rom,
|
||||
enum dc_transfer_func_predefined tf,
|
||||
uint32_t blend_size,
|
||||
|
|
@ -1105,18 +1115,15 @@ static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
|
|||
* module to fill the parameters that will be translated to HW
|
||||
* points.
|
||||
*/
|
||||
func_blend->type = TF_TYPE_DISTRIBUTED_POINTS;
|
||||
func_blend->tf = tf;
|
||||
func_blend->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
|
||||
|
||||
__set_tf_distributed_points(func_blend, tf);
|
||||
ret = __set_input_tf(NULL, func_blend, blend_lut, blend_size);
|
||||
} else {
|
||||
func_blend->type = TF_TYPE_BYPASS;
|
||||
func_blend->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
__set_tf_bypass(func_blend);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_atomic_blend_lut);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_verify_lut3d_size - verifies if 3D LUT is supported and if user
|
||||
|
|
@ -1198,6 +1205,7 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_verify_lut_sizes);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_check_crtc_color_mgmt: Check if DRM color props are programmable by DC.
|
||||
|
|
@ -1493,7 +1501,7 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
STATIC_IFN_KUNIT int
|
||||
__set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
|
||||
struct drm_colorop_state *colorop_state)
|
||||
{
|
||||
|
|
@ -1508,8 +1516,7 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
|
|||
return -EINVAL;
|
||||
|
||||
if (colorop_state->bypass) {
|
||||
tf->type = TF_TYPE_BYPASS;
|
||||
tf->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
__set_tf_bypass(tf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1520,6 +1527,7 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(__set_colorop_in_tf_1d_curve);
|
||||
|
||||
static int
|
||||
__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
|
||||
|
|
@ -1705,9 +1713,9 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
|
|||
* Returns:
|
||||
* 0 on success. -EINVAL if drm_lut3d_size is zero.
|
||||
*/
|
||||
static int __set_colorop_3dlut(const struct drm_color_lut32 *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut)
|
||||
STATIC_IFN_KUNIT int __set_colorop_3dlut(const struct drm_color_lut32 *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut)
|
||||
{
|
||||
if (!drm_lut3d_size) {
|
||||
lut->state.bits.initialized = 0;
|
||||
|
|
@ -1724,6 +1732,7 @@ static int __set_colorop_3dlut(const struct drm_color_lut32 *drm_lut3d,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(__set_colorop_3dlut);
|
||||
|
||||
static int
|
||||
__set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
|
||||
|
|
|
|||
|
|
@ -36,11 +36,14 @@ struct drm_color_lut;
|
|||
struct drm_color_lut32;
|
||||
struct drm_color_ctm;
|
||||
struct drm_color_ctm_3x4;
|
||||
struct drm_colorop_state;
|
||||
struct drm_property_blob;
|
||||
struct dc_gamma;
|
||||
struct dc_rgb;
|
||||
struct dc_plane_state;
|
||||
struct fixed31_32;
|
||||
struct tetrahedral_params;
|
||||
struct dc_transfer_func;
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
|
||||
/*
|
||||
|
|
@ -84,6 +87,32 @@ void __drm_3dlut32_to_dc_3dlut(const struct drm_color_lut32 *lut,
|
|||
struct tetrahedral_params *params,
|
||||
bool use_tetrahedral_9,
|
||||
int bit_depth);
|
||||
struct dc_3dlut;
|
||||
void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut);
|
||||
int __set_colorop_3dlut(const struct drm_color_lut32 *drm_lut3d,
|
||||
uint32_t drm_lut3d_size,
|
||||
struct dc_3dlut *lut);
|
||||
void __set_tf_bypass(struct dc_transfer_func *tf);
|
||||
void __set_tf_distributed_points(struct dc_transfer_func *tf,
|
||||
enum dc_transfer_func_predefined predefined_tf);
|
||||
int amdgpu_dm_set_atomic_regamma(struct dc_transfer_func *out_tf,
|
||||
const struct drm_color_lut *regamma_lut,
|
||||
uint32_t regamma_size, bool has_rom,
|
||||
enum dc_transfer_func_predefined tf);
|
||||
int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
|
||||
bool has_rom,
|
||||
enum dc_transfer_func_predefined tf,
|
||||
uint32_t shaper_size,
|
||||
struct dc_transfer_func *func_shaper);
|
||||
int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut,
|
||||
bool has_rom,
|
||||
enum dc_transfer_func_predefined tf,
|
||||
uint32_t blend_size,
|
||||
struct dc_transfer_func *func_blend);
|
||||
int __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
|
||||
struct drm_colorop_state *colorop_state);
|
||||
#endif
|
||||
|
||||
#endif /* __AMDGPU_DM_COLOR_H__ */
|
||||
|
|
|
|||
|
|
@ -63,12 +63,11 @@ static const struct drm_colorop_funcs dm_colorop_funcs = {
|
|||
.destroy = drm_colorop_destroy,
|
||||
};
|
||||
|
||||
int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
|
||||
STATIC_IFN_KUNIT int
|
||||
amdgpu_dm_build_default_pipeline(struct drm_device *dev, struct drm_plane *plane,
|
||||
bool hw_3d_lut, struct drm_prop_enum_list *list)
|
||||
{
|
||||
struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
|
||||
int ret;
|
||||
int i = 0;
|
||||
|
||||
|
|
@ -124,7 +123,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
|
|||
|
||||
i++;
|
||||
|
||||
if (has_3dlut) {
|
||||
if (hw_3d_lut) {
|
||||
/* 1D curve - SHAPER TF */
|
||||
ops[i] = kzalloc_obj(*ops[0]);
|
||||
if (!ops[i]) {
|
||||
|
|
@ -219,9 +218,20 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
|
|||
|
||||
cleanup:
|
||||
if (ret == -ENOMEM)
|
||||
drm_err(plane->dev, "KMS: Failed to allocate colorop\n");
|
||||
drm_err(dev, "KMS: Failed to allocate colorop\n");
|
||||
|
||||
drm_colorop_pipeline_destroy(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_build_default_pipeline);
|
||||
|
||||
int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
bool hw_3d_lut = adev->dm.dc->caps.color.dpp.hw_3d_lut ||
|
||||
adev->dm.dc->caps.color.mpc.preblend;
|
||||
|
||||
return amdgpu_dm_build_default_pipeline(dev, plane, hw_3d_lut, list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,4 +33,9 @@ extern const u64 amdgpu_dm_supported_blnd_tfs;
|
|||
|
||||
int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
|
||||
int amdgpu_dm_build_default_pipeline(struct drm_device *dev, struct drm_plane *plane,
|
||||
bool hw_3d_lut, struct drm_prop_enum_list *list);
|
||||
#endif
|
||||
|
||||
#endif /* __AMDGPU_DM_COLOROP_H__*/
|
||||
|
|
|
|||
|
|
@ -1345,8 +1345,13 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b
|
|||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!connector->base.state || !connector->base.state->crtc)
|
||||
return -ENODEV;
|
||||
|
||||
acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
|
||||
|
||||
write_size = min_t(size_t, size, sizeof(data));
|
||||
|
||||
r = copy_from_user(data, buf, write_size);
|
||||
|
||||
write_size -= r;
|
||||
|
|
@ -3137,6 +3142,7 @@ static int force_yuv420_output_set(void *data, u64 val)
|
|||
struct amdgpu_dm_connector *connector = data;
|
||||
|
||||
connector->force_yuv420_output = (bool)val;
|
||||
connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR420;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3156,6 +3162,31 @@ static int force_yuv420_output_get(void *data, u64 *val)
|
|||
DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,
|
||||
force_yuv420_output_set, "%llu\n");
|
||||
|
||||
static int force_yuv422_output_set(void *data, u64 val)
|
||||
{
|
||||
struct amdgpu_dm_connector *connector = data;
|
||||
|
||||
connector->force_yuv422_output = (bool)val;
|
||||
connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(force_yuv422_output_fops, NULL,
|
||||
force_yuv422_output_set, "%llu\n");
|
||||
|
||||
static int force_yuv444_output_set(void *data, u64 val)
|
||||
{
|
||||
struct amdgpu_dm_connector *connector = data;
|
||||
|
||||
connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR444;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(force_yuv444_output_fops, NULL,
|
||||
force_yuv444_output_set, "%llu\n");
|
||||
|
||||
/*
|
||||
* Read Replay state
|
||||
*/
|
||||
|
|
@ -3605,6 +3636,8 @@ static const struct {
|
|||
const struct file_operations *fops;
|
||||
} connector_debugfs_entries[] = {
|
||||
{"force_yuv420_output", &force_yuv420_output_fops},
|
||||
{"force_yuv422_output", &force_yuv422_output_fops},
|
||||
{"force_yuv444_output", &force_yuv444_output_fops},
|
||||
{"trigger_hotplug", &trigger_hotplug_debugfs_fops},
|
||||
{"internal_display", &internal_display_fops},
|
||||
{"odm_combine_segments", &odm_combine_segments_fops}
|
||||
|
|
|
|||
|
|
@ -581,6 +581,8 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
|
|||
link->dp.mst_enabled = config->mst_enabled;
|
||||
link->dp.dp2_enabled = config->dp2_enabled;
|
||||
link->dp.usb4_enabled = config->usb4_enabled;
|
||||
if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
|
||||
link->hdmi.frl_enabled = config->frl_enabled;
|
||||
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
|
||||
link->adjust.auth_delay = 2;
|
||||
link->adjust.retry_limit = MAX_NUM_OF_ATTEMPTS;
|
||||
|
|
|
|||
|
|
@ -178,8 +178,15 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
|
|||
|
||||
edid_caps->edid_hdmi = connector->display_info.is_hdmi;
|
||||
|
||||
if (edid_caps->edid_hdmi)
|
||||
populate_hdmi_info_from_connector(&connector->display_info.hdmi, edid_caps);
|
||||
if (edid_caps->edid_hdmi) {
|
||||
populate_hdmi_info_from_connector(link->dc->config.enable_frl, &connector->display_info.hdmi, edid_caps);
|
||||
drm_dbg_driver(connector->dev, "%s: HDMI_FRL [%s] max_frl_rate %d\n", __func__, connector->name, edid_caps->max_frl_rate);
|
||||
if (edid_caps->frl_dsc_support)
|
||||
drm_dbg_driver(connector->dev, "%s: HDMI_FRL_DSC [%s] frl_dsc_10bpc %d, frl_dsc_12bpc %d, frl_dsc_all_bpp %d, frl_dsc_native_420 %d, frl_dsc_max_slices %d, frl_dsc_max_frl_rate %d, frl_dsc_total_chunk_kbytes %d\n",
|
||||
__func__, connector->name, edid_caps->frl_dsc_10bpc, edid_caps->frl_dsc_12bpc, \
|
||||
edid_caps->frl_dsc_all_bpp, edid_caps->frl_dsc_native_420, edid_caps->frl_dsc_max_slices, \
|
||||
edid_caps->frl_dsc_max_frl_rate, edid_caps->frl_dsc_total_chunk_kbytes);
|
||||
}
|
||||
|
||||
apply_edid_quirks(dev, edid_buf, edid_caps);
|
||||
|
||||
|
|
@ -1071,9 +1078,70 @@ dm_helpers_read_vbios_hardcoded_edid(struct dc_link *link, struct amdgpu_dm_conn
|
|||
return edid;
|
||||
}
|
||||
|
||||
void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps)
|
||||
static uint8_t get_max_frl_rate(uint8_t max_lanes, uint8_t max_rate_per_lane)
|
||||
{
|
||||
uint8_t max_frl_rate;
|
||||
|
||||
if ((max_lanes == 3) && (max_rate_per_lane == 3))
|
||||
max_frl_rate = 1;
|
||||
else if ((max_lanes == 3) && (max_rate_per_lane == 6))
|
||||
max_frl_rate = 2;
|
||||
else if ((max_lanes == 4) && (max_rate_per_lane == 6))
|
||||
max_frl_rate = 3;
|
||||
else if ((max_lanes == 4) && (max_rate_per_lane == 8))
|
||||
max_frl_rate = 4;
|
||||
else if ((max_lanes == 4) && (max_rate_per_lane == 10))
|
||||
max_frl_rate = 5;
|
||||
else if ((max_lanes == 4) && (max_rate_per_lane == 12))
|
||||
max_frl_rate = 6;
|
||||
else
|
||||
max_frl_rate = 0;
|
||||
|
||||
return max_frl_rate;
|
||||
}
|
||||
|
||||
static uint8_t get_dsc_max_slices(uint8_t max_slices, int clk_per_slice)
|
||||
{
|
||||
uint8_t dsc_max_slices;
|
||||
|
||||
if ((max_slices == 1) && (clk_per_slice == 340))
|
||||
dsc_max_slices = 1;
|
||||
else if ((max_slices == 2) && (clk_per_slice == 340))
|
||||
dsc_max_slices = 2;
|
||||
else if ((max_slices == 4) && (clk_per_slice == 340))
|
||||
dsc_max_slices = 3;
|
||||
else if ((max_slices == 8) && (clk_per_slice == 340))
|
||||
dsc_max_slices = 4;
|
||||
else if ((max_slices == 8) && (clk_per_slice == 400))
|
||||
dsc_max_slices = 5;
|
||||
else if ((max_slices == 12) && (clk_per_slice == 400))
|
||||
dsc_max_slices = 6;
|
||||
else if ((max_slices == 16) && (clk_per_slice == 400))
|
||||
dsc_max_slices = 7;
|
||||
else
|
||||
dsc_max_slices = 0;
|
||||
|
||||
return dsc_max_slices;
|
||||
}
|
||||
|
||||
void populate_hdmi_info_from_connector(bool enable_frl, struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps)
|
||||
{
|
||||
edid_caps->scdc_present = hdmi->scdc.supported;
|
||||
if (enable_frl) {
|
||||
edid_caps->max_frl_rate = get_max_frl_rate(hdmi->max_lanes, hdmi->max_frl_rate_per_lane);
|
||||
edid_caps->frl_dsc_support = hdmi->dsc_cap.v_1p2;
|
||||
if (edid_caps->frl_dsc_support) {
|
||||
if (hdmi->dsc_cap.bpc_supported == 10)
|
||||
edid_caps->frl_dsc_10bpc = true;
|
||||
else if (hdmi->dsc_cap.bpc_supported == 12)
|
||||
edid_caps->frl_dsc_12bpc = true;
|
||||
edid_caps->frl_dsc_all_bpp = hdmi->dsc_cap.all_bpp;
|
||||
edid_caps->frl_dsc_native_420 = hdmi->dsc_cap.native_420;
|
||||
edid_caps->frl_dsc_max_slices = get_dsc_max_slices(hdmi->dsc_cap.max_slices, hdmi->dsc_cap.clk_per_slice);
|
||||
edid_caps->frl_dsc_max_frl_rate = get_max_frl_rate(hdmi->dsc_cap.max_lanes, hdmi->dsc_cap.max_frl_rate_per_lane);
|
||||
edid_caps->frl_dsc_total_chunk_kbytes = hdmi->dsc_cap.total_chunk_kbytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum dc_edid_status dm_helpers_read_local_edid(
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ EXPORT_IF_KUNIT(dm_ism_get_idle_allow_delay);
|
|||
* dm_ism_insert_record - Insert a record into the circular history buffer
|
||||
* @ism: ISM instance
|
||||
*/
|
||||
static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
|
||||
STATIC_IFN_KUNIT
|
||||
void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
|
||||
{
|
||||
struct amdgpu_dm_ism_record *record;
|
||||
|
||||
|
|
@ -245,15 +246,19 @@ static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
|
|||
record->duration_ns =
|
||||
record->timestamp_ns - ism->last_idle_timestamp_ns;
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_ism_insert_record);
|
||||
|
||||
|
||||
static void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism)
|
||||
STATIC_IFN_KUNIT
|
||||
void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism)
|
||||
{
|
||||
ism->last_idle_timestamp_ns = ktime_get_ns();
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_ism_set_last_idle_ts);
|
||||
|
||||
|
||||
static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
|
||||
STATIC_IFN_KUNIT
|
||||
bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
|
||||
enum amdgpu_dm_ism_event event)
|
||||
{
|
||||
enum amdgpu_dm_ism_state next_state;
|
||||
|
|
@ -268,6 +273,7 @@ static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
|
|||
|
||||
return gotNextState;
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_ism_trigger_event);
|
||||
|
||||
|
||||
static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
|
||||
|
|
@ -326,15 +332,36 @@ static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
|
|||
}
|
||||
}
|
||||
|
||||
STATIC_IFN_KUNIT
|
||||
enum amdgpu_dm_ism_event dm_ism_dispatch_next_event(
|
||||
enum amdgpu_dm_ism_state current_state,
|
||||
uint64_t delay_ns,
|
||||
uint64_t sso_delay_ns)
|
||||
{
|
||||
switch (current_state) {
|
||||
case DM_ISM_STATE_HYSTERESIS_WAITING:
|
||||
if (delay_ns == 0)
|
||||
return DM_ISM_EVENT_IMMEDIATE;
|
||||
break;
|
||||
case DM_ISM_STATE_OPTIMIZED_IDLE:
|
||||
if (sso_delay_ns == 0)
|
||||
return DM_ISM_EVENT_IMMEDIATE;
|
||||
break;
|
||||
case DM_ISM_STATE_TIMER_ABORTED:
|
||||
return DM_ISM_EVENT_IMMEDIATE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return DM_ISM_NUM_EVENTS;
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_ism_dispatch_next_event);
|
||||
|
||||
static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
|
||||
struct amdgpu_dm_ism *ism,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
enum amdgpu_dm_ism_event event)
|
||||
struct dm_crtc_state *acrtc_state)
|
||||
{
|
||||
enum amdgpu_dm_ism_event ret = event;
|
||||
const struct amdgpu_dm_ism_config *config = &ism->config;
|
||||
uint64_t delay_ns, sso_delay_ns;
|
||||
uint64_t delay_ns = 0, sso_delay_ns = 0;
|
||||
|
||||
switch (ism->previous_state) {
|
||||
case DM_ISM_STATE_HYSTERESIS_WAITING:
|
||||
|
|
@ -368,30 +395,15 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
|
|||
switch (ism->current_state) {
|
||||
case DM_ISM_STATE_HYSTERESIS_WAITING:
|
||||
dm_ism_set_last_idle_ts(ism);
|
||||
|
||||
/* CRTC can be disabled; allow immediate idle */
|
||||
if (!acrtc_state->stream) {
|
||||
ret = DM_ISM_EVENT_IMMEDIATE;
|
||||
break;
|
||||
}
|
||||
|
||||
delay_ns = dm_ism_get_idle_allow_delay(ism,
|
||||
acrtc_state->stream);
|
||||
if (delay_ns == 0) {
|
||||
ret = DM_ISM_EVENT_IMMEDIATE;
|
||||
break;
|
||||
}
|
||||
|
||||
delay_ns = dm_ism_get_idle_allow_delay(ism, acrtc_state->stream);
|
||||
/* Schedule worker */
|
||||
mod_delayed_work(system_dfl_wq, &ism->delayed_work,
|
||||
nsecs_to_jiffies(delay_ns));
|
||||
|
||||
if (delay_ns > 0)
|
||||
mod_delayed_work(system_dfl_wq, &ism->delayed_work,
|
||||
nsecs_to_jiffies(delay_ns));
|
||||
break;
|
||||
case DM_ISM_STATE_OPTIMIZED_IDLE:
|
||||
sso_delay_ns = dm_ism_get_sso_delay(ism, acrtc_state->stream);
|
||||
if (sso_delay_ns == 0)
|
||||
ret = DM_ISM_EVENT_IMMEDIATE;
|
||||
else if (config->sso_num_frames < config->filter_num_frames) {
|
||||
if (sso_delay_ns > 0) {
|
||||
/*
|
||||
* If sso_num_frames is less than hysteresis frames, it
|
||||
* indicates that allowing idle here, then disallowing
|
||||
|
|
@ -399,13 +411,10 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
|
|||
* have a negative power impact. Skip idle allow here,
|
||||
* and let the sso_delayed_work handle it.
|
||||
*/
|
||||
mod_delayed_work(system_dfl_wq,
|
||||
&ism->sso_delayed_work,
|
||||
nsecs_to_jiffies(sso_delay_ns));
|
||||
} else {
|
||||
/* Enable idle optimization without SSO */
|
||||
dm_ism_commit_idle_optimization_state(
|
||||
ism, acrtc_state->stream, false, false);
|
||||
if (config->sso_num_frames >= config->filter_num_frames)
|
||||
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
|
||||
false, false);
|
||||
|
||||
mod_delayed_work(system_dfl_wq,
|
||||
&ism->sso_delayed_work,
|
||||
nsecs_to_jiffies(sso_delay_ns));
|
||||
|
|
@ -420,13 +429,12 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
|
|||
dm_ism_insert_record(ism);
|
||||
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
|
||||
true, false);
|
||||
ret = DM_ISM_EVENT_IMMEDIATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return dm_ism_dispatch_next_event(ism->current_state, delay_ns, sso_delay_ns);
|
||||
}
|
||||
|
||||
static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
|
||||
|
|
@ -481,8 +489,7 @@ void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
|
|||
dm_ism_states_str[ism->previous_state],
|
||||
dm_ism_states_str[ism->current_state],
|
||||
dm_ism_events_str[event]);
|
||||
next_event = dm_ism_dispatch_power_state(
|
||||
ism, acrtc_state, next_event);
|
||||
next_event = dm_ism_dispatch_power_state(ism, acrtc_state);
|
||||
} else {
|
||||
trace_amdgpu_dm_ism_event(
|
||||
acrtc->crtc_id,
|
||||
|
|
@ -633,6 +640,7 @@ void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
|
|||
INIT_DELAYED_WORK(&ism->delayed_work, dm_ism_delayed_work_func);
|
||||
INIT_DELAYED_WORK(&ism->sso_delayed_work, dm_ism_sso_delayed_work_func);
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_ism_init);
|
||||
|
||||
|
||||
void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism)
|
||||
|
|
@ -640,3 +648,4 @@ void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism)
|
|||
cancel_delayed_work_sync(&ism->sso_delayed_work);
|
||||
cancel_delayed_work_sync(&ism->delayed_work);
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_ism_fini);
|
||||
|
|
|
|||
|
|
@ -157,6 +157,13 @@ uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism,
|
|||
const struct dc_stream_state *stream);
|
||||
uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
|
||||
const struct dc_stream_state *stream);
|
||||
void dm_ism_insert_record(struct amdgpu_dm_ism *ism);
|
||||
void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism);
|
||||
bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
|
||||
enum amdgpu_dm_ism_event event);
|
||||
enum amdgpu_dm_ism_event dm_ism_dispatch_next_event(enum amdgpu_dm_ism_state current_state,
|
||||
uint64_t delay_ns,
|
||||
uint64_t sso_delay_ns);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1174,6 +1174,77 @@ static int try_disable_dsc(struct drm_atomic_commit *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool get_conv_frl_bw(struct amdgpu_dm_connector *aconnector,
|
||||
uint32_t *bw_in_kbps, uint32_t *dsc_bw_in_kbps)
|
||||
{
|
||||
unsigned int max_conv_bw_in_kbps = 0;
|
||||
unsigned int max_sink_bw_in_kbps = 0;
|
||||
unsigned int dsc_max_sink_bw_in_kbps = 0;
|
||||
|
||||
if (aconnector->dc_link->dc->caps.dp_hdmi21_pcon_support &&
|
||||
aconnector->mst_downstream_port_caps.bytes.byte0.bits.DWN_STRM_PORTX_TYPE == DOWN_STREAM_DETAILED_HDMI) {
|
||||
max_conv_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(
|
||||
aconnector->dc_link->dc,
|
||||
aconnector->mst_downstream_port_caps.bytes.byte2.bits.MAX_ENCODED_LINK_BW_SUPPORT);
|
||||
if (aconnector->dc_sink->edid_caps.max_frl_rate && max_conv_bw_in_kbps) {
|
||||
max_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(
|
||||
aconnector->dc_link->dc,
|
||||
aconnector->dc_sink->edid_caps.max_frl_rate);
|
||||
dsc_max_sink_bw_in_kbps = dc_link_bw_kbps_from_raw_frl_link_rate_data(
|
||||
aconnector->dc_link->dc,
|
||||
aconnector->dc_sink->edid_caps.frl_dsc_max_frl_rate);
|
||||
|
||||
*bw_in_kbps = min(max_conv_bw_in_kbps, max_sink_bw_in_kbps);
|
||||
*dsc_bw_in_kbps = min(*bw_in_kbps, dsc_max_sink_bw_in_kbps);
|
||||
}
|
||||
}
|
||||
|
||||
return *bw_in_kbps > 0; // Frl endpoint is detected
|
||||
}
|
||||
|
||||
static void build_frl_mst_dsc_params(struct amdgpu_dm_connector *aconnector,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_dsc_policy *dsc_policy,
|
||||
struct dsc_mst_fairness_params *params,
|
||||
uint32_t frl_conv_dsc_bw_in_kbps)
|
||||
{
|
||||
uint32_t min_bpp_x16, max_bpp_x16;
|
||||
struct dc_dsc_config_options dsc_options = {0};
|
||||
|
||||
min_bpp_x16 = dsc_policy->min_target_bpp * 16;
|
||||
max_bpp_x16 = dsc_policy->max_target_bpp * 16;
|
||||
|
||||
dc_dsc_get_default_config_option(stream->sink->ctx->dc, &dsc_options);
|
||||
dsc_options.max_target_bpp_limit_override_x16 =
|
||||
stream->sink->edid_caps.panel_patch.max_dsc_target_bpp_limit * 16;
|
||||
|
||||
if (dc_dsc_compute_config(
|
||||
stream->sink->ctx->dc->res_pool->dscs[0],
|
||||
&stream->sink->dsc_caps.dsc_dec_caps,
|
||||
&dsc_options,
|
||||
frl_conv_dsc_bw_in_kbps,
|
||||
&stream->timing,
|
||||
dc_link_get_highest_encoding_format(aconnector->dc_link),
|
||||
&stream->timing.dsc_cfg)) {
|
||||
// The timing can enable dsc
|
||||
if (stream->sink->dsc_caps.dsc_dec_caps.is_vic_all_bpp && min_bpp_x16 <= stream->timing.dsc_cfg.bits_per_pixel) {
|
||||
// with all supported bpp within the range limit
|
||||
params->bw_range.max_target_bpp_x16 = min(stream->timing.dsc_cfg.bits_per_pixel, dsc_policy->max_target_bpp * 16);
|
||||
params->bw_range.min_target_bpp_x16 = min_bpp_x16;
|
||||
params->bw_range.max_kbps = (params->bw_range.max_target_bpp_x16 * stream->timing.pix_clk_100hz + 159) / 160;
|
||||
params->bw_range.min_kbps = (params->bw_range.min_target_bpp_x16 * stream->timing.pix_clk_100hz + 159) / 160;
|
||||
} else if (!stream->sink->dsc_caps.dsc_dec_caps.is_vic_all_bpp &&
|
||||
min_bpp_x16 <= stream->timing.dsc_cfg.bits_per_pixel &&
|
||||
max_bpp_x16 >= stream->timing.dsc_cfg.bits_per_pixel) {
|
||||
// with selected bpp only within the range limit
|
||||
params->bw_range.max_target_bpp_x16 = stream->timing.dsc_cfg.bits_per_pixel;
|
||||
params->bw_range.max_kbps = (params->bw_range.max_target_bpp_x16 * stream->timing.pix_clk_100hz + 159) / 160;
|
||||
params->bw_range.min_target_bpp_x16 = params->bw_range.max_target_bpp_x16;
|
||||
params->bw_range.min_kbps = params->bw_range.max_kbps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void log_dsc_params(int count, struct dsc_mst_fairness_vars *vars, int k)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -1199,6 +1270,8 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_commit *state,
|
|||
bool debugfs_overwrite = false;
|
||||
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
|
||||
struct drm_connector_state *new_conn_state;
|
||||
bool is_frl_endpoint_present;
|
||||
uint32_t frl_conv_bw_in_kbps, frl_conv_dsc_bw_in_kbps;
|
||||
|
||||
memset(params, 0, sizeof(params));
|
||||
|
||||
|
|
@ -1244,6 +1317,12 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_commit *state,
|
|||
params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel;
|
||||
params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported;
|
||||
dc_dsc_get_policy_for_timing(params[count].timing, 0, &dsc_policy, dc_link_get_highest_encoding_format(stream->link));
|
||||
is_frl_endpoint_present = get_conv_frl_bw(aconnector, &frl_conv_bw_in_kbps, &frl_conv_dsc_bw_in_kbps);
|
||||
if (stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported &&
|
||||
is_frl_endpoint_present &&
|
||||
frl_conv_dsc_bw_in_kbps &&
|
||||
stream->sink->dsc_caps.dsc_dec_caps.is_frl)
|
||||
build_frl_mst_dsc_params(aconnector, stream, &dsc_policy, ¶ms[count], frl_conv_dsc_bw_in_kbps);
|
||||
if (!dc_dsc_compute_bandwidth_range(
|
||||
stream->sink->ctx->dc->res_pool->dscs[0],
|
||||
stream->sink->ctx->dc->debug.dsc_min_slice_height_override,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "amdgpu_dm_psr.h"
|
||||
#include "amdgpu.h"
|
||||
#include "dc_dmub_srv.h"
|
||||
#include "dc.h"
|
||||
#include "amdgpu_dm.h"
|
||||
|
|
@ -122,7 +123,7 @@ bool amdgpu_dm_set_psr_caps(struct dc_link *link, struct amdgpu_dm_connector *ac
|
|||
return false;
|
||||
|
||||
/*disable allow psr/psrsu/replay on eDP1*/
|
||||
if (dc_get_edp_link_panel_inst(link->ctx->dc, link, &panel_inst) && panel_inst == 1)
|
||||
if (dc_get_edp_link_panel_inst(dc, link, &panel_inst) && panel_inst == 1)
|
||||
return false;
|
||||
|
||||
if (link_supports_psrsu(link))
|
||||
|
|
@ -144,22 +145,17 @@ bool amdgpu_dm_set_psr_caps(struct dc_link *link, struct amdgpu_dm_connector *ac
|
|||
bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm)
|
||||
{
|
||||
unsigned int i;
|
||||
bool allow_active = false;
|
||||
|
||||
for (i = 0; i < dm->dc->current_state->stream_count ; i++) {
|
||||
struct dc_link *link;
|
||||
struct dc_stream_state *stream = dm->dc->current_state->streams[i];
|
||||
for (i = 0; i < dm->dc->current_state->stream_count; i++) {
|
||||
const struct dc_link *link = dm->dc->current_state->streams[i]->link;
|
||||
|
||||
link = stream->link;
|
||||
if (!link)
|
||||
continue;
|
||||
if (link->psr_settings.psr_feature_enabled &&
|
||||
link->psr_settings.psr_allow_active) {
|
||||
allow_active = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (link->psr_settings.psr_feature_enabled && link->psr_settings.psr_allow_active)
|
||||
return true;
|
||||
}
|
||||
return allow_active;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -193,3 +189,4 @@ bool amdgpu_dm_psr_set_event(struct amdgpu_display_manager *dm, struct dc_stream
|
|||
return mod_power_set_psr_event(dm->power_module, stream,
|
||||
set_event, event, wait_for_disable);
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_psr_set_event);
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@
|
|||
#ifndef AMDGPU_DM_AMDGPU_DM_PSR_H_
|
||||
#define AMDGPU_DM_AMDGPU_DM_PSR_H_
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "dc.h"
|
||||
#include "modules/inc/mod_power.h"
|
||||
|
||||
struct amdgpu_display_manager;
|
||||
struct amdgpu_dm_connector;
|
||||
|
||||
/* the number of pageflips before enabling psr */
|
||||
#define AMDGPU_DM_PSR_ENTRY_DELAY 5
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,17 @@ CONFIG_DRM_AMD_DC=y
|
|||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DRM_AMD_DC_KUNIT_TEST=y
|
||||
CONFIG_FW_LOADER=y
|
||||
CONFIG_DRM_KUNIT_TEST=y
|
||||
CONFIG_DRM_KUNIT_TEST_HELPERS=y
|
||||
CONFIG_DRM_KMS_HELPER=y
|
||||
CONFIG_DRM_TTM=y
|
||||
CONFIG_HWMON=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_CRC16=y
|
||||
|
||||
# GCOV Coverage - see tools/testing/kunit/configs/coverage_uml.config
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_GCOV=y
|
||||
|
|
|
|||
|
|
@ -991,6 +991,542 @@ static void dm_test_3dlut32_to_dc_3dlut_green_blue(struct kunit *test)
|
|||
drm_color_lut32_extract(600000, 12));
|
||||
}
|
||||
|
||||
/* ---- Tests for amdgpu_dm_verify_lut_sizes ---- */
|
||||
|
||||
/**
|
||||
* dm_test_make_lut_blob - Allocate a fake drm_property_blob for testing
|
||||
* @test: KUnit test context
|
||||
* @num_entries: number of LUT entries the blob will report
|
||||
*
|
||||
* Allocates a fake blob whose drm_color_lut_size() returns exactly
|
||||
* @num_entries. The data pointer is non-NULL so that
|
||||
* __extract_blob_lut() returns a non-NULL lut pointer and the size
|
||||
* check inside amdgpu_dm_verify_lut_sizes() is actually exercised.
|
||||
*
|
||||
* Return: pointer to the allocated blob
|
||||
*/
|
||||
static struct drm_property_blob *
|
||||
dm_test_make_lut_blob(struct kunit *test, uint32_t num_entries)
|
||||
{
|
||||
struct drm_property_blob *blob;
|
||||
|
||||
blob = kunit_kzalloc(test, sizeof(*blob), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, blob);
|
||||
|
||||
blob->length = num_entries * sizeof(struct drm_color_lut);
|
||||
blob->data = kunit_kcalloc(test, num_entries,
|
||||
sizeof(struct drm_color_lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, blob->data);
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_null_luts - Both LUTs absent: must succeed
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_null_luts(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
/* degamma_lut and gamma_lut are NULL (zeroed allocation) */
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_valid_degamma - Degamma LUT with the correct atomic size: must succeed
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_valid_degamma(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->degamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_invalid_degamma - Degamma LUT with a wrong size: must return -EINVAL
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_invalid_degamma(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
/* Use an arbitrary size that is neither atomic nor legacy */
|
||||
state->degamma_lut = dm_test_make_lut_blob(test, 128);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), -EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_valid_gamma_atomic - Gamma LUT with correct atomic size: must succeed
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_valid_gamma_atomic(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->gamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_valid_gamma_legacy - Gamma LUT with legacy 256-entry size: must succeed
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_valid_gamma_legacy(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->gamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LEGACY_LUT_ENTRIES);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_invalid_gamma - Size is neither atomic nor legacy: must return -EINVAL
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_invalid_gamma(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->gamma_lut = dm_test_make_lut_blob(test, 128);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), -EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_both_valid - Both LUTs set to valid sizes: must succeed
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_both_valid(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->degamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
|
||||
state->gamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_verify_lut_sizes_invalid_degamma_valid_gamma - Bad degamma overrides valid gamma: -EINVAL
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_verify_lut_sizes_invalid_degamma_valid_gamma(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, state);
|
||||
|
||||
state->degamma_lut = dm_test_make_lut_blob(test, 128);
|
||||
state->gamma_lut = dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_verify_lut_sizes(state), -EINVAL);
|
||||
}
|
||||
|
||||
/* ---- Tests for amdgpu_dm_atomic_lut3d ---- */
|
||||
|
||||
/**
|
||||
* dm_test_atomic_lut3d_zero_size - Zero LUT size: initialized must be cleared, no LUT data written
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_atomic_lut3d_zero_size(struct kunit *test)
|
||||
{
|
||||
struct dc_3dlut *lut;
|
||||
u32 initialized;
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
/* Pre-set initialized so we can confirm it is cleared */
|
||||
lut->state.bits.initialized = 1;
|
||||
|
||||
amdgpu_dm_atomic_lut3d(NULL, 0, lut);
|
||||
|
||||
/* Copy bit-field: typeof cannot be applied to a bit-field */
|
||||
initialized = lut->state.bits.initialized;
|
||||
KUNIT_EXPECT_EQ(test, initialized, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_atomic_lut3d_nonzero_state_bits - Non-zero size: state bits and mode flags must be set
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_atomic_lut3d_nonzero_state_bits(struct kunit *test)
|
||||
{
|
||||
const uint32_t lut3d_size = 5;
|
||||
struct drm_color_lut *lut_data;
|
||||
struct dc_3dlut *lut;
|
||||
u32 initialized;
|
||||
|
||||
lut_data = kunit_kcalloc(test, lut3d_size, sizeof(*lut_data), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut_data);
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
amdgpu_dm_atomic_lut3d(lut_data, lut3d_size, lut);
|
||||
|
||||
/* Copy bit-field: typeof cannot be applied to a bit-field */
|
||||
initialized = lut->state.bits.initialized;
|
||||
KUNIT_EXPECT_EQ(test, initialized, 1U);
|
||||
KUNIT_EXPECT_FALSE(test, lut->lut_3d.use_tetrahedral_9);
|
||||
KUNIT_EXPECT_TRUE(test, lut->lut_3d.use_12bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_atomic_lut3d_data_forwarded - Non-zero size: LUT data forwarded to tetrahedral_17
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_atomic_lut3d_data_forwarded(struct kunit *test)
|
||||
{
|
||||
const uint32_t lut3d_size = 5;
|
||||
struct drm_color_lut *lut_data;
|
||||
struct dc_3dlut *lut;
|
||||
|
||||
lut_data = kunit_kcalloc(test, lut3d_size, sizeof(*lut_data), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut_data);
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
lut_data[0].red = 0xFFFF;
|
||||
lut_data[0].green = 0x8000;
|
||||
lut_data[0].blue = 0x4000;
|
||||
|
||||
amdgpu_dm_atomic_lut3d(lut_data, lut3d_size, lut);
|
||||
|
||||
/*
|
||||
* use_tetrahedral_9 == false → data goes into tetrahedral_17.
|
||||
* lut[0] maps to lut0[0] (first element of the first group).
|
||||
*/
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].red,
|
||||
drm_color_lut_extract(0xFFFF, MAX_COLOR_3DLUT_BITDEPTH));
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].green,
|
||||
drm_color_lut_extract(0x8000, MAX_COLOR_3DLUT_BITDEPTH));
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].blue,
|
||||
drm_color_lut_extract(0x4000, MAX_COLOR_3DLUT_BITDEPTH));
|
||||
}
|
||||
|
||||
/* ---- Tests for __set_colorop_3dlut ---- */
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_3dlut_zero_size - Zero LUT size: must return -EINVAL and clear initialized
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_3dlut_zero_size(struct kunit *test)
|
||||
{
|
||||
struct dc_3dlut *lut;
|
||||
u32 initialized;
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
lut->state.bits.initialized = 1;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, __set_colorop_3dlut(NULL, 0, lut), -EINVAL);
|
||||
/* Copy bit-field: typeof cannot be applied to a bit-field */
|
||||
initialized = lut->state.bits.initialized;
|
||||
KUNIT_EXPECT_EQ(test, initialized, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_3dlut_nonzero_state_bits - Non-zero size: must return 0 and set state bits
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_3dlut_nonzero_state_bits(struct kunit *test)
|
||||
{
|
||||
const uint32_t lut3d_size = 5;
|
||||
struct drm_color_lut32 *lut_data;
|
||||
struct dc_3dlut *lut;
|
||||
u32 initialized;
|
||||
|
||||
lut_data = kunit_kcalloc(test, lut3d_size, sizeof(*lut_data), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut_data);
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, __set_colorop_3dlut(lut_data, lut3d_size, lut), 0);
|
||||
/* Copy bit-field: typeof cannot be applied to a bit-field */
|
||||
initialized = lut->state.bits.initialized;
|
||||
KUNIT_EXPECT_EQ(test, initialized, 1U);
|
||||
KUNIT_EXPECT_FALSE(test, lut->lut_3d.use_tetrahedral_9);
|
||||
KUNIT_EXPECT_TRUE(test, lut->lut_3d.use_12bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_3dlut_data_forwarded - Non-zero size: 32-bit data forwarded to tetrahedral_17
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_3dlut_data_forwarded(struct kunit *test)
|
||||
{
|
||||
const uint32_t lut3d_size = 5;
|
||||
struct drm_color_lut32 *lut_data;
|
||||
struct dc_3dlut *lut;
|
||||
|
||||
lut_data = kunit_kcalloc(test, lut3d_size, sizeof(*lut_data), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut_data);
|
||||
|
||||
lut = kunit_kzalloc(test, sizeof(*lut), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, lut);
|
||||
|
||||
lut_data[0].red = 0xFFFFFFFF;
|
||||
lut_data[0].green = 0x80000000;
|
||||
lut_data[0].blue = 0x40000000;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, __set_colorop_3dlut(lut_data, lut3d_size, lut), 0);
|
||||
|
||||
/*
|
||||
* use_tetrahedral_9 == false → data goes into tetrahedral_17.
|
||||
* lut[0] maps to lut0[0]. Bit depth used by __set_colorop_3dlut is 12.
|
||||
*/
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].red,
|
||||
drm_color_lut32_extract(0xFFFFFFFF, 12));
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].green,
|
||||
drm_color_lut32_extract(0x80000000, 12));
|
||||
KUNIT_EXPECT_EQ(test, lut->lut_3d.tetrahedral_17.lut0[0].blue,
|
||||
drm_color_lut32_extract(0x40000000, 12));
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_tf_bypass - __set_tf_bypass: sets TF_TYPE_BYPASS and TRANSFER_FUNCTION_LINEAR
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_tf_bypass(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *tf;
|
||||
|
||||
tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tf);
|
||||
|
||||
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
|
||||
tf->tf = TRANSFER_FUNCTION_SRGB;
|
||||
|
||||
__set_tf_bypass(tf);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_BYPASS);
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_LINEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_tf_distributed_points_srgb - __set_tf_distributed_points: sRGB predefined TF
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_tf_distributed_points_srgb(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *tf;
|
||||
|
||||
tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tf);
|
||||
|
||||
__set_tf_distributed_points(tf, TRANSFER_FUNCTION_SRGB);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_DISTRIBUTED_POINTS);
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_SRGB);
|
||||
KUNIT_EXPECT_EQ(test, tf->sdr_ref_white_level, 80U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_tf_distributed_points_pq - __set_tf_distributed_points: PQ predefined TF
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_tf_distributed_points_pq(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *tf;
|
||||
|
||||
tf = kunit_kzalloc(test, sizeof(*tf), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tf);
|
||||
|
||||
__set_tf_distributed_points(tf, TRANSFER_FUNCTION_PQ);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->type, (int)TF_TYPE_DISTRIBUTED_POINTS);
|
||||
KUNIT_EXPECT_EQ(test, (int)tf->tf, (int)TRANSFER_FUNCTION_PQ);
|
||||
KUNIT_EXPECT_EQ(test, tf->sdr_ref_white_level, 80U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_atomic_regamma_bypass - No LUT and linear TF: must take bypass path
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_atomic_regamma_bypass(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *out_tf;
|
||||
|
||||
out_tf = kunit_kzalloc(test, sizeof(*out_tf), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, out_tf);
|
||||
|
||||
/* size=0 and tf=LINEAR: must take the bypass branch */
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
amdgpu_dm_set_atomic_regamma(out_tf, NULL, 0, false,
|
||||
TRANSFER_FUNCTION_LINEAR),
|
||||
0);
|
||||
KUNIT_EXPECT_EQ(test, (int)out_tf->type, (int)TF_TYPE_BYPASS);
|
||||
KUNIT_EXPECT_EQ(test, (int)out_tf->tf, (int)TRANSFER_FUNCTION_LINEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_atomic_shaper_lut_bypass - No LUT and linear TF: must take bypass path
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_atomic_shaper_lut_bypass(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *func_shaper;
|
||||
|
||||
func_shaper = kunit_kzalloc(test, sizeof(*func_shaper), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, func_shaper);
|
||||
|
||||
/* size=0 and tf=LINEAR: must take the bypass branch */
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
amdgpu_dm_atomic_shaper_lut(NULL, false,
|
||||
TRANSFER_FUNCTION_LINEAR,
|
||||
0, func_shaper),
|
||||
0);
|
||||
KUNIT_EXPECT_EQ(test, (int)func_shaper->type, (int)TF_TYPE_BYPASS);
|
||||
KUNIT_EXPECT_EQ(test, (int)func_shaper->tf, (int)TRANSFER_FUNCTION_LINEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_atomic_blend_lut_bypass - amdgpu_dm_atomic_blend_lut bypass: no LUT, linear TF -> bypass
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_atomic_blend_lut_bypass(struct kunit *test)
|
||||
{
|
||||
struct dc_transfer_func *func_blend;
|
||||
|
||||
func_blend = kunit_kzalloc(test, sizeof(*func_blend), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, func_blend);
|
||||
|
||||
/* size=0 and tf=LINEAR: must take the bypass branch */
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
amdgpu_dm_atomic_blend_lut(NULL, false,
|
||||
TRANSFER_FUNCTION_LINEAR,
|
||||
0, func_blend),
|
||||
0);
|
||||
KUNIT_EXPECT_EQ(test, (int)func_blend->type, (int)TF_TYPE_BYPASS);
|
||||
KUNIT_EXPECT_EQ(test, (int)func_blend->tf, (int)TRANSFER_FUNCTION_LINEAR);
|
||||
}
|
||||
|
||||
/* ---- Tests for __set_colorop_in_tf_1d_curve ---- */
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_in_tf_1d_curve_invalid_type - Non-1D colorop type must be rejected
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_in_tf_1d_curve_invalid_type(struct kunit *test)
|
||||
{
|
||||
struct dc_plane_state *dc_plane_state;
|
||||
struct drm_colorop *colorop;
|
||||
struct drm_colorop_state *colorop_state;
|
||||
|
||||
dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
|
||||
|
||||
colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop);
|
||||
|
||||
colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop_state);
|
||||
|
||||
colorop->type = DRM_COLOROP_3D_LUT;
|
||||
colorop_state->colorop = colorop;
|
||||
colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_EOTF;
|
||||
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
__set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
|
||||
-EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_in_tf_1d_curve_unsupported_curve - Unsupported 1D curve type must be rejected
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_in_tf_1d_curve_unsupported_curve(struct kunit *test)
|
||||
{
|
||||
struct dc_plane_state *dc_plane_state;
|
||||
struct drm_colorop *colorop;
|
||||
struct drm_colorop_state *colorop_state;
|
||||
|
||||
dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
|
||||
|
||||
colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop);
|
||||
|
||||
colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop_state);
|
||||
|
||||
colorop->type = DRM_COLOROP_1D_CURVE;
|
||||
colorop_state->colorop = colorop;
|
||||
colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_COUNT;
|
||||
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
__set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
|
||||
-EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_set_colorop_in_tf_1d_curve_bypass - Bypass mode forces linear bypass transfer function
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_set_colorop_in_tf_1d_curve_bypass(struct kunit *test)
|
||||
{
|
||||
struct dc_plane_state *dc_plane_state;
|
||||
struct drm_colorop *colorop;
|
||||
struct drm_colorop_state *colorop_state;
|
||||
|
||||
dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, dc_plane_state);
|
||||
|
||||
colorop = kunit_kzalloc(test, sizeof(*colorop), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop);
|
||||
|
||||
colorop_state = kunit_kzalloc(test, sizeof(*colorop_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, colorop_state);
|
||||
|
||||
colorop->type = DRM_COLOROP_1D_CURVE;
|
||||
colorop_state->colorop = colorop;
|
||||
colorop_state->curve_1d_type = DRM_COLOROP_1D_CURVE_SRGB_EOTF;
|
||||
colorop_state->bypass = true;
|
||||
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
__set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state),
|
||||
0);
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
(int)dc_plane_state->in_transfer_func.type,
|
||||
(int)TF_TYPE_BYPASS);
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
(int)dc_plane_state->in_transfer_func.tf,
|
||||
(int)TRANSFER_FUNCTION_LINEAR);
|
||||
}
|
||||
|
||||
static struct kunit_case dm_color_test_cases[] = {
|
||||
/* amdgpu_dm_fixpt_from_s3132 */
|
||||
KUNIT_CASE(dm_test_fixpt_from_s3132_zero),
|
||||
|
|
@ -1056,6 +1592,38 @@ static struct kunit_case dm_color_test_cases[] = {
|
|||
KUNIT_CASE(dm_test_3dlut32_to_dc_3dlut_distribution),
|
||||
KUNIT_CASE(dm_test_3dlut32_to_dc_3dlut_tetrahedral_17),
|
||||
KUNIT_CASE(dm_test_3dlut32_to_dc_3dlut_green_blue),
|
||||
/* amdgpu_dm_verify_lut_sizes */
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_null_luts),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_valid_degamma),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_invalid_degamma),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_valid_gamma_atomic),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_valid_gamma_legacy),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_invalid_gamma),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_both_valid),
|
||||
KUNIT_CASE(dm_test_verify_lut_sizes_invalid_degamma_valid_gamma),
|
||||
/* amdgpu_dm_atomic_lut3d */
|
||||
KUNIT_CASE(dm_test_atomic_lut3d_zero_size),
|
||||
KUNIT_CASE(dm_test_atomic_lut3d_nonzero_state_bits),
|
||||
KUNIT_CASE(dm_test_atomic_lut3d_data_forwarded),
|
||||
/* __set_colorop_3dlut */
|
||||
KUNIT_CASE(dm_test_set_colorop_3dlut_zero_size),
|
||||
KUNIT_CASE(dm_test_set_colorop_3dlut_nonzero_state_bits),
|
||||
KUNIT_CASE(dm_test_set_colorop_3dlut_data_forwarded),
|
||||
/* __set_tf_bypass */
|
||||
KUNIT_CASE(dm_test_set_tf_bypass),
|
||||
/* __set_tf_distributed_points */
|
||||
KUNIT_CASE(dm_test_set_tf_distributed_points_srgb),
|
||||
KUNIT_CASE(dm_test_set_tf_distributed_points_pq),
|
||||
/* amdgpu_dm_set_atomic_regamma */
|
||||
KUNIT_CASE(dm_test_set_atomic_regamma_bypass),
|
||||
/* amdgpu_dm_atomic_shaper_lut */
|
||||
KUNIT_CASE(dm_test_atomic_shaper_lut_bypass),
|
||||
/* amdgpu_dm_atomic_blend_lut */
|
||||
KUNIT_CASE(dm_test_atomic_blend_lut_bypass),
|
||||
/* __set_colorop_in_tf_1d_curve */
|
||||
KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_invalid_type),
|
||||
KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_unsupported_curve),
|
||||
KUNIT_CASE(dm_test_set_colorop_in_tf_1d_curve_bypass),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <kunit/test.h>
|
||||
#include <drm/drm_colorop.h>
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
|
||||
#include "amdgpu_dm_colorop.h"
|
||||
|
||||
|
|
@ -30,10 +31,10 @@ static void dm_test_supported_degam_tfs_has_bt2020_inv_oetf(struct kunit *test)
|
|||
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF));
|
||||
}
|
||||
|
||||
static void dm_test_supported_degam_tfs_has_gamma22_inv(struct kunit *test)
|
||||
static void dm_test_supported_degam_tfs_has_gamma22(struct kunit *test)
|
||||
{
|
||||
KUNIT_EXPECT_TRUE(test, amdgpu_dm_supported_degam_tfs &
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV));
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22));
|
||||
}
|
||||
|
||||
static void dm_test_supported_degam_tfs_no_extra_bits(struct kunit *test)
|
||||
|
|
@ -41,7 +42,7 @@ static void dm_test_supported_degam_tfs_no_extra_bits(struct kunit *test)
|
|||
u64 expected = BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_supported_degam_tfs, expected);
|
||||
}
|
||||
|
|
@ -66,10 +67,10 @@ static void dm_test_supported_shaper_tfs_has_bt2020_oetf(struct kunit *test)
|
|||
BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF));
|
||||
}
|
||||
|
||||
static void dm_test_supported_shaper_tfs_has_gamma22(struct kunit *test)
|
||||
static void dm_test_supported_shaper_tfs_has_gamma22_inv(struct kunit *test)
|
||||
{
|
||||
KUNIT_EXPECT_TRUE(test, amdgpu_dm_supported_shaper_tfs &
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22));
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV));
|
||||
}
|
||||
|
||||
static void dm_test_supported_shaper_tfs_no_extra_bits(struct kunit *test)
|
||||
|
|
@ -77,7 +78,7 @@ static void dm_test_supported_shaper_tfs_no_extra_bits(struct kunit *test)
|
|||
u64 expected = BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_supported_shaper_tfs, expected);
|
||||
}
|
||||
|
|
@ -102,10 +103,10 @@ static void dm_test_supported_blnd_tfs_has_bt2020_inv_oetf(struct kunit *test)
|
|||
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF));
|
||||
}
|
||||
|
||||
static void dm_test_supported_blnd_tfs_has_gamma22_inv(struct kunit *test)
|
||||
static void dm_test_supported_blnd_tfs_has_gamma22(struct kunit *test)
|
||||
{
|
||||
KUNIT_EXPECT_TRUE(test, amdgpu_dm_supported_blnd_tfs &
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV));
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22));
|
||||
}
|
||||
|
||||
static void dm_test_supported_blnd_tfs_no_extra_bits(struct kunit *test)
|
||||
|
|
@ -113,7 +114,7 @@ static void dm_test_supported_blnd_tfs_no_extra_bits(struct kunit *test)
|
|||
u64 expected = BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
|
||||
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_supported_blnd_tfs, expected);
|
||||
}
|
||||
|
|
@ -125,27 +126,104 @@ static void dm_test_degam_and_blnd_tfs_match(struct kunit *test)
|
|||
amdgpu_dm_supported_blnd_tfs);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_initialize_default_pipeline */
|
||||
|
||||
static void kunit_colorop_pipeline_destroy(void *drm)
|
||||
{
|
||||
drm_colorop_pipeline_destroy((struct drm_device *)drm);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_initialize_default_pipeline() - Verify amdgpu_dm_build_default_pipeline()
|
||||
* produces the expected colorop chain with all ops bypassable.
|
||||
* @test: KUnit test context.
|
||||
*/
|
||||
static void dm_test_initialize_default_pipeline(struct kunit *test)
|
||||
{
|
||||
static const enum drm_colorop_type expected[] = {
|
||||
DRM_COLOROP_1D_CURVE, /* degam TF */
|
||||
DRM_COLOROP_MULTIPLIER,
|
||||
DRM_COLOROP_CTM_3X4,
|
||||
DRM_COLOROP_1D_CURVE, /* shaper TF */
|
||||
DRM_COLOROP_1D_LUT, /* shaper LUT */
|
||||
DRM_COLOROP_3D_LUT,
|
||||
DRM_COLOROP_1D_CURVE, /* blnd TF */
|
||||
DRM_COLOROP_1D_LUT, /* blnd LUT */
|
||||
};
|
||||
struct device *dev;
|
||||
struct drm_device *drm;
|
||||
struct drm_plane *plane;
|
||||
struct drm_prop_enum_list list = {};
|
||||
struct drm_colorop *op, *first = NULL;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
/*
|
||||
* Allocate a plain drm_device (not an amdgpu_device) — sufficient
|
||||
* because amdgpu_dm_build_default_pipeline() only needs the DRM
|
||||
* mode-config infrastructure, not the amdgpu device wrapper.
|
||||
*/
|
||||
drm = __drm_kunit_helper_alloc_drm_device(test, dev,
|
||||
sizeof(*drm), 0, 0);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
|
||||
|
||||
plane = drm_kunit_helper_create_primary_plane(test, drm,
|
||||
NULL, NULL, NULL, 0, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
|
||||
|
||||
/*
|
||||
* Destroy the pipeline before the DRM device is cleaned up so
|
||||
* that the colorop objects (kzalloc'd inside the function) are
|
||||
* freed while the device is still valid.
|
||||
*/
|
||||
kunit_add_action(test, kunit_colorop_pipeline_destroy, drm);
|
||||
|
||||
ret = amdgpu_dm_build_default_pipeline(drm, plane, true, &list);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
kfree(list.name);
|
||||
|
||||
drm_for_each_colorop(op, drm) {
|
||||
if (op->base.id == (uint32_t)list.type) {
|
||||
first = op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, first);
|
||||
|
||||
for (op = first; op; op = op->next, i++) {
|
||||
KUNIT_ASSERT_LT(test, i, (int)ARRAY_SIZE(expected));
|
||||
KUNIT_EXPECT_EQ(test, op->type, expected[i]);
|
||||
KUNIT_EXPECT_NOT_NULL(test, op->bypass_property);
|
||||
}
|
||||
KUNIT_EXPECT_EQ(test, i, (int)ARRAY_SIZE(expected));
|
||||
}
|
||||
|
||||
static struct kunit_case dm_colorop_test_cases[] = {
|
||||
/* degam TFs */
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_has_srgb_eotf),
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_has_pq125_eotf),
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_has_bt2020_inv_oetf),
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_has_gamma22_inv),
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_has_gamma22),
|
||||
KUNIT_CASE(dm_test_supported_degam_tfs_no_extra_bits),
|
||||
/* shaper TFs */
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_has_srgb_inv_eotf),
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_has_pq125_inv_eotf),
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_has_bt2020_oetf),
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_has_gamma22),
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_has_gamma22_inv),
|
||||
KUNIT_CASE(dm_test_supported_shaper_tfs_no_extra_bits),
|
||||
/* blnd TFs */
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_has_srgb_eotf),
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_has_pq125_eotf),
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_has_bt2020_inv_oetf),
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_has_gamma22_inv),
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_has_gamma22),
|
||||
KUNIT_CASE(dm_test_supported_blnd_tfs_no_extra_bits),
|
||||
/* cross-check */
|
||||
KUNIT_CASE(dm_test_degam_and_blnd_tfs_match),
|
||||
/* amdgpu_dm_initialize_default_pipeline */
|
||||
KUNIT_CASE(dm_test_initialize_default_pipeline),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -579,6 +579,288 @@ static void dm_test_ism_idle_delay_mixed_durations(struct kunit *test)
|
|||
(uint64_t)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_ism_idle_delay_entry_count_exceeds_history_size - entry_count > history_size sets delay
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_idle_delay_entry_count_exceeds_history_size(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
struct dc_stream_state *stream = alloc_test_stream(test);
|
||||
uint64_t one_frame_ns, expected;
|
||||
|
||||
/*
|
||||
* filter_entry_count (5) > filter_history_size (3), so history_size
|
||||
* is determined by filter_entry_count via max(). All 5 records are
|
||||
* short idles, triggering the delay.
|
||||
*/
|
||||
stream->timing.v_total = 1125;
|
||||
stream->timing.h_total = 2200;
|
||||
stream->timing.pix_clk_100hz = 1485000;
|
||||
|
||||
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
|
||||
1485000);
|
||||
|
||||
ism->config.filter_num_frames = 5;
|
||||
ism->config.filter_entry_count = 5;
|
||||
ism->config.filter_history_size = 3;
|
||||
ism->config.activation_num_delay_frames = 10;
|
||||
ism->config.filter_old_history_threshold = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ism->records[i].duration_ns = one_frame_ns;
|
||||
ism->records[i].timestamp_ns = 0;
|
||||
}
|
||||
ism->next_record_idx = 5;
|
||||
|
||||
expected = 10 * one_frame_ns;
|
||||
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream), expected);
|
||||
}
|
||||
|
||||
/* ===== Tests for amdgpu_dm_ism_init ===== */
|
||||
|
||||
/**
|
||||
* dm_test_ism_init_sets_initial_state - all ISM fields initialized to expected values
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_init_sets_initial_state(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
struct amdgpu_dm_ism_config config = {
|
||||
.filter_num_frames = 5,
|
||||
.filter_entry_count = 3,
|
||||
.activation_num_delay_frames = 10,
|
||||
.filter_history_size = 8,
|
||||
.filter_old_history_threshold = 20,
|
||||
.sso_num_frames = 2,
|
||||
};
|
||||
|
||||
amdgpu_dm_ism_init(ism, &config);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 0);
|
||||
KUNIT_EXPECT_EQ(test, ism->last_idle_timestamp_ns, (uint64_t)0);
|
||||
KUNIT_EXPECT_EQ(test, ism->config.filter_num_frames,
|
||||
config.filter_num_frames);
|
||||
KUNIT_EXPECT_EQ(test, ism->config.filter_entry_count,
|
||||
config.filter_entry_count);
|
||||
KUNIT_EXPECT_EQ(test, ism->config.activation_num_delay_frames,
|
||||
config.activation_num_delay_frames);
|
||||
KUNIT_EXPECT_EQ(test, ism->config.sso_num_frames, config.sso_num_frames);
|
||||
}
|
||||
|
||||
/* ===== Tests for amdgpu_dm_ism_fini ===== */
|
||||
|
||||
/**
|
||||
* dm_test_ism_fini_after_init - fini cancels never-scheduled work without error
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_fini_after_init(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
struct amdgpu_dm_ism_config config = {
|
||||
.filter_num_frames = 5,
|
||||
.filter_entry_count = 3,
|
||||
.activation_num_delay_frames = 10,
|
||||
.sso_num_frames = 2,
|
||||
};
|
||||
|
||||
amdgpu_dm_ism_init(ism, &config);
|
||||
/* Work was never scheduled; cancel_delayed_work_sync is a no-op. */
|
||||
amdgpu_dm_ism_fini(ism);
|
||||
|
||||
/* FSM state is untouched by fini */
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
}
|
||||
|
||||
/* ===== Tests for dm_ism_set_last_idle_ts ===== */
|
||||
|
||||
/**
|
||||
* dm_test_ism_set_last_idle_ts_updates_timestamp - last_idle_timestamp_ns updated to current time
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_set_last_idle_ts_updates_timestamp(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
uint64_t before;
|
||||
|
||||
ism->last_idle_timestamp_ns = 0;
|
||||
before = ktime_get_ns();
|
||||
dm_ism_set_last_idle_ts(ism);
|
||||
|
||||
KUNIT_EXPECT_GE(test, ism->last_idle_timestamp_ns, before);
|
||||
}
|
||||
|
||||
/* ===== Tests for dm_ism_insert_record ===== */
|
||||
|
||||
/**
|
||||
* dm_test_ism_insert_record_basic - record inserted with correct index and duration
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_insert_record_basic(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
|
||||
ism->last_idle_timestamp_ns = 0;
|
||||
ism->next_record_idx = 0;
|
||||
|
||||
dm_ism_insert_record(ism);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 1);
|
||||
KUNIT_EXPECT_GT(test, ism->records[0].timestamp_ns, (uint64_t)0);
|
||||
/* duration = timestamp - last_idle_timestamp_ns (0) */
|
||||
KUNIT_EXPECT_EQ(test, ism->records[0].duration_ns,
|
||||
ism->records[0].timestamp_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_ism_insert_record_wraps_around - out-of-bounds index wraps to slot 0
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_insert_record_wraps_around(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
|
||||
ism->last_idle_timestamp_ns = 0;
|
||||
/* Out-of-bounds index triggers reset to 0 */
|
||||
ism->next_record_idx = AMDGPU_DM_IDLE_HIST_LEN;
|
||||
|
||||
dm_ism_insert_record(ism);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 1);
|
||||
KUNIT_EXPECT_GT(test, ism->records[0].timestamp_ns, (uint64_t)0);
|
||||
}
|
||||
|
||||
/* ===== Tests for dm_ism_trigger_event ===== */
|
||||
|
||||
/**
|
||||
* dm_test_ism_trigger_event_valid_transition - valid event advances current and previous state
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_trigger_event_valid_transition(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
bool ok;
|
||||
|
||||
ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
|
||||
ok = dm_ism_trigger_event(ism, DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, ok);
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
|
||||
(int)DM_ISM_STATE_HYSTERESIS_WAITING);
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_ism_trigger_event_invalid_transition - invalid event leaves state unchanged
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_ism_trigger_event_invalid_transition(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
|
||||
bool ok;
|
||||
|
||||
ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
|
||||
/* EXIT_IDLE_REQUESTED is not valid from FULL_POWER_RUNNING */
|
||||
ok = dm_ism_trigger_event(ism, DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, ok);
|
||||
/* State must remain unchanged on invalid transition */
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
|
||||
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
|
||||
}
|
||||
|
||||
/* ===== Tests for dm_ism_dispatch_next_event ===== */
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_hyst_wait_no_delay - zero delay_ns: IMMEDIATE in HYSTERESIS_WAITING
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_hyst_wait_no_delay(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
0, 0);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_hyst_wait_with_delay - delay_ns > 0, no IMMEDIATE event returned
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_hyst_wait_with_delay(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
1000000, 0);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_opt_idle_no_sso_delay - sso_delay_ns == 0 triggers IMMEDIATE event
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_opt_idle_no_sso_delay(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
0, 0);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_opt_idle_with_sso_delay - sso_delay_ns > 0, SSO timer, no IMMEDIATE
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_opt_idle_with_sso_delay(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
0, 1000000);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_timer_aborted - TIMER_ABORTED always returns IMMEDIATE
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_timer_aborted(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_TIMER_ABORTED,
|
||||
0, 0);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_dispatch_next_event_no_action_state - other states return DM_ISM_NUM_EVENTS
|
||||
* @test: KUnit test context
|
||||
*/
|
||||
static void dm_test_dispatch_next_event_no_action_state(struct kunit *test)
|
||||
{
|
||||
enum amdgpu_dm_ism_event result;
|
||||
|
||||
result = dm_ism_dispatch_next_event(DM_ISM_STATE_FULL_POWER_RUNNING,
|
||||
0, 0);
|
||||
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
|
||||
}
|
||||
|
||||
static struct kunit_case dm_ism_test_cases[] = {
|
||||
/* dm_ism_next_state — FULL_POWER_RUNNING */
|
||||
KUNIT_CASE(dm_test_ism_next_state_running_enter_idle),
|
||||
|
|
@ -621,6 +903,26 @@ static struct kunit_case dm_ism_test_cases[] = {
|
|||
KUNIT_CASE(dm_test_ism_idle_delay_wraps_around_buffer),
|
||||
KUNIT_CASE(dm_test_ism_idle_delay_old_history_cutoff),
|
||||
KUNIT_CASE(dm_test_ism_idle_delay_mixed_durations),
|
||||
KUNIT_CASE(dm_test_ism_idle_delay_entry_count_exceeds_history_size),
|
||||
/* amdgpu_dm_ism_init */
|
||||
KUNIT_CASE(dm_test_ism_init_sets_initial_state),
|
||||
/* amdgpu_dm_ism_fini */
|
||||
KUNIT_CASE(dm_test_ism_fini_after_init),
|
||||
/* dm_ism_set_last_idle_ts */
|
||||
KUNIT_CASE(dm_test_ism_set_last_idle_ts_updates_timestamp),
|
||||
/* dm_ism_insert_record */
|
||||
KUNIT_CASE(dm_test_ism_insert_record_basic),
|
||||
KUNIT_CASE(dm_test_ism_insert_record_wraps_around),
|
||||
/* dm_ism_trigger_event */
|
||||
KUNIT_CASE(dm_test_ism_trigger_event_valid_transition),
|
||||
KUNIT_CASE(dm_test_ism_trigger_event_invalid_transition),
|
||||
/* dm_ism_dispatch_next_event */
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_hyst_wait_no_delay),
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_hyst_wait_with_delay),
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_opt_idle_no_sso_delay),
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_opt_idle_with_sso_delay),
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_timer_aborted),
|
||||
KUNIT_CASE(dm_test_dispatch_next_event_no_action_state),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@
|
|||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "dc.h"
|
||||
|
||||
/* Extern declaration for the function under test */
|
||||
extern void amdgpu_dm_psr_fill_caps(struct dc_link *link,
|
||||
struct psr_caps *caps);
|
||||
#include "amdgpu_dm_psr.h"
|
||||
|
||||
/*
|
||||
* Helper: allocate and zero-initialise a dc_link sufficient for
|
||||
|
|
@ -227,6 +223,43 @@ static void dm_test_psr_fill_caps_power_opts_z10_always_set(struct kunit *test)
|
|||
}
|
||||
/* End of tests for amdgpu_dm_psr_fill_caps() */
|
||||
|
||||
/* Tests for amdgpu_dm_psr_set_event() — early-exit validation guards */
|
||||
|
||||
static void dm_test_psr_set_event_null_stream(struct kunit *test)
|
||||
{
|
||||
/* NULL stream → immediate false, dm is not accessed */
|
||||
KUNIT_EXPECT_FALSE(test, amdgpu_dm_psr_set_event(NULL, NULL, true, psr_event_vsync, false));
|
||||
}
|
||||
|
||||
static void dm_test_psr_set_event_null_link(struct kunit *test)
|
||||
{
|
||||
struct dc_stream_state *stream;
|
||||
|
||||
stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, stream);
|
||||
/* stream->link remains NULL from kzalloc */
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, amdgpu_dm_psr_set_event(NULL, stream, true, psr_event_vsync, false));
|
||||
}
|
||||
|
||||
static void dm_test_psr_set_event_psr_not_enabled(struct kunit *test)
|
||||
{
|
||||
struct dc_stream_state *stream;
|
||||
struct dc_link *link;
|
||||
|
||||
stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, stream);
|
||||
|
||||
link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, link);
|
||||
|
||||
stream->link = link;
|
||||
/* link->psr_settings.psr_feature_enabled remains false from kzalloc */
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, amdgpu_dm_psr_set_event(NULL, stream, true, psr_event_vsync, false));
|
||||
}
|
||||
/* End of tests for amdgpu_dm_psr_set_event() */
|
||||
|
||||
static struct kunit_case dm_psr_test_cases[] = {
|
||||
KUNIT_CASE(dm_test_psr_fill_caps_version_1),
|
||||
KUNIT_CASE(dm_test_psr_fill_caps_version_su1),
|
||||
|
|
@ -240,6 +273,9 @@ static struct kunit_case dm_psr_test_cases[] = {
|
|||
KUNIT_CASE(dm_test_psr_fill_caps_dpcd_fields_unset),
|
||||
KUNIT_CASE(dm_test_psr_fill_caps_rate_control_always_zero),
|
||||
KUNIT_CASE(dm_test_psr_fill_caps_power_opts_z10_always_set),
|
||||
KUNIT_CASE(dm_test_psr_set_event_null_stream),
|
||||
KUNIT_CASE(dm_test_psr_set_event_null_link),
|
||||
KUNIT_CASE(dm_test_psr_set_event_psr_not_enabled),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -289,8 +289,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
|
|||
if (capacity <= vector->capacity)
|
||||
return true;
|
||||
|
||||
new_container = krealloc(vector->container,
|
||||
capacity * vector->struct_size, GFP_KERNEL);
|
||||
new_container = krealloc_array(vector->container,
|
||||
capacity, vector->struct_size, GFP_KERNEL);
|
||||
|
||||
if (new_container) {
|
||||
vector->container = new_container;
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
|||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
ATOM_I2C_RECORD *record;
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
int i;
|
||||
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
|
@ -234,7 +235,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
|||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -293,11 +294,12 @@ static enum bp_result bios_parser_get_device_tag_record(
|
|||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -966,6 +968,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
|
|||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -975,7 +978,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
|
|||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -1670,6 +1673,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
|
|||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -1679,7 +1683,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
|
|||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -2733,6 +2737,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
|
|||
{
|
||||
(void)i;
|
||||
unsigned int j;
|
||||
unsigned int n;
|
||||
struct bios_parser *bp;
|
||||
ATOM_BRACKET_LAYOUT_RECORD *record;
|
||||
ATOM_COMMON_RECORD_HEADER *record_header;
|
||||
|
|
@ -2742,7 +2747,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
|
|||
record = NULL;
|
||||
record_header = NULL;
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
|
||||
if (record_header == NULL) {
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
|||
struct atom_i2c_record *record;
|
||||
struct atom_i2c_record dummy_record = {0};
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
int i;
|
||||
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
|
@ -429,7 +430,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
|||
break;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -534,6 +535,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -542,7 +544,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
|
|||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -611,6 +613,7 @@ static struct atom_hpd_int_record *get_hpd_record(
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -620,7 +623,7 @@ static struct atom_hpd_int_record *get_hpd_record(
|
|||
offset = le16_to_cpu(object->disp_recordoffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -701,8 +704,10 @@ static enum bp_result bios_parser_get_gpio_pin_info(
|
|||
info->offset_en = info->offset + 1;
|
||||
info->offset_mask = info->offset - 1;
|
||||
|
||||
info->mask = (uint32_t) (1 <<
|
||||
header->gpio_pin[i].gpio_bitshift);
|
||||
if (header->gpio_pin[i].gpio_bitshift >= 32)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
info->mask = 1u << header->gpio_pin[i].gpio_bitshift;
|
||||
info->mask_y = info->mask + 2;
|
||||
info->mask_en = info->mask + 1;
|
||||
info->mask_mask = info->mask - 1;
|
||||
|
|
@ -713,6 +718,69 @@ static enum bp_result bios_parser_get_gpio_pin_info(
|
|||
return BP_RESULT_NORECORD;
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_get_connector_aux_info(struct dc_bios *dcb,
|
||||
struct graphics_object_id id,
|
||||
struct graphics_object_i2c_info *info)
|
||||
{
|
||||
uint32_t offset;
|
||||
struct atom_display_object_path_v2 *object;
|
||||
struct atom_display_object_path_v3 *object_path_v3;
|
||||
struct atom_common_record_header *header;
|
||||
struct atom_i2c_record *record;
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
||||
switch (bp->object_info_tbl.revision.minor) {
|
||||
case 4:
|
||||
default:
|
||||
object = get_bios_object(bp, id);
|
||||
|
||||
if (!object)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
break;
|
||||
case 5:
|
||||
object_path_v3 = get_bios_object_from_path_v3(bp, id);
|
||||
|
||||
if (!object_path_v3)
|
||||
return BP_RESULT_BADINPUT;
|
||||
|
||||
offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
if (header->record_type == LAST_RECORD_TYPE ||
|
||||
!header->record_size)
|
||||
break;
|
||||
|
||||
if (header->record_type == ATOM_I2C_RECORD_TYPE
|
||||
&& sizeof(struct atom_i2c_record) <=
|
||||
header->record_size) {
|
||||
/* get_connector_aux_info - which aux instance is used it is based
|
||||
* on record->i2c_id field only, does not need GPIO DDC
|
||||
*/
|
||||
record = (struct atom_i2c_record *)header;
|
||||
|
||||
info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
offset += header->record_size;
|
||||
}
|
||||
|
||||
return BP_RESULT_NORECORD;
|
||||
}
|
||||
|
||||
static struct device_id device_type_from_device_id(uint16_t device_id)
|
||||
{
|
||||
|
||||
|
|
@ -2135,6 +2203,12 @@ static enum bp_result get_firmware_info_v3_5(
|
|||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
/* TODO: Remove this temp define after atomfirmware.h is updated */
|
||||
#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP 0x200
|
||||
#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP 0x400 // HDMI FRL 8Gb support
|
||||
#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP 0x800 // HDMI FRL 10Gb support
|
||||
#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP 0x1000 // HDMI FRL 12Gb support
|
||||
|
||||
static enum bp_result bios_parser_get_encoder_cap_info(
|
||||
struct dc_bios *dcb,
|
||||
struct graphics_object_id object_id,
|
||||
|
|
@ -2182,6 +2256,15 @@ static enum bp_result bios_parser_get_encoder_cap_info(
|
|||
info->DP_IS_USB_C = (record->encodercaps &
|
||||
ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
|
||||
DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
|
||||
info->IS_HDMI_FRL_CAPABLE = (record->encodercaps &
|
||||
ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP) ? 1 : 0;
|
||||
info->FRL_8G_EN = (record->encodercaps &
|
||||
ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP) ? 1 : 0;
|
||||
info->FRL_10G_EN = (record->encodercaps &
|
||||
ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP) ? 1 : 0;
|
||||
info->FRL_12G_EN = (record->encodercaps &
|
||||
ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP) ? 1 : 0;
|
||||
DC_LOG_BIOS("\t info->IS_HDMI_FRL_CAPABLE %d\n", info->IS_HDMI_FRL_CAPABLE);
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
|
@ -2193,6 +2276,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -2201,7 +2285,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
|
|||
|
||||
offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -2230,6 +2314,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -2238,7 +2323,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
|
|||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -2266,6 +2351,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -2274,7 +2360,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
|
|||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -2341,6 +2427,9 @@ static enum bp_result bios_parser_get_disp_connector_caps_info(
|
|||
? 1 : 0;
|
||||
info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
|
||||
? 1 : 0;
|
||||
// All aux transactions for this connector should rely only on aux instance, not on ddc instance
|
||||
info->NO_DDC_PIN = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_DP_PLUS_PLUS_TYPE2_ONLY) ? 1 : 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2352,6 +2441,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
|
|||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
|
|
@ -2360,7 +2450,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
|
|||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
|
|
@ -2410,6 +2500,12 @@ static enum bp_result bios_parser_get_connector_speed_cap_info(
|
|||
info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
|
||||
info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
|
||||
info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
|
||||
info->FRL_8G_EN = (record->connector_max_speed >= 8000) ? 1 : 0;
|
||||
info->FRL_10G_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
|
||||
info->FRL_12G_EN = (record->connector_max_speed >= 12000) ? 1 : 0;
|
||||
info->FRL_16G_EN = (record->connector_max_speed >= 16000) ? 1 : 0;
|
||||
info->FRL_20G_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
|
||||
info->FRL_24G_EN = (record->connector_max_speed >= 24000) ? 1 : 0;
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2600,14 +2696,16 @@ static enum bp_result get_integrated_info_v11(
|
|||
info_v11->extdispconninfo.checksum;
|
||||
|
||||
info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2616,14 +2714,16 @@ static enum bp_result get_integrated_info_v11(
|
|||
}
|
||||
|
||||
info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2632,14 +2732,16 @@ static enum bp_result get_integrated_info_v11(
|
|||
}
|
||||
|
||||
info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2648,14 +2750,16 @@ static enum bp_result get_integrated_info_v11(
|
|||
}
|
||||
|
||||
info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2796,14 +2900,16 @@ static enum bp_result get_integrated_info_v2_1(
|
|||
info->ext_disp_conn_info.checksum =
|
||||
info_v2_1->extdispconninfo.checksum;
|
||||
info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2811,14 +2917,16 @@ static enum bp_result get_integrated_info_v2_1(
|
|||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2826,14 +2934,16 @@ static enum bp_result get_integrated_info_v2_1(
|
|||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -2841,14 +2951,16 @@ static enum bp_result get_integrated_info_v2_1(
|
|||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
|
|
@ -3228,6 +3340,7 @@ static enum bp_result update_slot_layout_info(
|
|||
{
|
||||
unsigned int record_offset;
|
||||
unsigned int j;
|
||||
unsigned int n;
|
||||
struct atom_display_object_path_v2 *object;
|
||||
struct atom_bracket_layout_record *record;
|
||||
struct atom_common_record_header *record_header;
|
||||
|
|
@ -3249,7 +3362,7 @@ static enum bp_result update_slot_layout_info(
|
|||
(object->disp_recordoffset) +
|
||||
(unsigned int)(bp->object_info_tbl_offset);
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = (struct atom_common_record_header *)
|
||||
GET_IMAGE(struct atom_common_record_header,
|
||||
|
|
@ -3343,6 +3456,7 @@ static enum bp_result update_slot_layout_info_v2(
|
|||
struct slot_layout_info *slot_layout_info)
|
||||
{
|
||||
unsigned int record_offset;
|
||||
unsigned int n;
|
||||
struct atom_display_object_path_v3 *object;
|
||||
struct atom_bracket_layout_record_v2 *record;
|
||||
struct atom_common_record_header *record_header;
|
||||
|
|
@ -3365,7 +3479,7 @@ static enum bp_result update_slot_layout_info_v2(
|
|||
(object->disp_recordoffset) +
|
||||
(unsigned int)(bp->object_info_tbl_offset);
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = (struct atom_common_record_header *)
|
||||
GET_IMAGE(struct atom_common_record_header,
|
||||
|
|
@ -3690,6 +3804,7 @@ static const struct dc_vbios_funcs vbios_funcs = {
|
|||
.get_lttpr_interop = bios_parser_get_lttpr_interop,
|
||||
|
||||
.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
|
||||
.get_connector_aux_info = bios_parser_get_connector_aux_info,
|
||||
};
|
||||
|
||||
static bool bios_parser2_construct(
|
||||
|
|
|
|||
|
|
@ -37,4 +37,9 @@ void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
|
|||
|
||||
#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
|
||||
|
||||
/* Upper bound on the number of records in a VBIOS record chain. Prevents
|
||||
* unbounded looping if the VBIOS image is malformed and lacks a terminator.
|
||||
*/
|
||||
#define BIOS_MAX_NUM_RECORD 256
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -371,6 +371,10 @@ static enum bp_result transmitter_control_v1_7(
|
|||
if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||
|
||||
cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||
|
||||
cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {
|
||||
if (dc_is_hdmi_frl_signal(cntl->signal))
|
||||
DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_Hz = %d\n",
|
||||
__func__, dig_v1_7.symclk_units.symclk_Hz);
|
||||
else
|
||||
DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n",
|
||||
__func__, dig_v1_7.symclk_units.symclk_10khz);
|
||||
}
|
||||
|
|
@ -395,6 +399,8 @@ static enum bp_result transmitter_control_v1_7(
|
|||
process_phy_transition_init_params.sym_clock_10khz = dig_v1_7.symclk_units.symclk_10khz;
|
||||
process_phy_transition_init_params.display_port_link_rate = link->cur_link_settings.link_rate;
|
||||
process_phy_transition_init_params.transition_bitmask = link->phy_transition_bitmask;
|
||||
process_phy_transition_init_params.hdmi_frl_num_lanes = link->frl_link_settings.frl_num_lanes;
|
||||
process_phy_transition_init_params.hdmi_frl_link_rate = link->frl_link_settings.frl_link_rate;
|
||||
}
|
||||
dig_v1_7.skip_phy_ssc_reduction = link->wa_flags.skip_phy_ssc_reduction;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
|
|||
case DCN_VERSION_3_6:
|
||||
case DCN_VERSION_4_01:
|
||||
case DCN_VERSION_4_2:
|
||||
case DCN_VERSION_4_2B:
|
||||
*h = dal_cmd_tbl_helper_dce112_get_table2();
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
|
|||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI;
|
||||
break;
|
||||
case SIGNAL_TYPE_HDMI_FRL:
|
||||
atom_dig_mode = 4;
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
|
|||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI;
|
||||
break;
|
||||
case SIGNAL_TYPE_HDMI_FRL:
|
||||
atom_dig_mode = 4;
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -185,4 +185,14 @@ CLK_MGR_DCN42 = dcn42_smu.o dcn42_clk_mgr.o
|
|||
AMD_DAL_CLK_MGR_DCN42 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42/,$(CLK_MGR_DCN42))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42)
|
||||
|
||||
###############################################################################
|
||||
# DCN42B
|
||||
###############################################################################
|
||||
CLK_MGR_DCN42B = dcn42b_clk_mgr.o
|
||||
|
||||
AMD_DAL_CLK_MGR_DCN42B = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42b/,$(CLK_MGR_DCN42B))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42B)
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "dcn35/dcn35_clk_mgr.h"
|
||||
#include "dcn401/dcn401_clk_mgr.h"
|
||||
#include "dcn42/dcn42_clk_mgr.h"
|
||||
#include "dcn42b/dcn42b_clk_mgr.h"
|
||||
|
||||
int clk_mgr_helper_get_active_display_cnt(
|
||||
struct dc *dc,
|
||||
|
|
@ -338,6 +339,16 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
|
|||
break;
|
||||
|
||||
case AMDGPU_FAMILY_GC_11_5_0: {
|
||||
if (ctx->dce_version == DCN_VERSION_4_2B) {
|
||||
struct clk_mgr_dcn42 *clk_mgr = kzalloc_obj(*clk_mgr);
|
||||
|
||||
if (clk_mgr == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
dcn42b_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
struct clk_mgr_dcn35 *clk_mgr = kzalloc_obj(*clk_mgr);
|
||||
|
||||
if (clk_mgr == NULL) {
|
||||
|
|
@ -428,6 +439,10 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
|
|||
break;
|
||||
|
||||
case AMDGPU_FAMILY_GC_11_5_0:
|
||||
if (clk_mgr_base->ctx->dce_version == DCN_VERSION_4_2B) {
|
||||
dcn42_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
}
|
||||
dcn35_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
case AMDGPU_FAMILY_GC_12_0_0:
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ static int dcn31_get_active_display_cnt_wa(
|
|||
if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
|
||||
display_count++;
|
||||
|
||||
/* FRL can't be tracked by DIG enablement */
|
||||
if (dc_is_hdmi_frl_signal(stream->signal))
|
||||
display_count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,9 @@ static int dcn314_get_active_display_cnt_wa(
|
|||
if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
|
||||
display_count++;
|
||||
|
||||
/* FRL can't be tracked by DIG enablement */
|
||||
if (dc_is_hdmi_frl_signal(stream->signal))
|
||||
display_count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ static int dcn315_get_active_display_cnt_wa(
|
|||
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
|
||||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
|
||||
tmds_present = true;
|
||||
/* FRL can't be tracked by DIG enablement */
|
||||
if (dc_is_hdmi_frl_signal(stream->signal))
|
||||
display_count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ static int dcn316_get_active_display_cnt_wa(
|
|||
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
|
||||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
|
||||
tmds_present = true;
|
||||
/* FRL can't be tracked by DIG enablement */
|
||||
if (dc_is_hdmi_frl_signal(stream->signal))
|
||||
display_count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
|
|||
|
|
@ -283,6 +283,18 @@ static void dcn32_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
|
|||
dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
|
||||
dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
|
||||
|
||||
if (dc_is_hdmi_frl_signal(pipe_ctx->stream->signal) ||
|
||||
dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
|
||||
dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
|
||||
|
||||
if (pipe_ctx->stream_res.audio != NULL)
|
||||
dto_params.req_audio_dtbclk_khz = 24000;
|
||||
}
|
||||
|
||||
if (dc_is_hdmi_signal(pipe_ctx->stream->signal) ||
|
||||
dc_is_dvi_signal(pipe_ctx->stream->signal))
|
||||
dto_params.is_hdmi = true;
|
||||
|
||||
dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
|
||||
//dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user