18da1170aSLeo Liu /* 28da1170aSLeo Liu * Copyright 2021 Advanced Micro Devices, Inc. 38da1170aSLeo Liu * 48da1170aSLeo Liu * Permission is hereby granted, free of charge, to any person obtaining a 58da1170aSLeo Liu * copy of this software and associated documentation files (the "Software"), 68da1170aSLeo Liu * to deal in the Software without restriction, including without limitation 78da1170aSLeo Liu * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88da1170aSLeo Liu * and/or sell copies of the Software, and to permit persons to whom the 98da1170aSLeo Liu * Software is furnished to do so, subject to the following conditions: 108da1170aSLeo Liu * 118da1170aSLeo Liu * The above copyright notice and this permission notice shall be included in 128da1170aSLeo Liu * all copies or substantial portions of the Software. 138da1170aSLeo Liu * 148da1170aSLeo Liu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158da1170aSLeo Liu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168da1170aSLeo Liu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178da1170aSLeo Liu * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188da1170aSLeo Liu * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198da1170aSLeo Liu * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208da1170aSLeo Liu * OTHER DEALINGS IN THE SOFTWARE. 218da1170aSLeo Liu * 228da1170aSLeo Liu */ 238da1170aSLeo Liu 248da1170aSLeo Liu #include <linux/firmware.h> 258da1170aSLeo Liu #include "amdgpu.h" 268da1170aSLeo Liu #include "amdgpu_vcn.h" 278da1170aSLeo Liu #include "amdgpu_pm.h" 280b15205cSSonny Jiang #include "amdgpu_cs.h" 298da1170aSLeo Liu #include "soc15.h" 308da1170aSLeo Liu #include "soc15d.h" 318da1170aSLeo Liu #include "soc15_hw_ip.h" 328da1170aSLeo Liu #include "vcn_v2_0.h" 338da1170aSLeo Liu 348da1170aSLeo Liu #include "vcn/vcn_4_0_0_offset.h" 358da1170aSLeo Liu #include "vcn/vcn_4_0_0_sh_mask.h" 368da1170aSLeo Liu #include "ivsrcid/vcn/irqsrcs_vcn_4_0.h" 378da1170aSLeo Liu 388da1170aSLeo Liu #include <drm/drm_drv.h> 398da1170aSLeo Liu 408da1170aSLeo Liu #define mmUVD_DPG_LMA_CTL regUVD_DPG_LMA_CTL 418da1170aSLeo Liu #define mmUVD_DPG_LMA_CTL_BASE_IDX regUVD_DPG_LMA_CTL_BASE_IDX 428da1170aSLeo Liu #define mmUVD_DPG_LMA_DATA regUVD_DPG_LMA_DATA 438da1170aSLeo Liu #define mmUVD_DPG_LMA_DATA_BASE_IDX regUVD_DPG_LMA_DATA_BASE_IDX 448da1170aSLeo Liu 458da1170aSLeo Liu #define VCN_VID_SOC_ADDRESS_2_0 0x1fb00 468da1170aSLeo Liu #define VCN1_VID_SOC_ADDRESS_3_0 0x48300 478da1170aSLeo Liu 480b15205cSSonny Jiang #define RDECODE_MSG_CREATE 0x00000000 490b15205cSSonny Jiang #define RDECODE_MESSAGE_CREATE 0x00000001 500b15205cSSonny Jiang 518da1170aSLeo Liu static int amdgpu_ih_clientid_vcns[] = { 528da1170aSLeo Liu SOC15_IH_CLIENTID_VCN, 538da1170aSLeo Liu SOC15_IH_CLIENTID_VCN1 548da1170aSLeo Liu }; 558da1170aSLeo Liu 56bb4f196bSRuijing Dong static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev); 578da1170aSLeo Liu static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev); 588da1170aSLeo Liu static int vcn_v4_0_set_powergating_state(void *handle, 598da1170aSLeo Liu enum amd_powergating_state state); 608da1170aSLeo Liu static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, 618da1170aSLeo Liu int inst_idx, struct dpg_pause_state *new_state); 628da1170aSLeo Liu 638da1170aSLeo Liu /** 648da1170aSLeo Liu * vcn_v4_0_early_init - set function pointers 658da1170aSLeo Liu * 668da1170aSLeo Liu * @handle: amdgpu_device pointer 678da1170aSLeo Liu * 688da1170aSLeo Liu * Set ring and irq function pointers 698da1170aSLeo Liu */ 708da1170aSLeo Liu static int vcn_v4_0_early_init(void *handle) 718da1170aSLeo Liu { 728da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 738da1170aSLeo Liu 74bb4f196bSRuijing Dong /* re-use enc ring as unified ring */ 758da1170aSLeo Liu adev->vcn.num_enc_rings = 1; 768da1170aSLeo Liu 77bb4f196bSRuijing Dong vcn_v4_0_set_unified_ring_funcs(adev); 788da1170aSLeo Liu vcn_v4_0_set_irq_funcs(adev); 798da1170aSLeo Liu 808da1170aSLeo Liu return 0; 818da1170aSLeo Liu } 828da1170aSLeo Liu 838da1170aSLeo Liu /** 848da1170aSLeo Liu * vcn_v4_0_sw_init - sw init for VCN block 858da1170aSLeo Liu * 868da1170aSLeo Liu * @handle: amdgpu_device pointer 878da1170aSLeo Liu * 888da1170aSLeo Liu * Load firmware and sw initialization 898da1170aSLeo Liu */ 908da1170aSLeo Liu static int vcn_v4_0_sw_init(void *handle) 918da1170aSLeo Liu { 928da1170aSLeo Liu struct amdgpu_ring *ring; 938da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 94bb4f196bSRuijing Dong int i, r; 958da1170aSLeo Liu 968da1170aSLeo Liu r = amdgpu_vcn_sw_init(adev); 978da1170aSLeo Liu if (r) 988da1170aSLeo Liu return r; 998da1170aSLeo Liu 1008da1170aSLeo Liu amdgpu_vcn_setup_ucode(adev); 1018da1170aSLeo Liu 1028da1170aSLeo Liu r = amdgpu_vcn_resume(adev); 1038da1170aSLeo Liu if (r) 1048da1170aSLeo Liu return r; 1058da1170aSLeo Liu 1068da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 1078da1170aSLeo Liu volatile struct amdgpu_vcn4_fw_shared *fw_shared; 108bb4f196bSRuijing Dong 1098da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 1108da1170aSLeo Liu continue; 1118da1170aSLeo Liu 1128da1170aSLeo Liu atomic_set(&adev->vcn.inst[i].sched_score, 0); 1138da1170aSLeo Liu 114bb4f196bSRuijing Dong /* VCN UNIFIED TRAP */ 1158da1170aSLeo Liu r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i], 116bb4f196bSRuijing Dong VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq); 1178da1170aSLeo Liu if (r) 1188da1170aSLeo Liu return r; 1198da1170aSLeo Liu 120bb4f196bSRuijing Dong ring = &adev->vcn.inst[i].ring_enc[0]; 1218da1170aSLeo Liu ring->use_doorbell = true; 122bb4f196bSRuijing Dong ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i; 1238da1170aSLeo Liu 124bb4f196bSRuijing Dong sprintf(ring->name, "vcn_unified_%d", i); 1258da1170aSLeo Liu 1268da1170aSLeo Liu r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, 127bb4f196bSRuijing Dong AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score); 1288da1170aSLeo Liu if (r) 1298da1170aSLeo Liu return r; 1308da1170aSLeo Liu 1318da1170aSLeo Liu fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 132bb4f196bSRuijing Dong fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); 1338da1170aSLeo Liu fw_shared->sq.is_enabled = 1; 1348da1170aSLeo Liu 1358da1170aSLeo Liu if (amdgpu_vcnfw_log) 1368da1170aSLeo Liu amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); 1378da1170aSLeo Liu } 1388da1170aSLeo Liu 1398da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) 1408da1170aSLeo Liu adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode; 141bb4f196bSRuijing Dong 1428da1170aSLeo Liu return 0; 1438da1170aSLeo Liu } 1448da1170aSLeo Liu 1458da1170aSLeo Liu /** 1468da1170aSLeo Liu * vcn_v4_0_sw_fini - sw fini for VCN block 1478da1170aSLeo Liu * 1488da1170aSLeo Liu * @handle: amdgpu_device pointer 1498da1170aSLeo Liu * 1508da1170aSLeo Liu * VCN suspend and free up sw allocation 1518da1170aSLeo Liu */ 1528da1170aSLeo Liu static int vcn_v4_0_sw_fini(void *handle) 1538da1170aSLeo Liu { 1548da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1558da1170aSLeo Liu int i, r, idx; 1568da1170aSLeo Liu 1578585732bSGuchun Chen if (drm_dev_enter(adev_to_drm(adev), &idx)) { 1588da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 1598da1170aSLeo Liu volatile struct amdgpu_vcn4_fw_shared *fw_shared; 1608da1170aSLeo Liu 1618da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 1628da1170aSLeo Liu continue; 1638da1170aSLeo Liu 1648da1170aSLeo Liu fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 1658da1170aSLeo Liu fw_shared->present_flag_0 = 0; 1668da1170aSLeo Liu fw_shared->sq.is_enabled = 0; 1678da1170aSLeo Liu } 1688da1170aSLeo Liu 1698da1170aSLeo Liu drm_dev_exit(idx); 1708da1170aSLeo Liu } 1718da1170aSLeo Liu 1728da1170aSLeo Liu r = amdgpu_vcn_suspend(adev); 1738da1170aSLeo Liu if (r) 1748da1170aSLeo Liu return r; 1758da1170aSLeo Liu 1768da1170aSLeo Liu r = amdgpu_vcn_sw_fini(adev); 1778da1170aSLeo Liu 1788da1170aSLeo Liu return r; 1798da1170aSLeo Liu } 1808da1170aSLeo Liu 1818da1170aSLeo Liu /** 1828da1170aSLeo Liu * vcn_v4_0_hw_init - start and test VCN block 1838da1170aSLeo Liu * 1848da1170aSLeo Liu * @handle: amdgpu_device pointer 1858da1170aSLeo Liu * 1868da1170aSLeo Liu * Initialize the hardware, boot up the VCPU and do some testing 1878da1170aSLeo Liu */ 1888da1170aSLeo Liu static int vcn_v4_0_hw_init(void *handle) 1898da1170aSLeo Liu { 1908da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1918da1170aSLeo Liu struct amdgpu_ring *ring; 192bb4f196bSRuijing Dong int i, r; 1938da1170aSLeo Liu 1948da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 1958da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 1968da1170aSLeo Liu continue; 197bb4f196bSRuijing Dong 1988da1170aSLeo Liu ring = &adev->vcn.inst[i].ring_enc[0]; 1998da1170aSLeo Liu 2008da1170aSLeo Liu adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, 2018da1170aSLeo Liu ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i); 2028da1170aSLeo Liu 2038da1170aSLeo Liu r = amdgpu_ring_test_helper(ring); 2048da1170aSLeo Liu if (r) 2058da1170aSLeo Liu goto done; 2068da1170aSLeo Liu } 2078da1170aSLeo Liu 2088da1170aSLeo Liu done: 2098da1170aSLeo Liu if (!r) 2108da1170aSLeo Liu DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", 2118da1170aSLeo Liu (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode"); 2128da1170aSLeo Liu 2138da1170aSLeo Liu return r; 2148da1170aSLeo Liu } 2158da1170aSLeo Liu 2168da1170aSLeo Liu /** 2178da1170aSLeo Liu * vcn_v4_0_hw_fini - stop the hardware block 2188da1170aSLeo Liu * 2198da1170aSLeo Liu * @handle: amdgpu_device pointer 2208da1170aSLeo Liu * 2218da1170aSLeo Liu * Stop the VCN block, mark ring as not ready any more 2228da1170aSLeo Liu */ 2238da1170aSLeo Liu static int vcn_v4_0_hw_fini(void *handle) 2248da1170aSLeo Liu { 2258da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2268da1170aSLeo Liu int i; 2278da1170aSLeo Liu 2288da1170aSLeo Liu cancel_delayed_work_sync(&adev->vcn.idle_work); 2298da1170aSLeo Liu 2308da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 2318da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 2328da1170aSLeo Liu continue; 2338da1170aSLeo Liu 2348da1170aSLeo Liu if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) || 2358da1170aSLeo Liu (adev->vcn.cur_state != AMD_PG_STATE_GATE && 2368da1170aSLeo Liu RREG32_SOC15(VCN, i, regUVD_STATUS))) { 2378da1170aSLeo Liu vcn_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE); 2388da1170aSLeo Liu } 2398da1170aSLeo Liu } 2408da1170aSLeo Liu 2418da1170aSLeo Liu return 0; 2428da1170aSLeo Liu } 2438da1170aSLeo Liu 2448da1170aSLeo Liu /** 2458da1170aSLeo Liu * vcn_v4_0_suspend - suspend VCN block 2468da1170aSLeo Liu * 2478da1170aSLeo Liu * @handle: amdgpu_device pointer 2488da1170aSLeo Liu * 2498da1170aSLeo Liu * HW fini and suspend VCN block 2508da1170aSLeo Liu */ 2518da1170aSLeo Liu static int vcn_v4_0_suspend(void *handle) 2528da1170aSLeo Liu { 2538da1170aSLeo Liu int r; 2548da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2558da1170aSLeo Liu 2568da1170aSLeo Liu r = vcn_v4_0_hw_fini(adev); 2578da1170aSLeo Liu if (r) 2588da1170aSLeo Liu return r; 2598da1170aSLeo Liu 2608da1170aSLeo Liu r = amdgpu_vcn_suspend(adev); 2618da1170aSLeo Liu 2628da1170aSLeo Liu return r; 2638da1170aSLeo Liu } 2648da1170aSLeo Liu 2658da1170aSLeo Liu /** 2668da1170aSLeo Liu * vcn_v4_0_resume - resume VCN block 2678da1170aSLeo Liu * 2688da1170aSLeo Liu * @handle: amdgpu_device pointer 2698da1170aSLeo Liu * 2708da1170aSLeo Liu * Resume firmware and hw init VCN block 2718da1170aSLeo Liu */ 2728da1170aSLeo Liu static int vcn_v4_0_resume(void *handle) 2738da1170aSLeo Liu { 2748da1170aSLeo Liu int r; 2758da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2768da1170aSLeo Liu 2778da1170aSLeo Liu r = amdgpu_vcn_resume(adev); 2788da1170aSLeo Liu if (r) 2798da1170aSLeo Liu return r; 2808da1170aSLeo Liu 2818da1170aSLeo Liu r = vcn_v4_0_hw_init(adev); 2828da1170aSLeo Liu 2838da1170aSLeo Liu return r; 2848da1170aSLeo Liu } 2858da1170aSLeo Liu 2868da1170aSLeo Liu /** 2878da1170aSLeo Liu * vcn_v4_0_mc_resume - memory controller programming 2888da1170aSLeo Liu * 2898da1170aSLeo Liu * @adev: amdgpu_device pointer 2908da1170aSLeo Liu * @inst: instance number 2918da1170aSLeo Liu * 2928da1170aSLeo Liu * Let the VCN memory controller know it's offsets 2938da1170aSLeo Liu */ 2948da1170aSLeo Liu static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst) 2958da1170aSLeo Liu { 2968da1170aSLeo Liu uint32_t offset, size; 2978da1170aSLeo Liu const struct common_firmware_header *hdr; 2988da1170aSLeo Liu 2998da1170aSLeo Liu hdr = (const struct common_firmware_header *)adev->vcn.fw->data; 3008da1170aSLeo Liu size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); 3018da1170aSLeo Liu 3028da1170aSLeo Liu /* cache window 0: fw */ 3038da1170aSLeo Liu if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 3048da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, 3058da1170aSLeo Liu (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo)); 3068da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, 3078da1170aSLeo Liu (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi)); 3088da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0); 3098da1170aSLeo Liu offset = 0; 3108da1170aSLeo Liu } else { 3118da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, 3128da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst].gpu_addr)); 3138da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, 3148da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst].gpu_addr)); 3158da1170aSLeo Liu offset = size; 3168da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3); 3178da1170aSLeo Liu } 3188da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size); 3198da1170aSLeo Liu 3208da1170aSLeo Liu /* cache window 1: stack */ 3218da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW, 3228da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); 3238da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH, 3248da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); 3258da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0); 3268da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE); 3278da1170aSLeo Liu 3288da1170aSLeo Liu /* cache window 2: context */ 3298da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW, 3308da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); 3318da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH, 3328da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); 3338da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0); 3348da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE); 3358da1170aSLeo Liu 3368da1170aSLeo Liu /* non-cache window */ 3378da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW, 3388da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); 3398da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH, 3408da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); 3418da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0); 3428da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0, 3438da1170aSLeo Liu AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared))); 3448da1170aSLeo Liu } 3458da1170aSLeo Liu 3468da1170aSLeo Liu /** 3478da1170aSLeo Liu * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode 3488da1170aSLeo Liu * 3498da1170aSLeo Liu * @adev: amdgpu_device pointer 3508da1170aSLeo Liu * @inst_idx: instance number index 3518da1170aSLeo Liu * @indirect: indirectly write sram 3528da1170aSLeo Liu * 3538da1170aSLeo Liu * Let the VCN memory controller know it's offsets with dpg mode 3548da1170aSLeo Liu */ 3558da1170aSLeo Liu static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) 3568da1170aSLeo Liu { 3578da1170aSLeo Liu uint32_t offset, size; 3588da1170aSLeo Liu const struct common_firmware_header *hdr; 3598da1170aSLeo Liu hdr = (const struct common_firmware_header *)adev->vcn.fw->data; 3608da1170aSLeo Liu size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); 3618da1170aSLeo Liu 3628da1170aSLeo Liu /* cache window 0: fw */ 3638da1170aSLeo Liu if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 3648da1170aSLeo Liu if (!indirect) { 3658da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3668da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 3678da1170aSLeo Liu (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo), 0, indirect); 3688da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3698da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 3708da1170aSLeo Liu (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi), 0, indirect); 3718da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3728da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); 3738da1170aSLeo Liu } else { 3748da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3758da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect); 3768da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3778da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect); 3788da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3798da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); 3808da1170aSLeo Liu } 3818da1170aSLeo Liu offset = 0; 3828da1170aSLeo Liu } else { 3838da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3848da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 3858da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); 3868da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3878da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 3888da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); 3898da1170aSLeo Liu offset = size; 3908da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3918da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 3928da1170aSLeo Liu AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect); 3938da1170aSLeo Liu } 3948da1170aSLeo Liu 3958da1170aSLeo Liu if (!indirect) 3968da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 3978da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect); 3988da1170aSLeo Liu else 3998da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4008da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect); 4018da1170aSLeo Liu 4028da1170aSLeo Liu /* cache window 1: stack */ 4038da1170aSLeo Liu if (!indirect) { 4048da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4058da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 4068da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); 4078da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4088da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 4098da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); 4108da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4118da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); 4128da1170aSLeo Liu } else { 4138da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4148da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect); 4158da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4168da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect); 4178da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4188da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); 4198da1170aSLeo Liu } 4208da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4218da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect); 4228da1170aSLeo Liu 4238da1170aSLeo Liu /* cache window 2: context */ 4248da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4258da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), 4268da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect); 4278da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4288da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), 4298da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect); 4308da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4318da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect); 4328da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4338da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect); 4348da1170aSLeo Liu 4358da1170aSLeo Liu /* non-cache window */ 4368da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4378da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW), 4388da1170aSLeo Liu lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); 4398da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4408da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH), 4418da1170aSLeo Liu upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); 4428da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4438da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect); 4448da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4458da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0), 4468da1170aSLeo Liu AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect); 4478da1170aSLeo Liu 4488da1170aSLeo Liu /* VCN global tiling registers */ 4498da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 4508da1170aSLeo Liu VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); 4518da1170aSLeo Liu } 4528da1170aSLeo Liu 4538da1170aSLeo Liu /** 4548da1170aSLeo Liu * vcn_v4_0_disable_static_power_gating - disable VCN static power gating 4558da1170aSLeo Liu * 4568da1170aSLeo Liu * @adev: amdgpu_device pointer 4578da1170aSLeo Liu * @inst: instance number 4588da1170aSLeo Liu * 4598da1170aSLeo Liu * Disable static power gating for VCN block 4608da1170aSLeo Liu */ 4618da1170aSLeo Liu static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst) 4628da1170aSLeo Liu { 4638da1170aSLeo Liu uint32_t data = 0; 4648da1170aSLeo Liu 4658da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { 4668da1170aSLeo Liu data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT 4678da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT 4688da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT 4698da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT 4708da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT 4718da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT 4728da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT 4738da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT 4748da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT 4758da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT 4768da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT 4778da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT 4788da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT 4798da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); 4808da1170aSLeo Liu 4818da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); 4828da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, 4838da1170aSLeo Liu UVD_PGFSM_STATUS__UVDM_UVDU_UVDLM_PWR_ON_3_0, 0x3F3FFFFF); 4848da1170aSLeo Liu } else { 4858da1170aSLeo Liu uint32_t value; 4868da1170aSLeo Liu 4878da1170aSLeo Liu value = (inst) ? 0x2200800 : 0; 4888da1170aSLeo Liu data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT 4898da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT 4908da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT 4918da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT 4928da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT 4938da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT 4948da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT 4958da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT 4968da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT 4978da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT 4988da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT 4998da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT 5008da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT 5018da1170aSLeo Liu | 1 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); 5028da1170aSLeo Liu 5038da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); 5048da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, value, 0x3F3FFFFF); 5058da1170aSLeo Liu } 5068da1170aSLeo Liu 5078da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS); 5088da1170aSLeo Liu data &= ~0x103; 5098da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN) 5108da1170aSLeo Liu data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON | 5118da1170aSLeo Liu UVD_POWER_STATUS__UVD_PG_EN_MASK; 5128da1170aSLeo Liu 5138da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data); 5148da1170aSLeo Liu 5158da1170aSLeo Liu return; 5168da1170aSLeo Liu } 5178da1170aSLeo Liu 5188da1170aSLeo Liu /** 5198da1170aSLeo Liu * vcn_v4_0_enable_static_power_gating - enable VCN static power gating 5208da1170aSLeo Liu * 5218da1170aSLeo Liu * @adev: amdgpu_device pointer 5228da1170aSLeo Liu * @inst: instance number 5238da1170aSLeo Liu * 5248da1170aSLeo Liu * Enable static power gating for VCN block 5258da1170aSLeo Liu */ 5268da1170aSLeo Liu static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst) 5278da1170aSLeo Liu { 5288da1170aSLeo Liu uint32_t data; 5298da1170aSLeo Liu 5308da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN) { 5318da1170aSLeo Liu /* Before power off, this indicator has to be turned on */ 5328da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS); 5338da1170aSLeo Liu data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK; 5348da1170aSLeo Liu data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF; 5358da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data); 5368da1170aSLeo Liu 5378da1170aSLeo Liu data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT 5388da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT 5398da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT 5408da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT 5418da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT 5428da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT 5438da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT 5448da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT 5458da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT 5468da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT 5478da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT 5488da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT 5498da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT 5508da1170aSLeo Liu | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT); 5518da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data); 5528da1170aSLeo Liu 5538da1170aSLeo Liu data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT 5548da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDS_PWR_STATUS__SHIFT 5558da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT 5568da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDTC_PWR_STATUS__SHIFT 5578da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT 5588da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDTA_PWR_STATUS__SHIFT 5598da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDLM_PWR_STATUS__SHIFT 5608da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT 5618da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT 5628da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT 5638da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDAB_PWR_STATUS__SHIFT 5648da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDTB_PWR_STATUS__SHIFT 5658da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDNA_PWR_STATUS__SHIFT 5668da1170aSLeo Liu | 2 << UVD_PGFSM_STATUS__UVDNB_PWR_STATUS__SHIFT); 5678da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, data, 0x3F3FFFFF); 5688da1170aSLeo Liu } 5698da1170aSLeo Liu 5708da1170aSLeo Liu return; 5718da1170aSLeo Liu } 5728da1170aSLeo Liu 5738da1170aSLeo Liu /** 5748da1170aSLeo Liu * vcn_v4_0_disable_clock_gating - disable VCN clock gating 5758da1170aSLeo Liu * 5768da1170aSLeo Liu * @adev: amdgpu_device pointer 5778da1170aSLeo Liu * @inst: instance number 5788da1170aSLeo Liu * 5798da1170aSLeo Liu * Disable clock gating for VCN block 5808da1170aSLeo Liu */ 5818da1170aSLeo Liu static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst) 5828da1170aSLeo Liu { 5838da1170aSLeo Liu uint32_t data; 5848da1170aSLeo Liu 5858da1170aSLeo Liu if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) 5868da1170aSLeo Liu return; 5878da1170aSLeo Liu 5888da1170aSLeo Liu /* VCN disable CGC */ 5898da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); 5908da1170aSLeo Liu data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK; 5918da1170aSLeo Liu data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; 5928da1170aSLeo Liu data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; 5938da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); 5948da1170aSLeo Liu 5958da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_CGC_GATE); 5968da1170aSLeo Liu data &= ~(UVD_CGC_GATE__SYS_MASK 5978da1170aSLeo Liu | UVD_CGC_GATE__UDEC_MASK 5988da1170aSLeo Liu | UVD_CGC_GATE__MPEG2_MASK 5998da1170aSLeo Liu | UVD_CGC_GATE__REGS_MASK 6008da1170aSLeo Liu | UVD_CGC_GATE__RBC_MASK 6018da1170aSLeo Liu | UVD_CGC_GATE__LMI_MC_MASK 6028da1170aSLeo Liu | UVD_CGC_GATE__LMI_UMC_MASK 6038da1170aSLeo Liu | UVD_CGC_GATE__IDCT_MASK 6048da1170aSLeo Liu | UVD_CGC_GATE__MPRD_MASK 6058da1170aSLeo Liu | UVD_CGC_GATE__MPC_MASK 6068da1170aSLeo Liu | UVD_CGC_GATE__LBSI_MASK 6078da1170aSLeo Liu | UVD_CGC_GATE__LRBBM_MASK 6088da1170aSLeo Liu | UVD_CGC_GATE__UDEC_RE_MASK 6098da1170aSLeo Liu | UVD_CGC_GATE__UDEC_CM_MASK 6108da1170aSLeo Liu | UVD_CGC_GATE__UDEC_IT_MASK 6118da1170aSLeo Liu | UVD_CGC_GATE__UDEC_DB_MASK 6128da1170aSLeo Liu | UVD_CGC_GATE__UDEC_MP_MASK 6138da1170aSLeo Liu | UVD_CGC_GATE__WCB_MASK 6148da1170aSLeo Liu | UVD_CGC_GATE__VCPU_MASK 6158da1170aSLeo Liu | UVD_CGC_GATE__MMSCH_MASK); 6168da1170aSLeo Liu 6178da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_CGC_GATE, data); 6188da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst, regUVD_CGC_GATE, 0, 0xFFFFFFFF); 6198da1170aSLeo Liu 6208da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); 6218da1170aSLeo Liu data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK 6228da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_CM_MODE_MASK 6238da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_IT_MODE_MASK 6248da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_DB_MODE_MASK 6258da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_MP_MODE_MASK 6268da1170aSLeo Liu | UVD_CGC_CTRL__SYS_MODE_MASK 6278da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_MODE_MASK 6288da1170aSLeo Liu | UVD_CGC_CTRL__MPEG2_MODE_MASK 6298da1170aSLeo Liu | UVD_CGC_CTRL__REGS_MODE_MASK 6308da1170aSLeo Liu | UVD_CGC_CTRL__RBC_MODE_MASK 6318da1170aSLeo Liu | UVD_CGC_CTRL__LMI_MC_MODE_MASK 6328da1170aSLeo Liu | UVD_CGC_CTRL__LMI_UMC_MODE_MASK 6338da1170aSLeo Liu | UVD_CGC_CTRL__IDCT_MODE_MASK 6348da1170aSLeo Liu | UVD_CGC_CTRL__MPRD_MODE_MASK 6358da1170aSLeo Liu | UVD_CGC_CTRL__MPC_MODE_MASK 6368da1170aSLeo Liu | UVD_CGC_CTRL__LBSI_MODE_MASK 6378da1170aSLeo Liu | UVD_CGC_CTRL__LRBBM_MODE_MASK 6388da1170aSLeo Liu | UVD_CGC_CTRL__WCB_MODE_MASK 6398da1170aSLeo Liu | UVD_CGC_CTRL__VCPU_MODE_MASK 6408da1170aSLeo Liu | UVD_CGC_CTRL__MMSCH_MODE_MASK); 6418da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); 6428da1170aSLeo Liu 6438da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE); 6448da1170aSLeo Liu data |= (UVD_SUVD_CGC_GATE__SRE_MASK 6458da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_MASK 6468da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SMP_MASK 6478da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SCM_MASK 6488da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SDB_MASK 6498da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SRE_H264_MASK 6508da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK 6518da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_H264_MASK 6528da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK 6538da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SCM_H264_MASK 6548da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK 6558da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SDB_H264_MASK 6568da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK 6578da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SCLR_MASK 6588da1170aSLeo Liu | UVD_SUVD_CGC_GATE__UVD_SC_MASK 6598da1170aSLeo Liu | UVD_SUVD_CGC_GATE__ENT_MASK 6608da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK 6618da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK 6628da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SITE_MASK 6638da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SRE_VP9_MASK 6648da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SCM_VP9_MASK 6658da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK 6668da1170aSLeo Liu | UVD_SUVD_CGC_GATE__SDB_VP9_MASK 6678da1170aSLeo Liu | UVD_SUVD_CGC_GATE__IME_HEVC_MASK); 6688da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE, data); 6698da1170aSLeo Liu 6708da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL); 6718da1170aSLeo Liu data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK 6728da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK 6738da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK 6748da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK 6758da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK 6768da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK 6778da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 6788da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK 6798da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__IME_MODE_MASK 6808da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK); 6818da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data); 6828da1170aSLeo Liu } 6838da1170aSLeo Liu 6848da1170aSLeo Liu /** 6858da1170aSLeo Liu * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode 6868da1170aSLeo Liu * 6878da1170aSLeo Liu * @adev: amdgpu_device pointer 6888da1170aSLeo Liu * @sram_sel: sram select 6898da1170aSLeo Liu * @inst_idx: instance number index 6908da1170aSLeo Liu * @indirect: indirectly write sram 6918da1170aSLeo Liu * 6928da1170aSLeo Liu * Disable clock gating for VCN block with dpg mode 6938da1170aSLeo Liu */ 6948da1170aSLeo Liu static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel, 6958da1170aSLeo Liu int inst_idx, uint8_t indirect) 6968da1170aSLeo Liu { 6978da1170aSLeo Liu uint32_t reg_data = 0; 6988da1170aSLeo Liu 6998da1170aSLeo Liu if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) 7008da1170aSLeo Liu return; 7018da1170aSLeo Liu 7028da1170aSLeo Liu /* enable sw clock gating control */ 7038da1170aSLeo Liu reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; 7048da1170aSLeo Liu reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; 7058da1170aSLeo Liu reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; 7068da1170aSLeo Liu reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK | 7078da1170aSLeo Liu UVD_CGC_CTRL__UDEC_CM_MODE_MASK | 7088da1170aSLeo Liu UVD_CGC_CTRL__UDEC_IT_MODE_MASK | 7098da1170aSLeo Liu UVD_CGC_CTRL__UDEC_DB_MODE_MASK | 7108da1170aSLeo Liu UVD_CGC_CTRL__UDEC_MP_MODE_MASK | 7118da1170aSLeo Liu UVD_CGC_CTRL__SYS_MODE_MASK | 7128da1170aSLeo Liu UVD_CGC_CTRL__UDEC_MODE_MASK | 7138da1170aSLeo Liu UVD_CGC_CTRL__MPEG2_MODE_MASK | 7148da1170aSLeo Liu UVD_CGC_CTRL__REGS_MODE_MASK | 7158da1170aSLeo Liu UVD_CGC_CTRL__RBC_MODE_MASK | 7168da1170aSLeo Liu UVD_CGC_CTRL__LMI_MC_MODE_MASK | 7178da1170aSLeo Liu UVD_CGC_CTRL__LMI_UMC_MODE_MASK | 7188da1170aSLeo Liu UVD_CGC_CTRL__IDCT_MODE_MASK | 7198da1170aSLeo Liu UVD_CGC_CTRL__MPRD_MODE_MASK | 7208da1170aSLeo Liu UVD_CGC_CTRL__MPC_MODE_MASK | 7218da1170aSLeo Liu UVD_CGC_CTRL__LBSI_MODE_MASK | 7228da1170aSLeo Liu UVD_CGC_CTRL__LRBBM_MODE_MASK | 7238da1170aSLeo Liu UVD_CGC_CTRL__WCB_MODE_MASK | 7248da1170aSLeo Liu UVD_CGC_CTRL__VCPU_MODE_MASK); 7258da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 7268da1170aSLeo Liu VCN, inst_idx, regUVD_CGC_CTRL), reg_data, sram_sel, indirect); 7278da1170aSLeo Liu 7288da1170aSLeo Liu /* turn off clock gating */ 7298da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 7308da1170aSLeo Liu VCN, inst_idx, regUVD_CGC_GATE), 0, sram_sel, indirect); 7318da1170aSLeo Liu 7328da1170aSLeo Liu /* turn on SUVD clock gating */ 7338da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 7348da1170aSLeo Liu VCN, inst_idx, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect); 7358da1170aSLeo Liu 7368da1170aSLeo Liu /* turn on sw mode in UVD_SUVD_CGC_CTRL */ 7378da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 7388da1170aSLeo Liu VCN, inst_idx, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect); 7398da1170aSLeo Liu } 7408da1170aSLeo Liu 7418da1170aSLeo Liu /** 7428da1170aSLeo Liu * vcn_v4_0_enable_clock_gating - enable VCN clock gating 7438da1170aSLeo Liu * 7448da1170aSLeo Liu * @adev: amdgpu_device pointer 7458da1170aSLeo Liu * @inst: instance number 7468da1170aSLeo Liu * 7478da1170aSLeo Liu * Enable clock gating for VCN block 7488da1170aSLeo Liu */ 7498da1170aSLeo Liu static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst) 7508da1170aSLeo Liu { 7518da1170aSLeo Liu uint32_t data; 7528da1170aSLeo Liu 7538da1170aSLeo Liu if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG) 7548da1170aSLeo Liu return; 7558da1170aSLeo Liu 7568da1170aSLeo Liu /* enable VCN CGC */ 7578da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); 7588da1170aSLeo Liu data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT; 7598da1170aSLeo Liu data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT; 7608da1170aSLeo Liu data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT; 7618da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); 7628da1170aSLeo Liu 7638da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL); 7648da1170aSLeo Liu data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK 7658da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_CM_MODE_MASK 7668da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_IT_MODE_MASK 7678da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_DB_MODE_MASK 7688da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_MP_MODE_MASK 7698da1170aSLeo Liu | UVD_CGC_CTRL__SYS_MODE_MASK 7708da1170aSLeo Liu | UVD_CGC_CTRL__UDEC_MODE_MASK 7718da1170aSLeo Liu | UVD_CGC_CTRL__MPEG2_MODE_MASK 7728da1170aSLeo Liu | UVD_CGC_CTRL__REGS_MODE_MASK 7738da1170aSLeo Liu | UVD_CGC_CTRL__RBC_MODE_MASK 7748da1170aSLeo Liu | UVD_CGC_CTRL__LMI_MC_MODE_MASK 7758da1170aSLeo Liu | UVD_CGC_CTRL__LMI_UMC_MODE_MASK 7768da1170aSLeo Liu | UVD_CGC_CTRL__IDCT_MODE_MASK 7778da1170aSLeo Liu | UVD_CGC_CTRL__MPRD_MODE_MASK 7788da1170aSLeo Liu | UVD_CGC_CTRL__MPC_MODE_MASK 7798da1170aSLeo Liu | UVD_CGC_CTRL__LBSI_MODE_MASK 7808da1170aSLeo Liu | UVD_CGC_CTRL__LRBBM_MODE_MASK 7818da1170aSLeo Liu | UVD_CGC_CTRL__WCB_MODE_MASK 7828da1170aSLeo Liu | UVD_CGC_CTRL__VCPU_MODE_MASK 7838da1170aSLeo Liu | UVD_CGC_CTRL__MMSCH_MODE_MASK); 7848da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data); 7858da1170aSLeo Liu 7868da1170aSLeo Liu data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL); 7878da1170aSLeo Liu data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK 7888da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK 7898da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK 7908da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK 7918da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK 7928da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK 7938da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK 7948da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK 7958da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__IME_MODE_MASK 7968da1170aSLeo Liu | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK); 7978da1170aSLeo Liu WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data); 7988da1170aSLeo Liu 7998da1170aSLeo Liu return; 8008da1170aSLeo Liu } 8018da1170aSLeo Liu 8028da1170aSLeo Liu /** 8038da1170aSLeo Liu * vcn_v4_0_start_dpg_mode - VCN start with dpg mode 8048da1170aSLeo Liu * 8058da1170aSLeo Liu * @adev: amdgpu_device pointer 8068da1170aSLeo Liu * @inst_idx: instance number index 8078da1170aSLeo Liu * @indirect: indirectly write sram 8088da1170aSLeo Liu * 8098da1170aSLeo Liu * Start VCN block with dpg mode 8108da1170aSLeo Liu */ 8118da1170aSLeo Liu static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) 8128da1170aSLeo Liu { 8138da1170aSLeo Liu volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; 8148da1170aSLeo Liu struct amdgpu_ring *ring; 8158da1170aSLeo Liu uint32_t tmp; 8168da1170aSLeo Liu 8178da1170aSLeo Liu /* disable register anti-hang mechanism */ 8188da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1, 8198da1170aSLeo Liu ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 8208da1170aSLeo Liu /* enable dynamic power gating mode */ 8218da1170aSLeo Liu tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS); 8228da1170aSLeo Liu tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK; 8238da1170aSLeo Liu tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK; 8248da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp); 8258da1170aSLeo Liu 8268da1170aSLeo Liu if (indirect) 8278da1170aSLeo Liu adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; 8288da1170aSLeo Liu 8298da1170aSLeo Liu /* enable clock gating */ 8308da1170aSLeo Liu vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect); 8318da1170aSLeo Liu 8328da1170aSLeo Liu /* enable VCPU clock */ 8338da1170aSLeo Liu tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); 8348da1170aSLeo Liu tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK; 8358da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8368da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect); 8378da1170aSLeo Liu 8388da1170aSLeo Liu /* disable master interupt */ 8398da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8408da1170aSLeo Liu VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect); 8418da1170aSLeo Liu 8428da1170aSLeo Liu /* setup regUVD_LMI_CTRL */ 8438da1170aSLeo Liu tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | 8448da1170aSLeo Liu UVD_LMI_CTRL__REQ_MODE_MASK | 8458da1170aSLeo Liu UVD_LMI_CTRL__CRC_RESET_MASK | 8468da1170aSLeo Liu UVD_LMI_CTRL__MASK_MC_URGENT_MASK | 8478da1170aSLeo Liu UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | 8488da1170aSLeo Liu UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK | 8498da1170aSLeo Liu (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) | 8508da1170aSLeo Liu 0x00100000L); 8518da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8528da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect); 8538da1170aSLeo Liu 8548da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8558da1170aSLeo Liu VCN, inst_idx, regUVD_MPC_CNTL), 8568da1170aSLeo Liu 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect); 8578da1170aSLeo Liu 8588da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8598da1170aSLeo Liu VCN, inst_idx, regUVD_MPC_SET_MUXA0), 8608da1170aSLeo Liu ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | 8618da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | 8628da1170aSLeo Liu (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | 8638da1170aSLeo Liu (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect); 8648da1170aSLeo Liu 8658da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8668da1170aSLeo Liu VCN, inst_idx, regUVD_MPC_SET_MUXB0), 8678da1170aSLeo Liu ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | 8688da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | 8698da1170aSLeo Liu (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | 8708da1170aSLeo Liu (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect); 8718da1170aSLeo Liu 8728da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8738da1170aSLeo Liu VCN, inst_idx, regUVD_MPC_SET_MUX), 8748da1170aSLeo Liu ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | 8758da1170aSLeo Liu (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | 8768da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect); 8778da1170aSLeo Liu 8788da1170aSLeo Liu vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect); 8798da1170aSLeo Liu 8808da1170aSLeo Liu tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); 8818da1170aSLeo Liu tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; 8828da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8838da1170aSLeo Liu VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect); 8848da1170aSLeo Liu 8858da1170aSLeo Liu /* enable LMI MC and UMC channels */ 8868da1170aSLeo Liu tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT; 8878da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8888da1170aSLeo Liu VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect); 8898da1170aSLeo Liu 8908da1170aSLeo Liu /* enable master interrupt */ 8918da1170aSLeo Liu WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( 8928da1170aSLeo Liu VCN, inst_idx, regUVD_MASTINT_EN), 8938da1170aSLeo Liu UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect); 8948da1170aSLeo Liu 8958da1170aSLeo Liu 8968da1170aSLeo Liu if (indirect) 8978da1170aSLeo Liu psp_update_vcn_sram(adev, inst_idx, adev->vcn.inst[inst_idx].dpg_sram_gpu_addr, 8988da1170aSLeo Liu (uint32_t)((uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_curr_addr - 8998da1170aSLeo Liu (uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr)); 9008da1170aSLeo Liu 9018da1170aSLeo Liu ring = &adev->vcn.inst[inst_idx].ring_enc[0]; 9028da1170aSLeo Liu 9038da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr); 9048da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 9058da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4); 906bb4f196bSRuijing Dong 907bb4f196bSRuijing Dong tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE); 908bb4f196bSRuijing Dong tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); 909bb4f196bSRuijing Dong WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp); 910bb4f196bSRuijing Dong fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; 911bb4f196bSRuijing Dong WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0); 912bb4f196bSRuijing Dong WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0); 913bb4f196bSRuijing Dong 9148da1170aSLeo Liu tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR); 9158da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp); 9168da1170aSLeo Liu ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR); 9178da1170aSLeo Liu 918bb4f196bSRuijing Dong tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE); 919bb4f196bSRuijing Dong tmp |= VCN_RB_ENABLE__RB1_EN_MASK; 920bb4f196bSRuijing Dong WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp); 921bb4f196bSRuijing Dong fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); 922bb4f196bSRuijing Dong 9238da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL, 9248da1170aSLeo Liu ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | 9258da1170aSLeo Liu VCN_RB1_DB_CTRL__EN_MASK); 926bb4f196bSRuijing Dong 9278da1170aSLeo Liu return 0; 9288da1170aSLeo Liu } 9298da1170aSLeo Liu 9308da1170aSLeo Liu 9318da1170aSLeo Liu /** 9328da1170aSLeo Liu * vcn_v4_0_start - VCN start 9338da1170aSLeo Liu * 9348da1170aSLeo Liu * @adev: amdgpu_device pointer 9358da1170aSLeo Liu * 9368da1170aSLeo Liu * Start VCN block 9378da1170aSLeo Liu */ 9388da1170aSLeo Liu static int vcn_v4_0_start(struct amdgpu_device *adev) 9398da1170aSLeo Liu { 9408da1170aSLeo Liu volatile struct amdgpu_vcn4_fw_shared *fw_shared; 9418da1170aSLeo Liu struct amdgpu_ring *ring; 9428da1170aSLeo Liu uint32_t tmp; 9438da1170aSLeo Liu int i, j, k, r; 9448da1170aSLeo Liu 9458da1170aSLeo Liu if (adev->pm.dpm_enabled) 9468da1170aSLeo Liu amdgpu_dpm_enable_uvd(adev, true); 9478da1170aSLeo Liu 9488da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 949bb4f196bSRuijing Dong fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 950bb4f196bSRuijing Dong 9518da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { 9528da1170aSLeo Liu r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram); 9538da1170aSLeo Liu continue; 9548da1170aSLeo Liu } 9558da1170aSLeo Liu 9568da1170aSLeo Liu /* disable VCN power gating */ 9578da1170aSLeo Liu vcn_v4_0_disable_static_power_gating(adev, i); 9588da1170aSLeo Liu 9598da1170aSLeo Liu /* set VCN status busy */ 9608da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; 9618da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_STATUS, tmp); 9628da1170aSLeo Liu 9638da1170aSLeo Liu /*SW clock gating */ 9648da1170aSLeo Liu vcn_v4_0_disable_clock_gating(adev, i); 9658da1170aSLeo Liu 9668da1170aSLeo Liu /* enable VCPU clock */ 9678da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 9688da1170aSLeo Liu UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); 9698da1170aSLeo Liu 9708da1170aSLeo Liu /* disable master interrupt */ 9718da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0, 9728da1170aSLeo Liu ~UVD_MASTINT_EN__VCPU_EN_MASK); 9738da1170aSLeo Liu 9748da1170aSLeo Liu /* enable LMI MC and UMC channels */ 9758da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0, 9768da1170aSLeo Liu ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); 9778da1170aSLeo Liu 9788da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); 9798da1170aSLeo Liu tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; 9808da1170aSLeo Liu tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; 9818da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); 9828da1170aSLeo Liu 9838da1170aSLeo Liu /* setup regUVD_LMI_CTRL */ 9848da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL); 9858da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp | 9868da1170aSLeo Liu UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | 9878da1170aSLeo Liu UVD_LMI_CTRL__MASK_MC_URGENT_MASK | 9888da1170aSLeo Liu UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | 9898da1170aSLeo Liu UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); 9908da1170aSLeo Liu 9918da1170aSLeo Liu /* setup regUVD_MPC_CNTL */ 9928da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL); 9938da1170aSLeo Liu tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK; 9948da1170aSLeo Liu tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT; 9958da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp); 9968da1170aSLeo Liu 9978da1170aSLeo Liu /* setup UVD_MPC_SET_MUXA0 */ 9988da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0, 9998da1170aSLeo Liu ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) | 10008da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) | 10018da1170aSLeo Liu (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) | 10028da1170aSLeo Liu (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT))); 10038da1170aSLeo Liu 10048da1170aSLeo Liu /* setup UVD_MPC_SET_MUXB0 */ 10058da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0, 10068da1170aSLeo Liu ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) | 10078da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) | 10088da1170aSLeo Liu (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) | 10098da1170aSLeo Liu (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT))); 10108da1170aSLeo Liu 10118da1170aSLeo Liu /* setup UVD_MPC_SET_MUX */ 10128da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX, 10138da1170aSLeo Liu ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) | 10148da1170aSLeo Liu (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) | 10158da1170aSLeo Liu (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT))); 10168da1170aSLeo Liu 10178da1170aSLeo Liu vcn_v4_0_mc_resume(adev, i); 10188da1170aSLeo Liu 10198da1170aSLeo Liu /* VCN global tiling registers */ 10208da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG, 10218da1170aSLeo Liu adev->gfx.config.gb_addr_config); 10228da1170aSLeo Liu 10238da1170aSLeo Liu /* unblock VCPU register access */ 10248da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0, 10258da1170aSLeo Liu ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); 10268da1170aSLeo Liu 10278da1170aSLeo Liu /* release VCPU reset to boot */ 10288da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, 10298da1170aSLeo Liu ~UVD_VCPU_CNTL__BLK_RST_MASK); 10308da1170aSLeo Liu 10318da1170aSLeo Liu for (j = 0; j < 10; ++j) { 10328da1170aSLeo Liu uint32_t status; 10338da1170aSLeo Liu 10348da1170aSLeo Liu for (k = 0; k < 100; ++k) { 10358da1170aSLeo Liu status = RREG32_SOC15(VCN, i, regUVD_STATUS); 10368da1170aSLeo Liu if (status & 2) 10378da1170aSLeo Liu break; 10388da1170aSLeo Liu mdelay(10); 10398da1170aSLeo Liu if (amdgpu_emu_mode==1) 10408da1170aSLeo Liu msleep(1); 10418da1170aSLeo Liu } 10428da1170aSLeo Liu 10438da1170aSLeo Liu if (amdgpu_emu_mode==1) { 1044*736f7308SSonny Jiang r = -1; 10458da1170aSLeo Liu if (status & 2) { 10468da1170aSLeo Liu r = 0; 10478da1170aSLeo Liu break; 10488da1170aSLeo Liu } 10498da1170aSLeo Liu } else { 10508da1170aSLeo Liu r = 0; 10518da1170aSLeo Liu if (status & 2) 10528da1170aSLeo Liu break; 10538da1170aSLeo Liu 1054bb4f196bSRuijing Dong dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); 10558da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 10568da1170aSLeo Liu UVD_VCPU_CNTL__BLK_RST_MASK, 10578da1170aSLeo Liu ~UVD_VCPU_CNTL__BLK_RST_MASK); 10588da1170aSLeo Liu mdelay(10); 10598da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, 10608da1170aSLeo Liu ~UVD_VCPU_CNTL__BLK_RST_MASK); 10618da1170aSLeo Liu 10628da1170aSLeo Liu mdelay(10); 10638da1170aSLeo Liu r = -1; 10648da1170aSLeo Liu } 10658da1170aSLeo Liu } 10668da1170aSLeo Liu 10678da1170aSLeo Liu if (r) { 1068bb4f196bSRuijing Dong dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); 10698da1170aSLeo Liu return r; 10708da1170aSLeo Liu } 10718da1170aSLeo Liu 10728da1170aSLeo Liu /* enable master interrupt */ 10738da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 10748da1170aSLeo Liu UVD_MASTINT_EN__VCPU_EN_MASK, 10758da1170aSLeo Liu ~UVD_MASTINT_EN__VCPU_EN_MASK); 10768da1170aSLeo Liu 10778da1170aSLeo Liu /* clear the busy bit of VCN_STATUS */ 10788da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0, 10798da1170aSLeo Liu ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); 10808da1170aSLeo Liu 10818da1170aSLeo Liu ring = &adev->vcn.inst[i].ring_enc[0]; 10828da1170aSLeo Liu WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL, 10838da1170aSLeo Liu ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | 10848da1170aSLeo Liu VCN_RB1_DB_CTRL__EN_MASK); 1085bb4f196bSRuijing Dong 10868da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr); 10878da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 10888da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4); 1089bb4f196bSRuijing Dong 1090bb4f196bSRuijing Dong tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); 1091bb4f196bSRuijing Dong tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); 1092bb4f196bSRuijing Dong WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); 1093bb4f196bSRuijing Dong fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; 1094bb4f196bSRuijing Dong WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0); 1095bb4f196bSRuijing Dong WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0); 1096bb4f196bSRuijing Dong 1097bb4f196bSRuijing Dong tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR); 1098bb4f196bSRuijing Dong WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp); 1099bb4f196bSRuijing Dong ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR); 1100bb4f196bSRuijing Dong 1101bb4f196bSRuijing Dong tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); 1102bb4f196bSRuijing Dong tmp |= VCN_RB_ENABLE__RB1_EN_MASK; 1103bb4f196bSRuijing Dong WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); 11048da1170aSLeo Liu fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); 11058da1170aSLeo Liu } 11068da1170aSLeo Liu 11078da1170aSLeo Liu return 0; 11088da1170aSLeo Liu } 11098da1170aSLeo Liu 11108da1170aSLeo Liu /** 11118da1170aSLeo Liu * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode 11128da1170aSLeo Liu * 11138da1170aSLeo Liu * @adev: amdgpu_device pointer 11148da1170aSLeo Liu * @inst_idx: instance number index 11158da1170aSLeo Liu * 11168da1170aSLeo Liu * Stop VCN block with dpg mode 11178da1170aSLeo Liu */ 11188da1170aSLeo Liu static int vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) 11198da1170aSLeo Liu { 11208da1170aSLeo Liu uint32_t tmp; 11218da1170aSLeo Liu 11228da1170aSLeo Liu /* Wait for power status to be 1 */ 11238da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, 11248da1170aSLeo Liu UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 11258da1170aSLeo Liu 11268da1170aSLeo Liu /* wait for read ptr to be equal to write ptr */ 11278da1170aSLeo Liu tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR); 11288da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF); 11298da1170aSLeo Liu 11308da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, 11318da1170aSLeo Liu UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 11328da1170aSLeo Liu 11338da1170aSLeo Liu /* disable dynamic power gating mode */ 11348da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0, 11358da1170aSLeo Liu ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); 11368da1170aSLeo Liu return 0; 11378da1170aSLeo Liu } 11388da1170aSLeo Liu 11398da1170aSLeo Liu /** 11408da1170aSLeo Liu * vcn_v4_0_stop - VCN stop 11418da1170aSLeo Liu * 11428da1170aSLeo Liu * @adev: amdgpu_device pointer 11438da1170aSLeo Liu * 11448da1170aSLeo Liu * Stop VCN block 11458da1170aSLeo Liu */ 11468da1170aSLeo Liu static int vcn_v4_0_stop(struct amdgpu_device *adev) 11478da1170aSLeo Liu { 1148bb4f196bSRuijing Dong volatile struct amdgpu_vcn4_fw_shared *fw_shared; 11498da1170aSLeo Liu uint32_t tmp; 11508da1170aSLeo Liu int i, r = 0; 11518da1170aSLeo Liu 11528da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 1153bb4f196bSRuijing Dong fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 1154bb4f196bSRuijing Dong fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; 1155bb4f196bSRuijing Dong 11568da1170aSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { 11578da1170aSLeo Liu r = vcn_v4_0_stop_dpg_mode(adev, i); 11588da1170aSLeo Liu continue; 11598da1170aSLeo Liu } 11608da1170aSLeo Liu 11618da1170aSLeo Liu /* wait for vcn idle */ 11628da1170aSLeo Liu r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); 11638da1170aSLeo Liu if (r) 11648da1170aSLeo Liu return r; 11658da1170aSLeo Liu 11668da1170aSLeo Liu tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | 11678da1170aSLeo Liu UVD_LMI_STATUS__READ_CLEAN_MASK | 11688da1170aSLeo Liu UVD_LMI_STATUS__WRITE_CLEAN_MASK | 11698da1170aSLeo Liu UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; 11708da1170aSLeo Liu r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); 11718da1170aSLeo Liu if (r) 11728da1170aSLeo Liu return r; 11738da1170aSLeo Liu 11748da1170aSLeo Liu /* disable LMI UMC channel */ 11758da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2); 11768da1170aSLeo Liu tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; 11778da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp); 11788da1170aSLeo Liu tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | 11798da1170aSLeo Liu UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; 11808da1170aSLeo Liu r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp); 11818da1170aSLeo Liu if (r) 11828da1170aSLeo Liu return r; 11838da1170aSLeo Liu 11848da1170aSLeo Liu /* block VCPU register access */ 11858da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 11868da1170aSLeo Liu UVD_RB_ARB_CTRL__VCPU_DIS_MASK, 11878da1170aSLeo Liu ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); 11888da1170aSLeo Liu 11898da1170aSLeo Liu /* reset VCPU */ 11908da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 11918da1170aSLeo Liu UVD_VCPU_CNTL__BLK_RST_MASK, 11928da1170aSLeo Liu ~UVD_VCPU_CNTL__BLK_RST_MASK); 11938da1170aSLeo Liu 11948da1170aSLeo Liu /* disable VCPU clock */ 11958da1170aSLeo Liu WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0, 11968da1170aSLeo Liu ~(UVD_VCPU_CNTL__CLK_EN_MASK)); 11978da1170aSLeo Liu 11988da1170aSLeo Liu /* apply soft reset */ 11998da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); 12008da1170aSLeo Liu tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; 12018da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); 12028da1170aSLeo Liu tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET); 12038da1170aSLeo Liu tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; 12048da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp); 12058da1170aSLeo Liu 12068da1170aSLeo Liu /* clear status */ 12078da1170aSLeo Liu WREG32_SOC15(VCN, i, regUVD_STATUS, 0); 12088da1170aSLeo Liu 12098da1170aSLeo Liu /* apply HW clock gating */ 12108da1170aSLeo Liu vcn_v4_0_enable_clock_gating(adev, i); 12118da1170aSLeo Liu 12128da1170aSLeo Liu /* enable VCN power gating */ 12138da1170aSLeo Liu vcn_v4_0_enable_static_power_gating(adev, i); 12148da1170aSLeo Liu } 12158da1170aSLeo Liu 12168da1170aSLeo Liu if (adev->pm.dpm_enabled) 12178da1170aSLeo Liu amdgpu_dpm_enable_uvd(adev, false); 12188da1170aSLeo Liu 12198da1170aSLeo Liu return 0; 12208da1170aSLeo Liu } 12218da1170aSLeo Liu 12228da1170aSLeo Liu /** 12238da1170aSLeo Liu * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode 12248da1170aSLeo Liu * 12258da1170aSLeo Liu * @adev: amdgpu_device pointer 12268da1170aSLeo Liu * @inst_idx: instance number index 12278da1170aSLeo Liu * @new_state: pause state 12288da1170aSLeo Liu * 12298da1170aSLeo Liu * Pause dpg mode for VCN block 12308da1170aSLeo Liu */ 12318da1170aSLeo Liu static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, 12328da1170aSLeo Liu struct dpg_pause_state *new_state) 12338da1170aSLeo Liu { 12348da1170aSLeo Liu uint32_t reg_data = 0; 12358da1170aSLeo Liu int ret_code; 12368da1170aSLeo Liu 12378da1170aSLeo Liu /* pause/unpause if state is changed */ 12388da1170aSLeo Liu if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) { 12398da1170aSLeo Liu DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d", 12408da1170aSLeo Liu adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based); 12418da1170aSLeo Liu reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) & 12428da1170aSLeo Liu (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); 12438da1170aSLeo Liu 12448da1170aSLeo Liu if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { 12458da1170aSLeo Liu ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1, 12468da1170aSLeo Liu UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 12478da1170aSLeo Liu 12488da1170aSLeo Liu if (!ret_code) { 12498da1170aSLeo Liu /* pause DPG */ 12508da1170aSLeo Liu reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 12518da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data); 12528da1170aSLeo Liu 12538da1170aSLeo Liu /* wait for ACK */ 12548da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE, 12558da1170aSLeo Liu UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, 12568da1170aSLeo Liu UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); 12578da1170aSLeo Liu 12588da1170aSLeo Liu SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 12598da1170aSLeo Liu UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 12608da1170aSLeo Liu } 12618da1170aSLeo Liu } else { 12628da1170aSLeo Liu /* unpause dpg, no need to wait */ 12638da1170aSLeo Liu reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 12648da1170aSLeo Liu WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data); 12658da1170aSLeo Liu } 12668da1170aSLeo Liu adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based; 12678da1170aSLeo Liu } 12688da1170aSLeo Liu 12698da1170aSLeo Liu return 0; 12708da1170aSLeo Liu } 12718da1170aSLeo Liu 12728da1170aSLeo Liu /** 1273bb4f196bSRuijing Dong * vcn_v4_0_unified_ring_get_rptr - get unified read pointer 12748da1170aSLeo Liu * 12758da1170aSLeo Liu * @ring: amdgpu_ring pointer 12768da1170aSLeo Liu * 1277bb4f196bSRuijing Dong * Returns the current hardware unified read pointer 12788da1170aSLeo Liu */ 1279bb4f196bSRuijing Dong static uint64_t vcn_v4_0_unified_ring_get_rptr(struct amdgpu_ring *ring) 12808da1170aSLeo Liu { 12818da1170aSLeo Liu struct amdgpu_device *adev = ring->adev; 12828da1170aSLeo Liu 1283bb4f196bSRuijing Dong if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 1284bb4f196bSRuijing Dong DRM_ERROR("wrong ring id is identified in %s", __func__); 12858da1170aSLeo Liu 12868da1170aSLeo Liu return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR); 12878da1170aSLeo Liu } 12888da1170aSLeo Liu 12898da1170aSLeo Liu /** 1290bb4f196bSRuijing Dong * vcn_v4_0_unified_ring_get_wptr - get unified write pointer 12918da1170aSLeo Liu * 12928da1170aSLeo Liu * @ring: amdgpu_ring pointer 12938da1170aSLeo Liu * 1294bb4f196bSRuijing Dong * Returns the current hardware unified write pointer 12958da1170aSLeo Liu */ 1296bb4f196bSRuijing Dong static uint64_t vcn_v4_0_unified_ring_get_wptr(struct amdgpu_ring *ring) 12978da1170aSLeo Liu { 12988da1170aSLeo Liu struct amdgpu_device *adev = ring->adev; 12998da1170aSLeo Liu 1300bb4f196bSRuijing Dong if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 1301bb4f196bSRuijing Dong DRM_ERROR("wrong ring id is identified in %s", __func__); 1302bb4f196bSRuijing Dong 13038da1170aSLeo Liu if (ring->use_doorbell) 13048da1170aSLeo Liu return *ring->wptr_cpu_addr; 13058da1170aSLeo Liu else 13068da1170aSLeo Liu return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR); 13078da1170aSLeo Liu } 13088da1170aSLeo Liu 13098da1170aSLeo Liu /** 1310bb4f196bSRuijing Dong * vcn_v4_0_unified_ring_set_wptr - set enc write pointer 13118da1170aSLeo Liu * 13128da1170aSLeo Liu * @ring: amdgpu_ring pointer 13138da1170aSLeo Liu * 13148da1170aSLeo Liu * Commits the enc write pointer to the hardware 13158da1170aSLeo Liu */ 1316bb4f196bSRuijing Dong static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring) 13178da1170aSLeo Liu { 13188da1170aSLeo Liu struct amdgpu_device *adev = ring->adev; 13198da1170aSLeo Liu 1320bb4f196bSRuijing Dong if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 1321bb4f196bSRuijing Dong DRM_ERROR("wrong ring id is identified in %s", __func__); 1322bb4f196bSRuijing Dong 13238da1170aSLeo Liu if (ring->use_doorbell) { 13248da1170aSLeo Liu *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); 13258da1170aSLeo Liu WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); 13268da1170aSLeo Liu } else { 13278da1170aSLeo Liu WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr)); 13288da1170aSLeo Liu } 13298da1170aSLeo Liu } 13308da1170aSLeo Liu 13310b15205cSSonny Jiang static int vcn_v4_0_limit_sched(struct amdgpu_cs_parser *p) 13320b15205cSSonny Jiang { 13330b15205cSSonny Jiang struct drm_gpu_scheduler **scheds; 13340b15205cSSonny Jiang 13350b15205cSSonny Jiang /* The create msg must be in the first IB submitted */ 13360b15205cSSonny Jiang if (atomic_read(&p->entity->fence_seq)) 13370b15205cSSonny Jiang return -EINVAL; 13380b15205cSSonny Jiang 13390b15205cSSonny Jiang scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] 13400b15205cSSonny Jiang [AMDGPU_RING_PRIO_0].sched; 13410b15205cSSonny Jiang drm_sched_entity_modify_sched(p->entity, scheds, 1); 13420b15205cSSonny Jiang return 0; 13430b15205cSSonny Jiang } 13440b15205cSSonny Jiang 13450b15205cSSonny Jiang static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, uint64_t addr) 13460b15205cSSonny Jiang { 13470b15205cSSonny Jiang struct ttm_operation_ctx ctx = { false, false }; 13480b15205cSSonny Jiang struct amdgpu_bo_va_mapping *map; 13490b15205cSSonny Jiang uint32_t *msg, num_buffers; 13500b15205cSSonny Jiang struct amdgpu_bo *bo; 13510b15205cSSonny Jiang uint64_t start, end; 13520b15205cSSonny Jiang unsigned int i; 13530b15205cSSonny Jiang void *ptr; 13540b15205cSSonny Jiang int r; 13550b15205cSSonny Jiang 13560b15205cSSonny Jiang addr &= AMDGPU_GMC_HOLE_MASK; 13570b15205cSSonny Jiang r = amdgpu_cs_find_mapping(p, addr, &bo, &map); 13580b15205cSSonny Jiang if (r) { 13590b15205cSSonny Jiang DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr); 13600b15205cSSonny Jiang return r; 13610b15205cSSonny Jiang } 13620b15205cSSonny Jiang 13630b15205cSSonny Jiang start = map->start * AMDGPU_GPU_PAGE_SIZE; 13640b15205cSSonny Jiang end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE; 13650b15205cSSonny Jiang if (addr & 0x7) { 13660b15205cSSonny Jiang DRM_ERROR("VCN messages must be 8 byte aligned!\n"); 13670b15205cSSonny Jiang return -EINVAL; 13680b15205cSSonny Jiang } 13690b15205cSSonny Jiang 13700b15205cSSonny Jiang bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; 13710b15205cSSonny Jiang amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); 13720b15205cSSonny Jiang r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); 13730b15205cSSonny Jiang if (r) { 13740b15205cSSonny Jiang DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r); 13750b15205cSSonny Jiang return r; 13760b15205cSSonny Jiang } 13770b15205cSSonny Jiang 13780b15205cSSonny Jiang r = amdgpu_bo_kmap(bo, &ptr); 13790b15205cSSonny Jiang if (r) { 13800b15205cSSonny Jiang DRM_ERROR("Failed mapping the VCN message (%d)!\n", r); 13810b15205cSSonny Jiang return r; 13820b15205cSSonny Jiang } 13830b15205cSSonny Jiang 13840b15205cSSonny Jiang msg = ptr + addr - start; 13850b15205cSSonny Jiang 13860b15205cSSonny Jiang /* Check length */ 13870b15205cSSonny Jiang if (msg[1] > end - addr) { 13880b15205cSSonny Jiang r = -EINVAL; 13890b15205cSSonny Jiang goto out; 13900b15205cSSonny Jiang } 13910b15205cSSonny Jiang 13920b15205cSSonny Jiang if (msg[3] != RDECODE_MSG_CREATE) 13930b15205cSSonny Jiang goto out; 13940b15205cSSonny Jiang 13950b15205cSSonny Jiang num_buffers = msg[2]; 13960b15205cSSonny Jiang for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { 13970b15205cSSonny Jiang uint32_t offset, size, *create; 13980b15205cSSonny Jiang 13990b15205cSSonny Jiang if (msg[0] != RDECODE_MESSAGE_CREATE) 14000b15205cSSonny Jiang continue; 14010b15205cSSonny Jiang 14020b15205cSSonny Jiang offset = msg[1]; 14030b15205cSSonny Jiang size = msg[2]; 14040b15205cSSonny Jiang 14050b15205cSSonny Jiang if (offset + size > end) { 14060b15205cSSonny Jiang r = -EINVAL; 14070b15205cSSonny Jiang goto out; 14080b15205cSSonny Jiang } 14090b15205cSSonny Jiang 14100b15205cSSonny Jiang create = ptr + addr + offset - start; 14110b15205cSSonny Jiang 14120b15205cSSonny Jiang /* H246, HEVC and VP9 can run on any instance */ 14130b15205cSSonny Jiang if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) 14140b15205cSSonny Jiang continue; 14150b15205cSSonny Jiang 14160b15205cSSonny Jiang r = vcn_v4_0_limit_sched(p); 14170b15205cSSonny Jiang if (r) 14180b15205cSSonny Jiang goto out; 14190b15205cSSonny Jiang } 14200b15205cSSonny Jiang 14210b15205cSSonny Jiang out: 14220b15205cSSonny Jiang amdgpu_bo_kunmap(bo); 14230b15205cSSonny Jiang return r; 14240b15205cSSonny Jiang } 14250b15205cSSonny Jiang 14260b15205cSSonny Jiang #define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) 14270b15205cSSonny Jiang 14280b15205cSSonny Jiang static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, 14290b15205cSSonny Jiang struct amdgpu_job *job, 14300b15205cSSonny Jiang struct amdgpu_ib *ib) 14310b15205cSSonny Jiang { 14320b15205cSSonny Jiang struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched); 14330b15205cSSonny Jiang struct amdgpu_vcn_decode_buffer *decode_buffer = NULL; 14340b15205cSSonny Jiang uint32_t val; 14350b15205cSSonny Jiang int r = 0; 14360b15205cSSonny Jiang 14370b15205cSSonny Jiang /* The first instance can decode anything */ 14380b15205cSSonny Jiang if (!ring->me) 14390b15205cSSonny Jiang return r; 14400b15205cSSonny Jiang 14410b15205cSSonny Jiang /* unified queue ib header has 8 double words. */ 14420b15205cSSonny Jiang if (ib->length_dw < 8) 14430b15205cSSonny Jiang return r; 14440b15205cSSonny Jiang 14450b15205cSSonny Jiang val = amdgpu_ib_get_value(ib, 6); //RADEON_VCN_ENGINE_TYPE 14460b15205cSSonny Jiang 14470b15205cSSonny Jiang if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { 14480b15205cSSonny Jiang decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[10]; 14490b15205cSSonny Jiang 14500b15205cSSonny Jiang if (decode_buffer->valid_buf_flag & 0x1) 14510b15205cSSonny Jiang r = vcn_v4_0_dec_msg(p, ((u64)decode_buffer->msg_buffer_address_hi) << 32 | 14520b15205cSSonny Jiang decode_buffer->msg_buffer_address_lo); 14530b15205cSSonny Jiang } 14540b15205cSSonny Jiang return r; 14550b15205cSSonny Jiang } 14560b15205cSSonny Jiang 1457bb4f196bSRuijing Dong static const struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = { 14588da1170aSLeo Liu .type = AMDGPU_RING_TYPE_VCN_ENC, 14598da1170aSLeo Liu .align_mask = 0x3f, 14608da1170aSLeo Liu .nop = VCN_ENC_CMD_NO_OP, 14618da1170aSLeo Liu .vmhub = AMDGPU_MMHUB_0, 1462bb4f196bSRuijing Dong .get_rptr = vcn_v4_0_unified_ring_get_rptr, 1463bb4f196bSRuijing Dong .get_wptr = vcn_v4_0_unified_ring_get_wptr, 1464bb4f196bSRuijing Dong .set_wptr = vcn_v4_0_unified_ring_set_wptr, 14650b15205cSSonny Jiang .patch_cs_in_place = vcn_v4_0_ring_patch_cs_in_place, 14668da1170aSLeo Liu .emit_frame_size = 14678da1170aSLeo Liu SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + 14688da1170aSLeo Liu SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + 14698da1170aSLeo Liu 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ 14708da1170aSLeo Liu 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ 14718da1170aSLeo Liu 1, /* vcn_v2_0_enc_ring_insert_end */ 14728da1170aSLeo Liu .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */ 14738da1170aSLeo Liu .emit_ib = vcn_v2_0_enc_ring_emit_ib, 14748da1170aSLeo Liu .emit_fence = vcn_v2_0_enc_ring_emit_fence, 14758da1170aSLeo Liu .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush, 14768da1170aSLeo Liu .test_ring = amdgpu_vcn_enc_ring_test_ring, 1477bb4f196bSRuijing Dong .test_ib = amdgpu_vcn_unified_ring_test_ib, 14788da1170aSLeo Liu .insert_nop = amdgpu_ring_insert_nop, 14798da1170aSLeo Liu .insert_end = vcn_v2_0_enc_ring_insert_end, 14808da1170aSLeo Liu .pad_ib = amdgpu_ring_generic_pad_ib, 14818da1170aSLeo Liu .begin_use = amdgpu_vcn_ring_begin_use, 14828da1170aSLeo Liu .end_use = amdgpu_vcn_ring_end_use, 14838da1170aSLeo Liu .emit_wreg = vcn_v2_0_enc_ring_emit_wreg, 14848da1170aSLeo Liu .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait, 14858da1170aSLeo Liu .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, 14868da1170aSLeo Liu }; 14878da1170aSLeo Liu 14888da1170aSLeo Liu /** 1489bb4f196bSRuijing Dong * vcn_v4_0_set_unified_ring_funcs - set unified ring functions 14908da1170aSLeo Liu * 14918da1170aSLeo Liu * @adev: amdgpu_device pointer 14928da1170aSLeo Liu * 1493bb4f196bSRuijing Dong * Set unified ring functions 14948da1170aSLeo Liu */ 1495bb4f196bSRuijing Dong static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev) 14968da1170aSLeo Liu { 14978da1170aSLeo Liu int i; 14988da1170aSLeo Liu 14998da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 15008da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 15018da1170aSLeo Liu continue; 15028da1170aSLeo Liu 1503bb4f196bSRuijing Dong adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_unified_ring_vm_funcs; 1504bb4f196bSRuijing Dong adev->vcn.inst[i].ring_enc[0].me = i; 15058da1170aSLeo Liu 1506bb4f196bSRuijing Dong DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i); 15078da1170aSLeo Liu } 15088da1170aSLeo Liu } 15098da1170aSLeo Liu 15108da1170aSLeo Liu /** 15118da1170aSLeo Liu * vcn_v4_0_is_idle - check VCN block is idle 15128da1170aSLeo Liu * 15138da1170aSLeo Liu * @handle: amdgpu_device pointer 15148da1170aSLeo Liu * 15158da1170aSLeo Liu * Check whether VCN block is idle 15168da1170aSLeo Liu */ 15178da1170aSLeo Liu static bool vcn_v4_0_is_idle(void *handle) 15188da1170aSLeo Liu { 15198da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 15208da1170aSLeo Liu int i, ret = 1; 15218da1170aSLeo Liu 15228da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 15238da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 15248da1170aSLeo Liu continue; 15258da1170aSLeo Liu 15268da1170aSLeo Liu ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE); 15278da1170aSLeo Liu } 15288da1170aSLeo Liu 15298da1170aSLeo Liu return ret; 15308da1170aSLeo Liu } 15318da1170aSLeo Liu 15328da1170aSLeo Liu /** 15338da1170aSLeo Liu * vcn_v4_0_wait_for_idle - wait for VCN block idle 15348da1170aSLeo Liu * 15358da1170aSLeo Liu * @handle: amdgpu_device pointer 15368da1170aSLeo Liu * 15378da1170aSLeo Liu * Wait for VCN block idle 15388da1170aSLeo Liu */ 15398da1170aSLeo Liu static int vcn_v4_0_wait_for_idle(void *handle) 15408da1170aSLeo Liu { 15418da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 15428da1170aSLeo Liu int i, ret = 0; 15438da1170aSLeo Liu 15448da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 15458da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 15468da1170aSLeo Liu continue; 15478da1170aSLeo Liu 15488da1170aSLeo Liu ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 15498da1170aSLeo Liu UVD_STATUS__IDLE); 15508da1170aSLeo Liu if (ret) 15518da1170aSLeo Liu return ret; 15528da1170aSLeo Liu } 15538da1170aSLeo Liu 15548da1170aSLeo Liu return ret; 15558da1170aSLeo Liu } 15568da1170aSLeo Liu 15578da1170aSLeo Liu /** 15588da1170aSLeo Liu * vcn_v4_0_set_clockgating_state - set VCN block clockgating state 15598da1170aSLeo Liu * 15608da1170aSLeo Liu * @handle: amdgpu_device pointer 15618da1170aSLeo Liu * @state: clock gating state 15628da1170aSLeo Liu * 15638da1170aSLeo Liu * Set VCN block clockgating state 15648da1170aSLeo Liu */ 15658da1170aSLeo Liu static int vcn_v4_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) 15668da1170aSLeo Liu { 15678da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 15688da1170aSLeo Liu bool enable = (state == AMD_CG_STATE_GATE) ? true : false; 15698da1170aSLeo Liu int i; 15708da1170aSLeo Liu 15718da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 15728da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 15738da1170aSLeo Liu continue; 15748da1170aSLeo Liu 15758da1170aSLeo Liu if (enable) { 15768da1170aSLeo Liu if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE) 15778da1170aSLeo Liu return -EBUSY; 15788da1170aSLeo Liu vcn_v4_0_enable_clock_gating(adev, i); 15798da1170aSLeo Liu } else { 15808da1170aSLeo Liu vcn_v4_0_disable_clock_gating(adev, i); 15818da1170aSLeo Liu } 15828da1170aSLeo Liu } 15838da1170aSLeo Liu 15848da1170aSLeo Liu return 0; 15858da1170aSLeo Liu } 15868da1170aSLeo Liu 15878da1170aSLeo Liu /** 15888da1170aSLeo Liu * vcn_v4_0_set_powergating_state - set VCN block powergating state 15898da1170aSLeo Liu * 15908da1170aSLeo Liu * @handle: amdgpu_device pointer 15918da1170aSLeo Liu * @state: power gating state 15928da1170aSLeo Liu * 15938da1170aSLeo Liu * Set VCN block powergating state 15948da1170aSLeo Liu */ 15958da1170aSLeo Liu static int vcn_v4_0_set_powergating_state(void *handle, enum amd_powergating_state state) 15968da1170aSLeo Liu { 15978da1170aSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 15988da1170aSLeo Liu int ret; 15998da1170aSLeo Liu 16008da1170aSLeo Liu if(state == adev->vcn.cur_state) 16018da1170aSLeo Liu return 0; 16028da1170aSLeo Liu 16038da1170aSLeo Liu if (state == AMD_PG_STATE_GATE) 16048da1170aSLeo Liu ret = vcn_v4_0_stop(adev); 16058da1170aSLeo Liu else 16068da1170aSLeo Liu ret = vcn_v4_0_start(adev); 16078da1170aSLeo Liu 16088da1170aSLeo Liu if(!ret) 16098da1170aSLeo Liu adev->vcn.cur_state = state; 16108da1170aSLeo Liu 16118da1170aSLeo Liu return ret; 16128da1170aSLeo Liu } 16138da1170aSLeo Liu 16148da1170aSLeo Liu /** 16158da1170aSLeo Liu * vcn_v4_0_set_interrupt_state - set VCN block interrupt state 16168da1170aSLeo Liu * 16178da1170aSLeo Liu * @adev: amdgpu_device pointer 16188da1170aSLeo Liu * @source: interrupt sources 16198da1170aSLeo Liu * @type: interrupt types 16208da1170aSLeo Liu * @state: interrupt states 16218da1170aSLeo Liu * 16228da1170aSLeo Liu * Set VCN block interrupt state 16238da1170aSLeo Liu */ 16248da1170aSLeo Liu static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, 16258da1170aSLeo Liu unsigned type, enum amdgpu_interrupt_state state) 16268da1170aSLeo Liu { 16278da1170aSLeo Liu return 0; 16288da1170aSLeo Liu } 16298da1170aSLeo Liu 16308da1170aSLeo Liu /** 16318da1170aSLeo Liu * vcn_v4_0_process_interrupt - process VCN block interrupt 16328da1170aSLeo Liu * 16338da1170aSLeo Liu * @adev: amdgpu_device pointer 16348da1170aSLeo Liu * @source: interrupt sources 16358da1170aSLeo Liu * @entry: interrupt entry from clients and sources 16368da1170aSLeo Liu * 16378da1170aSLeo Liu * Process VCN block interrupt 16388da1170aSLeo Liu */ 16398da1170aSLeo Liu static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, 16408da1170aSLeo Liu struct amdgpu_iv_entry *entry) 16418da1170aSLeo Liu { 16428da1170aSLeo Liu uint32_t ip_instance; 16438da1170aSLeo Liu 16448da1170aSLeo Liu switch (entry->client_id) { 16458da1170aSLeo Liu case SOC15_IH_CLIENTID_VCN: 16468da1170aSLeo Liu ip_instance = 0; 16478da1170aSLeo Liu break; 16488da1170aSLeo Liu case SOC15_IH_CLIENTID_VCN1: 16498da1170aSLeo Liu ip_instance = 1; 16508da1170aSLeo Liu break; 16518da1170aSLeo Liu default: 16528da1170aSLeo Liu DRM_ERROR("Unhandled client id: %d\n", entry->client_id); 16538da1170aSLeo Liu return 0; 16548da1170aSLeo Liu } 16558da1170aSLeo Liu 16568da1170aSLeo Liu DRM_DEBUG("IH: VCN TRAP\n"); 16578da1170aSLeo Liu 16588da1170aSLeo Liu switch (entry->src_id) { 16598da1170aSLeo Liu case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE: 16608da1170aSLeo Liu amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]); 16618da1170aSLeo Liu break; 16628da1170aSLeo Liu default: 16638da1170aSLeo Liu DRM_ERROR("Unhandled interrupt: %d %d\n", 16648da1170aSLeo Liu entry->src_id, entry->src_data[0]); 16658da1170aSLeo Liu break; 16668da1170aSLeo Liu } 16678da1170aSLeo Liu 16688da1170aSLeo Liu return 0; 16698da1170aSLeo Liu } 16708da1170aSLeo Liu 16718da1170aSLeo Liu static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = { 16728da1170aSLeo Liu .set = vcn_v4_0_set_interrupt_state, 16738da1170aSLeo Liu .process = vcn_v4_0_process_interrupt, 16748da1170aSLeo Liu }; 16758da1170aSLeo Liu 16768da1170aSLeo Liu /** 16778da1170aSLeo Liu * vcn_v4_0_set_irq_funcs - set VCN block interrupt irq functions 16788da1170aSLeo Liu * 16798da1170aSLeo Liu * @adev: amdgpu_device pointer 16808da1170aSLeo Liu * 16818da1170aSLeo Liu * Set VCN block interrupt irq functions 16828da1170aSLeo Liu */ 16838da1170aSLeo Liu static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev) 16848da1170aSLeo Liu { 16858da1170aSLeo Liu int i; 16868da1170aSLeo Liu 16878da1170aSLeo Liu for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 16888da1170aSLeo Liu if (adev->vcn.harvest_config & (1 << i)) 16898da1170aSLeo Liu continue; 16908da1170aSLeo Liu 16918da1170aSLeo Liu adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; 16928da1170aSLeo Liu adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs; 16938da1170aSLeo Liu } 16948da1170aSLeo Liu } 16958da1170aSLeo Liu 16968da1170aSLeo Liu static const struct amd_ip_funcs vcn_v4_0_ip_funcs = { 16978da1170aSLeo Liu .name = "vcn_v4_0", 16988da1170aSLeo Liu .early_init = vcn_v4_0_early_init, 16998da1170aSLeo Liu .late_init = NULL, 17008da1170aSLeo Liu .sw_init = vcn_v4_0_sw_init, 17018da1170aSLeo Liu .sw_fini = vcn_v4_0_sw_fini, 17028da1170aSLeo Liu .hw_init = vcn_v4_0_hw_init, 17038da1170aSLeo Liu .hw_fini = vcn_v4_0_hw_fini, 17048da1170aSLeo Liu .suspend = vcn_v4_0_suspend, 17058da1170aSLeo Liu .resume = vcn_v4_0_resume, 17068da1170aSLeo Liu .is_idle = vcn_v4_0_is_idle, 17078da1170aSLeo Liu .wait_for_idle = vcn_v4_0_wait_for_idle, 17088da1170aSLeo Liu .check_soft_reset = NULL, 17098da1170aSLeo Liu .pre_soft_reset = NULL, 17108da1170aSLeo Liu .soft_reset = NULL, 17118da1170aSLeo Liu .post_soft_reset = NULL, 17128da1170aSLeo Liu .set_clockgating_state = vcn_v4_0_set_clockgating_state, 17138da1170aSLeo Liu .set_powergating_state = vcn_v4_0_set_powergating_state, 17148da1170aSLeo Liu }; 17158da1170aSLeo Liu 17168da1170aSLeo Liu const struct amdgpu_ip_block_version vcn_v4_0_ip_block = 17178da1170aSLeo Liu { 17188da1170aSLeo Liu .type = AMD_IP_BLOCK_TYPE_VCN, 17198da1170aSLeo Liu .major = 4, 17208da1170aSLeo Liu .minor = 0, 17218da1170aSLeo Liu .rev = 0, 17228da1170aSLeo Liu .funcs = &vcn_v4_0_ip_funcs, 17238da1170aSLeo Liu }; 1724