Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'amd-drm-next-6.8-2024-01-05' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.8-2024-01-05:

amdgpu:
- VRR fixes
- PSR-SU fixes
- SubVP fixes
- DCN 3.5 fixes
- Documentation updates
- DMCUB fixes
- DML2 fixes
- UMC 12.0 updates
- GPUVM fix
- Misc code cleanups and whitespace cleanups
- DP MST fix
- Let KFD sync with GPUVM fences
- GFX11 reset fix
- SMU 13.0.6 fixes
- VSC fix for DP/eDP
- Navi12 display fix
- RN/CZN system aperture fix
- DCN 2.1 bandwidth validation fix
- DCN INIT cleanup

amdkfd:
- SVM fixes
- Revert TBA/TMA location change

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240105220522.4976-1-alexander.deucher@amd.com

+4096 -2114
+2 -1
Documentation/gpu/amdgpu/apu-asic-info-table.csv
··· 7 7 Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1 8 8 Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3 9 9 Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 10 - Ryzen 7x45 series (FL1), / Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 10 + Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5 11 11 Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8 12 12 Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11 13 + Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
+25 -1
drivers/gpu/drm/amd/amdgpu/aldebaran.c
··· 330 330 { 331 331 struct list_head *reset_device_list = reset_context->reset_device_list; 332 332 struct amdgpu_device *tmp_adev = NULL; 333 + struct amdgpu_ras *con; 333 334 int r; 334 335 335 336 if (reset_device_list == NULL) ··· 356 355 */ 357 356 amdgpu_register_gpu_instance(tmp_adev); 358 357 359 - /* Resume RAS */ 358 + /* Resume RAS, ecc_irq */ 359 + con = amdgpu_ras_get_context(tmp_adev); 360 + if (!amdgpu_sriov_vf(tmp_adev) && con) { 361 + if (tmp_adev->sdma.ras && 362 + tmp_adev->sdma.ras->ras_block.ras_late_init) { 363 + r = tmp_adev->sdma.ras->ras_block.ras_late_init(tmp_adev, 364 + &tmp_adev->sdma.ras->ras_block.ras_comm); 365 + if (r) { 366 + dev_err(tmp_adev->dev, "SDMA failed to execute ras_late_init! ret:%d\n", r); 367 + goto end; 368 + } 369 + } 370 + 371 + if (tmp_adev->gfx.ras && 372 + tmp_adev->gfx.ras->ras_block.ras_late_init) { 373 + r = tmp_adev->gfx.ras->ras_block.ras_late_init(tmp_adev, 374 + &tmp_adev->gfx.ras->ras_block.ras_comm); 375 + if (r) { 376 + dev_err(tmp_adev->dev, "GFX failed to execute ras_late_init! ret:%d\n", r); 377 + goto end; 378 + } 379 + } 380 + } 381 + 360 382 amdgpu_ras_resume(tmp_adev); 361 383 362 384 /* Update PSP FW topology after reset */
+2
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 254 254 255 255 extern int amdgpu_wbrf; 256 256 257 + extern int fw_bo_location; 258 + 257 259 #define AMDGPU_VM_MAX_NUM_CTX 4096 258 260 #define AMDGPU_SG_THRESHOLD (256*1024*1024) 259 261 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
··· 90 90 return NULL; 91 91 92 92 fence = container_of(f, struct amdgpu_amdkfd_fence, base); 93 - if (fence && f->ops == &amdkfd_fence_ops) 93 + if (f->ops == &amdkfd_fence_ops) 94 94 return fence; 95 95 96 96 return NULL;
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
··· 1103 1103 * DDC line. The latter is more complex because with DVI<->HDMI adapters 1104 1104 * you don't really know what's connected to which port as both are digital. 1105 1105 */ 1106 - amdgpu_connector_shared_ddc(&ret, connector, amdgpu_connector); 1106 + amdgpu_connector_shared_ddc(&ret, connector, amdgpu_connector); 1107 1107 } 1108 1108 } 1109 1109
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
··· 870 870 struct amdgpu_bo *bo = e->bo; 871 871 int i; 872 872 873 - e->user_pages = kvmalloc_array(bo->tbo.ttm->num_pages, 874 - sizeof(struct page *), 875 - GFP_KERNEL | __GFP_ZERO); 873 + e->user_pages = kvcalloc(bo->tbo.ttm->num_pages, 874 + sizeof(struct page *), 875 + GFP_KERNEL); 876 876 if (!e->user_pages) { 877 877 DRM_ERROR("kvmalloc_array failure\n"); 878 878 r = -ENOMEM;
+9 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
··· 540 540 while (size) { 541 541 uint32_t value; 542 542 543 - value = RREG32_PCIE(*pos); 543 + if (upper_32_bits(*pos)) 544 + value = RREG32_PCIE_EXT(*pos); 545 + else 546 + value = RREG32_PCIE(*pos); 547 + 544 548 r = put_user(value, (uint32_t *)buf); 545 549 if (r) 546 550 goto out; ··· 604 600 if (r) 605 601 goto out; 606 602 607 - WREG32_PCIE(*pos, value); 603 + if (upper_32_bits(*pos)) 604 + WREG32_PCIE_EXT(*pos, value); 605 + else 606 + WREG32_PCIE(*pos, value); 608 607 609 608 result += 4; 610 609 buf += 4;
+2 -9
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 2251 2251 2252 2252 adev->firmware.gpu_info_fw = NULL; 2253 2253 2254 - if (adev->mman.discovery_bin) { 2255 - /* 2256 - * FIXME: The bounding box is still needed by Navi12, so 2257 - * temporarily read it from gpu_info firmware. Should be dropped 2258 - * when DAL no longer needs it. 2259 - */ 2260 - if (adev->asic_type != CHIP_NAVI12) 2261 - return 0; 2262 - } 2254 + if (adev->mman.discovery_bin) 2255 + return 0; 2263 2256 2264 2257 switch (adev->asic_type) { 2265 2258 default:
+5
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 210 210 uint amdgpu_debug_mask; 211 211 int amdgpu_agp = -1; /* auto */ 212 212 int amdgpu_wbrf = -1; 213 + int fw_bo_location = -1; 213 214 214 215 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work); 215 216 ··· 989 988 MODULE_PARM_DESC(wbrf, 990 989 "Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)"); 991 990 module_param_named(wbrf, amdgpu_wbrf, int, 0444); 991 + 992 + MODULE_PARM_DESC(fw_bo_location, 993 + "location to put firmware bo for frontdoor loading (-1 = auto (default), 0 = on ram, 1 = on vram"); 994 + module_param(fw_bo_location, int, 0644); 992 995 993 996 /* These devices are not supported by amdgpu. 994 997 * They are supported by the mach64, r128, radeon drivers
+15 -6
drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c
··· 218 218 int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data) 219 219 { 220 220 struct amdgpu_smuio_mcm_config_info mcm_info; 221 + struct ras_err_addr err_addr = {0}; 221 222 struct mca_bank_set mca_set; 222 223 struct mca_bank_node *node; 223 224 struct mca_bank_entry *entry; ··· 247 246 mcm_info.socket_id = entry->info.socket_id; 248 247 mcm_info.die_id = entry->info.aid; 249 248 249 + if (blk == AMDGPU_RAS_BLOCK__UMC) { 250 + err_addr.err_status = entry->regs[MCA_REG_IDX_STATUS]; 251 + err_addr.err_ipid = entry->regs[MCA_REG_IDX_IPID]; 252 + err_addr.err_addr = entry->regs[MCA_REG_IDX_ADDR]; 253 + } 254 + 250 255 if (type == AMDGPU_MCA_ERROR_TYPE_UE) 251 - amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, (uint64_t)count); 256 + amdgpu_ras_error_statistic_ue_count(err_data, 257 + &mcm_info, &err_addr, (uint64_t)count); 252 258 else 253 - amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, (uint64_t)count); 259 + amdgpu_ras_error_statistic_ce_count(err_data, 260 + &mcm_info, &err_addr, (uint64_t)count); 254 261 } 255 262 256 263 out_mca_release: ··· 360 351 const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs; 361 352 int count; 362 353 354 + if (!mca_funcs || !mca_funcs->mca_get_mca_entry) 355 + return -EOPNOTSUPP; 356 + 363 357 switch (type) { 364 358 case AMDGPU_MCA_ERROR_TYPE_UE: 365 359 count = mca_funcs->max_ue_count; ··· 377 365 if (idx >= count) 378 366 return -EINVAL; 379 367 380 - if (mca_funcs && mca_funcs->mca_get_mca_entry) 381 - return mca_funcs->mca_get_mca_entry(adev, type, idx, entry); 382 - 383 - return -EOPNOTSUPP; 368 + return mca_funcs->mca_get_mca_entry(adev, type, idx, entry); 384 369 } 385 370 386 371 #if defined(CONFIG_DEBUG_FS)
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 466 466 } 467 467 468 468 ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, 469 - amdgpu_sriov_vf(adev) ? 469 + (amdgpu_sriov_vf(adev) || fw_bo_location == 1) ? 470 470 AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, 471 471 &psp->fw_pri_bo, 472 472 &psp->fw_pri_mc_addr,
+22 -12
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
··· 1156 1156 for_each_ras_error(err_node, err_data) { 1157 1157 err_info = &err_node->err_info; 1158 1158 1159 - amdgpu_ras_error_statistic_ce_count(&obj->err_data, &err_info->mcm_info, err_info->ce_count); 1160 - amdgpu_ras_error_statistic_ue_count(&obj->err_data, &err_info->mcm_info, err_info->ue_count); 1159 + amdgpu_ras_error_statistic_ce_count(&obj->err_data, 1160 + &err_info->mcm_info, NULL, err_info->ce_count); 1161 + amdgpu_ras_error_statistic_ue_count(&obj->err_data, 1162 + &err_info->mcm_info, NULL, err_info->ue_count); 1161 1163 } 1162 1164 } else { 1163 1165 /* for legacy asic path which doesn't has error source info */ ··· 1175 1173 { 1176 1174 enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT; 1177 1175 struct amdgpu_ras_block_object *block_obj = NULL; 1176 + 1177 + if (blk == AMDGPU_RAS_BLOCK_COUNT) 1178 + return -EINVAL; 1178 1179 1179 1180 if (error_query_mode == AMDGPU_RAS_INVALID_ERROR_QUERY) 1180 1181 return -EINVAL; ··· 2543 2538 return 0; 2544 2539 2545 2540 data = &con->eh_data; 2546 - *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO); 2541 + *data = kzalloc(sizeof(**data), GFP_KERNEL); 2547 2542 if (!*data) { 2548 2543 ret = -ENOMEM; 2549 2544 goto out; ··· 2830 2825 if (con) 2831 2826 return 0; 2832 2827 2833 - con = kmalloc(sizeof(struct amdgpu_ras) + 2828 + con = kzalloc(sizeof(*con) + 2834 2829 sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT + 2835 2830 sizeof(struct ras_manager) * AMDGPU_RAS_MCA_BLOCK_COUNT, 2836 - GFP_KERNEL|__GFP_ZERO); 2831 + GFP_KERNEL); 2837 2832 if (!con) 2838 2833 return -ENOMEM; 2839 2834 ··· 3138 3133 if (amdgpu_sriov_vf(adev)) 3139 3134 return 0; 3140 3135 3141 - /* enable MCA debug on APU device */ 3142 - amdgpu_ras_set_mca_debug_mode(adev, !!(adev->flags & AMD_IS_APU)); 3136 + amdgpu_ras_set_mca_debug_mode(adev, false); 3143 3137 3144 3138 list_for_each_entry_safe(node, tmp, &adev->ras_list, node) { 3145 3139 if (!node->ras_obj) { ··· 3695 3691 } 3696 3692 3697 3693 static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_data, 3698 - struct amdgpu_smuio_mcm_config_info *mcm_info) 3694 + struct amdgpu_smuio_mcm_config_info *mcm_info, 3695 + struct ras_err_addr *err_addr) 3699 3696 { 3700 3697 struct ras_err_node *err_node; 3701 3698 ··· 3710 3705 3711 3706 memcpy(&err_node->err_info.mcm_info, mcm_info, sizeof(*mcm_info)); 3712 3707 3708 + if (err_addr) 3709 + memcpy(&err_node->err_info.err_addr, err_addr, sizeof(*err_addr)); 3710 + 3713 3711 err_data->err_list_count++; 3714 3712 list_add_tail(&err_node->node, &err_data->err_node_list); 3715 3713 list_sort(NULL, &err_data->err_node_list, ras_err_info_cmp); ··· 3721 3713 } 3722 3714 3723 3715 int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data, 3724 - struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count) 3716 + struct amdgpu_smuio_mcm_config_info *mcm_info, 3717 + struct ras_err_addr *err_addr, u64 count) 3725 3718 { 3726 3719 struct ras_err_info *err_info; 3727 3720 ··· 3732 3723 if (!count) 3733 3724 return 0; 3734 3725 3735 - err_info = amdgpu_ras_error_get_info(err_data, mcm_info); 3726 + err_info = amdgpu_ras_error_get_info(err_data, mcm_info, err_addr); 3736 3727 if (!err_info) 3737 3728 return -EINVAL; 3738 3729 ··· 3743 3734 } 3744 3735 3745 3736 int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data, 3746 - struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count) 3737 + struct amdgpu_smuio_mcm_config_info *mcm_info, 3738 + struct ras_err_addr *err_addr, u64 count) 3747 3739 { 3748 3740 struct ras_err_info *err_info; 3749 3741 ··· 3754 3744 if (!count) 3755 3745 return 0; 3756 3746 3757 - err_info = amdgpu_ras_error_get_info(err_data, mcm_info); 3747 + err_info = amdgpu_ras_error_get_info(err_data, mcm_info, err_addr); 3758 3748 if (!err_info) 3759 3749 return -EINVAL; 3760 3750
+11 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
··· 452 452 char debugfs_name[32]; 453 453 }; 454 454 455 + struct ras_err_addr { 456 + uint64_t err_status; 457 + uint64_t err_ipid; 458 + uint64_t err_addr; 459 + }; 460 + 455 461 struct ras_err_info { 456 462 struct amdgpu_smuio_mcm_config_info mcm_info; 457 463 u64 ce_count; 458 464 u64 ue_count; 465 + struct ras_err_addr err_addr; 459 466 }; 460 467 461 468 struct ras_err_node { ··· 813 806 int amdgpu_ras_error_data_init(struct ras_err_data *err_data); 814 807 void amdgpu_ras_error_data_fini(struct ras_err_data *err_data); 815 808 int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data, 816 - struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count); 809 + struct amdgpu_smuio_mcm_config_info *mcm_info, 810 + struct ras_err_addr *err_addr, u64 count); 817 811 int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data, 818 - struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count); 812 + struct amdgpu_smuio_mcm_config_info *mcm_info, 813 + struct ras_err_addr *err_addr, u64 count); 819 814 820 815 #endif
+5 -6
drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
··· 531 531 if (version_major == 2 && version_minor == 1) 532 532 adev->gfx.rlc.is_rlc_v2_1 = true; 533 533 534 - if (version_minor >= 0) { 535 - err = amdgpu_gfx_rlc_init_microcode_v2_0(adev); 536 - if (err) { 537 - dev_err(adev->dev, "fail to init rlc v2_0 microcode\n"); 538 - return err; 539 - } 534 + err = amdgpu_gfx_rlc_init_microcode_v2_0(adev); 535 + if (err) { 536 + dev_err(adev->dev, "fail to init rlc v2_0 microcode\n"); 537 + return err; 540 538 } 539 + 541 540 if (version_minor >= 1) 542 541 amdgpu_gfx_rlc_init_microcode_v2_1(adev); 543 542 if (version_minor >= 2)
+2 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
··· 191 191 192 192 /* Never sync to VM updates either. */ 193 193 if (fence_owner == AMDGPU_FENCE_OWNER_VM && 194 - owner != AMDGPU_FENCE_OWNER_UNDEFINED) 194 + owner != AMDGPU_FENCE_OWNER_UNDEFINED && 195 + owner != AMDGPU_FENCE_OWNER_KFD) 195 196 return false; 196 197 197 198 /* Ignore fences depending on the sync mode */
+7 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
··· 1062 1062 { 1063 1063 if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT) { 1064 1064 amdgpu_bo_create_kernel(adev, adev->firmware.fw_size, PAGE_SIZE, 1065 - amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, 1065 + (amdgpu_sriov_vf(adev) || fw_bo_location == 1) ? 1066 + AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, 1066 1067 &adev->firmware.fw_buf, 1067 1068 &adev->firmware.fw_buf_mc, 1068 1069 &adev->firmware.fw_buf_ptr); ··· 1398 1397 1399 1398 if (err) 1400 1399 return -ENODEV; 1400 + 1401 1401 err = amdgpu_ucode_validate(*fw); 1402 - if (err) 1402 + if (err) { 1403 1403 dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name); 1404 + release_firmware(*fw); 1405 + *fw = NULL; 1406 + } 1404 1407 1405 1408 return err; 1406 1409 }
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
··· 285 285 list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) { 286 286 struct amdgpu_bo *bo = vm_bo->bo; 287 287 288 + vm_bo->moved = true; 288 289 if (!bo || bo->tbo.type != ttm_bo_type_kernel) 289 290 list_move(&vm_bo->vm_status, &vm_bo->vm->moved); 290 291 else if (bo->parent)
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
··· 1313 1313 1314 1314 switch (xgmi_v6_4_0_pcs_mca_get_error_type(adev, status)) { 1315 1315 case AMDGPU_MCA_ERROR_TYPE_UE: 1316 - amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, 1ULL); 1316 + amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, NULL, 1ULL); 1317 1317 break; 1318 1318 case AMDGPU_MCA_ERROR_TYPE_CE: 1319 - amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, 1ULL); 1319 + amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, NULL, 1ULL); 1320 1320 break; 1321 1321 default: 1322 1322 break;
-1
drivers/gpu/drm/amd/amdgpu/atom.c
··· 395 395 (*ptr)++; 396 396 return; 397 397 } 398 - return; 399 398 } 400 399 } 401 400
+47 -1
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
··· 4474 4474 return -ETIMEDOUT; 4475 4475 } 4476 4476 4477 + static int gfx_v11_0_request_gfx_index_mutex(struct amdgpu_device *adev, 4478 + int req) 4479 + { 4480 + u32 i, tmp, val; 4481 + 4482 + for (i = 0; i < adev->usec_timeout; i++) { 4483 + /* Request with MeId=2, PipeId=0 */ 4484 + tmp = REG_SET_FIELD(0, CP_GFX_INDEX_MUTEX, REQUEST, req); 4485 + tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX, CLIENTID, 4); 4486 + WREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX, tmp); 4487 + 4488 + val = RREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX); 4489 + if (req) { 4490 + if (val == tmp) 4491 + break; 4492 + } else { 4493 + tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX, 4494 + REQUEST, 1); 4495 + 4496 + /* unlocked or locked by firmware */ 4497 + if (val != tmp) 4498 + break; 4499 + } 4500 + udelay(1); 4501 + } 4502 + 4503 + if (i >= adev->usec_timeout) 4504 + return -EINVAL; 4505 + 4506 + return 0; 4507 + } 4508 + 4477 4509 static int gfx_v11_0_soft_reset(void *handle) 4478 4510 { 4479 4511 u32 grbm_soft_reset = 0; 4480 4512 u32 tmp; 4481 - int i, j, k; 4513 + int r, i, j, k; 4482 4514 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 4483 4515 4484 4516 tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL); ··· 4550 4518 } 4551 4519 } 4552 4520 4521 + /* Try to acquire the gfx mutex before access to CP_VMID_RESET */ 4522 + r = gfx_v11_0_request_gfx_index_mutex(adev, 1); 4523 + if (r) { 4524 + DRM_ERROR("Failed to acquire the gfx mutex during soft reset\n"); 4525 + return r; 4526 + } 4527 + 4553 4528 WREG32_SOC15(GC, 0, regCP_VMID_RESET, 0xfffffffe); 4554 4529 4555 4530 // Read CP_VMID_RESET register three times. ··· 4564 4525 RREG32_SOC15(GC, 0, regCP_VMID_RESET); 4565 4526 RREG32_SOC15(GC, 0, regCP_VMID_RESET); 4566 4527 RREG32_SOC15(GC, 0, regCP_VMID_RESET); 4528 + 4529 + /* release the gfx mutex */ 4530 + r = gfx_v11_0_request_gfx_index_mutex(adev, 0); 4531 + if (r) { 4532 + DRM_ERROR("Failed to release the gfx mutex during soft reset\n"); 4533 + return r; 4534 + } 4567 4535 4568 4536 for (i = 0; i < adev->usec_timeout; i++) { 4569 4537 if (!RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) &&
+2 -2
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
··· 3828 3828 /* the caller should make sure initialize value of 3829 3829 * err_data->ue_count and err_data->ce_count 3830 3830 */ 3831 - amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count); 3832 - amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count); 3831 + amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count); 3832 + amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count); 3833 3833 } 3834 3834 3835 3835 static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
+3 -1
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
··· 102 102 WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, 103 103 min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); 104 104 105 - if (adev->apu_flags & AMD_APU_IS_RAVEN2) 105 + if (adev->apu_flags & (AMD_APU_IS_RAVEN2 | 106 + AMD_APU_IS_RENOIR | 107 + AMD_APU_IS_GREEN_SARDINE)) 106 108 /* 107 109 * Raven2 has a HW issue that it is unable to use the 108 110 * vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
+3 -1
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
··· 139 139 WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_LOW_ADDR, 140 140 min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); 141 141 142 - if (adev->apu_flags & AMD_APU_IS_RAVEN2) 142 + if (adev->apu_flags & (AMD_APU_IS_RAVEN2 | 143 + AMD_APU_IS_RENOIR | 144 + AMD_APU_IS_GREEN_SARDINE)) 143 145 /* 144 146 * Raven2 has a HW issue that it is unable to use the 145 147 * vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
+4
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
··· 1041 1041 1042 1042 amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); 1043 1043 1044 + if (adev->gmc.ecc_irq.funcs && 1045 + amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC)) 1046 + amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); 1047 + 1044 1048 return 0; 1045 1049 } 1046 1050
+5
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
··· 941 941 } 942 942 943 943 amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); 944 + 945 + if (adev->gmc.ecc_irq.funcs && 946 + amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC)) 947 + amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); 948 + 944 949 gmc_v11_0_gart_disable(adev); 945 950 946 951 return 0;
+4
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 2380 2380 2381 2381 amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); 2382 2382 2383 + if (adev->gmc.ecc_irq.funcs && 2384 + amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC)) 2385 + amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); 2386 + 2383 2387 return 0; 2384 2388 } 2385 2389
+3 -1
drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
··· 96 96 WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, 97 97 min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); 98 98 99 - if (adev->apu_flags & AMD_APU_IS_RAVEN2) 99 + if (adev->apu_flags & (AMD_APU_IS_RAVEN2 | 100 + AMD_APU_IS_RENOIR | 101 + AMD_APU_IS_GREEN_SARDINE)) 100 102 /* 101 103 * Raven2 has a HW issue that it is unable to use the vram which 102 104 * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
+2 -2
drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
··· 652 652 AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE, 653 653 &ue_count); 654 654 655 - amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count); 656 - amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count); 655 + amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count); 656 + amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count); 657 657 } 658 658 659 659 static void mmhub_v1_8_query_ras_error_count(struct amdgpu_device *adev,
+1 -1
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
··· 2156 2156 AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE, 2157 2157 &ue_count); 2158 2158 2159 - amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count); 2159 + amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count); 2160 2160 } 2161 2161 2162 2162 static void sdma_v4_4_2_query_ras_error_count(struct amdgpu_device *adev,
+73 -7
drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
··· 26 26 #include "amdgpu.h" 27 27 #include "umc/umc_12_0_0_offset.h" 28 28 #include "umc/umc_12_0_0_sh_mask.h" 29 + #include "mp/mp_13_0_6_sh_mask.h" 29 30 30 31 const uint32_t 31 32 umc_v12_0_channel_idx_tbl[] ··· 89 88 umc_v12_0_reset_error_count_per_channel, NULL); 90 89 } 91 90 92 - bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status) 91 + bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status) 93 92 { 93 + if (amdgpu_ras_is_poison_mode_supported(adev) && 94 + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && 95 + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1)) 96 + return true; 97 + 94 98 return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && 95 99 (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 || 96 100 REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 || 97 101 REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)); 98 102 } 99 103 100 - bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status) 104 + bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status) 101 105 { 106 + if (amdgpu_ras_is_poison_mode_supported(adev) && 107 + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && 108 + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1)) 109 + return false; 110 + 102 111 return (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && 103 112 (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1 || 104 113 (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 && ··· 116 105 /* Identify data parity error in replay mode */ 117 106 ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0x5 || 118 107 REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0xb) && 119 - !(umc_v12_0_is_uncorrectable_error(mc_umc_status))))); 108 + !(umc_v12_0_is_uncorrectable_error(adev, mc_umc_status))))); 120 109 } 121 110 122 111 static void umc_v12_0_query_correctable_error_count(struct amdgpu_device *adev, ··· 135 124 mc_umc_status = 136 125 RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4); 137 126 138 - if (umc_v12_0_is_correctable_error(mc_umc_status)) 127 + if (umc_v12_0_is_correctable_error(adev, mc_umc_status)) 139 128 *error_count += 1; 140 129 } 141 130 ··· 153 142 mc_umc_status = 154 143 RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4); 155 144 156 - if (umc_v12_0_is_uncorrectable_error(mc_umc_status)) 145 + if (umc_v12_0_is_uncorrectable_error(adev, mc_umc_status)) 157 146 *error_count += 1; 158 147 } 159 148 ··· 177 166 umc_v12_0_query_correctable_error_count(adev, umc_reg_offset, &ce_count); 178 167 umc_v12_0_query_uncorrectable_error_count(adev, umc_reg_offset, &ue_count); 179 168 180 - amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count); 181 - amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count); 169 + amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count); 170 + amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count); 182 171 183 172 return 0; 184 173 } ··· 371 360 return 0; 372 361 } 373 362 363 + static void umc_v12_0_ecc_info_query_ras_error_count(struct amdgpu_device *adev, 364 + void *ras_error_status) 365 + { 366 + amdgpu_mca_smu_log_ras_error(adev, 367 + AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_CE, ras_error_status); 368 + amdgpu_mca_smu_log_ras_error(adev, 369 + AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_UE, ras_error_status); 370 + } 371 + 372 + static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *adev, 373 + void *ras_error_status) 374 + { 375 + struct ras_err_node *err_node; 376 + uint64_t mc_umc_status; 377 + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; 378 + 379 + for_each_ras_error(err_node, err_data) { 380 + mc_umc_status = err_node->err_info.err_addr.err_status; 381 + if (!mc_umc_status) 382 + continue; 383 + 384 + if (umc_v12_0_is_uncorrectable_error(adev, mc_umc_status)) { 385 + uint64_t mca_addr, err_addr, mca_ipid; 386 + uint32_t InstanceIdLo; 387 + struct amdgpu_smuio_mcm_config_info *mcm_info; 388 + 389 + mcm_info = &err_node->err_info.mcm_info; 390 + mca_addr = err_node->err_info.err_addr.err_addr; 391 + mca_ipid = err_node->err_info.err_addr.err_ipid; 392 + 393 + err_addr = REG_GET_FIELD(mca_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); 394 + InstanceIdLo = REG_GET_FIELD(mca_ipid, MCMP1_IPIDT0, InstanceIdLo); 395 + 396 + dev_info(adev->dev, "UMC:IPID:0x%llx, aid:%d, inst:%d, ch:%d, err_addr:0x%llx\n", 397 + mca_ipid, 398 + mcm_info->die_id, 399 + MCA_IPID_LO_2_UMC_INST(InstanceIdLo), 400 + MCA_IPID_LO_2_UMC_CH(InstanceIdLo), 401 + err_addr); 402 + 403 + umc_v12_0_convert_error_address(adev, 404 + err_data, err_addr, 405 + MCA_IPID_LO_2_UMC_CH(InstanceIdLo), 406 + MCA_IPID_LO_2_UMC_INST(InstanceIdLo), 407 + mcm_info->die_id); 408 + 409 + /* Clear umc error address content */ 410 + memset(&err_node->err_info.err_addr, 411 + 0, sizeof(err_node->err_info.err_addr)); 412 + } 413 + } 414 + } 415 + 374 416 static void umc_v12_0_err_cnt_init(struct amdgpu_device *adev) 375 417 { 376 418 amdgpu_umc_loop_channels(adev, ··· 450 386 }, 451 387 .err_cnt_init = umc_v12_0_err_cnt_init, 452 388 .query_ras_poison_mode = umc_v12_0_query_ras_poison_mode, 389 + .ecc_info_query_ras_error_count = umc_v12_0_ecc_info_query_ras_error_count, 390 + .ecc_info_query_ras_error_address = umc_v12_0_ecc_info_query_ras_error_address, 453 391 };
+6 -2
drivers/gpu/drm/amd/amdgpu/umc_v12_0.h
··· 117 117 (pa) |= (UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) << UMC_V12_0_PA_CH6_BIT); \ 118 118 } while (0) 119 119 120 - bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status); 121 - bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status); 120 + #define MCA_IPID_LO_2_UMC_CH(_ipid_lo) (((((_ipid_lo) >> 20) & 0x1) * 4) + \ 121 + (((_ipid_lo) >> 12) & 0xF)) 122 + #define MCA_IPID_LO_2_UMC_INST(_ipid_lo) (((_ipid_lo) >> 21) & 0x7) 123 + 124 + bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); 125 + bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); 122 126 123 127 extern const uint32_t 124 128 umc_v12_0_channel_idx_tbl[]
+13 -13
drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
··· 330 330 pdd->gpuvm_limit = 331 331 pdd->dev->kfd->shared_resources.gpuvm_size - 1; 332 332 333 - /* dGPUs: the reserved space for kernel 334 - * before SVM 335 - */ 336 - pdd->qpd.cwsr_base = SVM_CWSR_BASE; 337 - pdd->qpd.ib_base = SVM_IB_BASE; 338 - 339 333 pdd->scratch_base = MAKE_SCRATCH_APP_BASE_VI(); 340 334 pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base); 341 335 } ··· 339 345 pdd->lds_base = MAKE_LDS_APP_BASE_V9(); 340 346 pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); 341 347 342 - pdd->gpuvm_base = PAGE_SIZE; 348 + /* Raven needs SVM to support graphic handle, etc. Leave the small 349 + * reserved space before SVM on Raven as well, even though we don't 350 + * have to. 351 + * Set gpuvm_base and gpuvm_limit to CANONICAL addresses so that they 352 + * are used in Thunk to reserve SVM. 353 + */ 354 + pdd->gpuvm_base = SVM_USER_BASE; 343 355 pdd->gpuvm_limit = 344 356 pdd->dev->kfd->shared_resources.gpuvm_size - 1; 345 357 346 358 pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9(); 347 359 pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base); 348 - 349 - /* 350 - * Place TBA/TMA on opposite side of VM hole to prevent 351 - * stray faults from triggering SVM on these pages. 352 - */ 353 - pdd->qpd.cwsr_base = pdd->dev->kfd->shared_resources.gpuvm_size; 354 360 } 355 361 356 362 int kfd_init_apertures(struct kfd_process *process) ··· 407 413 return -EINVAL; 408 414 } 409 415 } 416 + 417 + /* dGPUs: the reserved space for kernel 418 + * before SVM 419 + */ 420 + pdd->qpd.cwsr_base = SVM_CWSR_BASE; 421 + pdd->qpd.ib_base = SVM_IB_BASE; 410 422 } 411 423 412 424 dev_dbg(kfd_device, "node id %u\n", id);
+12 -23
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
··· 260 260 put_page(page); 261 261 } 262 262 263 - static unsigned long svm_migrate_successful_pages(struct migrate_vma *migrate) 264 - { 265 - unsigned long cpages = 0; 266 - unsigned long i; 267 - 268 - for (i = 0; i < migrate->npages; i++) { 269 - if (migrate->src[i] & MIGRATE_PFN_VALID && 270 - migrate->src[i] & MIGRATE_PFN_MIGRATE) 271 - cpages++; 272 - } 273 - return cpages; 274 - } 275 - 276 263 static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate) 277 264 { 278 265 unsigned long upages = 0; ··· 389 402 struct dma_fence *mfence = NULL; 390 403 struct migrate_vma migrate = { 0 }; 391 404 unsigned long cpages = 0; 405 + unsigned long mpages = 0; 392 406 dma_addr_t *scratch; 393 407 void *buf; 394 408 int r = -ENOMEM; ··· 438 450 r = svm_migrate_copy_to_vram(node, prange, &migrate, &mfence, scratch, ttm_res_offset); 439 451 migrate_vma_pages(&migrate); 440 452 441 - pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n", 442 - svm_migrate_successful_pages(&migrate), cpages, migrate.npages); 443 - 444 453 svm_migrate_copy_done(adev, mfence); 445 454 migrate_vma_finalize(&migrate); 455 + 456 + mpages = cpages - svm_migrate_unsuccessful_pages(&migrate); 457 + pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n", 458 + mpages, cpages, migrate.npages); 446 459 447 460 kfd_smi_event_migration_end(node, p->lead_thread->pid, 448 461 start >> PAGE_SHIFT, end >> PAGE_SHIFT, ··· 454 465 out_free: 455 466 kvfree(buf); 456 467 out: 457 - if (!r && cpages) { 468 + if (!r && mpages) { 458 469 pdd = svm_range_get_pdd_by_node(prange, node); 459 470 if (pdd) 460 - WRITE_ONCE(pdd->page_in, pdd->page_in + cpages); 471 + WRITE_ONCE(pdd->page_in, pdd->page_in + mpages); 461 472 462 - return cpages; 473 + return mpages; 463 474 } 464 475 return r; 465 476 } ··· 487 498 struct vm_area_struct *vma; 488 499 uint64_t ttm_res_offset; 489 500 struct kfd_node *node; 490 - unsigned long cpages = 0; 501 + unsigned long mpages = 0; 491 502 long r = 0; 492 503 493 504 if (start_mgr < prange->start || last_mgr > prange->last) { ··· 529 540 pr_debug("failed %ld to migrate\n", r); 530 541 break; 531 542 } else { 532 - cpages += r; 543 + mpages += r; 533 544 } 534 545 ttm_res_offset += next - addr; 535 546 addr = next; 536 547 } 537 548 538 - if (cpages) { 549 + if (mpages) { 539 550 prange->actual_loc = best_loc; 540 - prange->vram_pages = prange->vram_pages + cpages; 551 + prange->vram_pages += mpages; 541 552 } else if (!prange->actual_loc) { 542 553 /* if no page migrated and all pages from prange are at 543 554 * sys ram drop svm_bo got from svm_range_vram_node_new
+1 -1
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
··· 970 970 struct work_struct debug_event_workarea; 971 971 972 972 /* Tracks debug per-vmid request for debug flags */ 973 - bool dbg_flags; 973 + u32 dbg_flags; 974 974 975 975 atomic_t poison; 976 976 /* Queues are in paused stated because we are in the process of doing a CRIU checkpoint */
+36 -43
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 158 158 static int 159 159 svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, 160 160 unsigned long offset, unsigned long npages, 161 - unsigned long *hmm_pfns, uint32_t gpuidx, uint64_t *vram_pages) 161 + unsigned long *hmm_pfns, uint32_t gpuidx) 162 162 { 163 163 enum dma_data_direction dir = DMA_BIDIRECTIONAL; 164 164 dma_addr_t *addr = prange->dma_addr[gpuidx]; 165 165 struct device *dev = adev->dev; 166 166 struct page *page; 167 - uint64_t vram_pages_dev; 168 167 int i, r; 169 168 170 169 if (!addr) { ··· 173 174 prange->dma_addr[gpuidx] = addr; 174 175 } 175 176 176 - vram_pages_dev = 0; 177 177 addr += offset; 178 178 for (i = 0; i < npages; i++) { 179 179 if (svm_is_valid_dma_mapping_addr(dev, addr[i])) ··· 182 184 if (is_zone_device_page(page)) { 183 185 struct amdgpu_device *bo_adev = prange->svm_bo->node->adev; 184 186 185 - vram_pages_dev++; 186 187 addr[i] = (hmm_pfns[i] << PAGE_SHIFT) + 187 188 bo_adev->vm_manager.vram_base_offset - 188 189 bo_adev->kfd.pgmap.range.start; ··· 198 201 pr_debug_ratelimited("dma mapping 0x%llx for page addr 0x%lx\n", 199 202 addr[i] >> PAGE_SHIFT, page_to_pfn(page)); 200 203 } 201 - *vram_pages = vram_pages_dev; 204 + 202 205 return 0; 203 206 } 204 207 205 208 static int 206 209 svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, 207 210 unsigned long offset, unsigned long npages, 208 - unsigned long *hmm_pfns, uint64_t *vram_pages) 211 + unsigned long *hmm_pfns) 209 212 { 210 213 struct kfd_process *p; 211 214 uint32_t gpuidx; ··· 224 227 } 225 228 226 229 r = svm_range_dma_map_dev(pdd->dev->adev, prange, offset, npages, 227 - hmm_pfns, gpuidx, vram_pages); 230 + hmm_pfns, gpuidx); 228 231 if (r) 229 232 break; 230 233 } ··· 882 885 883 886 static void * 884 887 svm_range_copy_array(void *psrc, size_t size, uint64_t num_elements, 885 - uint64_t offset) 888 + uint64_t offset, uint64_t *vram_pages) 886 889 { 890 + unsigned char *src = (unsigned char *)psrc + offset; 887 891 unsigned char *dst; 892 + uint64_t i; 888 893 889 894 dst = kvmalloc_array(num_elements, size, GFP_KERNEL); 890 895 if (!dst) 891 896 return NULL; 892 - memcpy(dst, (unsigned char *)psrc + offset, num_elements * size); 897 + 898 + if (!vram_pages) { 899 + memcpy(dst, src, num_elements * size); 900 + return (void *)dst; 901 + } 902 + 903 + *vram_pages = 0; 904 + for (i = 0; i < num_elements; i++) { 905 + dma_addr_t *temp; 906 + temp = (dma_addr_t *)dst + i; 907 + *temp = *((dma_addr_t *)src + i); 908 + if (*temp&SVM_RANGE_VRAM_DOMAIN) 909 + (*vram_pages)++; 910 + } 893 911 894 912 return (void *)dst; 895 913 } ··· 918 906 if (!src->dma_addr[i]) 919 907 continue; 920 908 dst->dma_addr[i] = svm_range_copy_array(src->dma_addr[i], 921 - sizeof(*src->dma_addr[i]), src->npages, 0); 909 + sizeof(*src->dma_addr[i]), src->npages, 0, NULL); 922 910 if (!dst->dma_addr[i]) 923 911 return -ENOMEM; 924 912 } ··· 929 917 static int 930 918 svm_range_split_array(void *ppnew, void *ppold, size_t size, 931 919 uint64_t old_start, uint64_t old_n, 932 - uint64_t new_start, uint64_t new_n) 920 + uint64_t new_start, uint64_t new_n, uint64_t *new_vram_pages) 933 921 { 934 922 unsigned char *new, *old, *pold; 935 923 uint64_t d; ··· 941 929 return 0; 942 930 943 931 d = (new_start - old_start) * size; 944 - new = svm_range_copy_array(pold, size, new_n, d); 932 + /* get dma addr array for new range and calculte its vram page number */ 933 + new = svm_range_copy_array(pold, size, new_n, d, new_vram_pages); 945 934 if (!new) 946 935 return -ENOMEM; 947 936 d = (new_start == old_start) ? new_n * size : 0; 948 - old = svm_range_copy_array(pold, size, old_n, d); 937 + old = svm_range_copy_array(pold, size, old_n, d, NULL); 949 938 if (!old) { 950 939 kvfree(new); 951 940 return -ENOMEM; ··· 968 955 for (i = 0; i < MAX_GPU_INSTANCE; i++) { 969 956 r = svm_range_split_array(&new->dma_addr[i], &old->dma_addr[i], 970 957 sizeof(*old->dma_addr[i]), old->start, 971 - npages, new->start, new->npages); 958 + npages, new->start, new->npages, 959 + old->actual_loc ? &new->vram_pages : NULL); 972 960 if (r) 973 961 return r; 974 962 } 963 + if (old->actual_loc) 964 + old->vram_pages -= new->vram_pages; 975 965 976 966 return 0; 977 967 } ··· 997 981 998 982 new->svm_bo = svm_range_bo_ref(old->svm_bo); 999 983 new->ttm_res = old->ttm_res; 1000 - 1001 - /* set new's vram_pages as old range's now, the acurate vram_pages 1002 - * will be updated during mapping 1003 - */ 1004 - new->vram_pages = min(old->vram_pages, new->npages); 1005 984 1006 985 spin_lock(&new->svm_bo->list_lock); 1007 986 list_add(&new->svm_bo_list, &new->svm_bo->range_list); ··· 1120 1109 svm_range_split_tail(struct svm_range *prange, uint64_t new_last, 1121 1110 struct list_head *insert_list, struct list_head *remap_list) 1122 1111 { 1123 - struct svm_range *tail; 1112 + struct svm_range *tail = NULL; 1124 1113 int r = svm_range_split(prange, prange->start, new_last, &tail); 1125 1114 1126 1115 if (!r) { ··· 1135 1124 svm_range_split_head(struct svm_range *prange, uint64_t new_start, 1136 1125 struct list_head *insert_list, struct list_head *remap_list) 1137 1126 { 1138 - struct svm_range *head; 1127 + struct svm_range *head = NULL; 1139 1128 int r = svm_range_split(prange, new_start, prange->last, &head); 1140 1129 1141 1130 if (!r) { ··· 1584 1573 struct svm_validate_context *ctx; 1585 1574 unsigned long start, end, addr; 1586 1575 struct kfd_process *p; 1587 - uint64_t vram_pages; 1588 1576 void *owner; 1589 1577 int32_t idx; 1590 1578 int r = 0; ··· 1658 1648 } 1659 1649 } 1660 1650 1661 - vram_pages = 0; 1662 - start = prange->start << PAGE_SHIFT; 1663 - end = (prange->last + 1) << PAGE_SHIFT; 1651 + start = map_start << PAGE_SHIFT; 1652 + end = (map_last + 1) << PAGE_SHIFT; 1664 1653 for (addr = start; !r && addr < end; ) { 1665 1654 struct hmm_range *hmm_range; 1666 1655 unsigned long map_start_vma; 1667 1656 unsigned long map_last_vma; 1668 1657 struct vm_area_struct *vma; 1669 - uint64_t vram_pages_vma; 1670 1658 unsigned long next = 0; 1671 1659 unsigned long offset; 1672 1660 unsigned long npages; ··· 1691 1683 } 1692 1684 1693 1685 if (!r) { 1694 - offset = (addr - start) >> PAGE_SHIFT; 1686 + offset = (addr >> PAGE_SHIFT) - prange->start; 1695 1687 r = svm_range_dma_map(prange, ctx->bitmap, offset, npages, 1696 - hmm_range->hmm_pfns, &vram_pages_vma); 1688 + hmm_range->hmm_pfns); 1697 1689 if (r) 1698 1690 pr_debug("failed %d to dma map range\n", r); 1699 - else 1700 - vram_pages += vram_pages_vma; 1701 1691 } 1702 1692 1703 1693 svm_range_lock(prange); ··· 1726 1720 svm_range_unlock(prange); 1727 1721 1728 1722 addr = next; 1729 - } 1730 - 1731 - if (addr == end) { 1732 - prange->vram_pages = vram_pages; 1733 - 1734 - /* if prange does not include any vram page and it 1735 - * has not released svm_bo drop its svm_bo reference 1736 - * and set its actaul_loc to sys ram 1737 - */ 1738 - if (!vram_pages && prange->ttm_res) { 1739 - prange->actual_loc = 0; 1740 - svm_range_vram_node_free(prange); 1741 - } 1742 1723 } 1743 1724 1744 1725 svm_range_unreserve_bos(ctx);
+24 -19
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
··· 1342 1342 num_cpu++; 1343 1343 } 1344 1344 1345 + if (list_empty(&kdev->io_link_props)) 1346 + return -ENODATA; 1347 + 1345 1348 gpu_link = list_first_entry(&kdev->io_link_props, 1346 - struct kfd_iolink_properties, list); 1347 - if (!gpu_link) 1348 - return -ENOMEM; 1349 + struct kfd_iolink_properties, list); 1349 1350 1350 1351 for (i = 0; i < num_cpu; i++) { 1351 1352 /* CPU <--> GPU */ ··· 1424 1423 peer->gpu->adev)) 1425 1424 return ret; 1426 1425 1426 + if (list_empty(&kdev->io_link_props)) 1427 + return -ENODATA; 1428 + 1427 1429 iolink1 = list_first_entry(&kdev->io_link_props, 1428 - struct kfd_iolink_properties, list); 1429 - if (!iolink1) 1430 - return -ENOMEM; 1430 + struct kfd_iolink_properties, list); 1431 + 1432 + if (list_empty(&peer->io_link_props)) 1433 + return -ENODATA; 1431 1434 1432 1435 iolink2 = list_first_entry(&peer->io_link_props, 1433 - struct kfd_iolink_properties, list); 1434 - if (!iolink2) 1435 - return -ENOMEM; 1436 + struct kfd_iolink_properties, list); 1436 1437 1437 1438 props = kfd_alloc_struct(props); 1438 1439 if (!props) ··· 1452 1449 /* CPU->CPU link*/ 1453 1450 cpu_dev = kfd_topology_device_by_proximity_domain(iolink1->node_to); 1454 1451 if (cpu_dev) { 1455 - list_for_each_entry(iolink3, &cpu_dev->io_link_props, list) 1456 - if (iolink3->node_to == iolink2->node_to) 1457 - break; 1452 + list_for_each_entry(iolink3, &cpu_dev->io_link_props, list) { 1453 + if (iolink3->node_to != iolink2->node_to) 1454 + continue; 1458 1455 1459 - props->weight += iolink3->weight; 1460 - props->min_latency += iolink3->min_latency; 1461 - props->max_latency += iolink3->max_latency; 1462 - props->min_bandwidth = min(props->min_bandwidth, 1463 - iolink3->min_bandwidth); 1464 - props->max_bandwidth = min(props->max_bandwidth, 1465 - iolink3->max_bandwidth); 1456 + props->weight += iolink3->weight; 1457 + props->min_latency += iolink3->min_latency; 1458 + props->max_latency += iolink3->max_latency; 1459 + props->min_bandwidth = min(props->min_bandwidth, 1460 + iolink3->min_bandwidth); 1461 + props->max_bandwidth = min(props->max_bandwidth, 1462 + iolink3->max_bandwidth); 1463 + break; 1464 + } 1466 1465 } else { 1467 1466 WARN(1, "CPU node not found"); 1468 1467 }
+41 -60
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 37 37 #include "dc/dc_dmub_srv.h" 38 38 #include "dc/dc_edid_parser.h" 39 39 #include "dc/dc_stat.h" 40 + #include "dc/dc_state.h" 40 41 #include "amdgpu_dm_trace.h" 41 42 #include "dpcd_defs.h" 42 43 #include "link/protocols/link_dpcd.h" ··· 67 66 #include "amdgpu_dm_debugfs.h" 68 67 #endif 69 68 #include "amdgpu_dm_psr.h" 70 - #include "amdgpu_dm_replay.h" 71 69 72 70 #include "ivsrcid/ivsrcid_vislands30.h" 73 71 ··· 1294 1294 /* AGP aperture is disabled */ 1295 1295 if (agp_bot > agp_top) { 1296 1296 logical_addr_low = adev->gmc.fb_start >> 18; 1297 - if (adev->apu_flags & AMD_APU_IS_RAVEN2) 1297 + if (adev->apu_flags & (AMD_APU_IS_RAVEN2 | 1298 + AMD_APU_IS_RENOIR | 1299 + AMD_APU_IS_GREEN_SARDINE)) 1298 1300 /* 1299 1301 * Raven2 has a HW issue that it is unable to use the vram which 1300 1302 * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the ··· 1308 1306 logical_addr_high = adev->gmc.fb_end >> 18; 1309 1307 } else { 1310 1308 logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; 1311 - if (adev->apu_flags & AMD_APU_IS_RAVEN2) 1309 + if (adev->apu_flags & (AMD_APU_IS_RAVEN2 | 1310 + AMD_APU_IS_RENOIR | 1311 + AMD_APU_IS_GREEN_SARDINE)) 1312 1312 /* 1313 1313 * Raven2 has a HW issue that it is unable to use the vram which 1314 1314 * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the ··· 1714 1710 init_data.dcn_reg_offsets = adev->reg_offset[DCE_HWIP][0]; 1715 1711 init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0]; 1716 1712 init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0]; 1713 + 1714 + init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL; 1717 1715 1718 1716 /* Enable DWB for tested platforms only */ 1719 1717 if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) ··· 2613 2607 2614 2608 memset(del_streams, 0, sizeof(del_streams)); 2615 2609 2616 - context = dc_create_state(dc); 2610 + context = dc_state_create_current_copy(dc); 2617 2611 if (context == NULL) 2618 2612 goto context_alloc_fail; 2619 - 2620 - dc_resource_state_copy_construct_current(dc, context); 2621 2613 2622 2614 /* First remove from context all streams */ 2623 2615 for (i = 0; i < context->stream_count; i++) { ··· 2626 2622 2627 2623 /* Remove all planes for removed streams and then remove the streams */ 2628 2624 for (i = 0; i < del_streams_count; i++) { 2629 - if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) { 2625 + if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) { 2630 2626 res = DC_FAIL_DETACH_SURFACES; 2631 2627 goto fail; 2632 2628 } 2633 2629 2634 - res = dc_remove_stream_from_ctx(dc, context, del_streams[i]); 2630 + res = dc_state_remove_stream(dc, context, del_streams[i]); 2635 2631 if (res != DC_OK) 2636 2632 goto fail; 2637 2633 } ··· 2639 2635 res = dc_commit_streams(dc, context->streams, context->stream_count); 2640 2636 2641 2637 fail: 2642 - dc_release_state(context); 2638 + dc_state_release(context); 2643 2639 2644 2640 context_alloc_fail: 2645 2641 return res; ··· 2666 2662 2667 2663 dc_allow_idle_optimizations(adev->dm.dc, false); 2668 2664 2669 - dm->cached_dc_state = dc_copy_state(dm->dc->current_state); 2665 + dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state); 2670 2666 2671 2667 dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); 2672 2668 ··· 2860 2856 bool need_hotplug = false; 2861 2857 2862 2858 if (dm->dc->caps.ips_support) { 2863 - dc_dmub_srv_exit_low_power_state(dm->dc); 2859 + dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); 2864 2860 } 2865 2861 2866 2862 if (amdgpu_in_reset(adev)) { ··· 2913 2909 2914 2910 dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, true); 2915 2911 2916 - dc_release_state(dm->cached_dc_state); 2912 + dc_state_release(dm->cached_dc_state); 2917 2913 dm->cached_dc_state = NULL; 2918 2914 2919 2915 amdgpu_dm_irq_resume_late(adev); ··· 2923 2919 return 0; 2924 2920 } 2925 2921 /* Recreate dc_state - DC invalidates it when setting power state to S3. */ 2926 - dc_release_state(dm_state->context); 2927 - dm_state->context = dc_create_state(dm->dc); 2922 + dc_state_release(dm_state->context); 2923 + dm_state->context = dc_state_create(dm->dc); 2928 2924 /* TODO: Remove dc_state->dccg, use dc->dccg directly. */ 2929 - dc_resource_state_construct(dm->dc, dm_state->context); 2930 2925 2931 2926 /* Before powering on DC we need to re-initialize DMUB. */ 2932 2927 dm_dmub_hw_resume(adev); ··· 4001 3998 old_state = to_dm_atomic_state(obj->state); 4002 3999 4003 4000 if (old_state && old_state->context) 4004 - new_state->context = dc_copy_state(old_state->context); 4001 + new_state->context = dc_state_create_copy(old_state->context); 4005 4002 4006 4003 if (!new_state->context) { 4007 4004 kfree(new_state); ··· 4017 4014 struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 4018 4015 4019 4016 if (dm_state && dm_state->context) 4020 - dc_release_state(dm_state->context); 4017 + dc_state_release(dm_state->context); 4021 4018 4022 4019 kfree(dm_state); 4023 4020 } ··· 4053 4050 if (!state) 4054 4051 return -ENOMEM; 4055 4052 4056 - state->context = dc_create_state(adev->dm.dc); 4053 + state->context = dc_state_create_current_copy(adev->dm.dc); 4057 4054 if (!state->context) { 4058 4055 kfree(state); 4059 4056 return -ENOMEM; 4060 4057 } 4061 - 4062 - dc_resource_state_copy_construct_current(adev->dm.dc, state->context); 4063 4058 4064 4059 drm_atomic_private_obj_init(adev_to_drm(adev), 4065 4060 &adev->dm.atomic_obj, ··· 4066 4065 4067 4066 r = amdgpu_display_modeset_create_props(adev); 4068 4067 if (r) { 4069 - dc_release_state(state->context); 4068 + dc_state_release(state->context); 4070 4069 kfree(state); 4071 4070 return r; 4072 4071 } ··· 4078 4077 4079 4078 r = amdgpu_dm_audio_init(adev); 4080 4079 if (r) { 4081 - dc_release_state(state->context); 4080 + dc_state_release(state->context); 4082 4081 kfree(state); 4083 4082 return r; 4084 4083 } ··· 4392 4391 enum dc_connection_type new_connection_type = dc_connection_none; 4393 4392 const struct dc_plane_cap *plane; 4394 4393 bool psr_feature_enabled = false; 4395 - bool replay_feature_enabled = false; 4396 4394 int max_overlay = dm->dc->caps.max_slave_planes; 4397 4395 4398 4396 dm->display_indexes_num = dm->dc->caps.max_streams; ··· 4503 4503 } 4504 4504 } 4505 4505 4506 - if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) { 4507 - switch (adev->ip_versions[DCE_HWIP][0]) { 4508 - case IP_VERSION(3, 1, 4): 4509 - case IP_VERSION(3, 1, 5): 4510 - case IP_VERSION(3, 1, 6): 4511 - case IP_VERSION(3, 2, 0): 4512 - case IP_VERSION(3, 2, 1): 4513 - replay_feature_enabled = true; 4514 - break; 4515 - default: 4516 - replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK; 4517 - break; 4518 - } 4519 - } 4520 4506 /* loops over all connectors on the board */ 4521 4507 for (i = 0; i < link_cnt; i++) { 4522 4508 struct dc_link *link = NULL; ··· 4570 4584 if (ret) { 4571 4585 amdgpu_dm_update_connector_after_detect(aconnector); 4572 4586 setup_backlight_device(dm, aconnector); 4573 - 4574 - /* 4575 - * Disable psr if replay can be enabled 4576 - */ 4577 - if (replay_feature_enabled && amdgpu_dm_setup_replay(link, aconnector)) 4578 - psr_feature_enabled = false; 4579 4587 4580 4588 if (psr_feature_enabled) 4581 4589 amdgpu_dm_set_psr_caps(link); ··· 6240 6260 6241 6261 if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) 6242 6262 mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); 6243 - 6244 - if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) { 6263 + else if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 6264 + stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || 6265 + stream->signal == SIGNAL_TYPE_EDP) { 6245 6266 // 6246 6267 // should decide stream support vsc sdp colorimetry capability 6247 6268 // before building vsc info packet ··· 6258 6277 if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) 6259 6278 tf = TRANSFER_FUNC_GAMMA_22; 6260 6279 mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf); 6261 - aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; 6262 6280 6281 + if (stream->link->psr_settings.psr_feature_enabled) 6282 + aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; 6263 6283 } 6264 6284 finish: 6265 6285 dc_sink_release(sink); ··· 6640 6658 if (!dc_plane_state) 6641 6659 goto cleanup; 6642 6660 6643 - dc_state = dc_create_state(dc); 6661 + dc_state = dc_state_create(dc); 6644 6662 if (!dc_state) 6645 6663 goto cleanup; 6646 6664 ··· 6667 6685 dc_result = dc_validate_plane(dc, dc_plane_state); 6668 6686 6669 6687 if (dc_result == DC_OK) 6670 - dc_result = dc_add_stream_to_ctx(dc, dc_state, stream); 6688 + dc_result = dc_state_add_stream(dc, dc_state, stream); 6671 6689 6672 - if (dc_result == DC_OK && !dc_add_plane_to_context( 6690 + if (dc_result == DC_OK && !dc_state_add_plane( 6673 6691 dc, 6674 6692 stream, 6675 6693 dc_plane_state, ··· 6681 6699 6682 6700 cleanup: 6683 6701 if (dc_state) 6684 - dc_release_state(dc_state); 6702 + dc_state_release(dc_state); 6685 6703 6686 6704 if (dc_plane_state) 6687 6705 dc_plane_state_release(dc_plane_state); ··· 6989 7007 if (IS_ERR(mst_state)) 6990 7008 return PTR_ERR(mst_state); 6991 7009 6992 - if (!mst_state->pbn_div.full) 6993 - mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link)); 7010 + mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link)); 6994 7011 6995 7012 if (!state->duplicated) { 6996 7013 int max_bpc = conn_state->max_requested_bpc; ··· 8839 8858 dc_stream_get_status(dm_new_crtc_state->stream); 8840 8859 8841 8860 if (!status) 8842 - status = dc_stream_get_status_from_state(dc_state, 8861 + status = dc_state_get_stream_status(dc_state, 8843 8862 dm_new_crtc_state->stream); 8844 8863 if (!status) 8845 8864 drm_err(dev, ··· 8982 9001 if (new_con_state->crtc && 8983 9002 new_con_state->crtc->state->active && 8984 9003 drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) { 8985 - dc_dmub_srv_exit_low_power_state(dm->dc); 9004 + dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); 8986 9005 break; 8987 9006 } 8988 9007 } ··· 9764 9783 crtc->base.id); 9765 9784 9766 9785 /* i.e. reset mode */ 9767 - if (dc_remove_stream_from_ctx( 9786 + if (dc_state_remove_stream( 9768 9787 dm->dc, 9769 9788 dm_state->context, 9770 9789 dm_old_crtc_state->stream) != DC_OK) { ··· 9807 9826 DRM_DEBUG_ATOMIC("Enabling DRM crtc: %d\n", 9808 9827 crtc->base.id); 9809 9828 9810 - if (dc_add_stream_to_ctx( 9829 + if (dc_state_add_stream( 9811 9830 dm->dc, 9812 9831 dm_state->context, 9813 9832 dm_new_crtc_state->stream) != DC_OK) { ··· 10129 10148 if (ret) 10130 10149 return ret; 10131 10150 10132 - if (!dc_remove_plane_from_context( 10151 + if (!dc_state_remove_plane( 10133 10152 dc, 10134 10153 dm_old_crtc_state->stream, 10135 10154 dm_old_plane_state->dc_state, ··· 10207 10226 * state. It'll be released when the atomic state is 10208 10227 * cleaned. 10209 10228 */ 10210 - if (!dc_add_plane_to_context( 10229 + if (!dc_state_add_plane( 10211 10230 dc, 10212 10231 dm_new_crtc_state->stream, 10213 10232 dc_new_plane_state, ··· 10753 10772 DRM_DEBUG_DRIVER("drm_dp_mst_atomic_check() failed\n"); 10754 10773 goto fail; 10755 10774 } 10756 - status = dc_validate_global_state(dc, dm_state->context, true); 10775 + status = dc_validate_global_state(dc, dm_state->context, false); 10757 10776 if (status != DC_OK) { 10758 10777 DRM_DEBUG_DRIVER("DC global validation failure: %s (%d)", 10759 10778 dc_status_to_str(status), status); ··· 10891 10910 input->cea_total_length = total_length; 10892 10911 memcpy(input->payload, data, length); 10893 10912 10894 - res = dm_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 10913 + res = dc_wake_and_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 10895 10914 if (!res) { 10896 10915 DRM_ERROR("EDID CEA parser failed\n"); 10897 10916 return false;
+2 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 747 747 AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF, 748 748 AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF, 749 749 AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF, 750 - AMDGPU_TRANSFER_FUNCTION_COUNT 750 + AMDGPU_TRANSFER_FUNCTION_COUNT 751 751 }; 752 752 753 753 struct dm_plane_state { ··· 844 844 845 845 int abm_level; 846 846 847 - /** 847 + /** 848 848 * @regamma_tf: 849 849 * 850 850 * Pre-defined transfer function for converting internal FB -> wire
+17 -6
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
··· 85 85 setup_x_points_distribution(); 86 86 } 87 87 88 + static inline struct fixed31_32 amdgpu_dm_fixpt_from_s3132(__u64 x) 89 + { 90 + struct fixed31_32 val; 91 + 92 + /* If negative, convert to 2's complement. */ 93 + if (x & (1ULL << 63)) 94 + x = -(x & ~(1ULL << 63)); 95 + 96 + val.value = x; 97 + return val; 98 + } 99 + 88 100 #ifdef AMD_PRIVATE_COLOR 89 101 /* Pre-defined Transfer Functions (TF) 90 102 * ··· 442 430 } 443 431 444 432 /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */ 445 - matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i - (i / 4)]); 433 + matrix[i] = amdgpu_dm_fixpt_from_s3132(ctm->matrix[i - (i / 4)]); 446 434 } 447 435 } 448 436 ··· 464 452 */ 465 453 for (i = 0; i < 12; i++) { 466 454 /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */ 467 - matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i]); 455 + matrix[i] = amdgpu_dm_fixpt_from_s3132(ctm->matrix[i]); 468 456 } 469 457 } 470 458 ··· 642 630 static enum dc_transfer_func_predefined 643 631 amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf) 644 632 { 645 - switch (tf) 646 - { 633 + switch (tf) { 647 634 default: 648 635 case AMDGPU_TRANSFER_FUNCTION_DEFAULT: 649 636 case AMDGPU_TRANSFER_FUNCTION_IDENTITY: ··· 1148 1137 uint32_t shaper_size, lut3d_size, blend_size; 1149 1138 int ret; 1150 1139 1151 - dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult); 1140 + dc_plane_state->hdr_mult = amdgpu_dm_fixpt_from_s3132(dm_plane_state->hdr_mult); 1152 1141 1153 1142 shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size); 1154 1143 shaper_size = shaper_lut != NULL ? shaper_size : 0; ··· 1236 1225 * plane and CRTC degamma at the same time. Explicitly reject atomic 1237 1226 * updates when userspace sets both plane and CRTC degamma properties. 1238 1227 */ 1239 - if (has_crtc_cm_degamma && ret != -EINVAL){ 1228 + if (has_crtc_cm_degamma && ret != -EINVAL) { 1240 1229 drm_dbg_kms(crtc->base.crtc->dev, 1241 1230 "doesn't support plane and CRTC degamma at the same time\n"); 1242 1231 return -EINVAL;
+2 -9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
··· 29 29 #include "dc.h" 30 30 #include "amdgpu.h" 31 31 #include "amdgpu_dm_psr.h" 32 - #include "amdgpu_dm_replay.h" 33 32 #include "amdgpu_dm_crtc.h" 34 33 #include "amdgpu_dm_plane.h" 35 34 #include "amdgpu_dm_trace.h" ··· 123 124 * fill_dc_dirty_rects(). 124 125 */ 125 126 if (vblank_work->stream && vblank_work->stream->link) { 126 - /* 127 - * Prioritize replay, instead of psr 128 - */ 129 - if (vblank_work->stream->link->replay_settings.replay_feature_enabled) 130 - amdgpu_dm_replay_enable(vblank_work->stream, false); 131 - else if (vblank_work->enable) { 127 + if (vblank_work->enable) { 132 128 if (vblank_work->stream->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && 133 129 vblank_work->stream->link->psr_settings.psr_allow_active) 134 130 amdgpu_dm_psr_disable(vblank_work->stream); ··· 132 138 #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY 133 139 !amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) && 134 140 #endif 135 - vblank_work->stream->link->panel_config.psr.disallow_replay && 136 141 vblank_work->acrtc->dm_irq_params.allow_psr_entry) { 137 142 amdgpu_dm_psr_enable(vblank_work->stream); 138 143 } ··· 305 312 { 306 313 struct amdgpu_device *adev = drm_to_adev(crtc->dev); 307 314 308 - if(adev->dm.dc->caps.color.mpc.ogam_ram) 315 + if (adev->dm.dc->caps.color.mpc.ogam_ram) 309 316 drm_object_attach_property(&crtc->base, 310 317 adev->mode_info.regamma_tf_property, 311 318 AMDGPU_TRANSFER_FUNCTION_DEFAULT);
+4 -23
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
··· 2976 2976 struct amdgpu_device *adev = data; 2977 2977 struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub; 2978 2978 enum dmub_gpint_command cmd; 2979 - enum dmub_status status; 2980 2979 u64 mask = 0xffff; 2981 2980 u8 shift = 0; 2982 2981 u32 res; ··· 3002 3003 break; 3003 3004 } 3004 3005 3005 - status = dmub_srv_send_gpint_command(srv, cmd, res, 30); 3006 - 3007 - if (status == DMUB_STATUS_TIMEOUT) 3008 - return -ETIMEDOUT; 3009 - else if (status == DMUB_STATUS_INVALID) 3010 - return -EINVAL; 3011 - else if (status != DMUB_STATUS_OK) 3006 + if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, res, NULL, DM_DMUB_WAIT_TYPE_WAIT)) 3012 3007 return -EIO; 3013 3008 3014 3009 usleep_range(100, 1000); ··· 3019 3026 enum dmub_gpint_command cmd = DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD0; 3020 3027 struct amdgpu_device *adev = data; 3021 3028 struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub; 3022 - enum dmub_status status; 3023 3029 u8 shift = 0; 3024 3030 u64 raw = 0; 3025 3031 u64 res = 0; ··· 3028 3036 return -EINVAL; 3029 3037 3030 3038 while (i < 4) { 3031 - status = dmub_srv_send_gpint_command(srv, cmd, 0, 30); 3039 + uint32_t response; 3032 3040 3033 - if (status == DMUB_STATUS_OK) { 3034 - status = dmub_srv_get_gpint_response(srv, (u32 *) &raw); 3035 - 3036 - if (status == DMUB_STATUS_INVALID) 3037 - return -EINVAL; 3038 - else if (status != DMUB_STATUS_OK) 3039 - return -EIO; 3040 - } else if (status == DMUB_STATUS_TIMEOUT) { 3041 - return -ETIMEDOUT; 3042 - } else if (status == DMUB_STATUS_INVALID) { 3043 - return -EINVAL; 3044 - } else { 3041 + if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, 0, &response, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 3045 3042 return -EIO; 3046 - } 3047 3043 3044 + raw = response; 3048 3045 usleep_range(100, 1000); 3049 3046 3050 3047 cmd++;
+3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
··· 51 51 !link->dpcd_caps.psr_info.psr2_su_y_granularity_cap) 52 52 return false; 53 53 54 + if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU) 55 + return false; 56 + 54 57 return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub); 55 58 } 56 59
+1 -3
drivers/gpu/drm/amd/display/dc/Makefile
··· 34 34 DC_LIBS += dcn201 35 35 DC_LIBS += dcn30 36 36 DC_LIBS += dcn301 37 - DC_LIBS += dcn302 38 - DC_LIBS += dcn303 39 37 DC_LIBS += dcn31 40 38 DC_LIBS += dcn314 41 39 DC_LIBS += dcn32 ··· 60 62 include $(AMD_DC) 61 63 62 64 DISPLAY_CORE = dc.o dc_stat.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ 63 - dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o dc_link_exports.o 65 + dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o dc_link_exports.o dc_state.o 64 66 65 67 DISPLAY_CORE += dc_vm_helper.o 66 68
+2 -1
drivers/gpu/drm/amd/display/dc/basics/conversion.c
··· 103 103 104 104 static uint32_t find_gcd(uint32_t a, uint32_t b) 105 105 { 106 - uint32_t remainder = 0; 106 + uint32_t remainder; 107 + 107 108 while (b != 0) { 108 109 remainder = a % b; 109 110 a = b;
+14 -5
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
··· 1014 1014 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); 1015 1015 break; 1016 1016 case AS_SIGNAL_TYPE_DISPLAY_PORT: 1017 - ss_info->spread_spectrum_percentage = 1017 + if (bp->base.integrated_info) { 1018 + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage); 1019 + ss_info->spread_spectrum_percentage = 1020 + bp->base.integrated_info->gpuclk_ss_percentage; 1021 + ss_info->type.CENTER_MODE = 1022 + bp->base.integrated_info->gpuclk_ss_type; 1023 + } else { 1024 + ss_info->spread_spectrum_percentage = 1018 1025 disp_cntl_tbl->dp_ss_percentage; 1019 - ss_info->spread_spectrum_range = 1026 + ss_info->spread_spectrum_range = 1020 1027 disp_cntl_tbl->dp_ss_rate_10hz * 10; 1021 - if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) 1022 - ss_info->type.CENTER_MODE = true; 1023 - 1028 + if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) 1029 + ss_info->type.CENTER_MODE = true; 1030 + } 1024 1031 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage); 1025 1032 break; 1026 1033 case AS_SIGNAL_TYPE_GPU_PLL: ··· 2820 2813 info->ma_channel_number = info_v2_2->umachannelnumber; 2821 2814 info->dp_ss_control = 2822 2815 le16_to_cpu(info_v2_2->reserved1); 2816 + info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage; 2817 + info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type; 2823 2818 2824 2819 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 2825 2820 info->ext_disp_conn_info.gu_id[i] =
+6 -6
drivers/gpu/drm/amd/display/dc/bios/command_table2.c
··· 123 123 sizeof(cmd.digx_encoder_control.header); 124 124 cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig; 125 125 126 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 126 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 127 127 } 128 128 129 129 static enum bp_result encoder_control_digx_v1_5( ··· 259 259 sizeof(cmd.dig1_transmitter_control.header); 260 260 cmd.dig1_transmitter_control.transmitter_control.dig = *dig; 261 261 262 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 262 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 263 263 } 264 264 265 265 static enum bp_result transmitter_control_v1_6( ··· 321 321 sizeof(cmd.dig1_transmitter_control.header); 322 322 cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig; 323 323 324 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 324 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 325 325 } 326 326 327 327 static enum bp_result transmitter_control_v1_7( ··· 429 429 sizeof(cmd.set_pixel_clock.header); 430 430 cmd.set_pixel_clock.pixel_clock.clk = *clk; 431 431 432 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 432 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 433 433 } 434 434 435 435 static enum bp_result set_pixel_clock_v7( ··· 796 796 sizeof(cmd.enable_disp_power_gating.header); 797 797 cmd.enable_disp_power_gating.power_gating.pwr = *pwr; 798 798 799 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 799 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 800 800 } 801 801 802 802 static enum bp_result enable_disp_power_gating_v2_1( ··· 1006 1006 pwrseq_instance; 1007 1007 cmd.lvtma_control.data.bypass_panel_control_wait = 1008 1008 bypass_panel_control_wait; 1009 - dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 1009 + dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 1010 1010 } 1011 1011 1012 1012 static enum bp_result enable_lvtma_control(
+2 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
··· 29 29 #include "dc_types.h" 30 30 #include "dccg.h" 31 31 #include "clk_mgr_internal.h" 32 + #include "dc_state_priv.h" 32 33 #include "link.h" 33 34 34 35 #include "dce100/dce_clk_mgr.h" ··· 64 63 /* Don't count SubVP phantom pipes as part of active 65 64 * display count 66 65 */ 67 - if (stream->mall_stream_config.type == SUBVP_PHANTOM) 66 + if (dc_state_get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) 68 67 continue; 69 68 70 69 /*
+1 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
··· 253 253 cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 254 254 cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 255 255 256 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 256 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 257 257 } 258 258 259 259 static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
+1 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
··· 284 284 cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 285 285 cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 286 286 287 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 287 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 288 288 } 289 289 290 290 static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
+1 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
··· 232 232 cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 233 233 cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 234 234 235 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 235 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 236 236 } 237 237 238 238 static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+1 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
··· 239 239 cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 240 240 cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 241 241 242 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 242 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 243 243 } 244 244 245 245 static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+80 -10
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
··· 25 25 26 26 #include "dccg.h" 27 27 #include "clk_mgr_internal.h" 28 - 29 28 #include "dcn32/dcn32_clk_mgr_smu_msg.h" 30 29 #include "dcn20/dcn20_clk_mgr.h" 31 30 #include "dce100/dce_clk_mgr.h" ··· 33 34 #include "core_types.h" 34 35 #include "dm_helpers.h" 35 36 #include "link.h" 36 - 37 + #include "dc_state_priv.h" 37 38 #include "atomfirmware.h" 38 39 #include "smu13_driver_if.h" 39 40 ··· 457 458 return 0; 458 459 } 459 460 460 - static void dcn32_auto_dpm_test_log(struct dc_clocks *new_clocks, struct clk_mgr_internal *clk_mgr) 461 + static bool dcn32_check_native_scaling(struct pipe_ctx *pipe) 462 + { 463 + bool is_native_scaling = false; 464 + int width = pipe->plane_state->src_rect.width; 465 + int height = pipe->plane_state->src_rect.height; 466 + 467 + if (pipe->stream->timing.h_addressable == width && 468 + pipe->stream->timing.v_addressable == height && 469 + pipe->plane_state->dst_rect.width == width && 470 + pipe->plane_state->dst_rect.height == height) 471 + is_native_scaling = true; 472 + 473 + return is_native_scaling; 474 + } 475 + 476 + static void dcn32_auto_dpm_test_log( 477 + struct dc_clocks *new_clocks, 478 + struct clk_mgr_internal *clk_mgr, 479 + struct dc_state *context) 461 480 { 462 481 unsigned int dispclk_khz_reg, dppclk_khz_reg, dprefclk_khz_reg, dcfclk_khz_reg, dtbclk_khz_reg, 463 - fclk_khz_reg; 482 + fclk_khz_reg, mall_ss_size_bytes; 464 483 int dramclk_khz_override, fclk_khz_override, num_fclk_levels; 465 484 466 - msleep(5); 485 + struct pipe_ctx *pipe_ctx_list[MAX_PIPES]; 486 + int active_pipe_count = 0; 487 + 488 + for (int i = 0; i < MAX_PIPES; i++) { 489 + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 490 + 491 + if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) { 492 + pipe_ctx_list[active_pipe_count] = pipe_ctx; 493 + active_pipe_count++; 494 + } 495 + } 496 + 497 + mall_ss_size_bytes = context->bw_ctx.bw.dcn.mall_ss_size_bytes; 467 498 468 499 dispclk_khz_reg = REG_READ(CLK1_CLK0_CURRENT_CNT); // DISPCLK 469 500 dppclk_khz_reg = REG_READ(CLK1_CLK1_CURRENT_CNT); // DPPCLK ··· 523 494 // 524 495 // AutoDPMTest: clk1:%d - clk2:%d - clk3:%d - clk4:%d\n" 525 496 //////////////////////////////////////////////////////////////////////////// 526 - if (new_clocks && 497 + if (new_clocks && active_pipe_count > 0 && 527 498 new_clocks->dramclk_khz > 0 && 528 499 new_clocks->fclk_khz > 0 && 529 500 new_clocks->dcfclk_khz > 0 && 530 501 new_clocks->dppclk_khz > 0) { 531 502 503 + uint32_t pix_clk_list[MAX_PIPES] = {0}; 504 + int p_state_list[MAX_PIPES] = {0}; 505 + int disp_src_width_list[MAX_PIPES] = {0}; 506 + int disp_src_height_list[MAX_PIPES] = {0}; 507 + uint64_t disp_src_refresh_list[MAX_PIPES] = {0}; 508 + bool is_scaled_list[MAX_PIPES] = {0}; 509 + 510 + for (int i = 0; i < active_pipe_count; i++) { 511 + struct pipe_ctx *curr_pipe_ctx = pipe_ctx_list[i]; 512 + uint64_t refresh_rate; 513 + 514 + pix_clk_list[i] = curr_pipe_ctx->stream->timing.pix_clk_100hz; 515 + p_state_list[i] = curr_pipe_ctx->p_state_type; 516 + 517 + refresh_rate = (curr_pipe_ctx->stream->timing.pix_clk_100hz * (uint64_t)100 + 518 + curr_pipe_ctx->stream->timing.v_total * curr_pipe_ctx->stream->timing.h_total - (uint64_t)1); 519 + refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.v_total); 520 + refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.h_total); 521 + disp_src_refresh_list[i] = refresh_rate; 522 + 523 + if (curr_pipe_ctx->plane_state) { 524 + is_scaled_list[i] = !(dcn32_check_native_scaling(curr_pipe_ctx)); 525 + disp_src_width_list[i] = curr_pipe_ctx->plane_state->src_rect.width; 526 + disp_src_height_list[i] = curr_pipe_ctx->plane_state->src_rect.height; 527 + } 528 + } 529 + 532 530 DC_LOG_AUTO_DPM_TEST("AutoDPMTest: dramclk:%d - fclk:%d - " 533 531 "dcfclk:%d - dppclk:%d - dispclk_hw:%d - " 534 532 "dppclk_hw:%d - dprefclk_hw:%d - dcfclk_hw:%d - " 535 - "dtbclk_hw:%d - fclk_hw:%d\n", 533 + "dtbclk_hw:%d - fclk_hw:%d - pix_clk_0:%d - pix_clk_1:%d - " 534 + "pix_clk_2:%d - pix_clk_3:%d - mall_ss_size:%d - p_state_type_0:%d - " 535 + "p_state_type_1:%d - p_state_type_2:%d - p_state_type_3:%d - " 536 + "pix_width_0:%d - pix_height_0:%d - refresh_rate_0:%lld - is_scaled_0:%d - " 537 + "pix_width_1:%d - pix_height_1:%d - refresh_rate_1:%lld - is_scaled_1:%d - " 538 + "pix_width_2:%d - pix_height_2:%d - refresh_rate_2:%lld - is_scaled_2:%d - " 539 + "pix_width_3:%d - pix_height_3:%d - refresh_rate_3:%lld - is_scaled_3:%d - LOG_END\n", 536 540 dramclk_khz_override, 537 541 fclk_khz_override, 538 542 new_clocks->dcfclk_khz, ··· 575 513 dprefclk_khz_reg, 576 514 dcfclk_khz_reg, 577 515 dtbclk_khz_reg, 578 - fclk_khz_reg); 516 + fclk_khz_reg, 517 + pix_clk_list[0], pix_clk_list[1], pix_clk_list[3], pix_clk_list[2], 518 + mall_ss_size_bytes, 519 + p_state_list[0], p_state_list[1], p_state_list[2], p_state_list[3], 520 + disp_src_width_list[0], disp_src_height_list[0], disp_src_refresh_list[0], is_scaled_list[0], 521 + disp_src_width_list[1], disp_src_height_list[1], disp_src_refresh_list[1], is_scaled_list[1], 522 + disp_src_width_list[2], disp_src_height_list[2], disp_src_refresh_list[2], is_scaled_list[2], 523 + disp_src_width_list[3], disp_src_height_list[3], disp_src_refresh_list[3], is_scaled_list[3]); 579 524 } 580 525 } 581 526 ··· 755 686 /* DCCG requires KHz precision for DTBCLK */ 756 687 clk_mgr_base->clks.ref_dtbclk_khz = 757 688 dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DTBCLK, khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz)); 689 + 758 690 dcn32_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz); 759 691 } 760 692 ··· 783 713 dmcu->funcs->set_psr_wait_loop(dmcu, 784 714 clk_mgr_base->clks.dispclk_khz / 1000 / 7); 785 715 786 - if (dc->config.enable_auto_dpm_test_logs && safe_to_lower) { 787 - dcn32_auto_dpm_test_log(new_clocks, clk_mgr); 716 + if (dc->config.enable_auto_dpm_test_logs) { 717 + dcn32_auto_dpm_test_log(new_clocks, clk_mgr, context); 788 718 } 789 719 } 790 720
+4 -5
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
··· 50 50 #include "dc_dmub_srv.h" 51 51 #include "link.h" 52 52 #include "logger_types.h" 53 + 53 54 #undef DC_LOGGER 54 55 #define DC_LOGGER \ 55 56 clk_mgr->base.base.ctx->logger ··· 343 342 cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 344 343 cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 345 344 346 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 345 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 347 346 } 348 347 349 348 static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) ··· 418 417 } 419 418 420 419 static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, 421 - struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) 420 + struct clk_mgr_dcn35 *clk_mgr) 422 421 { 423 - 424 422 } 425 423 426 424 static struct clk_bw_params dcn35_bw_params = { ··· 986 986 struct dccg *dccg) 987 987 { 988 988 struct dcn35_smu_dpm_clks smu_dpm_clks = { 0 }; 989 - struct clk_log_info log_info = {0}; 990 989 clk_mgr->base.base.ctx = ctx; 991 990 clk_mgr->base.base.funcs = &dcn35_funcs; 992 991 ··· 1038 1039 dcn35_bw_params.wm_table = ddr5_wm_table; 1039 1040 } 1040 1041 /* Saved clocks configured at boot for debug purposes */ 1041 - dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); 1042 + dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr); 1042 1043 1043 1044 clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base); 1044 1045 clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
+155 -241
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 34 34 #include "dce/dce_hwseq.h" 35 35 36 36 #include "resource.h" 37 + #include "dc_state.h" 38 + #include "dc_state_priv.h" 37 39 38 40 #include "gpio_service_interface.h" 39 41 #include "clk_mgr.h" ··· 411 409 * avoid conflicting with firmware updates. 412 410 */ 413 411 if (dc->ctx->dce_version > DCE_VERSION_MAX) 414 - if (dc->optimized_required || dc->wm_optimized_required) 412 + if (dc->optimized_required) 415 413 return false; 414 + 415 + if (!memcmp(&stream->adjust, adjust, sizeof(*adjust))) 416 + return true; 416 417 417 418 stream->adjust.v_total_max = adjust->v_total_max; 418 419 stream->adjust.v_total_mid = adjust->v_total_mid; ··· 524 519 cmd.secure_display.roi_info.y_end = rect->y + rect->height; 525 520 } 526 521 527 - dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 522 + dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 528 523 } 529 524 530 525 static inline void ··· 813 808 link_enc_cfg_init(dc, dc->current_state); 814 809 815 810 if (dc->current_state) { 816 - dc_release_state(dc->current_state); 811 + dc_state_release(dc->current_state); 817 812 dc->current_state = NULL; 818 813 } 819 814 ··· 1025 1020 } 1026 1021 #endif 1027 1022 1028 - /* Creation of current_state must occur after dc->dml 1029 - * is initialized in dc_create_resource_pool because 1030 - * on creation it copies the contents of dc->dml 1031 - */ 1032 - 1033 - dc->current_state = dc_create_state(dc); 1034 - 1035 - if (!dc->current_state) { 1036 - dm_error("%s: failed to create validate ctx\n", __func__); 1037 - goto fail; 1038 - } 1039 - 1040 1023 if (!create_links(dc, init_params->num_virtual_links)) 1041 1024 goto fail; 1042 1025 ··· 1034 1041 if (!create_link_encoders(dc)) 1035 1042 goto fail; 1036 1043 1037 - dc_resource_state_construct(dc, dc->current_state); 1044 + /* Creation of current_state must occur after dc->dml 1045 + * is initialized in dc_create_resource_pool because 1046 + * on creation it copies the contents of dc->dml 1047 + */ 1048 + 1049 + dc->current_state = dc_state_create(dc); 1050 + 1051 + if (!dc->current_state) { 1052 + dm_error("%s: failed to create validate ctx\n", __func__); 1053 + goto fail; 1054 + } 1038 1055 1039 1056 return true; 1040 1057 ··· 1088 1085 } 1089 1086 } 1090 1087 1091 - static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) 1088 + static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) 1092 1089 { 1093 1090 if (dc->ctx->dce_version >= DCN_VERSION_1_0) { 1094 1091 memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color)); ··· 1108 1105 if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE) 1109 1106 get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1110 1107 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP) 1111 - get_subvp_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1108 + get_subvp_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1112 1109 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) 1113 - get_mclk_switch_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1110 + get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1114 1111 } 1115 1112 } 1116 1113 } ··· 1118 1115 static void disable_dangling_plane(struct dc *dc, struct dc_state *context) 1119 1116 { 1120 1117 int i, j; 1121 - struct dc_state *dangling_context = dc_create_state(dc); 1118 + struct dc_state *dangling_context = dc_state_create_current_copy(dc); 1122 1119 struct dc_state *current_ctx; 1123 1120 struct pipe_ctx *pipe; 1124 1121 struct timing_generator *tg; 1125 1122 1126 1123 if (dangling_context == NULL) 1127 1124 return; 1128 - 1129 - dc_resource_state_copy_construct(dc->current_state, dangling_context); 1130 1125 1131 1126 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1132 1127 struct dc_stream_state *old_stream = ··· 1162 1161 } 1163 1162 1164 1163 if (should_disable && old_stream) { 1164 + bool is_phantom = dc_state_get_stream_subvp_type(dc->current_state, old_stream) == SUBVP_PHANTOM; 1165 1165 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1166 1166 tg = pipe->stream_res.tg; 1167 1167 /* When disabling plane for a phantom pipe, we must turn on the ··· 1171 1169 * state that can result in underflow or hang when enabling it 1172 1170 * again for different use. 1173 1171 */ 1174 - if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { 1172 + if (is_phantom) { 1175 1173 if (tg->funcs->enable_crtc) { 1176 1174 int main_pipe_width, main_pipe_height; 1175 + struct dc_stream_state *old_paired_stream = dc_state_get_paired_subvp_stream(dc->current_state, old_stream); 1177 1176 1178 - main_pipe_width = old_stream->mall_stream_config.paired_stream->dst.width; 1179 - main_pipe_height = old_stream->mall_stream_config.paired_stream->dst.height; 1177 + main_pipe_width = old_paired_stream->dst.width; 1178 + main_pipe_height = old_paired_stream->dst.height; 1180 1179 if (dc->hwss.blank_phantom) 1181 1180 dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height); 1182 1181 tg->funcs->enable_crtc(tg); 1183 1182 } 1184 1183 } 1185 - dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); 1184 + 1185 + if (is_phantom) 1186 + dc_state_rem_all_phantom_planes_for_stream(dc, old_stream, dangling_context, true); 1187 + else 1188 + dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context); 1186 1189 disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); 1187 1190 1188 - if (pipe->stream && pipe->plane_state) 1189 - dc_update_viusal_confirm_color(dc, context, pipe); 1191 + if (pipe->stream && pipe->plane_state) { 1192 + set_p_state_switch_method(dc, context, pipe); 1193 + dc_update_visual_confirm_color(dc, context, pipe); 1194 + } 1190 1195 1191 1196 if (dc->hwss.apply_ctx_for_surface) { 1192 1197 apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true); ··· 1212 1203 * The OTG is set to disable on falling edge of VUPDATE so the plane disable 1213 1204 * will still get it's double buffer update. 1214 1205 */ 1215 - if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { 1206 + if (is_phantom) { 1216 1207 if (tg->funcs->disable_phantom_crtc) 1217 1208 tg->funcs->disable_phantom_crtc(tg); 1218 1209 } ··· 1221 1212 1222 1213 current_ctx = dc->current_state; 1223 1214 dc->current_state = dangling_context; 1224 - dc_release_state(current_ctx); 1215 + dc_state_release(current_ctx); 1225 1216 } 1226 1217 1227 1218 static void disable_vbios_mode_if_required( ··· 1293 1284 int count = 0; 1294 1285 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1295 1286 1296 - if (!pipe->plane_state || pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) 1287 + if (!pipe->plane_state || dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) 1297 1288 continue; 1298 1289 1299 1290 /* Timeout 100 ms */ ··· 1519 1510 } 1520 1511 1521 1512 for (k = 0; k < group_size; k++) { 1522 - struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream); 1513 + struct dc_stream_status *status = dc_state_get_stream_status(ctx, pipe_set[k]->stream); 1523 1514 1524 1515 status->timing_sync_info.group_id = num_group; 1525 1516 status->timing_sync_info.group_size = group_size; ··· 1564 1555 if (group_size > 1) { 1565 1556 if (sync_type == TIMING_SYNCHRONIZABLE) { 1566 1557 dc->hwss.enable_timing_synchronization( 1567 - dc, group_index, group_size, pipe_set); 1558 + dc, ctx, group_index, group_size, pipe_set); 1568 1559 } else 1569 1560 if (sync_type == VBLANK_SYNCHRONIZABLE) { 1570 1561 dc->hwss.enable_vblanks_synchronization( ··· 1846 1837 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1847 1838 1848 1839 /* Check old context for SubVP */ 1849 - subvp_prev_use |= (old_pipe->stream && old_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM); 1840 + subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM); 1850 1841 if (subvp_prev_use) 1851 1842 break; 1852 1843 } ··· 2004 1995 old_state = dc->current_state; 2005 1996 dc->current_state = context; 2006 1997 2007 - dc_release_state(old_state); 1998 + dc_state_release(old_state); 2008 1999 2009 - dc_retain_state(dc->current_state); 2000 + dc_state_retain(dc->current_state); 2010 2001 2011 2002 return result; 2012 2003 } ··· 2077 2068 if (handle_exit_odm2to1) 2078 2069 res = commit_minimal_transition_state(dc, dc->current_state); 2079 2070 2080 - context = dc_create_state(dc); 2071 + context = dc_state_create_current_copy(dc); 2081 2072 if (!context) 2082 2073 goto context_alloc_fail; 2083 - 2084 - dc_resource_state_copy_construct_current(dc, context); 2085 2074 2086 2075 res = dc_validate_with_context(dc, set, stream_count, context, false); 2087 2076 if (res != DC_OK) { ··· 2095 2088 streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; 2096 2089 2097 2090 if (dc_is_embedded_signal(streams[i]->signal)) { 2098 - struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]); 2091 + struct dc_stream_status *status = dc_state_get_stream_status(context, streams[i]); 2099 2092 2100 2093 if (dc->hwss.is_abm_supported) 2101 2094 status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]); ··· 2106 2099 } 2107 2100 2108 2101 fail: 2109 - dc_release_state(context); 2102 + dc_state_release(context); 2110 2103 2111 2104 context_alloc_fail: 2112 2105 ··· 2160 2153 pipe = &context->res_ctx.pipe_ctx[i]; 2161 2154 2162 2155 // Don't check flip pending on phantom pipes 2163 - if (!pipe->plane_state || (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)) 2156 + if (!pipe->plane_state || (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)) 2164 2157 continue; 2165 2158 2166 2159 /* Must set to false to start with, due to OR in update function */ ··· 2218 2211 if (context->res_ctx.pipe_ctx[i].stream == NULL || 2219 2212 context->res_ctx.pipe_ctx[i].plane_state == NULL) { 2220 2213 context->res_ctx.pipe_ctx[i].pipe_idx = i; 2221 - dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); 2214 + dc->hwss.disable_plane(dc, context, &context->res_ctx.pipe_ctx[i]); 2222 2215 } 2223 2216 2224 2217 process_deferred_updates(dc); ··· 2230 2223 } 2231 2224 2232 2225 dc->optimized_required = false; 2233 - dc->wm_optimized_required = false; 2234 - } 2235 - 2236 - static void init_state(struct dc *dc, struct dc_state *context) 2237 - { 2238 - /* Each context must have their own instance of VBA and in order to 2239 - * initialize and obtain IP and SOC the base DML instance from DC is 2240 - * initially copied into every context 2241 - */ 2242 - memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib)); 2243 - } 2244 - 2245 - struct dc_state *dc_create_state(struct dc *dc) 2246 - { 2247 - struct dc_state *context = kvzalloc(sizeof(struct dc_state), 2248 - GFP_KERNEL); 2249 - 2250 - if (!context) 2251 - return NULL; 2252 - 2253 - init_state(dc, context); 2254 - 2255 - #ifdef CONFIG_DRM_AMD_DC_FP 2256 - if (dc->debug.using_dml2) { 2257 - dml2_create(dc, &dc->dml2_options, &context->bw_ctx.dml2); 2258 - } 2259 - #endif 2260 - kref_init(&context->refcount); 2261 - 2262 - return context; 2263 - } 2264 - 2265 - struct dc_state *dc_copy_state(struct dc_state *src_ctx) 2266 - { 2267 - int i, j; 2268 - struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL); 2269 - 2270 - if (!new_ctx) 2271 - return NULL; 2272 - memcpy(new_ctx, src_ctx, sizeof(struct dc_state)); 2273 - 2274 - #ifdef CONFIG_DRM_AMD_DC_FP 2275 - if (new_ctx->bw_ctx.dml2 && !dml2_create_copy(&new_ctx->bw_ctx.dml2, src_ctx->bw_ctx.dml2)) { 2276 - dc_release_state(new_ctx); 2277 - return NULL; 2278 - } 2279 - #endif 2280 - 2281 - for (i = 0; i < MAX_PIPES; i++) { 2282 - struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i]; 2283 - 2284 - if (cur_pipe->top_pipe) 2285 - cur_pipe->top_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 2286 - 2287 - if (cur_pipe->bottom_pipe) 2288 - cur_pipe->bottom_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2289 - 2290 - if (cur_pipe->prev_odm_pipe) 2291 - cur_pipe->prev_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 2292 - 2293 - if (cur_pipe->next_odm_pipe) 2294 - cur_pipe->next_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2295 - 2296 - } 2297 - 2298 - for (i = 0; i < new_ctx->stream_count; i++) { 2299 - dc_stream_retain(new_ctx->streams[i]); 2300 - for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) 2301 - dc_plane_state_retain( 2302 - new_ctx->stream_status[i].plane_states[j]); 2303 - } 2304 - 2305 - kref_init(&new_ctx->refcount); 2306 - 2307 - return new_ctx; 2308 - } 2309 - 2310 - void dc_retain_state(struct dc_state *context) 2311 - { 2312 - kref_get(&context->refcount); 2313 - } 2314 - 2315 - static void dc_state_free(struct kref *kref) 2316 - { 2317 - struct dc_state *context = container_of(kref, struct dc_state, refcount); 2318 - dc_resource_state_destruct(context); 2319 - 2320 - #ifdef CONFIG_DRM_AMD_DC_FP 2321 - dml2_destroy(context->bw_ctx.dml2); 2322 - context->bw_ctx.dml2 = 0; 2323 - #endif 2324 - 2325 - kvfree(context); 2326 - } 2327 - 2328 - void dc_release_state(struct dc_state *context) 2329 - { 2330 - kref_put(&context->refcount, dc_state_free); 2331 2226 } 2332 2227 2333 2228 bool dc_set_generic_gpio_for_stereo(bool enable, ··· 2652 2743 } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) { 2653 2744 dc->optimized_required = true; 2654 2745 } 2655 - 2656 - dc->optimized_required |= dc->wm_optimized_required; 2657 2746 } 2658 2747 2659 2748 return type; ··· 2859 2952 if (update->vrr_active_fixed) 2860 2953 stream->vrr_active_fixed = *update->vrr_active_fixed; 2861 2954 2862 - if (update->crtc_timing_adjust) 2863 - stream->adjust = *update->crtc_timing_adjust; 2864 - 2865 2955 if (update->dpms_off) 2866 2956 stream->dpms_off = *update->dpms_off; 2867 2957 ··· 2899 2995 update->dsc_config->num_slices_v != 0); 2900 2996 2901 2997 /* Use temporarry context for validating new DSC config */ 2902 - struct dc_state *dsc_validate_context = dc_create_state(dc); 2998 + struct dc_state *dsc_validate_context = dc_state_create_copy(dc->current_state); 2903 2999 2904 3000 if (dsc_validate_context) { 2905 - dc_resource_state_copy_construct(dc->current_state, dsc_validate_context); 2906 - 2907 3001 stream->timing.dsc_cfg = *update->dsc_config; 2908 3002 stream->timing.flags.DSC = enable_dsc; 2909 3003 if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) { ··· 2910 3008 update->dsc_config = NULL; 2911 3009 } 2912 3010 2913 - dc_release_state(dsc_validate_context); 3011 + dc_state_release(dsc_validate_context); 2914 3012 } else { 2915 3013 DC_ERROR("Failed to allocate new validate context for DSC change\n"); 2916 3014 update->dsc_config = NULL; ··· 3009 3107 new_planes[i] = srf_updates[i].surface; 3010 3108 3011 3109 /* initialize scratch memory for building context */ 3012 - context = dc_create_state(dc); 3110 + context = dc_state_create_copy(dc->current_state); 3013 3111 if (context == NULL) { 3014 3112 DC_ERROR("Failed to allocate new validate context!\n"); 3015 3113 return false; 3016 3114 } 3017 3115 3018 - dc_resource_state_copy_construct( 3019 - dc->current_state, context); 3020 - 3021 3116 /* For each full update, remove all existing phantom pipes first. 3022 3117 * Ensures that we have enough pipes for newly added MPO planes 3023 3118 */ 3024 - if (dc->res_pool->funcs->remove_phantom_pipes) 3025 - dc->res_pool->funcs->remove_phantom_pipes(dc, context, false); 3119 + dc_state_remove_phantom_streams_and_planes(dc, context); 3120 + dc_state_release_phantom_streams_and_planes(dc, context); 3026 3121 3027 3122 /*remove old surfaces from context */ 3028 - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { 3123 + if (!dc_state_rem_all_planes_for_stream(dc, stream, context)) { 3029 3124 3030 3125 BREAK_TO_DEBUGGER(); 3031 3126 goto fail; 3032 3127 } 3033 3128 3034 3129 /* add surface to context */ 3035 - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { 3130 + if (!dc_state_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { 3036 3131 3037 3132 BREAK_TO_DEBUGGER(); 3038 3133 goto fail; ··· 3054 3155 3055 3156 if (update_type == UPDATE_TYPE_FULL) { 3056 3157 if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { 3057 - /* For phantom pipes we remove and create a new set of phantom pipes 3058 - * for each full update (because we don't know if we'll need phantom 3059 - * pipes until after the first round of validation). However, if validation 3060 - * fails we need to keep the existing phantom pipes (because we don't update 3061 - * the dc->current_state). 3062 - * 3063 - * The phantom stream/plane refcount is decremented for validation because 3064 - * we assume it'll be removed (the free comes when the dc_state is freed), 3065 - * but if validation fails we have to increment back the refcount so it's 3066 - * consistent. 3067 - */ 3068 - if (dc->res_pool->funcs->retain_phantom_pipes) 3069 - dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state); 3070 3158 BREAK_TO_DEBUGGER(); 3071 3159 goto fail; 3072 3160 } ··· 3074 3188 return true; 3075 3189 3076 3190 fail: 3077 - dc_release_state(context); 3191 + dc_state_release(context); 3078 3192 3079 3193 return false; 3080 3194 ··· 3270 3384 3271 3385 update_dirty_rect->panel_inst = panel_inst; 3272 3386 update_dirty_rect->pipe_idx = j; 3273 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 3387 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 3274 3388 } 3275 3389 } 3276 3390 } ··· 3372 3486 { 3373 3487 int i, j; 3374 3488 struct pipe_ctx *top_pipe_to_program = NULL; 3489 + struct dc_stream_status *stream_status = NULL; 3375 3490 dc_z10_restore(dc); 3376 3491 3377 3492 top_pipe_to_program = resource_get_otg_master_for_stream( 3378 3493 &context->res_ctx, 3379 3494 stream); 3380 3495 3381 - if (dc->debug.visual_confirm) { 3382 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3383 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3496 + if (!top_pipe_to_program) 3497 + return; 3384 3498 3385 - if (pipe->stream && pipe->plane_state) 3386 - dc_update_viusal_confirm_color(dc, context, pipe); 3499 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 3500 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3501 + 3502 + if (pipe->stream && pipe->plane_state) { 3503 + set_p_state_switch_method(dc, context, pipe); 3504 + 3505 + if (dc->debug.visual_confirm) 3506 + dc_update_visual_confirm_color(dc, context, pipe); 3387 3507 } 3388 3508 } 3389 3509 ··· 3413 3521 } 3414 3522 } 3415 3523 3524 + stream_status = dc_state_get_stream_status(context, stream); 3525 + 3416 3526 build_dmub_cmd_list(dc, 3417 3527 srf_updates, 3418 3528 surface_count, ··· 3427 3533 context->dmub_cmd_count, 3428 3534 context->block_sequence, 3429 3535 &(context->block_sequence_steps), 3430 - top_pipe_to_program); 3536 + top_pipe_to_program, 3537 + stream_status); 3431 3538 hwss_execute_sequence(dc, 3432 3539 context->block_sequence, 3433 3540 context->block_sequence_steps); ··· 3524 3629 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 3525 3630 3526 3631 // Check old context for SubVP 3527 - subvp_prev_use |= (old_pipe->stream && old_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM); 3632 + subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM); 3528 3633 if (subvp_prev_use) 3529 3634 break; 3530 3635 } ··· 3532 3637 for (i = 0; i < dc->res_pool->pipe_count; i++) { 3533 3638 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3534 3639 3535 - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 3640 + if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 3536 3641 subvp_curr_use = true; 3537 3642 break; 3538 3643 } 3539 3644 } 3540 3645 3541 - if (dc->debug.visual_confirm) 3542 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3543 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3646 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 3647 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3544 3648 3545 - if (pipe->stream && pipe->plane_state) 3546 - dc_update_viusal_confirm_color(dc, context, pipe); 3649 + if (pipe->stream && pipe->plane_state) { 3650 + set_p_state_switch_method(dc, context, pipe); 3651 + 3652 + if (dc->debug.visual_confirm) 3653 + dc_update_visual_confirm_color(dc, context, pipe); 3547 3654 } 3655 + } 3548 3656 3549 3657 if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { 3550 3658 struct pipe_ctx *mpcc_pipe; ··· 3920 4022 for (i = 0; i < dc->res_pool->pipe_count; i++) { 3921 4023 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 3922 4024 3923 - if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) { 4025 + if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) != SUBVP_NONE) { 3924 4026 subvp_active = true; 3925 4027 break; 3926 4028 } ··· 3957 4059 static void release_minimal_transition_state(struct dc *dc, 3958 4060 struct dc_state *context, struct pipe_split_policy_backup *policy) 3959 4061 { 3960 - dc_release_state(context); 4062 + dc_state_release(context); 3961 4063 /* restore previous pipe split and odm policy */ 3962 4064 if (!dc->config.is_vmin_only_asic) 3963 4065 dc->debug.pipe_split_policy = policy->mpc_policy; ··· 3968 4070 static struct dc_state *create_minimal_transition_state(struct dc *dc, 3969 4071 struct dc_state *base_context, struct pipe_split_policy_backup *policy) 3970 4072 { 3971 - struct dc_state *minimal_transition_context = dc_create_state(dc); 4073 + struct dc_state *minimal_transition_context = NULL; 3972 4074 unsigned int i, j; 3973 4075 3974 4076 if (!dc->config.is_vmin_only_asic) { ··· 3980 4082 policy->subvp_policy = dc->debug.force_disable_subvp; 3981 4083 dc->debug.force_disable_subvp = true; 3982 4084 3983 - dc_resource_state_copy_construct(base_context, minimal_transition_context); 4085 + minimal_transition_context = dc_state_create_copy(base_context); 4086 + if (!minimal_transition_context) 4087 + return NULL; 3984 4088 3985 4089 /* commit minimal state */ 3986 4090 if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) { ··· 4014 4114 bool success = false; 4015 4115 struct dc_state *minimal_transition_context; 4016 4116 struct pipe_split_policy_backup policy; 4017 - struct mall_temp_config mall_temp_config; 4018 4117 4019 4118 /* commit based on new context */ 4020 4119 /* Since all phantom pipes are removed in full validation, ··· 4022 4123 * pipe as subvp/phantom will be cleared (dc copy constructor 4023 4124 * creates a shallow copy). 4024 4125 */ 4025 - if (dc->res_pool->funcs->save_mall_state) 4026 - dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config); 4027 4126 minimal_transition_context = create_minimal_transition_state(dc, 4028 4127 context, &policy); 4029 4128 if (minimal_transition_context) { ··· 4034 4137 success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK; 4035 4138 } 4036 4139 release_minimal_transition_state(dc, minimal_transition_context, &policy); 4037 - if (dc->res_pool->funcs->restore_mall_state) 4038 - dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config); 4039 - /* If we do a minimal transition with plane removal and the context 4040 - * has subvp we also have to retain back the phantom stream / planes 4041 - * since the refcount is decremented as part of the min transition 4042 - * (we commit a state with no subvp, so the phantom streams / planes 4043 - * had to be removed). 4044 - */ 4045 - if (dc->res_pool->funcs->retain_phantom_pipes) 4046 - dc->res_pool->funcs->retain_phantom_pipes(dc, context); 4047 4140 } 4048 4141 4049 4142 if (!success) { ··· 4101 4214 for (i = 0; i < dc->res_pool->pipe_count; i++) { 4102 4215 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 4103 4216 4104 - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 4217 + if (pipe->stream && dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) { 4105 4218 subvp_in_use = true; 4106 4219 break; 4107 4220 } ··· 4288 4401 stream_update->mst_bw_update || 4289 4402 stream_update->func_shaper || 4290 4403 stream_update->lut3d_func || 4291 - stream_update->pending_test_pattern || 4292 - stream_update->crtc_timing_adjust)) 4404 + stream_update->pending_test_pattern)) 4293 4405 return true; 4294 4406 4295 4407 if (stream) { ··· 4366 4480 struct dc_state *context; 4367 4481 enum surface_update_type update_type; 4368 4482 int i; 4369 - struct mall_temp_config mall_temp_config; 4370 4483 struct dc_fast_update fast_update[MAX_SURFACES] = {0}; 4371 4484 4372 4485 /* In cases where MPO and split or ODM are used transitions can ··· 4409 4524 * pipe as subvp/phantom will be cleared (dc copy constructor 4410 4525 * creates a shallow copy). 4411 4526 */ 4412 - if (dc->res_pool->funcs->save_mall_state) 4413 - dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config); 4414 4527 if (!commit_minimal_transition_state(dc, context)) { 4415 - dc_release_state(context); 4528 + dc_state_release(context); 4416 4529 return false; 4417 4530 } 4418 - if (dc->res_pool->funcs->restore_mall_state) 4419 - dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config); 4420 - 4421 - /* If we do a minimal transition with plane removal and the context 4422 - * has subvp we also have to retain back the phantom stream / planes 4423 - * since the refcount is decremented as part of the min transition 4424 - * (we commit a state with no subvp, so the phantom streams / planes 4425 - * had to be removed). 4426 - */ 4427 - if (dc->res_pool->funcs->retain_phantom_pipes) 4428 - dc->res_pool->funcs->retain_phantom_pipes(dc, context); 4429 4531 update_type = UPDATE_TYPE_FULL; 4430 4532 } 4431 4533 ··· 4469 4597 struct dc_state *old = dc->current_state; 4470 4598 4471 4599 dc->current_state = context; 4472 - dc_release_state(old); 4600 + dc_state_release(old); 4473 4601 4474 4602 // clear any forced full updates 4475 4603 for (i = 0; i < dc->res_pool->pipe_count; i++) { ··· 4528 4656 if (update_type >= UPDATE_TYPE_FULL) { 4529 4657 4530 4658 /* initialize scratch memory for building context */ 4531 - context = dc_create_state(dc); 4659 + context = dc_state_create_copy(state); 4532 4660 if (context == NULL) { 4533 4661 DC_ERROR("Failed to allocate new validate context!\n"); 4534 4662 return; 4535 4663 } 4536 - 4537 - dc_resource_state_copy_construct(state, context); 4538 4664 4539 4665 for (i = 0; i < dc->res_pool->pipe_count; i++) { 4540 4666 struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; ··· 4572 4702 if (update_type >= UPDATE_TYPE_FULL) { 4573 4703 if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { 4574 4704 DC_ERROR("Mode validation failed for stream update!\n"); 4575 - dc_release_state(context); 4705 + dc_state_release(context); 4576 4706 return; 4577 4707 } 4578 4708 } ··· 4605 4735 struct dc_state *old = dc->current_state; 4606 4736 4607 4737 dc->current_state = context; 4608 - dc_release_state(old); 4738 + dc_state_release(old); 4609 4739 4610 4740 for (i = 0; i < dc->res_pool->pipe_count; i++) { 4611 4741 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ··· 4678 4808 4679 4809 switch (power_state) { 4680 4810 case DC_ACPI_CM_POWER_STATE_D0: 4681 - dc_resource_state_construct(dc, dc->current_state); 4811 + dc_state_construct(dc, dc->current_state); 4682 4812 4683 4813 dc_z10_restore(dc); 4684 4814 ··· 4693 4823 default: 4694 4824 ASSERT(dc->current_state->stream_count == 0); 4695 4825 4696 - dc_resource_state_destruct(dc->current_state); 4826 + dc_state_destruct(dc->current_state); 4697 4827 4698 4828 break; 4699 4829 } ··· 4762 4892 } else if (!enable && link->psr_settings.psr_allow_active) { 4763 4893 allow_active = false; 4764 4894 if (!dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL)) 4895 + return false; 4896 + } 4897 + } 4898 + } 4899 + 4900 + return true; 4901 + } 4902 + 4903 + /* enable/disable eDP Replay without specify stream for eDP */ 4904 + bool dc_set_replay_allow_active(struct dc *dc, bool active) 4905 + { 4906 + int i; 4907 + bool allow_active; 4908 + 4909 + for (i = 0; i < dc->current_state->stream_count; i++) { 4910 + struct dc_link *link; 4911 + struct dc_stream_state *stream = dc->current_state->streams[i]; 4912 + 4913 + link = stream->link; 4914 + if (!link) 4915 + continue; 4916 + 4917 + if (link->replay_settings.replay_feature_enabled) { 4918 + if (active && !link->replay_settings.replay_allow_active) { 4919 + allow_active = true; 4920 + if (!dc_link_set_replay_allow_active(link, &allow_active, 4921 + false, false, NULL)) 4922 + return false; 4923 + } else if (!active && link->replay_settings.replay_allow_active) { 4924 + allow_active = false; 4925 + if (!dc_link_set_replay_allow_active(link, &allow_active, 4926 + true, false, NULL)) 4765 4927 return false; 4766 4928 } 4767 4929 } ··· 4995 5093 */ 4996 5094 bool dc_is_dmub_outbox_supported(struct dc *dc) 4997 5095 { 4998 - /* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */ 4999 - if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP && 5000 - dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 && 5001 - !dc->debug.dpia_debug.bits.disable_dpia) 5002 - return true; 5096 + switch (dc->ctx->asic_id.chip_family) { 5003 5097 5004 - if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1 && 5005 - !dc->debug.dpia_debug.bits.disable_dpia) 5006 - return true; 5098 + case FAMILY_YELLOW_CARP: 5099 + /* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */ 5100 + if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 && 5101 + !dc->debug.dpia_debug.bits.disable_dpia) 5102 + return true; 5103 + break; 5104 + 5105 + case AMDGPU_FAMILY_GC_11_0_1: 5106 + case AMDGPU_FAMILY_GC_11_5_0: 5107 + if (!dc->debug.dpia_debug.bits.disable_dpia) 5108 + return true; 5109 + break; 5110 + 5111 + default: 5112 + break; 5113 + } 5007 5114 5008 5115 /* dmub aux needs dmub notifications to be enabled */ 5009 5116 return dc->debug.enable_dmub_aux_for_legacy_ddc; 5117 + 5010 5118 } 5011 5119 5012 5120 /** ··· 5113 5201 ); 5114 5202 } 5115 5203 5116 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 5204 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 5117 5205 5118 5206 return true; 5119 5207 } ··· 5167 5255 cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type; 5168 5256 cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data; 5169 5257 5170 - if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { 5258 + if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { 5171 5259 /* command is not processed by dmub */ 5172 5260 notify->sc_status = SET_CONFIG_UNKNOWN_ERROR; 5173 5261 return is_cmd_complete; ··· 5210 5298 cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst; 5211 5299 cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots; 5212 5300 5213 - if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 5301 + if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 5214 5302 /* command is not processed by dmub */ 5215 5303 return DC_ERROR_UNEXPECTED; 5216 5304 ··· 5248 5336 cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE; 5249 5337 cmd.dpia_hpd_int_enable.enable = hpd_int_enable; 5250 5338 5251 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 5339 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 5252 5340 5253 5341 DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable); 5254 5342 } ··· 5347 5435 struct dc_link *link = stream->sink->link; 5348 5436 struct dc_link *edp_links[MAX_NUM_EDP]; 5349 5437 5438 + if (link->replay_settings.replay_feature_enabled) 5439 + return false; 5350 5440 5351 5441 /*find primary pipe associated with stream*/ 5352 5442 for (i = 0; i < MAX_PIPES; i++) {
+122 -69
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
··· 31 31 #include "basics/dc_common.h" 32 32 #include "resource.h" 33 33 #include "dc_dmub_srv.h" 34 + #include "dc_state_priv.h" 34 35 35 36 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) 36 37 ··· 426 425 } 427 426 428 427 void get_subvp_visual_confirm_color( 429 - struct dc *dc, 430 - struct dc_state *context, 431 428 struct pipe_ctx *pipe_ctx, 432 429 struct tg_color *color) 433 430 { 434 431 uint32_t color_value = MAX_TG_COLOR_VALUE; 435 - bool enable_subvp = false; 436 - int i; 437 - 438 - if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context) 439 - return; 440 - 441 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 442 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 443 - 444 - if (pipe->stream && pipe->stream->mall_stream_config.paired_stream && 445 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 446 - /* SubVP enable - red */ 447 - color->color_g_y = 0; 448 - color->color_b_cb = 0; 432 + if (pipe_ctx) { 433 + switch (pipe_ctx->p_state_type) { 434 + case P_STATE_SUB_VP: 449 435 color->color_r_cr = color_value; 450 - enable_subvp = true; 451 - 452 - if (pipe_ctx->stream == pipe->stream) 453 - return; 436 + color->color_g_y = 0; 437 + color->color_b_cb = 0; 438 + break; 439 + case P_STATE_DRR_SUB_VP: 440 + color->color_r_cr = 0; 441 + color->color_g_y = color_value; 442 + color->color_b_cb = 0; 443 + break; 444 + case P_STATE_V_BLANK_SUB_VP: 445 + color->color_r_cr = 0; 446 + color->color_g_y = 0; 447 + color->color_b_cb = color_value; 448 + break; 449 + default: 454 450 break; 455 451 } 456 452 } 453 + } 457 454 458 - if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) { 459 - color->color_r_cr = 0; 460 - if (pipe_ctx->stream->allow_freesync == 1) { 461 - /* SubVP enable and DRR on - green */ 462 - color->color_b_cb = 0; 455 + void get_mclk_switch_visual_confirm_color( 456 + struct pipe_ctx *pipe_ctx, 457 + struct tg_color *color) 458 + { 459 + uint32_t color_value = MAX_TG_COLOR_VALUE; 460 + 461 + if (pipe_ctx) { 462 + switch (pipe_ctx->p_state_type) { 463 + case P_STATE_V_BLANK: 464 + color->color_r_cr = color_value; 463 465 color->color_g_y = color_value; 464 - } else { 465 - /* SubVP enable and No DRR - blue */ 466 - color->color_g_y = 0; 466 + color->color_b_cb = 0; 467 + break; 468 + case P_STATE_FPO: 469 + color->color_r_cr = 0; 470 + color->color_g_y = color_value; 467 471 color->color_b_cb = color_value; 472 + break; 473 + case P_STATE_V_ACTIVE: 474 + color->color_r_cr = color_value; 475 + color->color_g_y = 0; 476 + color->color_b_cb = color_value; 477 + break; 478 + case P_STATE_SUB_VP: 479 + color->color_r_cr = color_value; 480 + color->color_g_y = 0; 481 + color->color_b_cb = 0; 482 + break; 483 + case P_STATE_DRR_SUB_VP: 484 + color->color_r_cr = 0; 485 + color->color_g_y = color_value; 486 + color->color_b_cb = 0; 487 + break; 488 + case P_STATE_V_BLANK_SUB_VP: 489 + color->color_r_cr = 0; 490 + color->color_g_y = 0; 491 + color->color_b_cb = color_value; 492 + break; 493 + default: 494 + break; 495 + } 496 + } 497 + } 498 + 499 + void set_p_state_switch_method( 500 + struct dc *dc, 501 + struct dc_state *context, 502 + struct pipe_ctx *pipe_ctx) 503 + { 504 + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; 505 + bool enable_subvp; 506 + 507 + if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context) 508 + return; 509 + 510 + if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] != 511 + dm_dram_clock_change_unsupported) { 512 + /* MCLK switching is supported */ 513 + if (!pipe_ctx->has_vactive_margin) { 514 + /* In Vblank - yellow */ 515 + pipe_ctx->p_state_type = P_STATE_V_BLANK; 516 + 517 + if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) { 518 + /* FPO + Vblank - cyan */ 519 + pipe_ctx->p_state_type = P_STATE_FPO; 520 + } 521 + } else { 522 + /* In Vactive - pink */ 523 + pipe_ctx->p_state_type = P_STATE_V_ACTIVE; 524 + } 525 + 526 + /* SubVP */ 527 + enable_subvp = false; 528 + 529 + for (int i = 0; i < dc->res_pool->pipe_count; i++) { 530 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 531 + 532 + if (pipe->stream && dc_state_get_paired_subvp_stream(context, pipe->stream) && 533 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { 534 + /* SubVP enable - red */ 535 + pipe_ctx->p_state_type = P_STATE_SUB_VP; 536 + enable_subvp = true; 537 + 538 + if (pipe_ctx->stream == pipe->stream) 539 + return; 540 + break; 541 + } 542 + } 543 + 544 + if (enable_subvp && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_NONE) { 545 + if (pipe_ctx->stream->allow_freesync == 1) { 546 + /* SubVP enable and DRR on - green */ 547 + pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP; 548 + } else { 549 + /* SubVP enable and No DRR - blue */ 550 + pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP; 551 + } 468 552 } 469 553 } 470 554 } ··· 559 473 unsigned int dmub_cmd_count, 560 474 struct block_sequence block_sequence[], 561 475 int *num_steps, 562 - struct pipe_ctx *pipe_ctx) 476 + struct pipe_ctx *pipe_ctx, 477 + struct dc_stream_status *stream_status) 563 478 { 564 479 struct dc_plane_state *plane = pipe_ctx->plane_state; 565 480 struct dc_stream_state *stream = pipe_ctx->stream; ··· 577 490 if (dc->hwss.subvp_pipe_control_lock_fast) { 578 491 block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc; 579 492 block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true; 580 - block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx; 493 + block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip = 494 + plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN; 581 495 block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST; 582 496 (*num_steps)++; 583 497 } ··· 617 529 } 618 530 if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) { 619 531 if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) && 620 - current_mpc_pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 532 + stream_status->mall_stream_config.type == SUBVP_MAIN) { 621 533 block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv; 622 534 block_sequence[*num_steps].params.subvp_save_surf_addr.addr = &current_mpc_pipe->plane_state->address; 623 535 block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index; ··· 700 612 if (dc->hwss.subvp_pipe_control_lock_fast) { 701 613 block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc; 702 614 block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false; 703 - block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx; 615 + block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip = 616 + plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN; 704 617 block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST; 705 618 (*num_steps)++; 706 619 } ··· 813 724 union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd; 814 725 enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type; 815 726 816 - dm_execute_dmub_cmd(ctx, cmd, wait_type); 727 + dc_wake_and_execute_dmub_cmd(ctx, cmd, wait_type); 817 728 } 818 729 819 730 void hwss_program_manual_trigger(union block_sequence_params *params) ··· 899 810 uint8_t subvp_index = params->subvp_save_surf_addr.subvp_index; 900 811 901 812 dc_dmub_srv_subvp_save_surf_addr(dc_dmub_srv, addr, subvp_index); 902 - } 903 - 904 - void get_mclk_switch_visual_confirm_color( 905 - struct dc *dc, 906 - struct dc_state *context, 907 - struct pipe_ctx *pipe_ctx, 908 - struct tg_color *color) 909 - { 910 - uint32_t color_value = MAX_TG_COLOR_VALUE; 911 - struct vba_vars_st *vba = &context->bw_ctx.dml.vba; 912 - 913 - if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context) 914 - return; 915 - 916 - if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] != 917 - dm_dram_clock_change_unsupported) { 918 - /* MCLK switching is supported */ 919 - if (!pipe_ctx->has_vactive_margin) { 920 - /* In Vblank - yellow */ 921 - color->color_r_cr = color_value; 922 - color->color_g_y = color_value; 923 - 924 - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) { 925 - /* FPO + Vblank - cyan */ 926 - color->color_r_cr = 0; 927 - color->color_g_y = color_value; 928 - color->color_b_cb = color_value; 929 - } 930 - } else { 931 - /* In Vactive - pink */ 932 - color->color_r_cr = color_value; 933 - color->color_b_cb = color_value; 934 - } 935 - /* SubVP */ 936 - get_subvp_visual_confirm_color(dc, context, pipe_ctx, color); 937 - } 938 813 } 939 814 940 815 void get_surface_tile_visual_confirm_color(
+62 -373
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 42 42 #include "link_enc_cfg.h" 43 43 #include "link.h" 44 44 #include "clk_mgr.h" 45 + #include "dc_state_priv.h" 45 46 #include "virtual/virtual_link_hwss.h" 46 47 #include "link/hwss/link_hwss_dio.h" 47 48 #include "link/hwss/link_hwss_dpia.h" ··· 2460 2459 struct pipe_ctx *otg_master = resource_get_otg_master_for_stream( 2461 2460 &context->res_ctx, stream); 2462 2461 2462 + if (!otg_master) 2463 + return; 2464 + 2463 2465 ASSERT(resource_get_odm_slice_count(otg_master) == 1); 2464 2466 ASSERT(otg_master->plane_state == NULL); 2465 2467 ASSERT(otg_master->stream_res.stream_enc); ··· 2997 2993 return result; 2998 2994 } 2999 2995 3000 - bool dc_add_plane_to_context( 3001 - const struct dc *dc, 3002 - struct dc_stream_state *stream, 3003 - struct dc_plane_state *plane_state, 3004 - struct dc_state *context) 3005 - { 3006 - struct resource_pool *pool = dc->res_pool; 3007 - struct pipe_ctx *otg_master_pipe; 3008 - struct dc_stream_status *stream_status = NULL; 3009 - bool added = false; 3010 - 3011 - stream_status = dc_stream_get_status_from_state(context, stream); 3012 - if (stream_status == NULL) { 3013 - dm_error("Existing stream not found; failed to attach surface!\n"); 3014 - goto out; 3015 - } else if (stream_status->plane_count == MAX_SURFACE_NUM) { 3016 - dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 3017 - plane_state, MAX_SURFACE_NUM); 3018 - goto out; 3019 - } 3020 - 3021 - otg_master_pipe = resource_get_otg_master_for_stream( 3022 - &context->res_ctx, stream); 3023 - added = resource_append_dpp_pipes_for_plane_composition(context, 3024 - dc->current_state, pool, otg_master_pipe, plane_state); 3025 - 3026 - if (added) { 3027 - stream_status->plane_states[stream_status->plane_count] = 3028 - plane_state; 3029 - stream_status->plane_count++; 3030 - dc_plane_state_retain(plane_state); 3031 - } 3032 - 3033 - out: 3034 - return added; 3035 - } 3036 - 3037 - bool dc_remove_plane_from_context( 3038 - const struct dc *dc, 3039 - struct dc_stream_state *stream, 3040 - struct dc_plane_state *plane_state, 3041 - struct dc_state *context) 3042 - { 3043 - int i; 3044 - struct dc_stream_status *stream_status = NULL; 3045 - struct resource_pool *pool = dc->res_pool; 3046 - 3047 - if (!plane_state) 3048 - return true; 3049 - 3050 - for (i = 0; i < context->stream_count; i++) 3051 - if (context->streams[i] == stream) { 3052 - stream_status = &context->stream_status[i]; 3053 - break; 3054 - } 3055 - 3056 - if (stream_status == NULL) { 3057 - dm_error("Existing stream not found; failed to remove plane.\n"); 3058 - return false; 3059 - } 3060 - 3061 - resource_remove_dpp_pipes_for_plane_composition( 3062 - context, pool, plane_state); 3063 - 3064 - for (i = 0; i < stream_status->plane_count; i++) { 3065 - if (stream_status->plane_states[i] == plane_state) { 3066 - dc_plane_state_release(stream_status->plane_states[i]); 3067 - break; 3068 - } 3069 - } 3070 - 3071 - if (i == stream_status->plane_count) { 3072 - dm_error("Existing plane_state not found; failed to detach it!\n"); 3073 - return false; 3074 - } 3075 - 3076 - stream_status->plane_count--; 3077 - 3078 - /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 3079 - for (; i < stream_status->plane_count; i++) 3080 - stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 3081 - 3082 - stream_status->plane_states[stream_status->plane_count] = NULL; 3083 - 3084 - if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm) 3085 - /* ODM combine could prevent us from supporting more planes 3086 - * we will reset ODM slice count back to 1 when all planes have 3087 - * been removed to maximize the amount of planes supported when 3088 - * new planes are added. 3089 - */ 3090 - resource_update_pipes_for_stream_with_slice_count( 3091 - context, dc->current_state, dc->res_pool, stream, 1); 3092 - 3093 - return true; 3094 - } 3095 - 3096 - /** 3097 - * dc_rem_all_planes_for_stream - Remove planes attached to the target stream. 3098 - * 3099 - * @dc: Current dc state. 3100 - * @stream: Target stream, which we want to remove the attached plans. 3101 - * @context: New context. 3102 - * 3103 - * Return: 3104 - * Return true if DC was able to remove all planes from the target 3105 - * stream, otherwise, return false. 3106 - */ 3107 - bool dc_rem_all_planes_for_stream( 3108 - const struct dc *dc, 3109 - struct dc_stream_state *stream, 3110 - struct dc_state *context) 3111 - { 3112 - int i, old_plane_count; 3113 - struct dc_stream_status *stream_status = NULL; 3114 - struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 3115 - 3116 - for (i = 0; i < context->stream_count; i++) 3117 - if (context->streams[i] == stream) { 3118 - stream_status = &context->stream_status[i]; 3119 - break; 3120 - } 3121 - 3122 - if (stream_status == NULL) { 3123 - dm_error("Existing stream %p not found!\n", stream); 3124 - return false; 3125 - } 3126 - 3127 - old_plane_count = stream_status->plane_count; 3128 - 3129 - for (i = 0; i < old_plane_count; i++) 3130 - del_planes[i] = stream_status->plane_states[i]; 3131 - 3132 - for (i = 0; i < old_plane_count; i++) 3133 - if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 3134 - return false; 3135 - 3136 - return true; 3137 - } 3138 - 3139 - static bool add_all_planes_for_stream( 3140 - const struct dc *dc, 3141 - struct dc_stream_state *stream, 3142 - const struct dc_validation_set set[], 3143 - int set_count, 3144 - struct dc_state *context) 3145 - { 3146 - int i, j; 3147 - 3148 - for (i = 0; i < set_count; i++) 3149 - if (set[i].stream == stream) 3150 - break; 3151 - 3152 - if (i == set_count) { 3153 - dm_error("Stream %p not found in set!\n", stream); 3154 - return false; 3155 - } 3156 - 3157 - for (j = 0; j < set[i].plane_count; j++) 3158 - if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 3159 - return false; 3160 - 3161 - return true; 3162 - } 3163 - 3164 - bool dc_add_all_planes_for_stream( 3165 - const struct dc *dc, 3166 - struct dc_stream_state *stream, 3167 - struct dc_plane_state * const *plane_states, 3168 - int plane_count, 3169 - struct dc_state *context) 3170 - { 3171 - struct dc_validation_set set; 3172 - int i; 3173 - 3174 - set.stream = stream; 3175 - set.plane_count = plane_count; 3176 - 3177 - for (i = 0; i < plane_count; i++) 3178 - set.plane_states[i] = plane_states[i]; 3179 - 3180 - return add_all_planes_for_stream(dc, stream, &set, 1, context); 3181 - } 3182 - 3183 2996 bool dc_is_timing_changed(struct dc_stream_state *cur_stream, 3184 2997 struct dc_stream_state *new_stream) 3185 2998 { ··· 3146 3325 } 3147 3326 } 3148 3327 return NULL; 3149 - } 3150 - 3151 - /* 3152 - * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 3153 - */ 3154 - enum dc_status dc_add_stream_to_ctx( 3155 - struct dc *dc, 3156 - struct dc_state *new_ctx, 3157 - struct dc_stream_state *stream) 3158 - { 3159 - enum dc_status res; 3160 - DC_LOGGER_INIT(dc->ctx->logger); 3161 - 3162 - if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 3163 - DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 3164 - return DC_ERROR_UNEXPECTED; 3165 - } 3166 - 3167 - new_ctx->streams[new_ctx->stream_count] = stream; 3168 - dc_stream_retain(stream); 3169 - new_ctx->stream_count++; 3170 - 3171 - res = resource_add_otg_master_for_stream_output( 3172 - new_ctx, dc->res_pool, stream); 3173 - if (res != DC_OK) 3174 - DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 3175 - 3176 - return res; 3177 - } 3178 - 3179 - /* 3180 - * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 3181 - */ 3182 - enum dc_status dc_remove_stream_from_ctx( 3183 - struct dc *dc, 3184 - struct dc_state *new_ctx, 3185 - struct dc_stream_state *stream) 3186 - { 3187 - int i; 3188 - struct dc_context *dc_ctx = dc->ctx; 3189 - struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream( 3190 - &new_ctx->res_ctx, stream); 3191 - 3192 - if (!del_pipe) { 3193 - DC_ERROR("Pipe not found for stream %p !\n", stream); 3194 - return DC_ERROR_UNEXPECTED; 3195 - } 3196 - 3197 - resource_update_pipes_for_stream_with_slice_count(new_ctx, 3198 - dc->current_state, dc->res_pool, stream, 1); 3199 - resource_remove_otg_master_for_stream_output( 3200 - new_ctx, dc->res_pool, stream); 3201 - 3202 - for (i = 0; i < new_ctx->stream_count; i++) 3203 - if (new_ctx->streams[i] == stream) 3204 - break; 3205 - 3206 - if (new_ctx->streams[i] != stream) { 3207 - DC_ERROR("Context doesn't have stream %p !\n", stream); 3208 - return DC_ERROR_UNEXPECTED; 3209 - } 3210 - 3211 - dc_stream_release(new_ctx->streams[i]); 3212 - new_ctx->stream_count--; 3213 - 3214 - /* Trim back arrays */ 3215 - for (; i < new_ctx->stream_count; i++) { 3216 - new_ctx->streams[i] = new_ctx->streams[i + 1]; 3217 - new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 3218 - } 3219 - 3220 - new_ctx->streams[new_ctx->stream_count] = NULL; 3221 - memset( 3222 - &new_ctx->stream_status[new_ctx->stream_count], 3223 - 0, 3224 - sizeof(new_ctx->stream_status[0])); 3225 - 3226 - return DC_OK; 3227 3328 } 3228 3329 3229 3330 static struct dc_stream_state *find_pll_sharable_stream( ··· 3527 3784 return DC_ERROR_UNEXPECTED; 3528 3785 } 3529 3786 3530 - /** 3531 - * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 3532 - * 3533 - * @dc: copy out of dc->current_state 3534 - * @dst_ctx: copy into this 3535 - * 3536 - * This function makes a shallow copy of the current DC state and increments 3537 - * refcounts on existing streams and planes. 3538 - */ 3539 - void dc_resource_state_copy_construct_current( 3540 - const struct dc *dc, 3541 - struct dc_state *dst_ctx) 3542 - { 3543 - dc_resource_state_copy_construct(dc->current_state, dst_ctx); 3544 - } 3545 - 3546 - 3547 - void dc_resource_state_construct( 3548 - const struct dc *dc, 3549 - struct dc_state *dst_ctx) 3550 - { 3551 - dst_ctx->clk_mgr = dc->clk_mgr; 3552 - 3553 - /* Initialise DIG link encoder resource tracking variables. */ 3554 - link_enc_cfg_init(dc, dst_ctx); 3555 - } 3556 - 3557 - 3558 3787 bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 3559 3788 { 3560 3789 if (dc->res_pool == NULL) ··· 3568 3853 return true; 3569 3854 3570 3855 return false; 3856 + } 3857 + 3858 + static bool add_all_planes_for_stream( 3859 + const struct dc *dc, 3860 + struct dc_stream_state *stream, 3861 + const struct dc_validation_set set[], 3862 + int set_count, 3863 + struct dc_state *state) 3864 + { 3865 + int i, j; 3866 + 3867 + for (i = 0; i < set_count; i++) 3868 + if (set[i].stream == stream) 3869 + break; 3870 + 3871 + if (i == set_count) { 3872 + dm_error("Stream %p not found in set!\n", stream); 3873 + return false; 3874 + } 3875 + 3876 + for (j = 0; j < set[i].plane_count; j++) 3877 + if (!dc_state_add_plane(dc, stream, set[i].plane_states[j], state)) 3878 + return false; 3879 + 3880 + return true; 3571 3881 } 3572 3882 3573 3883 /** ··· 3700 3960 unchanged_streams[i], 3701 3961 set, 3702 3962 set_count)) { 3703 - if (!dc_rem_all_planes_for_stream(dc, 3963 + 3964 + if (!dc_state_rem_all_planes_for_stream(dc, 3704 3965 unchanged_streams[i], 3705 3966 context)) { 3706 3967 res = DC_FAIL_DETACH_SURFACES; ··· 3723 3982 } 3724 3983 } 3725 3984 3726 - if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) { 3727 - res = DC_FAIL_DETACH_SURFACES; 3728 - goto fail; 3985 + if (dc_state_get_stream_subvp_type(context, del_streams[i]) == SUBVP_PHANTOM) { 3986 + /* remove phantoms specifically */ 3987 + if (!dc_state_rem_all_phantom_planes_for_stream(dc, del_streams[i], context, true)) { 3988 + res = DC_FAIL_DETACH_SURFACES; 3989 + goto fail; 3990 + } 3991 + 3992 + res = dc_state_remove_phantom_stream(dc, context, del_streams[i]); 3993 + dc_state_release_phantom_stream(dc, context, del_streams[i]); 3994 + } else { 3995 + if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) { 3996 + res = DC_FAIL_DETACH_SURFACES; 3997 + goto fail; 3998 + } 3999 + 4000 + res = dc_state_remove_stream(dc, context, del_streams[i]); 3729 4001 } 3730 4002 3731 - res = dc_remove_stream_from_ctx(dc, context, del_streams[i]); 3732 4003 if (res != DC_OK) 3733 4004 goto fail; 3734 4005 } ··· 3763 4010 /* Add new streams and then add all planes for the new stream */ 3764 4011 for (i = 0; i < add_streams_count; i++) { 3765 4012 calculate_phy_pix_clks(add_streams[i]); 3766 - res = dc_add_stream_to_ctx(dc, context, add_streams[i]); 4013 + res = dc_state_add_stream(dc, context, add_streams[i]); 3767 4014 if (res != DC_OK) 3768 4015 goto fail; 3769 4016 ··· 4267 4514 return; 4268 4515 4269 4516 *info_packet = stream->vtem_infopacket; 4270 - } 4271 - 4272 - void dc_resource_state_destruct(struct dc_state *context) 4273 - { 4274 - int i, j; 4275 - 4276 - for (i = 0; i < context->stream_count; i++) { 4277 - for (j = 0; j < context->stream_status[i].plane_count; j++) 4278 - dc_plane_state_release( 4279 - context->stream_status[i].plane_states[j]); 4280 - 4281 - context->stream_status[i].plane_count = 0; 4282 - dc_stream_release(context->streams[i]); 4283 - context->streams[i] = NULL; 4284 - } 4285 - context->stream_count = 0; 4286 - context->stream_mask = 0; 4287 - memset(&context->res_ctx, 0, sizeof(context->res_ctx)); 4288 - memset(&context->pp_display_cfg, 0, sizeof(context->pp_display_cfg)); 4289 - memset(&context->dcn_bw_vars, 0, sizeof(context->dcn_bw_vars)); 4290 - context->clk_mgr = NULL; 4291 - memset(&context->bw_ctx.bw, 0, sizeof(context->bw_ctx.bw)); 4292 - memset(context->block_sequence, 0, sizeof(context->block_sequence)); 4293 - context->block_sequence_steps = 0; 4294 - memset(context->dc_dmub_cmd, 0, sizeof(context->dc_dmub_cmd)); 4295 - context->dmub_cmd_count = 0; 4296 - memset(&context->perf_params, 0, sizeof(context->perf_params)); 4297 - memset(&context->scratch, 0, sizeof(context->scratch)); 4298 - } 4299 - 4300 - void dc_resource_state_copy_construct( 4301 - const struct dc_state *src_ctx, 4302 - struct dc_state *dst_ctx) 4303 - { 4304 - int i, j; 4305 - struct kref refcount = dst_ctx->refcount; 4306 - #ifdef CONFIG_DRM_AMD_DC_FP 4307 - struct dml2_context *dml2 = NULL; 4308 - 4309 - // Need to preserve allocated dml2 context 4310 - if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2) 4311 - dml2 = dst_ctx->bw_ctx.dml2; 4312 - #endif 4313 - 4314 - *dst_ctx = *src_ctx; 4315 - 4316 - #ifdef CONFIG_DRM_AMD_DC_FP 4317 - // Preserve allocated dml2 context 4318 - if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2) 4319 - dst_ctx->bw_ctx.dml2 = dml2; 4320 - #endif 4321 - 4322 - for (i = 0; i < MAX_PIPES; i++) { 4323 - struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 4324 - 4325 - if (cur_pipe->top_pipe) 4326 - cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 4327 - 4328 - if (cur_pipe->bottom_pipe) 4329 - cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 4330 - 4331 - if (cur_pipe->next_odm_pipe) 4332 - cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 4333 - 4334 - if (cur_pipe->prev_odm_pipe) 4335 - cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 4336 - } 4337 - 4338 - for (i = 0; i < dst_ctx->stream_count; i++) { 4339 - dc_stream_retain(dst_ctx->streams[i]); 4340 - for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 4341 - dc_plane_state_retain( 4342 - dst_ctx->stream_status[i].plane_states[j]); 4343 - } 4344 - 4345 - /* context refcount should not be overridden */ 4346 - dst_ctx->refcount = refcount; 4347 - 4348 4517 } 4349 4518 4350 4519 struct clock_source *dc_resource_find_first_free_pll( ··· 4984 5309 } 4985 5310 4986 5311 return DC_OK; 5312 + } 5313 + 5314 + bool resource_subvp_in_use(struct dc *dc, 5315 + struct dc_state *context) 5316 + { 5317 + uint32_t i; 5318 + 5319 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 5320 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 5321 + 5322 + if (dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_NONE) 5323 + return true; 5324 + } 5325 + return false; 4987 5326 } 4988 5327 4989 5328 bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream)
+865
drivers/gpu/drm/amd/display/dc/core/dc_state.c
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + #include "core_types.h" 26 + #include "core_status.h" 27 + #include "dc_state.h" 28 + #include "dc_state_priv.h" 29 + #include "dc_stream_priv.h" 30 + #include "dc_plane_priv.h" 31 + 32 + #include "dm_services.h" 33 + #include "resource.h" 34 + #include "link_enc_cfg.h" 35 + 36 + #include "dml2/dml2_wrapper.h" 37 + #include "dml2/dml2_internal_types.h" 38 + 39 + #define DC_LOGGER \ 40 + dc->ctx->logger 41 + #define DC_LOGGER_INIT(logger) 42 + 43 + /* Private dc_state helper functions */ 44 + static bool dc_state_track_phantom_stream(struct dc_state *state, 45 + struct dc_stream_state *phantom_stream) 46 + { 47 + if (state->phantom_stream_count >= MAX_PHANTOM_PIPES) 48 + return false; 49 + 50 + state->phantom_streams[state->phantom_stream_count++] = phantom_stream; 51 + 52 + return true; 53 + } 54 + 55 + static bool dc_state_untrack_phantom_stream(struct dc_state *state, struct dc_stream_state *phantom_stream) 56 + { 57 + bool res = false; 58 + int i; 59 + 60 + /* first find phantom stream in the dc_state */ 61 + for (i = 0; i < state->phantom_stream_count; i++) { 62 + if (state->phantom_streams[i] == phantom_stream) { 63 + state->phantom_streams[i] = NULL; 64 + res = true; 65 + break; 66 + } 67 + } 68 + 69 + /* failed to find stream in state */ 70 + if (!res) 71 + return res; 72 + 73 + /* trim back phantom streams */ 74 + state->phantom_stream_count--; 75 + for (; i < state->phantom_stream_count; i++) 76 + state->phantom_streams[i] = state->phantom_streams[i + 1]; 77 + 78 + return res; 79 + } 80 + 81 + static bool dc_state_is_phantom_stream_tracked(struct dc_state *state, struct dc_stream_state *phantom_stream) 82 + { 83 + int i; 84 + 85 + for (i = 0; i < state->phantom_stream_count; i++) { 86 + if (state->phantom_streams[i] == phantom_stream) 87 + return true; 88 + } 89 + 90 + return false; 91 + } 92 + 93 + static bool dc_state_track_phantom_plane(struct dc_state *state, 94 + struct dc_plane_state *phantom_plane) 95 + { 96 + if (state->phantom_plane_count >= MAX_PHANTOM_PIPES) 97 + return false; 98 + 99 + state->phantom_planes[state->phantom_plane_count++] = phantom_plane; 100 + 101 + return true; 102 + } 103 + 104 + static bool dc_state_untrack_phantom_plane(struct dc_state *state, struct dc_plane_state *phantom_plane) 105 + { 106 + bool res = false; 107 + int i; 108 + 109 + /* first find phantom plane in the dc_state */ 110 + for (i = 0; i < state->phantom_plane_count; i++) { 111 + if (state->phantom_planes[i] == phantom_plane) { 112 + state->phantom_planes[i] = NULL; 113 + res = true; 114 + break; 115 + } 116 + } 117 + 118 + /* failed to find plane in state */ 119 + if (!res) 120 + return res; 121 + 122 + /* trim back phantom planes */ 123 + state->phantom_plane_count--; 124 + for (; i < state->phantom_plane_count; i++) 125 + state->phantom_planes[i] = state->phantom_planes[i + 1]; 126 + 127 + return res; 128 + } 129 + 130 + static bool dc_state_is_phantom_plane_tracked(struct dc_state *state, struct dc_plane_state *phantom_plane) 131 + { 132 + int i; 133 + 134 + for (i = 0; i < state->phantom_plane_count; i++) { 135 + if (state->phantom_planes[i] == phantom_plane) 136 + return true; 137 + } 138 + 139 + return false; 140 + } 141 + 142 + static void dc_state_copy_internal(struct dc_state *dst_state, struct dc_state *src_state) 143 + { 144 + int i, j; 145 + 146 + memcpy(dst_state, src_state, sizeof(struct dc_state)); 147 + 148 + for (i = 0; i < MAX_PIPES; i++) { 149 + struct pipe_ctx *cur_pipe = &dst_state->res_ctx.pipe_ctx[i]; 150 + 151 + if (cur_pipe->top_pipe) 152 + cur_pipe->top_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 153 + 154 + if (cur_pipe->bottom_pipe) 155 + cur_pipe->bottom_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 156 + 157 + if (cur_pipe->prev_odm_pipe) 158 + cur_pipe->prev_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 159 + 160 + if (cur_pipe->next_odm_pipe) 161 + cur_pipe->next_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 162 + } 163 + 164 + /* retain phantoms */ 165 + for (i = 0; i < dst_state->phantom_stream_count; i++) 166 + dc_stream_retain(dst_state->phantom_streams[i]); 167 + 168 + for (i = 0; i < dst_state->phantom_plane_count; i++) 169 + dc_plane_state_retain(dst_state->phantom_planes[i]); 170 + 171 + /* retain streams and planes */ 172 + for (i = 0; i < dst_state->stream_count; i++) { 173 + dc_stream_retain(dst_state->streams[i]); 174 + for (j = 0; j < dst_state->stream_status[i].plane_count; j++) 175 + dc_plane_state_retain( 176 + dst_state->stream_status[i].plane_states[j]); 177 + } 178 + 179 + } 180 + 181 + static void init_state(struct dc *dc, struct dc_state *state) 182 + { 183 + /* Each context must have their own instance of VBA and in order to 184 + * initialize and obtain IP and SOC the base DML instance from DC is 185 + * initially copied into every context 186 + */ 187 + memcpy(&state->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib)); 188 + } 189 + 190 + /* Public dc_state functions */ 191 + struct dc_state *dc_state_create(struct dc *dc) 192 + { 193 + struct dc_state *state = kvzalloc(sizeof(struct dc_state), 194 + GFP_KERNEL); 195 + 196 + if (!state) 197 + return NULL; 198 + 199 + init_state(dc, state); 200 + dc_state_construct(dc, state); 201 + 202 + #ifdef CONFIG_DRM_AMD_DC_FP 203 + if (dc->debug.using_dml2) 204 + dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2); 205 + #endif 206 + 207 + kref_init(&state->refcount); 208 + 209 + return state; 210 + } 211 + 212 + void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state) 213 + { 214 + struct kref refcount = dst_state->refcount; 215 + #ifdef CONFIG_DRM_AMD_DC_FP 216 + struct dml2_context *dst_dml2 = dst_state->bw_ctx.dml2; 217 + #endif 218 + 219 + dc_state_copy_internal(dst_state, src_state); 220 + 221 + #ifdef CONFIG_DRM_AMD_DC_FP 222 + dst_state->bw_ctx.dml2 = dst_dml2; 223 + if (src_state->bw_ctx.dml2) 224 + dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2); 225 + #endif 226 + 227 + /* context refcount should not be overridden */ 228 + dst_state->refcount = refcount; 229 + } 230 + 231 + struct dc_state *dc_state_create_copy(struct dc_state *src_state) 232 + { 233 + struct dc_state *new_state; 234 + 235 + new_state = kvmalloc(sizeof(struct dc_state), 236 + GFP_KERNEL); 237 + if (!new_state) 238 + return NULL; 239 + 240 + dc_state_copy_internal(new_state, src_state); 241 + 242 + #ifdef CONFIG_DRM_AMD_DC_FP 243 + if (src_state->bw_ctx.dml2 && 244 + !dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) { 245 + dc_state_release(new_state); 246 + return NULL; 247 + } 248 + #endif 249 + 250 + kref_init(&new_state->refcount); 251 + 252 + return new_state; 253 + } 254 + 255 + void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state) 256 + { 257 + dc_state_copy(dst_state, dc->current_state); 258 + } 259 + 260 + struct dc_state *dc_state_create_current_copy(struct dc *dc) 261 + { 262 + return dc_state_create_copy(dc->current_state); 263 + } 264 + 265 + void dc_state_construct(struct dc *dc, struct dc_state *state) 266 + { 267 + state->clk_mgr = dc->clk_mgr; 268 + 269 + /* Initialise DIG link encoder resource tracking variables. */ 270 + link_enc_cfg_init(dc, state); 271 + } 272 + 273 + void dc_state_destruct(struct dc_state *state) 274 + { 275 + int i, j; 276 + 277 + for (i = 0; i < state->stream_count; i++) { 278 + for (j = 0; j < state->stream_status[i].plane_count; j++) 279 + dc_plane_state_release( 280 + state->stream_status[i].plane_states[j]); 281 + 282 + state->stream_status[i].plane_count = 0; 283 + dc_stream_release(state->streams[i]); 284 + state->streams[i] = NULL; 285 + } 286 + state->stream_count = 0; 287 + 288 + /* release tracked phantoms */ 289 + for (i = 0; i < state->phantom_stream_count; i++) { 290 + dc_stream_release(state->phantom_streams[i]); 291 + state->phantom_streams[i] = NULL; 292 + } 293 + 294 + for (i = 0; i < state->phantom_plane_count; i++) { 295 + dc_plane_state_release(state->phantom_planes[i]); 296 + state->phantom_planes[i] = NULL; 297 + } 298 + state->stream_mask = 0; 299 + memset(&state->res_ctx, 0, sizeof(state->res_ctx)); 300 + memset(&state->pp_display_cfg, 0, sizeof(state->pp_display_cfg)); 301 + memset(&state->dcn_bw_vars, 0, sizeof(state->dcn_bw_vars)); 302 + state->clk_mgr = NULL; 303 + memset(&state->bw_ctx.bw, 0, sizeof(state->bw_ctx.bw)); 304 + memset(state->block_sequence, 0, sizeof(state->block_sequence)); 305 + state->block_sequence_steps = 0; 306 + memset(state->dc_dmub_cmd, 0, sizeof(state->dc_dmub_cmd)); 307 + state->dmub_cmd_count = 0; 308 + memset(&state->perf_params, 0, sizeof(state->perf_params)); 309 + memset(&state->scratch, 0, sizeof(state->scratch)); 310 + } 311 + 312 + void dc_state_retain(struct dc_state *state) 313 + { 314 + kref_get(&state->refcount); 315 + } 316 + 317 + static void dc_state_free(struct kref *kref) 318 + { 319 + struct dc_state *state = container_of(kref, struct dc_state, refcount); 320 + 321 + dc_state_destruct(state); 322 + 323 + #ifdef CONFIG_DRM_AMD_DC_FP 324 + dml2_destroy(state->bw_ctx.dml2); 325 + state->bw_ctx.dml2 = 0; 326 + #endif 327 + 328 + kvfree(state); 329 + } 330 + 331 + void dc_state_release(struct dc_state *state) 332 + { 333 + kref_put(&state->refcount, dc_state_free); 334 + } 335 + /* 336 + * dc_state_add_stream() - Add a new dc_stream_state to a dc_state. 337 + */ 338 + enum dc_status dc_state_add_stream( 339 + struct dc *dc, 340 + struct dc_state *state, 341 + struct dc_stream_state *stream) 342 + { 343 + enum dc_status res; 344 + 345 + DC_LOGGER_INIT(dc->ctx->logger); 346 + 347 + if (state->stream_count >= dc->res_pool->timing_generator_count) { 348 + DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 349 + return DC_ERROR_UNEXPECTED; 350 + } 351 + 352 + state->streams[state->stream_count] = stream; 353 + dc_stream_retain(stream); 354 + state->stream_count++; 355 + 356 + res = resource_add_otg_master_for_stream_output( 357 + state, dc->res_pool, stream); 358 + if (res != DC_OK) 359 + DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 360 + 361 + return res; 362 + } 363 + 364 + /* 365 + * dc_state_remove_stream() - Remove a stream from a dc_state. 366 + */ 367 + enum dc_status dc_state_remove_stream( 368 + struct dc *dc, 369 + struct dc_state *state, 370 + struct dc_stream_state *stream) 371 + { 372 + int i; 373 + struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream( 374 + &state->res_ctx, stream); 375 + 376 + if (!del_pipe) { 377 + dm_error("Pipe not found for stream %p !\n", stream); 378 + return DC_ERROR_UNEXPECTED; 379 + } 380 + 381 + resource_update_pipes_for_stream_with_slice_count(state, 382 + dc->current_state, dc->res_pool, stream, 1); 383 + resource_remove_otg_master_for_stream_output( 384 + state, dc->res_pool, stream); 385 + 386 + for (i = 0; i < state->stream_count; i++) 387 + if (state->streams[i] == stream) 388 + break; 389 + 390 + if (state->streams[i] != stream) { 391 + dm_error("Context doesn't have stream %p !\n", stream); 392 + return DC_ERROR_UNEXPECTED; 393 + } 394 + 395 + dc_stream_release(state->streams[i]); 396 + state->stream_count--; 397 + 398 + /* Trim back arrays */ 399 + for (; i < state->stream_count; i++) { 400 + state->streams[i] = state->streams[i + 1]; 401 + state->stream_status[i] = state->stream_status[i + 1]; 402 + } 403 + 404 + state->streams[state->stream_count] = NULL; 405 + memset( 406 + &state->stream_status[state->stream_count], 407 + 0, 408 + sizeof(state->stream_status[0])); 409 + 410 + return DC_OK; 411 + } 412 + 413 + bool dc_state_add_plane( 414 + const struct dc *dc, 415 + struct dc_stream_state *stream, 416 + struct dc_plane_state *plane_state, 417 + struct dc_state *state) 418 + { 419 + struct resource_pool *pool = dc->res_pool; 420 + struct pipe_ctx *otg_master_pipe; 421 + struct dc_stream_status *stream_status = NULL; 422 + bool added = false; 423 + 424 + stream_status = dc_state_get_stream_status(state, stream); 425 + if (stream_status == NULL) { 426 + dm_error("Existing stream not found; failed to attach surface!\n"); 427 + goto out; 428 + } else if (stream_status->plane_count == MAX_SURFACE_NUM) { 429 + dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 430 + plane_state, MAX_SURFACE_NUM); 431 + goto out; 432 + } 433 + 434 + otg_master_pipe = resource_get_otg_master_for_stream( 435 + &state->res_ctx, stream); 436 + added = resource_append_dpp_pipes_for_plane_composition(state, 437 + dc->current_state, pool, otg_master_pipe, plane_state); 438 + 439 + if (added) { 440 + stream_status->plane_states[stream_status->plane_count] = 441 + plane_state; 442 + stream_status->plane_count++; 443 + dc_plane_state_retain(plane_state); 444 + } 445 + 446 + out: 447 + return added; 448 + } 449 + 450 + bool dc_state_remove_plane( 451 + const struct dc *dc, 452 + struct dc_stream_state *stream, 453 + struct dc_plane_state *plane_state, 454 + struct dc_state *state) 455 + { 456 + int i; 457 + struct dc_stream_status *stream_status = NULL; 458 + struct resource_pool *pool = dc->res_pool; 459 + 460 + if (!plane_state) 461 + return true; 462 + 463 + for (i = 0; i < state->stream_count; i++) 464 + if (state->streams[i] == stream) { 465 + stream_status = &state->stream_status[i]; 466 + break; 467 + } 468 + 469 + if (stream_status == NULL) { 470 + dm_error("Existing stream not found; failed to remove plane.\n"); 471 + return false; 472 + } 473 + 474 + resource_remove_dpp_pipes_for_plane_composition( 475 + state, pool, plane_state); 476 + 477 + for (i = 0; i < stream_status->plane_count; i++) { 478 + if (stream_status->plane_states[i] == plane_state) { 479 + dc_plane_state_release(stream_status->plane_states[i]); 480 + break; 481 + } 482 + } 483 + 484 + if (i == stream_status->plane_count) { 485 + dm_error("Existing plane_state not found; failed to detach it!\n"); 486 + return false; 487 + } 488 + 489 + stream_status->plane_count--; 490 + 491 + /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 492 + for (; i < stream_status->plane_count; i++) 493 + stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 494 + 495 + stream_status->plane_states[stream_status->plane_count] = NULL; 496 + 497 + if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm) 498 + /* ODM combine could prevent us from supporting more planes 499 + * we will reset ODM slice count back to 1 when all planes have 500 + * been removed to maximize the amount of planes supported when 501 + * new planes are added. 502 + */ 503 + resource_update_pipes_for_stream_with_slice_count( 504 + state, dc->current_state, dc->res_pool, stream, 1); 505 + 506 + return true; 507 + } 508 + 509 + /** 510 + * dc_state_rem_all_planes_for_stream - Remove planes attached to the target stream. 511 + * 512 + * @dc: Current dc state. 513 + * @stream: Target stream, which we want to remove the attached plans. 514 + * @state: context from which the planes are to be removed. 515 + * 516 + * Return: 517 + * Return true if DC was able to remove all planes from the target 518 + * stream, otherwise, return false. 519 + */ 520 + bool dc_state_rem_all_planes_for_stream( 521 + const struct dc *dc, 522 + struct dc_stream_state *stream, 523 + struct dc_state *state) 524 + { 525 + int i, old_plane_count; 526 + struct dc_stream_status *stream_status = NULL; 527 + struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 528 + 529 + for (i = 0; i < state->stream_count; i++) 530 + if (state->streams[i] == stream) { 531 + stream_status = &state->stream_status[i]; 532 + break; 533 + } 534 + 535 + if (stream_status == NULL) { 536 + dm_error("Existing stream %p not found!\n", stream); 537 + return false; 538 + } 539 + 540 + old_plane_count = stream_status->plane_count; 541 + 542 + for (i = 0; i < old_plane_count; i++) 543 + del_planes[i] = stream_status->plane_states[i]; 544 + 545 + for (i = 0; i < old_plane_count; i++) 546 + if (!dc_state_remove_plane(dc, stream, del_planes[i], state)) 547 + return false; 548 + 549 + return true; 550 + } 551 + 552 + bool dc_state_add_all_planes_for_stream( 553 + const struct dc *dc, 554 + struct dc_stream_state *stream, 555 + struct dc_plane_state * const *plane_states, 556 + int plane_count, 557 + struct dc_state *state) 558 + { 559 + int i; 560 + bool result = true; 561 + 562 + for (i = 0; i < plane_count; i++) 563 + if (!dc_state_add_plane(dc, stream, plane_states[i], state)) { 564 + result = false; 565 + break; 566 + } 567 + 568 + return result; 569 + } 570 + 571 + /* Private dc_state functions */ 572 + 573 + /** 574 + * dc_state_get_stream_status - Get stream status from given dc state 575 + * @state: DC state to find the stream status in 576 + * @stream: The stream to get the stream status for 577 + * 578 + * The given stream is expected to exist in the given dc state. Otherwise, NULL 579 + * will be returned. 580 + */ 581 + struct dc_stream_status *dc_state_get_stream_status( 582 + struct dc_state *state, 583 + struct dc_stream_state *stream) 584 + { 585 + uint8_t i; 586 + 587 + if (state == NULL) 588 + return NULL; 589 + 590 + for (i = 0; i < state->stream_count; i++) { 591 + if (stream == state->streams[i]) 592 + return &state->stream_status[i]; 593 + } 594 + 595 + return NULL; 596 + } 597 + 598 + enum mall_stream_type dc_state_get_pipe_subvp_type(const struct dc_state *state, 599 + const struct pipe_ctx *pipe_ctx) 600 + { 601 + return dc_state_get_stream_subvp_type(state, pipe_ctx->stream); 602 + } 603 + 604 + enum mall_stream_type dc_state_get_stream_subvp_type(const struct dc_state *state, 605 + const struct dc_stream_state *stream) 606 + { 607 + int i; 608 + 609 + enum mall_stream_type type = SUBVP_NONE; 610 + 611 + for (i = 0; i < state->stream_count; i++) { 612 + if (state->streams[i] == stream) { 613 + type = state->stream_status[i].mall_stream_config.type; 614 + break; 615 + } 616 + } 617 + 618 + return type; 619 + } 620 + 621 + struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state *state, 622 + const struct dc_stream_state *stream) 623 + { 624 + int i; 625 + 626 + struct dc_stream_state *paired_stream = NULL; 627 + 628 + for (i = 0; i < state->stream_count; i++) { 629 + if (state->streams[i] == stream) { 630 + paired_stream = state->stream_status[i].mall_stream_config.paired_stream; 631 + break; 632 + } 633 + } 634 + 635 + return paired_stream; 636 + } 637 + 638 + struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc, 639 + struct dc_state *state, 640 + struct dc_stream_state *main_stream) 641 + { 642 + struct dc_stream_state *phantom_stream; 643 + 644 + DC_LOGGER_INIT(dc->ctx->logger); 645 + 646 + phantom_stream = dc_create_stream_for_sink(main_stream->sink); 647 + 648 + if (!phantom_stream) { 649 + DC_LOG_ERROR("Failed to allocate phantom stream.\n"); 650 + return NULL; 651 + } 652 + 653 + /* track phantom stream in dc_state */ 654 + dc_state_track_phantom_stream(state, phantom_stream); 655 + 656 + phantom_stream->is_phantom = true; 657 + phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; 658 + phantom_stream->dpms_off = true; 659 + 660 + return phantom_stream; 661 + } 662 + 663 + void dc_state_release_phantom_stream(const struct dc *dc, 664 + struct dc_state *state, 665 + struct dc_stream_state *phantom_stream) 666 + { 667 + DC_LOGGER_INIT(dc->ctx->logger); 668 + 669 + if (!dc_state_untrack_phantom_stream(state, phantom_stream)) { 670 + DC_LOG_ERROR("Failed to free phantom stream %p in dc state %p.\n", phantom_stream, state); 671 + return; 672 + } 673 + 674 + dc_stream_release(phantom_stream); 675 + } 676 + 677 + struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc, 678 + struct dc_state *state, 679 + struct dc_plane_state *main_plane) 680 + { 681 + struct dc_plane_state *phantom_plane = dc_create_plane_state(dc); 682 + 683 + DC_LOGGER_INIT(dc->ctx->logger); 684 + 685 + if (!phantom_plane) { 686 + DC_LOG_ERROR("Failed to allocate phantom plane.\n"); 687 + return NULL; 688 + } 689 + 690 + /* track phantom inside dc_state */ 691 + dc_state_track_phantom_plane(state, phantom_plane); 692 + 693 + phantom_plane->is_phantom = true; 694 + 695 + return phantom_plane; 696 + } 697 + 698 + void dc_state_release_phantom_plane(const struct dc *dc, 699 + struct dc_state *state, 700 + struct dc_plane_state *phantom_plane) 701 + { 702 + DC_LOGGER_INIT(dc->ctx->logger); 703 + 704 + if (!dc_state_untrack_phantom_plane(state, phantom_plane)) { 705 + DC_LOG_ERROR("Failed to free phantom plane %p in dc state %p.\n", phantom_plane, state); 706 + return; 707 + } 708 + 709 + dc_plane_state_release(phantom_plane); 710 + } 711 + 712 + /* add phantom streams to context and generate correct meta inside dc_state */ 713 + enum dc_status dc_state_add_phantom_stream(struct dc *dc, 714 + struct dc_state *state, 715 + struct dc_stream_state *phantom_stream, 716 + struct dc_stream_state *main_stream) 717 + { 718 + struct dc_stream_status *main_stream_status; 719 + struct dc_stream_status *phantom_stream_status; 720 + enum dc_status res = dc_state_add_stream(dc, state, phantom_stream); 721 + 722 + /* check if stream is tracked */ 723 + if (res == DC_OK && !dc_state_is_phantom_stream_tracked(state, phantom_stream)) { 724 + /* stream must be tracked if added to state */ 725 + dc_state_track_phantom_stream(state, phantom_stream); 726 + } 727 + 728 + /* setup subvp meta */ 729 + main_stream_status = dc_state_get_stream_status(state, main_stream); 730 + phantom_stream_status = dc_state_get_stream_status(state, phantom_stream); 731 + phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM; 732 + phantom_stream_status->mall_stream_config.paired_stream = main_stream; 733 + main_stream_status->mall_stream_config.type = SUBVP_MAIN; 734 + main_stream_status->mall_stream_config.paired_stream = phantom_stream; 735 + 736 + return res; 737 + } 738 + 739 + enum dc_status dc_state_remove_phantom_stream(struct dc *dc, 740 + struct dc_state *state, 741 + struct dc_stream_state *phantom_stream) 742 + { 743 + struct dc_stream_status *main_stream_status; 744 + struct dc_stream_status *phantom_stream_status; 745 + 746 + /* reset subvp meta */ 747 + phantom_stream_status = dc_state_get_stream_status(state, phantom_stream); 748 + main_stream_status = dc_state_get_stream_status(state, phantom_stream_status->mall_stream_config.paired_stream); 749 + phantom_stream_status->mall_stream_config.type = SUBVP_NONE; 750 + phantom_stream_status->mall_stream_config.paired_stream = NULL; 751 + if (main_stream_status) { 752 + main_stream_status->mall_stream_config.type = SUBVP_NONE; 753 + main_stream_status->mall_stream_config.paired_stream = NULL; 754 + } 755 + 756 + /* remove stream from state */ 757 + return dc_state_remove_stream(dc, state, phantom_stream); 758 + } 759 + 760 + bool dc_state_add_phantom_plane( 761 + const struct dc *dc, 762 + struct dc_stream_state *phantom_stream, 763 + struct dc_plane_state *phantom_plane, 764 + struct dc_state *state) 765 + { 766 + bool res = dc_state_add_plane(dc, phantom_stream, phantom_plane, state); 767 + 768 + /* check if stream is tracked */ 769 + if (res && !dc_state_is_phantom_plane_tracked(state, phantom_plane)) { 770 + /* stream must be tracked if added to state */ 771 + dc_state_track_phantom_plane(state, phantom_plane); 772 + } 773 + 774 + return res; 775 + } 776 + 777 + bool dc_state_remove_phantom_plane( 778 + const struct dc *dc, 779 + struct dc_stream_state *phantom_stream, 780 + struct dc_plane_state *phantom_plane, 781 + struct dc_state *state) 782 + { 783 + return dc_state_remove_plane(dc, phantom_stream, phantom_plane, state); 784 + } 785 + 786 + bool dc_state_rem_all_phantom_planes_for_stream( 787 + const struct dc *dc, 788 + struct dc_stream_state *phantom_stream, 789 + struct dc_state *state, 790 + bool should_release_planes) 791 + { 792 + int i, old_plane_count; 793 + struct dc_stream_status *stream_status = NULL; 794 + struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 795 + 796 + for (i = 0; i < state->stream_count; i++) 797 + if (state->streams[i] == phantom_stream) { 798 + stream_status = &state->stream_status[i]; 799 + break; 800 + } 801 + 802 + if (stream_status == NULL) { 803 + dm_error("Existing stream %p not found!\n", phantom_stream); 804 + return false; 805 + } 806 + 807 + old_plane_count = stream_status->plane_count; 808 + 809 + for (i = 0; i < old_plane_count; i++) 810 + del_planes[i] = stream_status->plane_states[i]; 811 + 812 + for (i = 0; i < old_plane_count; i++) { 813 + if (!dc_state_remove_plane(dc, phantom_stream, del_planes[i], state)) 814 + return false; 815 + if (should_release_planes) 816 + dc_state_release_phantom_plane(dc, state, del_planes[i]); 817 + } 818 + 819 + return true; 820 + } 821 + 822 + bool dc_state_add_all_phantom_planes_for_stream( 823 + const struct dc *dc, 824 + struct dc_stream_state *phantom_stream, 825 + struct dc_plane_state * const *phantom_planes, 826 + int plane_count, 827 + struct dc_state *state) 828 + { 829 + return dc_state_add_all_planes_for_stream(dc, phantom_stream, phantom_planes, plane_count, state); 830 + } 831 + 832 + bool dc_state_remove_phantom_streams_and_planes( 833 + struct dc *dc, 834 + struct dc_state *state) 835 + { 836 + int i; 837 + bool removed_phantom = false; 838 + struct dc_stream_state *phantom_stream = NULL; 839 + 840 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 841 + struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i]; 842 + 843 + if (pipe->plane_state && pipe->stream && dc_state_get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) { 844 + phantom_stream = pipe->stream; 845 + 846 + dc_state_rem_all_phantom_planes_for_stream(dc, phantom_stream, state, false); 847 + dc_state_remove_phantom_stream(dc, state, phantom_stream); 848 + removed_phantom = true; 849 + } 850 + } 851 + return removed_phantom; 852 + } 853 + 854 + void dc_state_release_phantom_streams_and_planes( 855 + struct dc *dc, 856 + struct dc_state *state) 857 + { 858 + int i; 859 + 860 + for (i = 0; i < state->phantom_stream_count; i++) 861 + dc_state_release_phantom_stream(dc, state, state->phantom_streams[i]); 862 + 863 + for (i = 0; i < state->phantom_plane_count; i++) 864 + dc_state_release_phantom_plane(dc, state, state->phantom_planes[i]); 865 + }
+16 -33
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
··· 31 31 #include "ipp.h" 32 32 #include "timing_generator.h" 33 33 #include "dc_dmub_srv.h" 34 + #include "dc_state_priv.h" 35 + #include "dc_stream_priv.h" 34 36 35 37 #define DC_LOGGER dc->ctx->logger 36 38 ··· 56 54 } 57 55 } 58 56 59 - static bool dc_stream_construct(struct dc_stream_state *stream, 57 + bool dc_stream_construct(struct dc_stream_state *stream, 60 58 struct dc_sink *dc_sink_data) 61 59 { 62 60 uint32_t i = 0; ··· 123 121 } 124 122 stream->out_transfer_func->type = TF_TYPE_BYPASS; 125 123 126 - stream->stream_id = stream->ctx->dc_stream_id_count; 127 - stream->ctx->dc_stream_id_count++; 124 + dc_stream_assign_stream_id(stream); 128 125 129 126 return true; 130 127 } 131 128 132 - static void dc_stream_destruct(struct dc_stream_state *stream) 129 + void dc_stream_destruct(struct dc_stream_state *stream) 133 130 { 134 131 dc_sink_release(stream->sink); 135 132 if (stream->out_transfer_func != NULL) { 136 133 dc_transfer_func_release(stream->out_transfer_func); 137 134 stream->out_transfer_func = NULL; 138 135 } 136 + } 137 + 138 + void dc_stream_assign_stream_id(struct dc_stream_state *stream) 139 + { 140 + /* MSB is reserved to indicate phantoms */ 141 + stream->stream_id = stream->ctx->dc_stream_id_count; 142 + stream->ctx->dc_stream_id_count++; 139 143 } 140 144 141 145 void dc_stream_retain(struct dc_stream_state *stream) ··· 204 196 if (new_stream->out_transfer_func) 205 197 dc_transfer_func_retain(new_stream->out_transfer_func); 206 198 207 - new_stream->stream_id = new_stream->ctx->dc_stream_id_count; 208 - new_stream->ctx->dc_stream_id_count++; 199 + dc_stream_assign_stream_id(new_stream); 209 200 210 201 /* If using dynamic encoder assignment, wait till stream committed to assign encoder. */ 211 202 if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign) ··· 213 206 kref_init(&new_stream->refcount); 214 207 215 208 return new_stream; 216 - } 217 - 218 - /** 219 - * dc_stream_get_status_from_state - Get stream status from given dc state 220 - * @state: DC state to find the stream status in 221 - * @stream: The stream to get the stream status for 222 - * 223 - * The given stream is expected to exist in the given dc state. Otherwise, NULL 224 - * will be returned. 225 - */ 226 - struct dc_stream_status *dc_stream_get_status_from_state( 227 - struct dc_state *state, 228 - struct dc_stream_state *stream) 229 - { 230 - uint8_t i; 231 - 232 - if (state == NULL) 233 - return NULL; 234 - 235 - for (i = 0; i < state->stream_count; i++) { 236 - if (stream == state->streams[i]) 237 - return &state->stream_status[i]; 238 - } 239 - 240 - return NULL; 241 209 } 242 210 243 211 /** ··· 226 244 struct dc_stream_state *stream) 227 245 { 228 246 struct dc *dc = stream->ctx->dc; 229 - return dc_stream_get_status_from_state(dc->current_state, stream); 247 + return dc_state_get_stream_status(dc->current_state, stream); 230 248 } 231 249 232 250 static void program_cursor_attributes( ··· 447 465 if (dc->hwss.enable_writeback) { 448 466 struct dc_stream_status *stream_status = dc_stream_get_status(stream); 449 467 struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; 450 - dwb->otg_inst = stream_status->primary_otg_inst; 468 + if (stream_status) 469 + dwb->otg_inst = stream_status->primary_otg_inst; 451 470 } 452 471 453 472 if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
+4 -2
drivers/gpu/drm/amd/display/dc/core/dc_surface.c
··· 32 32 #include "transform.h" 33 33 #include "dpp.h" 34 34 35 + #include "dc_plane_priv.h" 36 + 35 37 /******************************************************************************* 36 38 * Private functions 37 39 ******************************************************************************/ 38 - static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state) 40 + void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state) 39 41 { 40 42 plane_state->ctx = ctx; 41 43 ··· 65 63 66 64 } 67 65 68 - static void dc_plane_destruct(struct dc_plane_state *plane_state) 66 + void dc_plane_destruct(struct dc_plane_state *plane_state) 69 67 { 70 68 if (plane_state->gamma_correction != NULL) { 71 69 dc_gamma_release(&plane_state->gamma_correction);
+32 -30
drivers/gpu/drm/amd/display/dc/dc.h
··· 27 27 #define DC_INTERFACE_H_ 28 28 29 29 #include "dc_types.h" 30 + #include "dc_state.h" 31 + #include "dc_plane.h" 30 32 #include "grph_object_defs.h" 31 33 #include "logger_types.h" 32 34 #include "hdcp_msg_types.h" ··· 51 49 struct set_config_cmd_payload; 52 50 struct dmub_notification; 53 51 54 - #define DC_VER "3.2.264" 52 + #define DC_VER "3.2.265" 55 53 56 54 #define MAX_SURFACES 3 57 55 #define MAX_PLANES 6 ··· 461 459 DML_HOSTVM_NO_OVERRIDE = 0x0, 462 460 DML_HOSTVM_OVERRIDE_FALSE = 0x1, 463 461 DML_HOSTVM_OVERRIDE_TRUE = 0x2, 462 + }; 463 + 464 + enum dc_replay_power_opts { 465 + replay_power_opt_invalid = 0x0, 466 + replay_power_opt_smu_opt_static_screen = 0x1, 467 + replay_power_opt_z10_static_screen = 0x10, 464 468 }; 465 469 466 470 enum dcc_option { ··· 987 979 unsigned int ips2_eval_delay_us; 988 980 unsigned int ips2_entry_delay_us; 989 981 bool disable_timeout; 982 + bool disable_extblankadj; 983 + unsigned int static_screen_wait_frames; 990 984 }; 991 985 992 986 struct gpu_info_soc_bounding_box_v1_0; ··· 1036 1026 1037 1027 /* Require to optimize clocks and bandwidth for added/removed planes */ 1038 1028 bool optimized_required; 1039 - bool wm_optimized_required; 1040 1029 bool idle_optimizations_allowed; 1041 1030 bool enable_c20_dtm_b0; 1042 1031 ··· 1398 1389 /* 1399 1390 * Create a new surface with default parameters; 1400 1391 */ 1401 - struct dc_plane_state *dc_create_plane_state(struct dc *dc); 1402 - const struct dc_plane_status *dc_plane_get_status( 1403 - const struct dc_plane_state *plane_state); 1404 - 1405 - void dc_plane_state_retain(struct dc_plane_state *plane_state); 1406 - void dc_plane_state_release(struct dc_plane_state *plane_state); 1407 - 1408 1392 void dc_gamma_retain(struct dc_gamma *dc_gamma); 1409 1393 void dc_gamma_release(struct dc_gamma **dc_gamma); 1410 1394 struct dc_gamma *dc_create_gamma(void); ··· 1461 1459 struct dc_state *new_ctx, 1462 1460 bool fast_validate); 1463 1461 1464 - 1465 - void dc_resource_state_construct( 1466 - const struct dc *dc, 1467 - struct dc_state *dst_ctx); 1468 - 1469 1462 bool dc_acquire_release_mpc_3dlut( 1470 1463 struct dc *dc, bool acquire, 1471 1464 struct dc_stream_state *stream, 1472 1465 struct dc_3dlut **lut, 1473 1466 struct dc_transfer_func **shaper); 1474 1467 1475 - void dc_resource_state_copy_construct( 1476 - const struct dc_state *src_ctx, 1477 - struct dc_state *dst_ctx); 1478 - 1479 - void dc_resource_state_copy_construct_current( 1480 - const struct dc *dc, 1481 - struct dc_state *dst_ctx); 1482 - 1483 - void dc_resource_state_destruct(struct dc_state *context); 1484 - 1485 1468 bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); 1469 + void get_audio_check(struct audio_info *aud_modes, 1470 + struct audio_check *aud_chk); 1486 1471 1487 1472 enum dc_status dc_commit_streams(struct dc *dc, 1488 1473 struct dc_stream_state *streams[], 1489 1474 uint8_t stream_count); 1490 1475 1491 - struct dc_state *dc_create_state(struct dc *dc); 1492 - struct dc_state *dc_copy_state(struct dc_state *src_ctx); 1493 - void dc_retain_state(struct dc_state *context); 1494 - void dc_release_state(struct dc_state *context); 1495 1476 1496 1477 struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, 1497 1478 struct dc_stream_state *stream, ··· 2083 2098 const struct dc_stream_state *stream, struct psr_config *psr_config, 2084 2099 struct psr_context *psr_context); 2085 2100 2101 + /* 2102 + * Communicate with DMUB to allow or disallow Panel Replay on the specified link: 2103 + * 2104 + * @link: pointer to the dc_link struct instance 2105 + * @enable: enable(active) or disable(inactive) replay 2106 + * @wait: state transition need to wait the active set completed. 2107 + * @force_static: force disable(inactive) the replay 2108 + * @power_opts: set power optimazation parameters to DMUB. 2109 + * 2110 + * return: allow Replay active will return true, else will return false. 2111 + */ 2112 + bool dc_link_set_replay_allow_active(struct dc_link *dc_link, const bool *enable, 2113 + bool wait, bool force_static, const unsigned int *power_opts); 2114 + 2086 2115 bool dc_link_get_replay_state(const struct dc_link *dc_link, uint64_t *state); 2087 2116 2088 2117 /* On eDP links this function call will stall until T12 has elapsed. ··· 2192 2193 * 2193 2194 * @dc: pointer to dc struct 2194 2195 * @stream: pointer to all possible streams 2195 - * @num_streams: number of valid DPIA streams 2196 + * @count: number of valid DPIA streams 2196 2197 * 2197 2198 * return: TRUE if bw used by DPIAs doesn't exceed available BW else return FALSE 2198 2199 */ 2199 - bool dc_link_validate(struct dc *dc, const struct dc_stream_state *streams, 2200 + bool dc_link_dp_dpia_validate(struct dc *dc, const struct dc_stream_state *streams, 2200 2201 const unsigned int count); 2201 2202 2202 2203 /* Sink Interfaces - A sink corresponds to a display output device */ ··· 2341 2342 void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc); 2342 2343 2343 2344 bool dc_set_psr_allow_active(struct dc *dc, bool enable); 2345 + 2346 + bool dc_set_replay_allow_active(struct dc *dc, bool active); 2347 + 2344 2348 void dc_z10_restore(const struct dc *dc); 2345 2349 void dc_z10_save_init(struct dc *dc); 2346 2350
+197 -64
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
··· 33 33 #include "cursor_reg_cache.h" 34 34 #include "resource.h" 35 35 #include "clk_mgr.h" 36 + #include "dc_state_priv.h" 36 37 37 38 #define CTX dc_dmub_srv->ctx 38 39 #define DC_LOGGER CTX->logger ··· 141 140 142 141 if (status == DMUB_STATUS_QUEUE_FULL) { 143 142 /* Execute and wait for queue to become empty again. */ 144 - dmub_srv_cmd_execute(dmub); 143 + status = dmub_srv_cmd_execute(dmub); 144 + if (status == DMUB_STATUS_POWER_STATE_D3) 145 + return false; 146 + 145 147 dmub_srv_wait_for_idle(dmub, 100000); 146 148 147 149 /* Requeue the command. */ ··· 152 148 } 153 149 154 150 if (status != DMUB_STATUS_OK) { 155 - DC_ERROR("Error queueing DMUB command: status=%d\n", status); 156 - dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 151 + if (status != DMUB_STATUS_POWER_STATE_D3) { 152 + DC_ERROR("Error queueing DMUB command: status=%d\n", status); 153 + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 154 + } 157 155 return false; 158 156 } 159 157 } 160 158 161 159 status = dmub_srv_cmd_execute(dmub); 162 160 if (status != DMUB_STATUS_OK) { 163 - DC_ERROR("Error starting DMUB execution: status=%d\n", status); 164 - dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 161 + if (status != DMUB_STATUS_POWER_STATE_D3) { 162 + DC_ERROR("Error starting DMUB execution: status=%d\n", status); 163 + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 164 + } 165 165 return false; 166 166 } 167 167 ··· 226 218 227 219 if (status == DMUB_STATUS_QUEUE_FULL) { 228 220 /* Execute and wait for queue to become empty again. */ 229 - dmub_srv_cmd_execute(dmub); 221 + status = dmub_srv_cmd_execute(dmub); 222 + if (status == DMUB_STATUS_POWER_STATE_D3) 223 + return false; 224 + 230 225 dmub_srv_wait_for_idle(dmub, 100000); 231 226 232 227 /* Requeue the command. */ ··· 237 226 } 238 227 239 228 if (status != DMUB_STATUS_OK) { 240 - DC_ERROR("Error queueing DMUB command: status=%d\n", status); 241 - dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 229 + if (status != DMUB_STATUS_POWER_STATE_D3) { 230 + DC_ERROR("Error queueing DMUB command: status=%d\n", status); 231 + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 232 + } 242 233 return false; 243 234 } 244 235 } 245 236 246 237 status = dmub_srv_cmd_execute(dmub); 247 238 if (status != DMUB_STATUS_OK) { 248 - DC_ERROR("Error starting DMUB execution: status=%d\n", status); 249 - dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 239 + if (status != DMUB_STATUS_POWER_STATE_D3) { 240 + DC_ERROR("Error starting DMUB execution: status=%d\n", status); 241 + dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); 242 + } 250 243 return false; 251 244 } 252 245 ··· 302 287 bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, 303 288 unsigned int stream_mask) 304 289 { 305 - struct dmub_srv *dmub; 306 - const uint32_t timeout = 30; 307 - 308 290 if (!dc_dmub_srv || !dc_dmub_srv->dmub) 309 291 return false; 310 292 311 - dmub = dc_dmub_srv->dmub; 312 - 313 - return dmub_srv_send_gpint_command( 314 - dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, 315 - stream_mask, timeout) == DMUB_STATUS_OK; 293 + return dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, 294 + stream_mask, NULL, DM_DMUB_WAIT_TYPE_WAIT); 316 295 } 317 296 318 297 bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv) ··· 355 346 cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header); 356 347 357 348 // Send the command to the DMCUB. 358 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 349 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 359 350 } 360 351 361 352 void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst) ··· 369 360 cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header); 370 361 371 362 // Send the command to the DMCUB. 372 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 363 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 373 364 } 374 365 375 366 static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream) ··· 462 453 sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header); 463 454 464 455 // Send the command to the DMCUB. 465 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 456 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 466 457 467 458 return true; 468 459 } ··· 483 474 cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data); 484 475 485 476 /* If command was processed, copy feature caps to dmub srv */ 486 - if (dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && 477 + if (dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && 487 478 cmd.query_feature_caps.header.ret_status == 0) { 488 479 memcpy(&dc_dmub_srv->dmub->feature_caps, 489 480 &cmd.query_feature_caps.query_feature_caps_data, ··· 508 499 cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst; 509 500 510 501 // If command was processed, copy feature caps to dmub srv 511 - if (dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && 502 + if (dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && 512 503 cmd.visual_confirm_color.header.ret_status == 0) { 513 504 memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color, 514 505 &cmd.visual_confirm_color.visual_confirm_color_data, ··· 519 510 /** 520 511 * populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command 521 512 * 522 - * @dc: [in] current dc state 513 + * @dc: [in] pointer to dc object 523 514 * @subvp_pipe: [in] pipe_ctx for the SubVP pipe 524 515 * @vblank_pipe: [in] pipe_ctx for the DRR pipe 525 516 * @pipe_data: [in] Pipe data which stores the VBLANK/DRR info 517 + * @context: [in] DC state for access to phantom stream 526 518 * 527 519 * Populate the DMCUB SubVP command with DRR pipe info. All the information 528 520 * required for calculating the SubVP + DRR microschedule is populated here. ··· 534 524 * 3. Populate the drr_info with the min and max supported vtotal values 535 525 */ 536 526 static void populate_subvp_cmd_drr_info(struct dc *dc, 527 + struct dc_state *context, 537 528 struct pipe_ctx *subvp_pipe, 538 529 struct pipe_ctx *vblank_pipe, 539 530 struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data) 540 531 { 532 + struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream); 541 533 struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing; 542 - struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; 534 + struct dc_crtc_timing *phantom_timing = &phantom_stream->timing; 543 535 struct dc_crtc_timing *drr_timing = &vblank_pipe->stream->timing; 544 536 uint16_t drr_frame_us = 0; 545 537 uint16_t min_drr_supported_us = 0; ··· 629 617 continue; 630 618 631 619 // Find the SubVP pipe 632 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) 620 + if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) 633 621 break; 634 622 } 635 623 ··· 646 634 647 635 if (vblank_pipe->stream->ignore_msa_timing_param && 648 636 (vblank_pipe->stream->allow_freesync || vblank_pipe->stream->vrr_active_variable || vblank_pipe->stream->vrr_active_fixed)) 649 - populate_subvp_cmd_drr_info(dc, pipe, vblank_pipe, pipe_data); 637 + populate_subvp_cmd_drr_info(dc, context, pipe, vblank_pipe, pipe_data); 650 638 } 651 639 652 640 /** ··· 671 659 uint32_t subvp0_prefetch_us = 0; 672 660 uint32_t subvp1_prefetch_us = 0; 673 661 uint32_t prefetch_delta_us = 0; 674 - struct dc_crtc_timing *phantom_timing0 = &subvp_pipes[0]->stream->mall_stream_config.paired_stream->timing; 675 - struct dc_crtc_timing *phantom_timing1 = &subvp_pipes[1]->stream->mall_stream_config.paired_stream->timing; 662 + struct dc_stream_state *phantom_stream0 = NULL; 663 + struct dc_stream_state *phantom_stream1 = NULL; 664 + struct dc_crtc_timing *phantom_timing0 = NULL; 665 + struct dc_crtc_timing *phantom_timing1 = NULL; 676 666 struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL; 667 + 668 + phantom_stream0 = dc_state_get_paired_subvp_stream(context, subvp_pipes[0]->stream); 669 + phantom_stream1 = dc_state_get_paired_subvp_stream(context, subvp_pipes[1]->stream); 670 + phantom_timing0 = &phantom_stream0->timing; 671 + phantom_timing1 = &phantom_stream1->timing; 677 672 678 673 subvp0_prefetch_us = div64_u64(((uint64_t)(phantom_timing0->v_total - phantom_timing0->v_front_porch) * 679 674 (uint64_t)phantom_timing0->h_total * 1000000), ··· 731 712 uint32_t j; 732 713 struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = 733 714 &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index]; 715 + struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream); 734 716 struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing; 735 - struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; 717 + struct dc_crtc_timing *phantom_timing = &phantom_stream->timing; 736 718 uint32_t out_num_stream, out_den_stream, out_num_plane, out_den_plane, out_num, out_den; 737 719 738 720 pipe_data->mode = SUBVP; ··· 787 767 for (j = 0; j < dc->res_pool->pipe_count; j++) { 788 768 struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j]; 789 769 790 - if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) { 770 + if (phantom_pipe->stream == dc_state_get_paired_subvp_stream(context, subvp_pipe->stream)) { 791 771 pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->stream_res.tg->inst; 792 772 if (phantom_pipe->bottom_pipe) { 793 773 pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->plane_res.hubp->inst; ··· 821 801 union dmub_rb_cmd cmd; 822 802 struct pipe_ctx *subvp_pipes[2]; 823 803 uint32_t wm_val_refclk = 0; 804 + enum mall_stream_type pipe_mall_type; 824 805 825 806 memset(&cmd, 0, sizeof(cmd)); 826 807 // FW command for SUBVP ··· 837 816 */ 838 817 if (resource_is_pipe_type(pipe, OTG_MASTER) && 839 818 resource_is_pipe_type(pipe, DPP_PIPE) && 840 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) 819 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) 841 820 subvp_pipes[subvp_count++] = pipe; 842 821 } 843 822 ··· 845 824 // For each pipe that is a "main" SUBVP pipe, fill in pipe data for DMUB SUBVP cmd 846 825 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { 847 826 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 827 + pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 848 828 849 829 if (!pipe->stream) 850 830 continue; ··· 856 834 */ 857 835 if (resource_is_pipe_type(pipe, OTG_MASTER) && 858 836 resource_is_pipe_type(pipe, DPP_PIPE) && 859 - pipe->stream->mall_stream_config.paired_stream && 860 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 837 + pipe_mall_type == SUBVP_MAIN) { 861 838 populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++); 862 839 } else if (resource_is_pipe_type(pipe, OTG_MASTER) && 863 840 resource_is_pipe_type(pipe, DPP_PIPE) && 864 - pipe->stream->mall_stream_config.type == SUBVP_NONE) { 841 + pipe_mall_type == SUBVP_NONE) { 865 842 // Don't need to check for ActiveDRAMClockChangeMargin < 0, not valid in cases where 866 843 // we run through DML without calculating "natural" P-state support 867 844 populate_subvp_cmd_vblank_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++); ··· 882 861 cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF; 883 862 } 884 863 885 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 864 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 886 865 } 887 866 888 867 bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data) ··· 1119 1098 pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp); 1120 1099 1121 1100 /* Combine 2nd cmds update_curosr_info to DMU */ 1122 - dm_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT); 1101 + dc_wake_and_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT); 1123 1102 } 1124 1103 } 1125 1104 ··· 1133 1112 void dc_dmub_srv_enable_dpia_trace(const struct dc *dc) 1134 1113 { 1135 1114 struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; 1136 - struct dmub_srv *dmub; 1137 - enum dmub_status status; 1138 - static const uint32_t timeout_us = 30; 1139 1115 1140 1116 if (!dc_dmub_srv || !dc_dmub_srv->dmub) { 1141 1117 DC_LOG_ERROR("%s: invalid parameters.", __func__); 1142 1118 return; 1143 1119 } 1144 1120 1145 - dmub = dc_dmub_srv->dmub; 1146 - 1147 - status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1, 0x0010, timeout_us); 1148 - if (status != DMUB_STATUS_OK) { 1121 + if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1, 1122 + 0x0010, NULL, DM_DMUB_WAIT_TYPE_WAIT)) { 1149 1123 DC_LOG_ERROR("timeout updating trace buffer mask word\n"); 1150 1124 return; 1151 1125 } 1152 1126 1153 - status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK, 0x0000, timeout_us); 1154 - if (status != DMUB_STATUS_OK) { 1127 + if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK, 1128 + 0x0000, NULL, DM_DMUB_WAIT_TYPE_WAIT)) { 1155 1129 DC_LOG_ERROR("timeout updating trace buffer mask word\n"); 1156 1130 return; 1157 1131 } ··· 1163 1147 { 1164 1148 struct dc_context *dc_ctx = dc_dmub_srv->ctx; 1165 1149 enum dmub_status status; 1150 + 1151 + if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1152 + return true; 1166 1153 1167 1154 if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation) 1168 1155 return true; ··· 1188 1169 return true; 1189 1170 } 1190 1171 1191 - void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) 1172 + static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) 1192 1173 { 1193 1174 union dmub_rb_cmd cmd = {0}; 1194 1175 ··· 1209 1190 dc->hwss.set_idle_state(dc, true); 1210 1191 } 1211 1192 1212 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 1193 + /* NOTE: This does not use the "wake" interface since this is part of the wake path. */ 1194 + /* We also do not perform a wait since DMCUB could enter idle after the notification. */ 1195 + dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 1213 1196 } 1214 1197 1215 - void dc_dmub_srv_exit_low_power_state(const struct dc *dc) 1198 + static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) 1216 1199 { 1217 - const uint32_t max_num_polls = 10000; 1218 1200 uint32_t allow_state = 0; 1219 1201 uint32_t commit_state = 0; 1220 - int i; 1221 1202 1222 1203 if (dc->debug.dmcub_emulation) 1223 1204 return; 1224 1205 1225 - if (!dc->idle_optimizations_allowed) 1206 + if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub) 1226 1207 return; 1227 1208 1228 1209 if (dc->hwss.get_idle_state && ··· 1234 1215 1235 1216 if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) { 1236 1217 // Wait for evaluation time 1237 - udelay(dc->debug.ips2_eval_delay_us); 1238 - commit_state = dc->hwss.get_idle_state(dc); 1218 + for (;;) { 1219 + udelay(dc->debug.ips2_eval_delay_us); 1220 + commit_state = dc->hwss.get_idle_state(dc); 1221 + if (commit_state & DMUB_IPS2_ALLOW_MASK) 1222 + break; 1223 + 1224 + /* allow was still set, retry eval delay */ 1225 + dc->hwss.set_idle_state(dc, false); 1226 + } 1227 + 1239 1228 if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) { 1240 1229 // Tell PMFW to exit low power state 1241 1230 dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); ··· 1252 1225 udelay(dc->debug.ips2_entry_delay_us); 1253 1226 dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); 1254 1227 1255 - for (i = 0; i < max_num_polls; ++i) { 1228 + for (;;) { 1256 1229 commit_state = dc->hwss.get_idle_state(dc); 1257 1230 if (commit_state & DMUB_IPS2_COMMIT_MASK) 1258 1231 break; 1259 1232 1260 1233 udelay(1); 1261 - 1262 - if (dc->debug.disable_timeout) 1263 - i--; 1264 1234 } 1265 - ASSERT(i < max_num_polls); 1266 1235 1267 1236 if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true)) 1268 1237 ASSERT(0); ··· 1273 1250 1274 1251 dc_dmub_srv_notify_idle(dc, false); 1275 1252 if (!(allow_state & DMUB_IPS1_ALLOW_MASK)) { 1276 - for (i = 0; i < max_num_polls; ++i) { 1253 + for (;;) { 1277 1254 commit_state = dc->hwss.get_idle_state(dc); 1278 1255 if (commit_state & DMUB_IPS1_COMMIT_MASK) 1279 1256 break; 1280 1257 1281 1258 udelay(1); 1282 - 1283 - if (dc->debug.disable_timeout) 1284 - i--; 1285 1259 } 1286 - ASSERT(i < max_num_polls); 1287 1260 } 1288 1261 } 1289 1262 ··· 1300 1281 dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D0); 1301 1282 else 1302 1283 dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3); 1284 + } 1285 + 1286 + void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle) 1287 + { 1288 + struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; 1289 + 1290 + if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1291 + return; 1292 + 1293 + if (dc_dmub_srv->idle_allowed == allow_idle) 1294 + return; 1295 + 1296 + /* 1297 + * Entering a low power state requires a driver notification. 1298 + * Powering up the hardware requires notifying PMFW and DMCUB. 1299 + * Clearing the driver idle allow requires a DMCUB command. 1300 + * DMCUB commands requires the DMCUB to be powered up and restored. 1301 + * 1302 + * Exit out early to prevent an infinite loop of DMCUB commands 1303 + * triggering exit low power - use software state to track this. 1304 + */ 1305 + dc_dmub_srv->idle_allowed = allow_idle; 1306 + 1307 + if (!allow_idle) 1308 + dc_dmub_srv_exit_low_power_state(dc); 1309 + else 1310 + dc_dmub_srv_notify_idle(dc, allow_idle); 1311 + } 1312 + 1313 + bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, 1314 + enum dm_dmub_wait_type wait_type) 1315 + { 1316 + return dc_wake_and_execute_dmub_cmd_list(ctx, 1, cmd, wait_type); 1317 + } 1318 + 1319 + bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, 1320 + union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type) 1321 + { 1322 + struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; 1323 + bool result = false, reallow_idle = false; 1324 + 1325 + if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1326 + return false; 1327 + 1328 + if (count == 0) 1329 + return true; 1330 + 1331 + if (dc_dmub_srv->idle_allowed) { 1332 + dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false); 1333 + reallow_idle = true; 1334 + } 1335 + 1336 + /* 1337 + * These may have different implementations in DM, so ensure 1338 + * that we guide it to the expected helper. 1339 + */ 1340 + if (count > 1) 1341 + result = dm_execute_dmub_cmd_list(ctx, count, cmd, wait_type); 1342 + else 1343 + result = dm_execute_dmub_cmd(ctx, cmd, wait_type); 1344 + 1345 + if (result && reallow_idle) 1346 + dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); 1347 + 1348 + return result; 1349 + } 1350 + 1351 + static bool dc_dmub_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, 1352 + uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type) 1353 + { 1354 + struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; 1355 + const uint32_t wait_us = wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT ? 0 : 30; 1356 + enum dmub_status status; 1357 + 1358 + if (response) 1359 + *response = 0; 1360 + 1361 + if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1362 + return false; 1363 + 1364 + status = dmub_srv_send_gpint_command(dc_dmub_srv->dmub, command_code, param, wait_us); 1365 + if (status != DMUB_STATUS_OK) { 1366 + if (status == DMUB_STATUS_TIMEOUT && wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT) 1367 + return true; 1368 + 1369 + return false; 1370 + } 1371 + 1372 + if (response && wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) 1373 + dmub_srv_get_gpint_response(dc_dmub_srv->dmub, response); 1374 + 1375 + return true; 1376 + } 1377 + 1378 + bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, 1379 + uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type) 1380 + { 1381 + struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; 1382 + bool result = false, reallow_idle = false; 1383 + 1384 + if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1385 + return false; 1386 + 1387 + if (dc_dmub_srv->idle_allowed) { 1388 + dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false); 1389 + reallow_idle = true; 1390 + } 1391 + 1392 + result = dc_dmub_execute_gpint(ctx, command_code, param, response, wait_type); 1393 + 1394 + if (result && reallow_idle) 1395 + dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); 1396 + 1397 + return result; 1303 1398 }
+55 -2
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
··· 50 50 51 51 struct dc_context *ctx; 52 52 void *dm; 53 + 54 + bool idle_allowed; 53 55 }; 54 56 55 57 void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv); ··· 102 100 void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index); 103 101 104 102 bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait); 105 - void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle); 106 - void dc_dmub_srv_exit_low_power_state(const struct dc *dc); 103 + 104 + void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle); 107 105 108 106 void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); 107 + 108 + /** 109 + * dc_wake_and_execute_dmub_cmd() - Wrapper for DMUB command execution. 110 + * 111 + * Refer to dc_wake_and_execute_dmub_cmd_list() for usage and limitations, 112 + * This function is a convenience wrapper for a single command execution. 113 + * 114 + * @ctx: DC context 115 + * @cmd: The command to send/receive 116 + * @wait_type: The wait behavior for the execution 117 + * 118 + * Return: true on command submission success, false otherwise 119 + */ 120 + bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, 121 + enum dm_dmub_wait_type wait_type); 122 + 123 + /** 124 + * dc_wake_and_execute_dmub_cmd_list() - Wrapper for DMUB command list execution. 125 + * 126 + * If the DMCUB hardware was asleep then it wakes the DMUB before 127 + * executing the command and attempts to re-enter if the command 128 + * submission was successful. 129 + * 130 + * This should be the preferred command submission interface provided 131 + * the DC lock is acquired. 132 + * 133 + * Entry/exit out of idle power optimizations would need to be 134 + * manually performed otherwise through dc_allow_idle_optimizations(). 135 + * 136 + * @ctx: DC context 137 + * @count: Number of commands to send/receive 138 + * @cmd: Array of commands to send 139 + * @wait_type: The wait behavior for the execution 140 + * 141 + * Return: true on command submission success, false otherwise 142 + */ 143 + bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, 144 + union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type); 145 + 146 + /** 147 + * dc_wake_and_execute_gpint() 148 + * 149 + * @ctx: DC context 150 + * @command_code: The command ID to send to DMCUB 151 + * @param: The parameter to message DMCUB 152 + * @response: Optional response out value - may be NULL. 153 + * @wait_type: The wait behavior for the execution 154 + */ 155 + bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, 156 + uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type); 157 + 109 158 #endif /* _DMUB_DC_SRV_H_ */
+6
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
··· 1377 1377 #ifndef DP_TUNNELING_STATUS 1378 1378 #define DP_TUNNELING_STATUS 0xE0025 /* 1.4a */ 1379 1379 #endif 1380 + #ifndef DP_TUNNELING_MAX_LINK_RATE 1381 + #define DP_TUNNELING_MAX_LINK_RATE 0xE0028 /* 1.4a */ 1382 + #endif 1383 + #ifndef DP_TUNNELING_MAX_LANE_COUNT 1384 + #define DP_TUNNELING_MAX_LANE_COUNT 0xE0029 /* 1.4a */ 1385 + #endif 1380 1386 #ifndef DPTX_BW_ALLOCATION_MODE_CONTROL 1381 1387 #define DPTX_BW_ALLOCATION_MODE_CONTROL 0xE0030 /* 1.4a */ 1382 1388 #endif
+3 -3
drivers/gpu/drm/amd/display/dc/dc_helper.c
··· 50 50 cmd_buf->header.payload_bytes = 51 51 sizeof(struct dmub_cmd_read_modify_write_sequence) * offload->reg_seq_count; 52 52 53 - dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 53 + dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 54 54 55 55 memset(cmd_buf, 0, sizeof(*cmd_buf)); 56 56 ··· 67 67 cmd_buf->header.payload_bytes = 68 68 sizeof(uint32_t) * offload->reg_seq_count; 69 69 70 - dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 70 + dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 71 71 72 72 memset(cmd_buf, 0, sizeof(*cmd_buf)); 73 73 ··· 80 80 { 81 81 struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait; 82 82 83 - dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 83 + dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); 84 84 85 85 memset(cmd_buf, 0, sizeof(*cmd_buf)); 86 86 offload->reg_seq_count = 0;
+1 -1
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
··· 244 244 #define DC_MAX_DIRTY_RECTS 3 245 245 struct dc_flip_addrs { 246 246 struct dc_plane_address address; 247 - unsigned int flip_timestamp_in_us; 247 + unsigned long long flip_timestamp_in_us; 248 248 bool flip_immediate; 249 249 /* TODO: add flip duration for FreeSync */ 250 250 bool triplebuffer_flips;
+38
drivers/gpu/drm/amd/display/dc/dc_plane.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef _DC_PLANE_H_ 27 + #define _DC_PLANE_H_ 28 + 29 + #include "dc.h" 30 + #include "dc_hw_types.h" 31 + 32 + struct dc_plane_state *dc_create_plane_state(struct dc *dc); 33 + const struct dc_plane_status *dc_plane_get_status( 34 + const struct dc_plane_state *plane_state); 35 + void dc_plane_state_retain(struct dc_plane_state *plane_state); 36 + void dc_plane_state_release(struct dc_plane_state *plane_state); 37 + 38 + #endif /* _DC_PLANE_H_ */
+34
drivers/gpu/drm/amd/display/dc/dc_plane_priv.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef _DC_PLANE_PRIV_H_ 27 + #define _DC_PLANE_PRIV_H_ 28 + 29 + #include "dc_plane.h" 30 + 31 + void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state); 32 + void dc_plane_destruct(struct dc_plane_state *plane_state); 33 + 34 + #endif /* _DC_PLANE_PRIV_H_ */
+78
drivers/gpu/drm/amd/display/dc/dc_state.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef _DC_STATE_H_ 27 + #define _DC_STATE_H_ 28 + 29 + #include "dc.h" 30 + #include "inc/core_status.h" 31 + 32 + struct dc_state *dc_state_create(struct dc *dc); 33 + void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state); 34 + struct dc_state *dc_state_create_copy(struct dc_state *src_state); 35 + void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state); 36 + struct dc_state *dc_state_create_current_copy(struct dc *dc); 37 + void dc_state_construct(struct dc *dc, struct dc_state *state); 38 + void dc_state_destruct(struct dc_state *state); 39 + void dc_state_retain(struct dc_state *state); 40 + void dc_state_release(struct dc_state *state); 41 + 42 + enum dc_status dc_state_add_stream(struct dc *dc, 43 + struct dc_state *state, 44 + struct dc_stream_state *stream); 45 + 46 + enum dc_status dc_state_remove_stream( 47 + struct dc *dc, 48 + struct dc_state *state, 49 + struct dc_stream_state *stream); 50 + 51 + bool dc_state_add_plane( 52 + const struct dc *dc, 53 + struct dc_stream_state *stream, 54 + struct dc_plane_state *plane_state, 55 + struct dc_state *state); 56 + 57 + bool dc_state_remove_plane( 58 + const struct dc *dc, 59 + struct dc_stream_state *stream, 60 + struct dc_plane_state *plane_state, 61 + struct dc_state *state); 62 + 63 + bool dc_state_rem_all_planes_for_stream( 64 + const struct dc *dc, 65 + struct dc_stream_state *stream, 66 + struct dc_state *state); 67 + 68 + bool dc_state_add_all_planes_for_stream( 69 + const struct dc *dc, 70 + struct dc_stream_state *stream, 71 + struct dc_plane_state * const *plane_states, 72 + int plane_count, 73 + struct dc_state *state); 74 + 75 + struct dc_stream_status *dc_state_get_stream_status( 76 + struct dc_state *state, 77 + struct dc_stream_state *stream); 78 + #endif /* _DC_STATE_H_ */
+102
drivers/gpu/drm/amd/display/dc/dc_state_priv.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef _DC_STATE_PRIV_H_ 27 + #define _DC_STATE_PRIV_H_ 28 + 29 + #include "dc_state.h" 30 + #include "dc_stream.h" 31 + 32 + /* Get the type of the provided resource (none, phantom, main) based on the provided 33 + * context. If the context is unavailable, determine only if phantom or not. 34 + */ 35 + enum mall_stream_type dc_state_get_pipe_subvp_type(const struct dc_state *state, 36 + const struct pipe_ctx *pipe_ctx); 37 + enum mall_stream_type dc_state_get_stream_subvp_type(const struct dc_state *state, 38 + const struct dc_stream_state *stream); 39 + 40 + /* Gets the phantom stream if main is provided, gets the main if phantom is provided.*/ 41 + struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state *state, 42 + const struct dc_stream_state *stream); 43 + 44 + /* allocate's phantom stream or plane and returns pointer to the object */ 45 + struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc, 46 + struct dc_state *state, 47 + struct dc_stream_state *main_stream); 48 + struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc, 49 + struct dc_state *state, 50 + struct dc_plane_state *main_plane); 51 + 52 + /* deallocate's phantom stream or plane */ 53 + void dc_state_release_phantom_stream(const struct dc *dc, 54 + struct dc_state *state, 55 + struct dc_stream_state *phantom_stream); 56 + void dc_state_release_phantom_plane(const struct dc *dc, 57 + struct dc_state *state, 58 + struct dc_plane_state *phantom_plane); 59 + 60 + /* add/remove phantom stream to context and generate subvp meta data */ 61 + enum dc_status dc_state_add_phantom_stream(struct dc *dc, 62 + struct dc_state *state, 63 + struct dc_stream_state *phantom_stream, 64 + struct dc_stream_state *main_stream); 65 + enum dc_status dc_state_remove_phantom_stream(struct dc *dc, 66 + struct dc_state *state, 67 + struct dc_stream_state *phantom_stream); 68 + 69 + bool dc_state_add_phantom_plane( 70 + const struct dc *dc, 71 + struct dc_stream_state *phantom_stream, 72 + struct dc_plane_state *phantom_plane, 73 + struct dc_state *state); 74 + 75 + bool dc_state_remove_phantom_plane( 76 + const struct dc *dc, 77 + struct dc_stream_state *phantom_stream, 78 + struct dc_plane_state *phantom_plane, 79 + struct dc_state *state); 80 + 81 + bool dc_state_rem_all_phantom_planes_for_stream( 82 + const struct dc *dc, 83 + struct dc_stream_state *phantom_stream, 84 + struct dc_state *state, 85 + bool should_release_planes); 86 + 87 + bool dc_state_add_all_phantom_planes_for_stream( 88 + const struct dc *dc, 89 + struct dc_stream_state *phantom_stream, 90 + struct dc_plane_state * const *phantom_planes, 91 + int plane_count, 92 + struct dc_state *state); 93 + 94 + bool dc_state_remove_phantom_streams_and_planes( 95 + struct dc *dc, 96 + struct dc_state *state); 97 + 98 + void dc_state_release_phantom_streams_and_planes( 99 + struct dc *dc, 100 + struct dc_state *state); 101 + 102 + #endif /* _DC_STATE_PRIV_H_ */
+10 -66
drivers/gpu/drm/amd/display/dc/dc_stream.h
··· 38 38 bool master; 39 39 }; 40 40 41 + struct mall_stream_config { 42 + /* MALL stream config to indicate if the stream is phantom or not. 43 + * We will use a phantom stream to indicate that the pipe is phantom. 44 + */ 45 + enum mall_stream_type type; 46 + struct dc_stream_state *paired_stream; // master / slave stream 47 + }; 48 + 41 49 struct dc_stream_status { 42 50 int primary_otg_inst; 43 51 int stream_enc_inst; ··· 58 50 struct timing_sync_info timing_sync_info; 59 51 struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; 60 52 bool is_abm_supported; 53 + struct mall_stream_config mall_stream_config; 61 54 }; 62 55 63 56 enum hubp_dmdata_mode { ··· 139 130 uint32_t wb_update:1; 140 131 uint32_t dsc_changed : 1; 141 132 uint32_t mst_bw : 1; 142 - uint32_t crtc_timing_adjust : 1; 143 133 uint32_t fams_changed : 1; 144 134 } bits; 145 135 ··· 154 146 }; 155 147 156 148 #define SUBVP_DRR_MARGIN_US 100 // 100us for DRR margin (SubVP + DRR) 157 - 158 - enum mall_stream_type { 159 - SUBVP_NONE, // subvp not in use 160 - SUBVP_MAIN, // subvp in use, this stream is main stream 161 - SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream 162 - }; 163 - 164 - struct mall_stream_config { 165 - /* MALL stream config to indicate if the stream is phantom or not. 166 - * We will use a phantom stream to indicate that the pipe is phantom. 167 - */ 168 - enum mall_stream_type type; 169 - struct dc_stream_state *paired_stream; // master / slave stream 170 - }; 171 - 172 - /* Temp struct used to save and restore MALL config 173 - * during validation. 174 - * 175 - * TODO: Move MALL config into dc_state instead of stream struct 176 - * to avoid needing to save/restore. 177 - */ 178 - struct mall_temp_config { 179 - struct mall_stream_config mall_stream_config[MAX_PIPES]; 180 - bool is_phantom_plane[MAX_PIPES]; 181 - }; 182 149 183 150 struct dc_stream_debug_options { 184 151 char force_odm_combine_segments; ··· 284 301 bool has_non_synchronizable_pclk; 285 302 bool vblank_synchronized; 286 303 bool fpo_in_use; 287 - struct mall_stream_config mall_stream_config; 304 + bool is_phantom; 288 305 }; 289 306 290 307 #define ABM_LEVEL_IMMEDIATE_DISABLE 255 ··· 325 342 struct dc_3dlut *lut3d_func; 326 343 327 344 struct test_pattern *pending_test_pattern; 328 - struct dc_crtc_timing_adjust *crtc_timing_adjust; 329 345 }; 330 346 331 347 bool dc_is_stream_unchanged( ··· 397 415 uint32_t *h_position, 398 416 uint32_t *v_position); 399 417 400 - enum dc_status dc_add_stream_to_ctx( 401 - struct dc *dc, 402 - struct dc_state *new_ctx, 403 - struct dc_stream_state *stream); 404 - 405 - enum dc_status dc_remove_stream_from_ctx( 406 - struct dc *dc, 407 - struct dc_state *new_ctx, 408 - struct dc_stream_state *stream); 409 - 410 - 411 - bool dc_add_plane_to_context( 412 - const struct dc *dc, 413 - struct dc_stream_state *stream, 414 - struct dc_plane_state *plane_state, 415 - struct dc_state *context); 416 - 417 - bool dc_remove_plane_from_context( 418 - const struct dc *dc, 419 - struct dc_stream_state *stream, 420 - struct dc_plane_state *plane_state, 421 - struct dc_state *context); 422 - 423 - bool dc_rem_all_planes_for_stream( 424 - const struct dc *dc, 425 - struct dc_stream_state *stream, 426 - struct dc_state *context); 427 - 428 - bool dc_add_all_planes_for_stream( 429 - const struct dc *dc, 430 - struct dc_stream_state *stream, 431 - struct dc_plane_state * const *plane_states, 432 - int plane_count, 433 - struct dc_state *context); 434 - 435 418 bool dc_stream_add_writeback(struct dc *dc, 436 419 struct dc_stream_state *stream, 437 420 struct dc_writeback_info *wb_info); ··· 465 518 void dc_stream_retain(struct dc_stream_state *dc_stream); 466 519 void dc_stream_release(struct dc_stream_state *dc_stream); 467 520 468 - struct dc_stream_status *dc_stream_get_status_from_state( 469 - struct dc_state *state, 470 - struct dc_stream_state *stream); 471 521 struct dc_stream_status *dc_stream_get_status( 472 522 struct dc_stream_state *dc_stream); 473 523
+37
drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef _DC_STREAM_PRIV_H_ 27 + #define _DC_STREAM_PRIV_H_ 28 + 29 + #include "dc_stream.h" 30 + 31 + bool dc_stream_construct(struct dc_stream_state *stream, 32 + struct dc_sink *dc_sink_data); 33 + void dc_stream_destruct(struct dc_stream_state *stream); 34 + 35 + void dc_stream_assign_stream_id(struct dc_stream_state *stream); 36 + 37 + #endif // _DC_STREAM_PRIV_H_
+7
drivers/gpu/drm/amd/display/dc/dc_types.h
··· 1151 1151 int bw_granularity; // BW Granularity 1152 1152 bool bw_alloc_enabled; // The BW Alloc Mode Support is turned ON for all 3: DP-Tx & Dpia & CM 1153 1153 bool response_ready; // Response ready from the CM side 1154 + uint8_t nrd_max_lane_count; // Non-reduced max lane count 1155 + uint8_t nrd_max_link_rate; // Non-reduced max link rate 1154 1156 }; 1155 1157 1156 1158 #define MAX_SINKS_PER_LINK 4 ··· 1163 1161 HPD_EN_FOR_SECONDARY_EDP_ONLY, 1164 1162 }; 1165 1163 1164 + enum mall_stream_type { 1165 + SUBVP_NONE, // subvp not in use 1166 + SUBVP_MAIN, // subvp in use, this stream is main stream 1167 + SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream 1168 + }; 1166 1169 #endif /* DC_TYPES_H_ */
+2 -2
drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
··· 135 135 0, 1, 80000); 136 136 } 137 137 138 - static void dce_abm_init(struct abm *abm, uint32_t backlight) 138 + static void dce_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level) 139 139 { 140 140 struct dce_abm *abm_dce = TO_DCE_ABM(abm); 141 141 ··· 162 162 BL1_PWM_TARGET_ABM_LEVEL, backlight); 163 163 164 164 REG_UPDATE(BL1_PWM_USER_LEVEL, 165 - BL1_PWM_USER_LEVEL, backlight); 165 + BL1_PWM_USER_LEVEL, user_level); 166 166 167 167 REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, 168 168 ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
+2 -2
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
··· 57 57 return ret; 58 58 } 59 59 60 - static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight) 60 + static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight, uint32_t user_level) 61 61 { 62 - dmub_abm_init(abm, backlight); 62 + dmub_abm_init(abm, backlight, user_level); 63 63 } 64 64 65 65 static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm)
+9 -9
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
··· 76 76 cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask; 77 77 cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); 78 78 79 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 79 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 80 80 } 81 81 82 - void dmub_abm_init(struct abm *abm, uint32_t backlight) 82 + void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level) 83 83 { 84 84 struct dce_abm *dce_abm = TO_DMUB_ABM(abm); 85 85 ··· 106 106 BL1_PWM_TARGET_ABM_LEVEL, backlight); 107 107 108 108 REG_UPDATE(BL1_PWM_USER_LEVEL, 109 - BL1_PWM_USER_LEVEL, backlight); 109 + BL1_PWM_USER_LEVEL, user_level); 110 110 111 111 REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, 112 112 ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, ··· 155 155 cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask; 156 156 cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); 157 157 158 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 158 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 159 159 160 160 return true; 161 161 } ··· 186 186 187 187 cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data); 188 188 189 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 189 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 190 190 191 191 } 192 192 ··· 203 203 cmd.abm_pause.abm_pause_data.panel_mask = panel_mask; 204 204 cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data); 205 205 206 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 206 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 207 207 208 208 return true; 209 209 } ··· 246 246 247 247 cmd.abm_save_restore.header.payload_bytes = sizeof(struct dmub_rb_cmd_abm_save_restore); 248 248 249 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 249 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 250 250 251 251 // Copy iramtable data into local structure 252 252 memcpy((void *)pData, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes); ··· 274 274 cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; 275 275 cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); 276 276 277 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 277 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 278 278 279 279 return true; 280 280 } ··· 296 296 cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst); 297 297 cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); 298 298 299 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 299 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 300 300 301 301 return true; 302 302 }
+1 -1
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h
··· 30 30 31 31 struct abm_save_restore; 32 32 33 - void dmub_abm_init(struct abm *abm, uint32_t backlight); 33 + void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level); 34 34 bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask); 35 35 unsigned int dmub_abm_get_current_backlight(struct abm *abm); 36 36 unsigned int dmub_abm_get_target_backlight(struct abm *abm);
+1 -1
drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
··· 47 47 if (!lock) 48 48 cmd.lock_hw.lock_hw_data.should_release = 1; 49 49 50 - dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 50 + dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 51 51 } 52 52 53 53 void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
+1 -1
drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c
··· 48 48 sizeof(cmd.outbox1_enable.header); 49 49 cmd.outbox1_enable.enable = true; 50 50 51 - dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 51 + dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 52 52 }
+13 -20
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
··· 105 105 */ 106 106 static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst) 107 107 { 108 - struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; 109 108 uint32_t raw_state = 0; 110 109 uint32_t retry_count = 0; 111 - enum dmub_status status; 112 110 113 111 do { 114 112 // Send gpint command and wait for ack 115 - status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30); 116 - 117 - if (status == DMUB_STATUS_OK) { 118 - // GPINT was executed, get response 119 - dmub_srv_get_gpint_response(srv, &raw_state); 113 + if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state, 114 + DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { 120 115 *state = convert_psr_state(raw_state); 121 - } else 116 + } else { 122 117 // Return invalid state when GPINT times out 123 118 *state = PSR_STATE_INVALID; 124 - 119 + } 125 120 } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID); 126 121 127 122 // Assert if max retry hit ··· 166 171 cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst; 167 172 cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); 168 173 169 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 174 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 170 175 171 176 return true; 172 177 } ··· 194 199 195 200 cmd.psr_enable.header.payload_bytes = 0; // Send header only 196 201 197 - dm_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 202 + dc_wake_and_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 198 203 199 204 /* Below loops 1000 x 500us = 500 ms. 200 205 * Exit PSR may need to wait 1-2 frames to power up. Timeout after at ··· 243 248 cmd.psr_set_level.psr_set_level_data.psr_level = psr_level; 244 249 cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; 245 250 cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst; 246 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 251 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 247 252 } 248 253 249 254 /* ··· 262 267 cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle; 263 268 cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su; 264 269 265 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 270 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 266 271 } 267 272 268 273 /* ··· 281 286 cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt; 282 287 cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst; 283 288 284 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 289 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 285 290 } 286 291 287 292 /* ··· 418 423 copy_settings_data->relock_delay_frame_cnt = 2; 419 424 copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; 420 425 421 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 426 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 422 427 423 428 return true; 424 429 } ··· 439 444 cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC; 440 445 cmd.psr_enable.header.payload_bytes = 0; 441 446 442 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 447 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 443 448 } 444 449 445 450 /* ··· 447 452 */ 448 453 static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst) 449 454 { 450 - struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; 451 455 uint16_t param = (uint16_t)(panel_inst << 8); 452 456 453 457 /* Send gpint command and wait for ack */ 454 - dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, param, 30); 455 - 456 - dmub_srv_get_gpint_response(srv, residency); 458 + dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency, 459 + DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 457 460 } 458 461 459 462 static const struct dmub_psr_funcs psr_funcs = {
+90 -6
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
··· 258 258 *residency = 0; 259 259 } 260 260 261 + /** 262 + * Set REPLAY power optimization flags and coasting vtotal. 263 + */ 264 + static void dmub_replay_set_power_opt_and_coasting_vtotal(struct dmub_replay *dmub, 265 + unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal) 266 + { 267 + union dmub_rb_cmd cmd; 268 + struct dc_context *dc = dmub->ctx; 269 + 270 + memset(&cmd, 0, sizeof(cmd)); 271 + cmd.replay_set_power_opt_and_coasting_vtotal.header.type = DMUB_CMD__REPLAY; 272 + cmd.replay_set_power_opt_and_coasting_vtotal.header.sub_type = 273 + DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL; 274 + cmd.replay_set_power_opt_and_coasting_vtotal.header.payload_bytes = 275 + sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal); 276 + cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.power_opt = power_opt; 277 + cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.panel_inst = panel_inst; 278 + cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal; 279 + 280 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 281 + } 282 + 283 + /** 284 + * send Replay general cmd to DMUB. 285 + */ 286 + static void dmub_replay_send_cmd(struct dmub_replay *dmub, 287 + enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element) 288 + { 289 + union dmub_rb_cmd cmd; 290 + struct dc_context *ctx = NULL; 291 + 292 + if (dmub == NULL || cmd_element == NULL) 293 + return; 294 + 295 + ctx = dmub->ctx; 296 + if (ctx != NULL) { 297 + 298 + if (msg != Replay_Msg_Not_Support) { 299 + memset(&cmd, 0, sizeof(cmd)); 300 + //Header 301 + cmd.replay_set_timing_sync.header.type = DMUB_CMD__REPLAY; 302 + } else 303 + return; 304 + } else 305 + return; 306 + 307 + switch (msg) { 308 + case Replay_Set_Timing_Sync_Supported: 309 + //Header 310 + cmd.replay_set_timing_sync.header.sub_type = 311 + DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED; 312 + cmd.replay_set_timing_sync.header.payload_bytes = 313 + sizeof(struct dmub_rb_cmd_replay_set_timing_sync); 314 + //Cmd Body 315 + cmd.replay_set_timing_sync.replay_set_timing_sync_data.panel_inst = 316 + cmd_element->sync_data.panel_inst; 317 + cmd.replay_set_timing_sync.replay_set_timing_sync_data.timing_sync_supported = 318 + cmd_element->sync_data.timing_sync_supported; 319 + break; 320 + case Replay_Set_Residency_Frameupdate_Timer: 321 + //Header 322 + cmd.replay_set_frameupdate_timer.header.sub_type = 323 + DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER; 324 + cmd.replay_set_frameupdate_timer.header.payload_bytes = 325 + sizeof(struct dmub_rb_cmd_replay_set_frameupdate_timer); 326 + //Cmd Body 327 + cmd.replay_set_frameupdate_timer.data.panel_inst = 328 + cmd_element->panel_inst; 329 + cmd.replay_set_frameupdate_timer.data.enable = 330 + cmd_element->timer_data.enable; 331 + cmd.replay_set_frameupdate_timer.data.frameupdate_count = 332 + cmd_element->timer_data.frameupdate_count; 333 + break; 334 + case Replay_Msg_Not_Support: 335 + default: 336 + return; 337 + break; 338 + } 339 + 340 + dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 341 + } 342 + 261 343 static const struct dmub_replay_funcs replay_funcs = { 262 - .replay_copy_settings = dmub_replay_copy_settings, 263 - .replay_enable = dmub_replay_enable, 264 - .replay_get_state = dmub_replay_get_state, 265 - .replay_set_power_opt = dmub_replay_set_power_opt, 266 - .replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal, 267 - .replay_residency = dmub_replay_residency, 344 + .replay_copy_settings = dmub_replay_copy_settings, 345 + .replay_enable = dmub_replay_enable, 346 + .replay_get_state = dmub_replay_get_state, 347 + .replay_set_power_opt = dmub_replay_set_power_opt, 348 + .replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal, 349 + .replay_residency = dmub_replay_residency, 350 + .replay_set_power_opt_and_coasting_vtotal = dmub_replay_set_power_opt_and_coasting_vtotal, 351 + .replay_send_cmd = dmub_replay_send_cmd, 268 352 }; 269 353 270 354 /*
+2
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
··· 51 51 uint8_t panel_inst); 52 52 void (*replay_residency)(struct dmub_replay *dmub, 53 53 uint8_t panel_inst, uint32_t *residency, const bool is_start, const bool is_alpm); 54 + void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub, 55 + unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal); 54 56 }; 55 57 56 58 struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
+1 -1
drivers/gpu/drm/amd/display/dc/dcn10/Makefile
··· 22 22 # 23 23 # Makefile for DCN. 24 24 25 - DCN10 = dcn10_init.o dcn10_ipp.o \ 25 + DCN10 = dcn10_ipp.o \ 26 26 dcn10_hw_sequencer_debug.o \ 27 27 dcn10_dpp.o dcn10_opp.o \ 28 28 dcn10_hubp.o dcn10_mpc.o \
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.h
+1 -1
drivers/gpu/drm/amd/display/dc/dcn20/Makefile
··· 2 2 # 3 3 # Makefile for DCN. 4 4 5 - DCN20 = dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ 5 + DCN20 = dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ 6 6 dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_mmhubbub.o \ 7 7 dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \ 8 8 dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.h
+1 -2
drivers/gpu/drm/amd/display/dc/dcn201/Makefile
··· 1 1 # SPDX-License-Identifier: MIT 2 2 # 3 3 # Makefile for DCN. 4 - DCN201 = dcn201_init.o \ 5 - dcn201_hubbub.o\ 4 + DCN201 = dcn201_hubbub.o\ 6 5 dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_dpp.o \ 7 6 dcn201_dccg.o dcn201_link_encoder.o 8 7
drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c
drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.h
+1 -1
drivers/gpu/drm/amd/display/dc/dcn21/Makefile
··· 2 2 # 3 3 # Makefile for DCN21. 4 4 5 - DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o \ 5 + DCN21 = dcn21_hubp.o dcn21_hubbub.o \ 6 6 dcn21_link_encoder.o dcn21_dccg.o 7 7 8 8 AMD_DAL_DCN21 = $(addprefix $(AMDDALPATH)/dc/dcn21/,$(DCN21))
+1 -1
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
··· 691 691 cmd.PLAT_54186_wa.flip.flip_params.vmid = flip_regs->vmid; 692 692 693 693 PERF_TRACE(); // TODO: remove after performance is stable. 694 - dm_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 694 + dc_wake_and_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 695 695 PERF_TRACE(); // TODO: remove after performance is stable. 696 696 } 697 697
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.h
+1 -3
drivers/gpu/drm/amd/display/dc/dcn30/Makefile
··· 23 23 # 24 24 # 25 25 26 - DCN30 := \ 27 - dcn30_init.o \ 28 - dcn30_hubbub.o \ 26 + DCN30 := dcn30_hubbub.o \ 29 27 dcn30_hubp.o \ 30 28 dcn30_dpp.o \ 31 29 dcn30_dccg.o \
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.h
+1 -1
drivers/gpu/drm/amd/display/dc/dcn301/Makefile
··· 10 10 # 11 11 # Makefile for dcn30. 12 12 13 - DCN301 = dcn301_init.o dcn301_dccg.o \ 13 + DCN301 = dcn301_dccg.o \ 14 14 dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o 15 15 16 16 AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.h
-12
drivers/gpu/drm/amd/display/dc/dcn302/Makefile
··· 1 - # 2 - # (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved 3 - # 4 - # Authors: AMD 5 - # 6 - # Makefile for dcn302. 7 - 8 - DCN3_02 = dcn302_init.o 9 - 10 - AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02)) 11 - 12 - AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_02)
drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_init.c
drivers/gpu/drm/amd/display/dc/dcn302/dcn302_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn302/dcn302_init.h
drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_init.c
drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_init.h
+1 -1
drivers/gpu/drm/amd/display/dc/dcn31/Makefile
··· 10 10 # 11 11 # Makefile for dcn31. 12 12 13 - DCN31 = dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \ 13 + DCN31 = dcn31_hubbub.o dcn31_hubp.o \ 14 14 dcn31_dccg.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ 15 15 dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ 16 16 dcn31_afmt.o dcn31_vpg.o
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.h
+2 -2
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c
··· 52 52 cmd->panel_cntl.header.payload_bytes = sizeof(cmd->panel_cntl.data); 53 53 cmd->panel_cntl.data.pwrseq_inst = dcn31_panel_cntl->base.pwrseq_inst; 54 54 55 - return dm_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 55 + return dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 56 56 } 57 57 58 58 static uint32_t dcn31_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) ··· 85 85 panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; 86 86 cmd.panel_cntl.data.bl_pwm_ref_div2 = 87 87 panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2; 88 - if (!dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 88 + if (!dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 89 89 return 0; 90 90 91 91 panel_cntl->stored_backlight_registers.BL_PWM_CNTL = cmd.panel_cntl.data.bl_pwm_cntl;
+1 -2
drivers/gpu/drm/amd/display/dc/dcn314/Makefile
··· 10 10 # 11 11 # Makefile for dcn314. 12 12 13 - DCN314 = dcn314_init.o \ 14 - dcn314_dio_stream_encoder.o dcn314_dccg.o 13 + DCN314 = dcn314_dio_stream_encoder.o dcn314_dccg.o 15 14 16 15 AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314)) 17 16
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.h
+1 -1
drivers/gpu/drm/amd/display/dc/dcn32/Makefile
··· 10 10 # 11 11 # Makefile for dcn32. 12 12 13 - DCN32 = dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \ 13 + DCN32 = dcn32_hubbub.o dcn32_dccg.o \ 14 14 dcn32_mmhubbub.o dcn32_dpp.o dcn32_hubp.o dcn32_mpc.o \ 15 15 dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_resource_helpers.o \ 16 16 dcn32_hpo_dp_link_encoder.o
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.h
+31 -95
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
··· 28 28 #include "dcn20/dcn20_resource.h" 29 29 #include "dml/dcn32/display_mode_vba_util_32.h" 30 30 #include "dml/dcn32/dcn32_fpu.h" 31 + #include "dc_state_priv.h" 31 32 32 33 static bool is_dual_plane(enum surface_pixel_format format) 33 34 { ··· 183 182 return true; 184 183 } 185 184 186 - bool dcn32_subvp_in_use(struct dc *dc, 187 - struct dc_state *context) 188 - { 189 - uint32_t i; 190 - 191 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 192 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 193 - 194 - if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) 195 - return true; 196 - } 197 - return false; 198 - } 199 - 200 185 bool dcn32_mpo_in_use(struct dc_state *context) 201 186 { 202 187 uint32_t i; ··· 251 264 252 265 // Do not override if a stream has multiple planes 253 266 for (i = 0; i < context->stream_count; i++) { 254 - if (context->stream_status[i].plane_count > 1) { 267 + if (context->stream_status[i].plane_count > 1) 255 268 return; 256 - } 257 - if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) { 269 + 270 + if (dc_state_get_stream_subvp_type(context, context->streams[i]) != SUBVP_PHANTOM) 258 271 stream_count++; 259 - } 260 272 } 261 273 262 274 for (i = 0; i < dc->res_pool->pipe_count; i++) { 263 275 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 264 276 265 - if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { 277 + if (pipe_ctx->stream && pipe_ctx->plane_state && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) { 266 278 if (dcn32_allow_subvp_high_refresh_rate(dc, context, pipe_ctx)) { 267 279 268 280 if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) { ··· 276 290 for (i = 0; i < dc->res_pool->pipe_count; i++) { 277 291 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 278 292 279 - if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { 293 + if (pipe_ctx->stream && pipe_ctx->plane_state && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) { 280 294 if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) { 281 295 if (pipe_segments[i] > 4) 282 296 pipe_segments[i] = 4; ··· 323 337 324 338 for (i = 0; i < context->stream_count; i++) { 325 339 /* Don't count SubVP streams for DET allocation */ 326 - if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) 340 + if (dc_state_get_stream_subvp_type(context, context->streams[i]) != SUBVP_PHANTOM) 327 341 stream_count++; 328 342 } 329 343 330 344 if (stream_count > 0) { 331 345 stream_segments = 18 / stream_count; 332 346 for (i = 0; i < context->stream_count; i++) { 333 - if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM) 347 + if (dc_state_get_stream_subvp_type(context, context->streams[i]) == SUBVP_PHANTOM) 334 348 continue; 335 349 336 350 if (context->stream_status[i].plane_count > 0) ··· 414 428 } 415 429 } else 416 430 dcn32_determine_det_override(dc, context, pipes); 417 - } 418 - 419 - /** 420 - * dcn32_save_mall_state(): Save MALL (SubVP) state for fast validation cases 421 - * 422 - * This function saves the MALL (SubVP) case for fast validation cases. For fast validation, 423 - * there are situations where a shallow copy of the dc->current_state is created for the 424 - * validation. In this case we want to save and restore the mall config because we always 425 - * teardown subvp at the beginning of validation (and don't attempt to add it back if it's 426 - * fast validation). If we don't restore the subvp config in cases of fast validation + 427 - * shallow copy of the dc->current_state, the dc->current_state will have a partially 428 - * removed subvp state when we did not intend to remove it. 429 - * 430 - * NOTE: This function ONLY works if the streams are not moved to a different pipe in the 431 - * validation. We don't expect this to happen in fast_validation=1 cases. 432 - * 433 - * @dc: Current DC state 434 - * @context: New DC state to be programmed 435 - * @temp_config: struct used to cache the existing MALL state 436 - * 437 - * Return: void 438 - */ 439 - void dcn32_save_mall_state(struct dc *dc, 440 - struct dc_state *context, 441 - struct mall_temp_config *temp_config) 442 - { 443 - uint32_t i; 444 - 445 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 446 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 447 - 448 - if (pipe->stream) 449 - temp_config->mall_stream_config[i] = pipe->stream->mall_stream_config; 450 - 451 - if (pipe->plane_state) 452 - temp_config->is_phantom_plane[i] = pipe->plane_state->is_phantom; 453 - } 454 - } 455 - 456 - /** 457 - * dcn32_restore_mall_state(): Restore MALL (SubVP) state for fast validation cases 458 - * 459 - * Restore the MALL state based on the previously saved state from dcn32_save_mall_state 460 - * 461 - * @dc: Current DC state 462 - * @context: New DC state to be programmed, restore MALL state into here 463 - * @temp_config: struct that has the cached MALL state 464 - * 465 - * Return: void 466 - */ 467 - void dcn32_restore_mall_state(struct dc *dc, 468 - struct dc_state *context, 469 - struct mall_temp_config *temp_config) 470 - { 471 - uint32_t i; 472 - 473 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 474 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 475 - 476 - if (pipe->stream) 477 - pipe->stream->mall_stream_config = temp_config->mall_stream_config[i]; 478 - 479 - if (pipe->plane_state) 480 - pipe->plane_state->is_phantom = temp_config->is_phantom_plane[i]; 481 - } 482 431 } 483 432 484 433 #define MAX_STRETCHED_V_BLANK 1000 // in micro-seconds (must ensure to match value in FW) ··· 510 589 * 511 590 * Return: Pointer to FPO stream candidate if config can support FPO, otherwise NULL 512 591 */ 513 - struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context) 592 + struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) 514 593 { 515 594 int refresh_rate = 0; 516 595 const int minimum_refreshrate_supported = 120; 517 596 struct dc_stream_state *fpo_candidate_stream = NULL; 518 597 bool is_fpo_vactive = false; 519 598 uint32_t fpo_vactive_margin_us = 0; 599 + struct dc_stream_status *fpo_stream_status = NULL; 520 600 521 601 if (context == NULL) 522 602 return NULL; ··· 540 618 DC_FP_START(); 541 619 dcn32_assign_fpo_vactive_candidate(dc, context, &fpo_candidate_stream); 542 620 DC_FP_END(); 543 - 621 + if (fpo_candidate_stream) 622 + fpo_stream_status = dc_state_get_stream_status(context, fpo_candidate_stream); 544 623 DC_FP_START(); 545 624 is_fpo_vactive = dcn32_find_vactive_pipe(dc, context, dc->debug.fpo_vactive_min_active_margin_us); 546 625 DC_FP_END(); 547 626 if (!is_fpo_vactive || dc->debug.disable_fpo_vactive) 548 627 return NULL; 549 - } else 628 + } else { 550 629 fpo_candidate_stream = context->streams[0]; 630 + if (fpo_candidate_stream) 631 + fpo_stream_status = dc_state_get_stream_status(context, fpo_candidate_stream); 632 + } 551 633 552 - if (!fpo_candidate_stream) 634 + /* In DCN32/321, FPO uses per-pipe P-State force. 635 + * If there's no planes, HUBP is power gated and 636 + * therefore programming UCLK_PSTATE_FORCE does 637 + * nothing (P-State will always be asserted naturally 638 + * on a pipe that has HUBP power gated. Therefore we 639 + * only want to enable FPO if the FPO pipe has both 640 + * a stream and a plane. 641 + */ 642 + if (!fpo_candidate_stream || !fpo_stream_status || fpo_stream_status->plane_count == 0) 553 643 return NULL; 554 644 555 645 if (fpo_candidate_stream->sink->edid_caps.panel_patch.disable_fams) ··· 650 716 651 717 for (i = 0; i < dc->res_pool->pipe_count; i++) { 652 718 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 719 + enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 653 720 654 721 if (resource_is_pipe_type(pipe, OPP_HEAD) && 655 722 resource_is_pipe_type(pipe, DPP_PIPE)) { 656 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 723 + if (pipe_mall_type == SUBVP_MAIN) { 657 724 subvp_count++; 658 725 659 726 subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe); ··· 663 728 refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); 664 729 refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total); 665 730 } 666 - if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { 731 + if (pipe_mall_type == SUBVP_NONE) { 667 732 non_subvp_pipes++; 668 733 drr_psr_capable = (drr_psr_capable || dcn32_is_psr_capable(pipe)); 669 734 if (pipe->stream->ignore_msa_timing_param && ··· 711 776 712 777 for (i = 0; i < dc->res_pool->pipe_count; i++) { 713 778 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 779 + enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 714 780 715 781 if (resource_is_pipe_type(pipe, OPP_HEAD) && 716 782 resource_is_pipe_type(pipe, DPP_PIPE)) { 717 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 783 + if (pipe_mall_type == SUBVP_MAIN) { 718 784 subvp_count++; 719 785 720 786 subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe); ··· 724 788 refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); 725 789 refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total); 726 790 } 727 - if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { 791 + if (pipe_mall_type == SUBVP_NONE) { 728 792 non_subvp_pipes++; 729 793 vblank_psr_capable = (vblank_psr_capable || dcn32_is_psr_capable(pipe)); 730 794 if (pipe->stream->ignore_msa_timing_param &&
+1 -1
drivers/gpu/drm/amd/display/dc/dcn35/Makefile
··· 10 10 # 11 11 # Makefile for DCN35. 12 12 13 - DCN35 = dcn35_init.o dcn35_dio_stream_encoder.o \ 13 + DCN35 = dcn35_dio_stream_encoder.o \ 14 14 dcn35_dio_link_encoder.o dcn35_dccg.o \ 15 15 dcn35_hubp.o dcn35_hubbub.o \ 16 16 dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o
+6 -7
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
··· 1 - /* SPDX-License-Identifier: MIT */ 2 1 /* 3 2 * Copyright 2023 Advanced Micro Devices, Inc. 4 3 * ··· 33 34 #include "dcn32/dcn32_hwseq.h" 34 35 #include "dcn35/dcn35_hwseq.h" 35 36 36 - #include "dcn35_init.h" 37 + #include "dcn351_init.h" 37 38 38 - static const struct hw_sequencer_funcs dcn35_funcs = { 39 + static const struct hw_sequencer_funcs dcn351_funcs = { 39 40 .program_gamut_remap = dcn30_program_gamut_remap, 40 41 .init_hw = dcn35_init_hw, 41 42 .power_down_on_boot = dcn35_power_down_on_boot, ··· 124 125 .get_idle_state = dcn35_get_idle_state 125 126 }; 126 127 127 - static const struct hwseq_private_funcs dcn35_private_funcs = { 128 + static const struct hwseq_private_funcs dcn351_private_funcs = { 128 129 .init_pipes = dcn35_init_pipes, 129 130 .update_plane_addr = dcn20_update_plane_addr, 130 131 .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, ··· 163 164 .enable_plane = dcn35_enable_plane, 164 165 }; 165 166 166 - void dcn35_hw_sequencer_construct(struct dc *dc) 167 + void dcn351_hw_sequencer_construct(struct dc *dc) 167 168 { 168 - dc->hwss = dcn35_funcs; 169 - dc->hwseq->funcs = dcn35_private_funcs; 169 + dc->hwss = dcn351_funcs; 170 + dc->hwseq->funcs = dcn351_private_funcs; 170 171 171 172 }
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.h drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.h
+112 -3
drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
··· 33 33 34 34 #include "link.h" 35 35 #include "dcn20_fpu.h" 36 + #include "dc_state_priv.h" 36 37 37 38 #define DC_LOGGER \ 38 39 dc->ctx->logger ··· 441 440 .use_urgent_burst_bw = 0 442 441 }; 443 442 444 - struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; 443 + struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 444 + .clock_limits = { 445 + { 446 + .state = 0, 447 + .dcfclk_mhz = 560.0, 448 + .fabricclk_mhz = 560.0, 449 + .dispclk_mhz = 513.0, 450 + .dppclk_mhz = 513.0, 451 + .phyclk_mhz = 540.0, 452 + .socclk_mhz = 560.0, 453 + .dscclk_mhz = 171.0, 454 + .dram_speed_mts = 1069.0, 455 + }, 456 + { 457 + .state = 1, 458 + .dcfclk_mhz = 694.0, 459 + .fabricclk_mhz = 694.0, 460 + .dispclk_mhz = 642.0, 461 + .dppclk_mhz = 642.0, 462 + .phyclk_mhz = 600.0, 463 + .socclk_mhz = 694.0, 464 + .dscclk_mhz = 214.0, 465 + .dram_speed_mts = 1324.0, 466 + }, 467 + { 468 + .state = 2, 469 + .dcfclk_mhz = 875.0, 470 + .fabricclk_mhz = 875.0, 471 + .dispclk_mhz = 734.0, 472 + .dppclk_mhz = 734.0, 473 + .phyclk_mhz = 810.0, 474 + .socclk_mhz = 875.0, 475 + .dscclk_mhz = 245.0, 476 + .dram_speed_mts = 1670.0, 477 + }, 478 + { 479 + .state = 3, 480 + .dcfclk_mhz = 1000.0, 481 + .fabricclk_mhz = 1000.0, 482 + .dispclk_mhz = 1100.0, 483 + .dppclk_mhz = 1100.0, 484 + .phyclk_mhz = 810.0, 485 + .socclk_mhz = 1000.0, 486 + .dscclk_mhz = 367.0, 487 + .dram_speed_mts = 2000.0, 488 + }, 489 + { 490 + .state = 4, 491 + .dcfclk_mhz = 1200.0, 492 + .fabricclk_mhz = 1200.0, 493 + .dispclk_mhz = 1284.0, 494 + .dppclk_mhz = 1284.0, 495 + .phyclk_mhz = 810.0, 496 + .socclk_mhz = 1200.0, 497 + .dscclk_mhz = 428.0, 498 + .dram_speed_mts = 2000.0, 499 + }, 500 + { 501 + .state = 5, 502 + .dcfclk_mhz = 1200.0, 503 + .fabricclk_mhz = 1200.0, 504 + .dispclk_mhz = 1284.0, 505 + .dppclk_mhz = 1284.0, 506 + .phyclk_mhz = 810.0, 507 + .socclk_mhz = 1200.0, 508 + .dscclk_mhz = 428.0, 509 + .dram_speed_mts = 2000.0, 510 + }, 511 + }, 512 + 513 + .num_states = 5, 514 + .sr_exit_time_us = 1.9, 515 + .sr_enter_plus_exit_time_us = 4.4, 516 + .urgent_latency_us = 3.0, 517 + .urgent_latency_pixel_data_only_us = 4.0, 518 + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, 519 + .urgent_latency_vm_data_only_us = 4.0, 520 + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, 521 + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, 522 + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, 523 + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, 524 + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, 525 + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, 526 + .max_avg_sdp_bw_use_normal_percent = 40.0, 527 + .max_avg_dram_bw_use_normal_percent = 40.0, 528 + .writeback_latency_us = 12.0, 529 + .ideal_dram_bw_after_urgent_percent = 40.0, 530 + .max_request_size_bytes = 256, 531 + .dram_channel_width_bytes = 16, 532 + .fabric_datapath_to_dcn_data_return_bytes = 64, 533 + .dcn_downspread_percent = 0.5, 534 + .downspread_percent = 0.5, 535 + .dram_page_open_time_ns = 50.0, 536 + .dram_rw_turnaround_time_ns = 17.5, 537 + .dram_return_buffer_per_channel_bytes = 8192, 538 + .round_trip_ping_latency_dcfclk_cycles = 131, 539 + .urgent_out_of_order_return_per_channel_bytes = 4096, 540 + .channel_interleave_bytes = 256, 541 + .num_banks = 8, 542 + .num_chans = 16, 543 + .vmm_page_size_bytes = 4096, 544 + .dram_clock_change_latency_us = 45.0, 545 + .writeback_dram_clock_change_latency_us = 23.0, 546 + .return_bus_width_bytes = 64, 547 + .dispclk_dppclk_vco_speed_mhz = 3850, 548 + .xfc_bus_transport_time_us = 20, 549 + .xfc_xbuf_latency_tolerance_us = 50, 550 + .use_urgent_burst_bw = 0, 551 + }; 445 552 446 553 struct _vcs_dpi_ip_params_st dcn2_1_ip = { 447 554 .odm_capable = 1, ··· 1183 1074 pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); 1184 1075 pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); 1185 1076 1186 - if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) { 1077 + if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) { 1187 1078 // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests 1188 1079 context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0; 1189 1080 context->res_ctx.pipe_ctx[i].unbounded_req = false; ··· 1533 1424 */ 1534 1425 if (res_ctx->pipe_ctx[i].plane_state && 1535 1426 (res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE || 1536 - res_ctx->pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM)) 1427 + dc_state_get_pipe_subvp_type(context, &res_ctx->pipe_ctx[i]) == SUBVP_PHANTOM)) 1537 1428 pipes[pipe_cnt].pipe.src.num_cursors = 0; 1538 1429 else 1539 1430 pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors;
+72 -46
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
··· 32 32 #include "clk_mgr/dcn32/dcn32_smu13_driver_if.h" 33 33 #include "dcn30/dcn30_resource.h" 34 34 #include "link.h" 35 + #include "dc_state_priv.h" 36 + #include "resource.h" 35 37 36 38 #define DC_LOGGER_INIT(logger) 37 39 ··· 292 290 293 291 /* for subvp + DRR case, if subvp pipes are still present we support pstate */ 294 292 if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported && 295 - dcn32_subvp_in_use(dc, context)) 293 + resource_subvp_in_use(dc, context)) 296 294 vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = temp_clock_change_support; 297 295 298 296 if (vlevel < context->bw_ctx.dml.vba.soc.num_states && ··· 343 341 if (!pipe->stream) 344 342 continue; 345 343 346 - if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 344 + if (pipe->plane_state && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 347 345 pipes[pipe_idx].pipe.dest.vstartup_start = 348 346 get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); 349 347 pipes[pipe_idx].pipe.dest.vupdate_offset = ··· 626 624 if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && 627 625 !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && 628 626 (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && 629 - pipe->stream->mall_stream_config.type == SUBVP_NONE && 627 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && 630 628 (refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) && 631 629 !pipe->plane_state->address.tmz_surface && 632 630 (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 || ··· 684 682 685 683 // Find the minimum pipe split count for non SubVP pipes 686 684 if (resource_is_pipe_type(pipe, OPP_HEAD) && 687 - pipe->stream->mall_stream_config.type == SUBVP_NONE) { 685 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE) { 688 686 split_cnt = 0; 689 687 while (pipe) { 690 688 split_cnt++; ··· 737 735 * and also to store the two main SubVP pipe pointers in subvp_pipes[2]. 738 736 */ 739 737 if (pipe->stream && pipe->plane_state && !pipe->top_pipe && 740 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 741 - phantom = pipe->stream->mall_stream_config.paired_stream; 738 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { 739 + phantom = dc_state_get_paired_subvp_stream(context, pipe->stream); 742 740 microschedule_lines = (phantom->timing.v_total - phantom->timing.v_front_porch) + 743 741 phantom->timing.v_addressable; 744 742 ··· 806 804 int16_t stretched_drr_us = 0; 807 805 int16_t drr_stretched_vblank_us = 0; 808 806 int16_t max_vblank_mallregion = 0; 807 + struct dc_stream_state *phantom_stream; 808 + bool subvp_found = false; 809 + bool drr_found = false; 809 810 810 811 // Find SubVP pipe 811 812 for (i = 0; i < dc->res_pool->pipe_count; i++) { ··· 821 816 continue; 822 817 823 818 // Find the SubVP pipe 824 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) 819 + if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { 820 + subvp_found = true; 825 821 break; 822 + } 826 823 } 827 824 828 825 // Find the DRR pipe ··· 832 825 drr_pipe = &context->res_ctx.pipe_ctx[i]; 833 826 834 827 // We check for master pipe only 835 - if (!resource_is_pipe_type(pipe, OTG_MASTER) || 836 - !resource_is_pipe_type(pipe, DPP_PIPE)) 828 + if (!resource_is_pipe_type(drr_pipe, OTG_MASTER) || 829 + !resource_is_pipe_type(drr_pipe, DPP_PIPE)) 837 830 continue; 838 831 839 - if (drr_pipe->stream->mall_stream_config.type == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param && 840 - (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable || drr_pipe->stream->vrr_active_fixed)) 832 + if (dc_state_get_pipe_subvp_type(context, drr_pipe) == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param && 833 + (drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable || drr_pipe->stream->vrr_active_fixed)) { 834 + drr_found = true; 841 835 break; 836 + } 842 837 } 843 838 844 - main_timing = &pipe->stream->timing; 845 - phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing; 846 - drr_timing = &drr_pipe->stream->timing; 847 - prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total / 848 - (double)(phantom_timing->pix_clk_100hz * 100) * 1000000 + 849 - dc->caps.subvp_prefetch_end_to_mall_start_us; 850 - subvp_active_us = main_timing->v_addressable * main_timing->h_total / 851 - (double)(main_timing->pix_clk_100hz * 100) * 1000000; 852 - drr_frame_us = drr_timing->v_total * drr_timing->h_total / 853 - (double)(drr_timing->pix_clk_100hz * 100) * 1000000; 854 - // P-State allow width and FW delays already included phantom_timing->v_addressable 855 - mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total / 856 - (double)(phantom_timing->pix_clk_100hz * 100) * 1000000; 857 - stretched_drr_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US; 858 - drr_stretched_vblank_us = (drr_timing->v_total - drr_timing->v_addressable) * drr_timing->h_total / 859 - (double)(drr_timing->pix_clk_100hz * 100) * 1000000 + (stretched_drr_us - drr_frame_us); 860 - max_vblank_mallregion = drr_stretched_vblank_us > mall_region_us ? drr_stretched_vblank_us : mall_region_us; 839 + if (subvp_found && drr_found) { 840 + phantom_stream = dc_state_get_paired_subvp_stream(context, pipe->stream); 841 + main_timing = &pipe->stream->timing; 842 + phantom_timing = &phantom_stream->timing; 843 + drr_timing = &drr_pipe->stream->timing; 844 + prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total / 845 + (double)(phantom_timing->pix_clk_100hz * 100) * 1000000 + 846 + dc->caps.subvp_prefetch_end_to_mall_start_us; 847 + subvp_active_us = main_timing->v_addressable * main_timing->h_total / 848 + (double)(main_timing->pix_clk_100hz * 100) * 1000000; 849 + drr_frame_us = drr_timing->v_total * drr_timing->h_total / 850 + (double)(drr_timing->pix_clk_100hz * 100) * 1000000; 851 + // P-State allow width and FW delays already included phantom_timing->v_addressable 852 + mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total / 853 + (double)(phantom_timing->pix_clk_100hz * 100) * 1000000; 854 + stretched_drr_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US; 855 + drr_stretched_vblank_us = (drr_timing->v_total - drr_timing->v_addressable) * drr_timing->h_total / 856 + (double)(drr_timing->pix_clk_100hz * 100) * 1000000 + (stretched_drr_us - drr_frame_us); 857 + max_vblank_mallregion = drr_stretched_vblank_us > mall_region_us ? drr_stretched_vblank_us : mall_region_us; 858 + } 861 859 862 860 /* We consider SubVP + DRR schedulable if the stretched frame duration of the DRR display (i.e. the 863 861 * highest refresh rate + margin that can support UCLK P-State switch) passes the static analysis ··· 907 895 struct dc_crtc_timing *main_timing = NULL; 908 896 struct dc_crtc_timing *phantom_timing = NULL; 909 897 struct dc_crtc_timing *vblank_timing = NULL; 898 + struct dc_stream_state *phantom_stream; 899 + enum mall_stream_type pipe_mall_type; 910 900 911 901 /* For SubVP + VBLANK/DRR cases, we assume there can only be 912 902 * a single VBLANK/DRR display. If DML outputs SubVP + VBLANK ··· 918 904 */ 919 905 for (i = 0; i < dc->res_pool->pipe_count; i++) { 920 906 pipe = &context->res_ctx.pipe_ctx[i]; 907 + pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 921 908 922 909 // We check for master pipe, but it shouldn't matter since we only need 923 910 // the pipe for timing info (stream should be same for any pipe splits) ··· 926 911 !resource_is_pipe_type(pipe, DPP_PIPE)) 927 912 continue; 928 913 929 - if (!found && pipe->stream->mall_stream_config.type == SUBVP_NONE) { 914 + if (!found && pipe_mall_type == SUBVP_NONE) { 930 915 // Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe). 931 916 vblank_index = i; 932 917 found = true; 933 918 } 934 919 935 - if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) 920 + if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN) 936 921 subvp_pipe = pipe; 937 922 } 938 923 if (found) { 924 + phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream); 939 925 main_timing = &subvp_pipe->stream->timing; 940 - phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; 926 + phantom_timing = &phantom_stream->timing; 941 927 vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing; 942 928 // Prefetch time is equal to VACTIVE + BP + VSYNC of the phantom pipe 943 929 // Also include the prefetch end to mallstart delay time ··· 993 977 continue; 994 978 995 979 if (pipe->plane_state && !pipe->top_pipe && 996 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 980 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { 997 981 refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 + 998 982 pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1); 999 983 refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); ··· 1042 1026 1043 1027 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { 1044 1028 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1029 + enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 1045 1030 1046 1031 if (!pipe->stream) 1047 1032 continue; 1048 1033 1049 1034 if (pipe->plane_state && !pipe->top_pipe) { 1050 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) 1035 + if (pipe_mall_type == SUBVP_MAIN) 1051 1036 subvp_count++; 1052 - if (pipe->stream->mall_stream_config.type == SUBVP_NONE) { 1037 + if (pipe_mall_type == SUBVP_NONE) 1053 1038 non_subvp_pipes++; 1054 - } 1055 1039 } 1056 1040 1057 1041 // Count how many planes that aren't SubVP/phantom are capable of VACTIVE 1058 1042 // switching (SubVP + VACTIVE unsupported). In situations where we force 1059 1043 // SubVP for a VACTIVE plane, we don't want to increment the vactive_count. 1060 1044 if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vlevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 && 1061 - pipe->stream->mall_stream_config.type == SUBVP_NONE) { 1045 + pipe_mall_type == SUBVP_NONE) { 1062 1046 vactive_count++; 1063 1047 } 1064 1048 pipe_idx++; ··· 1094 1078 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1095 1079 1096 1080 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && 1097 - pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) { 1081 + dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) { 1098 1082 pipe_ctx->subvp_index = index++; 1099 1083 } else { 1100 1084 pipe_ctx->subvp_index = 0; ··· 1548 1532 // If SubVP pipe config is unsupported (or cannot be used for UCLK switching) 1549 1533 // remove phantom pipes and repopulate dml pipes 1550 1534 if (!found_supported_config) { 1551 - dc->res_pool->funcs->remove_phantom_pipes(dc, context, false); 1535 + dc_state_remove_phantom_streams_and_planes(dc, context); 1536 + dc_state_release_phantom_streams_and_planes(dc, context); 1552 1537 vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported; 1553 1538 *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false); 1554 1539 ··· 1701 1684 pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, 1702 1685 pipe_idx); 1703 1686 1704 - if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) { 1687 + if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) { 1705 1688 // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests 1706 1689 context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0; 1707 1690 context->res_ctx.pipe_ctx[i].unbounded_req = false; ··· 1733 1716 context->res_ctx.pipe_ctx[i].plane_state != context->res_ctx.pipe_ctx[i].top_pipe->plane_state) && 1734 1717 context->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { 1735 1718 /* SS: all active surfaces stored in MALL */ 1736 - if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type != SUBVP_PHANTOM) { 1719 + if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) != SUBVP_PHANTOM) { 1737 1720 context->bw_ctx.bw.dcn.mall_ss_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; 1738 1721 1739 1722 if (context->res_ctx.pipe_ctx[i].stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) { ··· 1947 1930 return false; 1948 1931 1949 1932 // For each full update, remove all existing phantom pipes first 1950 - dc->res_pool->funcs->remove_phantom_pipes(dc, context, fast_validate); 1933 + dc_state_remove_phantom_streams_and_planes(dc, context); 1934 + dc_state_release_phantom_streams_and_planes(dc, context); 1951 1935 1952 1936 dc->res_pool->funcs->update_soc_for_wm_a(dc, context); 1953 1937 ··· 2273 2255 unsigned int dummy_latency_index = 0; 2274 2256 int maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; 2275 2257 unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed; 2276 - bool subvp_in_use = dcn32_subvp_in_use(dc, context); 2258 + bool subvp_active = resource_subvp_in_use(dc, context); 2277 2259 unsigned int min_dram_speed_mts_margin; 2278 2260 bool need_fclk_lat_as_dummy = false; 2279 2261 bool is_subvp_p_drr = false; ··· 2282 2264 dc_assert_fp_enabled(); 2283 2265 2284 2266 /* need to find dummy latency index for subvp */ 2285 - if (subvp_in_use) { 2267 + if (subvp_active) { 2286 2268 /* Override DRAMClockChangeSupport for SubVP + DRR case where the DRR cannot switch without stretching it's VBLANK */ 2287 2269 if (!pstate_en) { 2288 2270 context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; ··· 2468 2450 dc->clk_mgr->bw_params->clk_table.entries[min_dram_speed_mts_offset].memclk_mhz * 16; 2469 2451 } 2470 2452 2471 - if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !subvp_in_use) { 2453 + if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !subvp_active) { 2472 2454 /* find largest table entry that is lower than dram speed, 2473 2455 * but lower than DPM0 still uses DPM0 2474 2456 */ ··· 3466 3448 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { 3467 3449 const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 3468 3450 3469 - if (!pipe->stream) 3451 + /* In DCN32/321, FPO uses per-pipe P-State force. 3452 + * If there's no planes, HUBP is power gated and 3453 + * therefore programming UCLK_PSTATE_FORCE does 3454 + * nothing (P-State will always be asserted naturally 3455 + * on a pipe that has HUBP power gated. Therefore we 3456 + * only want to enable FPO if the FPO pipe has both 3457 + * a stream and a plane. 3458 + */ 3459 + if (!pipe->stream || !pipe->plane_state) 3470 3460 continue; 3471 3461 3472 3462 if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) { ··· 3528 3502 void dcn32_override_min_req_memclk(struct dc *dc, struct dc_state *context) 3529 3503 { 3530 3504 // WA: restrict FPO and SubVP to use first non-strobe mode (DCN32 BW issue) 3531 - if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dcn32_subvp_in_use(dc, context)) && 3505 + if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || resource_subvp_in_use(dc, context)) && 3532 3506 dc->dml.soc.num_chans <= 8) { 3533 3507 int num_mclk_levels = dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; 3534 3508
+1 -1
drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
··· 5420 5420 *OutBpp = TruncToValidBPP((1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output, 5421 5421 OutputFormat, DSCInputBitPerComponent, NumberOfDSCSlices, (dml_uint_t)AudioSampleRate, AudioSampleLayout, ODMModeNoDSC, ODMModeDSC, RequiredSlots); 5422 5422 5423 - if (OutBpp == 0 && PHYCLKD32PerState < 20000 / 32 && DSCEnable == dml_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) { 5423 + if (*OutBpp == 0 && PHYCLKD32PerState < 20000 / 32 && DSCEnable == dml_dsc_enable_if_necessary && ForcedOutputLinkBPP == 0) { 5424 5424 *RequiresDSC = true; 5425 5425 LinkDSCEnable = true; 5426 5426 *OutBpp = TruncToValidBPP((1 - Downspreading / 100) * 13500, OutputLinkDPLanes, HTotal, HActive, PixelClockBackEnd, ForcedOutputLinkBPP, LinkDSCEnable, Output,
+1
drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_types.h
··· 38 38 #include "core_types.h" 39 39 #include "dsc.h" 40 40 #include "clk_mgr.h" 41 + #include "dc_state_priv.h" 41 42 42 43 #endif //__DML2_DC_TYPES_H__
+42 -47
drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
··· 51 51 52 52 // Find the phantom pipes 53 53 if (pipe->stream && pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && 54 - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 54 + ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 55 55 bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4; 56 56 mblk_width = ctx->config.mall_cfg.mblk_width_pixels; 57 57 mblk_height = bytes_per_pixel == 4 ? mblk_width = ctx->config.mall_cfg.mblk_height_4bpe_pixels : ctx->config.mall_cfg.mblk_height_8bpe_pixels; ··· 253 253 * to combine this with SubVP can cause issues with the scheduling). 254 254 */ 255 255 if (pipe->plane_state && !pipe->top_pipe && 256 - pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && 256 + ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe) == SUBVP_NONE && refresh_rate < 120 && 257 257 vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) { 258 258 while (pipe) { 259 259 num_pipes++; ··· 317 317 318 318 // Find the minimum pipe split count for non SubVP pipes 319 319 if (pipe->stream && !pipe->top_pipe && 320 - pipe->stream->mall_stream_config.type == SUBVP_NONE) { 320 + ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(state, pipe) == SUBVP_NONE) { 321 321 split_cnt = 0; 322 322 while (pipe) { 323 323 split_cnt++; ··· 372 372 * and also to store the two main SubVP pipe pointers in subvp_pipes[2]. 373 373 */ 374 374 if (pipe->stream && pipe->plane_state && !pipe->top_pipe && 375 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 376 - phantom = pipe->stream->mall_stream_config.paired_stream; 375 + ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) { 376 + phantom = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, pipe->stream); 377 377 microschedule_lines = (phantom->timing.v_total - phantom->timing.v_front_porch) + 378 378 phantom->timing.v_addressable; 379 379 ··· 435 435 struct pipe_ctx *pipe = NULL; 436 436 struct dc_crtc_timing *main_timing = NULL; 437 437 struct dc_crtc_timing *phantom_timing = NULL; 438 + struct dc_stream_state *phantom_stream; 438 439 int16_t prefetch_us = 0; 439 440 int16_t mall_region_us = 0; 440 441 int16_t drr_frame_us = 0; // nominal frame time ··· 454 453 continue; 455 454 456 455 // Find the SubVP pipe 457 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) 456 + if (ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) 458 457 break; 459 458 } 460 459 460 + phantom_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, pipe->stream); 461 461 main_timing = &pipe->stream->timing; 462 - phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing; 462 + phantom_timing = &phantom_stream->timing; 463 463 prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total / 464 464 (double)(phantom_timing->pix_clk_100hz * 100) * 1000000 + 465 465 ctx->config.svp_pstate.subvp_prefetch_end_to_mall_start_us; ··· 521 519 struct dc_crtc_timing *main_timing = NULL; 522 520 struct dc_crtc_timing *phantom_timing = NULL; 523 521 struct dc_crtc_timing *vblank_timing = NULL; 522 + struct dc_stream_state *phantom_stream; 523 + enum mall_stream_type pipe_mall_type; 524 524 525 525 /* For SubVP + VBLANK/DRR cases, we assume there can only be 526 526 * a single VBLANK/DRR display. If DML outputs SubVP + VBLANK ··· 532 528 */ 533 529 for (i = 0; i < ctx->config.dcn_pipe_count; i++) { 534 530 pipe = &context->res_ctx.pipe_ctx[i]; 531 + pipe_mall_type = ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe); 535 532 536 533 // We check for master pipe, but it shouldn't matter since we only need 537 534 // the pipe for timing info (stream should be same for any pipe splits) 538 535 if (!pipe->stream || !pipe->plane_state || pipe->top_pipe || pipe->prev_odm_pipe) 539 536 continue; 540 537 541 - if (!found && pipe->stream->mall_stream_config.type == SUBVP_NONE) { 538 + if (!found && pipe_mall_type == SUBVP_NONE) { 542 539 // Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe). 543 540 vblank_index = i; 544 541 found = true; 545 542 } 546 543 547 - if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) 544 + if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN) 548 545 subvp_pipe = pipe; 549 546 } 550 547 // Use ignore_msa_timing_param flag to identify as DRR ··· 553 548 // SUBVP + DRR case 554 549 schedulable = dml2_svp_drr_schedulable(ctx, context, &context->res_ctx.pipe_ctx[vblank_index].stream->timing); 555 550 } else if (found) { 551 + phantom_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, subvp_pipe->stream); 556 552 main_timing = &subvp_pipe->stream->timing; 557 - phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; 553 + phantom_timing = &phantom_stream->timing; 558 554 vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing; 559 555 // Prefetch time is equal to VACTIVE + BP + VSYNC of the phantom pipe 560 556 // Also include the prefetch end to mallstart delay time ··· 608 602 609 603 for (i = 0, pipe_idx = 0; i < ctx->config.dcn_pipe_count; i++) { 610 604 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 605 + enum mall_stream_type pipe_mall_type = ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe); 611 606 612 607 if (!pipe->stream) 613 608 continue; 614 609 615 610 if (pipe->plane_state && !pipe->top_pipe && 616 - pipe->stream->mall_stream_config.type == SUBVP_MAIN) 611 + pipe_mall_type == SUBVP_MAIN) 617 612 subvp_count++; 618 613 619 614 // Count how many planes that aren't SubVP/phantom are capable of VACTIVE 620 615 // switching (SubVP + VACTIVE unsupported). In situations where we force 621 616 // SubVP for a VACTIVE plane, we don't want to increment the vactive_count. 622 617 if (vba->ActiveDRAMClockChangeLatencyMargin[vba->pipe_plane[pipe_idx]] > 0 && 623 - pipe->stream->mall_stream_config.type == SUBVP_NONE) { 618 + pipe_mall_type == SUBVP_NONE) { 624 619 vactive_count++; 625 620 } 626 621 pipe_idx++; ··· 715 708 static struct dc_stream_state *enable_phantom_stream(struct dml2_context *ctx, struct dc_state *state, unsigned int dc_pipe_idx, unsigned int svp_height, unsigned int vstartup) 716 709 { 717 710 struct pipe_ctx *ref_pipe = &state->res_ctx.pipe_ctx[dc_pipe_idx]; 718 - struct dc_stream_state *phantom_stream = ctx->config.svp_pstate.callbacks.create_stream_for_sink(ref_pipe->stream->sink); 719 - 720 - phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; 721 - phantom_stream->dpms_off = true; 722 - phantom_stream->mall_stream_config.type = SUBVP_PHANTOM; 723 - phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream; 724 - ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN; 725 - ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream; 711 + struct dc_stream_state *phantom_stream = ctx->config.svp_pstate.callbacks.create_phantom_stream( 712 + ctx->config.svp_pstate.callbacks.dc, 713 + state, 714 + ref_pipe->stream); 726 715 727 716 /* stream has limited viewport and small timing */ 728 717 memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing)); ··· 726 723 memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst)); 727 724 set_phantom_stream_timing(ctx, state, ref_pipe, phantom_stream, dc_pipe_idx, svp_height, vstartup); 728 725 729 - ctx->config.svp_pstate.callbacks.add_stream_to_ctx(ctx->config.svp_pstate.callbacks.dc, state, phantom_stream); 726 + ctx->config.svp_pstate.callbacks.add_phantom_stream(ctx->config.svp_pstate.callbacks.dc, 727 + state, 728 + phantom_stream, 729 + ref_pipe->stream); 730 730 return phantom_stream; 731 731 } 732 732 ··· 746 740 if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) { 747 741 phantom_plane = prev_phantom_plane; 748 742 } else { 749 - phantom_plane = ctx->config.svp_pstate.callbacks.create_plane(ctx->config.svp_pstate.callbacks.dc); 743 + phantom_plane = ctx->config.svp_pstate.callbacks.create_phantom_plane( 744 + ctx->config.svp_pstate.callbacks.dc, 745 + state, 746 + curr_pipe->plane_state); 750 747 } 751 748 752 749 memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); ··· 772 763 phantom_plane->clip_rect.y = 0; 773 764 phantom_plane->clip_rect.height = phantom_stream->timing.v_addressable; 774 765 775 - phantom_plane->is_phantom = true; 776 - 777 - ctx->config.svp_pstate.callbacks.add_plane_to_context(ctx->config.svp_pstate.callbacks.dc, phantom_stream, phantom_plane, state); 766 + ctx->config.svp_pstate.callbacks.add_phantom_plane(ctx->config.svp_pstate.callbacks.dc, phantom_stream, phantom_plane, state); 778 767 779 768 curr_pipe = curr_pipe->bottom_pipe; 780 769 prev_phantom_plane = phantom_plane; ··· 797 790 // We determine which phantom pipes were added by comparing with 798 791 // the phantom stream. 799 792 if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream && 800 - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 793 + ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) { 801 794 pipe->stream->use_dynamic_meta = false; 802 795 pipe->plane_state->flip_immediate = false; 803 796 if (!ctx->config.svp_pstate.callbacks.build_scaling_params(pipe)) { ··· 807 800 } 808 801 } 809 802 810 - static bool remove_all_planes_for_stream(struct dml2_context *ctx, struct dc_stream_state *stream, struct dc_state *context) 803 + static bool remove_all_phantom_planes_for_stream(struct dml2_context *ctx, struct dc_stream_state *stream, struct dc_state *context) 811 804 { 812 805 int i, old_plane_count; 813 806 struct dc_stream_status *stream_status = NULL; ··· 828 821 for (i = 0; i < old_plane_count; i++) 829 822 del_planes[i] = stream_status->plane_states[i]; 830 823 831 - for (i = 0; i < old_plane_count; i++) 832 - if (!ctx->config.svp_pstate.callbacks.remove_plane_from_context(ctx->config.svp_pstate.callbacks.dc, stream, del_planes[i], context)) 824 + for (i = 0; i < old_plane_count; i++) { 825 + if (!ctx->config.svp_pstate.callbacks.remove_phantom_plane(ctx->config.svp_pstate.callbacks.dc, stream, del_planes[i], context)) 833 826 return false; 827 + ctx->config.svp_pstate.callbacks.release_phantom_plane(ctx->config.svp_pstate.callbacks.dc, context, del_planes[i]); 828 + } 834 829 835 830 return true; 836 831 } ··· 841 832 { 842 833 int i; 843 834 bool removed_pipe = false; 844 - struct dc_plane_state *phantom_plane = NULL; 845 835 struct dc_stream_state *phantom_stream = NULL; 846 836 847 837 for (i = 0; i < ctx->config.dcn_pipe_count; i++) { 848 838 struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i]; 849 839 // build scaling params for phantom pipes 850 - if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 851 - phantom_plane = pipe->plane_state; 840 + if (pipe->plane_state && pipe->stream && ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) { 852 841 phantom_stream = pipe->stream; 853 842 854 - remove_all_planes_for_stream(ctx, pipe->stream, state); 855 - ctx->config.svp_pstate.callbacks.remove_stream_from_ctx(ctx->config.svp_pstate.callbacks.dc, state, pipe->stream); 856 - 857 - /* Ref count is incremented on allocation and also when added to the context. 858 - * Therefore we must call release for the the phantom plane and stream once 859 - * they are removed from the ctx to finally decrement the refcount to 0 to free. 860 - */ 861 - ctx->config.svp_pstate.callbacks.plane_state_release(phantom_plane); 862 - ctx->config.svp_pstate.callbacks.stream_release(phantom_stream); 843 + remove_all_phantom_planes_for_stream(ctx, phantom_stream, state); 844 + ctx->config.svp_pstate.callbacks.remove_phantom_stream(ctx->config.svp_pstate.callbacks.dc, state, phantom_stream); 845 + ctx->config.svp_pstate.callbacks.release_phantom_stream(ctx->config.svp_pstate.callbacks.dc, state, phantom_stream); 863 846 864 847 removed_pipe = true; 865 - } 866 - 867 - // Clear all phantom stream info 868 - if (pipe->stream) { 869 - pipe->stream->mall_stream_config.type = SUBVP_NONE; 870 - pipe->stream->mall_stream_config.paired_stream = NULL; 871 848 } 872 849 873 850 if (pipe->plane_state) {
+19 -7
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
··· 1049 1049 1050 1050 void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg) 1051 1051 { 1052 - int i = 0, j = 0; 1052 + int i = 0, j = 0, k = 0; 1053 1053 int disp_cfg_stream_location, disp_cfg_plane_location; 1054 + enum mall_stream_type stream_mall_type; 1055 + struct pipe_ctx *current_pipe_context; 1054 1056 1055 1057 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { 1056 1058 dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[i] = false; ··· 1072 1070 dml2_populate_pipe_to_plane_index_mapping(dml2, context); 1073 1071 1074 1072 for (i = 0; i < context->stream_count; i++) { 1073 + current_pipe_context = NULL; 1074 + for (k = 0; k < MAX_PIPES; k++) { 1075 + /* find one pipe allocated to this stream for the purpose of getting 1076 + info about the link later */ 1077 + if (context->streams[i] == context->res_ctx.pipe_ctx[k].stream) { 1078 + current_pipe_context = &context->res_ctx.pipe_ctx[k]; 1079 + break; 1080 + } 1081 + } 1075 1082 disp_cfg_stream_location = map_stream_to_dml_display_cfg(dml2, context->streams[i], dml_dispcfg); 1083 + stream_mall_type = dc_state_get_stream_subvp_type(context, context->streams[i]); 1076 1084 1077 1085 if (disp_cfg_stream_location < 0) 1078 1086 disp_cfg_stream_location = dml_dispcfg->num_timings++; ··· 1090 1078 ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); 1091 1079 1092 1080 populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]); 1093 - populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], &context->res_ctx.pipe_ctx[i]); 1081 + populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context); 1094 1082 switch (context->streams[i]->debug.force_odm_combine_segments) { 1095 1083 case 2: 1096 1084 dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_stream_location] = dml_odm_use_policy_combine_2to1; ··· 1127 1115 populate_dml_surface_cfg_from_plane_state(dml2->v20.dml_core_ctx.project, &dml_dispcfg->surface, disp_cfg_plane_location, context->stream_status[i].plane_states[j]); 1128 1116 populate_dml_plane_cfg_from_plane_state(&dml_dispcfg->plane, disp_cfg_plane_location, context->stream_status[i].plane_states[j], context); 1129 1117 1130 - if (context->streams[i]->mall_stream_config.type == SUBVP_MAIN) { 1118 + if (stream_mall_type == SUBVP_MAIN) { 1131 1119 dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_sub_viewport; 1132 1120 dml_dispcfg->plane.UseMALLForStaticScreen[disp_cfg_plane_location] = dml_use_mall_static_screen_optimize; 1133 - } else if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM) { 1121 + } else if (stream_mall_type == SUBVP_PHANTOM) { 1134 1122 dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_phantom_pipe; 1135 1123 dml_dispcfg->plane.UseMALLForStaticScreen[disp_cfg_plane_location] = dml_use_mall_static_screen_disable; 1136 1124 dml2->v20.dml_core_ctx.policy.ImmediateFlipRequirement[disp_cfg_plane_location] = dml_immediate_flip_not_required; ··· 1147 1135 1148 1136 if (j >= 1) { 1149 1137 populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_plane_location, context->streams[i]); 1150 - populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_plane_location, context->streams[i], &context->res_ctx.pipe_ctx[i]); 1138 + populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_plane_location, context->streams[i], current_pipe_context); 1151 1139 switch (context->streams[i]->debug.force_odm_combine_segments) { 1152 1140 case 2: 1153 1141 dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_plane_location] = dml_odm_use_policy_combine_2to1; ··· 1159 1147 break; 1160 1148 } 1161 1149 1162 - if (context->streams[i]->mall_stream_config.type == SUBVP_MAIN) 1150 + if (stream_mall_type == SUBVP_MAIN) 1163 1151 dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_sub_viewport; 1164 - else if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM) 1152 + else if (stream_mall_type == SUBVP_PHANTOM) 1165 1153 dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_phantom_pipe; 1166 1154 1167 1155 dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[disp_cfg_plane_location] = context->streams[i]->stream_id;
+14 -4
drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
··· 155 155 156 156 bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx) 157 157 { 158 + if (pipe_ctx == NULL || pipe_ctx->stream == NULL) 159 + return false; 160 + 158 161 /* If this assert is hit then we have a link encoder dynamic management issue */ 159 162 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true); 160 163 161 - if (pipe_ctx->stream == NULL) 162 - return false; 164 + /* Count MST hubs once by treating only 1st remote sink in topology as an encoder */ 165 + if (pipe_ctx->stream->link && pipe_ctx->stream->link->remote_sinks[0]) { 166 + return (pipe_ctx->stream_res.hpo_dp_stream_enc && 167 + pipe_ctx->link_res.hpo_dp_link_enc && 168 + dc_is_dp_signal(pipe_ctx->stream->signal) && 169 + (pipe_ctx->stream->link->remote_sinks[0]->sink_id == pipe_ctx->stream->sink->sink_id)); 170 + } 163 171 164 172 return (pipe_ctx->stream_res.hpo_dp_stream_enc && 165 173 pipe_ctx->link_res.hpo_dp_link_enc && ··· 287 279 void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state, struct dml2_context *in_ctx, unsigned int pipe_cnt) 288 280 { 289 281 unsigned int dc_pipe_ctx_index, dml_pipe_idx, plane_id; 282 + enum mall_stream_type pipe_mall_type; 290 283 bool unbounded_req_enabled = false; 291 284 struct dml2_calculate_rq_and_dlg_params_scratch *s = &in_ctx->v20.scratch.calculate_rq_and_dlg_params_scratch; 292 285 ··· 335 326 */ 336 327 populate_pipe_ctx_dlg_params_from_dml(&context->res_ctx.pipe_ctx[dc_pipe_ctx_index], &context->bw_ctx.dml2->v20.dml_core_ctx, dml_pipe_idx); 337 328 338 - if (context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->mall_stream_config.type == SUBVP_PHANTOM) { 329 + pipe_mall_type = dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[dc_pipe_ctx_index]); 330 + if (pipe_mall_type == SUBVP_PHANTOM) { 339 331 // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests 340 332 context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb = 0; 341 333 context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = false; ··· 363 353 context->res_ctx.pipe_ctx[dc_pipe_ctx_index].plane_state != context->res_ctx.pipe_ctx[dc_pipe_ctx_index].top_pipe->plane_state) && 364 354 context->res_ctx.pipe_ctx[dc_pipe_ctx_index].prev_odm_pipe == NULL) { 365 355 /* SS: all active surfaces stored in MALL */ 366 - if (context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->mall_stream_config.type != SUBVP_PHANTOM) { 356 + if (pipe_mall_type != SUBVP_PHANTOM) { 367 357 context->bw_ctx.bw.dcn.mall_ss_size_bytes += context->res_ctx.pipe_ctx[dc_pipe_ctx_index].surface_size_in_mall_bytes; 368 358 } else { 369 359 /* SUBVP: phantom surfaces only stored in MALL */
+3 -1
drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
··· 418 418 int i; 419 419 420 420 for (i = 0; i < display_state->stream_count; i++) { 421 - if (display_state->streams[i]->mall_stream_config.type == SUBVP_NONE 421 + if (dc_state_get_stream_subvp_type(display_state, display_state->streams[i]) == SUBVP_NONE 422 422 && display_state->streams[i]->ignore_msa_timing_param) { 423 423 // Use ignore_msa_timing_param flag to identify as DRR 424 424 return i; ··· 634 634 dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.b, &dml2->v20.dml_core_ctx); 635 635 memcpy(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.g6_temp_read_watermark_set, sizeof(context->bw_ctx.bw.dcn.watermarks.c)); 636 636 dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.d, &dml2->v20.dml_core_ctx); 637 + //copy for deciding zstate use 638 + context->bw_ctx.dml.vba.StutterPeriod = context->bw_ctx.dml2->v20.dml_core_ctx.mp.StutterPeriod; 637 639 } 638 640 639 641 return result;
+27 -8
drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
··· 93 93 struct dml2_dc_svp_callbacks { 94 94 struct dc *dc; 95 95 bool (*build_scaling_params)(struct pipe_ctx *pipe_ctx); 96 - struct dc_stream_state* (*create_stream_for_sink)(struct dc_sink *dc_sink_data); 97 - struct dc_plane_state* (*create_plane)(struct dc *dc); 98 - enum dc_status (*add_stream_to_ctx)(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); 99 - bool (*add_plane_to_context)(const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context); 100 - bool (*remove_plane_from_context)(const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context); 101 - enum dc_status (*remove_stream_from_ctx)(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); 102 - void (*plane_state_release)(struct dc_plane_state *plane_state); 103 - void (*stream_release)(struct dc_stream_state *stream); 96 + struct dc_stream_state* (*create_phantom_stream)(const struct dc *dc, 97 + struct dc_state *state, 98 + struct dc_stream_state *main_stream); 99 + struct dc_plane_state* (*create_phantom_plane)(struct dc *dc, 100 + struct dc_state *state, 101 + struct dc_plane_state *main_plane); 102 + enum dc_status (*add_phantom_stream)(struct dc *dc, 103 + struct dc_state *state, 104 + struct dc_stream_state *phantom_stream, 105 + struct dc_stream_state *main_stream); 106 + bool (*add_phantom_plane)(const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context); 107 + bool (*remove_phantom_plane)(const struct dc *dc, 108 + struct dc_stream_state *stream, 109 + struct dc_plane_state *plane_state, 110 + struct dc_state *context); 111 + enum dc_status (*remove_phantom_stream)(struct dc *dc, 112 + struct dc_state *state, 113 + struct dc_stream_state *stream); 114 + void (*release_phantom_plane)(const struct dc *dc, 115 + struct dc_state *state, 116 + struct dc_plane_state *plane); 117 + void (*release_phantom_stream)(const struct dc *dc, 118 + struct dc_state *state, 119 + struct dc_stream_state *stream); 104 120 void (*release_dsc)(struct resource_context *res_ctx, const struct resource_pool *pool, struct display_stream_compressor **dsc); 121 + enum mall_stream_type (*get_pipe_subvp_type)(const struct dc_state *state, const struct pipe_ctx *pipe_ctx); 122 + enum mall_stream_type (*get_stream_subvp_type)(const struct dc_state *state, const struct dc_stream_state *stream); 123 + struct dc_stream_state *(*get_paired_subvp_stream)(const struct dc_state *state, const struct dc_stream_state *stream); 105 124 }; 106 125 107 126 struct dml2_clks_table_entry {
+14 -12
drivers/gpu/drm/amd/display/dc/hwss/Makefile
··· 78 78 # DCN 79 79 ############################################################################### 80 80 81 - HWSS_DCN10 = dcn10_hwseq.o 81 + HWSS_DCN10 = dcn10_hwseq.o dcn10_init.o 82 82 83 83 AMD_DAL_HWSS_DCN10 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn10/,$(HWSS_DCN10)) 84 84 ··· 86 86 87 87 ############################################################################### 88 88 89 - HWSS_DCN20 = dcn20_hwseq.o 89 + HWSS_DCN20 = dcn20_hwseq.o dcn20_init.o 90 90 91 91 AMD_DAL_HWSS_DCN20 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn20/,$(HWSS_DCN20)) 92 92 ··· 94 94 95 95 ############################################################################### 96 96 97 - HWSS_DCN201 = dcn201_hwseq.o 97 + HWSS_DCN201 = dcn201_hwseq.o dcn201_init.o 98 98 99 99 AMD_DAL_HWSS_DCN201 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn201/,$(HWSS_DCN201)) 100 100 ··· 102 102 103 103 ############################################################################### 104 104 105 - HWSS_DCN21 = dcn21_hwseq.o 105 + HWSS_DCN21 = dcn21_hwseq.o dcn21_init.o 106 106 107 107 AMD_DAL_HWSS_DCN21 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn21/,$(HWSS_DCN21)) 108 108 ··· 114 114 115 115 ############################################################################### 116 116 117 - HWSS_DCN30 = dcn30_hwseq.o 117 + HWSS_DCN30 = dcn30_hwseq.o dcn30_init.o 118 118 119 119 AMD_DAL_HWSS_DCN30 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn30/,$(HWSS_DCN30)) 120 120 ··· 122 122 123 123 ############################################################################### 124 124 125 - HWSS_DCN301 = dcn301_hwseq.o 125 + HWSS_DCN301 = dcn301_hwseq.o dcn301_init.o 126 126 127 127 AMD_DAL_HWSS_DCN301 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn301/,$(HWSS_DCN301)) 128 128 ··· 130 130 131 131 ############################################################################### 132 132 133 - HWSS_DCN302 = dcn302_hwseq.o 133 + HWSS_DCN302 = dcn302_hwseq.o dcn302_init.o 134 134 135 135 AMD_DAL_HWSS_DCN302 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn302/,$(HWSS_DCN302)) 136 136 137 137 AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN302) 138 138 139 + 140 + 139 141 ############################################################################### 140 142 141 - HWSS_DCN303 = dcn303_hwseq.o 143 + HWSS_DCN303 = dcn303_hwseq.o dcn303_init.o 142 144 143 145 AMD_DAL_HWSS_DCN303 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn303/,$(HWSS_DCN303)) 144 146 ··· 148 146 149 147 ############################################################################### 150 148 151 - HWSS_DCN31 = dcn31_hwseq.o 149 + HWSS_DCN31 = dcn31_hwseq.o dcn31_init.o 152 150 153 151 AMD_DAL_HWSS_DCN31 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn31/,$(HWSS_DCN31)) 154 152 ··· 156 154 157 155 ############################################################################### 158 156 159 - HWSS_DCN314 = dcn314_hwseq.o 157 + HWSS_DCN314 = dcn314_hwseq.o dcn314_init.o 160 158 161 159 AMD_DAL_HWSS_DCN314 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn314/,$(HWSS_DCN314)) 162 160 ··· 164 162 165 163 ############################################################################### 166 164 167 - HWSS_DCN32 = dcn32_hwseq.o 165 + HWSS_DCN32 = dcn32_hwseq.o dcn32_init.o 168 166 169 167 AMD_DAL_HWSS_DCN32 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn32/,$(HWSS_DCN32)) 170 168 ··· 172 170 173 171 ############################################################################### 174 172 175 - HWSS_DCN35 = dcn35_hwseq.o 173 + HWSS_DCN35 = dcn35_hwseq.o dcn35_init.o 176 174 177 175 AMD_DAL_HWSS_DCN35 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn35/,$(HWSS_DCN35)) 178 176
+13 -7
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
··· 55 55 #include "audio.h" 56 56 #include "reg_helper.h" 57 57 #include "panel_cntl.h" 58 + #include "dc_state_priv.h" 58 59 #include "dpcd_defs.h" 59 60 /* include DCE11 register header files */ 60 61 #include "dce/dce_11_0_d.h" ··· 1597 1596 * is constructed with the same sink). Make sure not to override 1598 1597 * and link programming on the main. 1599 1598 */ 1600 - if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) { 1599 + if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) { 1601 1600 pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false; 1602 1601 pipe_ctx->stream->link->replay_settings.replay_feature_enabled = false; 1603 1602 } ··· 1685 1684 true); 1686 1685 1687 1686 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; 1688 - dc->hwss.disable_plane(dc, 1687 + dc->hwss.disable_plane(dc, dc->current_state, 1689 1688 &dc->current_state->res_ctx.pipe_ctx[i]); 1690 1689 } 1691 1690 } ··· 2125 2124 BREAK_TO_DEBUGGER(); 2126 2125 } 2127 2126 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); 2128 - pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0; 2127 + if (dc_is_hdmi_tmds_signal(pipe_ctx_old->stream->signal)) 2128 + pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0; 2129 2129 pipe_ctx_old->plane_res.mi->funcs->free_mem_input( 2130 2130 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); 2131 2131 ··· 2135 2133 old_clk)) 2136 2134 old_clk->funcs->cs_power_down(old_clk); 2137 2135 2138 - dc->hwss.disable_plane(dc, pipe_ctx_old); 2136 + dc->hwss.disable_plane(dc, dc->current_state, pipe_ctx_old); 2139 2137 2140 2138 pipe_ctx_old->stream = NULL; 2141 2139 } ··· 2499 2497 /* Enable timing synchronization for a group of Timing Generators. */ 2500 2498 static void dce110_enable_timing_synchronization( 2501 2499 struct dc *dc, 2500 + struct dc_state *state, 2502 2501 int group_index, 2503 2502 int group_size, 2504 2503 struct pipe_ctx *grouped_pipes[]) ··· 2593 2590 struct dmcu *dmcu; 2594 2591 struct dce_hwseq *hws = dc->hwseq; 2595 2592 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 2593 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 2596 2594 2597 2595 bp = dc->ctx->dc_bios; 2598 2596 for (i = 0; i < dc->res_pool->pipe_count; i++) { ··· 2643 2639 for (i = 0; i < dc->link_count; i++) { 2644 2640 struct dc_link *link = dc->links[i]; 2645 2641 2646 - if (link->panel_cntl) 2642 + if (link->panel_cntl) { 2647 2643 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 2644 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 2645 + } 2648 2646 } 2649 2647 2650 2648 abm = dc->res_pool->abm; 2651 2649 if (abm != NULL) 2652 - abm->funcs->abm_init(abm, backlight); 2650 + abm->funcs->abm_init(abm, backlight, user_level); 2653 2651 2654 2652 dmcu = dc->res_pool->dmcu; 2655 2653 if (dmcu != NULL && abm != NULL) ··· 2848 2842 { 2849 2843 } 2850 2844 2851 - static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) 2845 + static void dce110_power_down_fe(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) 2852 2846 { 2853 2847 struct dce_hwseq *hws = dc->hwseq; 2854 2848 int fe_idx = pipe_ctx->plane_res.mi ?
+25 -17
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
··· 56 56 #include "dc_trace.h" 57 57 #include "dce/dmub_outbox.h" 58 58 #include "link.h" 59 + #include "dc_state_priv.h" 59 60 60 61 #define DC_LOGGER \ 61 62 dc_logger ··· 116 115 !pipe_ctx->stream || 117 116 (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) || 118 117 !tg->funcs->is_tg_enabled(tg) || 119 - pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) 118 + dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) 120 119 continue; 121 120 122 121 if (lock) ··· 1058 1057 if (pipe_ctx->stream_res.tg->funcs->set_drr) 1059 1058 pipe_ctx->stream_res.tg->funcs->set_drr( 1060 1059 pipe_ctx->stream_res.tg, NULL); 1061 - pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; 1060 + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 1061 + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; 1062 1062 } 1063 1063 1064 1064 for (i = 0; i < dc->res_pool->pipe_count; i++) ··· 1182 1180 } 1183 1181 1184 1182 /* trigger HW to start disconnect plane from stream on the next vsync */ 1185 - void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) 1183 + void dcn10_plane_atomic_disconnect(struct dc *dc, 1184 + struct dc_state *state, 1185 + struct pipe_ctx *pipe_ctx) 1186 1186 { 1187 1187 struct dce_hwseq *hws = dc->hwseq; 1188 1188 struct hubp *hubp = pipe_ctx->plane_res.hubp; ··· 1204 1200 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove); 1205 1201 // Phantom pipes have OTG disabled by default, so MPCC_STATUS will never assert idle, 1206 1202 // so don't wait for MPCC_IDLE in the programming sequence 1207 - if (opp != NULL && !pipe_ctx->plane_state->is_phantom) 1203 + if (opp != NULL && dc_state_get_pipe_subvp_type(state, pipe_ctx) != SUBVP_PHANTOM) 1208 1204 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; 1209 1205 1210 1206 dc->optimized_required = true; ··· 1294 1290 pipe_ctx->plane_state = NULL; 1295 1291 } 1296 1292 1297 - void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) 1293 + void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) 1298 1294 { 1299 1295 struct dce_hwseq *hws = dc->hwseq; 1300 1296 DC_LOGGER_INIT(dc->ctx->logger); ··· 1420 1416 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; 1421 1417 pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; 1422 1418 1423 - hws->funcs.plane_atomic_disconnect(dc, pipe_ctx); 1419 + hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx); 1424 1420 1425 1421 if (tg->funcs->is_tg_enabled(tg)) 1426 1422 tg->funcs->unlock(tg); 1427 1423 1428 - dc->hwss.disable_plane(dc, pipe_ctx); 1424 + dc->hwss.disable_plane(dc, context, pipe_ctx); 1429 1425 1430 1426 pipe_ctx->stream_res.tg = NULL; 1431 1427 pipe_ctx->plane_res.hubp = NULL; ··· 1490 1486 struct dc_bios *dcb = dc->ctx->dc_bios; 1491 1487 struct resource_pool *res_pool = dc->res_pool; 1492 1488 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 1489 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 1493 1490 bool is_optimized_init_done = false; 1494 1491 1495 1492 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) ··· 1588 1583 for (i = 0; i < dc->link_count; i++) { 1589 1584 struct dc_link *link = dc->links[i]; 1590 1585 1591 - if (link->panel_cntl) 1586 + if (link->panel_cntl) { 1592 1587 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 1588 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 1589 + } 1593 1590 } 1594 1591 1595 1592 if (abm != NULL) 1596 - abm->funcs->abm_init(abm, backlight); 1593 + abm->funcs->abm_init(abm, backlight, user_level); 1597 1594 1598 1595 if (dmcu != NULL && !dmcu->auto_load_dmcu) 1599 1596 dmcu->funcs->dmcu_init(dmcu); ··· 2269 2262 2270 2263 void dcn10_enable_timing_synchronization( 2271 2264 struct dc *dc, 2265 + struct dc_state *state, 2272 2266 int group_index, 2273 2267 int group_size, 2274 2268 struct pipe_ctx *grouped_pipes[]) ··· 2284 2276 DC_SYNC_INFO("Setting up OTG reset trigger\n"); 2285 2277 2286 2278 for (i = 1; i < group_size; i++) { 2287 - if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM) 2279 + if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM) 2288 2280 continue; 2289 2281 2290 2282 opp = grouped_pipes[i]->stream_res.opp; ··· 2304 2296 if (grouped_pipes[i]->stream == NULL) 2305 2297 continue; 2306 2298 2307 - if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM) 2299 + if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM) 2308 2300 continue; 2309 2301 2310 2302 grouped_pipes[i]->stream->vblank_synchronized = false; 2311 2303 } 2312 2304 2313 2305 for (i = 1; i < group_size; i++) { 2314 - if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM) 2306 + if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM) 2315 2307 continue; 2316 2308 2317 2309 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( ··· 2325 2317 * synchronized. Look at last pipe programmed to reset. 2326 2318 */ 2327 2319 2328 - if (grouped_pipes[1]->stream && grouped_pipes[1]->stream->mall_stream_config.type != SUBVP_PHANTOM) 2320 + if (grouped_pipes[1]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[1]) != SUBVP_PHANTOM) 2329 2321 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); 2330 2322 2331 2323 for (i = 1; i < group_size; i++) { 2332 - if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM) 2324 + if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM) 2333 2325 continue; 2334 2326 2335 2327 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( ··· 2337 2329 } 2338 2330 2339 2331 for (i = 1; i < group_size; i++) { 2340 - if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM) 2332 + if (dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM) 2341 2333 continue; 2342 2334 2343 2335 opp = grouped_pipes[i]->stream_res.opp; ··· 3029 3021 3030 3022 for (i = 0; i < dc->res_pool->pipe_count; i++) 3031 3023 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) 3032 - dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); 3024 + dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); 3033 3025 3034 3026 for (i = 0; i < dc->res_pool->pipe_count; i++) 3035 3027 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { ··· 3076 3068 context, 3077 3069 false); 3078 3070 3079 - dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub, 3071 + dc->optimized_required |= hubbub->funcs->program_watermarks(hubbub, 3080 3072 &context->bw_ctx.bw.dcn.watermarks, 3081 3073 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, 3082 3074 true);
+5 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
··· 75 75 void dcn10_reset_hw_ctx_wrap( 76 76 struct dc *dc, 77 77 struct dc_state *context); 78 - void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); 78 + void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx); 79 79 void dcn10_lock_all_pipes( 80 80 struct dc *dc, 81 81 struct dc_state *context, ··· 108 108 enum dc_status dce110_apply_ctx_to_hw( 109 109 struct dc *dc, 110 110 struct dc_state *context); 111 - void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx); 111 + void dcn10_plane_atomic_disconnect(struct dc *dc, 112 + struct dc_state *state, 113 + struct pipe_ctx *pipe_ctx); 112 114 void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data); 113 115 void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx); 114 116 void dce110_power_down(struct dc *dc); 115 117 void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context); 116 118 void dcn10_enable_timing_synchronization( 117 119 struct dc *dc, 120 + struct dc_state *state, 118 121 int group_index, 119 122 int group_size, 120 123 struct pipe_ctx *grouped_pipes[]);
+84 -32
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
··· 55 55 #include "inc/link_enc_cfg.h" 56 56 #include "link_hwss.h" 57 57 #include "link.h" 58 + #include "dc_state_priv.h" 58 59 59 60 #define DC_LOGGER \ 60 61 dc_logger ··· 624 623 } 625 624 626 625 627 - void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) 626 + void dcn20_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) 628 627 { 629 - bool is_phantom = pipe_ctx->plane_state && pipe_ctx->plane_state->is_phantom; 628 + bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM; 630 629 struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL; 631 630 632 631 DC_LOGGER_INIT(dc->ctx->logger); ··· 848 847 /* TODO enable stream if timing changed */ 849 848 /* TODO unblank stream if DP */ 850 849 851 - if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) { 850 + if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { 852 851 if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable) 853 852 pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg); 854 853 } ··· 1369 1368 } 1370 1369 } 1371 1370 1372 - static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) 1371 + static void dcn20_detect_pipe_changes(struct dc_state *old_state, 1372 + struct dc_state *new_state, 1373 + struct pipe_ctx *old_pipe, 1374 + struct pipe_ctx *new_pipe) 1373 1375 { 1376 + bool old_is_phantom = dc_state_get_pipe_subvp_type(old_state, old_pipe) == SUBVP_PHANTOM; 1377 + bool new_is_phantom = dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM; 1378 + 1374 1379 new_pipe->update_flags.raw = 0; 1375 1380 1376 1381 /* If non-phantom pipe is being transitioned to a phantom pipe, ··· 1386 1379 * be different). The post_unlock sequence will set the correct 1387 1380 * update flags to enable the phantom pipe. 1388 1381 */ 1389 - if (old_pipe->plane_state && !old_pipe->plane_state->is_phantom && 1390 - new_pipe->plane_state && new_pipe->plane_state->is_phantom) { 1382 + if (old_pipe->plane_state && !old_is_phantom && 1383 + new_pipe->plane_state && new_is_phantom) { 1391 1384 new_pipe->update_flags.bits.disable = 1; 1392 1385 return; 1393 1386 } ··· 1407 1400 new_pipe->update_flags.bits.scaler = 1; 1408 1401 new_pipe->update_flags.bits.viewport = 1; 1409 1402 new_pipe->update_flags.bits.det_size = 1; 1403 + if (new_pipe->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE && 1404 + new_pipe->stream_res.test_pattern_params.width != 0 && 1405 + new_pipe->stream_res.test_pattern_params.height != 0) 1406 + new_pipe->update_flags.bits.test_pattern_changed = 1; 1410 1407 if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) { 1411 1408 new_pipe->update_flags.bits.odm = 1; 1412 1409 new_pipe->update_flags.bits.global_sync = 1; ··· 1423 1412 * The remove-add sequence of the phantom pipe always results in the pipe 1424 1413 * being blanked in enable_stream_timing (DPG). 1425 1414 */ 1426 - if (new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) 1415 + if (new_pipe->stream && dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM) 1427 1416 new_pipe->update_flags.bits.enable = 1; 1428 1417 1429 1418 /* Phantom pipes are effectively disabled, if the pipe was previously phantom 1430 1419 * we have to enable 1431 1420 */ 1432 - if (old_pipe->plane_state && old_pipe->plane_state->is_phantom && 1433 - new_pipe->plane_state && !new_pipe->plane_state->is_phantom) 1421 + if (old_pipe->plane_state && old_is_phantom && 1422 + new_pipe->plane_state && !new_is_phantom) 1434 1423 new_pipe->update_flags.bits.enable = 1; 1435 1424 1436 1425 if (old_pipe->plane_state && !new_pipe->plane_state) { ··· 1567 1556 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 1568 1557 struct dccg *dccg = dc->res_pool->dccg; 1569 1558 bool viewport_changed = false; 1559 + enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe_ctx); 1570 1560 1571 1561 if (pipe_ctx->update_flags.bits.dppclk) 1572 1562 dpp->funcs->dpp_dppclk_control(dpp, false, true); ··· 1713 1701 pipe_ctx->update_flags.bits.plane_changed || 1714 1702 plane_state->update_flags.bits.addr_update) { 1715 1703 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && 1716 - pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) { 1704 + pipe_mall_type == SUBVP_MAIN) { 1717 1705 union block_sequence_params params; 1718 1706 1719 1707 params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv; ··· 1727 1715 if (pipe_ctx->update_flags.bits.enable) 1728 1716 hubp->funcs->set_blank(hubp, false); 1729 1717 /* If the stream paired with this plane is phantom, the plane is also phantom */ 1730 - if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM 1718 + if (pipe_ctx->stream && pipe_mall_type == SUBVP_PHANTOM 1731 1719 && hubp->funcs->phantom_hubp_post_enable) 1732 1720 hubp->funcs->phantom_hubp_post_enable(hubp); 1733 1721 } ··· 1785 1773 pipe_ctx->pipe_dlg_param.vupdate_offset, 1786 1774 pipe_ctx->pipe_dlg_param.vupdate_width); 1787 1775 1788 - if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) 1776 + if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) 1789 1777 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); 1790 1778 1791 1779 pipe_ctx->stream_res.tg->funcs->set_vtg_params( ··· 1882 1870 } 1883 1871 } 1884 1872 1873 + static void update_vmin_vmax_fams(struct dc *dc, 1874 + struct dc_state *context) 1875 + { 1876 + uint32_t i; 1877 + struct drr_params params = {0}; 1878 + bool subvp_in_use = resource_subvp_in_use(dc, context); 1879 + 1880 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 1881 + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1882 + 1883 + if (resource_is_pipe_type(pipe, OTG_MASTER) && 1884 + ((subvp_in_use && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM && 1885 + pipe->stream->allow_freesync) || (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && pipe->stream->fpo_in_use))) { 1886 + if (!pipe->stream->vrr_active_variable && !pipe->stream->vrr_active_fixed) { 1887 + struct timing_generator *tg = context->res_ctx.pipe_ctx[i].stream_res.tg; 1888 + 1889 + /* DRR should be configured already if we're in active variable 1890 + * or active fixed, so only program if we're not in this state 1891 + */ 1892 + params.vertical_total_min = pipe->stream->timing.v_total; 1893 + params.vertical_total_max = pipe->stream->timing.v_total; 1894 + tg->funcs->set_drr(tg, &params); 1895 + } 1896 + } else { 1897 + if (resource_is_pipe_type(pipe, OTG_MASTER) && 1898 + !pipe->stream->vrr_active_variable && 1899 + !pipe->stream->vrr_active_fixed) { 1900 + struct timing_generator *tg = context->res_ctx.pipe_ctx[i].stream_res.tg; 1901 + params.vertical_total_min = 0; 1902 + params.vertical_total_max = 0; 1903 + tg->funcs->set_drr(tg, &params); 1904 + } 1905 + } 1906 + } 1907 + } 1908 + 1885 1909 void dcn20_program_front_end_for_ctx( 1886 1910 struct dc *dc, 1887 1911 struct dc_state *context) ··· 1960 1912 1961 1913 /* Set pipe update flags and lock pipes */ 1962 1914 for (i = 0; i < dc->res_pool->pipe_count; i++) 1963 - dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], 1915 + dcn20_detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i], 1964 1916 &context->res_ctx.pipe_ctx[i]); 1965 1917 1966 1918 /* When disabling phantom pipes, turn on phantom OTG first (so we can get double ··· 1970 1922 struct dc_stream_state *stream = dc->current_state->res_ctx.pipe_ctx[i].stream; 1971 1923 1972 1924 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && stream && 1973 - dc->current_state->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) { 1925 + dc_state_get_pipe_subvp_type(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) { 1974 1926 struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg; 1975 1927 1976 1928 if (tg->funcs->enable_crtc) { 1977 1929 if (dc->hwss.blank_phantom) { 1978 1930 int main_pipe_width, main_pipe_height; 1931 + struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(dc->current_state, dc->current_state->res_ctx.pipe_ctx[i].stream); 1979 1932 1980 - main_pipe_width = dc->current_state->res_ctx.pipe_ctx[i].stream->mall_stream_config.paired_stream->dst.width; 1981 - main_pipe_height = dc->current_state->res_ctx.pipe_ctx[i].stream->mall_stream_config.paired_stream->dst.height; 1933 + main_pipe_width = phantom_stream->dst.width; 1934 + main_pipe_height = phantom_stream->dst.height; 1982 1935 dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height); 1983 1936 } 1984 1937 tg->funcs->enable_crtc(tg); ··· 1994 1945 && context->res_ctx.pipe_ctx[i].stream) 1995 1946 hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); 1996 1947 1948 + update_vmin_vmax_fams(dc, context); 1997 1949 1998 1950 /* Disconnect mpcc */ 1999 1951 for (i = 0; i < dc->res_pool->pipe_count; i++) ··· 2009 1959 * DET allocation. 2010 1960 */ 2011 1961 if (hubbub->funcs->program_det_size && (context->res_ctx.pipe_ctx[i].update_flags.bits.disable || 2012 - (context->res_ctx.pipe_ctx[i].plane_state && context->res_ctx.pipe_ctx[i].plane_state->is_phantom))) 1962 + (context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) 2013 1963 hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); 2014 - hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); 1964 + hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); 2015 1965 DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); 2016 1966 } 2017 1967 ··· 2034 1984 * but the MPO still exists until the double buffered update of the main pipe so we 2035 1985 * will get a frame of underflow if the phantom pipe is programmed here. 2036 1986 */ 2037 - if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) 1987 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) 2038 1988 dcn20_program_pipe(dc, pipe, context); 2039 1989 } 2040 1990 ··· 2084 2034 2085 2035 for (i = 0; i < dc->res_pool->pipe_count; i++) 2086 2036 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) 2087 - dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); 2037 + dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); 2088 2038 2089 2039 /* 2090 2040 * If we are enabling a pipe, we need to wait for pending clear as this is a critical ··· 2096 2046 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 2097 2047 // Don't check flip pending on phantom pipes 2098 2048 if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable && 2099 - pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { 2049 + dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) { 2100 2050 struct hubp *hubp = pipe->plane_res.hubp; 2101 2051 int j = 0; 2102 2052 for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us ··· 2119 2069 * programming sequence). 2120 2070 */ 2121 2071 while (pipe) { 2122 - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 2072 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 2123 2073 /* When turning on the phantom pipe we want to run through the 2124 2074 * entire enable sequence, so apply all the "enable" flags. 2125 2075 */ ··· 2189 2139 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 2190 2140 2191 2141 // At optimize don't restore the original watermark value 2192 - if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) { 2142 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_NONE) { 2193 2143 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U; 2194 2144 break; 2195 2145 } 2196 2146 } 2197 2147 2198 2148 /* program dchubbub watermarks: 2199 - * For assigning wm_optimized_required, use |= operator since we don't want 2149 + * For assigning optimized_required, use |= operator since we don't want 2200 2150 * to clear the value if the optimize has not happened yet 2201 2151 */ 2202 - dc->wm_optimized_required |= hubbub->funcs->program_watermarks(hubbub, 2152 + dc->optimized_required |= hubbub->funcs->program_watermarks(hubbub, 2203 2153 &context->bw_ctx.bw.dcn.watermarks, 2204 2154 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, 2205 2155 false); ··· 2212 2162 if (hubbub->funcs->program_compbuf_size) { 2213 2163 if (context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes) { 2214 2164 compbuf_size_kb = context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes; 2215 - dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.dml.ip.min_comp_buffer_size_kbytes); 2165 + dc->optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.dml.ip.min_comp_buffer_size_kbytes); 2216 2166 } else { 2217 2167 compbuf_size_kb = context->bw_ctx.bw.dcn.compbuf_size_kb; 2218 - dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.bw.dcn.compbuf_size_kb); 2168 + dc->optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.bw.dcn.compbuf_size_kb); 2219 2169 } 2220 2170 2221 2171 hubbub->funcs->program_compbuf_size(hubbub, compbuf_size_kb, false); ··· 2233 2183 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 2234 2184 2235 2185 // At optimize don't need to restore the original watermark value 2236 - if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) { 2186 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_NONE) { 2237 2187 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U; 2238 2188 break; 2239 2189 } ··· 2267 2217 dc->clk_mgr, 2268 2218 context, 2269 2219 true); 2270 - if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) { 2220 + if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW && 2221 + !dc->debug.disable_extblankadj) { 2271 2222 for (i = 0; i < dc->res_pool->pipe_count; ++i) { 2272 2223 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2273 2224 ··· 2661 2610 * the case where the same symclk is shared across multiple otg 2662 2611 * instances 2663 2612 */ 2664 - link->phy_state.symclk_ref_cnts.otg = 0; 2613 + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 2614 + link->phy_state.symclk_ref_cnts.otg = 0; 2665 2615 if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) { 2666 2616 link_hwss->disable_link_output(link, 2667 2617 &pipe_ctx->link_res, pipe_ctx->stream->signal); ··· 2995 2943 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; 2996 2944 pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; 2997 2945 /*to do*/ 2998 - hws->funcs.plane_atomic_disconnect(dc, pipe_ctx); 2946 + hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx); 2999 2947 } 3000 2948 3001 2949 /* initialize DWB pointer to MCIF_WB */ ··· 3012 2960 for (i = 0; i < dc->res_pool->pipe_count; i++) { 3013 2961 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 3014 2962 3015 - dc->hwss.disable_plane(dc, pipe_ctx); 2963 + dc->hwss.disable_plane(dc, context, pipe_ctx); 3016 2964 3017 2965 pipe_ctx->stream_res.tg = NULL; 3018 2966 pipe_ctx->plane_res.hubp = NULL;
+1 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
··· 52 52 void dcn20_enable_stream(struct pipe_ctx *pipe_ctx); 53 53 void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, 54 54 struct dc_link_settings *link_settings); 55 - void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); 55 + void dcn20_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx); 56 56 void dcn20_disable_pixel_data( 57 57 struct dc *dc, 58 58 struct pipe_ctx *pipe_ctx,
+5 -3
drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
··· 320 320 res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; 321 321 pipe_ctx->stream_res.opp = res_pool->opps[i]; 322 322 /*To do: number of MPCC != number of opp*/ 323 - hws->funcs.plane_atomic_disconnect(dc, pipe_ctx); 323 + hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx); 324 324 } 325 325 326 326 /* initialize DWB pointer to MCIF_WB */ ··· 337 337 for (i = 0; i < res_pool->pipe_count; i++) { 338 338 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 339 339 340 - dc->hwss.disable_plane(dc, pipe_ctx); 340 + dc->hwss.disable_plane(dc, context, pipe_ctx); 341 341 342 342 pipe_ctx->stream_res.tg = NULL; 343 343 pipe_ctx->plane_res.hubp = NULL; ··· 369 369 } 370 370 371 371 /* trigger HW to start disconnect plane from stream on the next vsync */ 372 - void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) 372 + void dcn201_plane_atomic_disconnect(struct dc *dc, 373 + struct dc_state *state, 374 + struct pipe_ctx *pipe_ctx) 373 375 { 374 376 struct dce_hwseq *hws = dc->hwseq; 375 377 struct hubp *hubp = pipe_ctx->plane_res.hubp;
+1 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h
··· 33 33 void dcn201_unblank_stream(struct pipe_ctx *pipe_ctx, 34 34 struct dc_link_settings *link_settings); 35 35 void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx); 36 - void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx); 36 + void dcn201_plane_atomic_disconnect(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx); 37 37 void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx); 38 38 void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx); 39 39 void dcn201_pipe_control_lock(
+2 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c
··· 154 154 cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; 155 155 cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); 156 156 157 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 157 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 158 158 159 159 return true; 160 160 } ··· 173 173 cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst); 174 174 cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); 175 175 176 - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 176 + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 177 177 } 178 178 179 179 void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
+11 -8
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
··· 51 51 #include "dcn20/dcn20_hwseq.h" 52 52 #include "dcn30/dcn30_resource.h" 53 53 #include "link.h" 54 - 54 + #include "dc_state_priv.h" 55 55 56 56 57 57 ··· 476 476 int i; 477 477 int edp_num; 478 478 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 479 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 479 480 480 481 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) 481 482 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); ··· 613 612 for (i = 0; i < dc->link_count; i++) { 614 613 struct dc_link *link = dc->links[i]; 615 614 616 - if (link->panel_cntl) 615 + if (link->panel_cntl) { 617 616 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 617 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 618 + } 618 619 } 619 620 620 621 for (i = 0; i < dc->res_pool->pipe_count; i++) { 621 622 if (abms[i] != NULL) 622 - abms[i]->funcs->abm_init(abms[i], backlight); 623 + abms[i]->funcs->abm_init(abms[i], backlight, user_level); 623 624 } 624 625 625 626 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ ··· 757 754 cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ; 758 755 cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); 759 756 760 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 757 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 761 758 762 759 return true; 763 760 } ··· 879 876 cmd.mall.cursor_height = cursor_attr.height; 880 877 cmd.mall.cursor_pitch = cursor_attr.pitch; 881 878 882 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 879 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 883 880 884 881 /* Use copied cursor, and it's okay to not switch back */ 885 882 cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part; ··· 895 892 cmd.mall.tmr_scale = tmr_scale; 896 893 cmd.mall.debug_bits = dc->debug.mall_error_as_fatal; 897 894 898 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 895 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 899 896 900 897 return true; 901 898 } ··· 912 909 cmd.mall.header.payload_bytes = 913 910 sizeof(cmd.mall) - sizeof(cmd.mall.header); 914 911 915 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 912 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 916 913 917 914 return true; 918 915 } ··· 969 966 if (!pipe->stream) 970 967 continue; 971 968 972 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 969 + if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_MAIN) { 973 970 subvp_in_use = true; 974 971 break; 975 972 }
+9 -5
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
··· 113 113 struct dc_bios *dcb = dc->ctx->dc_bios; 114 114 struct resource_pool *res_pool = dc->res_pool; 115 115 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 116 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 116 117 int i; 117 118 118 119 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) ··· 225 224 for (i = 0; i < dc->link_count; i++) { 226 225 struct dc_link *link = dc->links[i]; 227 226 228 - if (link->panel_cntl) 227 + if (link->panel_cntl) { 229 228 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 229 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 230 + } 230 231 } 231 232 232 233 for (i = 0; i < dc->res_pool->pipe_count; i++) { 233 234 if (abms[i] != NULL) 234 - abms[i]->funcs->abm_init(abms[i], backlight); 235 + abms[i]->funcs->abm_init(abms[i], backlight, user_level); 235 236 } 236 237 237 238 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ ··· 419 416 cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT; 420 417 cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT; 421 418 422 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 419 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 423 420 } 424 421 425 422 void dcn31_z10_restore(const struct dc *dc) ··· 437 434 cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT; 438 435 cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_RESTORE; 439 436 440 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 437 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 441 438 } 442 439 443 440 void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) ··· 527 524 if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass) 528 525 pipe_ctx->stream_res.tg->funcs->set_odm_bypass( 529 526 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); 530 - pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; 527 + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 528 + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; 531 529 532 530 if (pipe_ctx->stream_res.tg->funcs->set_drr) 533 531 pipe_ctx->stream_res.tg->funcs->set_drr(
+46 -45
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
··· 51 51 #include "dcn32/dcn32_resource.h" 52 52 #include "link.h" 53 53 #include "../dcn20/dcn20_hwseq.h" 54 + #include "dc_state_priv.h" 54 55 55 56 #define DC_LOGGER_INIT(logger) 56 57 ··· 278 277 cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ; 279 278 cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); 280 279 281 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 280 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 282 281 283 282 return true; 284 283 } ··· 312 311 cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); 313 312 cmd.cab.cab_alloc_ways = (uint8_t)ways; 314 313 315 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 314 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 316 315 317 316 return true; 318 317 } ··· 328 327 cmd.cab.header.payload_bytes = 329 328 sizeof(cmd.cab) - sizeof(cmd.cab.header); 330 329 331 - dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 330 + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 332 331 333 332 return true; 334 333 } ··· 349 348 for (i = 0; i < dc->res_pool->pipe_count; i++) { 350 349 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 351 350 352 - if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.paired_stream && 353 - pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) { 351 + if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) { 354 352 // There is at least 1 SubVP pipe, so enable SubVP 355 353 enable_subvp = true; 356 354 break; ··· 375 375 bool subvp_immediate_flip = false; 376 376 bool subvp_in_use = false; 377 377 struct pipe_ctx *pipe; 378 + enum mall_stream_type pipe_mall_type = SUBVP_NONE; 378 379 379 380 for (i = 0; i < dc->res_pool->pipe_count; i++) { 380 381 pipe = &context->res_ctx.pipe_ctx[i]; 382 + pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe); 381 383 382 - if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 384 + if (pipe->stream && pipe->plane_state && pipe_mall_type == SUBVP_MAIN) { 383 385 subvp_in_use = true; 384 386 break; 385 387 } 386 388 } 387 389 388 390 if (top_pipe_to_program && top_pipe_to_program->stream && top_pipe_to_program->plane_state) { 389 - if (top_pipe_to_program->stream->mall_stream_config.type == SUBVP_MAIN && 391 + if (dc_state_get_pipe_subvp_type(context, top_pipe_to_program) == SUBVP_MAIN && 390 392 top_pipe_to_program->plane_state->flip_immediate) 391 393 subvp_immediate_flip = true; 392 394 } ··· 400 398 if (!lock) { 401 399 for (i = 0; i < dc->res_pool->pipe_count; i++) { 402 400 pipe = &context->res_ctx.pipe_ctx[i]; 403 - if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN && 401 + if (pipe->stream && pipe->plane_state && pipe_mall_type == SUBVP_MAIN && 404 402 should_lock_all_pipes) 405 403 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK); 406 404 } ··· 418 416 { 419 417 struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc; 420 418 bool lock = params->subvp_pipe_control_lock_fast_params.lock; 421 - struct pipe_ctx *pipe_ctx = params->subvp_pipe_control_lock_fast_params.pipe_ctx; 422 - bool subvp_immediate_flip = false; 423 - 424 - if (pipe_ctx && pipe_ctx->stream && pipe_ctx->plane_state) { 425 - if (pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN && 426 - pipe_ctx->plane_state->flip_immediate) 427 - subvp_immediate_flip = true; 428 - } 419 + bool subvp_immediate_flip = params->subvp_pipe_control_lock_fast_params.subvp_immediate_flip; 429 420 430 421 // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared. 431 422 if (subvp_immediate_flip) { ··· 604 609 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 605 610 struct hubp *hubp = pipe->plane_res.hubp; 606 611 607 - if (!pipe->stream || !(pipe->stream->mall_stream_config.type == SUBVP_MAIN || 612 + if (!pipe->stream || !(dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN || 608 613 pipe->stream->fpo_in_use)) { 609 614 if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) 610 615 hubp->funcs->hubp_update_force_pstate_disallow(hubp, false); ··· 619 624 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 620 625 struct hubp *hubp = pipe->plane_res.hubp; 621 626 622 - if (pipe->stream && (pipe->stream->mall_stream_config.type == SUBVP_MAIN || 627 + if (pipe->stream && (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN || 623 628 pipe->stream->fpo_in_use)) { 624 629 if (hubp && hubp->funcs->hubp_update_force_pstate_disallow) 625 630 hubp->funcs->hubp_update_force_pstate_disallow(hubp, true); ··· 666 671 if (cursor_size > 16384) 667 672 cache_cursor = true; 668 673 669 - if (pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 670 - hubp->funcs->hubp_update_mall_sel(hubp, 1, false); 674 + if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 675 + hubp->funcs->hubp_update_mall_sel(hubp, 1, false); 671 676 } else { 672 677 // MALL not supported with Stereo3D 673 678 hubp->funcs->hubp_update_mall_sel(hubp, ··· 709 714 * see if CURSOR_REQ_MODE will be back to 1 for SubVP 710 715 * when it should be 0 for MPO 711 716 */ 712 - if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { 717 + if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) 713 718 hubp->funcs->hubp_prepare_subvp_buffering(hubp, true); 714 - } 715 719 } 716 720 } 717 721 } ··· 753 759 int i; 754 760 int edp_num; 755 761 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 762 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 756 763 757 764 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) 758 765 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); ··· 908 913 for (i = 0; i < dc->link_count; i++) { 909 914 struct dc_link *link = dc->links[i]; 910 915 911 - if (link->panel_cntl) 916 + if (link->panel_cntl) { 912 917 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 918 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 919 + } 913 920 } 914 921 915 922 for (i = 0; i < dc->res_pool->pipe_count; i++) { 916 923 if (abms[i] != NULL && abms[i]->funcs != NULL) 917 - abms[i]->funcs->abm_init(abms[i], backlight); 924 + abms[i]->funcs->abm_init(abms[i], backlight, user_level); 918 925 } 919 926 920 927 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ ··· 957 960 dc->caps.dmub_caps.subvp_psr = dc->ctx->dmub_srv->dmub->feature_caps.subvp_psr_support; 958 961 dc->caps.dmub_caps.gecc_enable = dc->ctx->dmub_srv->dmub->feature_caps.gecc_enable; 959 962 dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; 963 + 964 + if (dc->ctx->dmub_srv->dmub->fw_version < 965 + DMUB_FW_VERSION(7, 0, 35)) { 966 + dc->debug.force_disable_subvp = true; 967 + dc->debug.disable_fpo_optimizations = true; 968 + } 960 969 } 961 970 } 962 971 ··· 1225 1222 continue; 1226 1223 1227 1224 if ((pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal)) 1228 - && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { 1225 + && dc_state_get_pipe_subvp_type(dc->current_state, pipe) != SUBVP_PHANTOM) { 1229 1226 pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg); 1230 1227 reset_sync_context_for_pipe(dc, context, i); 1231 1228 otg_disabled[i] = true; ··· 1376 1373 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1377 1374 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1378 1375 1379 - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN && 1380 - pipe->stream->mall_stream_config.paired_stream == phantom_pipe->stream) { 1376 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN && 1377 + dc_state_get_paired_subvp_stream(context, pipe->stream) == phantom_pipe->stream) { 1381 1378 if (pipe->plane_state && pipe->plane_state->update_flags.bits.position_change) { 1382 1379 1383 1380 phantom_plane->src_rect.x = pipe->plane_state->src_rect.x; ··· 1402 1399 void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe) 1403 1400 { 1404 1401 phantom_pipe->update_flags.raw = 0; 1405 - if (phantom_pipe->stream && phantom_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 1406 - if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) { 1407 - phantom_pipe->update_flags.bits.enable = 1; 1408 - phantom_pipe->update_flags.bits.mpcc = 1; 1409 - phantom_pipe->update_flags.bits.dppclk = 1; 1410 - phantom_pipe->update_flags.bits.hubp_interdependent = 1; 1411 - phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1; 1412 - phantom_pipe->update_flags.bits.gamut_remap = 1; 1413 - phantom_pipe->update_flags.bits.scaler = 1; 1414 - phantom_pipe->update_flags.bits.viewport = 1; 1415 - phantom_pipe->update_flags.bits.det_size = 1; 1416 - if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) { 1417 - phantom_pipe->update_flags.bits.odm = 1; 1418 - phantom_pipe->update_flags.bits.global_sync = 1; 1419 - } 1402 + if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) { 1403 + phantom_pipe->update_flags.bits.enable = 1; 1404 + phantom_pipe->update_flags.bits.mpcc = 1; 1405 + phantom_pipe->update_flags.bits.dppclk = 1; 1406 + phantom_pipe->update_flags.bits.hubp_interdependent = 1; 1407 + phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1; 1408 + phantom_pipe->update_flags.bits.gamut_remap = 1; 1409 + phantom_pipe->update_flags.bits.scaler = 1; 1410 + phantom_pipe->update_flags.bits.viewport = 1; 1411 + phantom_pipe->update_flags.bits.det_size = 1; 1412 + if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) { 1413 + phantom_pipe->update_flags.bits.odm = 1; 1414 + phantom_pipe->update_flags.bits.global_sync = 1; 1420 1415 } 1421 1416 } 1422 1417 } ··· 1486 1485 * pipe, wait for the double buffer update to complete first before we do 1487 1486 * ANY phantom pipe programming. 1488 1487 */ 1489 - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM && 1490 - old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) { 1488 + if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM && 1489 + old_pipe->stream && dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) != SUBVP_PHANTOM) { 1491 1490 old_pipe->stream_res.tg->funcs->wait_for_state( 1492 1491 old_pipe->stream_res.tg, 1493 1492 CRTC_STATE_VBLANK); ··· 1499 1498 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1500 1499 struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; 1501 1500 1502 - if (new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 1501 + if (new_pipe->stream && dc_state_get_pipe_subvp_type(context, new_pipe) == SUBVP_PHANTOM) { 1503 1502 // If old context or new context has phantom pipes, apply 1504 1503 // the phantom timings now. We can't change the phantom 1505 1504 // pipe configuration safely without driver acquiring
+94 -39
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
··· 56 56 #include "dcn30/dcn30_cm_common.h" 57 57 #include "dcn31/dcn31_hwseq.h" 58 58 #include "dcn20/dcn20_hwseq.h" 59 + #include "dc_state_priv.h" 59 60 60 61 #define DC_LOGGER_INIT(logger) \ 61 62 struct dal_logger *dc_logger = logger ··· 134 133 struct dc_bios *dcb = dc->ctx->dc_bios; 135 134 struct resource_pool *res_pool = dc->res_pool; 136 135 uint32_t backlight = MAX_BACKLIGHT_LEVEL; 136 + uint32_t user_level = MAX_BACKLIGHT_LEVEL; 137 137 int i; 138 138 139 139 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) ··· 281 279 for (i = 0; i < dc->link_count; i++) { 282 280 struct dc_link *link = dc->links[i]; 283 281 284 - if (link->panel_cntl) 282 + if (link->panel_cntl) { 285 283 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); 284 + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; 285 + } 286 286 } 287 287 if (dc->ctx->dmub_srv) { 288 288 for (i = 0; i < dc->res_pool->pipe_count; i++) { 289 289 if (abms[i] != NULL && abms[i]->funcs != NULL) 290 - abms[i]->funcs->abm_init(abms[i], backlight); 290 + abms[i]->funcs->abm_init(abms[i], backlight, user_level); 291 291 } 292 292 } 293 293 ··· 691 687 } 692 688 693 689 // TODO: review other cases when idle optimization is allowed 694 - 695 - if (!enable) 696 - dc_dmub_srv_exit_low_power_state(dc); 697 - else 698 - dc_dmub_srv_notify_idle(dc, enable); 690 + dc_dmub_srv_apply_idle_power_optimizations(dc, enable); 699 691 700 692 return true; 701 693 } ··· 701 701 if (dc->debug.disable_z10) 702 702 return; 703 703 704 - dc_dmub_srv_exit_low_power_state(dc); 704 + dc_dmub_srv_apply_idle_power_optimizations(dc, false); 705 705 706 706 dcn31_z10_restore(dc); 707 707 } ··· 817 817 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; 818 818 pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; 819 819 820 - hws->funcs.plane_atomic_disconnect(dc, pipe_ctx); 820 + hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx); 821 821 822 822 if (tg->funcs->is_tg_enabled(tg)) 823 823 tg->funcs->unlock(tg); 824 824 825 - dc->hwss.disable_plane(dc, pipe_ctx); 825 + dc->hwss.disable_plane(dc, context, pipe_ctx); 826 826 827 827 pipe_ctx->stream_res.tg = NULL; 828 828 pipe_ctx->plane_res.hubp = NULL; ··· 949 949 pipe_ctx->plane_state = NULL; 950 950 } 951 951 952 - void dcn35_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) 952 + void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) 953 953 { 954 954 struct dce_hwseq *hws = dc->hwseq; 955 - bool is_phantom = pipe_ctx->plane_state && pipe_ctx->plane_state->is_phantom; 955 + bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM; 956 956 struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL; 957 957 958 958 DC_LOGGER_INIT(dc->ctx->logger); ··· 1123 1123 update_state->pg_res_update[PG_HPO] = true; 1124 1124 1125 1125 } 1126 + 1126 1127 /** 1127 - * power down sequence 1128 - * ONO Region 3, DCPG 25: hpo - SKIPPED 1129 - * ONO Region 4, DCPG 0: dchubp0, dpp0 1130 - * ONO Region 6, DCPG 1: dchubp1, dpp1 1131 - * ONO Region 8, DCPG 2: dchubp2, dpp2 1132 - * ONO Region 10, DCPG 3: dchubp3, dpp3 1133 - * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will pwr dwn at IPS2 entry 1134 - * ONO Region 5, DCPG 16: dsc0 1135 - * ONO Region 7, DCPG 17: dsc1 1136 - * ONO Region 9, DCPG 18: dsc2 1137 - * ONO Region 11, DCPG 19: dsc3 1138 - * ONO Region 2, DCPG 24: mpc opp optc dwb 1139 - * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed 1140 - */ 1128 + * dcn35_hw_block_power_down() - power down sequence 1129 + * 1130 + * The following sequence describes the ON-OFF (ONO) for power down: 1131 + * 1132 + * ONO Region 3, DCPG 25: hpo - SKIPPED 1133 + * ONO Region 4, DCPG 0: dchubp0, dpp0 1134 + * ONO Region 6, DCPG 1: dchubp1, dpp1 1135 + * ONO Region 8, DCPG 2: dchubp2, dpp2 1136 + * ONO Region 10, DCPG 3: dchubp3, dpp3 1137 + * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will pwr dwn at IPS2 entry 1138 + * ONO Region 5, DCPG 16: dsc0 1139 + * ONO Region 7, DCPG 17: dsc1 1140 + * ONO Region 9, DCPG 18: dsc2 1141 + * ONO Region 11, DCPG 19: dsc3 1142 + * ONO Region 2, DCPG 24: mpc opp optc dwb 1143 + * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed 1144 + * 1145 + * @dc: Current DC state 1146 + * @update_state: update PG sequence states for HW block 1147 + */ 1141 1148 void dcn35_hw_block_power_down(struct dc *dc, 1142 1149 struct pg_block_update *update_state) 1143 1150 { ··· 1182 1175 //domain22, 23, 25 currently always on. 1183 1176 1184 1177 } 1178 + 1185 1179 /** 1186 - * power up sequence 1187 - * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED 1188 - * ONO Region 2, DCPG 24: mpc opp optc dwb 1189 - * ONO Region 5, DCPG 16: dsc0 1190 - * ONO Region 7, DCPG 17: dsc1 1191 - * ONO Region 9, DCPG 18: dsc2 1192 - * ONO Region 11, DCPG 19: dsc3 1193 - * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit 1194 - * ONO Region 4, DCPG 0: dchubp0, dpp0 1195 - * ONO Region 6, DCPG 1: dchubp1, dpp1 1196 - * ONO Region 8, DCPG 2: dchubp2, dpp2 1197 - * ONO Region 10, DCPG 3: dchubp3, dpp3 1198 - * ONO Region 3, DCPG 25: hpo - SKIPPED 1180 + * dcn35_hw_block_power_up() - power up sequence 1181 + * 1182 + * The following sequence describes the ON-OFF (ONO) for power up: 1183 + * 1184 + * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED 1185 + * ONO Region 2, DCPG 24: mpc opp optc dwb 1186 + * ONO Region 5, DCPG 16: dsc0 1187 + * ONO Region 7, DCPG 17: dsc1 1188 + * ONO Region 9, DCPG 18: dsc2 1189 + * ONO Region 11, DCPG 19: dsc3 1190 + * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit 1191 + * ONO Region 4, DCPG 0: dchubp0, dpp0 1192 + * ONO Region 6, DCPG 1: dchubp1, dpp1 1193 + * ONO Region 8, DCPG 2: dchubp2, dpp2 1194 + * ONO Region 10, DCPG 3: dchubp3, dpp3 1195 + * ONO Region 3, DCPG 25: hpo - SKIPPED 1196 + * 1197 + * @dc: Current DC state 1198 + * @update_state: update PG sequence states for HW block 1199 1199 */ 1200 1200 void dcn35_hw_block_power_up(struct dc *dc, 1201 1201 struct pg_block_update *update_state) ··· 1328 1314 return dc->clk_mgr->funcs->get_idle_state(dc->clk_mgr); 1329 1315 1330 1316 return 0; 1317 + } 1318 + 1319 + void dcn35_set_drr(struct pipe_ctx **pipe_ctx, 1320 + int num_pipes, struct dc_crtc_timing_adjust adjust) 1321 + { 1322 + int i = 0; 1323 + struct drr_params params = {0}; 1324 + // DRR set trigger event mapped to OTG_TRIG_A (bit 11) for manual control flow 1325 + unsigned int event_triggers = 0x800; 1326 + // Note DRR trigger events are generated regardless of whether num frames met. 1327 + unsigned int num_frames = 2; 1328 + 1329 + params.vertical_total_max = adjust.v_total_max; 1330 + params.vertical_total_min = adjust.v_total_min; 1331 + params.vertical_total_mid = adjust.v_total_mid; 1332 + params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num; 1333 + 1334 + for (i = 0; i < num_pipes; i++) { 1335 + if ((pipe_ctx[i]->stream_res.tg != NULL) && pipe_ctx[i]->stream_res.tg->funcs) { 1336 + struct dc_crtc_timing *timing = &pipe_ctx[i]->stream->timing; 1337 + struct dc *dc = pipe_ctx[i]->stream->ctx->dc; 1338 + 1339 + if (dc->debug.static_screen_wait_frames) { 1340 + unsigned int frame_rate = timing->pix_clk_100hz / (timing->h_total * timing->v_total); 1341 + 1342 + if (frame_rate >= 120 && dc->caps.ips_support && 1343 + dc->config.disable_ips != DMUB_IPS_DISABLE_ALL) { 1344 + /*ips enable case*/ 1345 + num_frames = 2 * (frame_rate % 60); 1346 + } 1347 + } 1348 + if (pipe_ctx[i]->stream_res.tg->funcs->set_drr) 1349 + pipe_ctx[i]->stream_res.tg->funcs->set_drr( 1350 + pipe_ctx[i]->stream_res.tg, &params); 1351 + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) 1352 + if (pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control) 1353 + pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( 1354 + pipe_ctx[i]->stream_res.tg, 1355 + event_triggers, num_frames); 1356 + } 1357 + } 1331 1358 }
+5 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
··· 57 57 void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx); 58 58 void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, 59 59 struct dc_state *context); 60 - void dcn35_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx); 60 + void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx); 61 61 62 62 void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, 63 63 struct pg_block_update *update_state); ··· 86 86 87 87 void dcn35_set_idle_state(const struct dc *dc, bool allow_idle); 88 88 uint32_t dcn35_get_idle_state(const struct dc *dc); 89 + 90 + void dcn35_set_drr(struct pipe_ctx **pipe_ctx, 91 + int num_pipes, struct dc_crtc_timing_adjust adjust); 92 + 89 93 #endif /* __DC_HWSS_DCN35_H__ */
+172
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright 2023 Advanced Micro Devices, Inc. 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a 6 + * copy of this software and associated documentation files (the "Software"), 7 + * to deal in the Software without restriction, including without limitation 8 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 + * and/or sell copies of the Software, and to permit persons to whom the 10 + * Software is furnished to do so, subject to the following conditions: 11 + * 12 + * The above copyright notice and this permission notice shall be included in 13 + * all copies or substantial portions of the Software. 14 + * 15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 + * OTHER DEALINGS IN THE SOFTWARE. 22 + * 23 + * Authors: AMD 24 + * 25 + */ 26 + 27 + #include "dce110/dce110_hwseq.h" 28 + #include "dcn10/dcn10_hwseq.h" 29 + #include "dcn20/dcn20_hwseq.h" 30 + #include "dcn21/dcn21_hwseq.h" 31 + #include "dcn30/dcn30_hwseq.h" 32 + #include "dcn301/dcn301_hwseq.h" 33 + #include "dcn31/dcn31_hwseq.h" 34 + #include "dcn32/dcn32_hwseq.h" 35 + #include "dcn35/dcn35_hwseq.h" 36 + 37 + #include "dcn35_init.h" 38 + 39 + static const struct hw_sequencer_funcs dcn35_funcs = { 40 + .program_gamut_remap = dcn30_program_gamut_remap, 41 + .init_hw = dcn35_init_hw, 42 + .power_down_on_boot = dcn35_power_down_on_boot, 43 + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 44 + .apply_ctx_for_surface = NULL, 45 + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, 46 + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, 47 + .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, 48 + .update_plane_addr = dcn20_update_plane_addr, 49 + .update_dchub = dcn10_update_dchub, 50 + .update_pending_status = dcn10_update_pending_status, 51 + .program_output_csc = dcn20_program_output_csc, 52 + .enable_accelerated_mode = dce110_enable_accelerated_mode, 53 + .enable_timing_synchronization = dcn10_enable_timing_synchronization, 54 + .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, 55 + .update_info_frame = dcn31_update_info_frame, 56 + .send_immediate_sdp_message = dcn10_send_immediate_sdp_message, 57 + .enable_stream = dcn20_enable_stream, 58 + .disable_stream = dce110_disable_stream, 59 + .unblank_stream = dcn32_unblank_stream, 60 + .blank_stream = dce110_blank_stream, 61 + .enable_audio_stream = dce110_enable_audio_stream, 62 + .disable_audio_stream = dce110_disable_audio_stream, 63 + .disable_plane = dcn35_disable_plane, 64 + .disable_pixel_data = dcn20_disable_pixel_data, 65 + .pipe_control_lock = dcn20_pipe_control_lock, 66 + .interdependent_update_lock = dcn10_lock_all_pipes, 67 + .cursor_lock = dcn10_cursor_lock, 68 + .prepare_bandwidth = dcn35_prepare_bandwidth, 69 + .optimize_bandwidth = dcn35_optimize_bandwidth, 70 + .update_bandwidth = dcn20_update_bandwidth, 71 + .set_drr = dcn35_set_drr, 72 + .get_position = dcn10_get_position, 73 + .set_static_screen_control = dcn30_set_static_screen_control, 74 + .setup_stereo = dcn10_setup_stereo, 75 + .set_avmute = dcn30_set_avmute, 76 + .log_hw_state = dcn10_log_hw_state, 77 + .get_hw_state = dcn10_get_hw_state, 78 + .clear_status_bits = dcn10_clear_status_bits, 79 + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, 80 + .edp_backlight_control = dce110_edp_backlight_control, 81 + .edp_power_control = dce110_edp_power_control, 82 + .edp_wait_for_T12 = dce110_edp_wait_for_T12, 83 + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, 84 + .set_cursor_position = dcn10_set_cursor_position, 85 + .set_cursor_attribute = dcn10_set_cursor_attribute, 86 + .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, 87 + .setup_periodic_interrupt = dcn10_setup_periodic_interrupt, 88 + .set_clock = dcn10_set_clock, 89 + .get_clock = dcn10_get_clock, 90 + .program_triplebuffer = dcn20_program_triple_buffer, 91 + .enable_writeback = dcn30_enable_writeback, 92 + .disable_writeback = dcn30_disable_writeback, 93 + .update_writeback = dcn30_update_writeback, 94 + .mmhubbub_warmup = dcn30_mmhubbub_warmup, 95 + .dmdata_status_done = dcn20_dmdata_status_done, 96 + .program_dmdata_engine = dcn30_program_dmdata_engine, 97 + .set_dmdata_attributes = dcn20_set_dmdata_attributes, 98 + .init_sys_ctx = dcn31_init_sys_ctx, 99 + .init_vm_ctx = dcn20_init_vm_ctx, 100 + .set_flip_control_gsl = dcn20_set_flip_control_gsl, 101 + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, 102 + .calc_vupdate_position = dcn10_calc_vupdate_position, 103 + .power_down = dce110_power_down, 104 + .set_backlight_level = dcn21_set_backlight_level, 105 + .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, 106 + .set_pipe = dcn21_set_pipe, 107 + .enable_lvds_link_output = dce110_enable_lvds_link_output, 108 + .enable_tmds_link_output = dce110_enable_tmds_link_output, 109 + .enable_dp_link_output = dce110_enable_dp_link_output, 110 + .disable_link_output = dcn32_disable_link_output, 111 + .z10_restore = dcn35_z10_restore, 112 + .z10_save_init = dcn31_z10_save_init, 113 + .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, 114 + .optimize_pwr_state = dcn21_optimize_pwr_state, 115 + .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, 116 + .update_visual_confirm_color = dcn10_update_visual_confirm_color, 117 + .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, 118 + .update_dsc_pg = dcn32_update_dsc_pg, 119 + .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, 120 + .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, 121 + .hw_block_power_up = dcn35_hw_block_power_up, 122 + .hw_block_power_down = dcn35_hw_block_power_down, 123 + .root_clock_control = dcn35_root_clock_control, 124 + .set_idle_state = dcn35_set_idle_state, 125 + .get_idle_state = dcn35_get_idle_state 126 + }; 127 + 128 + static const struct hwseq_private_funcs dcn35_private_funcs = { 129 + .init_pipes = dcn35_init_pipes, 130 + .update_plane_addr = dcn20_update_plane_addr, 131 + .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, 132 + .update_mpcc = dcn20_update_mpcc, 133 + .set_input_transfer_func = dcn32_set_input_transfer_func, 134 + .set_output_transfer_func = dcn32_set_output_transfer_func, 135 + .power_down = dce110_power_down, 136 + .enable_display_power_gating = dcn10_dummy_display_power_gating, 137 + .blank_pixel_data = dcn20_blank_pixel_data, 138 + .reset_hw_ctx_wrap = dcn31_reset_hw_ctx_wrap, 139 + .enable_stream_timing = dcn20_enable_stream_timing, 140 + .edp_backlight_control = dce110_edp_backlight_control, 141 + .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, 142 + .did_underflow_occur = dcn10_did_underflow_occur, 143 + .init_blank = dcn20_init_blank, 144 + .disable_vga = NULL, 145 + .bios_golden_init = dcn10_bios_golden_init, 146 + .plane_atomic_disable = dcn35_plane_atomic_disable, 147 + //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ 148 + //.hubp_pg_control = dcn35_hubp_pg_control, 149 + .enable_power_gating_plane = dcn35_enable_power_gating_plane, 150 + .dpp_root_clock_control = dcn35_dpp_root_clock_control, 151 + .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, 152 + .update_odm = dcn35_update_odm, 153 + .set_hdr_multiplier = dcn10_set_hdr_multiplier, 154 + .verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high, 155 + .wait_for_blank_complete = dcn20_wait_for_blank_complete, 156 + .dccg_init = dcn20_dccg_init, 157 + .set_mcm_luts = dcn32_set_mcm_luts, 158 + .setup_hpo_hw_control = dcn35_setup_hpo_hw_control, 159 + .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, 160 + .set_pixels_per_cycle = dcn32_set_pixels_per_cycle, 161 + .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy, 162 + .dsc_pg_control = dcn35_dsc_pg_control, 163 + .dsc_pg_status = dcn32_dsc_pg_status, 164 + .enable_plane = dcn35_enable_plane, 165 + }; 166 + 167 + void dcn35_hw_sequencer_construct(struct dc *dc) 168 + { 169 + dc->hwss = dcn35_funcs; 170 + dc->hwseq->funcs = dcn35_private_funcs; 171 + 172 + }
+4
drivers/gpu/drm/amd/display/dc/hwss/dcn351/CMakeLists.txt
··· 1 + dal3_subdirectory_sources( 2 + dcn351_init.c 3 + dcn351_init.h 4 + )
+17
drivers/gpu/drm/amd/display/dc/hwss/dcn351/Makefile
··· 1 + # 2 + # (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved 3 + # 4 + # All rights reserved. This notice is intended as a precaution against 5 + # inadvertent publication and does not imply publication or any waiver 6 + # of confidentiality. The year included in the foregoing notice is the 7 + # year of creation of the work. 8 + # 9 + # Authors: AMD 10 + # 11 + # Makefile for DCN351. 12 + 13 + DCN351 = dcn351_init.o 14 + 15 + AMD_DAL_DCN351 = $(addprefix $(AMDDALPATH)/dc/dcn351/,$(DCN351)) 16 + 17 + AMD_DISPLAY_FILES += $(AMD_DAL_DCN351)
+33
drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.h
··· 1 + /* 2 + * Copyright 2023 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: AMD 23 + * 24 + */ 25 + 26 + #ifndef __DC_DCN351_INIT_H__ 27 + #define __DC_DCN351_INIT_H__ 28 + 29 + struct dc; 30 + 31 + void dcn351_hw_sequencer_construct(struct dc *dc); 32 + 33 + #endif /* __DC_DCN351_INIT_H__ */
+10 -7
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
··· 50 50 struct subvp_pipe_control_lock_fast_params { 51 51 struct dc *dc; 52 52 bool lock; 53 - struct pipe_ctx *pipe_ctx; 53 + bool subvp_immediate_flip; 54 54 }; 55 55 56 56 struct pipe_control_lock_params { ··· 200 200 struct dc_state *context); 201 201 enum dc_status (*apply_ctx_to_hw)(struct dc *dc, 202 202 struct dc_state *context); 203 - void (*disable_plane)(struct dc *dc, struct pipe_ctx *pipe_ctx); 203 + void (*disable_plane)(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx); 204 204 void (*disable_pixel_data)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool blank); 205 205 void (*apply_ctx_for_surface)(struct dc *dc, 206 206 const struct dc_stream_state *stream, ··· 248 248 void (*enable_per_frame_crtc_position_reset)(struct dc *dc, 249 249 int group_size, struct pipe_ctx *grouped_pipes[]); 250 250 void (*enable_timing_synchronization)(struct dc *dc, 251 + struct dc_state *state, 251 252 int group_index, int group_size, 252 253 struct pipe_ctx *grouped_pipes[]); 253 254 void (*enable_vblanks_synchronization)(struct dc *dc, ··· 455 454 struct tg_color *color); 456 455 457 456 void get_subvp_visual_confirm_color( 458 - struct dc *dc, 459 - struct dc_state *context, 460 457 struct pipe_ctx *pipe_ctx, 461 458 struct tg_color *color); 462 459 463 460 void get_mclk_switch_visual_confirm_color( 464 - struct dc *dc, 465 - struct dc_state *context, 466 461 struct pipe_ctx *pipe_ctx, 467 462 struct tg_color *color); 463 + 464 + void set_p_state_switch_method( 465 + struct dc *dc, 466 + struct dc_state *context, 467 + struct pipe_ctx *pipe_ctx); 468 468 469 469 void hwss_execute_sequence(struct dc *dc, 470 470 struct block_sequence block_sequence[], ··· 476 474 unsigned int dmub_cmd_count, 477 475 struct block_sequence block_sequence[], 478 476 int *num_steps, 479 - struct pipe_ctx *pipe_ctx); 477 + struct pipe_ctx *pipe_ctx, 478 + struct dc_stream_status *stream_status); 480 479 481 480 void hwss_send_dmcub_cmd(union block_sequence_params *params); 482 481
+1
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
··· 79 79 void (*update_plane_addr)(const struct dc *dc, 80 80 struct pipe_ctx *pipe_ctx); 81 81 void (*plane_atomic_disconnect)(struct dc *dc, 82 + struct dc_state *state, 82 83 struct pipe_ctx *pipe_ctx); 83 84 void (*update_mpcc)(struct dc *dc, struct pipe_ctx *pipe_ctx); 84 85 bool (*set_input_transfer_func)(struct dc *dc,
+27 -4
drivers/gpu/drm/amd/display/dc/inc/core_types.h
··· 200 200 unsigned int pipe_cnt, 201 201 unsigned int index); 202 202 203 - bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context, bool fast_update); 204 - void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context); 205 203 void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); 206 - void (*save_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); 207 - void (*restore_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); 208 204 void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx); 209 205 }; 210 206 ··· 381 385 uint32_t raw; 382 386 }; 383 387 388 + enum p_state_switch_method { 389 + P_STATE_UNKNOWN = 0, 390 + P_STATE_V_BLANK = 1, 391 + P_STATE_FPO, 392 + P_STATE_V_ACTIVE, 393 + P_STATE_SUB_VP, 394 + P_STATE_DRR_SUB_VP, 395 + P_STATE_V_BLANK_SUB_VP 396 + }; 397 + 384 398 struct pipe_ctx { 385 399 struct dc_plane_state *plane_state; 386 400 struct dc_stream_state *stream; ··· 439 433 struct dwbc *dwbc; 440 434 struct mcif_wb *mcif_wb; 441 435 union pipe_update_flags update_flags; 436 + enum p_state_switch_method p_state_type; 442 437 struct tg_color visual_confirm_color; 443 438 bool has_vactive_margin; 444 439 /* subvp_index: only valid if the pipe is a SUBVP_MAIN*/ ··· 533 526 * @stream_status: Planes status on a given stream 534 527 */ 535 528 struct dc_stream_status stream_status[MAX_PIPES]; 529 + /** 530 + * @phantom_streams: Stream state properties for phantoms 531 + */ 532 + struct dc_stream_state *phantom_streams[MAX_PHANTOM_PIPES]; 533 + /** 534 + * @phantom_planes: Planes state properties for phantoms 535 + */ 536 + struct dc_plane_state *phantom_planes[MAX_PHANTOM_PIPES]; 536 537 537 538 /** 538 539 * @stream_count: Total of streams in use ··· 548 533 uint8_t stream_count; 549 534 uint8_t stream_mask; 550 535 536 + /** 537 + * @stream_count: Total phantom streams in use 538 + */ 539 + uint8_t phantom_stream_count; 540 + /** 541 + * @stream_count: Total phantom planes in use 542 + */ 543 + uint8_t phantom_plane_count; 551 544 /** 552 545 * @res_ctx: Persistent state of resources 553 546 */
+1 -1
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
··· 36 36 }; 37 37 38 38 struct abm_funcs { 39 - void (*abm_init)(struct abm *abm, uint32_t back_light); 39 + void (*abm_init)(struct abm *abm, uint32_t back_light, uint32_t user_level); 40 40 bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); 41 41 bool (*set_abm_immediate_disable)(struct abm *abm, unsigned int panel_inst); 42 42 bool (*set_pipe)(struct abm *abm, unsigned int controller_id, unsigned int panel_inst);
+19
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
··· 62 62 uint32_t CLK4_CLK0_CURRENT_CNT; //fclk 63 63 }; 64 64 65 + struct dcn35_clk_internal { 66 + int dummy; 67 + uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk 68 + uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk 69 + uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk 70 + uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk 71 + uint32_t CLK1_CLK4_CURRENT_CNT; //dtbclk 72 + //uint32_t CLK1_CLK5_CURRENT_CNT; //dpiaclk 73 + //uint32_t CLK1_CLK6_CURRENT_CNT; //srdbgclk 74 + uint32_t CLK1_CLK3_DS_CNTL; //dcf_deep_sleep_divider 75 + uint32_t CLK1_CLK3_ALLOW_DS; //dcf_deep_sleep_allow 76 + 77 + uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass 78 + uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass 79 + uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass 80 + uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass 81 + uint32_t CLK1_CLK4_BYPASS_CNTL; //dtbclk bypass 82 + }; 83 + 65 84 struct dcn301_clk_internal { 66 85 int dummy; 67 86 uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
+1
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
··· 43 43 * to be used inside loops and for determining array sizes. 44 44 */ 45 45 #define MAX_PIPES 6 46 + #define MAX_PHANTOM_PIPES (MAX_PIPES / 2) 46 47 #define MAX_DIG_LINK_ENCODERS 7 47 48 #define MAX_DWB_PIPES 1 48 49 #define MAX_HPO_DP2_ENCODERS 4
+1
drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h
··· 40 40 unsigned int BL_PWM_PERIOD_CNTL; 41 41 unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; 42 42 unsigned int PANEL_PWRSEQ_REF_DIV2; 43 + unsigned int USER_LEVEL; 43 44 }; 44 45 45 46 struct panel_cntl_funcs {
+2
drivers/gpu/drm/amd/display/dc/inc/link.h
··· 289 289 bool (*edp_replay_residency)(const struct dc_link *link, 290 290 unsigned int *residency, const bool is_start, 291 291 const bool is_alpm); 292 + bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link, 293 + const unsigned int *power_opts, uint16_t coasting_vtotal); 292 294 293 295 bool (*edp_wait_for_t12)(struct dc_link *link); 294 296 bool (*edp_is_ilr_optimization_required)(struct dc_link *link,
+3 -4
drivers/gpu/drm/amd/display/dc/inc/resource.h
··· 573 573 574 574 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format); 575 575 576 - void get_audio_check(struct audio_info *aud_modes, 577 - struct audio_check *aud_chk); 578 - 579 576 bool get_temp_dp_link_res(struct dc_link *link, 580 577 struct link_resource *link_res, 581 578 struct dc_link_settings *link_settings); ··· 609 612 struct pipe_ctx *sec_pipe, 610 613 bool odm); 611 614 615 + bool resource_subvp_in_use(struct dc *dc, 616 + struct dc_state *context); 617 + 612 618 /* A test harness interface that modifies dp encoder resources in the given dc 613 619 * state and bypasses the need to revalidate. The interface assumes that the 614 620 * test harness interface is called with pre-validated link config stored in the ··· 622 622 struct pipe_ctx *pipe_ctx); 623 623 624 624 bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream); 625 - 626 625 #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
+7
drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
··· 172 172 REG_UPDATE(OTG_CONTROL, 173 173 OTG_MASTER_EN, 0); 174 174 175 + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, 176 + OPTC_SEG0_SRC_SEL, 0xf, 177 + OPTC_SEG1_SRC_SEL, 0xf, 178 + OPTC_SEG2_SRC_SEL, 0xf, 179 + OPTC_SEG3_SRC_SEL, 0xf, 180 + OPTC_NUM_OF_INPUT_SEGMENT, 0); 181 + 175 182 REG_UPDATE(CONTROL, 176 183 VTG0_ENABLE, 0); 177 184
+7
drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
··· 144 144 REG_UPDATE(OTG_CONTROL, 145 145 OTG_MASTER_EN, 0); 146 146 147 + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, 148 + OPTC_SEG0_SRC_SEL, 0xf, 149 + OPTC_SEG1_SRC_SEL, 0xf, 150 + OPTC_SEG2_SRC_SEL, 0xf, 151 + OPTC_SEG3_SRC_SEL, 0xf, 152 + OPTC_NUM_OF_INPUT_SEGMENT, 0); 153 + 147 154 REG_UPDATE(CONTROL, 148 155 VTG0_ENABLE, 0); 149 156
+20 -116
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
··· 89 89 #include "dcn20/dcn20_vmid.h" 90 90 #include "dml/dcn32/dcn32_fpu.h" 91 91 92 + #include "dc_state_priv.h" 93 + 92 94 #include "dml2/dml2_wrapper.h" 93 95 94 96 #define DC_LOGGER_INIT(logger) ··· 1646 1644 if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) 1647 1645 phantom_plane = prev_phantom_plane; 1648 1646 else 1649 - phantom_plane = dc_create_plane_state(dc); 1647 + phantom_plane = dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state); 1650 1648 1651 1649 memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); 1652 1650 memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality, ··· 1667 1665 phantom_plane->clip_rect.y = 0; 1668 1666 phantom_plane->clip_rect.height = phantom_stream->src.height; 1669 1667 1670 - phantom_plane->is_phantom = true; 1671 - 1672 - dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context); 1668 + dc_state_add_phantom_plane(dc, phantom_stream, phantom_plane, context); 1673 1669 1674 1670 curr_pipe = curr_pipe->bottom_pipe; 1675 1671 prev_phantom_plane = phantom_plane; ··· 1683 1683 struct dc_stream_state *phantom_stream = NULL; 1684 1684 struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; 1685 1685 1686 - phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink); 1687 - phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; 1688 - phantom_stream->dpms_off = true; 1689 - phantom_stream->mall_stream_config.type = SUBVP_PHANTOM; 1690 - phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream; 1691 - ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN; 1692 - ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream; 1686 + phantom_stream = dc_state_create_phantom_stream(dc, context, ref_pipe->stream); 1693 1687 1694 1688 /* stream has limited viewport and small timing */ 1695 1689 memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing)); ··· 1693 1699 dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx); 1694 1700 DC_FP_END(); 1695 1701 1696 - dc_add_stream_to_ctx(dc, context, phantom_stream); 1702 + dc_state_add_phantom_stream(dc, context, phantom_stream, ref_pipe->stream); 1697 1703 return phantom_stream; 1698 - } 1699 - 1700 - void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context) 1701 - { 1702 - int i; 1703 - struct dc_plane_state *phantom_plane = NULL; 1704 - struct dc_stream_state *phantom_stream = NULL; 1705 - 1706 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 1707 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1708 - 1709 - if (resource_is_pipe_type(pipe, OTG_MASTER) && 1710 - resource_is_pipe_type(pipe, DPP_PIPE) && 1711 - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 1712 - phantom_plane = pipe->plane_state; 1713 - phantom_stream = pipe->stream; 1714 - 1715 - dc_plane_state_retain(phantom_plane); 1716 - dc_stream_retain(phantom_stream); 1717 - } 1718 - } 1719 - } 1720 - 1721 - // return true if removed piped from ctx, false otherwise 1722 - bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update) 1723 - { 1724 - int i; 1725 - bool removed_pipe = false; 1726 - struct dc_plane_state *phantom_plane = NULL; 1727 - struct dc_stream_state *phantom_stream = NULL; 1728 - 1729 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 1730 - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 1731 - // build scaling params for phantom pipes 1732 - if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 1733 - phantom_plane = pipe->plane_state; 1734 - phantom_stream = pipe->stream; 1735 - 1736 - dc_rem_all_planes_for_stream(dc, pipe->stream, context); 1737 - dc_remove_stream_from_ctx(dc, context, pipe->stream); 1738 - 1739 - /* Ref count is incremented on allocation and also when added to the context. 1740 - * Therefore we must call release for the the phantom plane and stream once 1741 - * they are removed from the ctx to finally decrement the refcount to 0 to free. 1742 - */ 1743 - dc_plane_state_release(phantom_plane); 1744 - dc_stream_release(phantom_stream); 1745 - 1746 - removed_pipe = true; 1747 - } 1748 - 1749 - /* For non-full updates, a shallow copy of the current state 1750 - * is created. In this case we don't want to erase the current 1751 - * state (there can be 2 HIRQL threads, one in flip, and one in 1752 - * checkMPO) that can cause a race condition. 1753 - * 1754 - * This is just a workaround, needs a proper fix. 1755 - */ 1756 - if (!fast_update) { 1757 - // Clear all phantom stream info 1758 - if (pipe->stream) { 1759 - pipe->stream->mall_stream_config.type = SUBVP_NONE; 1760 - pipe->stream->mall_stream_config.paired_stream = NULL; 1761 - } 1762 - 1763 - if (pipe->plane_state) { 1764 - pipe->plane_state->is_phantom = false; 1765 - } 1766 - } 1767 - } 1768 - return removed_pipe; 1769 1704 } 1770 1705 1771 1706 /* TODO: Input to this function should indicate which pipe indexes (or streams) ··· 1721 1798 // We determine which phantom pipes were added by comparing with 1722 1799 // the phantom stream. 1723 1800 if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream && 1724 - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { 1801 + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 1725 1802 pipe->stream->use_dynamic_meta = false; 1726 1803 pipe->plane_state->flip_immediate = false; 1727 1804 if (!resource_build_scaling_params(pipe)) { ··· 1740 1817 int vlevel = 0; 1741 1818 int pipe_cnt = 0; 1742 1819 display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); 1743 - struct mall_temp_config mall_temp_config; 1744 1820 1745 1821 /* To handle Freesync properly, setting FreeSync DML parameters 1746 1822 * to its default state for the first stage of validation ··· 1749 1827 1750 1828 DC_LOGGER_INIT(dc->ctx->logger); 1751 1829 1752 - /* For fast validation, there are situations where a shallow copy of 1753 - * of the dc->current_state is created for the validation. In this case 1754 - * we want to save and restore the mall config because we always 1755 - * teardown subvp at the beginning of validation (and don't attempt 1756 - * to add it back if it's fast validation). If we don't restore the 1757 - * subvp config in cases of fast validation + shallow copy of the 1758 - * dc->current_state, the dc->current_state will have a partially 1759 - * removed subvp state when we did not intend to remove it. 1760 - */ 1761 - if (fast_validate) { 1762 - memset(&mall_temp_config, 0, sizeof(mall_temp_config)); 1763 - dcn32_save_mall_state(dc, context, &mall_temp_config); 1764 - } 1765 - 1766 1830 BW_VAL_TRACE_COUNT(); 1767 1831 1768 1832 DC_FP_START(); 1769 1833 out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); 1770 1834 DC_FP_END(); 1771 - 1772 - if (fast_validate) 1773 - dcn32_restore_mall_state(dc, context, &mall_temp_config); 1774 1835 1775 1836 if (pipe_cnt == 0) 1776 1837 goto validate_out; ··· 1838 1933 * This is just a workaround -- needs a proper fix. 1839 1934 */ 1840 1935 if (!fast_validate) { 1841 - switch (pipe->stream->mall_stream_config.type) { 1936 + switch (dc_state_get_pipe_subvp_type(context, pipe)) { 1842 1937 case SUBVP_MAIN: 1843 1938 pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport; 1844 1939 subvp_in_use = true; ··· 1899 1994 1900 1995 static struct dc_cap_funcs cap_funcs = { 1901 1996 .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, 1902 - .get_subvp_en = dcn32_subvp_in_use, 1997 + .get_subvp_en = resource_subvp_in_use, 1903 1998 }; 1904 1999 1905 2000 void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context, ··· 1942 2037 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, 1943 2038 .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, 1944 2039 .add_phantom_pipes = dcn32_add_phantom_pipes, 1945 - .remove_phantom_pipes = dcn32_remove_phantom_pipes, 1946 - .retain_phantom_pipes = dcn32_retain_phantom_pipes, 1947 - .save_mall_state = dcn32_save_mall_state, 1948 - .restore_mall_state = dcn32_restore_mall_state, 1949 2040 .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, 1950 2041 }; 1951 2042 ··· 2355 2454 dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; 2356 2455 2357 2456 dc->dml2_options.svp_pstate.callbacks.dc = dc; 2358 - dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; 2359 - dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; 2457 + dc->dml2_options.svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane; 2458 + dc->dml2_options.svp_pstate.callbacks.add_phantom_stream = &dc_state_add_phantom_stream; 2360 2459 dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; 2361 - dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; 2362 - dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; 2363 - dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; 2364 - dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; 2365 - dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; 2366 - dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; 2460 + dc->dml2_options.svp_pstate.callbacks.create_phantom_plane = &dc_state_create_phantom_plane; 2461 + dc->dml2_options.svp_pstate.callbacks.remove_phantom_plane = &dc_state_remove_phantom_plane; 2462 + dc->dml2_options.svp_pstate.callbacks.remove_phantom_stream = &dc_state_remove_phantom_stream; 2463 + dc->dml2_options.svp_pstate.callbacks.create_phantom_stream = &dc_state_create_phantom_stream; 2464 + dc->dml2_options.svp_pstate.callbacks.release_phantom_plane = &dc_state_release_phantom_plane; 2465 + dc->dml2_options.svp_pstate.callbacks.release_phantom_stream = &dc_state_release_phantom_stream; 2367 2466 dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; 2467 + dc->dml2_options.svp_pstate.callbacks.get_pipe_subvp_type = &dc_state_get_pipe_subvp_type; 2468 + dc->dml2_options.svp_pstate.callbacks.get_stream_subvp_type = &dc_state_get_stream_subvp_type; 2469 + dc->dml2_options.svp_pstate.callbacks.get_paired_subvp_stream = &dc_state_get_paired_subvp_stream; 2368 2470 2369 2471 dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; 2370 2472 dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+1 -18
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
··· 91 91 struct dc_3dlut **lut, 92 92 struct dc_transfer_func **shaper); 93 93 94 - bool dcn32_remove_phantom_pipes(struct dc *dc, 95 - struct dc_state *context, bool fast_update); 96 - 97 - void dcn32_retain_phantom_pipes(struct dc *dc, 98 - struct dc_state *context); 99 - 100 94 void dcn32_add_phantom_pipes(struct dc *dc, 101 95 struct dc_state *context, 102 96 display_e2e_pipe_params_st *pipes, ··· 131 137 bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc, 132 138 struct dc_state *context); 133 139 134 - bool dcn32_subvp_in_use(struct dc *dc, 135 - struct dc_state *context); 136 - 137 140 bool dcn32_mpo_in_use(struct dc_state *context); 138 141 139 142 bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context); ··· 160 169 void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, 161 170 display_e2e_pipe_params_st *pipes); 162 171 163 - void dcn32_save_mall_state(struct dc *dc, 164 - struct dc_state *context, 165 - struct mall_temp_config *temp_config); 166 - 167 - void dcn32_restore_mall_state(struct dc *dc, 168 - struct dc_state *context, 169 - struct mall_temp_config *temp_config); 170 - 171 - struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context); 172 + struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); 172 173 173 174 bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe); 174 175
+14 -13
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
··· 92 92 #include "vm_helper.h" 93 93 #include "dcn20/dcn20_vmid.h" 94 94 95 + #include "dc_state_priv.h" 96 + 95 97 #define DC_LOGGER_INIT(logger) 96 98 97 99 enum dcn321_clk_src_array_id { ··· 1574 1572 1575 1573 static struct dc_cap_funcs cap_funcs = { 1576 1574 .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, 1577 - .get_subvp_en = dcn32_subvp_in_use, 1575 + .get_subvp_en = resource_subvp_in_use, 1578 1576 }; 1579 1577 1580 1578 static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) ··· 1607 1605 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, 1608 1606 .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, 1609 1607 .add_phantom_pipes = dcn32_add_phantom_pipes, 1610 - .remove_phantom_pipes = dcn32_remove_phantom_pipes, 1611 - .retain_phantom_pipes = dcn32_retain_phantom_pipes, 1612 - .save_mall_state = dcn32_save_mall_state, 1613 - .restore_mall_state = dcn32_restore_mall_state, 1614 1608 .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, 1615 1609 }; 1616 1610 ··· 2006 2008 dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; 2007 2009 2008 2010 dc->dml2_options.svp_pstate.callbacks.dc = dc; 2009 - dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; 2010 - dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; 2011 + dc->dml2_options.svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane; 2012 + dc->dml2_options.svp_pstate.callbacks.add_phantom_stream = &dc_state_add_phantom_stream; 2011 2013 dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; 2012 - dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; 2013 - dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; 2014 - dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; 2015 - dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; 2016 - dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; 2017 - dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; 2014 + dc->dml2_options.svp_pstate.callbacks.create_phantom_plane = &dc_state_create_phantom_plane; 2015 + dc->dml2_options.svp_pstate.callbacks.remove_phantom_plane = &dc_state_remove_phantom_plane; 2016 + dc->dml2_options.svp_pstate.callbacks.remove_phantom_stream = &dc_state_remove_phantom_stream; 2017 + dc->dml2_options.svp_pstate.callbacks.create_phantom_stream = &dc_state_create_phantom_stream; 2018 + dc->dml2_options.svp_pstate.callbacks.release_phantom_plane = &dc_state_release_phantom_plane; 2019 + dc->dml2_options.svp_pstate.callbacks.release_phantom_stream = &dc_state_release_phantom_stream; 2018 2020 dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; 2021 + dc->dml2_options.svp_pstate.callbacks.get_pipe_subvp_type = &dc_state_get_pipe_subvp_type; 2022 + dc->dml2_options.svp_pstate.callbacks.get_stream_subvp_type = &dc_state_get_stream_subvp_type; 2023 + dc->dml2_options.svp_pstate.callbacks.get_paired_subvp_stream = &dc_state_get_paired_subvp_stream; 2019 2024 2020 2025 dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; 2021 2026 dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+18 -2
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
··· 96 96 #include "reg_helper.h" 97 97 #include "dce/dmub_abm.h" 98 98 #include "dce/dmub_psr.h" 99 + #include "dce/dmub_replay.h" 99 100 #include "dce/dce_aux.h" 100 101 #include "dce/dce_i2c.h" 101 102 #include "dml/dcn31/display_mode_vba_31.h" /*temp*/ 102 103 #include "vm_helper.h" 103 104 #include "dcn20/dcn20_vmid.h" 105 + 106 + #include "dc_state_priv.h" 104 107 105 108 #include "link_enc_cfg.h" 106 109 #define DC_LOGGER_INIT(logger) ··· 769 766 .enable_hpo_pg_support = false, 770 767 .enable_legacy_fast_update = true, 771 768 .enable_single_display_2to1_odm_policy = false, 772 - .disable_idle_power_optimizations = true, 769 + .disable_idle_power_optimizations = false, 773 770 .dmcub_emulation = false, 774 771 .disable_boot_optimizations = false, 775 772 .disable_unbounded_requesting = false, ··· 781 778 .ignore_pg = true, 782 779 .psp_disabled_wa = true, 783 780 .ips2_eval_delay_us = 200, 784 - .ips2_entry_delay_us = 400 781 + .ips2_entry_delay_us = 400, 782 + .static_screen_wait_frames = 2, 785 783 }; 786 784 787 785 static const struct dc_panel_config panel_config_defaults = { 788 786 .psr = { 789 787 .disable_psr = false, 790 788 .disallow_psrsu = false, 789 + .disallow_replay = false, 791 790 }, 792 791 .ilr = { 793 792 .optimize_edp_link_rate = true, ··· 1548 1543 if (pool->base.psr != NULL) 1549 1544 dmub_psr_destroy(&pool->base.psr); 1550 1545 1546 + if (pool->base.replay != NULL) 1547 + dmub_replay_destroy(&pool->base.replay); 1548 + 1551 1549 if (pool->base.pg_cntl != NULL) 1552 1550 dcn_pg_cntl_destroy(&pool->base.pg_cntl); 1553 1551 ··· 2031 2023 pool->base.psr = dmub_psr_create(ctx); 2032 2024 if (pool->base.psr == NULL) { 2033 2025 dm_error("DC: failed to create psr obj!\n"); 2026 + BREAK_TO_DEBUGGER(); 2027 + goto create_fail; 2028 + } 2029 + 2030 + /* Replay */ 2031 + pool->base.replay = dmub_replay_create(ctx); 2032 + if (pool->base.replay == NULL) { 2033 + dm_error("DC: failed to create replay obj!\n"); 2034 2034 BREAK_TO_DEBUGGER(); 2035 2035 goto create_fail; 2036 2036 }
+1
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
··· 86 86 DMUB_STATUS_TIMEOUT, 87 87 DMUB_STATUS_INVALID, 88 88 DMUB_STATUS_HW_FAILURE, 89 + DMUB_STATUS_POWER_STATE_D3 89 90 }; 90 91 91 92 /* enum dmub_asic - dmub asic identifier */
+1 -1
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
··· 653 653 uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/ 654 654 uint32_t usb4_cm_version: 1; /**< 1 CM support */ 655 655 uint32_t dpia_hpd_int_enable_supported: 1; /* 1 if dpia hpd int enable supported */ 656 - uint32_t usb4_dpia_bw_alloc_supported: 1; /* 1 if USB4 dpia BW allocation supported */ 656 + uint32_t reserved0: 1; 657 657 uint32_t disable_clk_ds: 1; /* 1 if disallow dispclk_ds and dppclk_ds*/ 658 658 uint32_t disable_timeout_recovery : 1; /* 1 if timeout recovery should be disabled */ 659 659 uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/
+2 -2
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
··· 768 768 return DMUB_STATUS_INVALID; 769 769 770 770 if (dmub->power_state != DMUB_POWER_STATE_D0) 771 - return DMUB_STATUS_INVALID; 771 + return DMUB_STATUS_POWER_STATE_D3; 772 772 773 773 if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity || 774 774 dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) { ··· 789 789 return DMUB_STATUS_INVALID; 790 790 791 791 if (dmub->power_state != DMUB_POWER_STATE_D0) 792 - return DMUB_STATUS_INVALID; 792 + return DMUB_STATUS_POWER_STATE_D3; 793 793 794 794 /** 795 795 * Read back all the queued commands to ensure that they've
-12
drivers/gpu/drm/amd/display/include/fixed31_32.h
··· 69 69 static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL }; 70 70 static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL }; 71 71 72 - static inline struct fixed31_32 dc_fixpt_from_s3132(__u64 x) 73 - { 74 - struct fixed31_32 val; 75 - 76 - /* If negative, convert to 2's complement. */ 77 - if (x & (1ULL << 63)) 78 - x = -(x & ~(1ULL << 63)); 79 - 80 - val.value = x; 81 - return val; 82 - } 83 - 84 72 /* 85 73 * @brief 86 74 * Initialization routines
+2
drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h
··· 417 417 /* V2.1 */ 418 418 struct edp_info edp1_info; 419 419 struct edp_info edp2_info; 420 + uint32_t gpuclk_ss_percentage; 421 + uint32_t gpuclk_ss_type; 420 422 }; 421 423 422 424 /*
+2 -2
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
··· 81 81 void mod_freesync_destroy(struct mod_freesync *mod_freesync) 82 82 { 83 83 struct core_freesync *core_freesync = NULL; 84 + 84 85 if (mod_freesync == NULL) 85 86 return; 86 87 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); ··· 279 278 } 280 279 } else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) { 281 280 /* Enter Below the Range */ 282 - if (!in_out_vrr->btr.btr_active) { 281 + if (!in_out_vrr->btr.btr_active) 283 282 in_out_vrr->btr.btr_active = true; 284 - } 285 283 } 286 284 287 285 /* BTR set to "not active" so disengage */
+2 -2
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
··· 63 63 static inline enum mod_hdcp_status check_r0p_available_dp(struct mod_hdcp *hdcp) 64 64 { 65 65 enum mod_hdcp_status status; 66 + 66 67 if (is_dp_hdcp(hdcp)) { 67 68 status = (hdcp->auth.msg.hdcp1.bstatus & 68 69 DP_BSTATUS_R0_PRIME_READY) ? ··· 132 131 static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) 133 132 { 134 133 /* Avoid device count == 0 to do authentication */ 135 - if (0 == get_device_count(hdcp)) { 134 + if (get_device_count(hdcp) == 0) 136 135 return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE; 137 - } 138 136 139 137 /* Some MST display may choose to report the internal panel as an HDCP RX. 140 138 * To update this condition with 1(because the immediate repeater's internal
+2 -4
drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
··· 208 208 static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) 209 209 { 210 210 /* Avoid device count == 0 to do authentication */ 211 - if (0 == get_device_count(hdcp)) { 211 + if (get_device_count(hdcp) == 0) 212 212 return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE; 213 - } 214 213 215 214 /* Some MST display may choose to report the internal panel as an HDCP RX. */ 216 215 /* To update this condition with 1(because the immediate repeater's internal */ ··· 688 689 if (is_hdmi_dvi_sl_hdcp(hdcp)) { 689 690 if (!process_rxstatus(hdcp, event_ctx, input, &status)) 690 691 goto out; 691 - if (event_ctx->rx_id_list_ready) { 692 + if (event_ctx->rx_id_list_ready) 692 693 goto out; 693 - } 694 694 } 695 695 if (is_hdmi_dvi_sl_hdcp(hdcp)) 696 696 if (!mod_hdcp_execute_and_set(check_stream_ready_available,
+6 -4
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
··· 86 86 #define HDCP_CPIRQ_TRACE(hdcp) \ 87 87 HDCP_LOG_FSM(hdcp, "[Link %d] --> CPIRQ", hdcp->config.index) 88 88 #define HDCP_EVENT_TRACE(hdcp, event) \ 89 - if (event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) \ 90 - HDCP_TIMEOUT_TRACE(hdcp); \ 91 - else if (event == MOD_HDCP_EVENT_CPIRQ) \ 92 - HDCP_CPIRQ_TRACE(hdcp) 89 + do { \ 90 + if (event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) \ 91 + HDCP_TIMEOUT_TRACE(hdcp); \ 92 + else if (event == MOD_HDCP_EVENT_CPIRQ) \ 93 + HDCP_CPIRQ_TRACE(hdcp); \ 94 + } while (0) 93 95 /* TODO: find some way to tell if logging is off to save time */ 94 96 #define HDCP_DDC_READ_TRACE(hdcp, msg_name, msg, msg_size) do { \ 95 97 mod_hdcp_dump_binary_message(msg, msg_size, hdcp->buf, \
+2 -2
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
··· 443 443 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 444 444 445 445 if (hdcp->displays[i].adjust.disable || hdcp->displays[i].state != MOD_HDCP_DISPLAY_ACTIVE) 446 - continue; 446 + continue; 447 447 448 448 memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); 449 449 ··· 926 926 927 927 for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) { 928 928 if (hdcp->displays[i].adjust.disable || hdcp->displays[i].state != MOD_HDCP_DISPLAY_ACTIVE) 929 - continue; 929 + continue; 930 930 931 931 hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.display_handle = hdcp->displays[i].index; 932 932 hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.session_handle = hdcp->auth.id;
+5 -5
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h
··· 98 98 * This enum defines software value for dio_output_type 99 99 */ 100 100 typedef enum { 101 - TA_DTM_DIO_OUTPUT_TYPE__INVALID, 102 - TA_DTM_DIO_OUTPUT_TYPE__DIRECT, 103 - TA_DTM_DIO_OUTPUT_TYPE__DPIA 101 + TA_DTM_DIO_OUTPUT_TYPE__INVALID, 102 + TA_DTM_DIO_OUTPUT_TYPE__DIRECT, 103 + TA_DTM_DIO_OUTPUT_TYPE__DPIA 104 104 } ta_dtm_dio_output_type; 105 105 106 106 struct ta_dtm_topology_update_input_v3 { ··· 237 237 #define TA_HDCP__HDCP1_KSV_LIST_MAX_ENTRIES 127 238 238 #define TA_HDCP__HDCP1_V_PRIME_SIZE 20 239 239 #define TA_HDCP__HDCP2_TX_BUF_MAX_SIZE \ 240 - TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_NO_STORED_KM + TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_STORED_KM + 6 240 + (TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_NO_STORED_KM + TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_STORED_KM + 6) 241 241 242 242 // 64 bits boundaries 243 243 #define TA_HDCP__HDCP2_RX_BUF_MAX_SIZE \ 244 - TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_SEND_CERT + TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_RECEIVER_INFO + 4 244 + (TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_SEND_CERT + TA_HDCP_HDCP2_MSG_ID_MAX_SIZE__AKE_RECEIVER_INFO + 4) 245 245 246 246 enum ta_hdcp_status { 247 247 TA_HDCP_STATUS__SUCCESS = 0x00,
-28
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
··· 23 23 * 24 24 */ 25 25 26 - 27 - 28 - 29 - /* 30 - * Copyright 2016 Advanced Micro Devices, Inc. 31 - * 32 - * Permission is hereby granted, free of charge, to any person obtaining a 33 - * copy of this software and associated documentation files (the "Software"), 34 - * to deal in the Software without restriction, including without limitation 35 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 36 - * and/or sell copies of the Software, and to permit persons to whom the 37 - * Software is furnished to do so, subject to the following conditions: 38 - * 39 - * The above copyright notice and this permission notice shall be included in 40 - * all copies or substantial portions of the Software. 41 - * 42 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 45 - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 46 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 47 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 48 - * OTHER DEALINGS IN THE SOFTWARE. 49 - * 50 - * Authors: AMD 51 - * 52 - */ 53 - 54 26 #ifndef MOD_FREESYNC_H_ 55 27 #define MOD_FREESYNC_H_ 56 28
+8 -5
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
··· 147 147 } 148 148 149 149 /* VSC packet set to 4 for PSR-SU, or 2 for PSR1 */ 150 - if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) 150 + if (stream->link->psr_settings.psr_feature_enabled) { 151 + if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) 152 + vsc_packet_revision = vsc_packet_rev4; 153 + else if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) 154 + vsc_packet_revision = vsc_packet_rev2; 155 + } 156 + 157 + if (stream->link->replay_settings.config.replay_supported) 151 158 vsc_packet_revision = vsc_packet_rev4; 152 - else if (stream->link->replay_settings.config.replay_supported) 153 - vsc_packet_revision = vsc_packet_rev4; 154 - else if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) 155 - vsc_packet_revision = vsc_packet_rev2; 156 159 157 160 /* Update to revision 5 for extended colorimetry support */ 158 161 if (stream->use_vsc_sdp_for_colorimetry)
+29 -1
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
··· 31 31 32 32 #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) 33 33 #define bswap16_based_on_endian(big_endian, value) \ 34 - (big_endian) ? cpu_to_be16(value) : cpu_to_le16(value) 34 + ((big_endian) ? cpu_to_be16(value) : cpu_to_le16(value)) 35 35 36 36 /* Possible Min Reduction config from least aggressive to most aggressive 37 37 * 0 1 2 3 4 5 6 7 8 9 10 11 12 ··· 971 971 } 972 972 973 973 return true; 974 + } 975 + 976 + void set_replay_coasting_vtotal(struct dc_link *link, 977 + enum replay_coasting_vtotal_type type, 978 + uint16_t vtotal) 979 + { 980 + link->replay_settings.coasting_vtotal_table[type] = vtotal; 981 + } 982 + 983 + void calculate_replay_link_off_frame_count(struct dc_link *link, 984 + uint16_t vtotal, uint16_t htotal) 985 + { 986 + uint8_t max_link_off_frame_count = 0; 987 + uint16_t max_deviation_line = 0, pixel_deviation_per_line = 0; 988 + 989 + max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line; 990 + pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line; 991 + 992 + if (htotal != 0 && vtotal != 0) 993 + max_link_off_frame_count = htotal * max_deviation_line / (pixel_deviation_per_line * vtotal); 994 + else 995 + ASSERT(0); 996 + 997 + link->replay_settings.link_off_frame_count_level = 998 + max_link_off_frame_count >= PR_LINK_OFF_FRAME_COUNT_BEST ? PR_LINK_OFF_FRAME_COUNT_BEST : 999 + max_link_off_frame_count >= PR_LINK_OFF_FRAME_COUNT_GOOD ? PR_LINK_OFF_FRAME_COUNT_GOOD : 1000 + PR_LINK_OFF_FRAME_COUNT_FAIL; 1001 + 974 1002 } 975 1003 976 1004 bool fill_custom_backlight_caps(unsigned int config_no, struct dm_acpi_atif_backlight_caps *caps)
+5
drivers/gpu/drm/amd/display/modules/power/power_helpers.h
··· 54 54 unsigned int inst); 55 55 56 56 void init_replay_config(struct dc_link *link, struct replay_config *pr_config); 57 + void set_replay_coasting_vtotal(struct dc_link *link, 58 + enum replay_coasting_vtotal_type type, 59 + uint16_t vtotal); 60 + void calculate_replay_link_off_frame_count(struct dc_link *link, 61 + uint16_t vtotal, uint16_t htotal); 57 62 58 63 bool is_psr_su_specific_panel(struct dc_link *link); 59 64 void mod_power_calc_psr_configs(struct psr_config *psr_config,
+2 -2
drivers/gpu/drm/amd/include/amd_shared.h
··· 244 244 DC_DISABLE_LTTPR_DP2_0 = (1 << 6), //0x40, disabled by default 245 245 DC_PSR_ALLOW_SMU_OPT = (1 << 7), //0x80, disabled by default 246 246 DC_PSR_ALLOW_MULTI_DISP_OPT = (1 << 8), //0x100, disabled by default 247 - DC_REPLAY_MASK = (1 << 9), //0x200, disabled by default for dcn < 3.1.4 248 247 }; 249 248 250 249 enum DC_DEBUG_MASK { ··· 254 255 DC_DISABLE_PSR = 0x10, 255 256 DC_FORCE_SUBVP_MCLK_SWITCH = 0x20, 256 257 DC_DISABLE_MPO = 0x40, 257 - DC_DISABLE_REPLAY = 0x50, 258 258 DC_ENABLE_DPIA_TRACE = 0x80, 259 259 DC_ENABLE_DML2 = 0x100, 260 + DC_DISABLE_PSR_SU = 0x200, 261 + DC_DISABLE_REPLAY = 0x400, 260 262 }; 261 263 262 264 enum amd_dpm_forced_level;
+80
drivers/gpu/drm/amd/include/kgd_pp_interface.h
··· 318 318 #define MAX_GFX_CLKS 8 319 319 #define MAX_CLKS 4 320 320 #define NUM_VCN 4 321 + #define NUM_JPEG_ENG 32 321 322 322 323 struct seq_file; 323 324 enum amd_pp_clock_type; ··· 758 757 759 758 /* PCIE replay rollover accumulated count */ 760 759 uint64_t pcie_replay_rover_count_acc; 760 + 761 + /* XGMI accumulated data transfer size(KiloBytes) */ 762 + uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS]; 763 + uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS]; 764 + 765 + /* PMFW attached timestamp (10ns resolution) */ 766 + uint64_t firmware_timestamp; 767 + 768 + /* Current clocks (Mhz) */ 769 + uint16_t current_gfxclk[MAX_GFX_CLKS]; 770 + uint16_t current_socclk[MAX_CLKS]; 771 + uint16_t current_vclk0[MAX_CLKS]; 772 + uint16_t current_dclk0[MAX_CLKS]; 773 + uint16_t current_uclk; 774 + 775 + uint16_t padding; 776 + }; 777 + 778 + struct gpu_metrics_v1_5 { 779 + struct metrics_table_header common_header; 780 + 781 + /* Temperature (Celsius) */ 782 + uint16_t temperature_hotspot; 783 + uint16_t temperature_mem; 784 + uint16_t temperature_vrsoc; 785 + 786 + /* Power (Watts) */ 787 + uint16_t curr_socket_power; 788 + 789 + /* Utilization (%) */ 790 + uint16_t average_gfx_activity; 791 + uint16_t average_umc_activity; // memory controller 792 + uint16_t vcn_activity[NUM_VCN]; 793 + uint16_t jpeg_activity[NUM_JPEG_ENG]; 794 + 795 + /* Energy (15.259uJ (2^-16) units) */ 796 + uint64_t energy_accumulator; 797 + 798 + /* Driver attached timestamp (in ns) */ 799 + uint64_t system_clock_counter; 800 + 801 + /* Throttle status */ 802 + uint32_t throttle_status; 803 + 804 + /* Clock Lock Status. Each bit corresponds to clock instance */ 805 + uint32_t gfxclk_lock_status; 806 + 807 + /* Link width (number of lanes) and speed (in 0.1 GT/s) */ 808 + uint16_t pcie_link_width; 809 + uint16_t pcie_link_speed; 810 + 811 + /* XGMI bus width and bitrate (in Gbps) */ 812 + uint16_t xgmi_link_width; 813 + uint16_t xgmi_link_speed; 814 + 815 + /* Utilization Accumulated (%) */ 816 + uint32_t gfx_activity_acc; 817 + uint32_t mem_activity_acc; 818 + 819 + /*PCIE accumulated bandwidth (GB/sec) */ 820 + uint64_t pcie_bandwidth_acc; 821 + 822 + /*PCIE instantaneous bandwidth (GB/sec) */ 823 + uint64_t pcie_bandwidth_inst; 824 + 825 + /* PCIE L0 to recovery state transition accumulated count */ 826 + uint64_t pcie_l0_to_recov_count_acc; 827 + 828 + /* PCIE replay accumulated count */ 829 + uint64_t pcie_replay_count_acc; 830 + 831 + /* PCIE replay rollover accumulated count */ 832 + uint64_t pcie_replay_rover_count_acc; 833 + 834 + /* PCIE NAK sent accumulated count */ 835 + uint32_t pcie_nak_sent_count_acc; 836 + 837 + /* PCIE NAK received accumulated count */ 838 + uint32_t pcie_nak_rcvd_count_acc; 761 839 762 840 /* XGMI accumulated data transfer size(KiloBytes) */ 763 841 uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS];
+3 -1
drivers/gpu/drm/amd/pm/amdgpu_pm.c
··· 2168 2168 if (amdgpu_dpm_is_overdrive_supported(adev)) 2169 2169 *states = ATTR_STATE_SUPPORTED; 2170 2170 } else if (DEVICE_ATTR_IS(mem_busy_percent)) { 2171 - if (adev->flags & AMD_IS_APU || gc_ver == IP_VERSION(9, 0, 1)) 2171 + if ((adev->flags & AMD_IS_APU && 2172 + gc_ver != IP_VERSION(9, 4, 3)) || 2173 + gc_ver == IP_VERSION(9, 0, 1)) 2172 2174 *states = ATTR_STATE_UNSUPPORTED; 2173 2175 } else if (DEVICE_ATTR_IS(pcie_bw)) { 2174 2176 /* PCIe Perf counters won't work on APU nodes */
+5 -1
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
··· 2974 2974 result = smu7_get_evv_voltages(hwmgr); 2975 2975 if (result) { 2976 2976 pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); 2977 + kfree(hwmgr->backend); 2978 + hwmgr->backend = NULL; 2977 2979 return -EINVAL; 2978 2980 } 2979 2981 } else { ··· 3021 3019 } 3022 3020 3023 3021 result = smu7_update_edc_leakage_table(hwmgr); 3024 - if (result) 3022 + if (result) { 3023 + smu7_hwmgr_backend_fini(hwmgr); 3025 3024 return result; 3025 + } 3026 3026 3027 3027 return 0; 3028 3028 }
+1
drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c
··· 2298 2298 case SMU_MAX_ENTRIES_SMIO: 2299 2299 return SMU7_MAX_ENTRIES_SMIO; 2300 2300 case SMU_MAX_LEVELS_VDDC: 2301 + case SMU_MAX_LEVELS_VDDGFX: 2301 2302 return SMU7_MAX_LEVELS_VDDC; 2302 2303 case SMU_MAX_LEVELS_VDDCI: 2303 2304 return SMU7_MAX_LEVELS_VDDCI;
+1
drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c
··· 2263 2263 case SMU_MAX_ENTRIES_SMIO: 2264 2264 return SMU71_MAX_ENTRIES_SMIO; 2265 2265 case SMU_MAX_LEVELS_VDDC: 2266 + case SMU_MAX_LEVELS_VDDGFX: 2266 2267 return SMU71_MAX_LEVELS_VDDC; 2267 2268 case SMU_MAX_LEVELS_VDDCI: 2268 2269 return SMU71_MAX_LEVELS_VDDCI;
+98 -2
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h
··· 123 123 VOLTAGE_GUARDBAND_COUNT 124 124 } GFX_GUARDBAND_e; 125 125 126 - #define SMU_METRICS_TABLE_VERSION 0x9 126 + #define SMU_METRICS_TABLE_VERSION 0xB 127 127 128 128 typedef struct __attribute__((packed, aligned(4))) { 129 129 uint32_t AccumulationCounter; ··· 219 219 uint32_t PCIenReplayARolloverCountAcc; // The Pcie counter itself is accumulated 220 220 uint32_t PCIeNAKSentCountAcc; // The Pcie counter itself is accumulated 221 221 uint32_t PCIeNAKReceivedCountAcc; // The Pcie counter itself is accumulated 222 - } MetricsTable_t; 222 + 223 + // VCN/JPEG ACTIVITY 224 + uint32_t VcnBusy[4]; 225 + uint32_t JpegBusy[32]; 226 + } MetricsTableX_t; 227 + 228 + typedef struct __attribute__((packed, aligned(4))) { 229 + uint32_t AccumulationCounter; 230 + 231 + //TEMPERATURE 232 + uint32_t MaxSocketTemperature; 233 + uint32_t MaxVrTemperature; 234 + uint32_t MaxHbmTemperature; 235 + uint64_t MaxSocketTemperatureAcc; 236 + uint64_t MaxVrTemperatureAcc; 237 + uint64_t MaxHbmTemperatureAcc; 238 + 239 + //POWER 240 + uint32_t SocketPowerLimit; 241 + uint32_t MaxSocketPowerLimit; 242 + uint32_t SocketPower; 243 + 244 + //ENERGY 245 + uint64_t Timestamp; 246 + uint64_t SocketEnergyAcc; 247 + uint64_t CcdEnergyAcc; 248 + uint64_t XcdEnergyAcc; 249 + uint64_t AidEnergyAcc; 250 + uint64_t HbmEnergyAcc; 251 + 252 + //FREQUENCY 253 + uint32_t CclkFrequencyLimit; 254 + uint32_t GfxclkFrequencyLimit; 255 + uint32_t FclkFrequency; 256 + uint32_t UclkFrequency; 257 + uint32_t SocclkFrequency[4]; 258 + uint32_t VclkFrequency[4]; 259 + uint32_t DclkFrequency[4]; 260 + uint32_t LclkFrequency[4]; 261 + uint64_t GfxclkFrequencyAcc[8]; 262 + uint64_t CclkFrequencyAcc[96]; 263 + 264 + //FREQUENCY RANGE 265 + uint32_t MaxCclkFrequency; 266 + uint32_t MinCclkFrequency; 267 + uint32_t MaxGfxclkFrequency; 268 + uint32_t MinGfxclkFrequency; 269 + uint32_t FclkFrequencyTable[4]; 270 + uint32_t UclkFrequencyTable[4]; 271 + uint32_t SocclkFrequencyTable[4]; 272 + uint32_t VclkFrequencyTable[4]; 273 + uint32_t DclkFrequencyTable[4]; 274 + uint32_t LclkFrequencyTable[4]; 275 + uint32_t MaxLclkDpmRange; 276 + uint32_t MinLclkDpmRange; 277 + 278 + //XGMI 279 + uint32_t XgmiWidth; 280 + uint32_t XgmiBitrate; 281 + uint64_t XgmiReadBandwidthAcc[8]; 282 + uint64_t XgmiWriteBandwidthAcc[8]; 283 + 284 + //ACTIVITY 285 + uint32_t SocketC0Residency; 286 + uint32_t SocketGfxBusy; 287 + uint32_t DramBandwidthUtilization; 288 + uint64_t SocketC0ResidencyAcc; 289 + uint64_t SocketGfxBusyAcc; 290 + uint64_t DramBandwidthAcc; 291 + uint32_t MaxDramBandwidth; 292 + uint64_t DramBandwidthUtilizationAcc; 293 + uint64_t PcieBandwidthAcc[4]; 294 + 295 + //THROTTLERS 296 + uint32_t ProchotResidencyAcc; 297 + uint32_t PptResidencyAcc; 298 + uint32_t SocketThmResidencyAcc; 299 + uint32_t VrThmResidencyAcc; 300 + uint32_t HbmThmResidencyAcc; 301 + uint32_t GfxLockXCDMak; 302 + 303 + // New Items at end to maintain driver compatibility 304 + uint32_t GfxclkFrequency[8]; 305 + 306 + //PSNs 307 + uint64_t PublicSerialNumber_AID[4]; 308 + uint64_t PublicSerialNumber_XCD[8]; 309 + uint64_t PublicSerialNumber_CCD[12]; 310 + 311 + //XGMI Data tranfser size 312 + uint64_t XgmiReadDataSizeAcc[8];//in KByte 313 + uint64_t XgmiWriteDataSizeAcc[8];//in KByte 314 + 315 + // VCN/JPEG ACTIVITY 316 + uint32_t VcnBusy[4]; 317 + uint32_t JpegBusy[32]; 318 + } MetricsTableA_t; 223 319 224 320 #define SMU_VF_METRICS_TABLE_VERSION 0x3 225 321
+101 -64
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
··· 248 248 #define SMUQ10_TO_UINT(x) ((x) >> 10) 249 249 #define SMUQ10_FRAC(x) ((x) & 0x3ff) 250 250 #define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200)) 251 + #define GET_METRIC_FIELD(field) ((adev->flags & AMD_IS_APU) ?\ 252 + (metrics_a->field) : (metrics_x->field)) 251 253 252 254 struct smu_v13_0_6_dpm_map { 253 255 enum smu_clk_type clk_type; ··· 332 330 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE, 333 331 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 334 332 335 - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(MetricsTable_t), 333 + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, 334 + max(sizeof(MetricsTableX_t), sizeof(MetricsTableA_t)), 336 335 PAGE_SIZE, 337 336 AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT); 338 337 ··· 341 338 PAGE_SIZE, 342 339 AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT); 343 340 344 - smu_table->metrics_table = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL); 341 + smu_table->metrics_table = kzalloc(max(sizeof(MetricsTableX_t), 342 + sizeof(MetricsTableA_t)), GFP_KERNEL); 345 343 if (!smu_table->metrics_table) 346 344 return -ENOMEM; 347 345 smu_table->metrics_time = 0; 348 346 349 - smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_4); 347 + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_5); 350 348 smu_table->gpu_metrics_table = 351 349 kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 352 350 if (!smu_table->gpu_metrics_table) { ··· 473 469 static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu) 474 470 { 475 471 struct smu_table_context *smu_table = &smu->smu_table; 476 - MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table; 472 + MetricsTableX_t *metrics_x = (MetricsTableX_t *)smu_table->metrics_table; 473 + MetricsTableA_t *metrics_a = (MetricsTableA_t *)smu_table->metrics_table; 477 474 struct PPTable_t *pptable = 478 475 (struct PPTable_t *)smu_table->driver_pptable; 476 + struct amdgpu_device *adev = smu->adev; 479 477 int ret, i, retry = 100; 480 478 uint32_t table_version; 481 479 ··· 489 483 return ret; 490 484 491 485 /* Ensure that metrics have been updated */ 492 - if (metrics->AccumulationCounter) 486 + if (GET_METRIC_FIELD(AccumulationCounter)) 493 487 break; 494 488 495 489 usleep_range(1000, 1100); ··· 506 500 table_version; 507 501 508 502 pptable->MaxSocketPowerLimit = 509 - SMUQ10_ROUND(metrics->MaxSocketPowerLimit); 503 + SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketPowerLimit)); 510 504 pptable->MaxGfxclkFrequency = 511 - SMUQ10_ROUND(metrics->MaxGfxclkFrequency); 505 + SMUQ10_ROUND(GET_METRIC_FIELD(MaxGfxclkFrequency)); 512 506 pptable->MinGfxclkFrequency = 513 - SMUQ10_ROUND(metrics->MinGfxclkFrequency); 507 + SMUQ10_ROUND(GET_METRIC_FIELD(MinGfxclkFrequency)); 514 508 515 509 for (i = 0; i < 4; ++i) { 516 510 pptable->FclkFrequencyTable[i] = 517 - SMUQ10_ROUND(metrics->FclkFrequencyTable[i]); 511 + SMUQ10_ROUND(GET_METRIC_FIELD(FclkFrequencyTable)[i]); 518 512 pptable->UclkFrequencyTable[i] = 519 - SMUQ10_ROUND(metrics->UclkFrequencyTable[i]); 513 + SMUQ10_ROUND(GET_METRIC_FIELD(UclkFrequencyTable)[i]); 520 514 pptable->SocclkFrequencyTable[i] = SMUQ10_ROUND( 521 - metrics->SocclkFrequencyTable[i]); 515 + GET_METRIC_FIELD(SocclkFrequencyTable)[i]); 522 516 pptable->VclkFrequencyTable[i] = 523 - SMUQ10_ROUND(metrics->VclkFrequencyTable[i]); 517 + SMUQ10_ROUND(GET_METRIC_FIELD(VclkFrequencyTable)[i]); 524 518 pptable->DclkFrequencyTable[i] = 525 - SMUQ10_ROUND(metrics->DclkFrequencyTable[i]); 519 + SMUQ10_ROUND(GET_METRIC_FIELD(DclkFrequencyTable)[i]); 526 520 pptable->LclkFrequencyTable[i] = 527 - SMUQ10_ROUND(metrics->LclkFrequencyTable[i]); 521 + SMUQ10_ROUND(GET_METRIC_FIELD(LclkFrequencyTable)[i]); 528 522 } 529 523 530 524 /* use AID0 serial number by default */ 531 - pptable->PublicSerialNumber_AID = metrics->PublicSerialNumber_AID[0]; 525 + pptable->PublicSerialNumber_AID = GET_METRIC_FIELD(PublicSerialNumber_AID)[0]; 532 526 533 527 pptable->Init = true; 534 528 } ··· 830 824 uint32_t *value) 831 825 { 832 826 struct smu_table_context *smu_table = &smu->smu_table; 833 - MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table; 827 + MetricsTableX_t *metrics_x = (MetricsTableX_t *)smu_table->metrics_table; 828 + MetricsTableA_t *metrics_a = (MetricsTableA_t *)smu_table->metrics_table; 834 829 struct amdgpu_device *adev = smu->adev; 835 830 int ret = 0; 836 831 int xcc_id; ··· 846 839 case METRICS_AVERAGE_GFXCLK: 847 840 if (smu->smc_fw_version >= 0x552F00) { 848 841 xcc_id = GET_INST(GC, 0); 849 - *value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]); 842 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(GfxclkFrequency)[xcc_id]); 850 843 } else { 851 844 *value = 0; 852 845 } 853 846 break; 854 847 case METRICS_CURR_SOCCLK: 855 848 case METRICS_AVERAGE_SOCCLK: 856 - *value = SMUQ10_ROUND(metrics->SocclkFrequency[0]); 849 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(SocclkFrequency)[0]); 857 850 break; 858 851 case METRICS_CURR_UCLK: 859 852 case METRICS_AVERAGE_UCLK: 860 - *value = SMUQ10_ROUND(metrics->UclkFrequency); 853 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(UclkFrequency)); 861 854 break; 862 855 case METRICS_CURR_VCLK: 863 - *value = SMUQ10_ROUND(metrics->VclkFrequency[0]); 856 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(VclkFrequency)[0]); 864 857 break; 865 858 case METRICS_CURR_DCLK: 866 - *value = SMUQ10_ROUND(metrics->DclkFrequency[0]); 859 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(DclkFrequency)[0]); 867 860 break; 868 861 case METRICS_CURR_FCLK: 869 - *value = SMUQ10_ROUND(metrics->FclkFrequency); 862 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(FclkFrequency)); 870 863 break; 871 864 case METRICS_AVERAGE_GFXACTIVITY: 872 - *value = SMUQ10_ROUND(metrics->SocketGfxBusy); 865 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(SocketGfxBusy)); 873 866 break; 874 867 case METRICS_AVERAGE_MEMACTIVITY: 875 - *value = SMUQ10_ROUND(metrics->DramBandwidthUtilization); 868 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(DramBandwidthUtilization)); 876 869 break; 877 870 case METRICS_CURR_SOCKETPOWER: 878 - *value = SMUQ10_ROUND(metrics->SocketPower) << 8; 871 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(SocketPower)) << 8; 879 872 break; 880 873 case METRICS_TEMPERATURE_HOTSPOT: 881 - *value = SMUQ10_ROUND(metrics->MaxSocketTemperature) * 874 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketTemperature)) * 882 875 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 883 876 break; 884 877 case METRICS_TEMPERATURE_MEM: 885 - *value = SMUQ10_ROUND(metrics->MaxHbmTemperature) * 878 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(MaxHbmTemperature)) * 886 879 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 887 880 break; 888 881 /* This is the max of all VRs and not just SOC VR. 889 882 * No need to define another data type for the same. 890 883 */ 891 884 case METRICS_TEMPERATURE_VRSOC: 892 - *value = SMUQ10_ROUND(metrics->MaxVrTemperature) * 885 + *value = SMUQ10_ROUND(GET_METRIC_FIELD(MaxVrTemperature)) * 893 886 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 894 887 break; 895 888 default: ··· 2074 2067 static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table) 2075 2068 { 2076 2069 struct smu_table_context *smu_table = &smu->smu_table; 2077 - struct gpu_metrics_v1_4 *gpu_metrics = 2078 - (struct gpu_metrics_v1_4 *)smu_table->gpu_metrics_table; 2070 + struct gpu_metrics_v1_5 *gpu_metrics = 2071 + (struct gpu_metrics_v1_5 *)smu_table->gpu_metrics_table; 2079 2072 struct amdgpu_device *adev = smu->adev; 2080 - int ret = 0, xcc_id, inst, i; 2081 - MetricsTable_t *metrics; 2073 + int ret = 0, xcc_id, inst, i, j; 2074 + MetricsTableX_t *metrics_x; 2075 + MetricsTableA_t *metrics_a; 2082 2076 u16 link_width_level; 2083 2077 2084 - metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL); 2085 - ret = smu_v13_0_6_get_metrics_table(smu, metrics, true); 2078 + metrics_x = kzalloc(max(sizeof(MetricsTableX_t), sizeof(MetricsTableA_t)), GFP_KERNEL); 2079 + ret = smu_v13_0_6_get_metrics_table(smu, metrics_x, true); 2086 2080 if (ret) { 2087 - kfree(metrics); 2081 + kfree(metrics_x); 2088 2082 return ret; 2089 2083 } 2090 2084 2091 - smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 4); 2085 + metrics_a = (MetricsTableA_t *)metrics_x; 2086 + 2087 + smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 5); 2092 2088 2093 2089 gpu_metrics->temperature_hotspot = 2094 - SMUQ10_ROUND(metrics->MaxSocketTemperature); 2090 + SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketTemperature)); 2095 2091 /* Individual HBM stack temperature is not reported */ 2096 2092 gpu_metrics->temperature_mem = 2097 - SMUQ10_ROUND(metrics->MaxHbmTemperature); 2093 + SMUQ10_ROUND(GET_METRIC_FIELD(MaxHbmTemperature)); 2098 2094 /* Reports max temperature of all voltage rails */ 2099 2095 gpu_metrics->temperature_vrsoc = 2100 - SMUQ10_ROUND(metrics->MaxVrTemperature); 2096 + SMUQ10_ROUND(GET_METRIC_FIELD(MaxVrTemperature)); 2101 2097 2102 2098 gpu_metrics->average_gfx_activity = 2103 - SMUQ10_ROUND(metrics->SocketGfxBusy); 2099 + SMUQ10_ROUND(GET_METRIC_FIELD(SocketGfxBusy)); 2104 2100 gpu_metrics->average_umc_activity = 2105 - SMUQ10_ROUND(metrics->DramBandwidthUtilization); 2101 + SMUQ10_ROUND(GET_METRIC_FIELD(DramBandwidthUtilization)); 2106 2102 2107 2103 gpu_metrics->curr_socket_power = 2108 - SMUQ10_ROUND(metrics->SocketPower); 2104 + SMUQ10_ROUND(GET_METRIC_FIELD(SocketPower)); 2109 2105 /* Energy counter reported in 15.259uJ (2^-16) units */ 2110 - gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc; 2106 + gpu_metrics->energy_accumulator = GET_METRIC_FIELD(SocketEnergyAcc); 2111 2107 2112 2108 for (i = 0; i < MAX_GFX_CLKS; i++) { 2113 2109 xcc_id = GET_INST(GC, i); 2114 2110 if (xcc_id >= 0) 2115 2111 gpu_metrics->current_gfxclk[i] = 2116 - SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]); 2112 + SMUQ10_ROUND(GET_METRIC_FIELD(GfxclkFrequency)[xcc_id]); 2117 2113 2118 2114 if (i < MAX_CLKS) { 2119 2115 gpu_metrics->current_socclk[i] = 2120 - SMUQ10_ROUND(metrics->SocclkFrequency[i]); 2116 + SMUQ10_ROUND(GET_METRIC_FIELD(SocclkFrequency)[i]); 2121 2117 inst = GET_INST(VCN, i); 2122 2118 if (inst >= 0) { 2123 2119 gpu_metrics->current_vclk0[i] = 2124 - SMUQ10_ROUND(metrics->VclkFrequency[inst]); 2120 + SMUQ10_ROUND(GET_METRIC_FIELD(VclkFrequency)[inst]); 2125 2121 gpu_metrics->current_dclk0[i] = 2126 - SMUQ10_ROUND(metrics->DclkFrequency[inst]); 2122 + SMUQ10_ROUND(GET_METRIC_FIELD(DclkFrequency)[inst]); 2127 2123 } 2128 2124 } 2129 2125 } 2130 2126 2131 - gpu_metrics->current_uclk = SMUQ10_ROUND(metrics->UclkFrequency); 2127 + gpu_metrics->current_uclk = SMUQ10_ROUND(GET_METRIC_FIELD(UclkFrequency)); 2132 2128 2133 2129 /* Throttle status is not reported through metrics now */ 2134 2130 gpu_metrics->throttle_status = 0; 2135 2131 2136 2132 /* Clock Lock Status. Each bit corresponds to each GFXCLK instance */ 2137 - gpu_metrics->gfxclk_lock_status = metrics->GfxLockXCDMak >> GET_INST(GC, 0); 2133 + gpu_metrics->gfxclk_lock_status = GET_METRIC_FIELD(GfxLockXCDMak) >> GET_INST(GC, 0); 2138 2134 2139 2135 if (!(adev->flags & AMD_IS_APU)) { 2140 2136 link_width_level = smu_v13_0_6_get_current_pcie_link_width_level(smu); ··· 2149 2139 gpu_metrics->pcie_link_speed = 2150 2140 smu_v13_0_6_get_current_pcie_link_speed(smu); 2151 2141 gpu_metrics->pcie_bandwidth_acc = 2152 - SMUQ10_ROUND(metrics->PcieBandwidthAcc[0]); 2142 + SMUQ10_ROUND(metrics_x->PcieBandwidthAcc[0]); 2153 2143 gpu_metrics->pcie_bandwidth_inst = 2154 - SMUQ10_ROUND(metrics->PcieBandwidth[0]); 2144 + SMUQ10_ROUND(metrics_x->PcieBandwidth[0]); 2155 2145 gpu_metrics->pcie_l0_to_recov_count_acc = 2156 - metrics->PCIeL0ToRecoveryCountAcc; 2146 + metrics_x->PCIeL0ToRecoveryCountAcc; 2157 2147 gpu_metrics->pcie_replay_count_acc = 2158 - metrics->PCIenReplayAAcc; 2148 + metrics_x->PCIenReplayAAcc; 2159 2149 gpu_metrics->pcie_replay_rover_count_acc = 2160 - metrics->PCIenReplayARolloverCountAcc; 2150 + metrics_x->PCIenReplayARolloverCountAcc; 2151 + gpu_metrics->pcie_nak_sent_count_acc = 2152 + metrics_x->PCIeNAKSentCountAcc; 2153 + gpu_metrics->pcie_nak_rcvd_count_acc = 2154 + metrics_x->PCIeNAKReceivedCountAcc; 2161 2155 } 2162 2156 2163 2157 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 2164 2158 2165 2159 gpu_metrics->gfx_activity_acc = 2166 - SMUQ10_ROUND(metrics->SocketGfxBusyAcc); 2160 + SMUQ10_ROUND(GET_METRIC_FIELD(SocketGfxBusyAcc)); 2167 2161 gpu_metrics->mem_activity_acc = 2168 - SMUQ10_ROUND(metrics->DramBandwidthUtilizationAcc); 2162 + SMUQ10_ROUND(GET_METRIC_FIELD(DramBandwidthUtilizationAcc)); 2169 2163 2170 2164 for (i = 0; i < NUM_XGMI_LINKS; i++) { 2171 2165 gpu_metrics->xgmi_read_data_acc[i] = 2172 - SMUQ10_ROUND(metrics->XgmiReadDataSizeAcc[i]); 2166 + SMUQ10_ROUND(GET_METRIC_FIELD(XgmiReadDataSizeAcc)[i]); 2173 2167 gpu_metrics->xgmi_write_data_acc[i] = 2174 - SMUQ10_ROUND(metrics->XgmiWriteDataSizeAcc[i]); 2168 + SMUQ10_ROUND(GET_METRIC_FIELD(XgmiWriteDataSizeAcc)[i]); 2175 2169 } 2176 2170 2177 - gpu_metrics->xgmi_link_width = SMUQ10_ROUND(metrics->XgmiWidth); 2178 - gpu_metrics->xgmi_link_speed = SMUQ10_ROUND(metrics->XgmiBitrate); 2171 + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { 2172 + inst = GET_INST(JPEG, i); 2173 + for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) { 2174 + gpu_metrics->jpeg_activity[(i * adev->jpeg.num_jpeg_rings) + j] = 2175 + SMUQ10_ROUND(GET_METRIC_FIELD(JpegBusy) 2176 + [(inst * adev->jpeg.num_jpeg_rings) + j]); 2177 + } 2178 + } 2179 2179 2180 - gpu_metrics->firmware_timestamp = metrics->Timestamp; 2180 + for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 2181 + inst = GET_INST(VCN, i); 2182 + gpu_metrics->vcn_activity[i] = 2183 + SMUQ10_ROUND(GET_METRIC_FIELD(VcnBusy)[inst]); 2184 + } 2185 + 2186 + gpu_metrics->xgmi_link_width = SMUQ10_ROUND(GET_METRIC_FIELD(XgmiWidth)); 2187 + gpu_metrics->xgmi_link_speed = SMUQ10_ROUND(GET_METRIC_FIELD(XgmiBitrate)); 2188 + 2189 + gpu_metrics->firmware_timestamp = GET_METRIC_FIELD(Timestamp); 2181 2190 2182 2191 *table = (void *)gpu_metrics; 2183 - kfree(metrics); 2192 + kfree(metrics_x); 2184 2193 2185 2194 return sizeof(*gpu_metrics); 2186 2195 } ··· 2553 2524 return 0; 2554 2525 } 2555 2526 2556 - if (type == AMDGPU_MCA_ERROR_TYPE_UE && umc_v12_0_is_uncorrectable_error(status0)) 2527 + if (type == AMDGPU_MCA_ERROR_TYPE_UE && umc_v12_0_is_uncorrectable_error(adev, status0)) 2557 2528 *count = 1; 2558 - else if (type == AMDGPU_MCA_ERROR_TYPE_CE && umc_v12_0_is_correctable_error(status0)) 2529 + else if (type == AMDGPU_MCA_ERROR_TYPE_CE && umc_v12_0_is_correctable_error(adev, status0)) 2559 2530 *count = 1; 2560 2531 2561 2532 return 0; ··· 2893 2864 return ret; 2894 2865 } 2895 2866 2867 + static ssize_t smu_v13_0_6_get_ecc_info(struct smu_context *smu, 2868 + void *table) 2869 + { 2870 + /* Support ecc info by default */ 2871 + return 0; 2872 + } 2873 + 2896 2874 static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { 2897 2875 /* init dpm */ 2898 2876 .get_allowed_feature_mask = smu_v13_0_6_get_allowed_feature_mask, ··· 2954 2918 .i2c_init = smu_v13_0_6_i2c_control_init, 2955 2919 .i2c_fini = smu_v13_0_6_i2c_control_fini, 2956 2920 .send_hbm_bad_pages_num = smu_v13_0_6_smu_send_hbm_bad_page_num, 2921 + .get_ecc_info = smu_v13_0_6_get_ecc_info, 2957 2922 }; 2958 2923 2959 2924 void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu)
+3
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
··· 989 989 case METRICS_VERSION(1, 4): 990 990 structure_size = sizeof(struct gpu_metrics_v1_4); 991 991 break; 992 + case METRICS_VERSION(1, 5): 993 + structure_size = sizeof(struct gpu_metrics_v1_5); 994 + break; 992 995 case METRICS_VERSION(2, 0): 993 996 structure_size = sizeof(struct gpu_metrics_v2_0); 994 997 break;