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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'amd-drm-next-6.8-2023-12-15' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.8-2023-12-15:

amdgpu:
- Suspend fixes
- Misc code cleanups
- JPEG fix
- Add AMD specific color management (protected by AMD_PRIVATE_COLOR)
- UHBR13.5 cable fixes
- Misc display fixes
- Display WB fixes
- PSR fixes
- XGMI fix
- ACPI WBRF support for handling potential RF interference from GPU clocks
- Enable tunneling on high priority compute queues
- drm_edid.h include cleanup
- VPE DPM support
- SMU 13 fixes
- Fix possible double frees in error paths
- Misc fixes

amdkfd:
- Support import and export of dma-bufs using GEM handles
- MES shader debugger fixes
- SVM fixes

radeon:
- drm_edid.h include cleanup
- Misc code cleanups
- Fix possible memory leak in error path

drm:
- Increase max objects to accomodate new color props
- Make replace_property_blob_from_id a DRM helper
- Track color management changes per plane

platform-x86:
- Merge immutable branch from Hans for platform dependencies for WBRF to coordinate
merge of WBRF feature across wifi, platform, and GPU

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

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZXygTgAKCRC93/aFa7yZ
# 2EW1AQCILfGTtDWXzgLSpUBtt9jOooHqaSrah19Cfw0HlA3QIQD+OCohXH1LLZo1
# tYHyfsLv0LsNawI198qABzB1PwptSAI=
# =M1AO
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 16 Dec 2023 04:51:58 AEST
# gpg: using EDDSA key 203B921D836B5735349902BDBDDFF6856BBC99D8
# gpg: Can't check signature: No public key
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231215193519.5040-1-alexander.deucher@amd.com

+3189 -438
+1
Documentation/driver-api/index.rst
··· 115 115 hte/index 116 116 wmi 117 117 dpll 118 + wbrf 118 119 119 120 .. only:: subproject and html 120 121
+78
Documentation/driver-api/wbrf.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + ================================= 4 + WBRF - Wifi Band RFI Mitigations 5 + ================================= 6 + 7 + Due to electrical and mechanical constraints in certain platform designs 8 + there may be likely interference of relatively high-powered harmonics of 9 + the GPU memory clocks with local radio module frequency bands used by 10 + certain Wifi bands. 11 + 12 + To mitigate possible RFI interference producers can advertise the 13 + frequencies in use and consumers can use this information to avoid using 14 + these frequencies for sensitive features. 15 + 16 + When a platform is known to have this issue with any contained devices, 17 + the platform designer will advertise the availability of this feature via 18 + ACPI devices with a device specific method (_DSM). 19 + * Producers with this _DSM will be able to advertise the frequencies in use. 20 + * Consumers with this _DSM will be able to register for notifications of 21 + frequencies in use. 22 + 23 + Some general terms 24 + ================== 25 + 26 + Producer: such component who can produce high-powered radio frequency 27 + Consumer: such component who can adjust its in-use frequency in 28 + response to the radio frequencies of other components to mitigate the 29 + possible RFI. 30 + 31 + To make the mechanism function, those producers should notify active use 32 + of their particular frequencies so that other consumers can make relative 33 + internal adjustments as necessary to avoid this resonance. 34 + 35 + ACPI interface 36 + ============== 37 + 38 + Although initially used by for wifi + dGPU use cases, the ACPI interface 39 + can be scaled to any type of device that a platform designer discovers 40 + can cause interference. 41 + 42 + The GUID used for the _DSM is 7B7656CF-DC3D-4C1C-83E9-66E721DE3070. 43 + 44 + 3 functions are available in this _DSM: 45 + 46 + * 0: discover # of functions available 47 + * 1: record RF bands in use 48 + * 2: retrieve RF bands in use 49 + 50 + Driver programming interface 51 + ============================ 52 + 53 + .. kernel-doc:: drivers/platform/x86/amd/wbrf.c 54 + 55 + Sample Usage 56 + ============= 57 + 58 + The expected flow for the producers: 59 + 1. During probe, call `acpi_amd_wbrf_supported_producer` to check if WBRF 60 + can be enabled for the device. 61 + 2. On using some frequency band, call `acpi_amd_wbrf_add_remove` with 'add' 62 + param to get other consumers properly notified. 63 + 3. Or on stopping using some frequency band, call 64 + `acpi_amd_wbrf_add_remove` with 'remove' param to get other consumers notified. 65 + 66 + The expected flow for the consumers: 67 + 1. During probe, call `acpi_amd_wbrf_supported_consumer` to check if WBRF 68 + can be enabled for the device. 69 + 2. Call `amd_wbrf_register_notifier` to register for notification 70 + of frequency band change(add or remove) from other producers. 71 + 3. Call the `amd_wbrf_retrieve_freq_band` initally to retrieve 72 + current active frequency bands considering some producers may broadcast 73 + such information before the consumer is up. 74 + 4. On receiving a notification for frequency band change, run 75 + `amd_wbrf_retrieve_freq_band` again to retrieve the latest 76 + active frequency bands. 77 + 5. During driver cleanup, call `amd_wbrf_unregister_notifier` to 78 + unregister the notifier.
+3
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 252 252 extern int amdgpu_user_partt_mode; 253 253 extern int amdgpu_agp; 254 254 255 + extern int amdgpu_wbrf; 256 + 255 257 #define AMDGPU_VM_MAX_NUM_CTX 4096 256 258 #define AMDGPU_SG_THRESHOLD (256*1024*1024) 257 259 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 ··· 791 789 uint64_t eop_gpu_addr; 792 790 uint32_t hqd_pipe_priority; 793 791 uint32_t hqd_queue_priority; 792 + bool allow_tunneling; 794 793 bool hqd_active; 795 794 }; 796 795
+11
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
··· 142 142 { 143 143 int i; 144 144 int last_valid_bit; 145 + int ret; 145 146 146 147 amdgpu_amdkfd_gpuvm_init_mem_limits(); 147 148 ··· 160 159 .sdma_doorbell_idx = adev->doorbell_index.sdma_engine, 161 160 .enable_mes = adev->enable_mes, 162 161 }; 162 + 163 + ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd", NULL); 164 + if (ret) { 165 + dev_err(adev->dev, "Failed to init DRM client: %d\n", ret); 166 + return; 167 + } 163 168 164 169 /* this is going to have a few of the MSBs set that we need to 165 170 * clear ··· 205 198 206 199 adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev, 207 200 &gpu_resources); 201 + if (adev->kfd.init_complete) 202 + drm_client_register(&adev->kfd.client); 203 + else 204 + drm_client_release(&adev->kfd.client); 208 205 209 206 amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; 210 207
+9 -5
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
··· 33 33 #include <linux/mmu_notifier.h> 34 34 #include <linux/memremap.h> 35 35 #include <kgd_kfd_interface.h> 36 + #include <drm/drm_client.h> 36 37 #include "amdgpu_sync.h" 37 38 #include "amdgpu_vm.h" 38 39 #include "amdgpu_xcp.h" ··· 84 83 85 84 struct amdgpu_sync sync; 86 85 86 + uint32_t gem_handle; 87 87 bool aql_queue; 88 88 bool is_imported; 89 89 }; ··· 107 105 108 106 /* HMM page migration MEMORY_DEVICE_PRIVATE mapping */ 109 107 struct dev_pagemap pgmap; 108 + 109 + /* Client for KFD BO GEM handle allocations */ 110 + struct drm_client_dev client; 110 111 }; 111 112 112 113 enum kgd_engine_type { ··· 314 309 struct dma_fence **ef); 315 310 int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct amdgpu_device *adev, 316 311 struct kfd_vm_fault_info *info); 317 - int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev, 318 - struct dma_buf *dmabuf, 319 - uint64_t va, void *drm_priv, 320 - struct kgd_mem **mem, uint64_t *size, 321 - uint64_t *mmap_offset); 312 + int amdgpu_amdkfd_gpuvm_import_dmabuf_fd(struct amdgpu_device *adev, int fd, 313 + uint64_t va, void *drm_priv, 314 + struct kgd_mem **mem, uint64_t *size, 315 + uint64_t *mmap_offset); 322 316 int amdgpu_amdkfd_gpuvm_export_dmabuf(struct kgd_mem *mem, 323 317 struct dma_buf **dmabuf); 324 318 void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev);
+68 -25
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
··· 25 25 #include <linux/pagemap.h> 26 26 #include <linux/sched/mm.h> 27 27 #include <linux/sched/task.h> 28 + #include <linux/fdtable.h> 28 29 #include <drm/ttm/ttm_tt.h> 29 30 30 31 #include <drm/drm_exec.h> ··· 807 806 static int kfd_mem_export_dmabuf(struct kgd_mem *mem) 808 807 { 809 808 if (!mem->dmabuf) { 810 - struct dma_buf *ret = amdgpu_gem_prime_export( 811 - &mem->bo->tbo.base, 809 + struct amdgpu_device *bo_adev; 810 + struct dma_buf *dmabuf; 811 + int r, fd; 812 + 813 + bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev); 814 + r = drm_gem_prime_handle_to_fd(&bo_adev->ddev, bo_adev->kfd.client.file, 815 + mem->gem_handle, 812 816 mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? 813 - DRM_RDWR : 0); 814 - if (IS_ERR(ret)) 815 - return PTR_ERR(ret); 816 - mem->dmabuf = ret; 817 + DRM_RDWR : 0, &fd); 818 + if (r) 819 + return r; 820 + dmabuf = dma_buf_get(fd); 821 + close_fd(fd); 822 + if (WARN_ON_ONCE(IS_ERR(dmabuf))) 823 + return PTR_ERR(dmabuf); 824 + mem->dmabuf = dmabuf; 817 825 } 818 826 819 827 return 0; ··· 1788 1778 pr_debug("Failed to allow vma node access. ret %d\n", ret); 1789 1779 goto err_node_allow; 1790 1780 } 1781 + ret = drm_gem_handle_create(adev->kfd.client.file, gobj, &(*mem)->gem_handle); 1782 + if (ret) 1783 + goto err_gem_handle_create; 1791 1784 bo = gem_to_amdgpu_bo(gobj); 1792 1785 if (bo_type == ttm_bo_type_sg) { 1793 1786 bo->tbo.sg = sg; ··· 1842 1829 err_pin_bo: 1843 1830 err_validate_bo: 1844 1831 remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); 1832 + drm_gem_handle_delete(adev->kfd.client.file, (*mem)->gem_handle); 1833 + err_gem_handle_create: 1845 1834 drm_vma_node_revoke(&gobj->vma_node, drm_priv); 1846 1835 err_node_allow: 1847 1836 /* Don't unreserve system mem limit twice */ ··· 1956 1941 1957 1942 /* Free the BO*/ 1958 1943 drm_vma_node_revoke(&mem->bo->tbo.base.vma_node, drm_priv); 1959 - if (mem->dmabuf) 1944 + drm_gem_handle_delete(adev->kfd.client.file, mem->gem_handle); 1945 + if (mem->dmabuf) { 1960 1946 dma_buf_put(mem->dmabuf); 1947 + mem->dmabuf = NULL; 1948 + } 1961 1949 mutex_destroy(&mem->lock); 1962 1950 1963 1951 /* If this releases the last reference, it will end up calling ··· 2312 2294 return 0; 2313 2295 } 2314 2296 2315 - int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev, 2316 - struct dma_buf *dma_buf, 2317 - uint64_t va, void *drm_priv, 2318 - struct kgd_mem **mem, uint64_t *size, 2319 - uint64_t *mmap_offset) 2297 + static int import_obj_create(struct amdgpu_device *adev, 2298 + struct dma_buf *dma_buf, 2299 + struct drm_gem_object *obj, 2300 + uint64_t va, void *drm_priv, 2301 + struct kgd_mem **mem, uint64_t *size, 2302 + uint64_t *mmap_offset) 2320 2303 { 2321 2304 struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); 2322 - struct drm_gem_object *obj; 2323 2305 struct amdgpu_bo *bo; 2324 2306 int ret; 2325 2307 2326 - obj = amdgpu_gem_prime_import(adev_to_drm(adev), dma_buf); 2327 - if (IS_ERR(obj)) 2328 - return PTR_ERR(obj); 2329 - 2330 2308 bo = gem_to_amdgpu_bo(obj); 2331 2309 if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | 2332 - AMDGPU_GEM_DOMAIN_GTT))) { 2310 + AMDGPU_GEM_DOMAIN_GTT))) 2333 2311 /* Only VRAM and GTT BOs are supported */ 2334 - ret = -EINVAL; 2335 - goto err_put_obj; 2336 - } 2312 + return -EINVAL; 2337 2313 2338 2314 *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); 2339 - if (!*mem) { 2340 - ret = -ENOMEM; 2341 - goto err_put_obj; 2342 - } 2315 + if (!*mem) 2316 + return -ENOMEM; 2343 2317 2344 2318 ret = drm_vma_node_allow(&obj->vma_node, drm_priv); 2345 2319 if (ret) ··· 2381 2371 drm_vma_node_revoke(&obj->vma_node, drm_priv); 2382 2372 err_free_mem: 2383 2373 kfree(*mem); 2374 + return ret; 2375 + } 2376 + 2377 + int amdgpu_amdkfd_gpuvm_import_dmabuf_fd(struct amdgpu_device *adev, int fd, 2378 + uint64_t va, void *drm_priv, 2379 + struct kgd_mem **mem, uint64_t *size, 2380 + uint64_t *mmap_offset) 2381 + { 2382 + struct drm_gem_object *obj; 2383 + uint32_t handle; 2384 + int ret; 2385 + 2386 + ret = drm_gem_prime_fd_to_handle(&adev->ddev, adev->kfd.client.file, fd, 2387 + &handle); 2388 + if (ret) 2389 + return ret; 2390 + obj = drm_gem_object_lookup(adev->kfd.client.file, handle); 2391 + if (!obj) { 2392 + ret = -EINVAL; 2393 + goto err_release_handle; 2394 + } 2395 + 2396 + ret = import_obj_create(adev, obj->dma_buf, obj, va, drm_priv, mem, size, 2397 + mmap_offset); 2398 + if (ret) 2399 + goto err_put_obj; 2400 + 2401 + (*mem)->gem_handle = handle; 2402 + 2403 + return 0; 2404 + 2384 2405 err_put_obj: 2385 2406 drm_gem_object_put(obj); 2407 + err_release_handle: 2408 + drm_gem_handle_delete(adev->kfd.client.file, handle); 2386 2409 return ret; 2387 2410 } 2388 2411
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
··· 755 755 int r; 756 756 757 757 if (!adev->smc_rreg) 758 - return -EPERM; 758 + return -EOPNOTSUPP; 759 759 760 760 if (size & 0x3 || *pos & 0x3) 761 761 return -EINVAL; ··· 814 814 int r; 815 815 816 816 if (!adev->smc_wreg) 817 - return -EPERM; 817 + return -EOPNOTSUPP; 818 818 819 819 if (size & 0x3 || *pos & 0x3) 820 820 return -EINVAL;
+1 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 1599 1599 if (adev->mman.keep_stolen_vga_memory) 1600 1600 return false; 1601 1601 1602 - return adev->ip_versions[DCE_HWIP][0] >= IP_VERSION(3, 0, 0); 1602 + return amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0); 1603 1603 } 1604 1604 1605 1605 /* ··· 4588 4588 flush_delayed_work(&adev->gfx.gfx_off_delay_work); 4589 4589 4590 4590 amdgpu_ras_suspend(adev); 4591 - 4592 - amdgpu_ttm_set_buffer_funcs_status(adev, false); 4593 4591 4594 4592 amdgpu_device_ip_suspend_phase1(adev); 4595 4593
+19 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 115 115 * 3.54.0 - Add AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS support 116 116 * - 3.55.0 - Add AMDGPU_INFO_GPUVM_FAULT query 117 117 * - 3.56.0 - Update IB start address and size alignment for decode and encode 118 + * - 3.57.0 - Compute tunneling on GFX10+ 118 119 */ 119 120 #define KMS_DRIVER_MAJOR 3 120 - #define KMS_DRIVER_MINOR 56 121 + #define KMS_DRIVER_MINOR 57 121 122 #define KMS_DRIVER_PATCHLEVEL 0 122 123 123 124 /* ··· 209 208 int amdgpu_seamless = -1; /* auto */ 210 209 uint amdgpu_debug_mask; 211 210 int amdgpu_agp = -1; /* auto */ 211 + int amdgpu_wbrf = -1; 212 212 213 213 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work); 214 214 ··· 972 970 */ 973 971 MODULE_PARM_DESC(agp, "AGP (-1 = auto (default), 0 = disable, 1 = enable)"); 974 972 module_param_named(agp, amdgpu_agp, int, 0444); 973 + 974 + /** 975 + * DOC: wbrf (int) 976 + * Enable Wifi RFI interference mitigation feature. 977 + * Due to electrical and mechanical constraints there may be likely interference of 978 + * relatively high-powered harmonics of the (G-)DDR memory clocks with local radio 979 + * module frequency bands used by Wifi 6/6e/7. To mitigate the possible RFI interference, 980 + * with this feature enabled, PMFW will use either “shadowed P-State” or “P-State” based 981 + * on active list of frequencies in-use (to be avoided) as part of initial setting or 982 + * P-state transition. However, there may be potential performance impact with this 983 + * feature enabled. 984 + * (0 = disabled, 1 = enabled, -1 = auto (default setting, will be enabled if supported)) 985 + */ 986 + MODULE_PARM_DESC(wbrf, 987 + "Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)"); 988 + module_param_named(wbrf, amdgpu_wbrf, int, 0444); 975 989 976 990 /* These devices are not supported by amdgpu. 977 991 * They are supported by the mach64, r128, radeon drivers
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
··· 190 190 pr_debug("hmm range: start = 0x%lx, end = 0x%lx", 191 191 hmm_range->start, hmm_range->end); 192 192 193 - /* Assuming 128MB takes maximum 1 second to fault page address */ 194 - timeout = max((hmm_range->end - hmm_range->start) >> 27, 1UL); 193 + /* Assuming 64MB takes maximum 1 second to fault page address */ 194 + timeout = max((hmm_range->end - hmm_range->start) >> 26, 1UL); 195 195 timeout *= HMM_RANGE_DEFAULT_TIMEOUT; 196 196 timeout = jiffies + msecs_to_jiffies(timeout); 197 197 ··· 199 199 hmm_range->notifier_seq = mmu_interval_read_begin(notifier); 200 200 r = hmm_range_fault(hmm_range); 201 201 if (unlikely(r)) { 202 + schedule(); 202 203 /* 203 204 * FIXME: This timeout should encompass the retry from 204 205 * mmu_interval_read_retry() as well. ··· 213 212 break; 214 213 hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT; 215 214 hmm_range->start = hmm_range->end; 216 - schedule(); 217 215 } while (hmm_range->end < end); 218 216 219 217 hmm_range->start = start;
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h
··· 46 46 #define MCA_REG__STATUS__ERRORCODEEXT(x) MCA_REG_FIELD(x, 21, 16) 47 47 #define MCA_REG__STATUS__ERRORCODE(x) MCA_REG_FIELD(x, 15, 0) 48 48 49 + #define MCA_REG__MISC0__ERRCNT(x) MCA_REG_FIELD(x, 43, 32) 50 + 49 51 #define MCA_REG__SYND__ERRORINFORMATION(x) MCA_REG_FIELD(x, 17, 0) 50 52 51 53 enum amdgpu_mca_ip {
+31
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
··· 916 916 op_input.op = MES_MISC_OP_SET_SHADER_DEBUGGER; 917 917 op_input.set_shader_debugger.process_context_addr = process_context_addr; 918 918 op_input.set_shader_debugger.flags.u32all = flags; 919 + 920 + /* use amdgpu mes_flush_shader_debugger instead */ 921 + if (op_input.set_shader_debugger.flags.process_ctx_flush) 922 + return -EINVAL; 923 + 919 924 op_input.set_shader_debugger.spi_gdbg_per_vmid_cntl = spi_gdbg_per_vmid_cntl; 920 925 memcpy(op_input.set_shader_debugger.tcp_watch_cntl, tcp_watch_cntl, 921 926 sizeof(op_input.set_shader_debugger.tcp_watch_cntl)); ··· 928 923 if (((adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK) >> 929 924 AMDGPU_MES_API_VERSION_SHIFT) >= 14) 930 925 op_input.set_shader_debugger.trap_en = trap_en; 926 + 927 + amdgpu_mes_lock(&adev->mes); 928 + 929 + r = adev->mes.funcs->misc_op(&adev->mes, &op_input); 930 + if (r) 931 + DRM_ERROR("failed to set_shader_debugger\n"); 932 + 933 + amdgpu_mes_unlock(&adev->mes); 934 + 935 + return r; 936 + } 937 + 938 + int amdgpu_mes_flush_shader_debugger(struct amdgpu_device *adev, 939 + uint64_t process_context_addr) 940 + { 941 + struct mes_misc_op_input op_input = {0}; 942 + int r; 943 + 944 + if (!adev->mes.funcs->misc_op) { 945 + DRM_ERROR("mes flush shader debugger is not supported!\n"); 946 + return -EINVAL; 947 + } 948 + 949 + op_input.op = MES_MISC_OP_SET_SHADER_DEBUGGER; 950 + op_input.set_shader_debugger.process_context_addr = process_context_addr; 951 + op_input.set_shader_debugger.flags.process_ctx_flush = true; 931 952 932 953 amdgpu_mes_lock(&adev->mes); 933 954
+6 -4
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
··· 296 296 uint64_t process_context_addr; 297 297 union { 298 298 struct { 299 - uint64_t single_memop : 1; 300 - uint64_t single_alu_op : 1; 301 - uint64_t reserved: 30; 299 + uint32_t single_memop : 1; 300 + uint32_t single_alu_op : 1; 301 + uint32_t reserved: 29; 302 + uint32_t process_ctx_flush: 1; 302 303 }; 303 304 uint32_t u32all; 304 305 } flags; ··· 375 374 const uint32_t *tcp_watch_cntl, 376 375 uint32_t flags, 377 376 bool trap_en); 378 - 377 + int amdgpu_mes_flush_shader_debugger(struct amdgpu_device *adev, 378 + uint64_t process_context_addr); 379 379 int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id, 380 380 int queue_type, int idx, 381 381 struct amdgpu_mes_ctx_data *ctx_data,
+92 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
··· 32 32 33 33 #include <drm/display/drm_dp_helper.h> 34 34 #include <drm/drm_crtc.h> 35 - #include <drm/drm_edid.h> 36 35 #include <drm/drm_encoder.h> 37 36 #include <drm/drm_fixed.h> 38 37 #include <drm/drm_framebuffer.h> ··· 50 51 struct amdgpu_encoder; 51 52 struct amdgpu_router; 52 53 struct amdgpu_hpd; 54 + struct edid; 53 55 54 56 #define to_amdgpu_crtc(x) container_of(x, struct amdgpu_crtc, base) 55 57 #define to_amdgpu_connector(x) container_of(x, struct amdgpu_connector, base) ··· 343 343 int disp_priority; 344 344 const struct amdgpu_display_funcs *funcs; 345 345 const enum drm_plane_type *plane_type; 346 + 347 + /* Driver-private color mgmt props */ 348 + 349 + /* @plane_degamma_lut_property: Plane property to set a degamma LUT to 350 + * convert encoded values to light linear values before sampling or 351 + * blending. 352 + */ 353 + struct drm_property *plane_degamma_lut_property; 354 + /* @plane_degamma_lut_size_property: Plane property to define the max 355 + * size of degamma LUT as supported by the driver (read-only). 356 + */ 357 + struct drm_property *plane_degamma_lut_size_property; 358 + /** 359 + * @plane_degamma_tf_property: Plane pre-defined transfer function to 360 + * to go from scanout/encoded values to linear values. 361 + */ 362 + struct drm_property *plane_degamma_tf_property; 363 + /** 364 + * @plane_hdr_mult_property: 365 + */ 366 + struct drm_property *plane_hdr_mult_property; 367 + 368 + struct drm_property *plane_ctm_property; 369 + /** 370 + * @shaper_lut_property: Plane property to set pre-blending shaper LUT 371 + * that converts color content before 3D LUT. If 372 + * plane_shaper_tf_property != Identity TF, AMD color module will 373 + * combine the user LUT values with pre-defined TF into the LUT 374 + * parameters to be programmed. 375 + */ 376 + struct drm_property *plane_shaper_lut_property; 377 + /** 378 + * @shaper_lut_size_property: Plane property for the size of 379 + * pre-blending shaper LUT as supported by the driver (read-only). 380 + */ 381 + struct drm_property *plane_shaper_lut_size_property; 382 + /** 383 + * @plane_shaper_tf_property: Plane property to set a predefined 384 + * transfer function for pre-blending shaper (before applying 3D LUT) 385 + * with or without LUT. There is no shaper ROM, but we can use AMD 386 + * color modules to program LUT parameters from predefined TF (or 387 + * from a combination of pre-defined TF and the custom 1D LUT). 388 + */ 389 + struct drm_property *plane_shaper_tf_property; 390 + /** 391 + * @plane_lut3d_property: Plane property for color transformation using 392 + * a 3D LUT (pre-blending), a three-dimensional array where each 393 + * element is an RGB triplet. Each dimension has the size of 394 + * lut3d_size. The array contains samples from the approximated 395 + * function. On AMD, values between samples are estimated by 396 + * tetrahedral interpolation. The array is accessed with three indices, 397 + * one for each input dimension (color channel), blue being the 398 + * outermost dimension, red the innermost. 399 + */ 400 + struct drm_property *plane_lut3d_property; 401 + /** 402 + * @plane_degamma_lut_size_property: Plane property to define the max 403 + * size of 3D LUT as supported by the driver (read-only). The max size 404 + * is the max size of one dimension and, therefore, the max number of 405 + * entries for 3D LUT array is the 3D LUT size cubed; 406 + */ 407 + struct drm_property *plane_lut3d_size_property; 408 + /** 409 + * @plane_blend_lut_property: Plane property for output gamma before 410 + * blending. Userspace set a blend LUT to convert colors after 3D LUT 411 + * conversion. It works as a post-3DLUT 1D LUT. With shaper LUT, they 412 + * are sandwiching 3D LUT with two 1D LUT. If plane_blend_tf_property 413 + * != Identity TF, AMD color module will combine the user LUT values 414 + * with pre-defined TF into the LUT parameters to be programmed. 415 + */ 416 + struct drm_property *plane_blend_lut_property; 417 + /** 418 + * @plane_blend_lut_size_property: Plane property to define the max 419 + * size of blend LUT as supported by the driver (read-only). 420 + */ 421 + struct drm_property *plane_blend_lut_size_property; 422 + /** 423 + * @plane_blend_tf_property: Plane property to set a predefined 424 + * transfer function for pre-blending blend/out_gamma (after applying 425 + * 3D LUT) with or without LUT. There is no blend ROM, but we can use 426 + * AMD color modules to program LUT parameters from predefined TF (or 427 + * from a combination of pre-defined TF and the custom 1D LUT). 428 + */ 429 + struct drm_property *plane_blend_tf_property; 430 + /* @regamma_tf_property: Transfer function for CRTC regamma 431 + * (post-blending). Possible values are defined by `enum 432 + * amdgpu_transfer_function`. There is no regamma ROM, but we can use 433 + * AMD color modules to program LUT parameters from predefined TF (or 434 + * from a combination of pre-defined TF and the custom 1D LUT). 435 + */ 436 + struct drm_property *regamma_tf_property; 346 437 }; 347 438 348 439 #define AMDGPU_MAX_BL_LEVEL 0xFF
+3 -12
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
··· 1245 1245 * amdgpu_bo_move_notify - notification about a memory move 1246 1246 * @bo: pointer to a buffer object 1247 1247 * @evict: if this move is evicting the buffer from the graphics address space 1248 - * @new_mem: new information of the bufer object 1249 1248 * 1250 1249 * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs 1251 1250 * bookkeeping. 1252 1251 * TTM driver callback which is called when ttm moves a buffer. 1253 1252 */ 1254 - void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, 1255 - bool evict, 1256 - struct ttm_resource *new_mem) 1253 + void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict) 1257 1254 { 1258 1255 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); 1259 1256 struct amdgpu_bo *abo; 1260 - struct ttm_resource *old_mem = bo->resource; 1261 1257 1262 1258 if (!amdgpu_bo_is_amdgpu_bo(bo)) 1263 1259 return; ··· 1270 1274 /* remember the eviction */ 1271 1275 if (evict) 1272 1276 atomic64_inc(&adev->num_evictions); 1273 - 1274 - /* update statistics */ 1275 - if (!new_mem) 1276 - return; 1277 - 1278 - /* move_notify is called before move happens */ 1279 - trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type); 1280 1277 } 1281 1278 1282 1279 void amdgpu_bo_get_memory(struct amdgpu_bo *bo, ··· 1331 1342 return; 1332 1343 1333 1344 abo = ttm_to_amdgpu_bo(bo); 1345 + 1346 + WARN_ON(abo->vm_bo); 1334 1347 1335 1348 if (abo->kfd_bo) 1336 1349 amdgpu_amdkfd_release_notify(abo);
+1 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
··· 344 344 int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, 345 345 size_t buffer_size, uint32_t *metadata_size, 346 346 uint64_t *flags); 347 - void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, 348 - bool evict, 349 - struct ttm_resource *new_mem); 347 + void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict); 350 348 void amdgpu_bo_release_notify(struct ttm_buffer_object *bo); 351 349 vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); 352 350 void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 1433 1433 get_extended_data) || 1434 1434 amdgpu_ip_version(psp->adev, MP0_HWIP, 0) == 1435 1435 IP_VERSION(13, 0, 6); 1436 - bool ta_port_num_support = psp->xgmi_context.xgmi_ta_caps & 1437 - EXTEND_PEER_LINK_INFO_CMD_FLAG; 1436 + bool ta_port_num_support = amdgpu_sriov_vf(psp->adev) ? 0 : 1437 + psp->xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG; 1438 1438 1439 1439 /* popluate the shared output buffer rather than the cmd input buffer 1440 1440 * with node_ids as the input for GET_PEER_LINKS command execution.
+6 -4
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
··· 642 642 struct amdgpu_mqd_prop *prop) 643 643 { 644 644 struct amdgpu_device *adev = ring->adev; 645 + bool is_high_prio_compute = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && 646 + amdgpu_gfx_is_high_priority_compute_queue(adev, ring); 647 + bool is_high_prio_gfx = ring->funcs->type == AMDGPU_RING_TYPE_GFX && 648 + amdgpu_gfx_is_high_priority_graphics_queue(adev, ring); 645 649 646 650 memset(prop, 0, sizeof(*prop)); 647 651 ··· 663 659 */ 664 660 prop->hqd_active = ring->funcs->type == AMDGPU_RING_TYPE_KIQ; 665 661 666 - if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && 667 - amdgpu_gfx_is_high_priority_compute_queue(adev, ring)) || 668 - (ring->funcs->type == AMDGPU_RING_TYPE_GFX && 669 - amdgpu_gfx_is_high_priority_graphics_queue(adev, ring))) { 662 + prop->allow_tunneling = is_high_prio_compute; 663 + if (is_high_prio_compute || is_high_prio_gfx) { 670 664 prop->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_HIGH; 671 665 prop->hqd_queue_priority = AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM; 672 666 }
+3 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 545 545 return r; 546 546 } 547 547 548 + trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type); 548 549 out: 549 550 /* update statistics */ 550 551 atomic64_add(bo->base.size, &adev->num_bytes_moved); 551 - amdgpu_bo_move_notify(bo, evict, new_mem); 552 + amdgpu_bo_move_notify(bo, evict); 552 553 return 0; 553 554 } 554 555 ··· 1554 1553 static void 1555 1554 amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo) 1556 1555 { 1557 - amdgpu_bo_move_notify(bo, false, NULL); 1556 + amdgpu_bo_move_notify(bo, false); 1558 1557 } 1559 1558 1560 1559 static struct ttm_device_funcs amdgpu_bo_driver = {
+2 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
··· 1099 1099 { 1100 1100 bool xnack_mode = true; 1101 1101 1102 - if (amdgpu_sriov_vf(adev) && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) 1102 + if (amdgpu_sriov_vf(adev) && 1103 + amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 2)) 1103 1104 xnack_mode = false; 1104 1105 1105 1106 return xnack_mode;
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0+ 2 2 3 3 #include <drm/drm_atomic_helper.h> 4 + #include <drm/drm_edid.h> 4 5 #include <drm/drm_simple_kms_helper.h> 5 6 #include <drm/drm_vblank.h> 6 7
+2 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
··· 642 642 643 643 if (!entry->bo) 644 644 return; 645 + 646 + entry->bo->vm_bo = NULL; 645 647 shadow = amdgpu_bo_shadowed(entry->bo); 646 648 if (shadow) { 647 649 ttm_bo_set_bulk_move(&shadow->tbo, NULL); 648 650 amdgpu_bo_unref(&shadow); 649 651 } 650 652 ttm_bo_set_bulk_move(&entry->bo->tbo, NULL); 651 - entry->bo->vm_bo = NULL; 652 653 653 654 spin_lock(&entry->vm->status_lock); 654 655 list_del(&entry->vm_status);
+249
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
··· 26 26 #include "amdgpu.h" 27 27 #include "amdgpu_ucode.h" 28 28 #include "amdgpu_vpe.h" 29 + #include "amdgpu_smu.h" 29 30 #include "soc15_common.h" 30 31 #include "vpe_v6_1.h" 31 32 ··· 34 33 /* VPE CSA resides in the 4th page of CSA */ 35 34 #define AMDGPU_CSA_VPE_OFFSET (4096 * 3) 36 35 36 + /* 1 second timeout */ 37 + #define VPE_IDLE_TIMEOUT msecs_to_jiffies(1000) 38 + 39 + #define VPE_MAX_DPM_LEVEL 4 40 + #define FIXED1_8_BITS_PER_FRACTIONAL_PART 8 41 + #define GET_PRATIO_INTEGER_PART(x) ((x) >> FIXED1_8_BITS_PER_FRACTIONAL_PART) 42 + 37 43 static void vpe_set_ring_funcs(struct amdgpu_device *adev); 44 + 45 + static inline uint16_t div16_u16_rem(uint16_t dividend, uint16_t divisor, uint16_t *remainder) 46 + { 47 + *remainder = dividend % divisor; 48 + return dividend / divisor; 49 + } 50 + 51 + static inline uint16_t complete_integer_division_u16( 52 + uint16_t dividend, 53 + uint16_t divisor, 54 + uint16_t *remainder) 55 + { 56 + return div16_u16_rem(dividend, divisor, (uint16_t *)remainder); 57 + } 58 + 59 + static uint16_t vpe_u1_8_from_fraction(uint16_t numerator, uint16_t denominator) 60 + { 61 + bool arg1_negative = numerator < 0; 62 + bool arg2_negative = denominator < 0; 63 + 64 + uint16_t arg1_value = (uint16_t)(arg1_negative ? -numerator : numerator); 65 + uint16_t arg2_value = (uint16_t)(arg2_negative ? -denominator : denominator); 66 + 67 + uint16_t remainder; 68 + 69 + /* determine integer part */ 70 + uint16_t res_value = complete_integer_division_u16( 71 + arg1_value, arg2_value, &remainder); 72 + 73 + if (res_value > 127 /* CHAR_MAX */) 74 + return 0; 75 + 76 + /* determine fractional part */ 77 + { 78 + unsigned int i = FIXED1_8_BITS_PER_FRACTIONAL_PART; 79 + 80 + do { 81 + remainder <<= 1; 82 + 83 + res_value <<= 1; 84 + 85 + if (remainder >= arg2_value) { 86 + res_value |= 1; 87 + remainder -= arg2_value; 88 + } 89 + } while (--i != 0); 90 + } 91 + 92 + /* round up LSB */ 93 + { 94 + uint16_t summand = (remainder << 1) >= arg2_value; 95 + 96 + if ((res_value + summand) > 32767 /* SHRT_MAX */) 97 + return 0; 98 + 99 + res_value += summand; 100 + } 101 + 102 + if (arg1_negative ^ arg2_negative) 103 + res_value = -res_value; 104 + 105 + return res_value; 106 + } 107 + 108 + static uint16_t vpe_internal_get_pratio(uint16_t from_frequency, uint16_t to_frequency) 109 + { 110 + uint16_t pratio = vpe_u1_8_from_fraction(from_frequency, to_frequency); 111 + 112 + if (GET_PRATIO_INTEGER_PART(pratio) > 1) 113 + pratio = 0; 114 + 115 + return pratio; 116 + } 117 + 118 + /* 119 + * VPE has 4 DPM levels from level 0 (lowerest) to 3 (highest), 120 + * VPE FW will dynamically decide which level should be used according to current loading. 121 + * 122 + * Get VPE and SOC clocks from PM, and select the appropriate four clock values, 123 + * calculate the ratios of adjusting from one clock to another. 124 + * The VPE FW can then request the appropriate frequency from the PMFW. 125 + */ 126 + int amdgpu_vpe_configure_dpm(struct amdgpu_vpe *vpe) 127 + { 128 + struct amdgpu_device *adev = vpe->ring.adev; 129 + uint32_t dpm_ctl; 130 + 131 + if (adev->pm.dpm_enabled) { 132 + struct dpm_clocks clock_table = { 0 }; 133 + struct dpm_clock *VPEClks; 134 + struct dpm_clock *SOCClks; 135 + uint32_t idx; 136 + uint32_t pratio_vmax_vnorm = 0, pratio_vnorm_vmid = 0, pratio_vmid_vmin = 0; 137 + uint16_t pratio_vmin_freq = 0, pratio_vmid_freq = 0, pratio_vnorm_freq = 0, pratio_vmax_freq = 0; 138 + 139 + dpm_ctl = RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable)); 140 + dpm_ctl |= 1; /* DPM enablement */ 141 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl); 142 + 143 + /* Get VPECLK and SOCCLK */ 144 + if (amdgpu_dpm_get_dpm_clock_table(adev, &clock_table)) { 145 + dev_dbg(adev->dev, "%s: get clock failed!\n", __func__); 146 + goto disable_dpm; 147 + } 148 + 149 + SOCClks = clock_table.SocClocks; 150 + VPEClks = clock_table.VPEClocks; 151 + 152 + /* vpe dpm only cares 4 levels. */ 153 + for (idx = 0; idx < VPE_MAX_DPM_LEVEL; idx++) { 154 + uint32_t soc_dpm_level; 155 + uint32_t min_freq; 156 + 157 + if (idx == 0) 158 + soc_dpm_level = 0; 159 + else 160 + soc_dpm_level = (idx * 2) + 1; 161 + 162 + /* clamp the max level */ 163 + if (soc_dpm_level > PP_SMU_NUM_VPECLK_DPM_LEVELS - 1) 164 + soc_dpm_level = PP_SMU_NUM_VPECLK_DPM_LEVELS - 1; 165 + 166 + min_freq = (SOCClks[soc_dpm_level].Freq < VPEClks[soc_dpm_level].Freq) ? 167 + SOCClks[soc_dpm_level].Freq : VPEClks[soc_dpm_level].Freq; 168 + 169 + switch (idx) { 170 + case 0: 171 + pratio_vmin_freq = min_freq; 172 + break; 173 + case 1: 174 + pratio_vmid_freq = min_freq; 175 + break; 176 + case 2: 177 + pratio_vnorm_freq = min_freq; 178 + break; 179 + case 3: 180 + pratio_vmax_freq = min_freq; 181 + break; 182 + default: 183 + break; 184 + } 185 + } 186 + 187 + if (pratio_vmin_freq && pratio_vmid_freq && pratio_vnorm_freq && pratio_vmax_freq) { 188 + uint32_t pratio_ctl; 189 + 190 + pratio_vmax_vnorm = (uint32_t)vpe_internal_get_pratio(pratio_vmax_freq, pratio_vnorm_freq); 191 + pratio_vnorm_vmid = (uint32_t)vpe_internal_get_pratio(pratio_vnorm_freq, pratio_vmid_freq); 192 + pratio_vmid_vmin = (uint32_t)vpe_internal_get_pratio(pratio_vmid_freq, pratio_vmin_freq); 193 + 194 + pratio_ctl = pratio_vmax_vnorm | (pratio_vnorm_vmid << 9) | (pratio_vmid_vmin << 18); 195 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_pratio), pratio_ctl); /* PRatio */ 196 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_request_interval), 24000); /* 1ms, unit=1/24MHz */ 197 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_decision_threshold), 1200000); /* 50ms */ 198 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_busy_clamp_threshold), 1200000);/* 50ms */ 199 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_idle_clamp_threshold), 1200000);/* 50ms */ 200 + dev_dbg(adev->dev, "%s: configure vpe dpm pratio done!\n", __func__); 201 + } else { 202 + dev_dbg(adev->dev, "%s: invalid pratio parameters!\n", __func__); 203 + goto disable_dpm; 204 + } 205 + } 206 + return 0; 207 + 208 + disable_dpm: 209 + dpm_ctl = RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable)); 210 + dpm_ctl &= 0xfffffffe; /* Disable DPM */ 211 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl); 212 + dev_dbg(adev->dev, "%s: disable vpe dpm\n", __func__); 213 + return 0; 214 + } 38 215 39 216 int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev) 40 217 { ··· 313 134 return 0; 314 135 } 315 136 137 + static void vpe_idle_work_handler(struct work_struct *work) 138 + { 139 + struct amdgpu_device *adev = 140 + container_of(work, struct amdgpu_device, vpe.idle_work.work); 141 + unsigned int fences = 0; 142 + 143 + fences += amdgpu_fence_count_emitted(&adev->vpe.ring); 144 + 145 + if (fences == 0) 146 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); 147 + else 148 + schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT); 149 + } 316 150 317 151 static int vpe_common_init(struct amdgpu_vpe *vpe) 318 152 { ··· 341 149 dev_err(adev->dev, "VPE: failed to allocate cmdbuf bo %d\n", r); 342 150 return r; 343 151 } 152 + 153 + vpe->context_started = false; 154 + INIT_DELAYED_WORK(&adev->vpe.idle_work, vpe_idle_work_handler); 344 155 345 156 return 0; 346 157 } ··· 414 219 415 220 vpe_ring_stop(vpe); 416 221 222 + /* Power off VPE */ 223 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); 224 + 417 225 return 0; 418 226 } 419 227 420 228 static int vpe_suspend(void *handle) 421 229 { 422 230 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 231 + 232 + cancel_delayed_work_sync(&adev->vpe.idle_work); 423 233 424 234 return vpe_hw_fini(adev); 425 235 } ··· 630 430 static int vpe_set_powergating_state(void *handle, 631 431 enum amd_powergating_state state) 632 432 { 433 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 434 + struct amdgpu_vpe *vpe = &adev->vpe; 435 + 436 + if (!adev->pm.dpm_enabled) 437 + dev_err(adev->dev, "Without PM, cannot support powergating\n"); 438 + 439 + dev_dbg(adev->dev, "%s: %s!\n", __func__, (state == AMD_PG_STATE_GATE) ? "GATE":"UNGATE"); 440 + 441 + if (state == AMD_PG_STATE_GATE) { 442 + amdgpu_dpm_enable_vpe(adev, false); 443 + vpe->context_started = false; 444 + } else { 445 + amdgpu_dpm_enable_vpe(adev, true); 446 + } 447 + 633 448 return 0; 634 449 } 635 450 ··· 810 595 return ret; 811 596 } 812 597 598 + static void vpe_ring_begin_use(struct amdgpu_ring *ring) 599 + { 600 + struct amdgpu_device *adev = ring->adev; 601 + struct amdgpu_vpe *vpe = &adev->vpe; 602 + 603 + cancel_delayed_work_sync(&adev->vpe.idle_work); 604 + 605 + /* Power on VPE and notify VPE of new context */ 606 + if (!vpe->context_started) { 607 + uint32_t context_notify; 608 + 609 + /* Power on VPE */ 610 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_UNGATE); 611 + 612 + /* Indicates that a job from a new context has been submitted. */ 613 + context_notify = RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.context_indicator)); 614 + if ((context_notify & 0x1) == 0) 615 + context_notify |= 0x1; 616 + else 617 + context_notify &= ~(0x1); 618 + WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.context_indicator), context_notify); 619 + vpe->context_started = true; 620 + } 621 + } 622 + 623 + static void vpe_ring_end_use(struct amdgpu_ring *ring) 624 + { 625 + struct amdgpu_device *adev = ring->adev; 626 + 627 + schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT); 628 + } 629 + 813 630 static const struct amdgpu_ring_funcs vpe_ring_funcs = { 814 631 .type = AMDGPU_RING_TYPE_VPE, 815 632 .align_mask = 0xf, ··· 872 625 .init_cond_exec = vpe_ring_init_cond_exec, 873 626 .patch_cond_exec = vpe_ring_patch_cond_exec, 874 627 .preempt_ib = vpe_ring_preempt_ib, 628 + .begin_use = vpe_ring_begin_use, 629 + .end_use = vpe_ring_end_use, 875 630 }; 876 631 877 632 static void vpe_set_ring_funcs(struct amdgpu_device *adev)
+12
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.h
··· 47 47 uint32_t queue0_rb_wptr_lo; 48 48 uint32_t queue0_rb_wptr_hi; 49 49 uint32_t queue0_preempt; 50 + 51 + uint32_t dpm_enable; 52 + uint32_t dpm_pratio; 53 + uint32_t dpm_request_interval; 54 + uint32_t dpm_decision_threshold; 55 + uint32_t dpm_busy_clamp_threshold; 56 + uint32_t dpm_idle_clamp_threshold; 57 + uint32_t dpm_request_lv; 58 + uint32_t context_indicator; 50 59 }; 51 60 52 61 struct amdgpu_vpe { ··· 72 63 struct amdgpu_bo *cmdbuf_obj; 73 64 uint64_t cmdbuf_gpu_addr; 74 65 uint32_t *cmdbuf_cpu_addr; 66 + struct delayed_work idle_work; 67 + bool context_started; 75 68 }; 76 69 77 70 int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev); 78 71 int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe); 79 72 int amdgpu_vpe_ring_init(struct amdgpu_vpe *vpe); 80 73 int amdgpu_vpe_ring_fini(struct amdgpu_vpe *vpe); 74 + int amdgpu_vpe_configure_dpm(struct amdgpu_vpe *vpe); 81 75 82 76 #define vpe_ring_init(vpe) ((vpe)->funcs->ring_init ? (vpe)->funcs->ring_init((vpe)) : 0) 83 77 #define vpe_ring_start(vpe) ((vpe)->funcs->ring_start ? (vpe)->funcs->ring_start((vpe)) : 0)
+50 -8
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
··· 823 823 return 0; 824 824 } 825 825 826 + static void amdgpu_xgmi_fill_topology_info(struct amdgpu_device *adev, 827 + struct amdgpu_device *peer_adev) 828 + { 829 + struct psp_xgmi_topology_info *top_info = &adev->psp.xgmi_context.top_info; 830 + struct psp_xgmi_topology_info *peer_info = &peer_adev->psp.xgmi_context.top_info; 831 + 832 + for (int i = 0; i < peer_info->num_nodes; i++) { 833 + if (peer_info->nodes[i].node_id == adev->gmc.xgmi.node_id) { 834 + for (int j = 0; j < top_info->num_nodes; j++) { 835 + if (top_info->nodes[j].node_id == peer_adev->gmc.xgmi.node_id) { 836 + peer_info->nodes[i].num_hops = top_info->nodes[j].num_hops; 837 + peer_info->nodes[i].is_sharing_enabled = 838 + top_info->nodes[j].is_sharing_enabled; 839 + peer_info->nodes[i].num_links = 840 + top_info->nodes[j].num_links; 841 + return; 842 + } 843 + } 844 + } 845 + } 846 + } 847 + 826 848 int amdgpu_xgmi_add_device(struct amdgpu_device *adev) 827 849 { 828 850 struct psp_xgmi_topology_info *top_info; ··· 919 897 goto exit_unlock; 920 898 } 921 899 922 - /* get latest topology info for each device from psp */ 923 - list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 924 - ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, 925 - &tmp_adev->psp.xgmi_context.top_info, false); 900 + if (amdgpu_sriov_vf(adev) && 901 + adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG) { 902 + /* only get topology for VF being init if it can support full duplex */ 903 + ret = psp_xgmi_get_topology_info(&adev->psp, count, 904 + &adev->psp.xgmi_context.top_info, false); 926 905 if (ret) { 927 - dev_err(tmp_adev->dev, 906 + dev_err(adev->dev, 928 907 "XGMI: Get topology failure on device %llx, hive %llx, ret %d", 929 - tmp_adev->gmc.xgmi.node_id, 930 - tmp_adev->gmc.xgmi.hive_id, ret); 931 - /* To do : continue with some node failed or disable the whole hive */ 908 + adev->gmc.xgmi.node_id, 909 + adev->gmc.xgmi.hive_id, ret); 910 + /* To do: continue with some node failed or disable the whole hive*/ 932 911 goto exit_unlock; 912 + } 913 + 914 + /* fill the topology info for peers instead of getting from PSP */ 915 + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 916 + amdgpu_xgmi_fill_topology_info(adev, tmp_adev); 917 + } 918 + } else { 919 + /* get latest topology info for each device from psp */ 920 + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 921 + ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, 922 + &tmp_adev->psp.xgmi_context.top_info, false); 923 + if (ret) { 924 + dev_err(tmp_adev->dev, 925 + "XGMI: Get topology failure on device %llx, hive %llx, ret %d", 926 + tmp_adev->gmc.xgmi.node_id, 927 + tmp_adev->gmc.xgmi.hive_id, ret); 928 + /* To do : continue with some node failed or disable the whole hive */ 929 + goto exit_unlock; 930 + } 933 931 } 934 932 } 935 933
+1
drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
··· 28 28 29 29 #include <acpi/video.h> 30 30 31 + #include <drm/drm_edid.h> 31 32 #include <drm/amdgpu_drm.h> 32 33 #include "amdgpu.h" 33 34 #include "amdgpu_connectors.h"
+1
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
··· 21 21 * 22 22 */ 23 23 24 + #include <drm/drm_edid.h> 24 25 #include <drm/drm_fourcc.h> 25 26 #include <drm/drm_modeset_helper.h> 26 27 #include <drm/drm_modeset_helper_vtables.h>
+1
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
··· 21 21 * 22 22 */ 23 23 24 + #include <drm/drm_edid.h> 24 25 #include <drm/drm_fourcc.h> 25 26 #include <drm/drm_modeset_helper.h> 26 27 #include <drm/drm_modeset_helper_vtables.h>
+1
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
··· 23 23 24 24 #include <linux/pci.h> 25 25 26 + #include <drm/drm_edid.h> 26 27 #include <drm/drm_fourcc.h> 27 28 #include <drm/drm_modeset_helper.h> 28 29 #include <drm/drm_modeset_helper_vtables.h>
+1
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
··· 21 21 * 22 22 */ 23 23 24 + #include <drm/drm_edid.h> 24 25 #include <drm/drm_fourcc.h> 25 26 #include <drm/drm_modeset_helper.h> 26 27 #include <drm/drm_modeset_helper_vtables.h>
+2 -1
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
··· 6593 6593 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); 6594 6594 #endif 6595 6595 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); 6596 - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); 6596 + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 6597 + prop->allow_tunneling); 6597 6598 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); 6598 6599 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); 6599 6600 mqd->cp_hqd_pq_control = tmp;
+2 -1
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
··· 3847 3847 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, 3848 3848 (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); 3849 3849 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); 3850 - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); 3850 + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 3851 + prop->allow_tunneling); 3851 3852 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); 3852 3853 tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); 3853 3854 mqd->cp_hqd_pq_control = tmp;
+1 -1
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 883 883 * GRBM interface. 884 884 */ 885 885 if ((vmhub == AMDGPU_GFXHUB(0)) && 886 - (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2))) 886 + (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2))) 887 887 RREG32_NO_KIQ(req); 888 888 889 889 for (j = 0; j < adev->usec_timeout; j++) {
+8 -7
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
··· 155 155 struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec; 156 156 int r; 157 157 158 - adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, 159 - (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); 160 - 161 - WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL, 162 - ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | 163 - VCN_JPEG_DB_CTRL__EN_MASK); 164 - 165 158 r = amdgpu_ring_test_helper(ring); 166 159 if (r) 167 160 return r; ··· 328 335 329 336 if (adev->pm.dpm_enabled) 330 337 amdgpu_dpm_enable_jpeg(adev, true); 338 + 339 + /* doorbell programming is done for every playback */ 340 + adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, 341 + (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0); 342 + 343 + WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL, 344 + ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT | 345 + VCN_JPEG_DB_CTRL__EN_MASK); 331 346 332 347 /* disable power gating */ 333 348 r = jpeg_v4_0_5_disable_static_power_gating(adev);
+2 -2
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
··· 813 813 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 814 814 int r; 815 815 816 + adev->sdma.num_instances = SDMA_MAX_INSTANCE; 817 + 816 818 r = sdma_v2_4_init_microcode(adev); 817 819 if (r) 818 820 return r; 819 - 820 - adev->sdma.num_instances = SDMA_MAX_INSTANCE; 821 821 822 822 sdma_v2_4_set_ring_funcs(adev); 823 823 sdma_v2_4_set_buffer_funcs(adev);
+28
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
··· 1643 1643 *flags |= AMD_CG_SUPPORT_SDMA_LS; 1644 1644 } 1645 1645 1646 + static void sdma_v5_2_ring_begin_use(struct amdgpu_ring *ring) 1647 + { 1648 + struct amdgpu_device *adev = ring->adev; 1649 + 1650 + /* SDMA 5.2.3 (RMB) FW doesn't seem to properly 1651 + * disallow GFXOFF in some cases leading to 1652 + * hangs in SDMA. Disallow GFXOFF while SDMA is active. 1653 + * We can probably just limit this to 5.2.3, 1654 + * but it shouldn't hurt for other parts since 1655 + * this GFXOFF will be disallowed anyway when SDMA is 1656 + * active, this just makes it explicit. 1657 + */ 1658 + amdgpu_gfx_off_ctrl(adev, false); 1659 + } 1660 + 1661 + static void sdma_v5_2_ring_end_use(struct amdgpu_ring *ring) 1662 + { 1663 + struct amdgpu_device *adev = ring->adev; 1664 + 1665 + /* SDMA 5.2.3 (RMB) FW doesn't seem to properly 1666 + * disallow GFXOFF in some cases leading to 1667 + * hangs in SDMA. Allow GFXOFF when SDMA is complete. 1668 + */ 1669 + amdgpu_gfx_off_ctrl(adev, true); 1670 + } 1671 + 1646 1672 const struct amd_ip_funcs sdma_v5_2_ip_funcs = { 1647 1673 .name = "sdma_v5_2", 1648 1674 .early_init = sdma_v5_2_early_init, ··· 1716 1690 .test_ib = sdma_v5_2_ring_test_ib, 1717 1691 .insert_nop = sdma_v5_2_ring_insert_nop, 1718 1692 .pad_ib = sdma_v5_2_ring_pad_ib, 1693 + .begin_use = sdma_v5_2_ring_begin_use, 1694 + .end_use = sdma_v5_2_ring_end_use, 1719 1695 .emit_wreg = sdma_v5_2_ring_emit_wreg, 1720 1696 .emit_reg_wait = sdma_v5_2_ring_emit_reg_wait, 1721 1697 .emit_reg_write_reg_wait = sdma_v5_2_ring_emit_reg_write_reg_wait,
+15
drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
··· 96 96 adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl; 97 97 98 98 amdgpu_vpe_psp_update_sram(adev); 99 + 100 + /* Config DPM */ 101 + amdgpu_vpe_configure_dpm(vpe); 102 + 99 103 return 0; 100 104 } 101 105 ··· 132 128 } 133 129 134 130 vpe_v6_1_halt(vpe, false); 131 + /* Config DPM */ 132 + amdgpu_vpe_configure_dpm(vpe); 135 133 136 134 return 0; 137 135 } ··· 269 263 vpe->regs.queue0_rb_wptr_lo = regVPEC_QUEUE0_RB_WPTR; 270 264 vpe->regs.queue0_rb_wptr_hi = regVPEC_QUEUE0_RB_WPTR_HI; 271 265 vpe->regs.queue0_preempt = regVPEC_QUEUE0_PREEMPT; 266 + 267 + vpe->regs.dpm_enable = regVPEC_PUB_DUMMY2; 268 + vpe->regs.dpm_pratio = regVPEC_QUEUE6_DUMMY4; 269 + vpe->regs.dpm_request_interval = regVPEC_QUEUE5_DUMMY3; 270 + vpe->regs.dpm_decision_threshold = regVPEC_QUEUE5_DUMMY4; 271 + vpe->regs.dpm_busy_clamp_threshold = regVPEC_QUEUE7_DUMMY2; 272 + vpe->regs.dpm_idle_clamp_threshold = regVPEC_QUEUE7_DUMMY3; 273 + vpe->regs.dpm_request_lv = regVPEC_QUEUE7_DUMMY1; 274 + vpe->regs.context_indicator = regVPEC_QUEUE6_DUMMY3; 272 275 273 276 return 0; 274 277 }
+6 -13
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
··· 1564 1564 { 1565 1565 struct kfd_ioctl_import_dmabuf_args *args = data; 1566 1566 struct kfd_process_device *pdd; 1567 - struct dma_buf *dmabuf; 1568 1567 int idr_handle; 1569 1568 uint64_t size; 1570 1569 void *mem; 1571 1570 int r; 1572 - 1573 - dmabuf = dma_buf_get(args->dmabuf_fd); 1574 - if (IS_ERR(dmabuf)) 1575 - return PTR_ERR(dmabuf); 1576 1571 1577 1572 mutex_lock(&p->mutex); 1578 1573 pdd = kfd_process_device_data_by_id(p, args->gpu_id); ··· 1582 1587 goto err_unlock; 1583 1588 } 1584 1589 1585 - r = amdgpu_amdkfd_gpuvm_import_dmabuf(pdd->dev->adev, dmabuf, 1586 - args->va_addr, pdd->drm_priv, 1587 - (struct kgd_mem **)&mem, &size, 1588 - NULL); 1590 + r = amdgpu_amdkfd_gpuvm_import_dmabuf_fd(pdd->dev->adev, args->dmabuf_fd, 1591 + args->va_addr, pdd->drm_priv, 1592 + (struct kgd_mem **)&mem, &size, 1593 + NULL); 1589 1594 if (r) 1590 1595 goto err_unlock; 1591 1596 ··· 1596 1601 } 1597 1602 1598 1603 mutex_unlock(&p->mutex); 1599 - dma_buf_put(dmabuf); 1600 1604 1601 1605 args->handle = MAKE_HANDLE(args->gpu_id, idr_handle); 1602 1606 ··· 1606 1612 pdd->drm_priv, NULL); 1607 1613 err_unlock: 1608 1614 mutex_unlock(&p->mutex); 1609 - dma_buf_put(dmabuf); 1610 1615 return r; 1611 1616 } 1612 1617 ··· 1848 1855 return num_of_bos; 1849 1856 } 1850 1857 1851 - static int criu_get_prime_handle(struct kgd_mem *mem, int flags, 1852 - u32 *shared_fd) 1858 + static int criu_get_prime_handle(struct kgd_mem *mem, 1859 + int flags, u32 *shared_fd) 1853 1860 { 1854 1861 struct dma_buf *dmabuf; 1855 1862 int ret;
+2
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
··· 87 87 return; 88 88 89 89 dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd); 90 + if (dev->kfd->shared_resources.enable_mes) 91 + amdgpu_mes_flush_shader_debugger(dev->adev, pdd->proc_ctx_gpu_addr); 90 92 pdd->already_dequeued = true; 91 93 } 92 94
+12 -6
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 1607 1607 if (test_bit(gpuidx, prange->bitmap_access)) 1608 1608 bitmap_set(ctx->bitmap, gpuidx, 1); 1609 1609 } 1610 + 1611 + /* 1612 + * If prange is already mapped or with always mapped flag, 1613 + * update mapping on GPUs with ACCESS attribute 1614 + */ 1615 + if (bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) { 1616 + if (prange->mapped_to_gpu || 1617 + prange->flags & KFD_IOCTL_SVM_FLAG_GPU_ALWAYS_MAPPED) 1618 + bitmap_copy(ctx->bitmap, prange->bitmap_access, MAX_GPU_INSTANCE); 1619 + } 1610 1620 } else { 1611 1621 bitmap_or(ctx->bitmap, prange->bitmap_access, 1612 1622 prange->bitmap_aip, MAX_GPU_INSTANCE); 1613 1623 } 1614 1624 1615 1625 if (bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) { 1616 - bitmap_copy(ctx->bitmap, prange->bitmap_access, MAX_GPU_INSTANCE); 1617 - if (!prange->mapped_to_gpu || 1618 - bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) { 1619 - r = 0; 1620 - goto free_ctx; 1621 - } 1626 + r = 0; 1627 + goto free_ctx; 1622 1628 } 1623 1629 1624 1630 if (prange->actual_loc && !prange->ttm_res) {
+42 -4
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 1712 1712 init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0]; 1713 1713 1714 1714 /* Enable DWB for tested platforms only */ 1715 - if (adev->ip_versions[DCE_HWIP][0] >= IP_VERSION(3, 0, 0)) 1715 + if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) 1716 1716 init_data.num_virtual_links = 1; 1717 1717 1718 1718 INIT_LIST_HEAD(&adev->dm.da_list); ··· 2687 2687 hpd_rx_irq_work_suspend(dm); 2688 2688 2689 2689 dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); 2690 + dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); 2690 2691 2691 2692 return 0; 2692 2693 } ··· 2883 2882 if (r) 2884 2883 DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); 2885 2884 2885 + dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); 2886 2886 dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); 2887 2887 2888 2888 dc_resume(dm->dc); ··· 2934 2932 } 2935 2933 2936 2934 /* power on hardware */ 2935 + dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); 2937 2936 dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); 2938 2937 2939 2938 /* program HPD filter */ ··· 4070 4067 return r; 4071 4068 } 4072 4069 4070 + #ifdef AMD_PRIVATE_COLOR 4071 + if (amdgpu_dm_create_color_properties(adev)) 4072 + return -ENOMEM; 4073 + #endif 4074 + 4073 4075 r = amdgpu_dm_audio_init(adev); 4074 4076 if (r) { 4075 4077 dc_release_state(state->context); ··· 5172 5164 * Always set input transfer function, since plane state is refreshed 5173 5165 * every time. 5174 5166 */ 5175 - ret = amdgpu_dm_update_plane_color_mgmt(dm_crtc_state, dc_plane_state); 5167 + ret = amdgpu_dm_update_plane_color_mgmt(dm_crtc_state, 5168 + plane_state, 5169 + dc_plane_state); 5176 5170 if (ret) 5177 5171 return ret; 5178 5172 ··· 8271 8261 bundle->surface_updates[planes_count].gamma = dc_plane->gamma_correction; 8272 8262 bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func; 8273 8263 bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix; 8264 + bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult; 8265 + bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func; 8266 + bundle->surface_updates[planes_count].lut3d_func = dc_plane->lut3d_func; 8267 + bundle->surface_updates[planes_count].blend_tf = dc_plane->blend_tf; 8274 8268 } 8275 8269 8276 8270 amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state, ··· 8486 8472 &acrtc_state->stream->csc_color_matrix; 8487 8473 bundle->stream_update.out_transfer_func = 8488 8474 acrtc_state->stream->out_transfer_func; 8475 + bundle->stream_update.lut3d_func = 8476 + (struct dc_3dlut *) acrtc_state->stream->lut3d_func; 8477 + bundle->stream_update.func_shaper = 8478 + (struct dc_transfer_func *) acrtc_state->stream->func_shaper; 8489 8479 } 8490 8480 8491 8481 acrtc_state->stream->abm_level = acrtc_state->abm_level; ··· 8892 8874 acrtc = to_amdgpu_crtc(wb_conn->encoder.crtc); 8893 8875 if (!acrtc) { 8894 8876 DRM_ERROR("no amdgpu_crtc found\n"); 8877 + kfree(wb_info); 8895 8878 return; 8896 8879 } 8897 8880 8898 8881 afb = to_amdgpu_framebuffer(new_con_state->writeback_job->fb); 8899 8882 if (!afb) { 8900 8883 DRM_ERROR("No amdgpu_framebuffer found\n"); 8884 + kfree(wb_info); 8901 8885 return; 8902 8886 } 8903 8887 ··· 8954 8934 } 8955 8935 8956 8936 wb_info->mcif_buf_params.p_vmid = 1; 8957 - if (adev->ip_versions[DCE_HWIP][0] >= IP_VERSION(3, 0, 0)) { 8937 + if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) { 8958 8938 wb_info->mcif_warmup_params.start_address.quad_part = afb->address; 8959 8939 wb_info->mcif_warmup_params.region_size = 8960 8940 wb_info->mcif_buf_params.luma_pitch * wb_info->dwb_params.dest_height; ··· 9873 9853 * when a modeset is needed, to ensure it gets reprogrammed. 9874 9854 */ 9875 9855 if (dm_new_crtc_state->base.color_mgmt_changed || 9856 + dm_old_crtc_state->regamma_tf != dm_new_crtc_state->regamma_tf || 9876 9857 drm_atomic_crtc_needs_modeset(new_crtc_state)) { 9877 9858 ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state); 9878 9859 if (ret) ··· 9907 9886 * TODO: Remove this hack for all asics once it proves that the 9908 9887 * fast updates works fine on DCN3.2+. 9909 9888 */ 9910 - if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && state->allow_modeset) 9889 + if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 2, 0) && 9890 + state->allow_modeset) 9911 9891 return true; 9912 9892 9913 9893 /* Exit early if we know that we're adding or removing the plane. */ ··· 9942 9920 */ 9943 9921 for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) { 9944 9922 struct amdgpu_framebuffer *old_afb, *new_afb; 9923 + struct dm_plane_state *dm_new_other_state, *dm_old_other_state; 9924 + 9925 + dm_new_other_state = to_dm_plane_state(new_other_state); 9926 + dm_old_other_state = to_dm_plane_state(old_other_state); 9945 9927 9946 9928 if (other->type == DRM_PLANE_TYPE_CURSOR) 9947 9929 continue; ··· 9980 9954 /* Colorspace changes. */ 9981 9955 if (old_other_state->color_range != new_other_state->color_range || 9982 9956 old_other_state->color_encoding != new_other_state->color_encoding) 9957 + return true; 9958 + 9959 + /* HDR/Transfer Function changes. */ 9960 + if (dm_old_other_state->degamma_tf != dm_new_other_state->degamma_tf || 9961 + dm_old_other_state->degamma_lut != dm_new_other_state->degamma_lut || 9962 + dm_old_other_state->hdr_mult != dm_new_other_state->hdr_mult || 9963 + dm_old_other_state->ctm != dm_new_other_state->ctm || 9964 + dm_old_other_state->shaper_lut != dm_new_other_state->shaper_lut || 9965 + dm_old_other_state->shaper_tf != dm_new_other_state->shaper_tf || 9966 + dm_old_other_state->lut3d != dm_new_other_state->lut3d || 9967 + dm_old_other_state->blend_lut != dm_new_other_state->blend_lut || 9968 + dm_old_other_state->blend_tf != dm_new_other_state->blend_tf) 9983 9969 return true; 9984 9970 9985 9971 /* Framebuffer checks fall at the end. */
+108
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 55 55 #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A 56 56 #define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40 57 57 #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3 58 + 59 + #define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL) 60 + 58 61 /* 59 62 #include "include/amdgpu_dal_power_if.h" 60 63 #include "amdgpu_dm_irq.h" ··· 727 724 728 725 extern const struct amdgpu_ip_block_version dm_ip_block; 729 726 727 + /* enum amdgpu_transfer_function: pre-defined transfer function supported by AMD. 728 + * 729 + * It includes standardized transfer functions and pure power functions. The 730 + * transfer function coefficients are available at modules/color/color_gamma.c 731 + */ 732 + enum amdgpu_transfer_function { 733 + AMDGPU_TRANSFER_FUNCTION_DEFAULT, 734 + AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF, 735 + AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF, 736 + AMDGPU_TRANSFER_FUNCTION_PQ_EOTF, 737 + AMDGPU_TRANSFER_FUNCTION_IDENTITY, 738 + AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF, 739 + AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF, 740 + AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF, 741 + AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF, 742 + AMDGPU_TRANSFER_FUNCTION_BT709_OETF, 743 + AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF, 744 + AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF, 745 + AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF, 746 + AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF, 747 + AMDGPU_TRANSFER_FUNCTION_COUNT 748 + }; 749 + 730 750 struct dm_plane_state { 731 751 struct drm_plane_state base; 732 752 struct dc_plane_state *dc_state; 753 + 754 + /* Plane color mgmt */ 755 + /** 756 + * @degamma_lut: 757 + * 758 + * 1D LUT for mapping framebuffer/plane pixel data before sampling or 759 + * blending operations. It's usually applied to linearize input space. 760 + * The blob (if not NULL) is an array of &struct drm_color_lut. 761 + */ 762 + struct drm_property_blob *degamma_lut; 763 + /** 764 + * @degamma_tf: 765 + * 766 + * Predefined transfer function to tell DC driver the input space to 767 + * linearize. 768 + */ 769 + enum amdgpu_transfer_function degamma_tf; 770 + /** 771 + * @hdr_mult: 772 + * 773 + * Multiplier to 'gain' the plane. When PQ is decoded using the fixed 774 + * func transfer function to the internal FP16 fb, 1.0 -> 80 nits (on 775 + * AMD at least). When sRGB is decoded, 1.0 -> 1.0, obviously. 776 + * Therefore, 1.0 multiplier = 80 nits for SDR content. So if you 777 + * want, 203 nits for SDR content, pass in (203.0 / 80.0). Format is 778 + * S31.32 sign-magnitude. 779 + * 780 + * HDR multiplier can wide range beyond [0.0, 1.0]. This means that PQ 781 + * TF is needed for any subsequent linear-to-non-linear transforms. 782 + */ 783 + __u64 hdr_mult; 784 + /** 785 + * @ctm: 786 + * 787 + * Color transformation matrix. The blob (if not NULL) is a &struct 788 + * drm_color_ctm_3x4. 789 + */ 790 + struct drm_property_blob *ctm; 791 + /** 792 + * @shaper_lut: shaper lookup table blob. The blob (if not NULL) is an 793 + * array of &struct drm_color_lut. 794 + */ 795 + struct drm_property_blob *shaper_lut; 796 + /** 797 + * @shaper_tf: 798 + * 799 + * Predefined transfer function to delinearize color space. 800 + */ 801 + enum amdgpu_transfer_function shaper_tf; 802 + /** 803 + * @lut3d: 3D lookup table blob. The blob (if not NULL) is an array of 804 + * &struct drm_color_lut. 805 + */ 806 + struct drm_property_blob *lut3d; 807 + /** 808 + * @blend_lut: blend lut lookup table blob. The blob (if not NULL) is an 809 + * array of &struct drm_color_lut. 810 + */ 811 + struct drm_property_blob *blend_lut; 812 + /** 813 + * @blend_tf: 814 + * 815 + * Pre-defined transfer function for converting plane pixel data before 816 + * applying blend LUT. 817 + */ 818 + enum amdgpu_transfer_function blend_tf; 733 819 }; 734 820 735 821 struct dm_crtc_state { ··· 843 751 struct dc_info_packet vrr_infopacket; 844 752 845 753 int abm_level; 754 + 755 + /** 756 + * @regamma_tf: 757 + * 758 + * Pre-defined transfer function for converting internal FB -> wire 759 + * encoding. 760 + */ 761 + enum amdgpu_transfer_function regamma_tf; 846 762 }; 847 763 848 764 #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) ··· 912 812 913 813 void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); 914 814 815 + /* 3D LUT max size is 17x17x17 (4913 entries) */ 816 + #define MAX_COLOR_3DLUT_SIZE 17 817 + #define MAX_COLOR_3DLUT_BITDEPTH 12 818 + int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev, 819 + struct drm_plane_state *plane_state); 820 + /* 1D LUT size */ 915 821 #define MAX_COLOR_LUT_ENTRIES 4096 916 822 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */ 917 823 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 918 824 919 825 void amdgpu_dm_init_color_mod(void); 826 + int amdgpu_dm_create_color_properties(struct amdgpu_device *adev); 920 827 int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); 921 828 int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); 922 829 int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, 830 + struct drm_plane_state *plane_state, 923 831 struct dc_plane_state *dc_plane_state); 924 832 925 833 void amdgpu_dm_update_connector_after_detect(
+752 -66
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
··· 72 72 */ 73 73 74 74 #define MAX_DRM_LUT_VALUE 0xFFFF 75 + #define SDR_WHITE_LEVEL_INIT_VALUE 80 75 76 76 77 /** 77 78 * amdgpu_dm_init_color_mod - Initialize the color module. ··· 84 83 { 85 84 setup_x_points_distribution(); 86 85 } 86 + 87 + #ifdef AMD_PRIVATE_COLOR 88 + /* Pre-defined Transfer Functions (TF) 89 + * 90 + * AMD driver supports pre-defined mathematical functions for transferring 91 + * between encoded values and optical/linear space. Depending on HW color caps, 92 + * ROMs and curves built by the AMD color module support these transforms. 93 + * 94 + * The driver-specific color implementation exposes properties for pre-blending 95 + * degamma TF, shaper TF (before 3D LUT), and blend(dpp.ogam) TF and 96 + * post-blending regamma (mpc.ogam) TF. However, only pre-blending degamma 97 + * supports ROM curves. AMD color module uses pre-defined coefficients to build 98 + * curves for the other blocks. What can be done by each color block is 99 + * described by struct dpp_color_capsand struct mpc_color_caps. 100 + * 101 + * AMD driver-specific color API exposes the following pre-defined transfer 102 + * functions: 103 + * 104 + * - Identity: linear/identity relationship between pixel value and 105 + * luminance value; 106 + * - Gamma 2.2, Gamma 2.4, Gamma 2.6: pure power functions; 107 + * - sRGB: 2.4: The piece-wise transfer function from IEC 61966-2-1:1999; 108 + * - BT.709: has a linear segment in the bottom part and then a power function 109 + * with a 0.45 (~1/2.22) gamma for the rest of the range; standardized by 110 + * ITU-R BT.709-6; 111 + * - PQ (Perceptual Quantizer): used for HDR display, allows luminance range 112 + * capability of 0 to 10,000 nits; standardized by SMPTE ST 2084. 113 + * 114 + * The AMD color model is designed with an assumption that SDR (sRGB, BT.709, 115 + * Gamma 2.2, etc.) peak white maps (normalized to 1.0 FP) to 80 nits in the PQ 116 + * system. This has the implication that PQ EOTF (non-linear to linear) maps to 117 + * [0.0..125.0] where 125.0 = 10,000 nits / 80 nits. 118 + * 119 + * Non-linear and linear forms are described in the table below: 120 + * 121 + * ┌───────────┬─────────────────────┬──────────────────────┐ 122 + * │ │ Non-linear │ Linear │ 123 + * ├───────────┼─────────────────────┼──────────────────────┤ 124 + * │ sRGB │ UNORM or [0.0, 1.0] │ [0.0, 1.0] │ 125 + * ├───────────┼─────────────────────┼──────────────────────┤ 126 + * │ BT709 │ UNORM or [0.0, 1.0] │ [0.0, 1.0] │ 127 + * ├───────────┼─────────────────────┼──────────────────────┤ 128 + * │ Gamma 2.x │ UNORM or [0.0, 1.0] │ [0.0, 1.0] │ 129 + * ├───────────┼─────────────────────┼──────────────────────┤ 130 + * │ PQ │ UNORM or FP16 CCCS* │ [0.0, 125.0] │ 131 + * ├───────────┼─────────────────────┼──────────────────────┤ 132 + * │ Identity │ UNORM or FP16 CCCS* │ [0.0, 1.0] or CCCS** │ 133 + * └───────────┴─────────────────────┴──────────────────────┘ 134 + * * CCCS: Windows canonical composition color space 135 + * ** Respectively 136 + * 137 + * In the driver-specific API, color block names attached to TF properties 138 + * suggest the intention regarding non-linear encoding pixel's luminance 139 + * values. As some newer encodings don't use gamma curve, we make encoding and 140 + * decoding explicit by defining an enum list of transfer functions supported 141 + * in terms of EOTF and inverse EOTF, where: 142 + * 143 + * - EOTF (electro-optical transfer function): is the transfer function to go 144 + * from the encoded value to an optical (linear) value. De-gamma functions 145 + * traditionally do this. 146 + * - Inverse EOTF (simply the inverse of the EOTF): is usually intended to go 147 + * from an optical/linear space (which might have been used for blending) 148 + * back to the encoded values. Gamma functions traditionally do this. 149 + */ 150 + static const char * const 151 + amdgpu_transfer_function_names[] = { 152 + [AMDGPU_TRANSFER_FUNCTION_DEFAULT] = "Default", 153 + [AMDGPU_TRANSFER_FUNCTION_IDENTITY] = "Identity", 154 + [AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF] = "sRGB EOTF", 155 + [AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF] = "BT.709 inv_OETF", 156 + [AMDGPU_TRANSFER_FUNCTION_PQ_EOTF] = "PQ EOTF", 157 + [AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF] = "Gamma 2.2 EOTF", 158 + [AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF] = "Gamma 2.4 EOTF", 159 + [AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF] = "Gamma 2.6 EOTF", 160 + [AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF] = "sRGB inv_EOTF", 161 + [AMDGPU_TRANSFER_FUNCTION_BT709_OETF] = "BT.709 OETF", 162 + [AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF] = "PQ inv_EOTF", 163 + [AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF] = "Gamma 2.2 inv_EOTF", 164 + [AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF] = "Gamma 2.4 inv_EOTF", 165 + [AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF] = "Gamma 2.6 inv_EOTF", 166 + }; 167 + 168 + static const u32 amdgpu_eotf = 169 + BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF) | 170 + BIT(AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF) | 171 + BIT(AMDGPU_TRANSFER_FUNCTION_PQ_EOTF) | 172 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF) | 173 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF) | 174 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF); 175 + 176 + static const u32 amdgpu_inv_eotf = 177 + BIT(AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF) | 178 + BIT(AMDGPU_TRANSFER_FUNCTION_BT709_OETF) | 179 + BIT(AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF) | 180 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF) | 181 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF) | 182 + BIT(AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF); 183 + 184 + static struct drm_property * 185 + amdgpu_create_tf_property(struct drm_device *dev, 186 + const char *name, 187 + u32 supported_tf) 188 + { 189 + u32 transfer_functions = supported_tf | 190 + BIT(AMDGPU_TRANSFER_FUNCTION_DEFAULT) | 191 + BIT(AMDGPU_TRANSFER_FUNCTION_IDENTITY); 192 + struct drm_prop_enum_list enum_list[AMDGPU_TRANSFER_FUNCTION_COUNT]; 193 + int i, len; 194 + 195 + len = 0; 196 + for (i = 0; i < AMDGPU_TRANSFER_FUNCTION_COUNT; i++) { 197 + if ((transfer_functions & BIT(i)) == 0) 198 + continue; 199 + 200 + enum_list[len].type = i; 201 + enum_list[len].name = amdgpu_transfer_function_names[i]; 202 + len++; 203 + } 204 + 205 + return drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, 206 + name, enum_list, len); 207 + } 208 + 209 + int 210 + amdgpu_dm_create_color_properties(struct amdgpu_device *adev) 211 + { 212 + struct drm_property *prop; 213 + 214 + prop = drm_property_create(adev_to_drm(adev), 215 + DRM_MODE_PROP_BLOB, 216 + "AMD_PLANE_DEGAMMA_LUT", 0); 217 + if (!prop) 218 + return -ENOMEM; 219 + adev->mode_info.plane_degamma_lut_property = prop; 220 + 221 + prop = drm_property_create_range(adev_to_drm(adev), 222 + DRM_MODE_PROP_IMMUTABLE, 223 + "AMD_PLANE_DEGAMMA_LUT_SIZE", 224 + 0, UINT_MAX); 225 + if (!prop) 226 + return -ENOMEM; 227 + adev->mode_info.plane_degamma_lut_size_property = prop; 228 + 229 + prop = amdgpu_create_tf_property(adev_to_drm(adev), 230 + "AMD_PLANE_DEGAMMA_TF", 231 + amdgpu_eotf); 232 + if (!prop) 233 + return -ENOMEM; 234 + adev->mode_info.plane_degamma_tf_property = prop; 235 + 236 + prop = drm_property_create_range(adev_to_drm(adev), 237 + 0, "AMD_PLANE_HDR_MULT", 0, U64_MAX); 238 + if (!prop) 239 + return -ENOMEM; 240 + adev->mode_info.plane_hdr_mult_property = prop; 241 + 242 + prop = drm_property_create(adev_to_drm(adev), 243 + DRM_MODE_PROP_BLOB, 244 + "AMD_PLANE_CTM", 0); 245 + if (!prop) 246 + return -ENOMEM; 247 + adev->mode_info.plane_ctm_property = prop; 248 + 249 + prop = drm_property_create(adev_to_drm(adev), 250 + DRM_MODE_PROP_BLOB, 251 + "AMD_PLANE_SHAPER_LUT", 0); 252 + if (!prop) 253 + return -ENOMEM; 254 + adev->mode_info.plane_shaper_lut_property = prop; 255 + 256 + prop = drm_property_create_range(adev_to_drm(adev), 257 + DRM_MODE_PROP_IMMUTABLE, 258 + "AMD_PLANE_SHAPER_LUT_SIZE", 0, UINT_MAX); 259 + if (!prop) 260 + return -ENOMEM; 261 + adev->mode_info.plane_shaper_lut_size_property = prop; 262 + 263 + prop = amdgpu_create_tf_property(adev_to_drm(adev), 264 + "AMD_PLANE_SHAPER_TF", 265 + amdgpu_inv_eotf); 266 + if (!prop) 267 + return -ENOMEM; 268 + adev->mode_info.plane_shaper_tf_property = prop; 269 + 270 + prop = drm_property_create(adev_to_drm(adev), 271 + DRM_MODE_PROP_BLOB, 272 + "AMD_PLANE_LUT3D", 0); 273 + if (!prop) 274 + return -ENOMEM; 275 + adev->mode_info.plane_lut3d_property = prop; 276 + 277 + prop = drm_property_create_range(adev_to_drm(adev), 278 + DRM_MODE_PROP_IMMUTABLE, 279 + "AMD_PLANE_LUT3D_SIZE", 0, UINT_MAX); 280 + if (!prop) 281 + return -ENOMEM; 282 + adev->mode_info.plane_lut3d_size_property = prop; 283 + 284 + prop = drm_property_create(adev_to_drm(adev), 285 + DRM_MODE_PROP_BLOB, 286 + "AMD_PLANE_BLEND_LUT", 0); 287 + if (!prop) 288 + return -ENOMEM; 289 + adev->mode_info.plane_blend_lut_property = prop; 290 + 291 + prop = drm_property_create_range(adev_to_drm(adev), 292 + DRM_MODE_PROP_IMMUTABLE, 293 + "AMD_PLANE_BLEND_LUT_SIZE", 0, UINT_MAX); 294 + if (!prop) 295 + return -ENOMEM; 296 + adev->mode_info.plane_blend_lut_size_property = prop; 297 + 298 + prop = amdgpu_create_tf_property(adev_to_drm(adev), 299 + "AMD_PLANE_BLEND_TF", 300 + amdgpu_eotf); 301 + if (!prop) 302 + return -ENOMEM; 303 + adev->mode_info.plane_blend_tf_property = prop; 304 + 305 + prop = amdgpu_create_tf_property(adev_to_drm(adev), 306 + "AMD_CRTC_REGAMMA_TF", 307 + amdgpu_inv_eotf); 308 + if (!prop) 309 + return -ENOMEM; 310 + adev->mode_info.regamma_tf_property = prop; 311 + 312 + return 0; 313 + } 314 + #endif 87 315 88 316 /** 89 317 * __extract_blob_lut - Extracts the DRM lut and lut size from a blob. ··· 412 182 static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, 413 183 struct fixed31_32 *matrix) 414 184 { 415 - int64_t val; 416 185 int i; 417 186 418 187 /* ··· 430 201 } 431 202 432 203 /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */ 433 - val = ctm->matrix[i - (i / 4)]; 434 - /* If negative, convert to 2's complement. */ 435 - if (val & (1ULL << 63)) 436 - val = -(val & ~(1ULL << 63)); 204 + matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i - (i / 4)]); 205 + } 206 + } 437 207 438 - matrix[i].value = val; 208 + /** 209 + * __drm_ctm_3x4_to_dc_matrix - converts a DRM CTM 3x4 to a DC CSC float matrix 210 + * @ctm: DRM color transformation matrix with 3x4 dimensions 211 + * @matrix: DC CSC float matrix 212 + * 213 + * The matrix needs to be a 3x4 (12 entry) matrix. 214 + */ 215 + static void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm, 216 + struct fixed31_32 *matrix) 217 + { 218 + int i; 219 + 220 + /* The format provided is S31.32, using signed-magnitude representation. 221 + * Our fixed31_32 is also S31.32, but is using 2's complement. We have 222 + * to convert from signed-magnitude to 2's complement. 223 + */ 224 + for (i = 0; i < 12; i++) { 225 + /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */ 226 + matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i]); 439 227 } 440 228 } 441 229 ··· 514 268 struct calculate_buffer cal_buffer = {0}; 515 269 bool res; 516 270 517 - ASSERT(lut && lut_size == MAX_COLOR_LUT_ENTRIES); 518 - 519 271 cal_buffer.buffer_index = -1; 520 272 521 - gamma = dc_create_gamma(); 522 - if (!gamma) 523 - return -ENOMEM; 273 + if (lut_size) { 274 + ASSERT(lut && lut_size == MAX_COLOR_LUT_ENTRIES); 524 275 525 - gamma->num_entries = lut_size; 526 - __drm_lut_to_dc_gamma(lut, gamma, false); 276 + gamma = dc_create_gamma(); 277 + if (!gamma) 278 + return -ENOMEM; 279 + 280 + gamma->num_entries = lut_size; 281 + __drm_lut_to_dc_gamma(lut, gamma, false); 282 + } 527 283 528 284 if (func->tf == TRANSFER_FUNCTION_LINEAR) { 529 285 /* ··· 533 285 * on top of a linear input. But degamma params can be used 534 286 * instead to simulate this. 535 287 */ 536 - gamma->type = GAMMA_CUSTOM; 288 + if (gamma) 289 + gamma->type = GAMMA_CUSTOM; 537 290 res = mod_color_calculate_degamma_params(NULL, func, 538 - gamma, true); 291 + gamma, gamma != NULL); 539 292 } else { 540 293 /* 541 294 * Assume sRGB. The actual mapping will depend on whether the 542 295 * input was legacy or not. 543 296 */ 544 - gamma->type = GAMMA_CS_TFM_1D; 545 - res = mod_color_calculate_regamma_params(func, gamma, false, 297 + if (gamma) 298 + gamma->type = GAMMA_CS_TFM_1D; 299 + res = mod_color_calculate_regamma_params(func, gamma, gamma != NULL, 546 300 has_rom, NULL, &cal_buffer); 547 301 } 548 302 549 - dc_gamma_release(&gamma); 303 + if (gamma) 304 + dc_gamma_release(&gamma); 550 305 551 306 return res ? 0 : -ENOMEM; 307 + } 308 + 309 + static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream, 310 + const struct drm_color_lut *regamma_lut, 311 + uint32_t regamma_size, bool has_rom, 312 + enum dc_transfer_func_predefined tf) 313 + { 314 + struct dc_transfer_func *out_tf = stream->out_transfer_func; 315 + int ret = 0; 316 + 317 + if (regamma_size || tf != TRANSFER_FUNCTION_LINEAR) { 318 + /* 319 + * CRTC RGM goes into RGM LUT. 320 + * 321 + * Note: there is no implicit sRGB regamma here. We are using 322 + * degamma calculation from color module to calculate the curve 323 + * from a linear base if gamma TF is not set. However, if gamma 324 + * TF (!= Linear) and LUT are set at the same time, we will use 325 + * regamma calculation, and the color module will combine the 326 + * pre-defined TF and the custom LUT values into the LUT that's 327 + * actually programmed. 328 + */ 329 + out_tf->type = TF_TYPE_DISTRIBUTED_POINTS; 330 + out_tf->tf = tf; 331 + out_tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE; 332 + 333 + ret = __set_output_tf(out_tf, regamma_lut, regamma_size, has_rom); 334 + } else { 335 + /* 336 + * No CRTC RGM means we can just put the block into bypass 337 + * since we don't have any plane level adjustments using it. 338 + */ 339 + out_tf->type = TF_TYPE_BYPASS; 340 + out_tf->tf = TRANSFER_FUNCTION_LINEAR; 341 + } 342 + 343 + return ret; 552 344 } 553 345 554 346 /** 555 347 * __set_input_tf - calculates the input transfer function based on expected 556 348 * input space. 349 + * @caps: dc color capabilities 557 350 * @func: transfer function 558 351 * @lut: lookup table that defines the color space 559 352 * @lut_size: size of respective lut. ··· 602 313 * Returns: 603 314 * 0 in case of success. -ENOMEM if fails. 604 315 */ 605 - static int __set_input_tf(struct dc_transfer_func *func, 316 + static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func, 606 317 const struct drm_color_lut *lut, uint32_t lut_size) 607 318 { 608 319 struct dc_gamma *gamma = NULL; 609 320 bool res; 610 321 611 - gamma = dc_create_gamma(); 612 - if (!gamma) 613 - return -ENOMEM; 322 + if (lut_size) { 323 + gamma = dc_create_gamma(); 324 + if (!gamma) 325 + return -ENOMEM; 614 326 615 - gamma->type = GAMMA_CUSTOM; 616 - gamma->num_entries = lut_size; 327 + gamma->type = GAMMA_CUSTOM; 328 + gamma->num_entries = lut_size; 617 329 618 - __drm_lut_to_dc_gamma(lut, gamma, false); 330 + __drm_lut_to_dc_gamma(lut, gamma, false); 331 + } 619 332 620 - res = mod_color_calculate_degamma_params(NULL, func, gamma, true); 621 - dc_gamma_release(&gamma); 333 + res = mod_color_calculate_degamma_params(caps, func, gamma, gamma != NULL); 334 + 335 + if (gamma) 336 + dc_gamma_release(&gamma); 622 337 623 338 return res ? 0 : -ENOMEM; 339 + } 340 + 341 + static enum dc_transfer_func_predefined 342 + amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf) 343 + { 344 + switch (tf) 345 + { 346 + default: 347 + case AMDGPU_TRANSFER_FUNCTION_DEFAULT: 348 + case AMDGPU_TRANSFER_FUNCTION_IDENTITY: 349 + return TRANSFER_FUNCTION_LINEAR; 350 + case AMDGPU_TRANSFER_FUNCTION_SRGB_EOTF: 351 + case AMDGPU_TRANSFER_FUNCTION_SRGB_INV_EOTF: 352 + return TRANSFER_FUNCTION_SRGB; 353 + case AMDGPU_TRANSFER_FUNCTION_BT709_OETF: 354 + case AMDGPU_TRANSFER_FUNCTION_BT709_INV_OETF: 355 + return TRANSFER_FUNCTION_BT709; 356 + case AMDGPU_TRANSFER_FUNCTION_PQ_EOTF: 357 + case AMDGPU_TRANSFER_FUNCTION_PQ_INV_EOTF: 358 + return TRANSFER_FUNCTION_PQ; 359 + case AMDGPU_TRANSFER_FUNCTION_GAMMA22_EOTF: 360 + case AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF: 361 + return TRANSFER_FUNCTION_GAMMA22; 362 + case AMDGPU_TRANSFER_FUNCTION_GAMMA24_EOTF: 363 + case AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF: 364 + return TRANSFER_FUNCTION_GAMMA24; 365 + case AMDGPU_TRANSFER_FUNCTION_GAMMA26_EOTF: 366 + case AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF: 367 + return TRANSFER_FUNCTION_GAMMA26; 368 + } 369 + } 370 + 371 + static void __to_dc_lut3d_color(struct dc_rgb *rgb, 372 + const struct drm_color_lut lut, 373 + int bit_precision) 374 + { 375 + rgb->red = drm_color_lut_extract(lut.red, bit_precision); 376 + rgb->green = drm_color_lut_extract(lut.green, bit_precision); 377 + rgb->blue = drm_color_lut_extract(lut.blue, bit_precision); 378 + } 379 + 380 + static void __drm_3dlut_to_dc_3dlut(const struct drm_color_lut *lut, 381 + uint32_t lut3d_size, 382 + struct tetrahedral_params *params, 383 + bool use_tetrahedral_9, 384 + int bit_depth) 385 + { 386 + struct dc_rgb *lut0; 387 + struct dc_rgb *lut1; 388 + struct dc_rgb *lut2; 389 + struct dc_rgb *lut3; 390 + int lut_i, i; 391 + 392 + 393 + if (use_tetrahedral_9) { 394 + lut0 = params->tetrahedral_9.lut0; 395 + lut1 = params->tetrahedral_9.lut1; 396 + lut2 = params->tetrahedral_9.lut2; 397 + lut3 = params->tetrahedral_9.lut3; 398 + } else { 399 + lut0 = params->tetrahedral_17.lut0; 400 + lut1 = params->tetrahedral_17.lut1; 401 + lut2 = params->tetrahedral_17.lut2; 402 + lut3 = params->tetrahedral_17.lut3; 403 + } 404 + 405 + for (lut_i = 0, i = 0; i < lut3d_size - 4; lut_i++, i += 4) { 406 + /* 407 + * We should consider the 3D LUT RGB values are distributed 408 + * along four arrays lut0-3 where the first sizes 1229 and the 409 + * other 1228. The bit depth supported for 3dlut channel is 410 + * 12-bit, but DC also supports 10-bit. 411 + * 412 + * TODO: improve color pipeline API to enable the userspace set 413 + * bit depth and 3D LUT size/stride, as specified by VA-API. 414 + */ 415 + __to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth); 416 + __to_dc_lut3d_color(&lut1[lut_i], lut[i + 1], bit_depth); 417 + __to_dc_lut3d_color(&lut2[lut_i], lut[i + 2], bit_depth); 418 + __to_dc_lut3d_color(&lut3[lut_i], lut[i + 3], bit_depth); 419 + } 420 + /* lut0 has 1229 points (lut_size/4 + 1) */ 421 + __to_dc_lut3d_color(&lut0[lut_i], lut[i], bit_depth); 422 + } 423 + 424 + /* amdgpu_dm_atomic_lut3d - set DRM 3D LUT to DC stream 425 + * @drm_lut3d: user 3D LUT 426 + * @drm_lut3d_size: size of 3D LUT 427 + * @lut3d: DC 3D LUT 428 + * 429 + * Map user 3D LUT data to DC 3D LUT and all necessary bits to program it 430 + * on DCN accordingly. 431 + */ 432 + static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut3d, 433 + uint32_t drm_lut3d_size, 434 + struct dc_3dlut *lut) 435 + { 436 + if (!drm_lut3d_size) { 437 + lut->state.bits.initialized = 0; 438 + } else { 439 + /* Stride and bit depth are not programmable by API yet. 440 + * Therefore, only supports 17x17x17 3D LUT (12-bit). 441 + */ 442 + lut->lut_3d.use_tetrahedral_9 = false; 443 + lut->lut_3d.use_12bits = true; 444 + lut->state.bits.initialized = 1; 445 + __drm_3dlut_to_dc_3dlut(drm_lut3d, drm_lut3d_size, &lut->lut_3d, 446 + lut->lut_3d.use_tetrahedral_9, 447 + MAX_COLOR_3DLUT_BITDEPTH); 448 + } 449 + } 450 + 451 + static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut, 452 + bool has_rom, 453 + enum dc_transfer_func_predefined tf, 454 + uint32_t shaper_size, 455 + struct dc_transfer_func *func_shaper) 456 + { 457 + int ret = 0; 458 + 459 + if (shaper_size || tf != TRANSFER_FUNCTION_LINEAR) { 460 + /* 461 + * If user shaper LUT is set, we assume a linear color space 462 + * (linearized by degamma 1D LUT or not). 463 + */ 464 + func_shaper->type = TF_TYPE_DISTRIBUTED_POINTS; 465 + func_shaper->tf = tf; 466 + func_shaper->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE; 467 + 468 + ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, has_rom); 469 + } else { 470 + func_shaper->type = TF_TYPE_BYPASS; 471 + func_shaper->tf = TRANSFER_FUNCTION_LINEAR; 472 + } 473 + 474 + return ret; 475 + } 476 + 477 + static int amdgpu_dm_atomic_blend_lut(const struct drm_color_lut *blend_lut, 478 + bool has_rom, 479 + enum dc_transfer_func_predefined tf, 480 + uint32_t blend_size, 481 + struct dc_transfer_func *func_blend) 482 + { 483 + int ret = 0; 484 + 485 + if (blend_size || tf != TRANSFER_FUNCTION_LINEAR) { 486 + /* 487 + * DRM plane gamma LUT or TF means we are linearizing color 488 + * space before blending (similar to degamma programming). As 489 + * we don't have hardcoded curve support, or we use AMD color 490 + * module to fill the parameters that will be translated to HW 491 + * points. 492 + */ 493 + func_blend->type = TF_TYPE_DISTRIBUTED_POINTS; 494 + func_blend->tf = tf; 495 + func_blend->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE; 496 + 497 + ret = __set_input_tf(NULL, func_blend, blend_lut, blend_size); 498 + } else { 499 + func_blend->type = TF_TYPE_BYPASS; 500 + func_blend->tf = TRANSFER_FUNCTION_LINEAR; 501 + } 502 + 503 + return ret; 504 + } 505 + 506 + /** 507 + * amdgpu_dm_verify_lut3d_size - verifies if 3D LUT is supported and if user 508 + * shaper and 3D LUTs match the hw supported size 509 + * @adev: amdgpu device 510 + * @plane_state: the DRM plane state 511 + * 512 + * Verifies if pre-blending (DPP) 3D LUT is supported by the HW (DCN 2.0 or 513 + * newer) and if the user shaper and 3D LUTs match the supported size. 514 + * 515 + * Returns: 516 + * 0 on success. -EINVAL if lut size are invalid. 517 + */ 518 + int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev, 519 + struct drm_plane_state *plane_state) 520 + { 521 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); 522 + const struct drm_color_lut *shaper = NULL, *lut3d = NULL; 523 + uint32_t exp_size, size, dim_size = MAX_COLOR_3DLUT_SIZE; 524 + bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut; 525 + 526 + /* shaper LUT is only available if 3D LUT color caps */ 527 + exp_size = has_3dlut ? MAX_COLOR_LUT_ENTRIES : 0; 528 + shaper = __extract_blob_lut(dm_plane_state->shaper_lut, &size); 529 + 530 + if (shaper && size != exp_size) { 531 + drm_dbg(&adev->ddev, 532 + "Invalid Shaper LUT size. Should be %u but got %u.\n", 533 + exp_size, size); 534 + return -EINVAL; 535 + } 536 + 537 + /* The number of 3D LUT entries is the dimension size cubed */ 538 + exp_size = has_3dlut ? dim_size * dim_size * dim_size : 0; 539 + lut3d = __extract_blob_lut(dm_plane_state->lut3d, &size); 540 + 541 + if (lut3d && size != exp_size) { 542 + drm_dbg(&adev->ddev, 543 + "Invalid 3D LUT size. Should be %u but got %u.\n", 544 + exp_size, size); 545 + return -EINVAL; 546 + } 547 + 548 + return 0; 624 549 } 625 550 626 551 /** ··· 904 401 const struct drm_color_lut *degamma_lut, *regamma_lut; 905 402 uint32_t degamma_size, regamma_size; 906 403 bool has_regamma, has_degamma; 404 + enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_LINEAR; 907 405 bool is_legacy; 908 406 int r; 407 + 408 + tf = amdgpu_tf_to_dc_tf(crtc->regamma_tf); 909 409 910 410 r = amdgpu_dm_verify_lut_sizes(&crtc->base); 911 411 if (r) ··· 945 439 crtc->cm_is_degamma_srgb = true; 946 440 stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 947 441 stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB; 948 - 442 + /* 443 + * Note: although we pass has_rom as parameter here, we never 444 + * actually use ROM because the color module only takes the ROM 445 + * path if transfer_func->type == PREDEFINED. 446 + * 447 + * See more in mod_color_calculate_regamma_params() 448 + */ 949 449 r = __set_legacy_tf(stream->out_transfer_func, regamma_lut, 950 450 regamma_size, has_rom); 951 451 if (r) 952 452 return r; 953 - } else if (has_regamma) { 954 - /* If atomic regamma, CRTC RGM goes into RGM LUT. */ 955 - stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 956 - stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 957 - 958 - r = __set_output_tf(stream->out_transfer_func, regamma_lut, 959 - regamma_size, has_rom); 453 + } else { 454 + regamma_size = has_regamma ? regamma_size : 0; 455 + r = amdgpu_dm_set_atomic_regamma(stream, regamma_lut, 456 + regamma_size, has_rom, tf); 960 457 if (r) 961 458 return r; 962 - } else { 963 - /* 964 - * No CRTC RGM means we can just put the block into bypass 965 - * since we don't have any plane level adjustments using it. 966 - */ 967 - stream->out_transfer_func->type = TF_TYPE_BYPASS; 968 - stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 969 459 } 970 460 971 461 /* ··· 997 495 return 0; 998 496 } 999 497 1000 - /** 1001 - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane. 1002 - * @crtc: amdgpu_dm crtc state 1003 - * @dc_plane_state: target DC surface 1004 - * 1005 - * Update the underlying dc_stream_state's input transfer function (ITF) in 1006 - * preparation for hardware commit. The transfer function used depends on 1007 - * the preparation done on the stream for color management. 1008 - * 1009 - * Returns: 1010 - * 0 on success. -ENOMEM if mem allocation fails. 1011 - */ 1012 - int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, 1013 - struct dc_plane_state *dc_plane_state) 498 + static int 499 + map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, 500 + struct dc_plane_state *dc_plane_state, 501 + struct dc_color_caps *caps) 1014 502 { 1015 503 const struct drm_color_lut *degamma_lut; 1016 504 enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; ··· 1023 531 &degamma_size); 1024 532 ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); 1025 533 1026 - dc_plane_state->in_transfer_func->type = 1027 - TF_TYPE_DISTRIBUTED_POINTS; 534 + dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 1028 535 1029 536 /* 1030 537 * This case isn't fully correct, but also fairly ··· 1055 564 dc_plane_state->in_transfer_func->tf = 1056 565 TRANSFER_FUNCTION_LINEAR; 1057 566 1058 - r = __set_input_tf(dc_plane_state->in_transfer_func, 567 + r = __set_input_tf(caps, dc_plane_state->in_transfer_func, 1059 568 degamma_lut, degamma_size); 1060 569 if (r) 1061 570 return r; 1062 - } else if (crtc->cm_is_degamma_srgb) { 571 + } else { 1063 572 /* 1064 573 * For legacy gamma support we need the regamma input 1065 574 * in linear space. Assume that the input is sRGB. ··· 1068 577 dc_plane_state->in_transfer_func->tf = tf; 1069 578 1070 579 if (tf != TRANSFER_FUNCTION_SRGB && 1071 - !mod_color_calculate_degamma_params(NULL, 1072 - dc_plane_state->in_transfer_func, NULL, false)) 580 + !mod_color_calculate_degamma_params(caps, 581 + dc_plane_state->in_transfer_func, 582 + NULL, false)) 1073 583 return -ENOMEM; 1074 - } else { 1075 - /* ...Otherwise we can just bypass the DGM block. */ 1076 - dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 1077 - dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 1078 584 } 1079 585 1080 586 return 0; 587 + } 588 + 589 + static int 590 + __set_dm_plane_degamma(struct drm_plane_state *plane_state, 591 + struct dc_plane_state *dc_plane_state, 592 + struct dc_color_caps *color_caps) 593 + { 594 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); 595 + const struct drm_color_lut *degamma_lut; 596 + enum amdgpu_transfer_function tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 597 + uint32_t degamma_size; 598 + bool has_degamma_lut; 599 + int ret; 600 + 601 + degamma_lut = __extract_blob_lut(dm_plane_state->degamma_lut, 602 + &degamma_size); 603 + 604 + has_degamma_lut = degamma_lut && 605 + !__is_lut_linear(degamma_lut, degamma_size); 606 + 607 + tf = dm_plane_state->degamma_tf; 608 + 609 + /* If we don't have plane degamma LUT nor TF to set on DC, we have 610 + * nothing to do here, return. 611 + */ 612 + if (!has_degamma_lut && tf == AMDGPU_TRANSFER_FUNCTION_DEFAULT) 613 + return -EINVAL; 614 + 615 + dc_plane_state->in_transfer_func->tf = amdgpu_tf_to_dc_tf(tf); 616 + 617 + if (has_degamma_lut) { 618 + ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); 619 + 620 + dc_plane_state->in_transfer_func->type = 621 + TF_TYPE_DISTRIBUTED_POINTS; 622 + 623 + ret = __set_input_tf(color_caps, dc_plane_state->in_transfer_func, 624 + degamma_lut, degamma_size); 625 + if (ret) 626 + return ret; 627 + } else { 628 + dc_plane_state->in_transfer_func->type = 629 + TF_TYPE_PREDEFINED; 630 + 631 + if (!mod_color_calculate_degamma_params(color_caps, 632 + dc_plane_state->in_transfer_func, NULL, false)) 633 + return -ENOMEM; 634 + } 635 + return 0; 636 + } 637 + 638 + static int 639 + amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state, 640 + struct dc_plane_state *dc_plane_state) 641 + { 642 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); 643 + enum amdgpu_transfer_function shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 644 + enum amdgpu_transfer_function blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 645 + const struct drm_color_lut *shaper_lut, *lut3d, *blend_lut; 646 + uint32_t shaper_size, lut3d_size, blend_size; 647 + int ret; 648 + 649 + dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult); 650 + 651 + shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size); 652 + shaper_size = shaper_lut != NULL ? shaper_size : 0; 653 + shaper_tf = dm_plane_state->shaper_tf; 654 + lut3d = __extract_blob_lut(dm_plane_state->lut3d, &lut3d_size); 655 + lut3d_size = lut3d != NULL ? lut3d_size : 0; 656 + 657 + amdgpu_dm_atomic_lut3d(lut3d, lut3d_size, dc_plane_state->lut3d_func); 658 + ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, false, 659 + amdgpu_tf_to_dc_tf(shaper_tf), 660 + shaper_size, 661 + dc_plane_state->in_shaper_func); 662 + if (ret) { 663 + drm_dbg_kms(plane_state->plane->dev, 664 + "setting plane %d shaper LUT failed.\n", 665 + plane_state->plane->index); 666 + 667 + return ret; 668 + } 669 + 670 + blend_tf = dm_plane_state->blend_tf; 671 + blend_lut = __extract_blob_lut(dm_plane_state->blend_lut, &blend_size); 672 + blend_size = blend_lut != NULL ? blend_size : 0; 673 + 674 + ret = amdgpu_dm_atomic_blend_lut(blend_lut, false, 675 + amdgpu_tf_to_dc_tf(blend_tf), 676 + blend_size, dc_plane_state->blend_tf); 677 + if (ret) { 678 + drm_dbg_kms(plane_state->plane->dev, 679 + "setting plane %d gamma lut failed.\n", 680 + plane_state->plane->index); 681 + 682 + return ret; 683 + } 684 + 685 + return 0; 686 + } 687 + 688 + /** 689 + * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane. 690 + * @crtc: amdgpu_dm crtc state 691 + * @plane_state: DRM plane state 692 + * @dc_plane_state: target DC surface 693 + * 694 + * Update the underlying dc_stream_state's input transfer function (ITF) in 695 + * preparation for hardware commit. The transfer function used depends on 696 + * the preparation done on the stream for color management. 697 + * 698 + * Returns: 699 + * 0 on success. -ENOMEM if mem allocation fails. 700 + */ 701 + int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, 702 + struct drm_plane_state *plane_state, 703 + struct dc_plane_state *dc_plane_state) 704 + { 705 + struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev); 706 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); 707 + struct drm_color_ctm_3x4 *ctm = NULL; 708 + struct dc_color_caps *color_caps = NULL; 709 + bool has_crtc_cm_degamma; 710 + int ret; 711 + 712 + ret = amdgpu_dm_verify_lut3d_size(adev, plane_state); 713 + if (ret) { 714 + drm_dbg_driver(&adev->ddev, "amdgpu_dm_verify_lut3d_size() failed\n"); 715 + return ret; 716 + } 717 + 718 + if (dc_plane_state->ctx && dc_plane_state->ctx->dc) 719 + color_caps = &dc_plane_state->ctx->dc->caps.color; 720 + 721 + /* Initially, we can just bypass the DGM block. */ 722 + dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 723 + dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 724 + 725 + /* After, we start to update values according to color props */ 726 + has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb); 727 + 728 + ret = __set_dm_plane_degamma(plane_state, dc_plane_state, color_caps); 729 + if (ret == -ENOMEM) 730 + return ret; 731 + 732 + /* We only have one degamma block available (pre-blending) for the 733 + * whole color correction pipeline, so that we can't actually perform 734 + * plane and CRTC degamma at the same time. Explicitly reject atomic 735 + * updates when userspace sets both plane and CRTC degamma properties. 736 + */ 737 + if (has_crtc_cm_degamma && ret != -EINVAL){ 738 + drm_dbg_kms(crtc->base.crtc->dev, 739 + "doesn't support plane and CRTC degamma at the same time\n"); 740 + return -EINVAL; 741 + } 742 + 743 + /* If we are here, it means we don't have plane degamma settings, check 744 + * if we have CRTC degamma waiting for mapping to pre-blending degamma 745 + * block 746 + */ 747 + if (has_crtc_cm_degamma) { 748 + /* 749 + * AMD HW doesn't have post-blending degamma caps. When DRM 750 + * CRTC atomic degamma is set, we maps it to DPP degamma block 751 + * (pre-blending) or, on legacy gamma, we use DPP degamma to 752 + * linearize (implicit degamma) from sRGB/BT709 according to 753 + * the input space. 754 + */ 755 + ret = map_crtc_degamma_to_dc_plane(crtc, dc_plane_state, color_caps); 756 + if (ret) 757 + return ret; 758 + } 759 + 760 + /* Setup CRTC CTM. */ 761 + if (dm_plane_state->ctm) { 762 + ctm = (struct drm_color_ctm_3x4 *)dm_plane_state->ctm->data; 763 + /* 764 + * DCN2 and older don't support both pre-blending and 765 + * post-blending gamut remap. For this HW family, if we have 766 + * the plane and CRTC CTMs simultaneously, CRTC CTM takes 767 + * priority, and we discard plane CTM, as implemented in 768 + * dcn10_program_gamut_remap(). However, DCN3+ has DPP 769 + * (pre-blending) and MPC (post-blending) `gamut remap` blocks; 770 + * therefore, we can program plane and CRTC CTMs together by 771 + * mapping CRTC CTM to MPC and keeping plane CTM setup at DPP, 772 + * as it's done by dcn30_program_gamut_remap(). 773 + */ 774 + __drm_ctm_3x4_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix); 775 + 776 + dc_plane_state->gamut_remap_matrix.enable_remap = true; 777 + dc_plane_state->input_csc_color_matrix.enable_adjustment = false; 778 + } else { 779 + /* Bypass CTM. */ 780 + dc_plane_state->gamut_remap_matrix.enable_remap = false; 781 + dc_plane_state->input_csc_color_matrix.enable_adjustment = false; 782 + } 783 + 784 + return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state); 1081 785 }
+72
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
··· 260 260 state->freesync_config = cur->freesync_config; 261 261 state->cm_has_degamma = cur->cm_has_degamma; 262 262 state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb; 263 + state->regamma_tf = cur->regamma_tf; 263 264 state->crc_skip_count = cur->crc_skip_count; 264 265 state->mpo_requested = cur->mpo_requested; 265 266 /* TODO Duplicate dc_stream after objects are stream object is flattened */ ··· 297 296 } 298 297 #endif 299 298 299 + #ifdef AMD_PRIVATE_COLOR 300 + /** 301 + * dm_crtc_additional_color_mgmt - enable additional color properties 302 + * @crtc: DRM CRTC 303 + * 304 + * This function lets the driver enable post-blending CRTC regamma transfer 305 + * function property in addition to DRM CRTC gamma LUT. Default value means 306 + * linear transfer function, which is the default CRTC gamma LUT behaviour 307 + * without this property. 308 + */ 309 + static void 310 + dm_crtc_additional_color_mgmt(struct drm_crtc *crtc) 311 + { 312 + struct amdgpu_device *adev = drm_to_adev(crtc->dev); 313 + 314 + if(adev->dm.dc->caps.color.mpc.ogam_ram) 315 + drm_object_attach_property(&crtc->base, 316 + adev->mode_info.regamma_tf_property, 317 + AMDGPU_TRANSFER_FUNCTION_DEFAULT); 318 + } 319 + 320 + static int 321 + amdgpu_dm_atomic_crtc_set_property(struct drm_crtc *crtc, 322 + struct drm_crtc_state *state, 323 + struct drm_property *property, 324 + uint64_t val) 325 + { 326 + struct amdgpu_device *adev = drm_to_adev(crtc->dev); 327 + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); 328 + 329 + if (property == adev->mode_info.regamma_tf_property) { 330 + if (acrtc_state->regamma_tf != val) { 331 + acrtc_state->regamma_tf = val; 332 + acrtc_state->base.color_mgmt_changed |= 1; 333 + } 334 + } else { 335 + drm_dbg_atomic(crtc->dev, 336 + "[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n", 337 + crtc->base.id, crtc->name, 338 + property->base.id, property->name); 339 + return -EINVAL; 340 + } 341 + 342 + return 0; 343 + } 344 + 345 + static int 346 + amdgpu_dm_atomic_crtc_get_property(struct drm_crtc *crtc, 347 + const struct drm_crtc_state *state, 348 + struct drm_property *property, 349 + uint64_t *val) 350 + { 351 + struct amdgpu_device *adev = drm_to_adev(crtc->dev); 352 + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(state); 353 + 354 + if (property == adev->mode_info.regamma_tf_property) 355 + *val = acrtc_state->regamma_tf; 356 + else 357 + return -EINVAL; 358 + 359 + return 0; 360 + } 361 + #endif 362 + 300 363 /* Implemented only the options currently available for the driver */ 301 364 static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { 302 365 .reset = amdgpu_dm_crtc_reset_state, ··· 378 313 .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, 379 314 #if defined(CONFIG_DEBUG_FS) 380 315 .late_register = amdgpu_dm_crtc_late_register, 316 + #endif 317 + #ifdef AMD_PRIVATE_COLOR 318 + .atomic_set_property = amdgpu_dm_atomic_crtc_set_property, 319 + .atomic_get_property = amdgpu_dm_atomic_crtc_get_property, 381 320 #endif 382 321 }; 383 322 ··· 558 489 559 490 drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); 560 491 492 + #ifdef AMD_PRIVATE_COLOR 493 + dm_crtc_additional_color_mgmt(&acrtc->base); 494 + #endif 561 495 return 0; 562 496 563 497 fail:
+1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 28 28 #include <drm/drm_atomic.h> 29 29 #include <drm/drm_atomic_helper.h> 30 30 #include <drm/drm_fixed.h> 31 + #include <drm/drm_edid.h> 31 32 #include "dm_services.h" 32 33 #include "amdgpu.h" 33 34 #include "amdgpu_dm.h"
+230 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
··· 1337 1337 amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); 1338 1338 WARN_ON(amdgpu_state == NULL); 1339 1339 1340 - if (amdgpu_state) 1341 - __drm_atomic_helper_plane_reset(plane, &amdgpu_state->base); 1340 + if (!amdgpu_state) 1341 + return; 1342 + 1343 + __drm_atomic_helper_plane_reset(plane, &amdgpu_state->base); 1344 + amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 1345 + amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT; 1346 + amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 1347 + amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT; 1342 1348 } 1343 1349 1344 1350 static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane) ··· 1362 1356 dm_plane_state->dc_state = old_dm_plane_state->dc_state; 1363 1357 dc_plane_state_retain(dm_plane_state->dc_state); 1364 1358 } 1359 + 1360 + if (old_dm_plane_state->degamma_lut) 1361 + dm_plane_state->degamma_lut = 1362 + drm_property_blob_get(old_dm_plane_state->degamma_lut); 1363 + if (old_dm_plane_state->ctm) 1364 + dm_plane_state->ctm = 1365 + drm_property_blob_get(old_dm_plane_state->ctm); 1366 + if (old_dm_plane_state->shaper_lut) 1367 + dm_plane_state->shaper_lut = 1368 + drm_property_blob_get(old_dm_plane_state->shaper_lut); 1369 + if (old_dm_plane_state->lut3d) 1370 + dm_plane_state->lut3d = 1371 + drm_property_blob_get(old_dm_plane_state->lut3d); 1372 + if (old_dm_plane_state->blend_lut) 1373 + dm_plane_state->blend_lut = 1374 + drm_property_blob_get(old_dm_plane_state->blend_lut); 1375 + 1376 + dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf; 1377 + dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult; 1378 + dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf; 1379 + dm_plane_state->blend_tf = old_dm_plane_state->blend_tf; 1365 1380 1366 1381 return &dm_plane_state->base; 1367 1382 } ··· 1451 1424 { 1452 1425 struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); 1453 1426 1427 + if (dm_plane_state->degamma_lut) 1428 + drm_property_blob_put(dm_plane_state->degamma_lut); 1429 + if (dm_plane_state->ctm) 1430 + drm_property_blob_put(dm_plane_state->ctm); 1431 + if (dm_plane_state->lut3d) 1432 + drm_property_blob_put(dm_plane_state->lut3d); 1433 + if (dm_plane_state->shaper_lut) 1434 + drm_property_blob_put(dm_plane_state->shaper_lut); 1435 + if (dm_plane_state->blend_lut) 1436 + drm_property_blob_put(dm_plane_state->blend_lut); 1437 + 1454 1438 if (dm_plane_state->dc_state) 1455 1439 dc_plane_state_release(dm_plane_state->dc_state); 1456 1440 1457 1441 drm_atomic_helper_plane_destroy_state(plane, state); 1458 1442 } 1443 + 1444 + #ifdef AMD_PRIVATE_COLOR 1445 + static void 1446 + dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm, 1447 + struct drm_plane *plane) 1448 + { 1449 + struct amdgpu_mode_info mode_info = dm->adev->mode_info; 1450 + struct dpp_color_caps dpp_color_caps = dm->dc->caps.color.dpp; 1451 + 1452 + /* Check HW color pipeline capabilities on DPP block (pre-blending) 1453 + * before exposing related properties. 1454 + */ 1455 + if (dpp_color_caps.dgam_ram || dpp_color_caps.gamma_corr) { 1456 + drm_object_attach_property(&plane->base, 1457 + mode_info.plane_degamma_lut_property, 1458 + 0); 1459 + drm_object_attach_property(&plane->base, 1460 + mode_info.plane_degamma_lut_size_property, 1461 + MAX_COLOR_LUT_ENTRIES); 1462 + drm_object_attach_property(&plane->base, 1463 + dm->adev->mode_info.plane_degamma_tf_property, 1464 + AMDGPU_TRANSFER_FUNCTION_DEFAULT); 1465 + } 1466 + /* HDR MULT is always available */ 1467 + drm_object_attach_property(&plane->base, 1468 + dm->adev->mode_info.plane_hdr_mult_property, 1469 + AMDGPU_HDR_MULT_DEFAULT); 1470 + 1471 + /* Only enable plane CTM if both DPP and MPC gamut remap is available. */ 1472 + if (dm->dc->caps.color.mpc.gamut_remap) 1473 + drm_object_attach_property(&plane->base, 1474 + dm->adev->mode_info.plane_ctm_property, 0); 1475 + 1476 + if (dpp_color_caps.hw_3d_lut) { 1477 + drm_object_attach_property(&plane->base, 1478 + mode_info.plane_shaper_lut_property, 0); 1479 + drm_object_attach_property(&plane->base, 1480 + mode_info.plane_shaper_lut_size_property, 1481 + MAX_COLOR_LUT_ENTRIES); 1482 + drm_object_attach_property(&plane->base, 1483 + mode_info.plane_shaper_tf_property, 1484 + AMDGPU_TRANSFER_FUNCTION_DEFAULT); 1485 + drm_object_attach_property(&plane->base, 1486 + mode_info.plane_lut3d_property, 0); 1487 + drm_object_attach_property(&plane->base, 1488 + mode_info.plane_lut3d_size_property, 1489 + MAX_COLOR_3DLUT_SIZE); 1490 + } 1491 + 1492 + if (dpp_color_caps.ogam_ram) { 1493 + drm_object_attach_property(&plane->base, 1494 + mode_info.plane_blend_lut_property, 0); 1495 + drm_object_attach_property(&plane->base, 1496 + mode_info.plane_blend_lut_size_property, 1497 + MAX_COLOR_LUT_ENTRIES); 1498 + drm_object_attach_property(&plane->base, 1499 + mode_info.plane_blend_tf_property, 1500 + AMDGPU_TRANSFER_FUNCTION_DEFAULT); 1501 + } 1502 + } 1503 + 1504 + static int 1505 + dm_atomic_plane_set_property(struct drm_plane *plane, 1506 + struct drm_plane_state *state, 1507 + struct drm_property *property, 1508 + uint64_t val) 1509 + { 1510 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); 1511 + struct amdgpu_device *adev = drm_to_adev(plane->dev); 1512 + bool replaced = false; 1513 + int ret; 1514 + 1515 + if (property == adev->mode_info.plane_degamma_lut_property) { 1516 + ret = drm_property_replace_blob_from_id(plane->dev, 1517 + &dm_plane_state->degamma_lut, 1518 + val, -1, 1519 + sizeof(struct drm_color_lut), 1520 + &replaced); 1521 + dm_plane_state->base.color_mgmt_changed |= replaced; 1522 + return ret; 1523 + } else if (property == adev->mode_info.plane_degamma_tf_property) { 1524 + if (dm_plane_state->degamma_tf != val) { 1525 + dm_plane_state->degamma_tf = val; 1526 + dm_plane_state->base.color_mgmt_changed = 1; 1527 + } 1528 + } else if (property == adev->mode_info.plane_hdr_mult_property) { 1529 + if (dm_plane_state->hdr_mult != val) { 1530 + dm_plane_state->hdr_mult = val; 1531 + dm_plane_state->base.color_mgmt_changed = 1; 1532 + } 1533 + } else if (property == adev->mode_info.plane_ctm_property) { 1534 + ret = drm_property_replace_blob_from_id(plane->dev, 1535 + &dm_plane_state->ctm, 1536 + val, 1537 + sizeof(struct drm_color_ctm_3x4), -1, 1538 + &replaced); 1539 + dm_plane_state->base.color_mgmt_changed |= replaced; 1540 + return ret; 1541 + } else if (property == adev->mode_info.plane_shaper_lut_property) { 1542 + ret = drm_property_replace_blob_from_id(plane->dev, 1543 + &dm_plane_state->shaper_lut, 1544 + val, -1, 1545 + sizeof(struct drm_color_lut), 1546 + &replaced); 1547 + dm_plane_state->base.color_mgmt_changed |= replaced; 1548 + return ret; 1549 + } else if (property == adev->mode_info.plane_shaper_tf_property) { 1550 + if (dm_plane_state->shaper_tf != val) { 1551 + dm_plane_state->shaper_tf = val; 1552 + dm_plane_state->base.color_mgmt_changed = 1; 1553 + } 1554 + } else if (property == adev->mode_info.plane_lut3d_property) { 1555 + ret = drm_property_replace_blob_from_id(plane->dev, 1556 + &dm_plane_state->lut3d, 1557 + val, -1, 1558 + sizeof(struct drm_color_lut), 1559 + &replaced); 1560 + dm_plane_state->base.color_mgmt_changed |= replaced; 1561 + return ret; 1562 + } else if (property == adev->mode_info.plane_blend_lut_property) { 1563 + ret = drm_property_replace_blob_from_id(plane->dev, 1564 + &dm_plane_state->blend_lut, 1565 + val, -1, 1566 + sizeof(struct drm_color_lut), 1567 + &replaced); 1568 + dm_plane_state->base.color_mgmt_changed |= replaced; 1569 + return ret; 1570 + } else if (property == adev->mode_info.plane_blend_tf_property) { 1571 + if (dm_plane_state->blend_tf != val) { 1572 + dm_plane_state->blend_tf = val; 1573 + dm_plane_state->base.color_mgmt_changed = 1; 1574 + } 1575 + } else { 1576 + drm_dbg_atomic(plane->dev, 1577 + "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n", 1578 + plane->base.id, plane->name, 1579 + property->base.id, property->name); 1580 + return -EINVAL; 1581 + } 1582 + 1583 + return 0; 1584 + } 1585 + 1586 + static int 1587 + dm_atomic_plane_get_property(struct drm_plane *plane, 1588 + const struct drm_plane_state *state, 1589 + struct drm_property *property, 1590 + uint64_t *val) 1591 + { 1592 + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); 1593 + struct amdgpu_device *adev = drm_to_adev(plane->dev); 1594 + 1595 + if (property == adev->mode_info.plane_degamma_lut_property) { 1596 + *val = (dm_plane_state->degamma_lut) ? 1597 + dm_plane_state->degamma_lut->base.id : 0; 1598 + } else if (property == adev->mode_info.plane_degamma_tf_property) { 1599 + *val = dm_plane_state->degamma_tf; 1600 + } else if (property == adev->mode_info.plane_hdr_mult_property) { 1601 + *val = dm_plane_state->hdr_mult; 1602 + } else if (property == adev->mode_info.plane_ctm_property) { 1603 + *val = (dm_plane_state->ctm) ? 1604 + dm_plane_state->ctm->base.id : 0; 1605 + } else if (property == adev->mode_info.plane_shaper_lut_property) { 1606 + *val = (dm_plane_state->shaper_lut) ? 1607 + dm_plane_state->shaper_lut->base.id : 0; 1608 + } else if (property == adev->mode_info.plane_shaper_tf_property) { 1609 + *val = dm_plane_state->shaper_tf; 1610 + } else if (property == adev->mode_info.plane_lut3d_property) { 1611 + *val = (dm_plane_state->lut3d) ? 1612 + dm_plane_state->lut3d->base.id : 0; 1613 + } else if (property == adev->mode_info.plane_blend_lut_property) { 1614 + *val = (dm_plane_state->blend_lut) ? 1615 + dm_plane_state->blend_lut->base.id : 0; 1616 + } else if (property == adev->mode_info.plane_blend_tf_property) { 1617 + *val = dm_plane_state->blend_tf; 1618 + 1619 + } else { 1620 + return -EINVAL; 1621 + } 1622 + 1623 + return 0; 1624 + } 1625 + #endif 1459 1626 1460 1627 static const struct drm_plane_funcs dm_plane_funcs = { 1461 1628 .update_plane = drm_atomic_helper_update_plane, ··· 1659 1438 .atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state, 1660 1439 .atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state, 1661 1440 .format_mod_supported = amdgpu_dm_plane_format_mod_supported, 1441 + #ifdef AMD_PRIVATE_COLOR 1442 + .atomic_set_property = dm_atomic_plane_set_property, 1443 + .atomic_get_property = dm_atomic_plane_get_property, 1444 + #endif 1662 1445 }; 1663 1446 1664 1447 int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, ··· 1742 1517 1743 1518 drm_plane_helper_add(plane, &dm_plane_helper_funcs); 1744 1519 1520 + #ifdef AMD_PRIVATE_COLOR 1521 + dm_atomic_plane_attach_color_mgmt_properties(dm, plane); 1522 + #endif 1745 1523 /* Create (reset) the plane state */ 1746 1524 if (plane->funcs->reset) 1747 1525 plane->funcs->reset(plane);
+1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
··· 32 32 #include "amdgpu_display.h" 33 33 #include "dc.h" 34 34 35 + #include <drm/drm_edid.h> 35 36 #include <drm/drm_atomic_state_helper.h> 36 37 #include <drm/drm_modeset_helper_vtables.h> 37 38
+1 -9
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
··· 1747 1747 result = get_firmware_info_v3_2(bp, info); 1748 1748 break; 1749 1749 case 4: 1750 - case 5: 1751 1750 result = get_firmware_info_v3_4(bp, info); 1752 1751 break; 1753 1752 default: ··· 2386 2387 return BP_RESULT_BADBIOSTABLE; 2387 2388 2388 2389 info->num_chans = info_v30->channel_num; 2389 - /* As suggested by VBIOS we should always use 2390 - * dram_channel_width_bytes = 2 when using VRAM 2391 - * table version 3.0. This is because the channel_width 2392 - * param in the VRAM info table is changed in 7000 series and 2393 - * no longer represents the memory channel width. 2394 - */ 2395 - info->dram_channel_width_bytes = 2; 2390 + info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8; 2396 2391 2397 2392 return result; 2398 2393 } 2399 - 2400 2394 2401 2395 /* 2402 2396 * get_integrated_info_v11
+1 -1
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
··· 368 368 } 369 369 break; 370 370 371 - #endif /* CONFIG_DRM_AMD_DC_FP - Family RV */ 371 + #endif /* CONFIG_DRM_AMD_DC_FP */ 372 372 default: 373 373 ASSERT(0); /* Unknown Asic */ 374 374 break;
+4 -4
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
··· 361 361 case DCN_ZSTATE_SUPPORT_ALLOW: 362 362 msg_id = VBIOSSMC_MSG_AllowZstatesEntry; 363 363 param = (1 << 10) | (1 << 9) | (1 << 8); 364 - smu_print("%s: SMC_MSG_AllowZstatesEntr msg = ALLOW, param = %d\n", __func__, param); 364 + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW, param = %d\n", __func__, param); 365 365 break; 366 366 367 367 case DCN_ZSTATE_SUPPORT_DISALLOW: 368 368 msg_id = VBIOSSMC_MSG_AllowZstatesEntry; 369 369 param = 0; 370 - smu_print("%s: SMC_MSG_AllowZstatesEntr msg_id = DISALLOW, param = %d\n", __func__, param); 370 + smu_print("%s: SMC_MSG_AllowZstatesEntry msg_id = DISALLOW, param = %d\n", __func__, param); 371 371 break; 372 372 373 373 374 374 case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY: 375 375 msg_id = VBIOSSMC_MSG_AllowZstatesEntry; 376 376 param = (1 << 10); 377 - smu_print("%s: SMC_MSG_AllowZstatesEntr msg = ALLOW_Z10_ONLY, param = %d\n", __func__, param); 377 + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z10_ONLY, param = %d\n", __func__, param); 378 378 break; 379 379 380 380 case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY: 381 381 msg_id = VBIOSSMC_MSG_AllowZstatesEntry; 382 382 param = (1 << 10) | (1 << 8); 383 - smu_print("%s: SMC_MSG_AllowZstatesEntr msg = ALLOW_Z8_Z10_ONLY, param = %d\n", __func__, param); 383 + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_Z10_ONLY, param = %d\n", __func__, param); 384 384 break; 385 385 386 386 case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY:
+1 -1
drivers/gpu/drm/amd/display/dc/dc.h
··· 49 49 struct set_config_cmd_payload; 50 50 struct dmub_notification; 51 51 52 - #define DC_VER "3.2.263" 52 + #define DC_VER "3.2.264" 53 53 54 54 #define MAX_SURFACES 3 55 55 #define MAX_PLANES 6
+14
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
··· 1268 1268 ASSERT(0); 1269 1269 } 1270 1270 1271 + void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState) 1272 + { 1273 + struct dmub_srv *dmub; 1274 + 1275 + if (!dc_dmub_srv) 1276 + return; 1277 + 1278 + dmub = dc_dmub_srv->dmub; 1279 + 1280 + if (powerState == DC_ACPI_CM_POWER_STATE_D0) 1281 + dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D0); 1282 + else 1283 + dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3); 1284 + }
+2
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
··· 102 102 bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait); 103 103 void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle); 104 104 void dc_dmub_srv_exit_low_power_state(const struct dc *dc); 105 + 106 + void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); 105 107 #endif /* _DMUB_DC_SRV_H_ */
+4
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
··· 64 64 65 65 static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm) 66 66 { 67 + dc_allow_idle_optimizations(abm->ctx->dc, false); 68 + 67 69 return dmub_abm_get_current_backlight(abm); 68 70 } 69 71 70 72 static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm) 71 73 { 74 + dc_allow_idle_optimizations(abm->ctx->dc, false); 75 + 72 76 return dmub_abm_get_target_backlight(abm); 73 77 } 74 78
+2 -1
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c
··· 118 118 .update_dsc_pg = dcn32_update_dsc_pg, 119 119 .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, 120 120 .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, 121 - .block_power_control = dcn35_block_power_control, 121 + .hw_block_power_up = dcn35_hw_block_power_up, 122 + .hw_block_power_down = dcn35_hw_block_power_down, 122 123 .root_clock_control = dcn35_root_clock_control, 123 124 .set_idle_state = dcn35_set_idle_state, 124 125 .get_idle_state = dcn35_get_idle_state
+2
drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
··· 247 247 #define PP_SMU_NUM_MEMCLK_DPM_LEVELS 4 248 248 #define PP_SMU_NUM_DCLK_DPM_LEVELS 8 249 249 #define PP_SMU_NUM_VCLK_DPM_LEVELS 8 250 + #define PP_SMU_NUM_VPECLK_DPM_LEVELS 8 250 251 251 252 struct dpm_clock { 252 253 uint32_t Freq; // In MHz ··· 263 262 struct dpm_clock MemClocks[PP_SMU_NUM_MEMCLK_DPM_LEVELS]; 264 263 struct dpm_clock VClocks[PP_SMU_NUM_VCLK_DPM_LEVELS]; 265 264 struct dpm_clock DClocks[PP_SMU_NUM_DCLK_DPM_LEVELS]; 265 + struct dpm_clock VPEClocks[PP_SMU_NUM_VPECLK_DPM_LEVELS]; 266 266 }; 267 267 268 268
+3
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
··· 813 813 (v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ || 814 814 v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ? 815 815 mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, 816 + mode_lib->vba.PrefetchModePerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] > 0 || mode_lib->vba.DRAMClockChangeRequirementFinal == false, 817 + 816 818 /* Output */ 817 819 &v->DSTXAfterScaler[k], 818 820 &v->DSTYAfterScaler[k], ··· 3319 3317 v->SwathHeightCThisState[k], v->TWait, 3320 3318 (v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ? 3321 3319 mode_lib->vba.ip.min_prefetch_in_strobe_us : 0, 3320 + mode_lib->vba.PrefetchModePerState[i][j] > 0 || mode_lib->vba.DRAMClockChangeRequirementFinal == false, 3322 3321 3323 3322 /* Output */ 3324 3323 &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler[k],
+27 -6
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
··· 3423 3423 unsigned int SwathHeightC, 3424 3424 double TWait, 3425 3425 double TPreReq, 3426 + bool ExtendPrefetchIfPossible, 3426 3427 /* Output */ 3427 3428 double *DSTXAfterScaler, 3428 3429 double *DSTYAfterScaler, ··· 3893 3892 /* Clamp to oto for bandwidth calculation */ 3894 3893 LinesForPrefetchBandwidth = dst_y_prefetch_oto; 3895 3894 } else { 3896 - *DestinationLinesForPrefetch = dst_y_prefetch_equ; 3897 - TimeForFetchingMetaPTE = Tvm_equ; 3898 - TimeForFetchingRowInVBlank = Tr0_equ; 3899 - *PrefetchBandwidth = prefetch_bw_equ; 3900 - /* Clamp to equ for bandwidth calculation */ 3901 - LinesForPrefetchBandwidth = dst_y_prefetch_equ; 3895 + /* For mode programming we want to extend the prefetch as much as possible 3896 + * (up to oto, or as long as we can for equ) if we're not already applying 3897 + * the 60us prefetch requirement. This is to avoid intermittent underflow 3898 + * issues during prefetch. 3899 + * 3900 + * The prefetch extension is applied under the following scenarios: 3901 + * 1. We're in prefetch mode > 0 (i.e. we don't support MCLK switch in blank) 3902 + * 2. We're using subvp or drr methods of p-state switch, in which case we 3903 + * we don't care if prefetch takes up more of the blanking time 3904 + * 3905 + * Mode programming typically chooses the smallest prefetch time possible 3906 + * (i.e. highest bandwidth during prefetch) presumably to create margin between 3907 + * p-states / c-states that happen in vblank and prefetch. Therefore we only 3908 + * apply this prefetch extension when p-state in vblank is not required (UCLK 3909 + * p-states take up the most vblank time). 3910 + */ 3911 + if (ExtendPrefetchIfPossible && TPreReq == 0 && VStartup < MaxVStartup) { 3912 + MyError = true; 3913 + } else { 3914 + *DestinationLinesForPrefetch = dst_y_prefetch_equ; 3915 + TimeForFetchingMetaPTE = Tvm_equ; 3916 + TimeForFetchingRowInVBlank = Tr0_equ; 3917 + *PrefetchBandwidth = prefetch_bw_equ; 3918 + /* Clamp to equ for bandwidth calculation */ 3919 + LinesForPrefetchBandwidth = dst_y_prefetch_equ; 3920 + } 3902 3921 } 3903 3922 3904 3923 *DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * TimeForFetchingMetaPTE / LineTime, 1.0) / 4.0;
+1
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
··· 747 747 unsigned int SwathHeightC, 748 748 double TWait, 749 749 double TPreReq, 750 + bool ExtendPrefetchIfPossible, 750 751 /* Output */ 751 752 double *DSTXAfterScaler, 752 753 double *DSTYAfterScaler,
+9 -5
drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
··· 124 124 .phyclk_mhz = 600.0, 125 125 .phyclk_d18_mhz = 667.0, 126 126 .dscclk_mhz = 186.0, 127 - .dtbclk_mhz = 625.0, 127 + .dtbclk_mhz = 600.0, 128 128 }, 129 129 { 130 130 .state = 1, ··· 133 133 .phyclk_mhz = 810.0, 134 134 .phyclk_d18_mhz = 667.0, 135 135 .dscclk_mhz = 209.0, 136 - .dtbclk_mhz = 625.0, 136 + .dtbclk_mhz = 600.0, 137 137 }, 138 138 { 139 139 .state = 2, ··· 142 142 .phyclk_mhz = 810.0, 143 143 .phyclk_d18_mhz = 667.0, 144 144 .dscclk_mhz = 209.0, 145 - .dtbclk_mhz = 625.0, 145 + .dtbclk_mhz = 600.0, 146 146 }, 147 147 { 148 148 .state = 3, ··· 151 151 .phyclk_mhz = 810.0, 152 152 .phyclk_d18_mhz = 667.0, 153 153 .dscclk_mhz = 371.0, 154 - .dtbclk_mhz = 625.0, 154 + .dtbclk_mhz = 600.0, 155 155 }, 156 156 { 157 157 .state = 4, ··· 160 160 .phyclk_mhz = 810.0, 161 161 .phyclk_d18_mhz = 667.0, 162 162 .dscclk_mhz = 417.0, 163 - .dtbclk_mhz = 625.0, 163 + .dtbclk_mhz = 600.0, 164 164 }, 165 165 }, 166 166 .num_states = 5, ··· 367 367 clock_limits[i].socclk_mhz; 368 368 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = 369 369 clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; 370 + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = 371 + clock_limits[i].dtbclk_mhz; 370 372 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = 371 373 clk_table->num_entries; 372 374 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels = ··· 380 378 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels = 381 379 clk_table->num_entries; 382 380 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels = 381 + clk_table->num_entries; 382 + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels = 383 383 clk_table->num_entries; 384 384 } 385 385 }
+8 -8
drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
··· 6329 6329 mode_lib->ms.NoOfDPPThisState, 6330 6330 mode_lib->ms.dpte_group_bytes, 6331 6331 s->HostVMInefficiencyFactor, 6332 - mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, 6332 + mode_lib->ms.soc.hostvm_min_page_size_kbytes, 6333 6333 mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); 6334 6334 6335 6335 s->NextMaxVStartup = s->MaxVStartupAllPlanes[j]; ··· 6542 6542 mode_lib->ms.cache_display_cfg.plane.HostVMEnable, 6543 6543 mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, 6544 6544 mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, 6545 - mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, 6545 + mode_lib->ms.soc.hostvm_min_page_size_kbytes, 6546 6546 mode_lib->ms.PDEAndMetaPTEBytesPerFrame[j][k], 6547 6547 mode_lib->ms.MetaRowBytes[j][k], 6548 6548 mode_lib->ms.DPTEBytesPerRow[j][k], ··· 7687 7687 CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; 7688 7688 CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; 7689 7689 CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; 7690 - CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; 7690 + CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; 7691 7691 CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; 7692 7692 CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; 7693 7693 CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = mode_lib->ms.PTEBufferSizeNotExceededPerState; ··· 7957 7957 UseMinimumDCFCLK_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; 7958 7958 UseMinimumDCFCLK_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; 7959 7959 UseMinimumDCFCLK_params->NumberOfActiveSurfaces = mode_lib->ms.num_active_planes; 7960 - UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; 7960 + UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; 7961 7961 UseMinimumDCFCLK_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; 7962 7962 UseMinimumDCFCLK_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; 7963 7963 UseMinimumDCFCLK_params->ImmediateFlipRequirement = s->ImmediateFlipRequiredFinal; ··· 8699 8699 CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; 8700 8700 CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; 8701 8701 CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; 8702 - CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; 8702 + CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; 8703 8703 CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; 8704 8704 CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; 8705 8705 CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = s->dummy_boolean_array[0]; ··· 8805 8805 mode_lib->ms.cache_display_cfg.hw.DPPPerSurface, 8806 8806 locals->dpte_group_bytes, 8807 8807 s->HostVMInefficiencyFactor, 8808 - mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, 8808 + mode_lib->ms.soc.hostvm_min_page_size_kbytes, 8809 8809 mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); 8810 8810 8811 8811 locals->TCalc = 24.0 / locals->DCFCLKDeepSleep; ··· 8995 8995 CalculatePrefetchSchedule_params->GPUVMEnable = mode_lib->ms.cache_display_cfg.plane.GPUVMEnable; 8996 8996 CalculatePrefetchSchedule_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; 8997 8997 CalculatePrefetchSchedule_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; 8998 - CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; 8998 + CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; 8999 8999 CalculatePrefetchSchedule_params->DynamicMetadataEnable = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataEnable[k]; 9000 9000 CalculatePrefetchSchedule_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; 9001 9001 CalculatePrefetchSchedule_params->DynamicMetadataLinesBeforeActiveRequired = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataLinesBeforeActiveRequired[k]; ··· 9240 9240 mode_lib->ms.cache_display_cfg.plane.HostVMEnable, 9241 9241 mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, 9242 9242 mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, 9243 - mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, 9243 + mode_lib->ms.soc.hostvm_min_page_size_kbytes, 9244 9244 locals->PDEAndMetaPTEBytesFrame[k], 9245 9245 locals->MetaRowByte[k], 9246 9246 locals->PixelPTEBytesPerRow[k],
+3 -2
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
··· 425 425 } 426 426 427 427 for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels; i++) { 428 - p->in_states->state_array[i].dtbclk_mhz = 429 - dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz; 428 + if (dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz > 0) 429 + p->in_states->state_array[i].dtbclk_mhz = 430 + dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz; 430 431 } 431 432 432 433 for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels; i++) {
-7
drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c
··· 160 160 161 161 if (pipe_ctx->stream == NULL) 162 162 return false; 163 - /* Count MST hubs once by treating only 1st remote sink in topology as an encoder */ 164 - if (pipe_ctx->stream->link && pipe_ctx->stream->link->remote_sinks[0]) { 165 - return (pipe_ctx->stream_res.hpo_dp_stream_enc && 166 - pipe_ctx->link_res.hpo_dp_link_enc && 167 - dc_is_dp_signal(pipe_ctx->stream->signal) && 168 - (pipe_ctx->stream->link->remote_sinks[0] == pipe_ctx->stream->sink)); 169 - } 170 163 171 164 return (pipe_ctx->stream_res.hpo_dp_stream_enc && 172 165 pipe_ctx->link_res.hpo_dp_link_enc &&
+20
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
··· 1877 1877 int i; 1878 1878 struct dce_hwseq *hws = dc->hwseq; 1879 1879 DC_LOGGER_INIT(dc->ctx->logger); 1880 + unsigned int prev_hubp_count = 0; 1881 + unsigned int hubp_count = 0; 1880 1882 1881 1883 if (resource_is_pipe_topology_changed(dc->current_state, context)) 1882 1884 resource_log_pipe_topology_update(dc, context); ··· 1894 1892 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); 1895 1893 } 1896 1894 } 1895 + } 1896 + 1897 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 1898 + if (dc->current_state->res_ctx.pipe_ctx[i].plane_state) 1899 + prev_hubp_count++; 1900 + if (context->res_ctx.pipe_ctx[i].plane_state) 1901 + hubp_count++; 1902 + } 1903 + 1904 + if (prev_hubp_count == 0 && hubp_count > 0) { 1905 + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) 1906 + dc->res_pool->hubbub->funcs->force_pstate_change_control( 1907 + dc->res_pool->hubbub, true, false); 1908 + udelay(500); 1897 1909 } 1898 1910 1899 1911 /* Set pipe update flags and lock pipes */ ··· 2054 2038 udelay(polling_interval_us); 2055 2039 } 2056 2040 } 2041 + 2042 + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) 2043 + dc->res_pool->hubbub->funcs->force_pstate_change_control( 2044 + dc->res_pool->hubbub, false, false); 2057 2045 2058 2046 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2059 2047 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+97 -41
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
··· 1123 1123 update_state->pg_res_update[PG_HPO] = true; 1124 1124 1125 1125 } 1126 - 1127 - void dcn35_block_power_control(struct dc *dc, 1128 - struct pg_block_update *update_state, bool power_on) 1126 + /** 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 + */ 1141 + void dcn35_hw_block_power_down(struct dc *dc, 1142 + struct pg_block_update *update_state) 1129 1143 { 1130 1144 int i = 0; 1131 1145 struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; ··· 1148 1134 return; 1149 1135 if (dc->debug.ignore_pg) 1150 1136 return; 1137 + 1151 1138 if (update_state->pg_res_update[PG_HPO]) { 1152 1139 if (pg_cntl->funcs->hpo_pg_control) 1153 - pg_cntl->funcs->hpo_pg_control(pg_cntl, power_on); 1140 + pg_cntl->funcs->hpo_pg_control(pg_cntl, false); 1154 1141 } 1155 1142 1156 1143 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1157 1144 if (update_state->pg_pipe_res_update[PG_HUBP][i] && 1158 1145 update_state->pg_pipe_res_update[PG_DPP][i]) { 1159 1146 if (pg_cntl->funcs->hubp_dpp_pg_control) 1160 - pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, power_on); 1147 + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false); 1161 1148 } 1162 - 1149 + } 1150 + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) 1163 1151 if (update_state->pg_pipe_res_update[PG_DSC][i]) { 1164 1152 if (pg_cntl->funcs->dsc_pg_control) 1165 - pg_cntl->funcs->dsc_pg_control(pg_cntl, i, power_on); 1153 + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false); 1166 1154 } 1167 1155 1168 - if (update_state->pg_pipe_res_update[PG_MPCC][i]) { 1169 - if (pg_cntl->funcs->mpcc_pg_control) 1170 - pg_cntl->funcs->mpcc_pg_control(pg_cntl, i, power_on); 1171 - } 1172 - 1173 - if (update_state->pg_pipe_res_update[PG_OPP][i]) { 1174 - if (pg_cntl->funcs->opp_pg_control) 1175 - pg_cntl->funcs->opp_pg_control(pg_cntl, i, power_on); 1176 - } 1177 - 1178 - if (update_state->pg_pipe_res_update[PG_OPTC][i]) { 1179 - if (pg_cntl->funcs->optc_pg_control) 1180 - pg_cntl->funcs->optc_pg_control(pg_cntl, i, power_on); 1181 - } 1182 - } 1183 - 1184 - if (update_state->pg_res_update[PG_DWB]) { 1185 - if (pg_cntl->funcs->dwb_pg_control) 1186 - pg_cntl->funcs->dwb_pg_control(pg_cntl, power_on); 1187 - } 1188 1156 1189 1157 /*this will need all the clients to unregister optc interruts let dmubfw handle this*/ 1190 1158 if (pg_cntl->funcs->plane_otg_pg_control) 1191 - pg_cntl->funcs->plane_otg_pg_control(pg_cntl, power_on); 1159 + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false); 1160 + 1161 + //domain22, 23, 25 currently always on. 1192 1162 1193 1163 } 1164 + /** 1165 + * power up sequence 1166 + * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED 1167 + * ONO Region 2, DCPG 24: mpc opp optc dwb 1168 + * ONO Region 5, DCPG 16: dsc0 1169 + * ONO Region 7, DCPG 17: dsc1 1170 + * ONO Region 9, DCPG 18: dsc2 1171 + * ONO Region 11, DCPG 19: dsc3 1172 + * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit 1173 + * ONO Region 4, DCPG 0: dchubp0, dpp0 1174 + * ONO Region 6, DCPG 1: dchubp1, dpp1 1175 + * ONO Region 8, DCPG 2: dchubp2, dpp2 1176 + * ONO Region 10, DCPG 3: dchubp3, dpp3 1177 + * ONO Region 3, DCPG 25: hpo - SKIPPED 1178 + */ 1179 + void dcn35_hw_block_power_up(struct dc *dc, 1180 + struct pg_block_update *update_state) 1181 + { 1182 + int i = 0; 1183 + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; 1194 1184 1185 + if (!pg_cntl) 1186 + return; 1187 + if (dc->debug.ignore_pg) 1188 + return; 1189 + //domain22, 23, 25 currently always on. 1190 + /*this will need all the clients to unregister optc interruts let dmubfw handle this*/ 1191 + if (pg_cntl->funcs->plane_otg_pg_control) 1192 + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true); 1193 + 1194 + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) 1195 + if (update_state->pg_pipe_res_update[PG_DSC][i]) { 1196 + if (pg_cntl->funcs->dsc_pg_control) 1197 + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true); 1198 + } 1199 + 1200 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 1201 + if (update_state->pg_pipe_res_update[PG_HUBP][i] && 1202 + update_state->pg_pipe_res_update[PG_DPP][i]) { 1203 + if (pg_cntl->funcs->hubp_dpp_pg_control) 1204 + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true); 1205 + } 1206 + } 1207 + if (update_state->pg_res_update[PG_HPO]) { 1208 + if (pg_cntl->funcs->hpo_pg_control) 1209 + pg_cntl->funcs->hpo_pg_control(pg_cntl, true); 1210 + } 1211 + } 1195 1212 void dcn35_root_clock_control(struct dc *dc, 1196 1213 struct pg_block_update *update_state, bool power_on) 1197 1214 { ··· 1231 1186 1232 1187 if (!pg_cntl) 1233 1188 return; 1234 - 1235 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 1236 - if (update_state->pg_pipe_res_update[PG_HUBP][i] && 1237 - update_state->pg_pipe_res_update[PG_DPP][i]) { 1238 - if (dc->hwseq->funcs.dpp_root_clock_control) 1239 - dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); 1189 + /*enable root clock first when power up*/ 1190 + if (power_on) 1191 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 1192 + if (update_state->pg_pipe_res_update[PG_HUBP][i] && 1193 + update_state->pg_pipe_res_update[PG_DPP][i]) { 1194 + if (dc->hwseq->funcs.dpp_root_clock_control) 1195 + dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); 1196 + } 1240 1197 } 1241 - 1198 + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { 1242 1199 if (update_state->pg_pipe_res_update[PG_DSC][i]) { 1243 1200 if (power_on) { 1244 1201 if (dc->res_pool->dccg->funcs->enable_dsc) ··· 1251 1204 } 1252 1205 } 1253 1206 } 1207 + /*disable root clock first when power down*/ 1208 + if (!power_on) 1209 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 1210 + if (update_state->pg_pipe_res_update[PG_HUBP][i] && 1211 + update_state->pg_pipe_res_update[PG_DPP][i]) { 1212 + if (dc->hwseq->funcs.dpp_root_clock_control) 1213 + dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); 1214 + } 1215 + } 1254 1216 } 1255 1217 1256 1218 void dcn35_prepare_bandwidth( ··· 1273 1217 1274 1218 if (dc->hwss.root_clock_control) 1275 1219 dc->hwss.root_clock_control(dc, &pg_update_state, true); 1276 - 1277 - if (dc->hwss.block_power_control) 1278 - dc->hwss.block_power_control(dc, &pg_update_state, true); 1220 + /*power up required HW block*/ 1221 + if (dc->hwss.hw_block_power_up) 1222 + dc->hwss.hw_block_power_up(dc, &pg_update_state); 1279 1223 } 1280 1224 1281 1225 dcn20_prepare_bandwidth(dc, context); ··· 1291 1235 1292 1236 if (dc->hwss.calc_blocks_to_gate) { 1293 1237 dc->hwss.calc_blocks_to_gate(dc, context, &pg_update_state); 1294 - 1295 - if (dc->hwss.block_power_control) 1296 - dc->hwss.block_power_control(dc, &pg_update_state, false); 1238 + /*try to power down unused block*/ 1239 + if (dc->hwss.hw_block_power_down) 1240 + dc->hwss.hw_block_power_down(dc, &pg_update_state); 1297 1241 1298 1242 if (dc->hwss.root_clock_control) 1299 1243 dc->hwss.root_clock_control(dc, &pg_update_state, false);
+4 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
··· 63 63 struct pg_block_update *update_state); 64 64 void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, 65 65 struct pg_block_update *update_state); 66 - void dcn35_block_power_control(struct dc *dc, 67 - struct pg_block_update *update_state, bool power_on); 66 + void dcn35_hw_block_power_up(struct dc *dc, 67 + struct pg_block_update *update_state); 68 + void dcn35_hw_block_power_down(struct dc *dc, 69 + struct pg_block_update *update_state); 68 70 void dcn35_root_clock_control(struct dc *dc, 69 71 struct pg_block_update *update_state, bool power_on); 70 72
+4 -2
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
··· 414 414 struct pg_block_update *update_state); 415 415 void (*calc_blocks_to_ungate)(struct dc *dc, struct dc_state *context, 416 416 struct pg_block_update *update_state); 417 - void (*block_power_control)(struct dc *dc, 418 - struct pg_block_update *update_state, bool power_on); 417 + void (*hw_block_power_up)(struct dc *dc, 418 + struct pg_block_update *update_state); 419 + void (*hw_block_power_down)(struct dc *dc, 420 + struct pg_block_update *update_state); 419 421 void (*root_clock_control)(struct dc *dc, 420 422 struct pg_block_update *update_state, bool power_on); 421 423 void (*set_idle_state)(const struct dc *dc, bool allow_idle);
+2 -2
drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
··· 59 59 struct dp_dto_params { 60 60 int otg_inst; 61 61 enum signal_type signal; 62 - long long pixclk_hz; 63 - long long refclk_hz; 62 + uint64_t pixclk_hz; 63 + uint64_t refclk_hz; 64 64 }; 65 65 66 66 enum pixel_rate_div {
+2
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
··· 717 717 .disable_dcc = DCC_ENABLE, 718 718 .disable_dpp_power_gate = true, 719 719 .disable_hubp_power_gate = true, 720 + .disable_optc_power_gate = true, /*should the same as above two*/ 721 + .disable_hpo_power_gate = true, /*dmubfw force domain25 on*/ 720 722 .disable_clock_gate = false, 721 723 .disable_dsc_power_gate = true, 722 724 .vsr_support = true,
+21
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
··· 150 150 DMUB_MEMORY_ACCESS_DMA 151 151 }; 152 152 153 + /* enum dmub_power_state type - to track DC power state in dmub_srv */ 154 + enum dmub_srv_power_state_type { 155 + DMUB_POWER_STATE_UNDEFINED = 0, 156 + DMUB_POWER_STATE_D0 = 1, 157 + DMUB_POWER_STATE_D3 = 8 158 + }; 159 + 153 160 /** 154 161 * struct dmub_region - dmub hw memory region 155 162 * @base: base address for region, must be 256 byte aligned ··· 492 485 /* Feature capabilities reported by fw */ 493 486 struct dmub_feature_caps feature_caps; 494 487 struct dmub_visual_confirm_color visual_confirm_color; 488 + 489 + enum dmub_srv_power_state_type power_state; 495 490 }; 496 491 497 492 /** ··· 897 888 * void 898 889 */ 899 890 void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index); 891 + 892 + /** 893 + * dmub_srv_set_power_state() - Track DC power state in dmub_srv 894 + * @dmub: The dmub service 895 + * @power_state: DC power state setting 896 + * 897 + * Store DC power state in dmub_srv. If dmub_srv is in D3, then don't send messages to DMUB 898 + * 899 + * Return: 900 + * void 901 + */ 902 + void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state); 900 903 901 904 #if defined(__cplusplus) 902 905 }
+15
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
··· 713 713 dmub->hw_funcs.reset_release(dmub); 714 714 715 715 dmub->hw_init = true; 716 + dmub->power_state = DMUB_POWER_STATE_D0; 716 717 717 718 return DMUB_STATUS_OK; 718 719 } ··· 767 766 if (!dmub->hw_init) 768 767 return DMUB_STATUS_INVALID; 769 768 769 + if (dmub->power_state != DMUB_POWER_STATE_D0) 770 + return DMUB_STATUS_INVALID; 771 + 770 772 if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity || 771 773 dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) { 772 774 return DMUB_STATUS_HW_FAILURE; ··· 786 782 struct dmub_rb flush_rb; 787 783 788 784 if (!dmub->hw_init) 785 + return DMUB_STATUS_INVALID; 786 + 787 + if (dmub->power_state != DMUB_POWER_STATE_D0) 789 788 return DMUB_STATUS_INVALID; 790 789 791 790 /** ··· 1106 1099 addr, 1107 1100 subvp_index); 1108 1101 } 1102 + } 1103 + 1104 + void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state) 1105 + { 1106 + if (!dmub || !dmub->hw_init) 1107 + return; 1108 + 1109 + dmub->power_state = dmub_srv_power_state; 1109 1110 }
+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 + 72 84 /* 73 85 * @brief 74 86 * Initialization routines
+2
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
··· 839 839 ((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) || 840 840 (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07))) 841 841 isPSRSUSupported = false; 842 + else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03) 843 + isPSRSUSupported = false; 842 844 else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1) 843 845 isPSRSUSupported = true; 844 846 }
+2 -1
drivers/gpu/drm/amd/include/mes_v11_api_def.h
··· 572 572 struct { 573 573 uint32_t single_memop : 1; /* SQ_DEBUG.single_memop */ 574 574 uint32_t single_alu_op : 1; /* SQ_DEBUG.single_alu_op */ 575 - uint32_t reserved : 30; 575 + uint32_t reserved : 29; 576 + uint32_t process_ctx_flush : 1; 576 577 }; 577 578 uint32_t u32all; 578 579 } flags;
+10
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
··· 616 616 enable ? "enable" : "disable", ret); 617 617 } 618 618 619 + void amdgpu_dpm_enable_vpe(struct amdgpu_device *adev, bool enable) 620 + { 621 + int ret = 0; 622 + 623 + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VPE, !enable); 624 + if (ret) 625 + DRM_ERROR("Dpm %s vpe failed, ret = %d.\n", 626 + enable ? "enable" : "disable", ret); 627 + } 628 + 619 629 int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 620 630 { 621 631 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+1
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
··· 445 445 void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); 446 446 void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); 447 447 void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); 448 + void amdgpu_dpm_enable_vpe(struct amdgpu_device *adev, bool enable); 448 449 int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); 449 450 int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable); 450 451 int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size);
+1 -3
drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c
··· 2735 2735 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 2736 2736 &non_clock_info_array->nonClockInfo[non_clock_array_index]; 2737 2737 ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL); 2738 - if (ps == NULL) { 2739 - kfree(adev->pm.dpm.ps); 2738 + if (ps == NULL) 2740 2739 return -ENOMEM; 2741 - } 2742 2740 adev->pm.dpm.ps[i].ps_priv = ps; 2743 2741 k = 0; 2744 2742 idx = (u8 *)&power_state->v2.clockInfoIndex[0];
+13 -39
drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c
··· 272 272 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 273 273 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 274 274 dep_table); 275 - if (ret) { 276 - amdgpu_free_extended_power_table(adev); 275 + if (ret) 277 276 return ret; 278 - } 279 277 } 280 278 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 281 279 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) ··· 281 283 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 282 284 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 283 285 dep_table); 284 - if (ret) { 285 - amdgpu_free_extended_power_table(adev); 286 + if (ret) 286 287 return ret; 287 - } 288 288 } 289 289 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 290 290 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) ··· 290 294 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 291 295 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 292 296 dep_table); 293 - if (ret) { 294 - amdgpu_free_extended_power_table(adev); 297 + if (ret) 295 298 return ret; 296 - } 297 299 } 298 300 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 299 301 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) ··· 299 305 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 300 306 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 301 307 dep_table); 302 - if (ret) { 303 - amdgpu_free_extended_power_table(adev); 308 + if (ret) 304 309 return ret; 305 - } 306 310 } 307 311 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 308 312 ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = ··· 331 339 kcalloc(psl->ucNumEntries, 332 340 sizeof(struct amdgpu_phase_shedding_limits_entry), 333 341 GFP_KERNEL); 334 - if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 335 - amdgpu_free_extended_power_table(adev); 342 + if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) 336 343 return -ENOMEM; 337 - } 338 344 339 345 entry = &psl->entries[0]; 340 346 for (i = 0; i < psl->ucNumEntries; i++) { ··· 373 383 ATOM_PPLIB_CAC_Leakage_Record *entry; 374 384 u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); 375 385 adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 376 - if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { 377 - amdgpu_free_extended_power_table(adev); 386 + if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) 378 387 return -ENOMEM; 379 - } 380 388 entry = &cac_table->entries[0]; 381 389 for (i = 0; i < cac_table->ucNumEntries; i++) { 382 390 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { ··· 426 438 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); 427 439 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 428 440 kzalloc(size, GFP_KERNEL); 429 - if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 430 - amdgpu_free_extended_power_table(adev); 441 + if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) 431 442 return -ENOMEM; 432 - } 433 443 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 434 444 limits->numEntries; 435 445 entry = &limits->entries[0]; ··· 479 493 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); 480 494 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 481 495 kzalloc(size, GFP_KERNEL); 482 - if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 483 - amdgpu_free_extended_power_table(adev); 496 + if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) 484 497 return -ENOMEM; 485 - } 486 498 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 487 499 limits->numEntries; 488 500 entry = &limits->entries[0]; ··· 509 525 sizeof(struct amdgpu_clock_voltage_dependency_entry); 510 526 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 511 527 kzalloc(size, GFP_KERNEL); 512 - if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 513 - amdgpu_free_extended_power_table(adev); 528 + if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) 514 529 return -ENOMEM; 515 - } 516 530 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 517 531 limits->numEntries; 518 532 entry = &limits->entries[0]; ··· 530 548 le16_to_cpu(ext_hdr->usPPMTableOffset)); 531 549 adev->pm.dpm.dyn_state.ppm_table = 532 550 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); 533 - if (!adev->pm.dpm.dyn_state.ppm_table) { 534 - amdgpu_free_extended_power_table(adev); 551 + if (!adev->pm.dpm.dyn_state.ppm_table) 535 552 return -ENOMEM; 536 - } 537 553 adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 538 554 adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 539 555 le16_to_cpu(ppm->usCpuCoreNumber); ··· 563 583 sizeof(struct amdgpu_clock_voltage_dependency_entry); 564 584 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 565 585 kzalloc(size, GFP_KERNEL); 566 - if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 567 - amdgpu_free_extended_power_table(adev); 586 + if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) 568 587 return -ENOMEM; 569 - } 570 588 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 571 589 limits->numEntries; 572 590 entry = &limits->entries[0]; ··· 584 606 ATOM_PowerTune_Table *pt; 585 607 adev->pm.dpm.dyn_state.cac_tdp_table = 586 608 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); 587 - if (!adev->pm.dpm.dyn_state.cac_tdp_table) { 588 - amdgpu_free_extended_power_table(adev); 609 + if (!adev->pm.dpm.dyn_state.cac_tdp_table) 589 610 return -ENOMEM; 590 - } 591 611 if (rev > 0) { 592 612 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 593 613 (mode_info->atom_context->bios + data_offset + ··· 621 645 ret = amdgpu_parse_clk_voltage_dep_table( 622 646 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, 623 647 dep_table); 624 - if (ret) { 625 - kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); 648 + if (ret) 626 649 return ret; 627 - } 628 650 } 629 651 } 630 652
+2 -3
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
··· 7379 7379 kcalloc(4, 7380 7380 sizeof(struct amdgpu_clock_voltage_dependency_entry), 7381 7381 GFP_KERNEL); 7382 - if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { 7383 - amdgpu_free_extended_power_table(adev); 7382 + if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) 7384 7383 return -ENOMEM; 7385 - } 7384 + 7386 7385 adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; 7387 7386 adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; 7388 7387 adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
+208
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
··· 1322 1322 return ret; 1323 1323 } 1324 1324 1325 + /** 1326 + * smu_wbrf_handle_exclusion_ranges - consume the wbrf exclusion ranges 1327 + * 1328 + * @smu: smu_context pointer 1329 + * 1330 + * Retrieve the wbrf exclusion ranges and send them to PMFW for proper handling. 1331 + * Returns 0 on success, error on failure. 1332 + */ 1333 + static int smu_wbrf_handle_exclusion_ranges(struct smu_context *smu) 1334 + { 1335 + struct wbrf_ranges_in_out wbrf_exclusion = {0}; 1336 + struct freq_band_range *wifi_bands = wbrf_exclusion.band_list; 1337 + struct amdgpu_device *adev = smu->adev; 1338 + uint32_t num_of_wbrf_ranges = MAX_NUM_OF_WBRF_RANGES; 1339 + uint64_t start, end; 1340 + int ret, i, j; 1341 + 1342 + ret = amd_wbrf_retrieve_freq_band(adev->dev, &wbrf_exclusion); 1343 + if (ret) { 1344 + dev_err(adev->dev, "Failed to retrieve exclusion ranges!\n"); 1345 + return ret; 1346 + } 1347 + 1348 + /* 1349 + * The exclusion ranges array we got might be filled with holes and duplicate 1350 + * entries. For example: 1351 + * {(2400, 2500), (0, 0), (6882, 6962), (2400, 2500), (0, 0), (6117, 6189), (0, 0)...} 1352 + * We need to do some sortups to eliminate those holes and duplicate entries. 1353 + * Expected output: {(2400, 2500), (6117, 6189), (6882, 6962), (0, 0)...} 1354 + */ 1355 + for (i = 0; i < num_of_wbrf_ranges; i++) { 1356 + start = wifi_bands[i].start; 1357 + end = wifi_bands[i].end; 1358 + 1359 + /* get the last valid entry to fill the intermediate hole */ 1360 + if (!start && !end) { 1361 + for (j = num_of_wbrf_ranges - 1; j > i; j--) 1362 + if (wifi_bands[j].start && wifi_bands[j].end) 1363 + break; 1364 + 1365 + /* no valid entry left */ 1366 + if (j <= i) 1367 + break; 1368 + 1369 + start = wifi_bands[i].start = wifi_bands[j].start; 1370 + end = wifi_bands[i].end = wifi_bands[j].end; 1371 + wifi_bands[j].start = 0; 1372 + wifi_bands[j].end = 0; 1373 + num_of_wbrf_ranges = j; 1374 + } 1375 + 1376 + /* eliminate duplicate entries */ 1377 + for (j = i + 1; j < num_of_wbrf_ranges; j++) { 1378 + if ((wifi_bands[j].start == start) && (wifi_bands[j].end == end)) { 1379 + wifi_bands[j].start = 0; 1380 + wifi_bands[j].end = 0; 1381 + } 1382 + } 1383 + } 1384 + 1385 + /* Send the sorted wifi_bands to PMFW */ 1386 + ret = smu_set_wbrf_exclusion_ranges(smu, wifi_bands); 1387 + /* Try to set the wifi_bands again */ 1388 + if (unlikely(ret == -EBUSY)) { 1389 + mdelay(5); 1390 + ret = smu_set_wbrf_exclusion_ranges(smu, wifi_bands); 1391 + } 1392 + 1393 + return ret; 1394 + } 1395 + 1396 + /** 1397 + * smu_wbrf_event_handler - handle notify events 1398 + * 1399 + * @nb: notifier block 1400 + * @action: event type 1401 + * @_arg: event data 1402 + * 1403 + * Calls relevant amdgpu function in response to wbrf event 1404 + * notification from kernel. 1405 + */ 1406 + static int smu_wbrf_event_handler(struct notifier_block *nb, 1407 + unsigned long action, void *_arg) 1408 + { 1409 + struct smu_context *smu = container_of(nb, struct smu_context, wbrf_notifier); 1410 + 1411 + switch (action) { 1412 + case WBRF_CHANGED: 1413 + schedule_delayed_work(&smu->wbrf_delayed_work, 1414 + msecs_to_jiffies(SMU_WBRF_EVENT_HANDLING_PACE)); 1415 + break; 1416 + default: 1417 + return NOTIFY_DONE; 1418 + } 1419 + 1420 + return NOTIFY_OK; 1421 + } 1422 + 1423 + /** 1424 + * smu_wbrf_delayed_work_handler - callback on delayed work timer expired 1425 + * 1426 + * @work: struct work_struct pointer 1427 + * 1428 + * Flood is over and driver will consume the latest exclusion ranges. 1429 + */ 1430 + static void smu_wbrf_delayed_work_handler(struct work_struct *work) 1431 + { 1432 + struct smu_context *smu = container_of(work, struct smu_context, wbrf_delayed_work.work); 1433 + 1434 + smu_wbrf_handle_exclusion_ranges(smu); 1435 + } 1436 + 1437 + /** 1438 + * smu_wbrf_support_check - check wbrf support 1439 + * 1440 + * @smu: smu_context pointer 1441 + * 1442 + * Verifies the ACPI interface whether wbrf is supported. 1443 + */ 1444 + static void smu_wbrf_support_check(struct smu_context *smu) 1445 + { 1446 + struct amdgpu_device *adev = smu->adev; 1447 + 1448 + smu->wbrf_supported = smu_is_asic_wbrf_supported(smu) && amdgpu_wbrf && 1449 + acpi_amd_wbrf_supported_consumer(adev->dev); 1450 + 1451 + if (smu->wbrf_supported) 1452 + dev_info(adev->dev, "RF interference mitigation is supported\n"); 1453 + } 1454 + 1455 + /** 1456 + * smu_wbrf_init - init driver wbrf support 1457 + * 1458 + * @smu: smu_context pointer 1459 + * 1460 + * Verifies the AMD ACPI interfaces and registers with the wbrf 1461 + * notifier chain if wbrf feature is supported. 1462 + * Returns 0 on success, error on failure. 1463 + */ 1464 + static int smu_wbrf_init(struct smu_context *smu) 1465 + { 1466 + int ret; 1467 + 1468 + if (!smu->wbrf_supported) 1469 + return 0; 1470 + 1471 + INIT_DELAYED_WORK(&smu->wbrf_delayed_work, smu_wbrf_delayed_work_handler); 1472 + 1473 + smu->wbrf_notifier.notifier_call = smu_wbrf_event_handler; 1474 + ret = amd_wbrf_register_notifier(&smu->wbrf_notifier); 1475 + if (ret) 1476 + return ret; 1477 + 1478 + /* 1479 + * Some wifiband exclusion ranges may be already there 1480 + * before our driver loaded. To make sure our driver 1481 + * is awared of those exclusion ranges. 1482 + */ 1483 + schedule_delayed_work(&smu->wbrf_delayed_work, 1484 + msecs_to_jiffies(SMU_WBRF_EVENT_HANDLING_PACE)); 1485 + 1486 + return 0; 1487 + } 1488 + 1489 + /** 1490 + * smu_wbrf_fini - tear down driver wbrf support 1491 + * 1492 + * @smu: smu_context pointer 1493 + * 1494 + * Unregisters with the wbrf notifier chain. 1495 + */ 1496 + static void smu_wbrf_fini(struct smu_context *smu) 1497 + { 1498 + if (!smu->wbrf_supported) 1499 + return; 1500 + 1501 + amd_wbrf_unregister_notifier(&smu->wbrf_notifier); 1502 + 1503 + cancel_delayed_work_sync(&smu->wbrf_delayed_work); 1504 + } 1505 + 1325 1506 static int smu_smc_hw_setup(struct smu_context *smu) 1326 1507 { 1327 1508 struct smu_feature *feature = &smu->smu_feature; ··· 1594 1413 ret = smu_run_btc(smu); 1595 1414 if (ret) 1596 1415 return ret; 1416 + 1417 + /* Enable UclkShadow on wbrf supported */ 1418 + if (smu->wbrf_supported) { 1419 + ret = smu_enable_uclk_shadow(smu, true); 1420 + if (ret) { 1421 + dev_err(adev->dev, "Failed to enable UclkShadow feature to support wbrf!\n"); 1422 + return ret; 1423 + } 1424 + } 1597 1425 1598 1426 /* 1599 1427 * With SCPM enabled, these actions(and relevant messages) are ··· 1702 1512 */ 1703 1513 ret = smu_set_min_dcef_deep_sleep(smu, 1704 1514 smu->smu_table.boot_values.dcefclk / 100); 1515 + if (ret) { 1516 + dev_err(adev->dev, "Error setting min deepsleep dcefclk\n"); 1517 + return ret; 1518 + } 1519 + 1520 + /* Init wbrf support. Properly setup the notifier */ 1521 + ret = smu_wbrf_init(smu); 1522 + if (ret) 1523 + dev_err(adev->dev, "Error during wbrf init call\n"); 1705 1524 1706 1525 return ret; 1707 1526 } ··· 1765 1566 dev_err(adev->dev, "SMC engine is not correctly up!\n"); 1766 1567 return ret; 1767 1568 } 1569 + 1570 + /* 1571 + * Check whether wbrf is supported. This needs to be done 1572 + * before SMU setup starts since part of SMU configuration 1573 + * relies on this. 1574 + */ 1575 + smu_wbrf_support_check(smu); 1768 1576 1769 1577 if (smu->is_apu) { 1770 1578 ret = smu_set_gfx_imu_enable(smu); ··· 1938 1732 { 1939 1733 struct amdgpu_device *adev = smu->adev; 1940 1734 int ret = 0; 1735 + 1736 + smu_wbrf_fini(smu); 1941 1737 1942 1738 cancel_work_sync(&smu->throttling_logging_work); 1943 1739 cancel_work_sync(&smu->interrupt_work);
+42
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
··· 22 22 #ifndef __AMDGPU_SMU_H__ 23 23 #define __AMDGPU_SMU_H__ 24 24 25 + #include <linux/acpi_amd_wbrf.h> 26 + #include <linux/units.h> 27 + 25 28 #include "amdgpu.h" 26 29 #include "kgd_pp_interface.h" 27 30 #include "dm_pp_interface.h" ··· 321 318 SMU_TABLE_PACE, 322 319 SMU_TABLE_ECCINFO, 323 320 SMU_TABLE_COMBO_PPTABLE, 321 + SMU_TABLE_WIFIBAND, 324 322 SMU_TABLE_COUNT, 325 323 }; 326 324 ··· 475 471 476 472 #define WORKLOAD_POLICY_MAX 7 477 473 474 + /* 475 + * Configure wbrf event handling pace as there can be only one 476 + * event processed every SMU_WBRF_EVENT_HANDLING_PACE ms. 477 + */ 478 + #define SMU_WBRF_EVENT_HANDLING_PACE 10 479 + 478 480 struct smu_context { 479 481 struct amdgpu_device *adev; 480 482 struct amdgpu_irq_src irq_source; ··· 580 570 struct delayed_work swctf_delayed_work; 581 571 582 572 enum pp_xgmi_plpd_mode plpd_mode; 573 + 574 + /* data structures for wbrf feature support */ 575 + bool wbrf_supported; 576 + struct notifier_block wbrf_notifier; 577 + struct delayed_work wbrf_delayed_work; 583 578 }; 584 579 585 580 struct i2c_adapter; ··· 1390 1375 * @notify_rlc_state: Notify RLC power state to SMU. 1391 1376 */ 1392 1377 int (*notify_rlc_state)(struct smu_context *smu, bool en); 1378 + 1379 + /** 1380 + * @is_asic_wbrf_supported: check whether PMFW supports the wbrf feature 1381 + */ 1382 + bool (*is_asic_wbrf_supported)(struct smu_context *smu); 1383 + 1384 + /** 1385 + * @enable_uclk_shadow: Enable the uclk shadow feature on wbrf supported 1386 + */ 1387 + int (*enable_uclk_shadow)(struct smu_context *smu, bool enable); 1388 + 1389 + /** 1390 + * @set_wbrf_exclusion_ranges: notify SMU the wifi bands occupied 1391 + */ 1392 + int (*set_wbrf_exclusion_ranges)(struct smu_context *smu, 1393 + struct freq_band_range *exclusion_ranges); 1393 1394 }; 1394 1395 1395 1396 typedef enum { ··· 1531 1500 (u8 *)(src) + __src_offset, \ 1532 1501 __dst_size); \ 1533 1502 }) 1503 + 1504 + typedef struct { 1505 + uint16_t LowFreq; 1506 + uint16_t HighFreq; 1507 + } WifiOneBand_t; 1508 + 1509 + typedef struct { 1510 + uint32_t WifiBandEntryNum; 1511 + WifiOneBand_t WifiBandEntry[11]; 1512 + uint32_t MmHubPadding[8]; 1513 + } WifiBandEntryTable_t; 1534 1514 1535 1515 #if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4) 1536 1516 int smu_get_power_limit(void *handle,
+2 -1
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
··· 1615 1615 #define TABLE_I2C_COMMANDS 9 1616 1616 #define TABLE_DRIVER_INFO 10 1617 1617 #define TABLE_ECCINFO 11 1618 - #define TABLE_COUNT 12 1618 + #define TABLE_WIFIBAND 12 1619 + #define TABLE_COUNT 13 1619 1620 1620 1621 //IH Interupt ID 1621 1622 #define IH_INTERRUPT_ID_TO_DRIVER 0xFE
+2 -1
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
··· 1605 1605 #define TABLE_I2C_COMMANDS 9 1606 1606 #define TABLE_DRIVER_INFO 10 1607 1607 #define TABLE_ECCINFO 11 1608 - #define TABLE_COUNT 12 1608 + #define TABLE_WIFIBAND 12 1609 + #define TABLE_COUNT 13 1609 1610 1610 1611 //IH Interupt ID 1611 1612 #define IH_INTERRUPT_ID_TO_DRIVER 0xFE
-5
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h
··· 24 24 #ifndef SMU14_DRIVER_IF_V14_0_0_H 25 25 #define SMU14_DRIVER_IF_V14_0_0_H 26 26 27 - // *** IMPORTANT *** 28 - // SMU TEAM: Always increment the interface version if 29 - // any structure is changed in this file 30 - #define PMFW_DRIVER_IF_VERSION 7 31 - 32 27 typedef struct { 33 28 int32_t value; 34 29 uint32_t numFractionalBits;
+2 -3
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
··· 138 138 #define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4A 139 139 #define PPSMC_MSG_SetPriorityDeltaGain 0x4B 140 140 #define PPSMC_MSG_AllowIHHostInterrupt 0x4C 141 - 142 141 #define PPSMC_MSG_DALNotPresent 0x4E 143 - 144 - #define PPSMC_Message_Count 0x4F 142 + #define PPSMC_MSG_EnableUCLKShadow 0x51 143 + #define PPSMC_Message_Count 0x52 145 144 146 145 //Debug Dump Message 147 146 #define DEBUGSMC_MSG_TestMessage 0x1
+2 -1
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
··· 134 134 #define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4A 135 135 #define PPSMC_MSG_SetPriorityDeltaGain 0x4B 136 136 #define PPSMC_MSG_AllowIHHostInterrupt 0x4C 137 - #define PPSMC_Message_Count 0x4D 137 + #define PPSMC_MSG_EnableUCLKShadow 0x51 138 + #define PPSMC_Message_Count 0x52 138 139 139 140 #endif
+2 -1
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
··· 260 260 __SMU_DUMMY_MAP(PowerDownUmsch), \ 261 261 __SMU_DUMMY_MAP(SetSoftMaxVpe), \ 262 262 __SMU_DUMMY_MAP(SetSoftMinVpe), \ 263 - __SMU_DUMMY_MAP(GetMetricsVersion), 263 + __SMU_DUMMY_MAP(GetMetricsVersion), \ 264 + __SMU_DUMMY_MAP(EnableUCLKShadow), 264 265 265 266 #undef __SMU_DUMMY_MAP 266 267 #define __SMU_DUMMY_MAP(type) SMU_MSG_##type
+4 -4
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
··· 212 212 213 213 bool smu_v13_0_baco_is_support(struct smu_context *smu); 214 214 215 - enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu); 216 - 217 - int smu_v13_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state); 218 - 219 215 int smu_v13_0_baco_enter(struct smu_context *smu); 220 216 int smu_v13_0_baco_exit(struct smu_context *smu); 221 217 ··· 294 298 295 299 int smu_v13_0_disable_pmfw_state(struct smu_context *smu); 296 300 301 + int smu_v13_0_enable_uclk_shadow(struct smu_context *smu, bool enable); 302 + 303 + int smu_v13_0_set_wbrf_exclusion_ranges(struct smu_context *smu, 304 + struct freq_band_range *exclusion_ranges); 297 305 #endif 298 306 #endif
+1 -1
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
··· 26 26 #include "amdgpu_smu.h" 27 27 28 28 #define SMU14_DRIVER_IF_VERSION_INV 0xFFFFFFFF 29 + #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7 29 30 #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x1 30 - #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x6 31 31 32 32 #define FEATURE_MASK(feature) (1ULL << feature) 33 33
-2
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
··· 2407 2407 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, 2408 2408 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, 2409 2409 .baco_is_support = smu_v11_0_baco_is_support, 2410 - .baco_get_state = smu_v11_0_baco_get_state, 2411 - .baco_set_state = smu_v11_0_baco_set_state, 2412 2410 .baco_enter = smu_v11_0_baco_enter, 2413 2411 .baco_exit = smu_v11_0_baco_exit, 2414 2412 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
-2
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
··· 3537 3537 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, 3538 3538 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, 3539 3539 .baco_is_support = smu_v11_0_baco_is_support, 3540 - .baco_get_state = smu_v11_0_baco_get_state, 3541 - .baco_set_state = smu_v11_0_baco_set_state, 3542 3540 .baco_enter = navi10_baco_enter, 3543 3541 .baco_exit = navi10_baco_exit, 3544 3542 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
-2
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
··· 4428 4428 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, 4429 4429 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, 4430 4430 .baco_is_support = smu_v11_0_baco_is_support, 4431 - .baco_get_state = smu_v11_0_baco_get_state, 4432 - .baco_set_state = smu_v11_0_baco_set_state, 4433 4431 .baco_enter = sienna_cichlid_baco_enter, 4434 4432 .baco_exit = sienna_cichlid_baco_exit, 4435 4433 .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported,
+68 -21
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
··· 2221 2221 return 0; 2222 2222 } 2223 2223 2224 - bool smu_v13_0_baco_is_support(struct smu_context *smu) 2225 - { 2226 - struct smu_baco_context *smu_baco = &smu->smu_baco; 2227 - 2228 - if (amdgpu_sriov_vf(smu->adev) || 2229 - !smu_baco->platform_support) 2230 - return false; 2231 - 2232 - /* return true if ASIC is in BACO state already */ 2233 - if (smu_v13_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) 2234 - return true; 2235 - 2236 - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && 2237 - !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) 2238 - return false; 2239 - 2240 - return true; 2241 - } 2242 - 2243 - enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu) 2224 + static enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu) 2244 2225 { 2245 2226 struct smu_baco_context *smu_baco = &smu->smu_baco; 2246 2227 2247 2228 return smu_baco->state; 2248 2229 } 2249 2230 2250 - int smu_v13_0_baco_set_state(struct smu_context *smu, 2231 + static int smu_v13_0_baco_set_state(struct smu_context *smu, 2251 2232 enum smu_baco_state state) 2252 2233 { 2253 2234 struct smu_baco_context *smu_baco = &smu->smu_baco; ··· 2260 2279 smu_baco->state = state; 2261 2280 2262 2281 return ret; 2282 + } 2283 + 2284 + bool smu_v13_0_baco_is_support(struct smu_context *smu) 2285 + { 2286 + struct smu_baco_context *smu_baco = &smu->smu_baco; 2287 + 2288 + if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) 2289 + return false; 2290 + 2291 + /* return true if ASIC is in BACO state already */ 2292 + if (smu_v13_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) 2293 + return true; 2294 + 2295 + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && 2296 + !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) 2297 + return false; 2298 + 2299 + return true; 2263 2300 } 2264 2301 2265 2302 int smu_v13_0_baco_enter(struct smu_context *smu) ··· 2506 2507 (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); 2507 2508 2508 2509 return ret == 0 ? 0 : -EINVAL; 2510 + } 2511 + 2512 + int smu_v13_0_enable_uclk_shadow(struct smu_context *smu, bool enable) 2513 + { 2514 + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableUCLKShadow, enable, NULL); 2515 + } 2516 + 2517 + int smu_v13_0_set_wbrf_exclusion_ranges(struct smu_context *smu, 2518 + struct freq_band_range *exclusion_ranges) 2519 + { 2520 + WifiBandEntryTable_t wifi_bands; 2521 + int valid_entries = 0; 2522 + int ret, i; 2523 + 2524 + memset(&wifi_bands, 0, sizeof(wifi_bands)); 2525 + for (i = 0; i < ARRAY_SIZE(wifi_bands.WifiBandEntry); i++) { 2526 + if (!exclusion_ranges[i].start && !exclusion_ranges[i].end) 2527 + break; 2528 + 2529 + /* PMFW expects the inputs to be in Mhz unit */ 2530 + wifi_bands.WifiBandEntry[valid_entries].LowFreq = 2531 + DIV_ROUND_DOWN_ULL(exclusion_ranges[i].start, HZ_PER_MHZ); 2532 + wifi_bands.WifiBandEntry[valid_entries++].HighFreq = 2533 + DIV_ROUND_UP_ULL(exclusion_ranges[i].end, HZ_PER_MHZ); 2534 + } 2535 + wifi_bands.WifiBandEntryNum = valid_entries; 2536 + 2537 + /* 2538 + * Per confirm with PMFW team, WifiBandEntryNum = 0 2539 + * is a valid setting. 2540 + * 2541 + * Considering the scenarios below: 2542 + * - At first the wifi device adds an exclusion range e.g. (2400,2500) to 2543 + * BIOS and our driver gets notified. We will set WifiBandEntryNum = 1 2544 + * and pass the WifiBandEntry (2400, 2500) to PMFW. 2545 + * 2546 + * - Later the wifi device removes the wifiband list added above and 2547 + * our driver gets notified again. At this time, driver will set 2548 + * WifiBandEntryNum = 0 and pass an empty WifiBandEntry list to PMFW. 2549 + * 2550 + * - PMFW may still need to do some uclk shadow update(e.g. switching 2551 + * from shadow clock back to primary clock) on receiving this. 2552 + */ 2553 + ret = smu_cmn_update_table(smu, SMU_TABLE_WIFIBAND, 0, &wifi_bands, true); 2554 + if (ret) 2555 + dev_warn(smu->adev->dev, "Failed to set wifiband!"); 2556 + 2557 + return ret; 2509 2558 }
+35 -12
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
··· 169 169 MSG_MAP(AllowIHHostInterrupt, PPSMC_MSG_AllowIHHostInterrupt, 0), 170 170 MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0), 171 171 MSG_MAP(DALNotPresent, PPSMC_MSG_DALNotPresent, 0), 172 + MSG_MAP(EnableUCLKShadow, PPSMC_MSG_EnableUCLKShadow, 0), 172 173 }; 173 174 174 175 static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = { ··· 254 253 TAB_MAP(I2C_COMMANDS), 255 254 TAB_MAP(ECCINFO), 256 255 TAB_MAP(OVERDRIVE), 256 + TAB_MAP(WIFIBAND), 257 257 }; 258 258 259 259 static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { ··· 500 498 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 501 499 SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), 502 500 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 501 + SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND, 502 + sizeof(WifiBandEntryTable_t), PAGE_SIZE, 503 + AMDGPU_GEM_DOMAIN_VRAM); 503 504 504 505 smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); 505 506 if (!smu_table->metrics_table) ··· 2545 2540 2546 2541 workload_mask = 1 << workload_type; 2547 2542 2548 - /* Add optimizations for SMU13.0.0. Reuse the power saving profile */ 2549 - if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE && 2550 - (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0)) && 2551 - ((smu->adev->pm.fw_version == 0x004e6601) || 2552 - (smu->adev->pm.fw_version >= 0x004e7400))) { 2553 - workload_type = smu_cmn_to_asic_specific_index(smu, 2554 - CMN2ASIC_MAPPING_WORKLOAD, 2555 - PP_SMC_POWER_PROFILE_POWERSAVING); 2556 - if (workload_type >= 0) 2557 - workload_mask |= 1 << workload_type; 2543 + /* Add optimizations for SMU13.0.0/10. Reuse the power saving profile */ 2544 + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) { 2545 + if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) && 2546 + ((smu->adev->pm.fw_version == 0x004e6601) || 2547 + (smu->adev->pm.fw_version >= 0x004e7300))) || 2548 + (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) && 2549 + smu->adev->pm.fw_version >= 0x00504500)) { 2550 + workload_type = smu_cmn_to_asic_specific_index(smu, 2551 + CMN2ASIC_MAPPING_WORKLOAD, 2552 + PP_SMC_POWER_PROFILE_POWERSAVING); 2553 + if (workload_type >= 0) 2554 + workload_mask |= 1 << workload_type; 2555 + } 2558 2556 } 2559 2557 2560 2558 return smu_cmn_send_smc_msg_with_param(smu, ··· 2946 2938 return ret; 2947 2939 } 2948 2940 2941 + static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu) 2942 + { 2943 + struct amdgpu_device *adev = smu->adev; 2944 + 2945 + switch (adev->ip_versions[MP1_HWIP][0]) { 2946 + case IP_VERSION(13, 0, 0): 2947 + return smu->smc_fw_version >= 0x004e6300; 2948 + case IP_VERSION(13, 0, 10): 2949 + return smu->smc_fw_version >= 0x00503300; 2950 + default: 2951 + return false; 2952 + } 2953 + } 2954 + 2949 2955 static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { 2950 2956 .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, 2951 2957 .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, ··· 3025 3003 .deep_sleep_control = smu_v13_0_deep_sleep_control, 3026 3004 .gfx_ulv_control = smu_v13_0_gfx_ulv_control, 3027 3005 .baco_is_support = smu_v13_0_baco_is_support, 3028 - .baco_get_state = smu_v13_0_baco_get_state, 3029 - .baco_set_state = smu_v13_0_baco_set_state, 3030 3006 .baco_enter = smu_v13_0_baco_enter, 3031 3007 .baco_exit = smu_v13_0_baco_exit, 3032 3008 .mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported, ··· 3038 3018 .gpo_control = smu_v13_0_gpo_control, 3039 3019 .get_ecc_info = smu_v13_0_0_get_ecc_info, 3040 3020 .notify_display_change = smu_v13_0_notify_display_change, 3021 + .is_asic_wbrf_supported = smu_v13_0_0_wbrf_support_check, 3022 + .enable_uclk_shadow = smu_v13_0_enable_uclk_shadow, 3023 + .set_wbrf_exclusion_ranges = smu_v13_0_set_wbrf_exclusion_ranges, 3041 3024 }; 3042 3025 3043 3026 void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
+4 -2
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
··· 2537 2537 uint32_t *count) 2538 2538 { 2539 2539 u32 ext_error_code; 2540 + u32 err_cnt; 2540 2541 2541 2542 ext_error_code = MCA_REG__STATUS__ERRORCODEEXT(entry->regs[MCA_REG_IDX_STATUS]); 2543 + err_cnt = MCA_REG__MISC0__ERRCNT(entry->regs[MCA_REG_IDX_MISC0]); 2542 2544 2543 2545 if (type == AMDGPU_MCA_ERROR_TYPE_UE && ext_error_code == 0) 2544 - *count = 1; 2546 + *count = err_cnt; 2545 2547 else if (type == AMDGPU_MCA_ERROR_TYPE_CE && ext_error_code == 6) 2546 - *count = 1; 2548 + *count = err_cnt; 2547 2549 2548 2550 return 0; 2549 2551 }
+13 -2
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
··· 140 140 MSG_MAP(AllowGpo, PPSMC_MSG_SetGpoAllow, 0), 141 141 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), 142 142 MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), 143 + MSG_MAP(EnableUCLKShadow, PPSMC_MSG_EnableUCLKShadow, 0), 143 144 }; 144 145 145 146 static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = { ··· 223 222 TAB_MAP(ACTIVITY_MONITOR_COEFF), 224 223 [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE}, 225 224 TAB_MAP(OVERDRIVE), 225 + TAB_MAP(WIFIBAND), 226 226 }; 227 227 228 228 static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { ··· 514 512 AMDGPU_GEM_DOMAIN_VRAM); 515 513 SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE, 516 514 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 515 + SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND, 516 + sizeof(WifiBandEntryTable_t), PAGE_SIZE, 517 + AMDGPU_GEM_DOMAIN_VRAM); 517 518 518 519 smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); 519 520 if (!smu_table->metrics_table) ··· 2540 2535 NULL); 2541 2536 } 2542 2537 2538 + static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu) 2539 + { 2540 + return smu->smc_fw_version > 0x00524600; 2541 + } 2542 + 2543 2543 static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { 2544 2544 .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask, 2545 2545 .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table, ··· 2604 2594 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 2605 2595 .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, 2606 2596 .baco_is_support = smu_v13_0_baco_is_support, 2607 - .baco_get_state = smu_v13_0_baco_get_state, 2608 - .baco_set_state = smu_v13_0_baco_set_state, 2609 2597 .baco_enter = smu_v13_0_baco_enter, 2610 2598 .baco_exit = smu_v13_0_baco_exit, 2611 2599 .mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported, ··· 2611 2603 .set_mp1_state = smu_v13_0_7_set_mp1_state, 2612 2604 .set_df_cstate = smu_v13_0_7_set_df_cstate, 2613 2605 .gpo_control = smu_v13_0_gpo_control, 2606 + .is_asic_wbrf_supported = smu_v13_0_7_wbrf_support_check, 2607 + .enable_uclk_shadow = smu_v13_0_enable_uclk_shadow, 2608 + .set_wbrf_exclusion_ranges = smu_v13_0_set_wbrf_exclusion_ranges, 2614 2609 }; 2615 2610 2616 2611 void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
+3 -3
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
··· 224 224 if (smu->is_apu) 225 225 adev->pm.fw_version = smu_version; 226 226 227 - switch (adev->ip_versions[MP1_HWIP][0]) { 227 + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { 228 228 case IP_VERSION(14, 0, 2): 229 229 smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2; 230 230 break; ··· 235 235 break; 236 236 default: 237 237 dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n", 238 - adev->ip_versions[MP1_HWIP][0]); 238 + amdgpu_ip_version(adev, MP1_HWIP, 0)); 239 239 smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_INV; 240 240 break; 241 241 } ··· 733 733 int ret = 0; 734 734 struct amdgpu_device *adev = smu->adev; 735 735 736 - switch (adev->ip_versions[MP1_HWIP][0]) { 736 + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { 737 737 case IP_VERSION(14, 0, 2): 738 738 case IP_VERSION(14, 0, 0): 739 739 if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
+20
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
··· 1085 1085 0, NULL); 1086 1086 } 1087 1087 1088 + static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) 1089 + { 1090 + DpmClocks_t *clk_table = smu->smu_table.clocks_table; 1091 + uint8_t idx; 1092 + 1093 + /* Only the Clock information of SOC and VPE is copied to provide VPE DPM settings for use. */ 1094 + for (idx = 0; idx < NUM_SOCCLK_DPM_LEVELS; idx++) { 1095 + clock_table->SocClocks[idx].Freq = (idx < clk_table->NumSocClkLevelsEnabled) ? clk_table->SocClocks[idx]:0; 1096 + clock_table->SocClocks[idx].Vol = 0; 1097 + } 1098 + 1099 + for (idx = 0; idx < NUM_VPE_DPM_LEVELS; idx++) { 1100 + clock_table->VPEClocks[idx].Freq = (idx < clk_table->VpeClkLevelsEnabled) ? clk_table->VPEClocks[idx]:0; 1101 + clock_table->VPEClocks[idx].Vol = 0; 1102 + } 1103 + 1104 + return 0; 1105 + } 1106 + 1088 1107 static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { 1089 1108 .check_fw_status = smu_v14_0_check_fw_status, 1090 1109 .check_fw_version = smu_v14_0_check_fw_version, ··· 1134 1115 .set_gfx_power_up_by_imu = smu_v14_0_set_gfx_power_up_by_imu, 1135 1116 .dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable, 1136 1117 .dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable, 1118 + .get_dpm_clock_table = smu_14_0_0_get_dpm_table, 1137 1119 }; 1138 1120 1139 1121 static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *smu)
+3
drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
··· 98 98 #define smu_set_config_table(smu, config_table) smu_ppt_funcs(set_config_table, -EOPNOTSUPP, smu, config_table) 99 99 #define smu_init_pptable_microcode(smu) smu_ppt_funcs(init_pptable_microcode, 0, smu) 100 100 #define smu_notify_rlc_state(smu, en) smu_ppt_funcs(notify_rlc_state, 0, smu, en) 101 + #define smu_is_asic_wbrf_supported(smu) smu_ppt_funcs(is_asic_wbrf_supported, false, smu) 102 + #define smu_enable_uclk_shadow(smu, enable) smu_ppt_funcs(enable_uclk_shadow, 0, smu, enable) 103 + #define smu_set_wbrf_exclusion_ranges(smu, freq_band_range) smu_ppt_funcs(set_wbrf_exclusion_ranges, -EOPNOTSUPP, smu, freq_band_range) 101 104 102 105 #endif 103 106 #endif
+1 -1
drivers/gpu/drm/arm/malidp_crtc.c
··· 221 221 222 222 /* 223 223 * The size of the ctm is checked in 224 - * drm_atomic_replace_property_blob_from_id. 224 + * drm_property_replace_blob_from_id. 225 225 */ 226 226 ctm = (struct drm_color_ctm *)state->ctm->data; 227 227 for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
+1
drivers/gpu/drm/drm_atomic.c
··· 733 733 drm_get_color_encoding_name(state->color_encoding)); 734 734 drm_printf(p, "\tcolor-range=%s\n", 735 735 drm_get_color_range_name(state->color_range)); 736 + drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); 736 737 737 738 if (plane->funcs->atomic_print_state) 738 739 plane->funcs->atomic_print_state(p, state);
+1
drivers/gpu/drm/drm_atomic_state_helper.c
··· 352 352 state->fence = NULL; 353 353 state->commit = NULL; 354 354 state->fb_damage_clips = NULL; 355 + state->color_mgmt_changed = false; 355 356 } 356 357 EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); 357 358
+5 -47
drivers/gpu/drm/drm_atomic_uapi.c
··· 362 362 return fence_ptr; 363 363 } 364 364 365 - static int 366 - drm_atomic_replace_property_blob_from_id(struct drm_device *dev, 367 - struct drm_property_blob **blob, 368 - uint64_t blob_id, 369 - ssize_t expected_size, 370 - ssize_t expected_elem_size, 371 - bool *replaced) 372 - { 373 - struct drm_property_blob *new_blob = NULL; 374 - 375 - if (blob_id != 0) { 376 - new_blob = drm_property_lookup_blob(dev, blob_id); 377 - if (new_blob == NULL) { 378 - drm_dbg_atomic(dev, 379 - "cannot find blob ID %llu\n", blob_id); 380 - return -EINVAL; 381 - } 382 - 383 - if (expected_size > 0 && 384 - new_blob->length != expected_size) { 385 - drm_dbg_atomic(dev, 386 - "[BLOB:%d] length %zu different from expected %zu\n", 387 - new_blob->base.id, new_blob->length, expected_size); 388 - drm_property_blob_put(new_blob); 389 - return -EINVAL; 390 - } 391 - if (expected_elem_size > 0 && 392 - new_blob->length % expected_elem_size != 0) { 393 - drm_dbg_atomic(dev, 394 - "[BLOB:%d] length %zu not divisible by element size %zu\n", 395 - new_blob->base.id, new_blob->length, expected_elem_size); 396 - drm_property_blob_put(new_blob); 397 - return -EINVAL; 398 - } 399 - } 400 - 401 - *replaced |= drm_property_replace_blob(blob, new_blob); 402 - drm_property_blob_put(new_blob); 403 - 404 - return 0; 405 - } 406 - 407 365 static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, 408 366 struct drm_crtc_state *state, struct drm_property *property, 409 367 uint64_t val) ··· 382 424 } else if (property == config->prop_vrr_enabled) { 383 425 state->vrr_enabled = val; 384 426 } else if (property == config->degamma_lut_property) { 385 - ret = drm_atomic_replace_property_blob_from_id(dev, 427 + ret = drm_property_replace_blob_from_id(dev, 386 428 &state->degamma_lut, 387 429 val, 388 430 -1, sizeof(struct drm_color_lut), ··· 390 432 state->color_mgmt_changed |= replaced; 391 433 return ret; 392 434 } else if (property == config->ctm_property) { 393 - ret = drm_atomic_replace_property_blob_from_id(dev, 435 + ret = drm_property_replace_blob_from_id(dev, 394 436 &state->ctm, 395 437 val, 396 438 sizeof(struct drm_color_ctm), -1, ··· 398 440 state->color_mgmt_changed |= replaced; 399 441 return ret; 400 442 } else if (property == config->gamma_lut_property) { 401 - ret = drm_atomic_replace_property_blob_from_id(dev, 443 + ret = drm_property_replace_blob_from_id(dev, 402 444 &state->gamma_lut, 403 445 val, 404 446 -1, sizeof(struct drm_color_lut), ··· 539 581 } else if (property == plane->color_range_property) { 540 582 state->color_range = val; 541 583 } else if (property == config->prop_fb_damage_clips) { 542 - ret = drm_atomic_replace_property_blob_from_id(dev, 584 + ret = drm_property_replace_blob_from_id(dev, 543 585 &state->fb_damage_clips, 544 586 val, 545 587 -1, ··· 736 778 if (state->link_status != DRM_LINK_STATUS_GOOD) 737 779 state->link_status = val; 738 780 } else if (property == config->hdr_output_metadata_property) { 739 - ret = drm_atomic_replace_property_blob_from_id(dev, 781 + ret = drm_property_replace_blob_from_id(dev, 740 782 &state->hdr_output_metadata, 741 783 val, 742 784 sizeof(struct hdr_output_metadata), -1,
+59
drivers/gpu/drm/drm_property.c
··· 27 27 #include <drm/drm_drv.h> 28 28 #include <drm/drm_file.h> 29 29 #include <drm/drm_framebuffer.h> 30 + #include <drm/drm_print.h> 30 31 #include <drm/drm_property.h> 31 32 32 33 #include "drm_crtc_internal.h" ··· 751 750 return true; 752 751 } 753 752 EXPORT_SYMBOL(drm_property_replace_blob); 753 + 754 + /** 755 + * drm_property_replace_blob_from_id - replace a blob property taking a reference 756 + * @dev: DRM device 757 + * @blob: a pointer to the member blob to be replaced 758 + * @blob_id: the id of the new blob to replace with 759 + * @expected_size: expected size of the blob property 760 + * @expected_elem_size: expected size of an element in the blob property 761 + * @replaced: if the blob was in fact replaced 762 + * 763 + * Look up the new blob from id, take its reference, check expected sizes of 764 + * the blob and its element and replace the old blob by the new one. Advertise 765 + * if the replacement operation was successful. 766 + * 767 + * Return: true if the blob was in fact replaced. -EINVAL if the new blob was 768 + * not found or sizes don't match. 769 + */ 770 + int drm_property_replace_blob_from_id(struct drm_device *dev, 771 + struct drm_property_blob **blob, 772 + uint64_t blob_id, 773 + ssize_t expected_size, 774 + ssize_t expected_elem_size, 775 + bool *replaced) 776 + { 777 + struct drm_property_blob *new_blob = NULL; 778 + 779 + if (blob_id != 0) { 780 + new_blob = drm_property_lookup_blob(dev, blob_id); 781 + if (new_blob == NULL) { 782 + drm_dbg_atomic(dev, 783 + "cannot find blob ID %llu\n", blob_id); 784 + return -EINVAL; 785 + } 786 + 787 + if (expected_size > 0 && 788 + new_blob->length != expected_size) { 789 + drm_dbg_atomic(dev, 790 + "[BLOB:%d] length %zu different from expected %zu\n", 791 + new_blob->base.id, new_blob->length, expected_size); 792 + drm_property_blob_put(new_blob); 793 + return -EINVAL; 794 + } 795 + if (expected_elem_size > 0 && 796 + new_blob->length % expected_elem_size != 0) { 797 + drm_dbg_atomic(dev, 798 + "[BLOB:%d] length %zu not divisible by element size %zu\n", 799 + new_blob->base.id, new_blob->length, expected_elem_size); 800 + drm_property_blob_put(new_blob); 801 + return -EINVAL; 802 + } 803 + } 804 + 805 + *replaced |= drm_property_replace_blob(blob, new_blob); 806 + drm_property_blob_put(new_blob); 807 + 808 + return 0; 809 + } 810 + EXPORT_SYMBOL(drm_property_replace_blob_from_id); 754 811 755 812 int drm_mode_getblob_ioctl(struct drm_device *dev, 756 813 void *data, struct drm_file *file_priv)
+1
drivers/gpu/drm/radeon/atombios_encoders.c
··· 29 29 #include <linux/pci.h> 30 30 31 31 #include <drm/drm_crtc_helper.h> 32 + #include <drm/drm_edid.h> 32 33 #include <drm/drm_file.h> 33 34 #include <drm/drm_modeset_helper_vtables.h> 34 35 #include <drm/radeon_drm.h>
+1
drivers/gpu/drm/radeon/dce3_1_afmt.c
··· 21 21 * OTHER DEALINGS IN THE SOFTWARE. 22 22 */ 23 23 #include <linux/hdmi.h> 24 + #include <drm/drm_edid.h> 24 25 25 26 #include "radeon.h" 26 27 #include "radeon_asic.h"
+1
drivers/gpu/drm/radeon/dce6_afmt.c
··· 21 21 * 22 22 */ 23 23 #include <linux/hdmi.h> 24 + #include <drm/drm_edid.h> 24 25 25 26 #include "dce6_afmt.h" 26 27 #include "radeon.h"
+1
drivers/gpu/drm/radeon/evergreen.c
··· 26 26 #include <linux/pci.h> 27 27 #include <linux/slab.h> 28 28 29 + #include <drm/drm_edid.h> 29 30 #include <drm/drm_vblank.h> 30 31 #include <drm/radeon_drm.h> 31 32 #include <drm/drm_fourcc.h>
+1
drivers/gpu/drm/radeon/evergreen_hdmi.c
··· 26 26 */ 27 27 #include <linux/hdmi.h> 28 28 29 + #include <drm/drm_edid.h> 29 30 #include <drm/radeon_drm.h> 30 31 #include "evergreen_hdmi.h" 31 32 #include "radeon.h"
+1
drivers/gpu/drm/radeon/radeon_atombios.c
··· 27 27 #include <linux/pci.h> 28 28 29 29 #include <drm/drm_device.h> 30 + #include <drm/drm_edid.h> 30 31 #include <drm/radeon_drm.h> 31 32 32 33 #include "radeon.h"
+1
drivers/gpu/drm/radeon/radeon_audio.c
··· 27 27 28 28 #include <drm/drm_crtc.h> 29 29 #include <drm/drm_eld.h> 30 + #include <drm/drm_edid.h> 30 31 #include "dce6_afmt.h" 31 32 #include "evergreen_hdmi.h" 32 33 #include "radeon.h"
+3 -1
drivers/gpu/drm/radeon/radeon_audio.h
··· 27 27 28 28 #include <linux/types.h> 29 29 30 - #define RREG32_ENDPOINT(block, reg) \ 30 + struct cea_sad; 31 + 32 + #define RREG32_ENDPOINT(block, reg) \ 31 33 radeon_audio_endpoint_rreg(rdev, (block), (reg)) 32 34 #define WREG32_ENDPOINT(block, reg, v) \ 33 35 radeon_audio_endpoint_wreg(rdev, (block), (reg), (v))
+1
drivers/gpu/drm/radeon/radeon_combios.c
··· 28 28 #include <linux/pci.h> 29 29 30 30 #include <drm/drm_device.h> 31 + #include <drm/drm_edid.h> 31 32 #include <drm/radeon_drm.h> 32 33 33 34 #include "radeon.h"
+1
drivers/gpu/drm/radeon/radeon_encoders.c
··· 26 26 27 27 #include <linux/pci.h> 28 28 29 + #include <drm/drm_edid.h> 29 30 #include <drm/drm_device.h> 30 31 #include <drm/radeon_drm.h> 31 32
+1 -1
drivers/gpu/drm/radeon/radeon_mode.h
··· 32 32 33 33 #include <drm/display/drm_dp_helper.h> 34 34 #include <drm/drm_crtc.h> 35 - #include <drm/drm_edid.h> 36 35 #include <drm/drm_encoder.h> 37 36 #include <drm/drm_fixed.h> 38 37 #include <drm/drm_modeset_helper_vtables.h> 39 38 #include <linux/i2c.h> 40 39 #include <linux/i2c-algo-bit.h> 41 40 41 + struct edid; 42 42 struct radeon_bo; 43 43 struct radeon_device; 44 44
+1 -1
drivers/gpu/drm/radeon/radeon_ring.c
··· 413 413 dev_err(rdev->dev, "(%d) ring map failed\n", r); 414 414 return r; 415 415 } 416 + radeon_debugfs_ring_init(rdev, ring); 416 417 } 417 418 ring->ptr_mask = (ring->ring_size / 4) - 1; 418 419 ring->ring_free_dw = ring->ring_size / 4; ··· 422 421 ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; 423 422 ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; 424 423 } 425 - radeon_debugfs_ring_init(rdev, ring); 426 424 radeon_ring_lockup_update(rdev, ring); 427 425 return 0; 428 426 }
+6 -2
drivers/gpu/drm/radeon/radeon_vm.c
··· 1204 1204 r = radeon_bo_create(rdev, pd_size, align, true, 1205 1205 RADEON_GEM_DOMAIN_VRAM, 0, NULL, 1206 1206 NULL, &vm->page_directory); 1207 - if (r) 1207 + if (r) { 1208 + kfree(vm->page_tables); 1209 + vm->page_tables = NULL; 1208 1210 return r; 1209 - 1211 + } 1210 1212 r = radeon_vm_clear_bo(rdev, vm->page_directory); 1211 1213 if (r) { 1212 1214 radeon_bo_unref(&vm->page_directory); 1213 1215 vm->page_directory = NULL; 1216 + kfree(vm->page_tables); 1217 + vm->page_tables = NULL; 1214 1218 return r; 1215 1219 } 1216 1220
+14
drivers/platform/x86/amd/Kconfig
··· 18 18 19 19 If you choose to compile this driver as a module the module will be 20 20 called amd_hsmp. 21 + 22 + config AMD_WBRF 23 + bool "AMD Wifi RF Band mitigations (WBRF)" 24 + depends on ACPI 25 + help 26 + WBRF(Wifi Band RFI mitigation) mechanism allows Wifi drivers 27 + to notify the frequencies they are using so that other hardware 28 + can be reconfigured to avoid harmonic conflicts. 29 + 30 + AMD provides an ACPI based mechanism to support WBRF on platform with 31 + appropriate underlying support. 32 + 33 + This mechanism will only be activated on platforms that advertise a 34 + need for it.
+1
drivers/platform/x86/amd/Makefile
··· 8 8 amd_hsmp-y := hsmp.o 9 9 obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o 10 10 obj-$(CONFIG_AMD_PMF) += pmf/ 11 + obj-$(CONFIG_AMD_WBRF) += wbrf.o
+317
drivers/platform/x86/amd/wbrf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Wifi Frequency Band Manage Interface 4 + * Copyright (C) 2023 Advanced Micro Devices 5 + */ 6 + 7 + #include <linux/acpi.h> 8 + #include <linux/acpi_amd_wbrf.h> 9 + 10 + /* 11 + * Functions bit vector for WBRF method 12 + * 13 + * Bit 0: WBRF supported. 14 + * Bit 1: Function 1 (Add / Remove frequency) is supported. 15 + * Bit 2: Function 2 (Get frequency list) is supported. 16 + */ 17 + #define WBRF_ENABLED 0x0 18 + #define WBRF_RECORD 0x1 19 + #define WBRF_RETRIEVE 0x2 20 + 21 + #define WBRF_REVISION 0x1 22 + 23 + /* 24 + * The data structure used for WBRF_RETRIEVE is not naturally aligned. 25 + * And unfortunately the design has been settled down. 26 + */ 27 + struct amd_wbrf_ranges_out { 28 + u32 num_of_ranges; 29 + struct freq_band_range band_list[MAX_NUM_OF_WBRF_RANGES]; 30 + } __packed; 31 + 32 + static const guid_t wifi_acpi_dsm_guid = 33 + GUID_INIT(0x7b7656cf, 0xdc3d, 0x4c1c, 34 + 0x83, 0xe9, 0x66, 0xe7, 0x21, 0xde, 0x30, 0x70); 35 + 36 + /* 37 + * Used to notify consumer (amdgpu driver currently) about 38 + * the wifi frequency is change. 39 + */ 40 + static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head); 41 + 42 + static int wbrf_record(struct acpi_device *adev, uint8_t action, struct wbrf_ranges_in_out *in) 43 + { 44 + union acpi_object argv4; 45 + union acpi_object *tmp; 46 + union acpi_object *obj; 47 + u32 num_of_ranges = 0; 48 + u32 num_of_elements; 49 + u32 arg_idx = 0; 50 + int ret; 51 + u32 i; 52 + 53 + if (!in) 54 + return -EINVAL; 55 + 56 + for (i = 0; i < ARRAY_SIZE(in->band_list); i++) { 57 + if (in->band_list[i].start && in->band_list[i].end) 58 + num_of_ranges++; 59 + } 60 + 61 + /* 62 + * The num_of_ranges value in the "in" object supplied by 63 + * the caller is required to be equal to the number of 64 + * entries in the band_list array in there. 65 + */ 66 + if (num_of_ranges != in->num_of_ranges) 67 + return -EINVAL; 68 + 69 + /* 70 + * Every input frequency band comes with two end points(start/end) 71 + * and each is accounted as an element. Meanwhile the range count 72 + * and action type are accounted as an element each. 73 + * So, the total element count = 2 * num_of_ranges + 1 + 1. 74 + */ 75 + num_of_elements = 2 * num_of_ranges + 2; 76 + 77 + tmp = kcalloc(num_of_elements, sizeof(*tmp), GFP_KERNEL); 78 + if (!tmp) 79 + return -ENOMEM; 80 + 81 + argv4.package.type = ACPI_TYPE_PACKAGE; 82 + argv4.package.count = num_of_elements; 83 + argv4.package.elements = tmp; 84 + 85 + /* save the number of ranges*/ 86 + tmp[0].integer.type = ACPI_TYPE_INTEGER; 87 + tmp[0].integer.value = num_of_ranges; 88 + 89 + /* save the action(WBRF_RECORD_ADD/REMOVE/RETRIEVE) */ 90 + tmp[1].integer.type = ACPI_TYPE_INTEGER; 91 + tmp[1].integer.value = action; 92 + 93 + arg_idx = 2; 94 + for (i = 0; i < ARRAY_SIZE(in->band_list); i++) { 95 + if (!in->band_list[i].start || !in->band_list[i].end) 96 + continue; 97 + 98 + tmp[arg_idx].integer.type = ACPI_TYPE_INTEGER; 99 + tmp[arg_idx++].integer.value = in->band_list[i].start; 100 + tmp[arg_idx].integer.type = ACPI_TYPE_INTEGER; 101 + tmp[arg_idx++].integer.value = in->band_list[i].end; 102 + } 103 + 104 + obj = acpi_evaluate_dsm(adev->handle, &wifi_acpi_dsm_guid, 105 + WBRF_REVISION, WBRF_RECORD, &argv4); 106 + 107 + if (!obj) 108 + return -EINVAL; 109 + 110 + if (obj->type != ACPI_TYPE_INTEGER) { 111 + ret = -EINVAL; 112 + goto out; 113 + } 114 + 115 + ret = obj->integer.value; 116 + if (ret) 117 + ret = -EINVAL; 118 + 119 + out: 120 + ACPI_FREE(obj); 121 + kfree(tmp); 122 + 123 + return ret; 124 + } 125 + 126 + /** 127 + * acpi_amd_wbrf_add_remove - add or remove the frequency band the device is using 128 + * 129 + * @dev: device pointer 130 + * @action: remove or add the frequency band into bios 131 + * @in: input structure containing the frequency band the device is using 132 + * 133 + * Broadcast to other consumers the frequency band the device starts 134 + * to use. Underneath the surface the information is cached into an 135 + * internal buffer first. Then a notification is sent to all those 136 + * registered consumers. So then they can retrieve that buffer to 137 + * know the latest active frequency bands. Consumers that haven't 138 + * yet been registered can retrieve the information from the cache 139 + * when they register. 140 + * 141 + * Return: 142 + * 0 for success add/remove wifi frequency band. 143 + * Returns a negative error code for failure. 144 + */ 145 + int acpi_amd_wbrf_add_remove(struct device *dev, uint8_t action, struct wbrf_ranges_in_out *in) 146 + { 147 + struct acpi_device *adev; 148 + int ret; 149 + 150 + adev = ACPI_COMPANION(dev); 151 + if (!adev) 152 + return -ENODEV; 153 + 154 + ret = wbrf_record(adev, action, in); 155 + if (ret) 156 + return ret; 157 + 158 + blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED, NULL); 159 + 160 + return 0; 161 + } 162 + EXPORT_SYMBOL_GPL(acpi_amd_wbrf_add_remove); 163 + 164 + /** 165 + * acpi_amd_wbrf_supported_producer - determine if the WBRF can be enabled 166 + * for the device as a producer 167 + * 168 + * @dev: device pointer 169 + * 170 + * Check if the platform equipped with necessary implementations to 171 + * support WBRF for the device as a producer. 172 + * 173 + * Return: 174 + * true if WBRF is supported, otherwise returns false 175 + */ 176 + bool acpi_amd_wbrf_supported_producer(struct device *dev) 177 + { 178 + struct acpi_device *adev; 179 + 180 + adev = ACPI_COMPANION(dev); 181 + if (!adev) 182 + return false; 183 + 184 + return acpi_check_dsm(adev->handle, &wifi_acpi_dsm_guid, 185 + WBRF_REVISION, BIT(WBRF_RECORD)); 186 + } 187 + EXPORT_SYMBOL_GPL(acpi_amd_wbrf_supported_producer); 188 + 189 + /** 190 + * acpi_amd_wbrf_supported_consumer - determine if the WBRF can be enabled 191 + * for the device as a consumer 192 + * 193 + * @dev: device pointer 194 + * 195 + * Determine if the platform equipped with necessary implementations to 196 + * support WBRF for the device as a consumer. 197 + * 198 + * Return: 199 + * true if WBRF is supported, otherwise returns false. 200 + */ 201 + bool acpi_amd_wbrf_supported_consumer(struct device *dev) 202 + { 203 + struct acpi_device *adev; 204 + 205 + adev = ACPI_COMPANION(dev); 206 + if (!adev) 207 + return false; 208 + 209 + return acpi_check_dsm(adev->handle, &wifi_acpi_dsm_guid, 210 + WBRF_REVISION, BIT(WBRF_RETRIEVE)); 211 + } 212 + EXPORT_SYMBOL_GPL(acpi_amd_wbrf_supported_consumer); 213 + 214 + /** 215 + * amd_wbrf_retrieve_freq_band - retrieve current active frequency bands 216 + * 217 + * @dev: device pointer 218 + * @out: output structure containing all the active frequency bands 219 + * 220 + * Retrieve the current active frequency bands which were broadcasted 221 + * by other producers. The consumer who calls this API should take 222 + * proper actions if any of the frequency band may cause RFI with its 223 + * own frequency band used. 224 + * 225 + * Return: 226 + * 0 for getting wifi freq band successfully. 227 + * Returns a negative error code for failure. 228 + */ 229 + int amd_wbrf_retrieve_freq_band(struct device *dev, struct wbrf_ranges_in_out *out) 230 + { 231 + struct amd_wbrf_ranges_out acpi_out = {0}; 232 + struct acpi_device *adev; 233 + union acpi_object *obj; 234 + union acpi_object param; 235 + int ret = 0; 236 + 237 + adev = ACPI_COMPANION(dev); 238 + if (!adev) 239 + return -ENODEV; 240 + 241 + param.type = ACPI_TYPE_STRING; 242 + param.string.length = 0; 243 + param.string.pointer = NULL; 244 + 245 + obj = acpi_evaluate_dsm(adev->handle, &wifi_acpi_dsm_guid, 246 + WBRF_REVISION, WBRF_RETRIEVE, &param); 247 + if (!obj) 248 + return -EINVAL; 249 + 250 + /* 251 + * The return buffer is with variable length and the format below: 252 + * number_of_entries(1 DWORD): Number of entries 253 + * start_freq of 1st entry(1 QWORD): Start frequency of the 1st entry 254 + * end_freq of 1st entry(1 QWORD): End frequency of the 1st entry 255 + * ... 256 + * ... 257 + * start_freq of the last entry(1 QWORD) 258 + * end_freq of the last entry(1 QWORD) 259 + * 260 + * Thus the buffer length is determined by the number of entries. 261 + * - For zero entry scenario, the buffer length will be 4 bytes. 262 + * - For one entry scenario, the buffer length will be 20 bytes. 263 + */ 264 + if (obj->buffer.length > sizeof(acpi_out) || obj->buffer.length < 4) { 265 + dev_err(dev, "Wrong sized WBRT information"); 266 + ret = -EINVAL; 267 + goto out; 268 + } 269 + memcpy(&acpi_out, obj->buffer.pointer, obj->buffer.length); 270 + 271 + out->num_of_ranges = acpi_out.num_of_ranges; 272 + memcpy(out->band_list, acpi_out.band_list, sizeof(acpi_out.band_list)); 273 + 274 + out: 275 + ACPI_FREE(obj); 276 + return ret; 277 + } 278 + EXPORT_SYMBOL_GPL(amd_wbrf_retrieve_freq_band); 279 + 280 + /** 281 + * amd_wbrf_register_notifier - register for notifications of frequency 282 + * band update 283 + * 284 + * @nb: driver notifier block 285 + * 286 + * The consumer should register itself via this API so that it can get 287 + * notified on the frequency band updates from other producers. 288 + * 289 + * Return: 290 + * 0 for registering a consumer driver successfully. 291 + * Returns a negative error code for failure. 292 + */ 293 + int amd_wbrf_register_notifier(struct notifier_block *nb) 294 + { 295 + return blocking_notifier_chain_register(&wbrf_chain_head, nb); 296 + } 297 + EXPORT_SYMBOL_GPL(amd_wbrf_register_notifier); 298 + 299 + /** 300 + * amd_wbrf_unregister_notifier - unregister for notifications of 301 + * frequency band update 302 + * 303 + * @nb: driver notifier block 304 + * 305 + * The consumer should call this API when it is longer interested with 306 + * the frequency band updates from other producers. Usually, this should 307 + * be performed during driver cleanup. 308 + * 309 + * Return: 310 + * 0 for unregistering a consumer driver. 311 + * Returns a negative error code for failure. 312 + */ 313 + int amd_wbrf_unregister_notifier(struct notifier_block *nb) 314 + { 315 + return blocking_notifier_chain_unregister(&wbrf_chain_head, nb); 316 + } 317 + EXPORT_SYMBOL_GPL(amd_wbrf_unregister_notifier);
+1 -1
include/drm/drm_mode_object.h
··· 60 60 void (*free_cb)(struct kref *kref); 61 61 }; 62 62 63 - #define DRM_OBJECT_MAX_PROPERTY 24 63 + #define DRM_OBJECT_MAX_PROPERTY 64 64 64 /** 65 65 * struct drm_object_properties - property tracking for &drm_mode_object 66 66 */
+7
include/drm/drm_plane.h
··· 251 251 252 252 /** @state: backpointer to global drm_atomic_state */ 253 253 struct drm_atomic_state *state; 254 + 255 + /** 256 + * @color_mgmt_changed: Color management properties have changed. Used 257 + * by the atomic helpers and drivers to steer the atomic commit control 258 + * flow. 259 + */ 260 + bool color_mgmt_changed : 1; 254 261 }; 255 262 256 263 static inline struct drm_rect
+6
include/drm/drm_property.h
··· 279 279 const void *data); 280 280 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, 281 281 uint32_t id); 282 + int drm_property_replace_blob_from_id(struct drm_device *dev, 283 + struct drm_property_blob **blob, 284 + uint64_t blob_id, 285 + ssize_t expected_size, 286 + ssize_t expected_elem_size, 287 + bool *replaced); 282 288 int drm_property_replace_global_blob(struct drm_device *dev, 283 289 struct drm_property_blob **replace, 284 290 size_t length,
+91
include/linux/acpi_amd_wbrf.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Wifi Band Exclusion Interface (AMD ACPI Implementation) 4 + * Copyright (C) 2023 Advanced Micro Devices 5 + */ 6 + 7 + #ifndef _ACPI_AMD_WBRF_H 8 + #define _ACPI_AMD_WBRF_H 9 + 10 + #include <linux/device.h> 11 + #include <linux/notifier.h> 12 + 13 + /* The maximum number of frequency band ranges */ 14 + #define MAX_NUM_OF_WBRF_RANGES 11 15 + 16 + /* Record actions */ 17 + #define WBRF_RECORD_ADD 0x0 18 + #define WBRF_RECORD_REMOVE 0x1 19 + 20 + /** 21 + * struct freq_band_range - Wifi frequency band range definition 22 + * @start: start frequency point (in Hz) 23 + * @end: end frequency point (in Hz) 24 + */ 25 + struct freq_band_range { 26 + u64 start; 27 + u64 end; 28 + }; 29 + 30 + /** 31 + * struct wbrf_ranges_in_out - wbrf ranges info 32 + * @num_of_ranges: total number of band ranges in this struct 33 + * @band_list: array of Wifi band ranges 34 + */ 35 + struct wbrf_ranges_in_out { 36 + u64 num_of_ranges; 37 + struct freq_band_range band_list[MAX_NUM_OF_WBRF_RANGES]; 38 + }; 39 + 40 + /** 41 + * enum wbrf_notifier_actions - wbrf notifier actions index 42 + * @WBRF_CHANGED: there was some frequency band updates. The consumers 43 + * should retrieve the latest active frequency bands. 44 + */ 45 + enum wbrf_notifier_actions { 46 + WBRF_CHANGED, 47 + }; 48 + 49 + #if IS_ENABLED(CONFIG_AMD_WBRF) 50 + bool acpi_amd_wbrf_supported_producer(struct device *dev); 51 + int acpi_amd_wbrf_add_remove(struct device *dev, uint8_t action, struct wbrf_ranges_in_out *in); 52 + bool acpi_amd_wbrf_supported_consumer(struct device *dev); 53 + int amd_wbrf_retrieve_freq_band(struct device *dev, struct wbrf_ranges_in_out *out); 54 + int amd_wbrf_register_notifier(struct notifier_block *nb); 55 + int amd_wbrf_unregister_notifier(struct notifier_block *nb); 56 + #else 57 + static inline 58 + bool acpi_amd_wbrf_supported_consumer(struct device *dev) 59 + { 60 + return false; 61 + } 62 + 63 + static inline 64 + int acpi_amd_wbrf_add_remove(struct device *dev, uint8_t action, struct wbrf_ranges_in_out *in) 65 + { 66 + return -ENODEV; 67 + } 68 + 69 + static inline 70 + bool acpi_amd_wbrf_supported_producer(struct device *dev) 71 + { 72 + return false; 73 + } 74 + static inline 75 + int amd_wbrf_retrieve_freq_band(struct device *dev, struct wbrf_ranges_in_out *out) 76 + { 77 + return -ENODEV; 78 + } 79 + static inline 80 + int amd_wbrf_register_notifier(struct notifier_block *nb) 81 + { 82 + return -ENODEV; 83 + } 84 + static inline 85 + int amd_wbrf_unregister_notifier(struct notifier_block *nb) 86 + { 87 + return -ENODEV; 88 + } 89 + #endif /* CONFIG_AMD_WBRF */ 90 + 91 + #endif /* _ACPI_AMD_WBRF_H */
+8
include/uapi/drm/drm_mode.h
··· 846 846 __u64 matrix[9]; 847 847 }; 848 848 849 + struct drm_color_ctm_3x4 { 850 + /* 851 + * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude 852 + * (not two's complement!) format. 853 + */ 854 + __u64 matrix[12]; 855 + }; 856 + 849 857 struct drm_color_lut { 850 858 /* 851 859 * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and