amd-drm-next-7.1-2026-04-01:
amdgpu: - UserQ fixes - PASID handling fix - S4 fix for smu11 chips - devcoredump fixes - RAS fixes - Misc small fixes - DCN 4.2 updates - DVI fixes - DML fixes - DC pipe validation fixes - eDP DSC seamless boot - DC FP rework - swsmu cleanups - GC 11.5.4 updates - Add DC idle state manager - Add support for using multiple engines for buffer fills and clears - Misc SMU7 fixes amdkfd: - Non-4K page fixes - Logging cleanups - sysfs fixes -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCac1kDQAKCRC93/aFa7yZ 2MHgAP45SqxOBmns0YnLQkeubzJDqSvsmwkrIU3hf5OiEFf/tAEAxbAuEow2ZaUK XIIRtWufXQ3Fi8vTinNDrMM6xXIXqgo= =h0mR -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-7.1-2026-04-01' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-7.1-2026-04-01: amdgpu: - UserQ fixes - PASID handling fix - S4 fix for smu11 chips - devcoredump fixes - RAS fixes - Misc small fixes - DCN 4.2 updates - DVI fixes - DML fixes - DC pipe validation fixes - eDP DSC seamless boot - DC FP rework - swsmu cleanups - GC 11.5.4 updates - Add DC idle state manager - Add support for using multiple engines for buffer fills and clears - Misc SMU7 fixes amdkfd: - Non-4K page fixes - Logging cleanups - sysfs fixes Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260401184456.3576660-1-alexander.deucher@amd.commaster
commit
cdd65e8bb9
|
|
@ -373,17 +373,148 @@ int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
int
|
||||
amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
u32 mem_channel_number;
|
||||
u32 mem_channel_width;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 11:
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v11.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
case 2:
|
||||
mem_channel_number = igp_info->v21.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v21.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
case 3:
|
||||
mem_channel_number = igp_info->v23.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v23.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union umc_info *umc_info;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
u8 mem_vendor;
|
||||
u32 mem_channel_number;
|
||||
u32 mem_channel_width;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
|
||||
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
if (frev == 4) {
|
||||
switch (crev) {
|
||||
case 0:
|
||||
mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
|
||||
mem_type = le32_to_cpu(umc_info->v40.vram_type);
|
||||
mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
|
||||
mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index, i = 0;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
union vram_info *vram_info;
|
||||
union umc_info *umc_info;
|
||||
union vram_module *vram_module;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
|
|
@ -392,230 +523,130 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
|||
u32 mem_channel_width;
|
||||
u32 module_id;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
else {
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
|
||||
break;
|
||||
default:
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
|
||||
}
|
||||
}
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
|
||||
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 11:
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v11.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
vram_info = (union vram_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
|
||||
if (frev == 3) {
|
||||
switch (crev) {
|
||||
/* v30 */
|
||||
case 0:
|
||||
vram_module = (union vram_module *)vram_info->v30.vram_module;
|
||||
mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
mem_type = vram_info->v30.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_info->v30.channel_num;
|
||||
mem_channel_width = vram_info->v30.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * 16;
|
||||
break;
|
||||
case 2:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
case 2:
|
||||
mem_channel_number = igp_info->v21.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v21.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
case 3:
|
||||
mem_channel_number = igp_info->v23.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v23.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (frev == 2) {
|
||||
switch (crev) {
|
||||
/* v23 */
|
||||
case 3:
|
||||
if (module_id > vram_info->v23.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v23.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v24 */
|
||||
case 4:
|
||||
if (module_id > vram_info->v24.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v24.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v10.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v10.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v10.channel_num;
|
||||
mem_channel_width = vram_module->v10.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v25 */
|
||||
case 5:
|
||||
if (module_id > vram_info->v25.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v25.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v11.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v11.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v11.channel_num;
|
||||
mem_channel_width = vram_module->v11.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v26 */
|
||||
case 6:
|
||||
if (module_id > vram_info->v26.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v26.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
if (frev == 4) {
|
||||
switch (crev) {
|
||||
case 0:
|
||||
mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
|
||||
mem_type = le32_to_cpu(umc_info->v40.vram_type);
|
||||
mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
|
||||
mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
vram_info = (union vram_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
|
||||
if (frev == 3) {
|
||||
switch (crev) {
|
||||
/* v30 */
|
||||
case 0:
|
||||
vram_module = (union vram_module *)vram_info->v30.vram_module;
|
||||
mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
mem_type = vram_info->v30.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_info->v30.channel_num;
|
||||
mem_channel_width = vram_info->v30.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * 16;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (frev == 2) {
|
||||
switch (crev) {
|
||||
/* v23 */
|
||||
case 3:
|
||||
if (module_id > vram_info->v23.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v23.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v24 */
|
||||
case 4:
|
||||
if (module_id > vram_info->v24.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v24.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v10.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v10.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v10.channel_num;
|
||||
mem_channel_width = vram_module->v10.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v25 */
|
||||
case 5:
|
||||
if (module_id > vram_info->v25.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v25.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v11.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v11.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v11.channel_num;
|
||||
mem_channel_width = vram_module->v11.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v26 */
|
||||
case 6:
|
||||
if (module_id > vram_info->v26.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v26.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* invalid frev */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* invalid frev */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ uint32_t amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device *ade
|
|||
bool amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device *adev);
|
||||
void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -908,9 +908,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
goto out_free_user_pages;
|
||||
|
||||
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
||||
/* One fence for TTM and one for each CS job */
|
||||
r = drm_exec_prepare_obj(&p->exec, &e->bo->tbo.base,
|
||||
1 + p->gang_size);
|
||||
TTM_NUM_MOVE_FENCES + p->gang_size);
|
||||
drm_exec_retry_on_contention(&p->exec);
|
||||
if (unlikely(r))
|
||||
goto out_free_user_pages;
|
||||
|
|
@ -920,7 +919,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
|
||||
if (p->uf_bo) {
|
||||
r = drm_exec_prepare_obj(&p->exec, &p->uf_bo->tbo.base,
|
||||
1 + p->gang_size);
|
||||
TTM_NUM_MOVE_FENCES + p->gang_size);
|
||||
drm_exec_retry_on_contention(&p->exec);
|
||||
if (unlikely(r))
|
||||
goto out_free_user_pages;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
void amdgpu_coredump_init(struct amdgpu_device *adev)
|
||||
{
|
||||
}
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
}
|
||||
#else
|
||||
|
||||
#define AMDGPU_CORE_DUMP_SIZE_MAX (256 * 1024 * 1024)
|
||||
|
|
@ -192,12 +195,16 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
|
|||
drm_printf(p, "VPE feature version: %u, fw version: 0x%08x\n",
|
||||
adev->vpe.feature_version, adev->vpe.fw_version);
|
||||
|
||||
drm_printf(p, "\nVBIOS Information\n");
|
||||
drm_printf(p, "vbios name : %s\n", ctx->name);
|
||||
drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
|
||||
drm_printf(p, "vbios version : %d\n", ctx->version);
|
||||
drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
|
||||
drm_printf(p, "vbios date : %s\n", ctx->date);
|
||||
if (adev->bios) {
|
||||
drm_printf(p, "\nVBIOS Information\n");
|
||||
drm_printf(p, "vbios name : %s\n", ctx->name);
|
||||
drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
|
||||
drm_printf(p, "vbios version : %d\n", ctx->version);
|
||||
drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
|
||||
drm_printf(p, "vbios date : %s\n", ctx->date);
|
||||
}else {
|
||||
drm_printf(p, "\nVBIOS Information: NA\n");
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
|
@ -436,4 +443,10 @@ void amdgpu_coredump_init(struct amdgpu_device *adev)
|
|||
{
|
||||
INIT_WORK(&adev->coredump_work, amdgpu_devcoredump_deferred_work);
|
||||
}
|
||||
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
/* Finish deferred coredump formatting before HW/IP teardown. */
|
||||
flush_work(&adev->coredump_work);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,4 +50,5 @@ struct amdgpu_coredump_info {
|
|||
void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
bool vram_lost, struct amdgpu_job *job);
|
||||
void amdgpu_coredump_init(struct amdgpu_device *adev);
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4225,6 +4225,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
|||
if (pci_dev_is_disconnected(adev->pdev))
|
||||
amdgpu_amdkfd_device_fini_sw(adev);
|
||||
|
||||
amdgpu_coredump_fini(adev);
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
|
|
|||
|
|
@ -2683,8 +2683,12 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_acpi_should_gpu_reset(adev))
|
||||
return amdgpu_asic_reset(adev);
|
||||
if (amdgpu_acpi_should_gpu_reset(adev)) {
|
||||
amdgpu_device_lock_reset_domain(adev->reset_domain);
|
||||
r = amdgpu_asic_reset(adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -403,6 +403,50 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_map_gfx9_mqd - map mqd and ctrl_stack dma_addresses into GART entries
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @offset: offset into the GPU's gart aperture
|
||||
* @pages: number of pages to bind
|
||||
* @dma_addr: DMA addresses of pages
|
||||
* @flags: page table entry flags
|
||||
*
|
||||
* Map the MQD and control stack addresses into GART entries with the correct
|
||||
* memory types on gfxv9. The MQD occupies the first 4KB and is followed by
|
||||
* the control stack. The MQD uses UC (uncached) memory, while the control stack
|
||||
* uses NC (non-coherent) memory.
|
||||
*/
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags)
|
||||
{
|
||||
uint64_t page_base;
|
||||
unsigned int i, j, t;
|
||||
int idx;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
void *dst;
|
||||
|
||||
if (!adev->gart.ptr)
|
||||
return;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
t = offset / AMDGPU_GPU_PAGE_SIZE;
|
||||
dst = adev->gart.ptr;
|
||||
for (i = 0; i < pages; i++) {
|
||||
page_base = dma_addr[i];
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
if ((i == 0) && (j == 0))
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
|
||||
else
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, ctrl_flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_bind - bind pages into the gart page table
|
||||
*
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
|||
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst);
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_atomfirmware.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
|
@ -1747,3 +1748,31 @@ int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return amdgpu_atomfirmware_get_integrated_system_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
return amdgpu_atomfirmware_get_umc_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
case IP_VERSION(9, 5, 0):
|
||||
case IP_VERSION(9, 4, 4):
|
||||
case IP_VERSION(9, 4, 3):
|
||||
ret = amdgpu_atomfirmware_get_umc_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
if (vram_width && !ret)
|
||||
*vram_width *= hweight32(adev->aid_mask);
|
||||
return ret;
|
||||
default:
|
||||
return amdgpu_atomfirmware_get_vram_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,4 +482,6 @@ amdgpu_gmc_query_memory_partition(struct amdgpu_device *adev);
|
|||
int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev);
|
||||
void amdgpu_gmc_init_sw_mem_ranges(struct amdgpu_device *adev,
|
||||
struct amdgpu_mem_partition_info *mem_ranges);
|
||||
int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -68,8 +68,11 @@ int amdgpu_pasid_alloc(unsigned int bits)
|
|||
return -EINVAL;
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
/* TODO: Need to replace the idr with an xarry, and then
|
||||
* handle the internal locking with ATOMIC safe paths.
|
||||
*/
|
||||
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
|
||||
1U << bits, GFP_KERNEL);
|
||||
1U << bits, GFP_ATOMIC);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
|
||||
if (pasid >= 0)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <drm/display/drm_dp_mst_helper.h>
|
||||
#include "modules/inc/mod_freesync.h"
|
||||
#include "amdgpu_dm_irq_params.h"
|
||||
#include "amdgpu_dm_ism.h"
|
||||
|
||||
struct amdgpu_bo;
|
||||
struct amdgpu_device;
|
||||
|
|
@ -486,6 +487,10 @@ struct amdgpu_crtc {
|
|||
int deferred_flip_completion;
|
||||
/* parameters access from DM IRQ handler */
|
||||
struct dm_irq_params dm_irq_params;
|
||||
|
||||
/* DM idle state manager */
|
||||
struct amdgpu_dm_ism ism;
|
||||
|
||||
/* pll sharing */
|
||||
struct amdgpu_atom_ss ss;
|
||||
bool ss_enabled;
|
||||
|
|
|
|||
|
|
@ -1325,7 +1325,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_fill_buffer(&adev->mman.clear_entity, abo, 0, &bo->base._resv,
|
||||
r = amdgpu_fill_buffer(amdgpu_ttm_next_clear_entity(adev),
|
||||
abo, 0, &bo->base._resv,
|
||||
&fence, AMDGPU_KERNEL_JOB_ID_CLEAR_ON_RELEASE);
|
||||
if (WARN_ON(r))
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -1558,6 +1558,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
|
||||
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
int dev_var = adev->pdev->device & 0xF;
|
||||
uint32_t vram_type = adev->gmc.vram_type;
|
||||
int res;
|
||||
|
||||
if (amdgpu_ras_smu_eeprom_supported(adev))
|
||||
|
|
@ -1597,6 +1599,12 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU) && (dev_var == 0x5) &&
|
||||
(vram_type == AMDGPU_VRAM_TYPE_HBM3E) &&
|
||||
(hdr->version < RAS_TABLE_VER_V3)) {
|
||||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
|
||||
switch (hdr->version) {
|
||||
case RAS_TABLE_VER_V2_1:
|
||||
case RAS_TABLE_VER_V3:
|
||||
|
|
|
|||
|
|
@ -387,9 +387,11 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
struct amdgpu_ttm_buffer_entity *entity;
|
||||
struct amdgpu_copy_mem src, dst;
|
||||
struct dma_fence *fence = NULL;
|
||||
int r;
|
||||
u32 e;
|
||||
|
||||
src.bo = bo;
|
||||
dst.bo = bo;
|
||||
|
|
@ -398,8 +400,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
src.offset = 0;
|
||||
dst.offset = 0;
|
||||
|
||||
e = atomic_inc_return(&adev->mman.next_move_entity) %
|
||||
adev->mman.num_move_entities;
|
||||
entity = &adev->mman.move_entities[e];
|
||||
|
||||
r = amdgpu_ttm_copy_mem_to_mem(adev,
|
||||
&adev->mman.move_entity,
|
||||
entity,
|
||||
&src, &dst,
|
||||
new_mem->size,
|
||||
amdgpu_bo_encrypted(abo),
|
||||
|
|
@ -411,9 +417,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
if (old_mem->mem_type == TTM_PL_VRAM &&
|
||||
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
|
||||
struct dma_fence *wipe_fence = NULL;
|
||||
|
||||
r = amdgpu_fill_buffer(&adev->mman.move_entity,
|
||||
abo, 0, NULL, &wipe_fence,
|
||||
r = amdgpu_fill_buffer(entity, abo, 0, NULL, &wipe_fence,
|
||||
AMDGPU_KERNEL_JOB_ID_MOVE_BLIT);
|
||||
if (r) {
|
||||
goto error;
|
||||
|
|
@ -854,25 +858,15 @@ static void amdgpu_ttm_gart_bind_gfx9_mqd(struct amdgpu_device *adev,
|
|||
int num_xcc = max(1U, adev->gfx.num_xcc_per_xcp);
|
||||
uint64_t page_idx, pages_per_xcc;
|
||||
int i;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
|
||||
pages_per_xcc = total_pages;
|
||||
do_div(pages_per_xcc, num_xcc);
|
||||
|
||||
for (i = 0, page_idx = 0; i < num_xcc; i++, page_idx += pages_per_xcc) {
|
||||
/* MQD page: use default flags */
|
||||
amdgpu_gart_bind(adev,
|
||||
amdgpu_gart_map_gfx9_mqd(adev,
|
||||
gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
1, >t->ttm.dma_address[page_idx], flags);
|
||||
/*
|
||||
* Ctrl pages - modify the memory type to NC (ctrl_flags) from
|
||||
* the second page of the BO onward.
|
||||
*/
|
||||
amdgpu_gart_bind(adev,
|
||||
gtt->offset + ((page_idx + 1) << PAGE_SHIFT),
|
||||
pages_per_xcc - 1,
|
||||
>t->ttm.dma_address[page_idx + 1],
|
||||
ctrl_flags);
|
||||
pages_per_xcc, >t->ttm.dma_address[page_idx],
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2345,8 +2339,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
|||
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
u32 num_clear_entities, num_move_entities;
|
||||
uint64_t size;
|
||||
int r;
|
||||
int r, i, j;
|
||||
|
||||
if (!adev->mman.initialized || amdgpu_in_reset(adev) ||
|
||||
adev->mman.buffer_funcs_enabled == enable || adev->gmc.is_app_apu)
|
||||
|
|
@ -2361,6 +2356,8 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
num_clear_entities = 1;
|
||||
num_move_entities = 1;
|
||||
ring = adev->mman.buffer_funcs_ring;
|
||||
sched = &ring->sched;
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
|
|
@ -2373,36 +2370,64 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity,
|
||||
DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, 1);
|
||||
if (r < 0) {
|
||||
dev_err(adev->dev,
|
||||
"Failed setting up TTM BO clear entity (%d)\n", r);
|
||||
adev->mman.clear_entities = kcalloc(num_clear_entities,
|
||||
sizeof(struct amdgpu_ttm_buffer_entity),
|
||||
GFP_KERNEL);
|
||||
atomic_set(&adev->mman.next_clear_entity, 0);
|
||||
if (!adev->mman.clear_entities)
|
||||
goto error_free_default_entity;
|
||||
|
||||
adev->mman.num_clear_entities = num_clear_entities;
|
||||
|
||||
for (i = 0; i < num_clear_entities; i++) {
|
||||
r = amdgpu_ttm_buffer_entity_init(
|
||||
&adev->mman.gtt_mgr, &adev->mman.clear_entities[i],
|
||||
DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 1);
|
||||
|
||||
if (r < 0) {
|
||||
for (j = 0; j < i; j++)
|
||||
amdgpu_ttm_buffer_entity_fini(
|
||||
&adev->mman.gtt_mgr, &adev->mman.clear_entities[j]);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.num_clear_entities = 0;
|
||||
adev->mman.clear_entities = NULL;
|
||||
goto error_free_default_entity;
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entity,
|
||||
DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, 2);
|
||||
if (r < 0) {
|
||||
dev_err(adev->dev,
|
||||
"Failed setting up TTM BO move entity (%d)\n", r);
|
||||
goto error_free_clear_entity;
|
||||
adev->mman.num_move_entities = num_move_entities;
|
||||
atomic_set(&adev->mman.next_move_entity, 0);
|
||||
for (i = 0; i < num_move_entities; i++) {
|
||||
r = amdgpu_ttm_buffer_entity_init(
|
||||
&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entities[i],
|
||||
DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 2);
|
||||
|
||||
if (r < 0) {
|
||||
for (j = 0; j < i; j++)
|
||||
amdgpu_ttm_buffer_entity_fini(
|
||||
&adev->mman.gtt_mgr, &adev->mman.move_entities[j]);
|
||||
adev->mman.num_move_entities = 0;
|
||||
goto error_free_clear_entities;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.default_entity);
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity);
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entity);
|
||||
for (i = 0; i < adev->mman.num_clear_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entities[i]);
|
||||
for (i = 0; i < adev->mman.num_move_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entities[i]);
|
||||
/* Drop all the old fences since re-creating the scheduler entities
|
||||
* will allocate new contexts.
|
||||
*/
|
||||
ttm_resource_manager_cleanup(man);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.clear_entities = NULL;
|
||||
adev->mman.num_clear_entities = 0;
|
||||
adev->mman.num_move_entities = 0;
|
||||
}
|
||||
|
||||
/* this just adjusts TTM size idea, which sets lpfn to the correct value */
|
||||
|
|
@ -2415,9 +2440,13 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
|
||||
return;
|
||||
|
||||
error_free_clear_entity:
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity);
|
||||
error_free_clear_entities:
|
||||
for (i = 0; i < adev->mman.num_clear_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entities[i]);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.clear_entities = NULL;
|
||||
adev->mman.num_clear_entities = 0;
|
||||
error_free_default_entity:
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.default_entity);
|
||||
|
|
@ -2567,8 +2596,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
|||
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
entity = &adev->mman.clear_entity;
|
||||
entity = &adev->mman.clear_entities[0];
|
||||
*fence = dma_fence_get_stub();
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
|
||||
|
|
@ -2620,11 +2648,8 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
|
|||
struct amdgpu_res_cursor dst;
|
||||
int r;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
dev_err(adev->dev,
|
||||
"Trying to clear memory with ring turned off.\n");
|
||||
if (!entity)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst);
|
||||
|
||||
|
|
@ -2660,6 +2685,20 @@ error:
|
|||
return r;
|
||||
}
|
||||
|
||||
struct amdgpu_ttm_buffer_entity *
|
||||
amdgpu_ttm_next_clear_entity(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mman *mman = &adev->mman;
|
||||
u32 i;
|
||||
|
||||
if (mman->num_clear_entities == 0)
|
||||
return NULL;
|
||||
|
||||
i = atomic_inc_return(&mman->next_clear_entity) %
|
||||
mman->num_clear_entities;
|
||||
return &mman->clear_entities[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_evict_resources - evict memory buffers
|
||||
* @adev: amdgpu device object
|
||||
|
|
|
|||
|
|
@ -72,8 +72,12 @@ struct amdgpu_mman {
|
|||
|
||||
/* @default_entity: for workarounds, has no gart windows */
|
||||
struct amdgpu_ttm_buffer_entity default_entity;
|
||||
struct amdgpu_ttm_buffer_entity clear_entity;
|
||||
struct amdgpu_ttm_buffer_entity move_entity;
|
||||
struct amdgpu_ttm_buffer_entity *clear_entities;
|
||||
atomic_t next_clear_entity;
|
||||
u32 num_clear_entities;
|
||||
struct amdgpu_ttm_buffer_entity move_entities[TTM_NUM_MOVE_FENCES];
|
||||
atomic_t next_move_entity;
|
||||
u32 num_move_entities;
|
||||
|
||||
struct amdgpu_vram_mgr vram_mgr;
|
||||
struct amdgpu_gtt_mgr gtt_mgr;
|
||||
|
|
@ -191,6 +195,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
|
|||
struct dma_resv *resv,
|
||||
struct dma_fence **f,
|
||||
u64 k_job_id);
|
||||
struct amdgpu_ttm_buffer_entity *amdgpu_ttm_next_clear_entity(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo);
|
||||
void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo);
|
||||
|
|
|
|||
|
|
@ -600,6 +600,13 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
|
|||
goto unpin_bo;
|
||||
}
|
||||
|
||||
/* Validate doorbell_offset is within the doorbell BO */
|
||||
if ((u64)db_info->doorbell_offset * db_size + db_size >
|
||||
amdgpu_bo_size(db_obj->obj)) {
|
||||
r = -EINVAL;
|
||||
goto unpin_bo;
|
||||
}
|
||||
|
||||
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
|
||||
db_info->doorbell_offset, db_size);
|
||||
drm_dbg_driver(adev_to_drm(uq_mgr->adev),
|
||||
|
|
@ -997,6 +1004,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
unsigned long queue_id;
|
||||
int ret = 0, r;
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
/* Resume all the queues for this process */
|
||||
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
|
||||
|
||||
|
|
@ -1012,6 +1020,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
ret = r;
|
||||
|
||||
}
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
if (ret)
|
||||
drm_file_err(uq_mgr->file, "Failed to map all the queues\n");
|
||||
|
|
@ -1215,23 +1224,21 @@ static void amdgpu_userq_restore_worker(struct work_struct *work)
|
|||
struct dma_fence *ev_fence;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
ev_fence = amdgpu_evf_mgr_get_fence(&fpriv->evf_mgr);
|
||||
if (!dma_fence_is_signaled(ev_fence))
|
||||
goto unlock;
|
||||
goto put_fence;
|
||||
|
||||
ret = amdgpu_userq_vm_validate(uq_mgr);
|
||||
if (ret) {
|
||||
drm_file_err(uq_mgr->file, "Failed to validate BOs to restore\n");
|
||||
goto unlock;
|
||||
goto put_fence;
|
||||
}
|
||||
|
||||
ret = amdgpu_userq_restore_all(uq_mgr);
|
||||
if (ret)
|
||||
drm_file_err(uq_mgr->file, "Failed to restore all queues\n");
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
put_fence:
|
||||
dma_fence_put(ev_fence);
|
||||
}
|
||||
|
||||
|
|
@ -1454,17 +1461,19 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
|
|||
|
||||
if (!adev->userq_halt_for_enforce_isolation)
|
||||
dev_warn(adev->dev, "userq scheduling already started!\n");
|
||||
|
||||
adev->userq_halt_for_enforce_isolation = false;
|
||||
|
||||
xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
|
||||
uqm = queue->userq_mgr;
|
||||
mutex_lock(&uqm->userq_mutex);
|
||||
if (((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
||||
(queue->queue_type == AMDGPU_HW_IP_COMPUTE)) &&
|
||||
(queue->xcp_id == idx)) {
|
||||
if (((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
||||
(queue->queue_type == AMDGPU_HW_IP_COMPUTE)) &&
|
||||
(queue->xcp_id == idx)) {
|
||||
r = amdgpu_userq_restore_helper(queue);
|
||||
if (r)
|
||||
ret = r;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&uqm->userq_mutex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -328,11 +328,9 @@ static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
|
|||
return r;
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "allocating fence slot failed (%d)\n", r);
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
||||
if (r)
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
||||
domain = amdgpu_display_supported_domains(adev, rbo->flags);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ struct amdgpu_bo_vm;
|
|||
#define AMDGPU_VA_RESERVED_SEQ64_SIZE (2ULL << 20)
|
||||
#define AMDGPU_VA_RESERVED_SEQ64_START(adev) (AMDGPU_VA_RESERVED_CSA_START(adev) \
|
||||
- AMDGPU_VA_RESERVED_SEQ64_SIZE)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_SIZE (2ULL << 12)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_SIZE (1ULL << 16)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_START(adev) (AMDGPU_VA_RESERVED_SEQ64_START(adev) \
|
||||
- AMDGPU_VA_RESERVED_TRAP_SIZE)
|
||||
#define AMDGPU_VA_RESERVED_BOTTOM (1ULL << 16)
|
||||
|
|
|
|||
|
|
@ -1722,6 +1722,20 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case IP_VERSION(11, 5, 4):
|
||||
adev->gfx.cleaner_shader_ptr = gfx_11_0_3_cleaner_shader_hex;
|
||||
adev->gfx.cleaner_shader_size = sizeof(gfx_11_0_3_cleaner_shader_hex);
|
||||
if (adev->gfx.me_fw_version >= 4 &&
|
||||
adev->gfx.pfp_fw_version >= 7 &&
|
||||
adev->gfx.mec_fw_version >= 5) {
|
||||
adev->gfx.enable_cleaner_shader = true;
|
||||
r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size);
|
||||
if (r) {
|
||||
adev->gfx.enable_cleaner_shader = false;
|
||||
dev_err(adev->dev, "Failed to initialize cleaner shader\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
adev->gfx.enable_cleaner_shader = false;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_GDDR6;
|
||||
adev->gmc.vram_width = 1 * 128; /* numchan * chansize */
|
||||
} else {
|
||||
r = amdgpu_atomfirmware_get_vram_info(adev,
|
||||
r = amdgpu_gmc_get_vram_info(adev,
|
||||
&vram_width, &vram_type, &vram_vendor);
|
||||
adev->gmc.vram_width = vram_width;
|
||||
|
||||
|
|
|
|||
|
|
@ -751,7 +751,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
spin_lock_init(&adev->gmc.invalidate_lock);
|
||||
|
||||
r = amdgpu_atomfirmware_get_vram_info(adev,
|
||||
r = amdgpu_gmc_get_vram_info(adev,
|
||||
&vram_width, &vram_type, &vram_vendor);
|
||||
adev->gmc.vram_width = vram_width;
|
||||
|
||||
|
|
|
|||
|
|
@ -825,7 +825,7 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) {
|
||||
gmc_v12_1_init_vram_info(adev);
|
||||
} else {
|
||||
r = amdgpu_atomfirmware_get_vram_info(adev,
|
||||
r = amdgpu_gmc_get_vram_info(adev,
|
||||
&vram_width, &vram_type, &vram_vendor);
|
||||
adev->gmc.vram_width = vram_width;
|
||||
adev->gmc.vram_type = vram_type;
|
||||
|
|
|
|||
|
|
@ -1823,24 +1823,37 @@ static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
|
|||
adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
|
||||
}
|
||||
|
||||
static void gmc_v9_4_3_init_vram_info(struct amdgpu_device *adev)
|
||||
static void gmc_v9_0_init_vram_info(struct amdgpu_device *adev)
|
||||
{
|
||||
static const u32 regBIF_BIOS_SCRATCH_4 = 0x50;
|
||||
int dev_var = adev->pdev->device & 0xF;
|
||||
u32 vram_info;
|
||||
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
adev->gmc.vram_width = 128 * 64;
|
||||
if (adev->gmc.is_app_apu) {
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
adev->gmc.vram_width = 128 * 64;
|
||||
} else if (adev->flags & AMD_IS_APU) {
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
|
||||
adev->gmc.vram_width = 64 * 64;
|
||||
} else if (amdgpu_is_multi_aid(adev)) {
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
adev->gmc.vram_width = 128 * 64;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0))
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0))
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
|
||||
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) &&
|
||||
adev->rev_id == 0x3)
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) &&
|
||||
adev->rev_id == 0x3)
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU) && !amdgpu_sriov_vf(adev)) {
|
||||
vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
|
||||
adev->gmc.vram_vendor = vram_info & 0xF;
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) &&
|
||||
(dev_var == 0x5))
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM3E;
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU) && !amdgpu_sriov_vf(adev)) {
|
||||
vram_info = RREG32(regBIF_BIOS_SCRATCH_4);
|
||||
adev->gmc.vram_vendor = vram_info & 0xF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1856,19 +1869,11 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
spin_lock_init(&adev->gmc.invalidate_lock);
|
||||
|
||||
if (amdgpu_is_multi_aid(adev)) {
|
||||
gmc_v9_4_3_init_vram_info(adev);
|
||||
} else if (!adev->bios) {
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_DDR4;
|
||||
adev->gmc.vram_width = 64 * 64;
|
||||
} else {
|
||||
adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
adev->gmc.vram_width = 128 * 64;
|
||||
}
|
||||
if (!adev->bios) {
|
||||
gmc_v9_0_init_vram_info(adev);
|
||||
} else {
|
||||
r = amdgpu_atomfirmware_get_vram_info(adev,
|
||||
&vram_width, &vram_type, &vram_vendor);
|
||||
r = amdgpu_gmc_get_vram_info(adev,
|
||||
&vram_width, &vram_type, &vram_vendor);
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
/* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
|
||||
* and DF related registers is not readable, seems hardcord is the
|
||||
|
|
@ -1896,6 +1901,7 @@ static int gmc_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
adev->gmc.vram_type = vram_type;
|
||||
adev->gmc.vram_vendor = vram_vendor;
|
||||
}
|
||||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(9, 1, 0):
|
||||
case IP_VERSION(9, 2, 2):
|
||||
|
|
|
|||
|
|
@ -324,8 +324,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
|||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
|
||||
2048);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(compute_mqd);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
userq_props->eop_gpu_addr = compute_mqd->eop_va;
|
||||
userq_props->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_NORMAL;
|
||||
|
|
@ -365,12 +367,16 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
|||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
|
||||
shadow_info.shadow_size);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
|
||||
shadow_info.csa_size);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
kfree(mqd_gfx_v11);
|
||||
} else if (queue->queue_type == AMDGPU_HW_IP_DMA) {
|
||||
|
|
@ -390,8 +396,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
|||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
|
||||
32);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_sdma_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
userq_props->csa_addr = mqd_sdma_v11->csa_va;
|
||||
kfree(mqd_sdma_v11);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
|
|||
int retry_loop;
|
||||
|
||||
/* For a reset done at the end of S3, only wait for TOS to be unloaded */
|
||||
if (adev->in_s3 && !(adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev))
|
||||
if ((adev->in_s4 || adev->in_s3) && !(adev->flags & AMD_IS_APU) &&
|
||||
amdgpu_in_reset(adev))
|
||||
return psp_v11_wait_for_tos_unload(psp);
|
||||
|
||||
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ static void uvd_v4_2_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
static int uvd_v4_2_early_init(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
/* UVD doesn't work without DPM, it needs DPM to ungate it. */
|
||||
if (!amdgpu_dpm)
|
||||
return -ENOENT;
|
||||
|
||||
adev->uvd.num_uvd_inst = 1;
|
||||
|
||||
uvd_v4_2_set_ring_funcs(adev);
|
||||
|
|
|
|||
|
|
@ -144,9 +144,10 @@ enum SQ_INTERRUPT_ERROR_TYPE {
|
|||
#define KFD_CTXID0_DOORBELL_ID(ctxid0) ((ctxid0) & \
|
||||
KFD_CTXID0_DOORBELL_ID_MASK)
|
||||
|
||||
static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
|
||||
static void print_sq_intr_info_auto(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
|
||||
{
|
||||
pr_debug_ratelimited(
|
||||
dev_dbg_ratelimited(
|
||||
dev->adev->dev,
|
||||
"sq_intr: auto, ttrace %d, wlt %d, ttrace_buf0_full %d, ttrace_buf1_full %d ttrace_utc_err %d\n",
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, THREAD_TRACE),
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, WLT),
|
||||
|
|
@ -155,9 +156,10 @@ static void print_sq_intr_info_auto(uint32_t context_id0, uint32_t context_id1)
|
|||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_AUTO_CTXID0, THREAD_TRACE_UTC_ERROR));
|
||||
}
|
||||
|
||||
static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
|
||||
static void print_sq_intr_info_inst(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
|
||||
{
|
||||
pr_debug_ratelimited(
|
||||
dev_dbg_ratelimited(
|
||||
dev->adev->dev,
|
||||
"sq_intr: inst, data 0x%08x, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, DATA),
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_WAVE_CTXID0, SA_ID),
|
||||
|
|
@ -167,9 +169,10 @@ static void print_sq_intr_info_inst(uint32_t context_id0, uint32_t context_id1)
|
|||
REG_GET_FIELD(context_id1, SQ_INTERRUPT_WORD_WAVE_CTXID1, WGP_ID));
|
||||
}
|
||||
|
||||
static void print_sq_intr_info_error(uint32_t context_id0, uint32_t context_id1)
|
||||
static void print_sq_intr_info_error(struct kfd_node *dev, uint32_t context_id0, uint32_t context_id1)
|
||||
{
|
||||
pr_debug_ratelimited(
|
||||
dev_warn_ratelimited(
|
||||
dev->adev->dev,
|
||||
"sq_intr: error, detail 0x%08x, type %d, sh %d, priv %d, wave_id %d, simd_id %d, wgp_id %d\n",
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, DETAIL),
|
||||
REG_GET_FIELD(context_id0, SQ_INTERRUPT_WORD_ERROR_CTXID0, TYPE),
|
||||
|
|
@ -246,7 +249,8 @@ static bool event_interrupt_isr_v12_1(struct kfd_node *node,
|
|||
vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
|
||||
|
||||
if (!kfd_irq_is_from_node(node, node_id, vmid)) {
|
||||
pr_debug("Interrupt not for Node, node_id: %d, vmid: %d\n", node_id, vmid);
|
||||
dev_dbg_ratelimited(node->adev->dev,
|
||||
"Interrupt not for Node, node_id: %d, vmid: %d\n", node_id, vmid);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -266,9 +270,9 @@ static bool event_interrupt_isr_v12_1(struct kfd_node *node,
|
|||
(context_id0 & AMDGPU_FENCE_MES_QUEUE_FLAG))
|
||||
return false;
|
||||
|
||||
pr_debug("client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n",
|
||||
dev_dbg(node->adev->dev, "client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n",
|
||||
client_id, source_id, vmid, pasid);
|
||||
pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
|
||||
dev_dbg(node->adev->dev, "%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n",
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[4], data[5], data[6], data[7]);
|
||||
|
||||
|
|
@ -361,10 +365,10 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
|
|||
SQ_INTERRUPT_WORD_WAVE_CTXID1, ENCODING);
|
||||
switch (sq_int_enc) {
|
||||
case SQ_INTERRUPT_WORD_ENCODING_AUTO:
|
||||
print_sq_intr_info_auto(context_id0, context_id1);
|
||||
print_sq_intr_info_auto(node, context_id0, context_id1);
|
||||
break;
|
||||
case SQ_INTERRUPT_WORD_ENCODING_INST:
|
||||
print_sq_intr_info_inst(context_id0, context_id1);
|
||||
print_sq_intr_info_inst(node, context_id0, context_id1);
|
||||
sq_int_priv = REG_GET_FIELD(context_id0,
|
||||
SQ_INTERRUPT_WORD_WAVE_CTXID0, PRIV);
|
||||
if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(node, pasid,
|
||||
|
|
@ -374,7 +378,7 @@ static void event_interrupt_wq_v12_1(struct kfd_node *node,
|
|||
return;
|
||||
break;
|
||||
case SQ_INTERRUPT_WORD_ENCODING_ERROR:
|
||||
print_sq_intr_info_error(context_id0, context_id1);
|
||||
print_sq_intr_info_error(node, context_id0, context_id1);
|
||||
sq_int_errtype = REG_GET_FIELD(context_id0,
|
||||
SQ_INTERRUPT_WORD_ERROR_CTXID0, TYPE);
|
||||
if (sq_int_errtype != SQ_INTERRUPT_ERROR_TYPE_ILLEGAL_INST &&
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys,
|
|||
u64 size;
|
||||
int r;
|
||||
|
||||
entity = &adev->mman.move_entity;
|
||||
entity = &adev->mman.move_entities[0];
|
||||
|
||||
mutex_lock(&entity->lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,16 @@ static uint64_t mqd_stride_v9(struct mqd_manager *mm,
|
|||
struct queue_properties *q)
|
||||
{
|
||||
if (mm->dev->kfd->cwsr_enabled &&
|
||||
q->type == KFD_QUEUE_TYPE_COMPUTE)
|
||||
return ALIGN(q->ctl_stack_size, PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE);
|
||||
q->type == KFD_QUEUE_TYPE_COMPUTE) {
|
||||
|
||||
/* On gfxv9, the MQD resides in the first 4K page,
|
||||
* followed by the control stack. Align both to
|
||||
* AMDGPU_GPU_PAGE_SIZE to maintain the required 4K boundary.
|
||||
*/
|
||||
|
||||
return ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE);
|
||||
}
|
||||
|
||||
return mm->mqd_size;
|
||||
}
|
||||
|
|
@ -150,8 +157,8 @@ static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
|||
if (!mqd_mem_obj)
|
||||
return NULL;
|
||||
retval = amdgpu_amdkfd_alloc_kernel_mem(node->adev,
|
||||
(ALIGN(q->ctl_stack_size, PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
|
||||
(ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE)) *
|
||||
NUM_XCC(node->xcc_mask),
|
||||
mqd_on_vram(node->adev) ? AMDGPU_GEM_DOMAIN_VRAM :
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
|
|
@ -359,7 +366,7 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
|||
struct kfd_context_save_area_header header;
|
||||
|
||||
/* Control stack is located one page after MQD. */
|
||||
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
|
||||
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
|
|
@ -399,7 +406,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
|
|||
{
|
||||
struct v9_mqd *m;
|
||||
/* Control stack is located one page after MQD. */
|
||||
void *ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
|
||||
void *ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
|
|
@ -445,7 +452,7 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
|||
*gart_addr = addr;
|
||||
|
||||
/* Control stack is located one page after MQD. */
|
||||
ctl_stack = (void *)((uintptr_t)*mqd + PAGE_SIZE);
|
||||
ctl_stack = (void *)((uintptr_t)*mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
memcpy(ctl_stack, ctl_stack_src, ctl_stack_size);
|
||||
|
||||
m->cp_hqd_pq_doorbell_control =
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@
|
|||
* The first chunk is the TBA used for the CWSR ISA code. The second
|
||||
* chunk is used as TMA for user-mode trap handler setup in daisy-chain mode.
|
||||
*/
|
||||
#define KFD_CWSR_TBA_TMA_SIZE (PAGE_SIZE * 2)
|
||||
#define KFD_CWSR_TMA_OFFSET (PAGE_SIZE + 2048)
|
||||
#define KFD_CWSR_TBA_TMA_SIZE (AMDGPU_GPU_PAGE_SIZE * 2)
|
||||
#define KFD_CWSR_TMA_OFFSET (AMDGPU_GPU_PAGE_SIZE + 2048)
|
||||
|
||||
#define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \
|
||||
(KFD_MAX_NUM_OF_PROCESSES * \
|
||||
|
|
|
|||
|
|
@ -679,7 +679,7 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
|
|||
|
||||
void kfd_procfs_del_queue(struct queue *q)
|
||||
{
|
||||
if (!q)
|
||||
if (!q || !q->process->kobj)
|
||||
return;
|
||||
|
||||
kobject_del(&q->kobj);
|
||||
|
|
@ -858,6 +858,7 @@ int kfd_create_process_sysfs(struct kfd_process *process)
|
|||
if (ret) {
|
||||
pr_warn("Creating procfs pid directory failed");
|
||||
kobject_put(process->kobj);
|
||||
process->kobj = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,10 +249,10 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
|
|||
topo_dev->node_props.gfx_target_version < 90000)
|
||||
/* metadata_queue_size not supported on GFX7/GFX8 */
|
||||
expected_queue_size =
|
||||
properties->queue_size / 2;
|
||||
PAGE_ALIGN(properties->queue_size / 2);
|
||||
else
|
||||
expected_queue_size =
|
||||
properties->queue_size + properties->metadata_queue_size;
|
||||
PAGE_ALIGN(properties->queue_size + properties->metadata_queue_size);
|
||||
|
||||
vm = drm_priv_to_vm(pdd->drm_priv);
|
||||
err = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
|
|
@ -492,10 +492,11 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
|
|||
cu_num = props->simd_count / props->simd_per_cu / NUM_XCC(dev->gpu->xcc_mask);
|
||||
wave_num = get_num_waves(props, gfxv, cu_num);
|
||||
|
||||
wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props), PAGE_SIZE);
|
||||
wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props),
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
ctl_stack_size = wave_num * CNTL_STACK_BYTES_PER_WAVE(gfxv) + 8;
|
||||
ctl_stack_size = ALIGN(SIZEOF_HSA_USER_CONTEXT_SAVE_AREA_HEADER + ctl_stack_size,
|
||||
PAGE_SIZE);
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
if ((gfxv / 10000 * 10000) == 100000) {
|
||||
/* HW design limits control stack size to 0x7000.
|
||||
|
|
@ -507,7 +508,7 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
|
|||
|
||||
props->ctl_stack_size = ctl_stack_size;
|
||||
props->debug_memory_size = ALIGN(wave_num * DEBUGGER_BYTES_PER_WAVE, DEBUGGER_BYTES_ALIGN);
|
||||
props->cwsr_size = ctl_stack_size + wg_data_size;
|
||||
props->cwsr_size = ALIGN(ctl_stack_size + wg_data_size, PAGE_SIZE);
|
||||
|
||||
if (gfxv == 80002) /* GFX_VERSION_TONGA */
|
||||
props->eop_buffer_size = 0x8000;
|
||||
|
|
|
|||
|
|
@ -628,9 +628,8 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange,
|
|||
}
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
|
||||
r = dma_resv_reserve_fences(bo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
||||
if (r) {
|
||||
pr_debug("failed %d to reserve bo\n", r);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
goto reserve_bo_failed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ AMDGPUDM = \
|
|||
amdgpu_dm_replay.o \
|
||||
amdgpu_dm_quirks.o \
|
||||
amdgpu_dm_wb.o \
|
||||
amdgpu_dm_colorop.o
|
||||
amdgpu_dm_colorop.o \
|
||||
amdgpu_dm_ism.o
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_FP
|
||||
AMDGPUDM += dc_fpu.o
|
||||
|
|
|
|||
|
|
@ -3283,6 +3283,7 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
mutex_lock(&dm->dc_lock);
|
||||
|
||||
amdgpu_dm_ism_disable(dm);
|
||||
dc_allow_idle_optimizations(adev->dm.dc, false);
|
||||
|
||||
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
|
||||
|
|
@ -3316,6 +3317,9 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
amdgpu_dm_irq_suspend(adev);
|
||||
|
||||
scoped_guard(mutex, &dm->dc_lock)
|
||||
amdgpu_dm_ism_disable(dm);
|
||||
|
||||
hpd_rx_irq_work_suspend(dm);
|
||||
|
||||
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
|
||||
|
|
@ -3606,6 +3610,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
dc_resume(dm->dc);
|
||||
|
||||
amdgpu_dm_ism_enable(dm);
|
||||
amdgpu_dm_irq_resume_early(adev);
|
||||
|
||||
for (i = 0; i < dc_state->stream_count; i++) {
|
||||
|
|
@ -3666,6 +3671,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
|
|||
/* program HPD filter */
|
||||
dc_resume(dm->dc);
|
||||
|
||||
scoped_guard(mutex, &dm->dc_lock)
|
||||
amdgpu_dm_ism_enable(dm);
|
||||
|
||||
/*
|
||||
* early enable HPD Rx IRQ, should be done before set mode as short
|
||||
* pulse interrupts are used for MST
|
||||
|
|
@ -5581,6 +5589,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
case IP_VERSION(3, 5, 0):
|
||||
case IP_VERSION(3, 5, 1):
|
||||
case IP_VERSION(3, 6, 0):
|
||||
case IP_VERSION(4, 2, 0):
|
||||
replay_feature_enabled = true;
|
||||
break;
|
||||
|
||||
|
|
@ -9333,31 +9342,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
|
|||
if (acrtc_state) {
|
||||
timing = &acrtc_state->stream->timing;
|
||||
|
||||
/*
|
||||
* Depending on when the HW latching event of double-buffered
|
||||
* registers happen relative to the PSR SDP deadline, and how
|
||||
* bad the Panel clock has drifted since the last ALPM off
|
||||
* event, there can be up to 3 frames of delay between sending
|
||||
* the PSR exit cmd to DMUB fw, and when the panel starts
|
||||
* displaying live frames.
|
||||
*
|
||||
* We can set:
|
||||
*
|
||||
* 20/100 * offdelay_ms = 3_frames_ms
|
||||
* => offdelay_ms = 5 * 3_frames_ms
|
||||
*
|
||||
* This ensures that `3_frames_ms` will only be experienced as a
|
||||
* 20% delay on top how long the display has been static, and
|
||||
* thus make the delay less perceivable.
|
||||
*/
|
||||
if (acrtc_state->stream->link->psr_settings.psr_version <
|
||||
DC_PSR_VERSION_UNSUPPORTED) {
|
||||
offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 *
|
||||
timing->v_total *
|
||||
timing->h_total,
|
||||
timing->pix_clk_100hz);
|
||||
config.offdelay_ms = offdelay ?: 30;
|
||||
} else if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
|
||||
IP_VERSION(3, 5, 0) ||
|
||||
!(adev->flags & AMD_IS_APU)) {
|
||||
/*
|
||||
|
|
@ -9889,7 +9874,7 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
|
|||
}
|
||||
|
||||
/* Decrement skip count when SR is enabled and we're doing fast updates. */
|
||||
if (acrtc_state->update_type <= UPDATE_TYPE_FAST &&
|
||||
if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
|
||||
(psr->psr_feature_enabled || pr->config.replay_supported)) {
|
||||
if (aconn->sr_skip_count > 0)
|
||||
aconn->sr_skip_count--;
|
||||
|
|
@ -10099,7 +10084,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
* fast updates.
|
||||
*/
|
||||
if (crtc->state->async_flip &&
|
||||
(acrtc_state->update_type > UPDATE_TYPE_FAST ||
|
||||
(acrtc_state->update_type != UPDATE_TYPE_FAST ||
|
||||
get_mem_type(old_plane_state->fb) != get_mem_type(fb)))
|
||||
drm_warn_once(state->dev,
|
||||
"[PLANE:%d:%s] async flip with non-fast update\n",
|
||||
|
|
@ -10107,7 +10092,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
|
||||
bundle->flip_addrs[planes_count].flip_immediate =
|
||||
crtc->state->async_flip &&
|
||||
acrtc_state->update_type <= UPDATE_TYPE_FAST &&
|
||||
acrtc_state->update_type == UPDATE_TYPE_FAST &&
|
||||
get_mem_type(old_plane_state->fb) == get_mem_type(fb);
|
||||
|
||||
timestamp_ns = ktime_get_ns();
|
||||
|
|
|
|||
|
|
@ -124,37 +124,37 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
|
|||
* - Enable condition same as above
|
||||
* - Disable when vblank counter is enabled
|
||||
*/
|
||||
static void amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
struct vblank_control_work *vblank_work,
|
||||
void amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_crtc *acrtc,
|
||||
struct dc_stream_state *stream,
|
||||
bool vblank_enabled, bool allow_sr_entry)
|
||||
{
|
||||
struct dc_link *link = vblank_work->stream->link;
|
||||
struct dc_link *link = stream->link;
|
||||
bool is_sr_active = (link->replay_settings.replay_allow_active ||
|
||||
link->psr_settings.psr_allow_active);
|
||||
bool is_crc_window_active = false;
|
||||
bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(vblank_work->acrtc);
|
||||
bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
|
||||
is_crc_window_active =
|
||||
amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base);
|
||||
amdgpu_dm_crc_window_is_activated(&acrtc->base);
|
||||
#endif
|
||||
|
||||
if (link->replay_settings.replay_feature_enabled && !vrr_active &&
|
||||
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
|
||||
amdgpu_dm_replay_enable(vblank_work->stream, true);
|
||||
amdgpu_dm_replay_enable(stream, true);
|
||||
} else if (vblank_enabled) {
|
||||
if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active)
|
||||
amdgpu_dm_psr_disable(vblank_work->stream, false);
|
||||
amdgpu_dm_psr_disable(stream, false);
|
||||
} else if (link->psr_settings.psr_feature_enabled && !vrr_active &&
|
||||
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
|
||||
|
||||
struct amdgpu_dm_connector *aconn =
|
||||
(struct amdgpu_dm_connector *) vblank_work->stream->dm_stream_context;
|
||||
(struct amdgpu_dm_connector *) stream->dm_stream_context;
|
||||
|
||||
if (!aconn->disallow_edp_enter_psr) {
|
||||
struct amdgpu_display_manager *dm = vblank_work->dm;
|
||||
|
||||
amdgpu_dm_psr_enable(vblank_work->stream);
|
||||
amdgpu_dm_psr_enable(stream);
|
||||
if (dm->idle_workqueue &&
|
||||
(dm->dc->config.disable_ips == DMUB_IPS_ENABLE) &&
|
||||
dm->dc->idle_optimizations_allowed &&
|
||||
|
|
@ -251,33 +251,15 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
|
|||
|
||||
mutex_lock(&dm->dc_lock);
|
||||
|
||||
if (vblank_work->enable)
|
||||
if (vblank_work->enable) {
|
||||
dm->active_vblank_irq_count++;
|
||||
else if (dm->active_vblank_irq_count)
|
||||
dm->active_vblank_irq_count--;
|
||||
|
||||
if (dm->active_vblank_irq_count > 0)
|
||||
dc_allow_idle_optimizations(dm->dc, false);
|
||||
|
||||
/*
|
||||
* Control PSR based on vblank requirements from OS
|
||||
*
|
||||
* If panel supports PSR SU, there's no need to disable PSR when OS is
|
||||
* submitting fast atomic commits (we infer this by whether the OS
|
||||
* requests vblank events). Fast atomic commits will simply trigger a
|
||||
* full-frame-update (FFU); a specific case of selective-update (SU)
|
||||
* where the SU region is the full hactive*vactive region. See
|
||||
* fill_dc_dirty_rects().
|
||||
*/
|
||||
if (vblank_work->stream && vblank_work->stream->link && vblank_work->acrtc) {
|
||||
amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
vblank_work, vblank_work->enable,
|
||||
vblank_work->acrtc->dm_irq_params.allow_sr_entry);
|
||||
}
|
||||
|
||||
if (dm->active_vblank_irq_count == 0) {
|
||||
dc_post_update_surfaces_to_stream(dm->dc);
|
||||
dc_allow_idle_optimizations(dm->dc, true);
|
||||
amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
|
||||
} else {
|
||||
if (dm->active_vblank_irq_count > 0)
|
||||
dm->active_vblank_irq_count--;
|
||||
amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
|
||||
DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
|
||||
}
|
||||
|
||||
mutex_unlock(&dm->dc_lock);
|
||||
|
|
@ -476,6 +458,9 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
|
|||
|
||||
static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
||||
|
||||
amdgpu_dm_ism_fini(&acrtc->ism);
|
||||
drm_crtc_cleanup(crtc);
|
||||
kfree(crtc);
|
||||
}
|
||||
|
|
@ -685,7 +670,7 @@ static int amdgpu_dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
|
|||
* pitch, the DCC state, rotation, etc.
|
||||
*/
|
||||
if (crtc_state->async_flip &&
|
||||
dm_crtc_state->update_type > UPDATE_TYPE_FAST) {
|
||||
dm_crtc_state->update_type != UPDATE_TYPE_FAST) {
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"[CRTC:%d:%s] async flips are only supported for fast updates\n",
|
||||
crtc->base.id, crtc->name);
|
||||
|
|
@ -719,6 +704,35 @@ static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
|
|||
.get_scanout_position = amdgpu_crtc_get_scanout_position,
|
||||
};
|
||||
|
||||
/*
|
||||
* This hysteresis filter as configured will:
|
||||
*
|
||||
* * Search through the latest 8[filter_history_size] entries in history,
|
||||
* skipping entries that are older than [filter_old_history_threshold] frames
|
||||
* (0 means ignore age)
|
||||
* * Searches for short-idle-periods that lasted shorter than
|
||||
* 4[filter_num_frames] frames-times
|
||||
* * If there is at least 1[filter_entry_count] short-idle-period, then a delay
|
||||
* of 4[activation_num_delay_frames] will applied before allowing idle
|
||||
* optimizations again.
|
||||
* * An additional delay of 11[sso_num_frames] is applied before enabling
|
||||
* panel-specific optimizations.
|
||||
*
|
||||
* The values were determined empirically on another OS, optimizing for Z8
|
||||
* residency on APUs when running a productivity + web browsing test.
|
||||
*
|
||||
* TODO: Run similar tests to determine if these values are also optimal for
|
||||
* Linux, and if each APU generation benefits differently.
|
||||
*/
|
||||
static struct amdgpu_dm_ism_config default_ism_config = {
|
||||
.filter_num_frames = 4,
|
||||
.filter_history_size = 8,
|
||||
.filter_entry_count = 1,
|
||||
.activation_num_delay_frames = 4,
|
||||
.filter_old_history_threshold = 0,
|
||||
.sso_num_frames = 11,
|
||||
};
|
||||
|
||||
int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
||||
struct drm_plane *plane,
|
||||
uint32_t crtc_index)
|
||||
|
|
@ -749,6 +763,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
|||
if (res)
|
||||
goto fail;
|
||||
|
||||
amdgpu_dm_ism_init(&acrtc->ism, &default_ism_config);
|
||||
|
||||
drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
|
||||
|
||||
/* Create (reset) the plane state */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@
|
|||
#ifndef __AMDGPU_DM_CRTC_H__
|
||||
#define __AMDGPU_DM_CRTC_H__
|
||||
|
||||
void amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_crtc *acrtc,
|
||||
struct dc_stream_state *stream,
|
||||
bool vblank_enabled, bool allow_sr_entry);
|
||||
|
||||
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc);
|
||||
|
||||
bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,598 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "dc.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm_ism.h"
|
||||
#include "amdgpu_dm_crtc.h"
|
||||
#include "amdgpu_dm_trace.h"
|
||||
|
||||
/**
|
||||
* dm_ism_next_state - Get next state based on current state and event
|
||||
*
|
||||
* This function defines the idle state management FSM. Invalid transitions
|
||||
* are ignored and will not progress the FSM.
|
||||
*/
|
||||
static bool dm_ism_next_state(enum amdgpu_dm_ism_state current_state,
|
||||
enum amdgpu_dm_ism_event event,
|
||||
enum amdgpu_dm_ism_state *next_state)
|
||||
{
|
||||
switch (STATE_EVENT(current_state, event)) {
|
||||
case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
|
||||
DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_BUSY;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
|
||||
DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
|
||||
DM_ISM_EVENT_END_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_TIMER_ABORTED;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
DM_ISM_EVENT_TIMER_ELAPSED):
|
||||
*next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
DM_ISM_EVENT_IMMEDIATE):
|
||||
*next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_BUSY;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
|
||||
DM_ISM_EVENT_END_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
DM_ISM_EVENT_SSO_TIMER_ELAPSED):
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
DM_ISM_EVENT_IMMEDIATE):
|
||||
*next_state = DM_ISM_STATE_OPTIMIZED_IDLE_SSO;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
break;
|
||||
case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
|
||||
*next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
|
||||
break;
|
||||
|
||||
case STATE_EVENT(DM_ISM_STATE_TIMER_ABORTED,
|
||||
DM_ISM_EVENT_IMMEDIATE):
|
||||
*next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
const struct amdgpu_dm_ism_config *config = &ism->config;
|
||||
uint32_t v_total, h_total;
|
||||
uint64_t one_frame_ns, sso_delay_ns;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
if (!config->sso_num_frames)
|
||||
return 0;
|
||||
|
||||
v_total = stream->timing.v_total;
|
||||
h_total = stream->timing.h_total;
|
||||
|
||||
one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
|
||||
stream->timing.pix_clk_100hz);
|
||||
sso_delay_ns = config->sso_num_frames * one_frame_ns;
|
||||
|
||||
return sso_delay_ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_ism_get_idle_allow_delay - Calculate hysteresis-based idle allow delay
|
||||
*/
|
||||
static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
const struct amdgpu_dm_ism_config *config = &ism->config;
|
||||
uint32_t v_total, h_total;
|
||||
uint64_t one_frame_ns, short_idle_ns, old_hist_ns;
|
||||
uint32_t history_size;
|
||||
int pos;
|
||||
uint32_t short_idle_count = 0;
|
||||
uint64_t ret_ns = 0;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
if (!config->filter_num_frames)
|
||||
return 0;
|
||||
if (!config->filter_entry_count)
|
||||
return 0;
|
||||
if (!config->activation_num_delay_frames)
|
||||
return 0;
|
||||
|
||||
v_total = stream->timing.v_total;
|
||||
h_total = stream->timing.h_total;
|
||||
|
||||
one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
|
||||
stream->timing.pix_clk_100hz);
|
||||
|
||||
short_idle_ns = config->filter_num_frames * one_frame_ns;
|
||||
old_hist_ns = config->filter_old_history_threshold * one_frame_ns;
|
||||
|
||||
/*
|
||||
* Look back into the recent history and count how many times we entered
|
||||
* idle power state for a short duration of time
|
||||
*/
|
||||
history_size = min(
|
||||
max(config->filter_history_size, config->filter_entry_count),
|
||||
AMDGPU_DM_IDLE_HIST_LEN);
|
||||
pos = ism->next_record_idx;
|
||||
|
||||
for (int k = 0; k < history_size; k++) {
|
||||
if (pos <= 0 || pos > AMDGPU_DM_IDLE_HIST_LEN)
|
||||
pos = AMDGPU_DM_IDLE_HIST_LEN;
|
||||
pos -= 1;
|
||||
|
||||
if (ism->records[pos].duration_ns <= short_idle_ns)
|
||||
short_idle_count += 1;
|
||||
|
||||
if (short_idle_count >= config->filter_entry_count)
|
||||
break;
|
||||
|
||||
if (old_hist_ns > 0 &&
|
||||
ism->last_idle_timestamp_ns - ism->records[pos].timestamp_ns > old_hist_ns)
|
||||
break;
|
||||
}
|
||||
|
||||
if (short_idle_count >= config->filter_entry_count)
|
||||
ret_ns = config->activation_num_delay_frames * one_frame_ns;
|
||||
|
||||
return ret_ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_ism_insert_record - Insert a record into the circular history buffer
|
||||
*/
|
||||
static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
|
||||
{
|
||||
struct amdgpu_dm_ism_record *record;
|
||||
|
||||
if (ism->next_record_idx < 0 ||
|
||||
ism->next_record_idx >= AMDGPU_DM_IDLE_HIST_LEN)
|
||||
ism->next_record_idx = 0;
|
||||
|
||||
record = &ism->records[ism->next_record_idx];
|
||||
ism->next_record_idx += 1;
|
||||
|
||||
record->timestamp_ns = ktime_get_ns();
|
||||
record->duration_ns =
|
||||
record->timestamp_ns - ism->last_idle_timestamp_ns;
|
||||
}
|
||||
|
||||
|
||||
static void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism)
|
||||
{
|
||||
ism->last_idle_timestamp_ns = ktime_get_ns();
|
||||
}
|
||||
|
||||
|
||||
static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
|
||||
enum amdgpu_dm_ism_event event)
|
||||
{
|
||||
enum amdgpu_dm_ism_state next_state;
|
||||
|
||||
bool gotNextState = dm_ism_next_state(ism->current_state, event,
|
||||
&next_state);
|
||||
|
||||
if (gotNextState) {
|
||||
ism->previous_state = ism->current_state;
|
||||
ism->current_state = next_state;
|
||||
}
|
||||
|
||||
return gotNextState;
|
||||
}
|
||||
|
||||
|
||||
static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
|
||||
struct dc_stream_state *stream,
|
||||
bool vblank_enabled,
|
||||
bool allow_panel_sso)
|
||||
{
|
||||
struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
|
||||
struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
int r;
|
||||
|
||||
trace_amdgpu_dm_ism_commit(dm->active_vblank_irq_count,
|
||||
vblank_enabled,
|
||||
allow_panel_sso);
|
||||
|
||||
/*
|
||||
* If there is an active vblank requestor, or if SSO is being engaged,
|
||||
* then disallow idle optimizations.
|
||||
*/
|
||||
if (vblank_enabled || allow_panel_sso)
|
||||
dc_allow_idle_optimizations(dm->dc, false);
|
||||
|
||||
/*
|
||||
* Control PSR based on vblank requirements from OS
|
||||
*
|
||||
* If panel supports PSR SU/Replay, there's no need to exit self-refresh
|
||||
* when OS is submitting fast atomic commits, as they can allow
|
||||
* self-refresh during vblank periods.
|
||||
*/
|
||||
if (stream && stream->link) {
|
||||
/*
|
||||
* If allow_panel_sso is true when disabling vblank, allow
|
||||
* deeper panel sleep states such as PSR1 and Replay static
|
||||
* screen optimization.
|
||||
*/
|
||||
if (!vblank_enabled && allow_panel_sso) {
|
||||
amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
dm, acrtc, stream, false,
|
||||
acrtc->dm_irq_params.allow_sr_entry);
|
||||
} else if (vblank_enabled) {
|
||||
/* Make sure to exit SSO on vblank enable */
|
||||
amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
dm, acrtc, stream, true,
|
||||
acrtc->dm_irq_params.allow_sr_entry);
|
||||
}
|
||||
/*
|
||||
* Else, vblank_enabled == false and allow_panel_sso == false;
|
||||
* do nothing here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for any active drm vblank requestors on other CRTCs
|
||||
* (dm->active_vblank_irq_count) before allowing HW-wide idle
|
||||
* optimizations.
|
||||
*
|
||||
* There's no need to have a "balanced" check when disallowing idle
|
||||
* optimizations at the start of this func -- we should disallow
|
||||
* whenever there's *an* active CRTC.
|
||||
*/
|
||||
if (!vblank_enabled && dm->active_vblank_irq_count == 0) {
|
||||
dc_post_update_surfaces_to_stream(dm->dc);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to set default power profile mode\n");
|
||||
|
||||
dc_allow_idle_optimizations(dm->dc, true);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to restore the power profile mode\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
enum amdgpu_dm_ism_event ret = event;
|
||||
const struct amdgpu_dm_ism_config *config = &ism->config;
|
||||
uint64_t delay_ns, sso_delay_ns;
|
||||
|
||||
switch (ism->previous_state) {
|
||||
case DM_ISM_STATE_HYSTERESIS_WAITING:
|
||||
/*
|
||||
* Stop the timer if it was set, and we're not running from the
|
||||
* idle allow worker.
|
||||
*/
|
||||
if (ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE &&
|
||||
ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
|
||||
cancel_delayed_work(&ism->delayed_work);
|
||||
break;
|
||||
case DM_ISM_STATE_OPTIMIZED_IDLE:
|
||||
if (ism->current_state == DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
|
||||
break;
|
||||
/* If idle disallow, cancel SSO work and insert record */
|
||||
cancel_delayed_work(&ism->sso_delayed_work);
|
||||
dm_ism_insert_record(ism);
|
||||
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
|
||||
true, false);
|
||||
break;
|
||||
case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
|
||||
/* Disable idle optimization */
|
||||
dm_ism_insert_record(ism);
|
||||
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
|
||||
true, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Schedule worker */
|
||||
mod_delayed_work(system_unbound_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_num_frames is less than hysteresis frames, it
|
||||
* indicates that allowing idle here, then disallowing
|
||||
* idle after sso_num_frames has expired, will likely
|
||||
* have a negative power impact. Skip idle allow here,
|
||||
* and let the sso_delayed_work handle it.
|
||||
*/
|
||||
mod_delayed_work(system_unbound_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);
|
||||
mod_delayed_work(system_unbound_wq,
|
||||
&ism->sso_delayed_work,
|
||||
nsecs_to_jiffies(sso_delay_ns));
|
||||
}
|
||||
break;
|
||||
case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
|
||||
/* Enable static screen optimizations. */
|
||||
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
|
||||
false, true);
|
||||
break;
|
||||
case DM_ISM_STATE_TIMER_ABORTED:
|
||||
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;
|
||||
}
|
||||
|
||||
static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
|
||||
[DM_ISM_EVENT_IMMEDIATE] = "IMMEDIATE",
|
||||
[DM_ISM_EVENT_ENTER_IDLE_REQUESTED] = "ENTER_IDLE_REQUESTED",
|
||||
[DM_ISM_EVENT_EXIT_IDLE_REQUESTED] = "EXIT_IDLE_REQUESTED",
|
||||
[DM_ISM_EVENT_BEGIN_CURSOR_UPDATE] = "BEGIN_CURSOR_UPDATE",
|
||||
[DM_ISM_EVENT_END_CURSOR_UPDATE] = "END_CURSOR_UPDATE",
|
||||
[DM_ISM_EVENT_TIMER_ELAPSED] = "TIMER_ELAPSED",
|
||||
[DM_ISM_EVENT_SSO_TIMER_ELAPSED] = "SSO_TIMER_ELAPSED",
|
||||
};
|
||||
|
||||
static char *dm_ism_states_str[DM_ISM_NUM_STATES] = {
|
||||
[DM_ISM_STATE_FULL_POWER_RUNNING] = "FULL_POWER_RUNNING",
|
||||
[DM_ISM_STATE_FULL_POWER_BUSY] = "FULL_POWER_BUSY",
|
||||
[DM_ISM_STATE_HYSTERESIS_WAITING] = "HYSTERESIS_WAITING",
|
||||
[DM_ISM_STATE_HYSTERESIS_BUSY] = "HYSTERESIS_BUSY",
|
||||
[DM_ISM_STATE_OPTIMIZED_IDLE] = "OPTIMIZED_IDLE",
|
||||
[DM_ISM_STATE_OPTIMIZED_IDLE_SSO] = "OPTIMIZED_IDLE_SSO",
|
||||
[DM_ISM_STATE_TIMER_ABORTED] = "TIMER_ABORTED",
|
||||
};
|
||||
|
||||
|
||||
void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
|
||||
enum amdgpu_dm_ism_event event)
|
||||
{
|
||||
enum amdgpu_dm_ism_event next_event = event;
|
||||
struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
|
||||
struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(acrtc->base.state);
|
||||
|
||||
/* ISM transitions must be called with mutex acquired */
|
||||
ASSERT(mutex_is_locked(&dm->dc_lock));
|
||||
|
||||
if (!acrtc_state) {
|
||||
trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE",
|
||||
"NO_STATE", "N/A");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
bool transition = dm_ism_trigger_event(ism, event);
|
||||
|
||||
next_event = DM_ISM_NUM_EVENTS;
|
||||
if (transition) {
|
||||
trace_amdgpu_dm_ism_event(
|
||||
acrtc->crtc_id,
|
||||
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);
|
||||
} else {
|
||||
trace_amdgpu_dm_ism_event(
|
||||
acrtc->crtc_id,
|
||||
dm_ism_states_str[ism->current_state],
|
||||
dm_ism_states_str[ism->current_state],
|
||||
dm_ism_events_str[event]);
|
||||
}
|
||||
|
||||
event = next_event;
|
||||
|
||||
} while (next_event < DM_ISM_NUM_EVENTS);
|
||||
}
|
||||
|
||||
|
||||
static void dm_ism_delayed_work_func(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism =
|
||||
container_of(work, struct amdgpu_dm_ism, delayed_work.work);
|
||||
struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
|
||||
struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
|
||||
guard(mutex)(&dm->dc_lock);
|
||||
|
||||
amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_TIMER_ELAPSED);
|
||||
}
|
||||
|
||||
static void dm_ism_sso_delayed_work_func(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_dm_ism *ism =
|
||||
container_of(work, struct amdgpu_dm_ism, sso_delayed_work.work);
|
||||
struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
|
||||
struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
|
||||
guard(mutex)(&dm->dc_lock);
|
||||
|
||||
amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_SSO_TIMER_ELAPSED);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_ism_disable - Disable the ISM
|
||||
*
|
||||
* @dm: The amdgpu display manager
|
||||
*
|
||||
* Disable the idle state manager by disabling any ISM work, canceling pending
|
||||
* work, and waiting for in-progress work to finish. After disabling, the system
|
||||
* is left in DM_ISM_STATE_FULL_POWER_RUNNING state.
|
||||
*/
|
||||
void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct amdgpu_crtc *acrtc;
|
||||
struct amdgpu_dm_ism *ism;
|
||||
|
||||
drm_for_each_crtc(crtc, dm->ddev) {
|
||||
acrtc = to_amdgpu_crtc(crtc);
|
||||
ism = &acrtc->ism;
|
||||
|
||||
/* Cancel and disable any pending work */
|
||||
disable_delayed_work_sync(&ism->delayed_work);
|
||||
disable_delayed_work_sync(&ism->sso_delayed_work);
|
||||
|
||||
/*
|
||||
* When disabled, leave in FULL_POWER_RUNNING state.
|
||||
* EXIT_IDLE will not queue any work
|
||||
*/
|
||||
amdgpu_dm_ism_commit_event(ism,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_ism_enable - enable the ISM
|
||||
*
|
||||
* @dm: The amdgpu display manager
|
||||
*
|
||||
* Re-enable the idle state manager by enabling work that was disabled by
|
||||
* amdgpu_dm_ism_disable.
|
||||
*/
|
||||
void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct amdgpu_crtc *acrtc;
|
||||
struct amdgpu_dm_ism *ism;
|
||||
|
||||
drm_for_each_crtc(crtc, dm->ddev) {
|
||||
acrtc = to_amdgpu_crtc(crtc);
|
||||
ism = &acrtc->ism;
|
||||
|
||||
enable_delayed_work(&ism->delayed_work);
|
||||
enable_delayed_work(&ism->sso_delayed_work);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
|
||||
struct amdgpu_dm_ism_config *config)
|
||||
{
|
||||
ism->config = *config;
|
||||
|
||||
ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
|
||||
ism->next_record_idx = 0;
|
||||
ism->last_idle_timestamp_ns = 0;
|
||||
|
||||
INIT_DELAYED_WORK(&ism->delayed_work, dm_ism_delayed_work_func);
|
||||
INIT_DELAYED_WORK(&ism->sso_delayed_work, dm_ism_sso_delayed_work_func);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_DM_ISM_H__
|
||||
#define __AMDGPU_DM_ISM_H__
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct amdgpu_crtc;
|
||||
struct amdgpu_display_manager;
|
||||
|
||||
#define AMDGPU_DM_IDLE_HIST_LEN 16
|
||||
|
||||
enum amdgpu_dm_ism_state {
|
||||
DM_ISM_STATE_FULL_POWER_RUNNING,
|
||||
DM_ISM_STATE_FULL_POWER_BUSY,
|
||||
DM_ISM_STATE_HYSTERESIS_WAITING,
|
||||
DM_ISM_STATE_HYSTERESIS_BUSY,
|
||||
DM_ISM_STATE_OPTIMIZED_IDLE,
|
||||
DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
|
||||
DM_ISM_STATE_TIMER_ABORTED,
|
||||
DM_ISM_NUM_STATES,
|
||||
};
|
||||
|
||||
enum amdgpu_dm_ism_event {
|
||||
DM_ISM_EVENT_IMMEDIATE,
|
||||
DM_ISM_EVENT_ENTER_IDLE_REQUESTED,
|
||||
DM_ISM_EVENT_EXIT_IDLE_REQUESTED,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE,
|
||||
DM_ISM_EVENT_END_CURSOR_UPDATE,
|
||||
DM_ISM_EVENT_TIMER_ELAPSED,
|
||||
DM_ISM_EVENT_SSO_TIMER_ELAPSED,
|
||||
DM_ISM_NUM_EVENTS,
|
||||
};
|
||||
|
||||
#define STATE_EVENT(state, event) (((state) << 8) | (event))
|
||||
|
||||
struct amdgpu_dm_ism_config {
|
||||
|
||||
/**
|
||||
* @filter_num_frames: Idle periods shorter than this number of frames
|
||||
* will be considered a "short idle period" for filtering.
|
||||
*
|
||||
* 0 indicates no filtering (i.e. no idle allow delay will be applied)
|
||||
*/
|
||||
unsigned int filter_num_frames;
|
||||
|
||||
/**
|
||||
* @filter_history_size: Number of recent idle periods to consider when
|
||||
* counting the number of short idle periods.
|
||||
*/
|
||||
unsigned int filter_history_size;
|
||||
|
||||
/**
|
||||
* @filter_entry_count: When the number of short idle periods within
|
||||
* recent &filter_history_size reaches this count, the idle allow delay
|
||||
* will be applied.
|
||||
*
|
||||
* 0 indicates no filtering (i.e. no idle allow delay will be applied)
|
||||
*/
|
||||
unsigned int filter_entry_count;
|
||||
|
||||
/**
|
||||
* @activation_num_delay_frames: Defines the number of frames to wait
|
||||
* for the idle allow delay.
|
||||
*
|
||||
* 0 indicates no filtering (i.e. no idle allow delay will be applied)
|
||||
*/
|
||||
unsigned int activation_num_delay_frames;
|
||||
|
||||
/**
|
||||
* @filter_old_history_threshold: A time-based restriction on top of
|
||||
* &filter_history_size. Idle periods older than this threshold (in
|
||||
* number of frames) will be ignored when counting the number of short
|
||||
* idle periods.
|
||||
*
|
||||
* 0 indicates no time-based restriction, i.e. history is limited only
|
||||
* by &filter_history_size.
|
||||
*/
|
||||
unsigned int filter_old_history_threshold;
|
||||
|
||||
/**
|
||||
* @sso_num_frames: Number of frames to delay before enabling static
|
||||
* screen optimizations, such as PSR1 and Replay low HZ idle mode.
|
||||
*
|
||||
* 0 indicates immediate SSO enable upon allowing idle.
|
||||
*/
|
||||
unsigned int sso_num_frames;
|
||||
};
|
||||
|
||||
struct amdgpu_dm_ism_record {
|
||||
/**
|
||||
* @timestamp_ns: When idle was allowed
|
||||
*/
|
||||
unsigned long long timestamp_ns;
|
||||
|
||||
/**
|
||||
* @duration_ns: How long idle was allowed
|
||||
*/
|
||||
unsigned long long duration_ns;
|
||||
};
|
||||
|
||||
struct amdgpu_dm_ism {
|
||||
struct amdgpu_dm_ism_config config;
|
||||
unsigned long long last_idle_timestamp_ns;
|
||||
|
||||
enum amdgpu_dm_ism_state current_state;
|
||||
enum amdgpu_dm_ism_state previous_state;
|
||||
|
||||
struct amdgpu_dm_ism_record records[AMDGPU_DM_IDLE_HIST_LEN];
|
||||
int next_record_idx;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
struct delayed_work sso_delayed_work;
|
||||
};
|
||||
|
||||
#define ism_to_amdgpu_crtc(ism_ptr) \
|
||||
container_of(ism_ptr, struct amdgpu_crtc, ism)
|
||||
|
||||
void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
|
||||
struct amdgpu_dm_ism_config *config);
|
||||
void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism);
|
||||
void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
|
||||
enum amdgpu_dm_ism_event event);
|
||||
void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm);
|
||||
void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm);
|
||||
|
||||
#endif
|
||||
|
|
@ -954,11 +954,9 @@ static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
|
|||
return r;
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
||||
if (r)
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
||||
domain = amdgpu_display_supported_domains(adev, rbo->flags);
|
||||
|
|
@ -1374,8 +1372,16 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
|
|||
/* turn off cursor */
|
||||
if (crtc_state && crtc_state->stream) {
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
amdgpu_dm_ism_commit_event(
|
||||
&amdgpu_crtc->ism,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
|
||||
|
||||
dc_stream_program_cursor_position(crtc_state->stream,
|
||||
&position);
|
||||
|
||||
amdgpu_dm_ism_commit_event(
|
||||
&amdgpu_crtc->ism,
|
||||
DM_ISM_EVENT_END_CURSOR_UPDATE);
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
}
|
||||
return;
|
||||
|
|
@ -1405,6 +1411,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
|
|||
|
||||
if (crtc_state->stream) {
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
amdgpu_dm_ism_commit_event(
|
||||
&amdgpu_crtc->ism,
|
||||
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
|
||||
|
||||
if (!dc_stream_program_cursor_attributes(crtc_state->stream,
|
||||
&attributes))
|
||||
DRM_ERROR("DC failed to set cursor attributes\n");
|
||||
|
|
@ -1412,6 +1422,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
|
|||
if (!dc_stream_program_cursor_position(crtc_state->stream,
|
||||
&position))
|
||||
DRM_ERROR("DC failed to set cursor position\n");
|
||||
|
||||
amdgpu_dm_ism_commit_event(
|
||||
&amdgpu_crtc->ism,
|
||||
DM_ISM_EVENT_END_CURSOR_UPDATE);
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -753,6 +753,69 @@ TRACE_EVENT(amdgpu_dm_brightness,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_dm_ism_commit,
|
||||
TP_PROTO(
|
||||
int active_vblank_irq_count,
|
||||
bool vblank_enabled,
|
||||
bool allow_panel_sso
|
||||
),
|
||||
TP_ARGS(
|
||||
active_vblank_irq_count,
|
||||
vblank_enabled,
|
||||
allow_panel_sso
|
||||
),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, active_vblank_irq_count)
|
||||
__field(bool, vblank_enabled)
|
||||
__field(bool, allow_panel_sso)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->active_vblank_irq_count = active_vblank_irq_count;
|
||||
__entry->vblank_enabled = vblank_enabled;
|
||||
__entry->allow_panel_sso = allow_panel_sso;
|
||||
),
|
||||
TP_printk(
|
||||
"active_vblank_irq_count=%d vblank_enabled=%d allow_panel_sso=%d",
|
||||
__entry->active_vblank_irq_count,
|
||||
__entry->vblank_enabled,
|
||||
__entry->allow_panel_sso
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_dm_ism_event,
|
||||
TP_PROTO(
|
||||
int crtc_id,
|
||||
const char *prev_state,
|
||||
const char *curr_state,
|
||||
const char *event
|
||||
),
|
||||
TP_ARGS(
|
||||
crtc_id,
|
||||
prev_state,
|
||||
curr_state,
|
||||
event
|
||||
),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, crtc_id)
|
||||
__string(prev_state, prev_state)
|
||||
__string(curr_state, curr_state)
|
||||
__string(event, event)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->crtc_id = crtc_id;
|
||||
__assign_str(prev_state);
|
||||
__assign_str(curr_state);
|
||||
__assign_str(event);
|
||||
),
|
||||
TP_printk(
|
||||
"[CRTC %d] %s -> %s on event %s",
|
||||
__entry->crtc_id,
|
||||
__get_str(prev_state),
|
||||
__get_str(curr_state),
|
||||
__get_str(event))
|
||||
);
|
||||
|
||||
|
||||
#endif /* _AMDGPU_DM_TRACE_H_ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
|||
|
|
@ -106,11 +106,9 @@ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector
|
|||
return r;
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
|
||||
r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
|
||||
if (r)
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
domain = amdgpu_display_supported_domains(adev, rbo->flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,11 +53,30 @@ inline void dc_assert_fp_enabled(void)
|
|||
{
|
||||
int depth;
|
||||
|
||||
depth = __this_cpu_read(fpu_recursion_depth);
|
||||
depth = this_cpu_read(fpu_recursion_depth);
|
||||
|
||||
ASSERT(depth >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_assert_fp_enabled - Check if FPU protection is enabled
|
||||
*
|
||||
* This function tells if the code is already under FPU protection or not. A
|
||||
* function that works as an API for a set of FPU operations can use this
|
||||
* function for checking if the caller invoked it after DC_FP_START(). For
|
||||
* example, take a look at dcn20_fpu.c file.
|
||||
*
|
||||
* Similar to dc_assert_fp_enabled, but does not assert, returns status instead.
|
||||
*/
|
||||
inline bool dc_is_fp_enabled(void)
|
||||
{
|
||||
int depth;
|
||||
|
||||
depth = this_cpu_read(fpu_recursion_depth);
|
||||
|
||||
return (depth >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_fpu_begin - Enables FPU protection
|
||||
* @function_name: A string containing the function name for debug purposes
|
||||
|
|
@ -77,7 +96,7 @@ void dc_fpu_begin(const char *function_name, const int line)
|
|||
|
||||
WARN_ON_ONCE(!in_task());
|
||||
preempt_disable();
|
||||
depth = __this_cpu_inc_return(fpu_recursion_depth);
|
||||
depth = this_cpu_inc_return(fpu_recursion_depth);
|
||||
if (depth == 1) {
|
||||
BUG_ON(!kernel_fpu_available());
|
||||
kernel_fpu_begin();
|
||||
|
|
@ -100,7 +119,7 @@ void dc_fpu_end(const char *function_name, const int line)
|
|||
{
|
||||
int depth;
|
||||
|
||||
depth = __this_cpu_dec_return(fpu_recursion_depth);
|
||||
depth = this_cpu_dec_return(fpu_recursion_depth);
|
||||
if (depth == 0) {
|
||||
kernel_fpu_end();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -28,15 +28,30 @@
|
|||
#define __DC_FPU_H__
|
||||
|
||||
void dc_assert_fp_enabled(void);
|
||||
bool dc_is_fp_enabled(void);
|
||||
void dc_fpu_begin(const char *function_name, const int line);
|
||||
void dc_fpu_end(const char *function_name, const int line);
|
||||
|
||||
#ifndef _LINUX_FPU_COMPILATION_UNIT
|
||||
#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
|
||||
#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) \
|
||||
do { \
|
||||
bool dc_fp_enabled = dc_is_fp_enabled(); \
|
||||
if (dc_fp_enabled) \
|
||||
DC_FP_END(); \
|
||||
code; \
|
||||
if (dc_fp_enabled) \
|
||||
DC_FP_START(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
|
||||
#endif // !CONFIG_DRM_AMD_DC_FP
|
||||
#else
|
||||
#define DC_FP_START() BUILD_BUG()
|
||||
#define DC_FP_END() BUILD_BUG()
|
||||
#endif
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
|
||||
#endif // !_LINUX_FPU_COMPILATION_UNIT
|
||||
|
||||
#endif /* __DC_FPU_H__ */
|
||||
|
|
|
|||
|
|
@ -2010,10 +2010,10 @@ static void calculate_bandwidth(
|
|||
}
|
||||
/*output link bit per pixel supported*/
|
||||
for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
|
||||
data->output_bpphdmi[k] = bw_def_na;
|
||||
data->output_bppdp4_lane_hbr[k] = bw_def_na;
|
||||
data->output_bppdp4_lane_hbr2[k] = bw_def_na;
|
||||
data->output_bppdp4_lane_hbr3[k] = bw_def_na;
|
||||
data->output_bpphdmi[k] = (uint32_t)bw_def_na;
|
||||
data->output_bppdp4_lane_hbr[k] = (uint32_t)bw_def_na;
|
||||
data->output_bppdp4_lane_hbr2[k] = (uint32_t)bw_def_na;
|
||||
data->output_bppdp4_lane_hbr3[k] = (uint32_t)bw_def_na;
|
||||
if (data->enable[k]) {
|
||||
data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24)));
|
||||
if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) {
|
||||
|
|
|
|||
|
|
@ -503,6 +503,7 @@ struct fixed31_32 dc_fixpt_from_int_dy(unsigned int int_value,
|
|||
unsigned int integer_bits,
|
||||
unsigned int fractional_bits)
|
||||
{
|
||||
(void)integer_bits;
|
||||
struct fixed31_32 fixpt_value = dc_fixpt_from_int(int_value);
|
||||
|
||||
fixpt_value.value |= (long long)frac_value << (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ static bool dal_vector_presized_costruct(struct vector *vector,
|
|||
void *initial_value,
|
||||
uint32_t struct_size)
|
||||
{
|
||||
(void)ctx;
|
||||
uint32_t i;
|
||||
|
||||
vector->container = NULL;
|
||||
|
|
|
|||
|
|
@ -1963,7 +1963,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
|
|||
count = (le16_to_cpu(header->sHeader.usStructureSize)
|
||||
- sizeof(ATOM_COMMON_TABLE_HEADER))
|
||||
/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
|
||||
if (count < record->sucI2cId.bfI2C_LineMux)
|
||||
if (count <= record->sucI2cId.bfI2C_LineMux)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
/* get the GPIO_I2C_INFO */
|
||||
|
|
@ -2696,6 +2696,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
|
|||
struct slot_layout_info *slot_layout_info,
|
||||
unsigned int record_offset)
|
||||
{
|
||||
(void)i;
|
||||
unsigned int j;
|
||||
struct bios_parser *bp;
|
||||
ATOM_BRACKET_LAYOUT_RECORD *record;
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
|
|||
struct graphics_object_id object_id, uint32_t index,
|
||||
struct graphics_object_id *src_object_id)
|
||||
{
|
||||
(void)index;
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
unsigned int i;
|
||||
enum bp_result bp_result = BP_RESULT_BADINPUT;
|
||||
|
|
@ -765,6 +766,7 @@ static enum bp_result bios_parser_get_device_tag(
|
|||
uint32_t device_tag_index,
|
||||
struct connector_device_tag_info *info)
|
||||
{
|
||||
(void)device_tag_index;
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
struct atom_display_object_path_v2 *object;
|
||||
|
||||
|
|
@ -809,6 +811,7 @@ static enum bp_result get_ss_info_v4_1(
|
|||
uint32_t index,
|
||||
struct spread_spectrum_info *ss_info)
|
||||
{
|
||||
(void)index;
|
||||
enum bp_result result = BP_RESULT_OK;
|
||||
struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
|
||||
struct atom_smu_info_v3_3 *smu_info = NULL;
|
||||
|
|
@ -897,6 +900,7 @@ static enum bp_result get_ss_info_v4_2(
|
|||
uint32_t index,
|
||||
struct spread_spectrum_info *ss_info)
|
||||
{
|
||||
(void)index;
|
||||
enum bp_result result = BP_RESULT_OK;
|
||||
struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
|
||||
struct atom_smu_info_v3_1 *smu_info = NULL;
|
||||
|
|
@ -977,6 +981,7 @@ static enum bp_result get_ss_info_v4_5(
|
|||
uint32_t index,
|
||||
struct spread_spectrum_info *ss_info)
|
||||
{
|
||||
(void)index;
|
||||
enum bp_result result = BP_RESULT_OK;
|
||||
struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
|
||||
|
||||
|
|
@ -1604,6 +1609,8 @@ static uint32_t bios_parser_get_ss_entry_number(
|
|||
struct dc_bios *dcb,
|
||||
enum as_signal_type signal)
|
||||
{
|
||||
(void)dcb;
|
||||
(void)signal;
|
||||
/* TODO: DAL2 atomfirmware implementation does not need this.
|
||||
* why DAL3 need this?
|
||||
*/
|
||||
|
|
@ -3536,6 +3543,8 @@ static uint16_t bios_parser_pack_data_tables(
|
|||
struct dc_bios *dcb,
|
||||
void *dst)
|
||||
{
|
||||
(void)dcb;
|
||||
(void)dst;
|
||||
// TODO: There is data bytes alignment issue, disable it for now.
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -783,6 +783,8 @@ static enum bp_result external_encoder_control_v3(
|
|||
struct bios_parser *bp,
|
||||
struct bp_external_encoder_control *cntl)
|
||||
{
|
||||
(void)bp;
|
||||
(void)cntl;
|
||||
/* TODO */
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
|||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
(void)id;
|
||||
/* On any ASIC after DCE80, we manually program the DIG_FE
|
||||
* selection (see connect_dig_be_to_fe function of the link
|
||||
* encoder), so translation should always return 0 (no FE).
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
|||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
(void)id;
|
||||
/* On any ASIC after DCE80, we manually program the DIG_FE
|
||||
* selection (see connect_dig_be_to_fe function of the link
|
||||
* encoder), so translation should always return 0 (no FE).
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
|||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
(void)id;
|
||||
/* On any ASIC after DCE80, we manually program the DIG_FE
|
||||
* selection (see connect_dig_be_to_fe function of the link
|
||||
* encoder), so translation should always return 0 (no FE).
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ int clk_mgr_helper_get_active_plane_cnt(
|
|||
struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
(void)dc;
|
||||
int i, total_plane_count;
|
||||
|
||||
total_plane_count = 0;
|
||||
|
|
@ -97,7 +98,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
|
|||
{
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
struct dc_link *edp_link = NULL;
|
||||
int edp_num;
|
||||
unsigned int edp_num;
|
||||
unsigned int panel_inst;
|
||||
|
||||
dc_get_edp_links(dc, edp_links, &edp_num);
|
||||
|
|
@ -123,7 +124,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
|
|||
{
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
struct dc_link *edp_link = NULL;
|
||||
int edp_num;
|
||||
unsigned int edp_num;
|
||||
unsigned int panel_inst;
|
||||
|
||||
dc_get_edp_links(dc, edp_links, &edp_num);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ static int determine_sclk_from_bounding_box(
|
|||
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
|
||||
{
|
||||
uint8_t j;
|
||||
uint32_t min_vertical_blank_time = -1;
|
||||
uint32_t min_vertical_blank_time = (uint32_t)-1;
|
||||
|
||||
for (j = 0; j < context->stream_count; j++) {
|
||||
struct dc_stream_state *stream = context->streams[j];
|
||||
|
|
|
|||
|
|
@ -740,7 +740,8 @@ void rn_clk_mgr_construct(
|
|||
if (clk_mgr->base.dentist_vco_freq_khz == 0)
|
||||
clk_mgr->base.dentist_vco_freq_khz = 3600000;
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
|
||||
if (clk_mgr->periodic_retraining_disabled) {
|
||||
rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -421,10 +421,8 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
|
|||
clk_mgr_base->bw_params->dc_mode_softmax_memclk = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
|
||||
|
||||
/* Refresh bounding box */
|
||||
DC_FP_START();
|
||||
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
|
||||
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base)
|
||||
|
|
@ -523,6 +521,7 @@ void dcn3_clk_mgr_construct(
|
|||
struct pp_smu_funcs *pp_smu,
|
||||
struct dccg *dccg)
|
||||
{
|
||||
(void)pp_smu;
|
||||
struct clk_state_registers_and_bypass s = { 0 };
|
||||
|
||||
clk_mgr->base.ctx = ctx;
|
||||
|
|
|
|||
|
|
@ -733,11 +733,12 @@ void vg_clk_mgr_construct(
|
|||
if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
vg_bw_params.wm_table = lpddr5_wm_table;
|
||||
} else {
|
||||
else
|
||||
vg_bw_params.wm_table = ddr4_wm_table;
|
||||
}
|
||||
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
|
||||
|
||||
|
|
|
|||
|
|
@ -329,6 +329,9 @@ bool dcn31_are_clock_states_equal(struct dc_clocks *a,
|
|||
static void dcn31_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)regs_and_bypass;
|
||||
(void)clk_mgr_base;
|
||||
(void)log_info;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -725,11 +728,12 @@ void dcn31_clk_mgr_construct(
|
|||
/* TODO: Check we get what we expect during bringup */
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn31_bw_params.wm_table = lpddr5_wm_table;
|
||||
} else {
|
||||
else
|
||||
dcn31_bw_params.wm_table = ddr5_wm_table;
|
||||
}
|
||||
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
|
||||
&clk_mgr->base.base, &log_info);
|
||||
|
|
|
|||
|
|
@ -395,6 +395,9 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
|
|||
static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)regs_and_bypass;
|
||||
(void)clk_mgr_base;
|
||||
(void)log_info;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -842,7 +845,8 @@ void dcn314_clk_mgr_construct(
|
|||
/* TODO: Check we get what we expect during bringup */
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn314_bw_params.wm_table = lpddr5_wm_table;
|
||||
else
|
||||
dcn314_bw_params.wm_table = ddr5_wm_table;
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)regs_and_bypass;
|
||||
(void)clk_mgr_base;
|
||||
(void)log_info;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -652,11 +655,12 @@ void dcn315_clk_mgr_construct(
|
|||
if (clk_mgr->base.smu_ver > 0)
|
||||
clk_mgr->base.smu_present = true;
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn315_bw_params.wm_table = lpddr5_wm_table;
|
||||
} else {
|
||||
else
|
||||
dcn315_bw_params.wm_table = ddr5_wm_table;
|
||||
}
|
||||
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
|
||||
&clk_mgr->base.base, &log_info);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,9 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)regs_and_bypass;
|
||||
(void)clk_mgr_base;
|
||||
(void)log_info;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -636,11 +639,12 @@ void dcn316_clk_mgr_construct(
|
|||
clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */
|
||||
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn316_bw_params.wm_table = lpddr5_wm_table;
|
||||
} else {
|
||||
else
|
||||
dcn316_bw_params.wm_table = ddr4_wm_table;
|
||||
}
|
||||
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
|
||||
&clk_mgr->base.base, &log_info);
|
||||
|
|
|
|||
|
|
@ -872,6 +872,7 @@ static uint32_t dcn32_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mg
|
|||
static void dcn32_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)log_info;
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
uint32_t dprefclk_did = 0;
|
||||
uint32_t dcfclk_did = 0;
|
||||
|
|
@ -1059,11 +1060,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
|
|||
if (!clk_mgr->dpm_present)
|
||||
dcn32_patch_dpm_table(clk_mgr_base->bw_params);
|
||||
|
||||
DC_FP_START();
|
||||
/* Refresh bounding box */
|
||||
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
|
||||
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
static bool dcn32_are_clock_states_equal(struct dc_clocks *a,
|
||||
|
|
@ -1147,6 +1146,7 @@ void dcn32_clk_mgr_construct(
|
|||
struct pp_smu_funcs *pp_smu,
|
||||
struct dccg *dccg)
|
||||
{
|
||||
(void)pp_smu;
|
||||
struct clk_log_info log_info = {0};
|
||||
|
||||
clk_mgr->base.ctx = ctx;
|
||||
|
|
|
|||
|
|
@ -1464,11 +1464,12 @@ void dcn35_clk_mgr_construct(
|
|||
/* TODO: Check we get what we expect during bringup */
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
|
||||
|
||||
if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
|
||||
if (ctx->dc_bios->integrated_info &&
|
||||
ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
|
||||
dcn35_bw_params.wm_table = lpddr5_wm_table;
|
||||
} else {
|
||||
else
|
||||
dcn35_bw_params.wm_table = ddr5_wm_table;
|
||||
}
|
||||
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@ bool dcn401_is_dc_mode_present(struct clk_mgr *clk_mgr_base)
|
|||
static void dcn401_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
{
|
||||
(void)log_info;
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
uint32_t dprefclk_did = 0;
|
||||
uint32_t dcfclk_did = 0;
|
||||
|
|
@ -525,6 +526,7 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr
|
|||
struct dc_state *context,
|
||||
int ref_dtbclk_khz)
|
||||
{
|
||||
(void)ref_dtbclk_khz;
|
||||
int i;
|
||||
struct dccg *dccg = clk_mgr->dccg;
|
||||
struct pipe_ctx *otg_master;
|
||||
|
|
@ -614,6 +616,7 @@ static void dcn401_update_clocks_update_dentist(
|
|||
struct clk_mgr_internal *clk_mgr,
|
||||
struct dc_state *context)
|
||||
{
|
||||
(void)context;
|
||||
uint32_t new_disp_divider = 0;
|
||||
uint32_t new_dispclk_wdivider = 0;
|
||||
uint32_t dentist_dispclk_wdivider_readback = 0;
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@
|
|||
#define DC_LOGGER_INIT(logger) \
|
||||
struct dal_logger *dc_logger = logger
|
||||
|
||||
#define DCN42_CLKIP_REFCLK 48000
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
|
||||
|
|
@ -160,6 +158,9 @@ void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
|
|||
struct dc_state *context,
|
||||
int ref_dtbclk_khz)
|
||||
{
|
||||
(void)clk_mgr;
|
||||
(void)context;
|
||||
(void)ref_dtbclk_khz;
|
||||
/* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */
|
||||
}
|
||||
|
||||
|
|
@ -255,6 +256,10 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
}
|
||||
/* Only attempt to enable dtbclk if currently disabled AND new state requests it.
|
||||
* For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and
|
||||
* new_clocks->dtbclk_en should always be false, so this block never executes.
|
||||
*/
|
||||
if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
|
||||
int actual_dtbclk = 0;
|
||||
|
||||
|
|
@ -326,7 +331,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
}
|
||||
|
||||
/* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
|
||||
if (!dc->debug.disable_dtb_ref_clk_switch &&
|
||||
if (!dc->debug.disable_dtb_ref_clk_switch && new_clocks->dtbclk_en &&
|
||||
should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
|
||||
clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
|
||||
dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
|
||||
|
|
@ -519,7 +524,7 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
|
|||
clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
|
||||
}
|
||||
|
||||
static void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
|
||||
void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
|
||||
struct dcn42_smu_dpm_clks *smu_dpm_clks)
|
||||
{
|
||||
DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks;
|
||||
|
|
@ -833,6 +838,7 @@ void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base)
|
|||
|
||||
void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
(void)clk_mgr_base;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -842,7 +848,7 @@ static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr)
|
|||
|
||||
}
|
||||
|
||||
static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
|
||||
void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
|
||||
struct dc_state *context,
|
||||
bool safe_to_lower)
|
||||
{
|
||||
|
|
@ -895,13 +901,13 @@ static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
|
|||
// Both fclk and ref_dppclk run on the same scemi clock.
|
||||
clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
|
||||
|
||||
/* TODO: set dtbclk in correct place */
|
||||
clk_mgr->clks.dtbclk_en = true;
|
||||
|
||||
dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
|
||||
if (clk_mgr->clks.dtbclk_en) {
|
||||
dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
|
||||
} else {
|
||||
clk_mgr->clks.ref_dtbclk_khz = 0;
|
||||
}
|
||||
dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower);
|
||||
|
||||
dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
|
||||
}
|
||||
|
||||
unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
|
||||
|
|
@ -933,8 +939,9 @@ unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
|
||||
int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
(void)clk_mgr_base;
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
uint32_t dispclk_wdivider;
|
||||
int disp_divider;
|
||||
|
|
@ -954,7 +961,7 @@ bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base)
|
|||
return clk_mgr->smu_present;
|
||||
}
|
||||
|
||||
static void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
|
||||
void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
|
||||
{
|
||||
struct clk_mgr *clk_mgr_base = &clk_mgr_int->base;
|
||||
struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "clk_mgr_internal.h"
|
||||
|
||||
#define NUM_CLOCK_SOURCES 5
|
||||
#define DCN42_CLKIP_REFCLK 48000
|
||||
|
||||
struct dcn42_watermarks;
|
||||
|
||||
|
|
@ -71,9 +72,15 @@ void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base);
|
|||
void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base);
|
||||
unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type);
|
||||
bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base);
|
||||
bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
|
||||
int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps);
|
||||
bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
|
||||
void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower);
|
||||
void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz);
|
||||
bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base);
|
||||
bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
|
||||
struct dcn42_smu_dpm_clks; /* Forward declaration for pointer parameter below */
|
||||
void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42_smu_dpm_clks *smu_dpm_clks);
|
||||
void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int);
|
||||
void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower);
|
||||
int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base);
|
||||
#endif //__DCN42_CLK_MGR_H__
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -249,6 +249,7 @@ void color_space_to_black_color(
|
|||
enum dc_color_space colorspace,
|
||||
struct tg_color *black_color)
|
||||
{
|
||||
(void)dc;
|
||||
switch (colorspace) {
|
||||
case COLOR_SPACE_YCBCR601:
|
||||
case COLOR_SPACE_YCBCR709:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
|
|||
|
||||
void dc_get_edp_links(const struct dc *dc,
|
||||
struct dc_link **edp_links,
|
||||
int *edp_num)
|
||||
unsigned int *edp_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
|
|||
unsigned int *inst_out)
|
||||
{
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
int edp_num, i;
|
||||
unsigned int edp_num, i;
|
||||
|
||||
*inst_out = 0;
|
||||
if (link->connector_signal != SIGNAL_TYPE_EDP)
|
||||
|
|
|
|||
|
|
@ -1748,6 +1748,7 @@ enum dc_status resource_build_scaling_params_for_context(
|
|||
const struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
(void)dc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
|
|
@ -1825,6 +1826,7 @@ int resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(
|
|||
struct resource_context *new_res_ctx,
|
||||
const struct pipe_ctx *cur_otg_master)
|
||||
{
|
||||
(void)cur_res_ctx;
|
||||
const struct pipe_ctx *cur_sec_opp_head = cur_otg_master->next_odm_pipe;
|
||||
struct pipe_ctx *new_pipe;
|
||||
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
|
||||
|
|
@ -1846,6 +1848,7 @@ int resource_find_free_pipe_used_in_cur_mpc_blending_tree(
|
|||
struct resource_context *new_res_ctx,
|
||||
const struct pipe_ctx *cur_opp_head)
|
||||
{
|
||||
(void)cur_res_ctx;
|
||||
const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe;
|
||||
struct pipe_ctx *new_pipe;
|
||||
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
|
||||
|
|
@ -2941,6 +2944,7 @@ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ct
|
|||
const struct resource_pool *pool,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
(void)pool;
|
||||
struct dc *dc = stream->ctx->dc;
|
||||
|
||||
return dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
|
||||
|
|
@ -3023,6 +3027,7 @@ static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
|
|||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context)
|
||||
{
|
||||
(void)context;
|
||||
struct pipe_ctx *opp_head_pipe = otg_master_pipe;
|
||||
|
||||
while (opp_head_pipe) {
|
||||
|
|
@ -3615,6 +3620,7 @@ static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for
|
|||
const struct resource_pool *pool,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
(void)stream;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
|
||||
|
|
@ -3634,6 +3640,7 @@ static struct audio *find_first_free_audio(
|
|||
enum engine_id id,
|
||||
enum dce_version dc_version)
|
||||
{
|
||||
(void)dc_version;
|
||||
int i, available_audio_count;
|
||||
|
||||
if (id == ENGINE_ID_UNKNOWN)
|
||||
|
|
@ -5240,7 +5247,7 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
|
|||
return 64;
|
||||
default:
|
||||
ASSERT_CRITICAL(false);
|
||||
return -1;
|
||||
return UINT_MAX;
|
||||
}
|
||||
}
|
||||
static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
|
||||
|
|
|
|||
|
|
@ -205,19 +205,33 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p
|
|||
state->power_source = params ? params->power_source : DC_POWER_SOURCE_AC;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
bool status;
|
||||
|
||||
if (dc->debug.using_dml2) {
|
||||
if (!dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2)) {
|
||||
DC_FP_START();
|
||||
status = dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2);
|
||||
DC_FP_END();
|
||||
|
||||
if (!status) {
|
||||
dc_state_release(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dc->caps.dcmode_power_limits_present && !dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source)) {
|
||||
dc_state_release(state);
|
||||
return NULL;
|
||||
if (dc->caps.dcmode_power_limits_present) {
|
||||
bool status;
|
||||
|
||||
DC_FP_START();
|
||||
status = dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source);
|
||||
DC_FP_END();
|
||||
|
||||
if (!status) {
|
||||
dc_state_release(state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_DRM_AMD_DC_FP
|
||||
kref_init(&state->refcount);
|
||||
|
||||
return state;
|
||||
|
|
@ -235,14 +249,20 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state)
|
|||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
dst_state->bw_ctx.dml2 = dst_dml2;
|
||||
if (src_state->bw_ctx.dml2)
|
||||
if (src_state->bw_ctx.dml2) {
|
||||
DC_FP_START();
|
||||
dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
dst_state->bw_ctx.dml2_dc_power_source = dst_dml2_dc_power_source;
|
||||
if (src_state->bw_ctx.dml2_dc_power_source)
|
||||
dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
|
||||
#endif
|
||||
|
||||
if (src_state->bw_ctx.dml2_dc_power_source) {
|
||||
DC_FP_START();
|
||||
dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
|
||||
DC_FP_END();
|
||||
}
|
||||
#endif // CONFIG_DRM_AMD_DC_FP
|
||||
/* context refcount should not be overridden */
|
||||
dst_state->refcount = refcount;
|
||||
}
|
||||
|
|
@ -258,22 +278,35 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state)
|
|||
dc_state_copy_internal(new_state, src_state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
bool status;
|
||||
|
||||
new_state->bw_ctx.dml2 = NULL;
|
||||
new_state->bw_ctx.dml2_dc_power_source = NULL;
|
||||
|
||||
if (src_state->bw_ctx.dml2 &&
|
||||
!dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
if (src_state->bw_ctx.dml2) {
|
||||
DC_FP_START();
|
||||
status = dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
|
||||
DC_FP_END();
|
||||
|
||||
if (!status) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (src_state->bw_ctx.dml2_dc_power_source &&
|
||||
!dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source)) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (src_state->bw_ctx.dml2_dc_power_source) {
|
||||
DC_FP_START();
|
||||
status = dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source,
|
||||
src_state->bw_ctx.dml2_dc_power_source);
|
||||
DC_FP_END();
|
||||
|
||||
if (!status) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_DRM_AMD_DC_FP
|
||||
kref_init(&new_state->refcount);
|
||||
|
||||
return new_state;
|
||||
|
|
@ -351,11 +384,13 @@ static void dc_state_free(struct kref *kref)
|
|||
dc_state_destruct(state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
DC_FP_START();
|
||||
dml2_destroy(state->bw_ctx.dml2);
|
||||
state->bw_ctx.dml2 = 0;
|
||||
|
||||
dml2_destroy(state->bw_ctx.dml2_dc_power_source);
|
||||
state->bw_ctx.dml2_dc_power_source = 0;
|
||||
DC_FP_END();
|
||||
#endif
|
||||
|
||||
kvfree(state);
|
||||
|
|
@ -374,6 +409,7 @@ enum dc_status dc_state_add_stream(
|
|||
struct dc_state *state,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
(void)dc;
|
||||
enum dc_status res;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
|
@ -749,6 +785,7 @@ struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc,
|
|||
struct dc_state *state,
|
||||
struct dc_plane_state *main_plane)
|
||||
{
|
||||
(void)main_plane;
|
||||
struct dc_plane_state *phantom_plane = dc_create_plane_state(dc);
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,13 @@
|
|||
#define MAX(x, y) ((x > y) ? x : y)
|
||||
#endif
|
||||
|
||||
#include "dc_fpu.h"
|
||||
|
||||
#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
|
||||
#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Private functions
|
||||
******************************************************************************/
|
||||
|
|
@ -170,12 +177,14 @@ struct dc_stream_state *dc_create_stream_for_sink(
|
|||
if (sink == NULL)
|
||||
goto fail;
|
||||
|
||||
stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED(stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC));
|
||||
|
||||
if (stream == NULL)
|
||||
goto fail;
|
||||
|
||||
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED(stream->update_scratch =
|
||||
kzalloc((int32_t) dc_update_scratch_space_size(),
|
||||
GFP_ATOMIC));
|
||||
|
||||
if (stream->update_scratch == NULL)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta
|
|||
|
||||
void dc_plane_destruct(struct dc_plane_state *plane_state)
|
||||
{
|
||||
(void)plane_state;
|
||||
// no more pointers to free within dc_plane_state
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
|
|||
struct dcn_optc_reg_state;
|
||||
struct dcn_dccg_reg_state;
|
||||
|
||||
#define DC_VER "3.2.375"
|
||||
#define DC_VER "3.2.376"
|
||||
|
||||
/**
|
||||
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
|
||||
|
|
@ -467,7 +467,6 @@ struct dc_static_screen_params {
|
|||
*/
|
||||
|
||||
enum surface_update_type {
|
||||
UPDATE_TYPE_ADDR_ONLY, /* only surface address is being updated, no other programming needed */
|
||||
UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */
|
||||
UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/
|
||||
UPDATE_TYPE_FULL, /* may need to shuffle resources */
|
||||
|
|
@ -521,7 +520,7 @@ struct dc_config {
|
|||
union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode;
|
||||
bool multi_mon_pp_mclk_switch;
|
||||
bool disable_dmcu;
|
||||
bool enable_4to1MPC;
|
||||
bool allow_4to1MPC;
|
||||
bool enable_windowed_mpo_odm;
|
||||
bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
|
||||
uint32_t allow_edp_hotplug_detection;
|
||||
|
|
@ -563,7 +562,6 @@ struct dc_config {
|
|||
bool frame_update_cmd_version2;
|
||||
struct spl_sharpness_range dcn_sharpness_range;
|
||||
struct spl_sharpness_range dcn_override_sharpness_range;
|
||||
bool no_native422_support;
|
||||
};
|
||||
|
||||
enum visual_confirm {
|
||||
|
|
@ -988,6 +986,7 @@ struct link_service;
|
|||
* causing an issue or not.
|
||||
*/
|
||||
struct dc_debug_options {
|
||||
bool native422_support;
|
||||
bool disable_dsc;
|
||||
enum visual_confirm visual_confirm;
|
||||
int visual_confirm_rect_height;
|
||||
|
|
@ -1881,6 +1880,20 @@ struct dc_scaling_info {
|
|||
struct scaling_taps scaling_quality;
|
||||
};
|
||||
|
||||
struct dc_fast_update {
|
||||
const struct dc_flip_addrs *flip_addr;
|
||||
const struct dc_gamma *gamma;
|
||||
const struct colorspace_transform *gamut_remap_matrix;
|
||||
const struct dc_csc_transform *input_csc_color_matrix;
|
||||
const struct fixed31_32 *coeff_reduction_factor;
|
||||
struct dc_transfer_func *out_transfer_func;
|
||||
struct dc_csc_transform *output_csc_transform;
|
||||
const struct dc_csc_transform *cursor_csc_color_matrix;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
|
||||
struct cm_hist_control *cm_hist_control;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_surface_update {
|
||||
struct dc_plane_state *surface;
|
||||
|
||||
|
|
@ -2019,7 +2032,12 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
|
|||
void get_audio_check(struct audio_info *aud_modes,
|
||||
struct audio_check *aud_chk);
|
||||
|
||||
/*
|
||||
bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_count);
|
||||
void populate_fast_updates(struct dc_fast_update *fast_update,
|
||||
struct dc_surface_update *srf_updates,
|
||||
int surface_count,
|
||||
struct dc_stream_update *stream_update);
|
||||
/*
|
||||
* Set up streams and links associated to drive sinks
|
||||
* The streams parameter is an absolute set of all active streams.
|
||||
*
|
||||
|
|
@ -2062,7 +2080,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
|
|||
/* Return an array of link pointers to edp links. */
|
||||
void dc_get_edp_links(const struct dc *dc,
|
||||
struct dc_link **edp_links,
|
||||
int *edp_num);
|
||||
unsigned int *edp_num);
|
||||
|
||||
void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
|
||||
bool powerOn);
|
||||
|
|
|
|||
|
|
@ -958,7 +958,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
|
|||
{
|
||||
uint32_t i;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
|
||||
if (!dc_dmub_srv)
|
||||
return;
|
||||
|
||||
if (!dc_dmub_srv->dmub) {
|
||||
DC_LOG_ERROR("%s: invalid parameters.", __func__);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1082,6 +1085,7 @@ static void dc_build_cursor_attribute_update_payload1(
|
|||
struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx,
|
||||
const struct hubp *hubp, const struct dpp *dpp)
|
||||
{
|
||||
(void)p_idx;
|
||||
/* Hubp */
|
||||
pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH;
|
||||
pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR;
|
||||
|
|
@ -1163,7 +1167,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
|
|||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
|
||||
if (!dc_dmub_srv)
|
||||
return;
|
||||
|
||||
if (!dc_dmub_srv->dmub) {
|
||||
DC_LOG_ERROR("%s: invalid parameters.", __func__);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ struct dc_dsc_policy {
|
|||
uint32_t max_target_bpp;
|
||||
uint32_t min_target_bpp;
|
||||
bool enable_dsc_when_not_needed;
|
||||
bool ycbcr422_simple;
|
||||
};
|
||||
|
||||
struct dc_dsc_config_options {
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
|
|||
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
|
||||
va_list ap)
|
||||
{
|
||||
(void)addr;
|
||||
uint32_t shift, mask, field_value;
|
||||
int i = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ void dccg31_set_dpstreamclk(
|
|||
int otg_inst,
|
||||
int dp_hpo_inst)
|
||||
{
|
||||
(void)dp_hpo_inst;
|
||||
if (src == REFCLK)
|
||||
dccg31_disable_dpstreamclk(dccg, otg_inst);
|
||||
else
|
||||
|
|
@ -644,6 +645,7 @@ void dccg31_get_dccg_ref_freq(struct dccg *dccg,
|
|||
unsigned int xtalin_freq_inKhz,
|
||||
unsigned int *dccg_ref_freq_inKhz)
|
||||
{
|
||||
(void)dccg;
|
||||
/*
|
||||
* Assume refclk is sourced from xtalin
|
||||
* expect 24MHz
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ static void dccg32_get_dccg_ref_freq(struct dccg *dccg,
|
|||
unsigned int xtalin_freq_inKhz,
|
||||
unsigned int *dccg_ref_freq_inKhz)
|
||||
{
|
||||
(void)dccg;
|
||||
/*
|
||||
* Assume refclk is sourced from xtalin
|
||||
* expect 100MHz
|
||||
|
|
|
|||
|
|
@ -558,6 +558,7 @@ static void dccg35_set_symclk32_se_src_new(
|
|||
static int
|
||||
dccg35_is_symclk32_se_src_functional_le_new(struct dccg *dccg, int symclk_32_se_inst, int symclk_32_le_inst)
|
||||
{
|
||||
(void)symclk_32_se_inst;
|
||||
uint32_t en;
|
||||
uint32_t src_sel;
|
||||
|
||||
|
|
@ -2373,6 +2374,7 @@ static void dccg35_disable_symclk_se_cb(
|
|||
uint32_t stream_enc_inst,
|
||||
uint32_t link_enc_inst)
|
||||
{
|
||||
(void)link_enc_inst;
|
||||
dccg35_disable_symclk_fe_new(dccg, stream_enc_inst);
|
||||
|
||||
/* DMU PHY sequence switches SYMCLK_BE (link_enc_inst) to ref clock once PHY is turned off */
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ void dccg401_set_pixel_rate_div(
|
|||
enum pixel_rate_div tmds_div,
|
||||
enum pixel_rate_div unused)
|
||||
{
|
||||
(void)unused;
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
|
||||
uint32_t dp_dto_int;
|
||||
|
|
@ -353,6 +354,7 @@ void dccg401_get_dccg_ref_freq(struct dccg *dccg,
|
|||
unsigned int xtalin_freq_inKhz,
|
||||
unsigned int *dccg_ref_freq_inKhz)
|
||||
{
|
||||
(void)dccg;
|
||||
/*
|
||||
* Assume refclk is sourced from xtalin
|
||||
* expect 100MHz
|
||||
|
|
@ -526,10 +528,6 @@ static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_h
|
|||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
|
||||
REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
|
||||
DPSTREAMCLK_GATE_DISABLE, 1,
|
||||
DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
|
||||
}
|
||||
|
||||
void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst)
|
||||
|
|
@ -725,6 +723,7 @@ void dccg401_init(struct dccg *dccg)
|
|||
|
||||
void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h)
|
||||
{
|
||||
(void)num_slices_h;
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
switch (inst) {
|
||||
|
|
@ -842,6 +841,7 @@ void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3
|
|||
|
||||
void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
|
||||
{
|
||||
(void)link_enc_inst;
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
switch (stream_enc_inst) {
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ void dccg42_set_pixel_rate_div(
|
|||
enum pixel_rate_div tmds_div,
|
||||
enum pixel_rate_div unused)
|
||||
{
|
||||
(void)unused;
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
|
||||
uint32_t dp_dto_int;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
|
||||
static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst)
|
||||
{
|
||||
(void)panel_inst;
|
||||
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
|
||||
uint32_t rampingBoundary = 0xFFFF;
|
||||
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ static uint32_t calculate_required_audio_bw_in_symbols(
|
|||
uint32_t av_stream_map_lane_count,
|
||||
uint32_t audio_sdp_overhead)
|
||||
{
|
||||
(void)channel_count;
|
||||
/* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */
|
||||
struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100);
|
||||
struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction(
|
||||
|
|
@ -1027,6 +1028,7 @@ static void get_azalia_clock_info_hdmi(
|
|||
uint32_t actual_pixel_clock_100Hz,
|
||||
struct azalia_clock_info *azalia_clock_info)
|
||||
{
|
||||
(void)crtc_pixel_clock_100hz;
|
||||
/* audio_dto_phase= 24 * 10,000;
|
||||
* 24MHz in [100Hz] units */
|
||||
azalia_clock_info->audio_dto_phase =
|
||||
|
|
@ -1043,6 +1045,7 @@ static void get_azalia_clock_info_dp(
|
|||
const struct audio_pll_info *pll_info,
|
||||
struct azalia_clock_info *azalia_clock_info)
|
||||
{
|
||||
(void)requested_pixel_clock_100Hz;
|
||||
/* Reported dpDtoSourceClockInkhz value for
|
||||
* DCE8 already adjusted for SS, do not need any
|
||||
* adjustment here anymore
|
||||
|
|
|
|||
|
|
@ -539,6 +539,7 @@ static void dce112_get_pix_clk_dividers_helper (
|
|||
struct pll_settings *pll_settings,
|
||||
struct pixel_clk_params *pix_clk_params)
|
||||
{
|
||||
(void)clk_src;
|
||||
uint32_t actual_pixel_clock_100hz;
|
||||
|
||||
actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;
|
||||
|
|
@ -610,7 +611,7 @@ static uint32_t dce112_get_pix_clk_dividers(
|
|||
|| pix_clk_params->requested_pix_clk_100hz == 0) {
|
||||
DC_LOG_ERROR(
|
||||
"%s: Invalid parameters!!\n", __func__);
|
||||
return -1;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
memset(pll_settings, 0, sizeof(*pll_settings));
|
||||
|
|
@ -621,7 +622,7 @@ static uint32_t dce112_get_pix_clk_dividers(
|
|||
pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
|
||||
pll_settings->actual_pix_clk_100hz =
|
||||
pix_clk_params->requested_pix_clk_100hz;
|
||||
return -1;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
dce112_get_pix_clk_dividers_helper(clk_src,
|
||||
|
|
@ -847,6 +848,7 @@ static bool dce110_program_pix_clk(
|
|||
enum dp_link_encoding encoding,
|
||||
struct pll_settings *pll_settings)
|
||||
{
|
||||
(void)encoding;
|
||||
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
|
||||
struct bp_pixel_clock_parameters bp_pc_params = {0};
|
||||
|
||||
|
|
@ -921,6 +923,7 @@ static bool dce112_program_pix_clk(
|
|||
enum dp_link_encoding encoding,
|
||||
struct pll_settings *pll_settings)
|
||||
{
|
||||
(void)encoding;
|
||||
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
|
||||
struct bp_pixel_clock_parameters bp_pc_params = {0};
|
||||
|
||||
|
|
@ -1070,6 +1073,7 @@ static bool dcn401_program_pix_clk(
|
|||
enum dp_link_encoding encoding,
|
||||
struct pll_settings *pll_settings)
|
||||
{
|
||||
(void)encoding;
|
||||
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
|
||||
unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
|
||||
const struct pixel_rate_range_table_entry *e =
|
||||
|
|
@ -1376,7 +1380,7 @@ static uint32_t dcn3_get_pix_clk_dividers(
|
|||
|| pix_clk_params->requested_pix_clk_100hz == 0) {
|
||||
DC_LOG_ERROR(
|
||||
"%s: Invalid parameters!!\n", __func__);
|
||||
return -1;
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
memset(pll_settings, 0, sizeof(*pll_settings));
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ static const uint32_t abm_gain_stepsize = 0x0060;
|
|||
|
||||
static bool dce_dmcu_init(struct dmcu *dmcu)
|
||||
{
|
||||
(void)dmcu;
|
||||
// Do nothing
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ bool dce_i2c_oem_device_present(
|
|||
size_t slave_address
|
||||
)
|
||||
{
|
||||
(void)pool;
|
||||
struct dc *dc = ddc->ctx->dc;
|
||||
struct dc_bios *dcb = dc->ctx->dc_bios;
|
||||
struct graphics_object_id id = {0};
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ static enum i2c_channel_operation_result get_channel_status(
|
|||
struct dce_i2c_hw *dce_i2c_hw,
|
||||
uint8_t *returned_bytes)
|
||||
{
|
||||
(void)returned_bytes;
|
||||
uint32_t i2c_sw_status = 0;
|
||||
uint32_t value =
|
||||
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
|
||||
|
|
@ -631,6 +632,7 @@ bool dce_i2c_submit_command_hw(
|
|||
struct i2c_command *cmd,
|
||||
struct dce_i2c_hw *dce_i2c_hw)
|
||||
{
|
||||
(void)ddc;
|
||||
uint8_t index_of_payload = 0;
|
||||
bool result;
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ static void release_engine_dce_sw(
|
|||
struct resource_pool *pool,
|
||||
struct dce_i2c_sw *dce_i2c_sw)
|
||||
{
|
||||
(void)pool;
|
||||
dal_ddc_close(dce_i2c_sw->ddc);
|
||||
dce_i2c_sw->ddc = NULL;
|
||||
}
|
||||
|
|
@ -76,6 +77,7 @@ static bool wait_for_scl_high_sw(
|
|||
struct ddc *ddc,
|
||||
uint16_t clock_delay_div_4)
|
||||
{
|
||||
(void)ctx;
|
||||
uint32_t scl_retry = 0;
|
||||
uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
|
||||
|
||||
|
|
@ -469,6 +471,7 @@ bool dce_i2c_submit_command_sw(
|
|||
struct i2c_command *cmd,
|
||||
struct dce_i2c_sw *dce_i2c_sw)
|
||||
{
|
||||
(void)ddc;
|
||||
uint8_t index_of_payload = 0;
|
||||
bool result;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ static void dce_ipp_cursor_set_position(
|
|||
const struct dc_cursor_position *position,
|
||||
const struct dc_cursor_mi_param *param)
|
||||
{
|
||||
(void)param;
|
||||
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
|
||||
|
||||
/* lock cursor registers */
|
||||
|
|
|
|||
|
|
@ -847,6 +847,7 @@ bool dce110_link_encoder_validate_dp_output(
|
|||
const struct dce110_link_encoder *enc110,
|
||||
const struct dc_crtc_timing *crtc_timing)
|
||||
{
|
||||
(void)enc110;
|
||||
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@ static void dce_mi_program_display_marks(
|
|||
struct dce_watermarks urgent,
|
||||
uint32_t total_dest_line_time_ns)
|
||||
{
|
||||
(void)stutter_enter;
|
||||
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
|
||||
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
|
||||
|
||||
|
|
@ -370,6 +371,7 @@ static void dce112_mi_program_display_marks(struct mem_input *mi,
|
|||
struct dce_watermarks urgent,
|
||||
uint32_t total_dest_line_time_ns)
|
||||
{
|
||||
(void)stutter_entry;
|
||||
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
|
||||
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
|
||||
|
||||
|
|
@ -656,6 +658,8 @@ static void dce_mi_program_surface_config(
|
|||
struct dc_plane_dcc_param *dcc,
|
||||
bool horizontal_mirror)
|
||||
{
|
||||
(void)dcc;
|
||||
(void)horizontal_mirror;
|
||||
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
|
||||
REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -600,6 +600,7 @@ void dce110_opp_set_dyn_expansion(
|
|||
enum dc_color_depth color_dpth,
|
||||
enum signal_type signal)
|
||||
{
|
||||
(void)color_sp;
|
||||
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
|
||||
|
||||
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
|
||||
|
|
|
|||
|
|
@ -271,6 +271,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
|
|||
bool use_vsc_sdp_for_colorimetry,
|
||||
uint32_t enable_sdp_splitting)
|
||||
{
|
||||
(void)use_vsc_sdp_for_colorimetry;
|
||||
(void)enable_sdp_splitting;
|
||||
uint32_t h_active_start;
|
||||
uint32_t v_active_start;
|
||||
uint32_t misc0 = 0;
|
||||
|
|
@ -901,6 +903,7 @@ static void dce110_stream_encoder_dp_blank(
|
|||
struct dc_link *link,
|
||||
struct stream_encoder *enc)
|
||||
{
|
||||
(void)link;
|
||||
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
|
||||
uint32_t reg1 = 0;
|
||||
uint32_t max_retries = DP_BLANK_MAX_RETRY * 10;
|
||||
|
|
@ -951,6 +954,7 @@ static void dce110_stream_encoder_dp_unblank(
|
|||
struct stream_encoder *enc,
|
||||
const struct encoder_unblank_param *param)
|
||||
{
|
||||
(void)link;
|
||||
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
|
||||
|
||||
if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ static void calculate_inits(
|
|||
const struct scaler_data *data,
|
||||
struct scl_ratios_inits *inits)
|
||||
{
|
||||
(void)xfm_dce;
|
||||
struct fixed31_32 h_init;
|
||||
struct fixed31_32 v_init;
|
||||
|
||||
|
|
@ -1240,6 +1241,7 @@ static void program_color_matrix(
|
|||
const struct out_csc_color_matrix *tbl_entry,
|
||||
enum grph_color_adjust_option options)
|
||||
{
|
||||
(void)options;
|
||||
{
|
||||
REG_SET_2(OUTPUT_CSC_C11_C12, 0,
|
||||
OUTPUT_CSC_C11, tbl_entry->regval[0],
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst
|
|||
{
|
||||
struct dc_context *dc = abm->ctx;
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
int i;
|
||||
int edp_num;
|
||||
unsigned int i, edp_num;
|
||||
unsigned int ret = ABM_FEATURE_NO_SUPPORT;
|
||||
|
||||
dc_get_edp_links(dc->dc, edp_links, &edp_num);
|
||||
|
|
@ -174,6 +173,7 @@ static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm,
|
|||
unsigned int controller_id,
|
||||
unsigned int panel_inst)
|
||||
{
|
||||
(void)controller_id;
|
||||
bool ret = false;
|
||||
unsigned int feature_support;
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ void dmub_abm_init_config(struct abm *abm,
|
|||
|
||||
bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
|
||||
{
|
||||
(void)stream_inst;
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *dc = abm->ctx;
|
||||
uint8_t panel_mask = 0x01 << panel_inst;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue