1435 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 */23 24#include <linux/firmware.h>25#include "amdgpu.h"26#include "amdgpu_vcn.h"27#include "amdgpu_pm.h"28#include "soc15.h"29#include "soc15d.h"30#include "soc15_hw_ip.h"31#include "vcn_v2_0.h"32 33#include "vcn/vcn_5_0_0_offset.h"34#include "vcn/vcn_5_0_0_sh_mask.h"35#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"36#include "vcn_v5_0_0.h"37 38#include <drm/drm_drv.h>39 40static const struct amdgpu_hwip_reg_entry vcn_reg_list_5_0[] = {41 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_POWER_STATUS),42 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_STATUS),43 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_CONTEXT_ID),44 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_CONTEXT_ID2),45 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_DATA0),46 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_DATA1),47 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_CMD),48 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI),49 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO),50 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI2),51 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO2),52 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI3),53 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO3),54 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI4),55 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO4),56 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR),57 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR),58 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR2),59 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR2),60 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR3),61 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR3),62 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR4),63 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR4),64 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE),65 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE2),66 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE3),67 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE4),68 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_CTL),69 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_DATA),70 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_MASK),71 SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_PAUSE)72};73 74static int amdgpu_ih_clientid_vcns[] = {75 SOC15_IH_CLIENTID_VCN,76 SOC15_IH_CLIENTID_VCN177};78 79static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev);80static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);81static int vcn_v5_0_0_set_powergating_state(void *handle,82 enum amd_powergating_state state);83static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev,84 int inst_idx, struct dpg_pause_state *new_state);85static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring);86 87/**88 * vcn_v5_0_0_early_init - set function pointers and load microcode89 *90 * @handle: amdgpu_device pointer91 *92 * Set ring and irq function pointers93 * Load microcode from filesystem94 */95static int vcn_v5_0_0_early_init(void *handle)96{97 struct amdgpu_device *adev = (struct amdgpu_device *)handle;98 99 /* re-use enc ring as unified ring */100 adev->vcn.num_enc_rings = 1;101 102 vcn_v5_0_0_set_unified_ring_funcs(adev);103 vcn_v5_0_0_set_irq_funcs(adev);104 105 return amdgpu_vcn_early_init(adev);106}107 108/**109 * vcn_v5_0_0_sw_init - sw init for VCN block110 *111 * @handle: amdgpu_device pointer112 *113 * Load firmware and sw initialization114 */115static int vcn_v5_0_0_sw_init(void *handle)116{117 struct amdgpu_ring *ring;118 struct amdgpu_device *adev = (struct amdgpu_device *)handle;119 int i, r;120 uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_5_0);121 uint32_t *ptr;122 123 r = amdgpu_vcn_sw_init(adev);124 if (r)125 return r;126 127 amdgpu_vcn_setup_ucode(adev);128 129 r = amdgpu_vcn_resume(adev);130 if (r)131 return r;132 133 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {134 volatile struct amdgpu_vcn5_fw_shared *fw_shared;135 136 if (adev->vcn.harvest_config & (1 << i))137 continue;138 139 atomic_set(&adev->vcn.inst[i].sched_score, 0);140 141 /* VCN UNIFIED TRAP */142 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],143 VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq);144 if (r)145 return r;146 147 /* VCN POISON TRAP */148 r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],149 VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq);150 if (r)151 return r;152 153 ring = &adev->vcn.inst[i].ring_enc[0];154 ring->use_doorbell = true;155 ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;156 157 ring->vm_hub = AMDGPU_MMHUB0(0);158 sprintf(ring->name, "vcn_unified_%d", i);159 160 r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,161 AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score);162 if (r)163 return r;164 165 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;166 fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);167 fw_shared->sq.is_enabled = 1;168 169 if (amdgpu_vcnfw_log)170 amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);171 }172 173 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)174 adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;175 176 /* Allocate memory for VCN IP Dump buffer */177 ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);178 if (!ptr) {179 DRM_ERROR("Failed to allocate memory for VCN IP Dump\n");180 adev->vcn.ip_dump = NULL;181 } else {182 adev->vcn.ip_dump = ptr;183 }184 return 0;185}186 187/**188 * vcn_v5_0_0_sw_fini - sw fini for VCN block189 *190 * @handle: amdgpu_device pointer191 *192 * VCN suspend and free up sw allocation193 */194static int vcn_v5_0_0_sw_fini(void *handle)195{196 struct amdgpu_device *adev = (struct amdgpu_device *)handle;197 int i, r, idx;198 199 if (drm_dev_enter(adev_to_drm(adev), &idx)) {200 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {201 volatile struct amdgpu_vcn5_fw_shared *fw_shared;202 203 if (adev->vcn.harvest_config & (1 << i))204 continue;205 206 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;207 fw_shared->present_flag_0 = 0;208 fw_shared->sq.is_enabled = 0;209 }210 211 drm_dev_exit(idx);212 }213 214 r = amdgpu_vcn_suspend(adev);215 if (r)216 return r;217 218 r = amdgpu_vcn_sw_fini(adev);219 220 kfree(adev->vcn.ip_dump);221 222 return r;223}224 225/**226 * vcn_v5_0_0_hw_init - start and test VCN block227 *228 * @handle: amdgpu_device pointer229 *230 * Initialize the hardware, boot up the VCPU and do some testing231 */232static int vcn_v5_0_0_hw_init(void *handle)233{234 struct amdgpu_device *adev = (struct amdgpu_device *)handle;235 struct amdgpu_ring *ring;236 int i, r;237 238 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {239 if (adev->vcn.harvest_config & (1 << i))240 continue;241 242 ring = &adev->vcn.inst[i].ring_enc[0];243 244 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,245 ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i);246 247 r = amdgpu_ring_test_helper(ring);248 if (r)249 return r;250 }251 252 return 0;253}254 255/**256 * vcn_v5_0_0_hw_fini - stop the hardware block257 *258 * @handle: amdgpu_device pointer259 *260 * Stop the VCN block, mark ring as not ready any more261 */262static int vcn_v5_0_0_hw_fini(void *handle)263{264 struct amdgpu_device *adev = (struct amdgpu_device *)handle;265 int i;266 267 cancel_delayed_work_sync(&adev->vcn.idle_work);268 269 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {270 if (adev->vcn.harvest_config & (1 << i))271 continue;272 if (!amdgpu_sriov_vf(adev)) {273 if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||274 (adev->vcn.cur_state != AMD_PG_STATE_GATE &&275 RREG32_SOC15(VCN, i, regUVD_STATUS))) {276 vcn_v5_0_0_set_powergating_state(adev, AMD_PG_STATE_GATE);277 }278 }279 }280 281 return 0;282}283 284/**285 * vcn_v5_0_0_suspend - suspend VCN block286 *287 * @handle: amdgpu_device pointer288 *289 * HW fini and suspend VCN block290 */291static int vcn_v5_0_0_suspend(void *handle)292{293 int r;294 struct amdgpu_device *adev = (struct amdgpu_device *)handle;295 296 r = vcn_v5_0_0_hw_fini(adev);297 if (r)298 return r;299 300 r = amdgpu_vcn_suspend(adev);301 302 return r;303}304 305/**306 * vcn_v5_0_0_resume - resume VCN block307 *308 * @handle: amdgpu_device pointer309 *310 * Resume firmware and hw init VCN block311 */312static int vcn_v5_0_0_resume(void *handle)313{314 int r;315 struct amdgpu_device *adev = (struct amdgpu_device *)handle;316 317 r = amdgpu_vcn_resume(adev);318 if (r)319 return r;320 321 r = vcn_v5_0_0_hw_init(adev);322 323 return r;324}325 326/**327 * vcn_v5_0_0_mc_resume - memory controller programming328 *329 * @adev: amdgpu_device pointer330 * @inst: instance number331 *332 * Let the VCN memory controller know it's offsets333 */334static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst)335{336 uint32_t offset, size;337 const struct common_firmware_header *hdr;338 339 hdr = (const struct common_firmware_header *)adev->vcn.fw[inst]->data;340 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);341 342 /* cache window 0: fw */343 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {344 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,345 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));346 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,347 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));348 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0);349 offset = 0;350 } else {351 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,352 lower_32_bits(adev->vcn.inst[inst].gpu_addr));353 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,354 upper_32_bits(adev->vcn.inst[inst].gpu_addr));355 offset = size;356 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3);357 }358 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size);359 360 /* cache window 1: stack */361 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,362 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));363 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,364 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));365 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0);366 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);367 368 /* cache window 2: context */369 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,370 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));371 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,372 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));373 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0);374 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);375 376 /* non-cache window */377 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,378 lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));379 WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,380 upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));381 WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);382 WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0,383 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)));384}385 386/**387 * vcn_v5_0_0_mc_resume_dpg_mode - memory controller programming for dpg mode388 *389 * @adev: amdgpu_device pointer390 * @inst_idx: instance number index391 * @indirect: indirectly write sram392 *393 * Let the VCN memory controller know it's offsets with dpg mode394 */395static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)396{397 uint32_t offset, size;398 const struct common_firmware_header *hdr;399 400 hdr = (const struct common_firmware_header *)adev->vcn.fw[inst_idx]->data;401 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);402 403 /* cache window 0: fw */404 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {405 if (!indirect) {406 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(407 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),408 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo), 0, indirect);409 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(410 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),411 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi), 0, indirect);412 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(413 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);414 } else {415 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(416 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);417 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(418 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);419 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(420 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);421 }422 offset = 0;423 } else {424 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(425 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),426 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);427 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(428 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),429 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);430 offset = size;431 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(432 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0),433 AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);434 }435 436 if (!indirect)437 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(438 VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);439 else440 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(441 VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);442 443 /* cache window 1: stack */444 if (!indirect) {445 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(446 VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),447 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);448 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(449 VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),450 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);451 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(452 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);453 } else {454 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(455 VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);456 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(457 VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);458 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(459 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);460 }461 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(462 VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);463 464 /* cache window 2: context */465 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(466 VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),467 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect);468 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(469 VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),470 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect);471 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(472 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);473 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(474 VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);475 476 /* non-cache window */477 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(478 VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),479 lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);480 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(481 VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),482 upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);483 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(484 VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);485 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(486 VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0),487 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect);488 489 /* VCN global tiling registers */490 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(491 VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);492 493 return;494}495 496/**497 * vcn_v5_0_0_disable_static_power_gating - disable VCN static power gating498 *499 * @adev: amdgpu_device pointer500 * @inst: instance number501 *502 * Disable static power gating for VCN block503 */504static void vcn_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)505{506 uint32_t data = 0;507 508 if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {509 data = 1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT;510 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);511 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,512 UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);513 514 data = 2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT;515 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);516 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,517 1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,518 UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);519 520 data = 2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT;521 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);522 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,523 1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,524 UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);525 526 data = 2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT;527 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);528 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,529 1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,530 UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);531 } else {532 data = 1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT;533 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);534 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,535 UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);536 537 data = 1 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT;538 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);539 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,540 UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);541 542 data = 1 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT;543 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);544 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,545 UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);546 547 data = 1 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT;548 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);549 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,550 UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);551 }552 553 data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);554 data &= ~0x103;555 if (adev->pg_flags & AMD_PG_SUPPORT_VCN)556 data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON |557 UVD_POWER_STATUS__UVD_PG_EN_MASK;558 559 WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);560 return;561}562 563/**564 * vcn_v5_0_0_enable_static_power_gating - enable VCN static power gating565 *566 * @adev: amdgpu_device pointer567 * @inst: instance number568 *569 * Enable static power gating for VCN block570 */571static void vcn_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)572{573 uint32_t data;574 575 if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {576 /* Before power off, this indicator has to be turned on */577 data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);578 data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;579 data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;580 WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);581 582 data = 2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT;583 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);584 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,585 1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,586 UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);587 588 data = 2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT;589 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);590 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,591 1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,592 UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);593 594 data = 2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT;595 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);596 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,597 1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,598 UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);599 600 data = 2 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT;601 WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG, data);602 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,603 1 << UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS__SHIFT,604 UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);605 }606 return;607}608 609/**610 * vcn_v5_0_0_disable_clock_gating - disable VCN clock gating611 *612 * @adev: amdgpu_device pointer613 * @inst: instance number614 *615 * Disable clock gating for VCN block616 */617static void vcn_v5_0_0_disable_clock_gating(struct amdgpu_device *adev, int inst)618{619 return;620}621 622#if 0623/**624 * vcn_v5_0_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode625 *626 * @adev: amdgpu_device pointer627 * @sram_sel: sram select628 * @inst_idx: instance number index629 * @indirect: indirectly write sram630 *631 * Disable clock gating for VCN block with dpg mode632 */633static void vcn_v5_0_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,634 int inst_idx, uint8_t indirect)635{636 return;637}638#endif639 640/**641 * vcn_v5_0_0_enable_clock_gating - enable VCN clock gating642 *643 * @adev: amdgpu_device pointer644 * @inst: instance number645 *646 * Enable clock gating for VCN block647 */648static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst)649{650 return;651}652 653/**654 * vcn_v5_0_0_start_dpg_mode - VCN start with dpg mode655 *656 * @adev: amdgpu_device pointer657 * @inst_idx: instance number index658 * @indirect: indirectly write sram659 *660 * Start VCN block with dpg mode661 */662static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)663{664 volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;665 struct amdgpu_ring *ring;666 uint32_t tmp;667 668 /* disable register anti-hang mechanism */669 WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1,670 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);671 672 /* enable dynamic power gating mode */673 tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS);674 tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;675 tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;676 WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp);677 678 if (indirect)679 adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;680 681 /* enable VCPU clock */682 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);683 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;684 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(685 VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);686 687 /* disable master interrupt */688 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(689 VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect);690 691 /* setup regUVD_LMI_CTRL */692 tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |693 UVD_LMI_CTRL__REQ_MODE_MASK |694 UVD_LMI_CTRL__CRC_RESET_MASK |695 UVD_LMI_CTRL__MASK_MC_URGENT_MASK |696 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |697 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |698 (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |699 0x00100000L);700 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(701 VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);702 703 vcn_v5_0_0_mc_resume_dpg_mode(adev, inst_idx, indirect);704 705 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);706 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;707 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(708 VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);709 710 /* enable LMI MC and UMC channels */711 tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;712 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(713 VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);714 715 /* enable master interrupt */716 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET(717 VCN, inst_idx, regUVD_MASTINT_EN),718 UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);719 720 if (indirect)721 amdgpu_vcn_psp_update_sram(adev, inst_idx, 0);722 723 ring = &adev->vcn.inst[inst_idx].ring_enc[0];724 725 WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr);726 WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));727 WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4);728 729 tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);730 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);731 WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);732 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;733 WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0);734 WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0);735 736 tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR);737 WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp);738 ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);739 740 tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);741 tmp |= VCN_RB_ENABLE__RB1_EN_MASK;742 WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);743 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);744 745 WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL,746 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |747 VCN_RB1_DB_CTRL__EN_MASK);748 749 return 0;750}751 752/**753 * vcn_v5_0_0_start - VCN start754 *755 * @adev: amdgpu_device pointer756 *757 * Start VCN block758 */759static int vcn_v5_0_0_start(struct amdgpu_device *adev)760{761 volatile struct amdgpu_vcn5_fw_shared *fw_shared;762 struct amdgpu_ring *ring;763 uint32_t tmp;764 int i, j, k, r;765 766 if (adev->pm.dpm_enabled)767 amdgpu_dpm_enable_uvd(adev, true);768 769 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {770 if (adev->vcn.harvest_config & (1 << i))771 continue;772 773 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;774 775 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {776 r = vcn_v5_0_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);777 continue;778 }779 780 /* disable VCN power gating */781 vcn_v5_0_0_disable_static_power_gating(adev, i);782 783 /* set VCN status busy */784 tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;785 WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);786 787 /* enable VCPU clock */788 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),789 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);790 791 /* disable master interrupt */792 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,793 ~UVD_MASTINT_EN__VCPU_EN_MASK);794 795 /* enable LMI MC and UMC channels */796 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,797 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);798 799 tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);800 tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;801 tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;802 WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);803 804 /* setup regUVD_LMI_CTRL */805 tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);806 WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |807 UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |808 UVD_LMI_CTRL__MASK_MC_URGENT_MASK |809 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |810 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);811 812 vcn_v5_0_0_mc_resume(adev, i);813 814 /* VCN global tiling registers */815 WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,816 adev->gfx.config.gb_addr_config);817 818 /* unblock VCPU register access */819 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,820 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);821 822 /* release VCPU reset to boot */823 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,824 ~UVD_VCPU_CNTL__BLK_RST_MASK);825 826 for (j = 0; j < 10; ++j) {827 uint32_t status;828 829 for (k = 0; k < 100; ++k) {830 status = RREG32_SOC15(VCN, i, regUVD_STATUS);831 if (status & 2)832 break;833 mdelay(10);834 if (amdgpu_emu_mode == 1)835 msleep(1);836 }837 838 if (amdgpu_emu_mode == 1) {839 r = -1;840 if (status & 2) {841 r = 0;842 break;843 }844 } else {845 r = 0;846 if (status & 2)847 break;848 849 dev_err(adev->dev,850 "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);851 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),852 UVD_VCPU_CNTL__BLK_RST_MASK,853 ~UVD_VCPU_CNTL__BLK_RST_MASK);854 mdelay(10);855 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,856 ~UVD_VCPU_CNTL__BLK_RST_MASK);857 858 mdelay(10);859 r = -1;860 }861 }862 863 if (r) {864 dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);865 return r;866 }867 868 /* enable master interrupt */869 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),870 UVD_MASTINT_EN__VCPU_EN_MASK,871 ~UVD_MASTINT_EN__VCPU_EN_MASK);872 873 /* clear the busy bit of VCN_STATUS */874 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,875 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));876 877 ring = &adev->vcn.inst[i].ring_enc[0];878 WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,879 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |880 VCN_RB1_DB_CTRL__EN_MASK);881 882 WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);883 WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));884 WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);885 886 tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);887 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);888 WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);889 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;890 WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);891 WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);892 893 tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);894 WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);895 ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);896 897 tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);898 tmp |= VCN_RB_ENABLE__RB1_EN_MASK;899 WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);900 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);901 }902 903 return 0;904}905 906/**907 * vcn_v5_0_0_stop_dpg_mode - VCN stop with dpg mode908 *909 * @adev: amdgpu_device pointer910 * @inst_idx: instance number index911 *912 * Stop VCN block with dpg mode913 */914static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)915{916 struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};917 uint32_t tmp;918 919 vcn_v5_0_0_pause_dpg_mode(adev, inst_idx, &state);920 921 /* Wait for power status to be 1 */922 SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,923 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);924 925 /* wait for read ptr to be equal to write ptr */926 tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);927 SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);928 929 /* disable dynamic power gating mode */930 WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0,931 ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);932 933 return;934}935 936/**937 * vcn_v5_0_0_stop - VCN stop938 *939 * @adev: amdgpu_device pointer940 *941 * Stop VCN block942 */943static int vcn_v5_0_0_stop(struct amdgpu_device *adev)944{945 volatile struct amdgpu_vcn5_fw_shared *fw_shared;946 uint32_t tmp;947 int i, r = 0;948 949 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {950 if (adev->vcn.harvest_config & (1 << i))951 continue;952 953 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;954 fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;955 956 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {957 vcn_v5_0_0_stop_dpg_mode(adev, i);958 continue;959 }960 961 /* wait for vcn idle */962 r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);963 if (r)964 return r;965 966 tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |967 UVD_LMI_STATUS__READ_CLEAN_MASK |968 UVD_LMI_STATUS__WRITE_CLEAN_MASK |969 UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;970 r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);971 if (r)972 return r;973 974 /* disable LMI UMC channel */975 tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);976 tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;977 WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);978 tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |979 UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;980 r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);981 if (r)982 return r;983 984 /* block VCPU register access */985 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),986 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,987 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);988 989 /* reset VCPU */990 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),991 UVD_VCPU_CNTL__BLK_RST_MASK,992 ~UVD_VCPU_CNTL__BLK_RST_MASK);993 994 /* disable VCPU clock */995 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,996 ~(UVD_VCPU_CNTL__CLK_EN_MASK));997 998 /* apply soft reset */999 tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);1000 tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;1001 WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);1002 tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);1003 tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;1004 WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);1005 1006 /* clear status */1007 WREG32_SOC15(VCN, i, regUVD_STATUS, 0);1008 1009 /* enable VCN power gating */1010 vcn_v5_0_0_enable_static_power_gating(adev, i);1011 }1012 1013 if (adev->pm.dpm_enabled)1014 amdgpu_dpm_enable_uvd(adev, false);1015 1016 return 0;1017}1018 1019/**1020 * vcn_v5_0_0_pause_dpg_mode - VCN pause with dpg mode1021 *1022 * @adev: amdgpu_device pointer1023 * @inst_idx: instance number index1024 * @new_state: pause state1025 *1026 * Pause dpg mode for VCN block1027 */1028static int vcn_v5_0_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,1029 struct dpg_pause_state *new_state)1030{1031 uint32_t reg_data = 0;1032 int ret_code;1033 1034 /* pause/unpause if state is changed */1035 if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {1036 DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",1037 adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based);1038 reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &1039 (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);1040 1041 if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {1042 ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,1043 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);1044 1045 if (!ret_code) {1046 /* pause DPG */1047 reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;1048 WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);1049 1050 /* wait for ACK */1051 SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,1052 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,1053 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);1054 }1055 } else {1056 /* unpause dpg, no need to wait */1057 reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;1058 WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);1059 }1060 adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;1061 }1062 1063 return 0;1064}1065 1066/**1067 * vcn_v5_0_0_unified_ring_get_rptr - get unified read pointer1068 *1069 * @ring: amdgpu_ring pointer1070 *1071 * Returns the current hardware unified read pointer1072 */1073static uint64_t vcn_v5_0_0_unified_ring_get_rptr(struct amdgpu_ring *ring)1074{1075 struct amdgpu_device *adev = ring->adev;1076 1077 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1078 DRM_ERROR("wrong ring id is identified in %s", __func__);1079 1080 return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR);1081}1082 1083/**1084 * vcn_v5_0_0_unified_ring_get_wptr - get unified write pointer1085 *1086 * @ring: amdgpu_ring pointer1087 *1088 * Returns the current hardware unified write pointer1089 */1090static uint64_t vcn_v5_0_0_unified_ring_get_wptr(struct amdgpu_ring *ring)1091{1092 struct amdgpu_device *adev = ring->adev;1093 1094 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1095 DRM_ERROR("wrong ring id is identified in %s", __func__);1096 1097 if (ring->use_doorbell)1098 return *ring->wptr_cpu_addr;1099 else1100 return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR);1101}1102 1103/**1104 * vcn_v5_0_0_unified_ring_set_wptr - set enc write pointer1105 *1106 * @ring: amdgpu_ring pointer1107 *1108 * Commits the enc write pointer to the hardware1109 */1110static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring)1111{1112 struct amdgpu_device *adev = ring->adev;1113 1114 if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1115 DRM_ERROR("wrong ring id is identified in %s", __func__);1116 1117 if (ring->use_doorbell) {1118 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);1119 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));1120 } else {1121 WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr));1122 }1123}1124 1125static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {1126 .type = AMDGPU_RING_TYPE_VCN_ENC,1127 .align_mask = 0x3f,1128 .nop = VCN_ENC_CMD_NO_OP,1129 .get_rptr = vcn_v5_0_0_unified_ring_get_rptr,1130 .get_wptr = vcn_v5_0_0_unified_ring_get_wptr,1131 .set_wptr = vcn_v5_0_0_unified_ring_set_wptr,1132 .emit_frame_size =1133 SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +1134 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +1135 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */1136 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */1137 1, /* vcn_v2_0_enc_ring_insert_end */1138 .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */1139 .emit_ib = vcn_v2_0_enc_ring_emit_ib,1140 .emit_fence = vcn_v2_0_enc_ring_emit_fence,1141 .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,1142 .test_ring = amdgpu_vcn_enc_ring_test_ring,1143 .test_ib = amdgpu_vcn_unified_ring_test_ib,1144 .insert_nop = amdgpu_ring_insert_nop,1145 .insert_end = vcn_v2_0_enc_ring_insert_end,1146 .pad_ib = amdgpu_ring_generic_pad_ib,1147 .begin_use = amdgpu_vcn_ring_begin_use,1148 .end_use = amdgpu_vcn_ring_end_use,1149 .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,1150 .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,1151 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,1152};1153 1154/**1155 * vcn_v5_0_0_set_unified_ring_funcs - set unified ring functions1156 *1157 * @adev: amdgpu_device pointer1158 *1159 * Set unified ring functions1160 */1161static void vcn_v5_0_0_set_unified_ring_funcs(struct amdgpu_device *adev)1162{1163 int i;1164 1165 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1166 if (adev->vcn.harvest_config & (1 << i))1167 continue;1168 1169 adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v5_0_0_unified_ring_vm_funcs;1170 adev->vcn.inst[i].ring_enc[0].me = i;1171 }1172}1173 1174/**1175 * vcn_v5_0_0_is_idle - check VCN block is idle1176 *1177 * @handle: amdgpu_device pointer1178 *1179 * Check whether VCN block is idle1180 */1181static bool vcn_v5_0_0_is_idle(void *handle)1182{1183 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1184 int i, ret = 1;1185 1186 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1187 if (adev->vcn.harvest_config & (1 << i))1188 continue;1189 1190 ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE);1191 }1192 1193 return ret;1194}1195 1196/**1197 * vcn_v5_0_0_wait_for_idle - wait for VCN block idle1198 *1199 * @handle: amdgpu_device pointer1200 *1201 * Wait for VCN block idle1202 */1203static int vcn_v5_0_0_wait_for_idle(void *handle)1204{1205 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1206 int i, ret = 0;1207 1208 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1209 if (adev->vcn.harvest_config & (1 << i))1210 continue;1211 1212 ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE,1213 UVD_STATUS__IDLE);1214 if (ret)1215 return ret;1216 }1217 1218 return ret;1219}1220 1221/**1222 * vcn_v5_0_0_set_clockgating_state - set VCN block clockgating state1223 *1224 * @handle: amdgpu_device pointer1225 * @state: clock gating state1226 *1227 * Set VCN block clockgating state1228 */1229static int vcn_v5_0_0_set_clockgating_state(void *handle, enum amd_clockgating_state state)1230{1231 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1232 bool enable = (state == AMD_CG_STATE_GATE) ? true : false;1233 int i;1234 1235 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1236 if (adev->vcn.harvest_config & (1 << i))1237 continue;1238 1239 if (enable) {1240 if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)1241 return -EBUSY;1242 vcn_v5_0_0_enable_clock_gating(adev, i);1243 } else {1244 vcn_v5_0_0_disable_clock_gating(adev, i);1245 }1246 }1247 1248 return 0;1249}1250 1251/**1252 * vcn_v5_0_0_set_powergating_state - set VCN block powergating state1253 *1254 * @handle: amdgpu_device pointer1255 * @state: power gating state1256 *1257 * Set VCN block powergating state1258 */1259static int vcn_v5_0_0_set_powergating_state(void *handle, enum amd_powergating_state state)1260{1261 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1262 int ret;1263 1264 if (state == adev->vcn.cur_state)1265 return 0;1266 1267 if (state == AMD_PG_STATE_GATE)1268 ret = vcn_v5_0_0_stop(adev);1269 else1270 ret = vcn_v5_0_0_start(adev);1271 1272 if (!ret)1273 adev->vcn.cur_state = state;1274 1275 return ret;1276}1277 1278/**1279 * vcn_v5_0_0_process_interrupt - process VCN block interrupt1280 *1281 * @adev: amdgpu_device pointer1282 * @source: interrupt sources1283 * @entry: interrupt entry from clients and sources1284 *1285 * Process VCN block interrupt1286 */1287static int vcn_v5_0_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,1288 struct amdgpu_iv_entry *entry)1289{1290 uint32_t ip_instance;1291 1292 switch (entry->client_id) {1293 case SOC15_IH_CLIENTID_VCN:1294 ip_instance = 0;1295 break;1296 case SOC15_IH_CLIENTID_VCN1:1297 ip_instance = 1;1298 break;1299 default:1300 DRM_ERROR("Unhandled client id: %d\n", entry->client_id);1301 return 0;1302 }1303 1304 DRM_DEBUG("IH: VCN TRAP\n");1305 1306 switch (entry->src_id) {1307 case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:1308 amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);1309 break;1310 case VCN_4_0__SRCID_UVD_POISON:1311 amdgpu_vcn_process_poison_irq(adev, source, entry);1312 break;1313 default:1314 DRM_ERROR("Unhandled interrupt: %d %d\n",1315 entry->src_id, entry->src_data[0]);1316 break;1317 }1318 1319 return 0;1320}1321 1322static const struct amdgpu_irq_src_funcs vcn_v5_0_0_irq_funcs = {1323 .process = vcn_v5_0_0_process_interrupt,1324};1325 1326/**1327 * vcn_v5_0_0_set_irq_funcs - set VCN block interrupt irq functions1328 *1329 * @adev: amdgpu_device pointer1330 *1331 * Set VCN block interrupt irq functions1332 */1333static void vcn_v5_0_0_set_irq_funcs(struct amdgpu_device *adev)1334{1335 int i;1336 1337 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1338 if (adev->vcn.harvest_config & (1 << i))1339 continue;1340 1341 adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;1342 adev->vcn.inst[i].irq.funcs = &vcn_v5_0_0_irq_funcs;1343 }1344}1345 1346static void vcn_v5_0_print_ip_state(void *handle, struct drm_printer *p)1347{1348 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1349 int i, j;1350 uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_5_0);1351 uint32_t inst_off, is_powered;1352 1353 if (!adev->vcn.ip_dump)1354 return;1355 1356 drm_printf(p, "num_instances:%d\n", adev->vcn.num_vcn_inst);1357 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1358 if (adev->vcn.harvest_config & (1 << i)) {1359 drm_printf(p, "\nHarvested Instance:VCN%d Skipping dump\n", i);1360 continue;1361 }1362 1363 inst_off = i * reg_count;1364 is_powered = (adev->vcn.ip_dump[inst_off] &1365 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK) != 1;1366 1367 if (is_powered) {1368 drm_printf(p, "\nActive Instance:VCN%d\n", i);1369 for (j = 0; j < reg_count; j++)1370 drm_printf(p, "%-50s \t 0x%08x\n", vcn_reg_list_5_0[j].reg_name,1371 adev->vcn.ip_dump[inst_off + j]);1372 } else {1373 drm_printf(p, "\nInactive Instance:VCN%d\n", i);1374 }1375 }1376}1377 1378static void vcn_v5_0_dump_ip_state(void *handle)1379{1380 struct amdgpu_device *adev = (struct amdgpu_device *)handle;1381 int i, j;1382 bool is_powered;1383 uint32_t inst_off;1384 uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_5_0);1385 1386 if (!adev->vcn.ip_dump)1387 return;1388 1389 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1390 if (adev->vcn.harvest_config & (1 << i))1391 continue;1392 1393 inst_off = i * reg_count;1394 /* mmUVD_POWER_STATUS is always readable and is first element of the array */1395 adev->vcn.ip_dump[inst_off] = RREG32_SOC15(VCN, i, regUVD_POWER_STATUS);1396 is_powered = (adev->vcn.ip_dump[inst_off] &1397 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK) != 1;1398 1399 if (is_powered)1400 for (j = 1; j < reg_count; j++)1401 adev->vcn.ip_dump[inst_off + j] =1402 RREG32(SOC15_REG_ENTRY_OFFSET_INST(vcn_reg_list_5_0[j], i));1403 }1404}1405 1406static const struct amd_ip_funcs vcn_v5_0_0_ip_funcs = {1407 .name = "vcn_v5_0_0",1408 .early_init = vcn_v5_0_0_early_init,1409 .late_init = NULL,1410 .sw_init = vcn_v5_0_0_sw_init,1411 .sw_fini = vcn_v5_0_0_sw_fini,1412 .hw_init = vcn_v5_0_0_hw_init,1413 .hw_fini = vcn_v5_0_0_hw_fini,1414 .suspend = vcn_v5_0_0_suspend,1415 .resume = vcn_v5_0_0_resume,1416 .is_idle = vcn_v5_0_0_is_idle,1417 .wait_for_idle = vcn_v5_0_0_wait_for_idle,1418 .check_soft_reset = NULL,1419 .pre_soft_reset = NULL,1420 .soft_reset = NULL,1421 .post_soft_reset = NULL,1422 .set_clockgating_state = vcn_v5_0_0_set_clockgating_state,1423 .set_powergating_state = vcn_v5_0_0_set_powergating_state,1424 .dump_ip_state = vcn_v5_0_dump_ip_state,1425 .print_ip_state = vcn_v5_0_print_ip_state,1426};1427 1428const struct amdgpu_ip_block_version vcn_v5_0_0_ip_block = {1429 .type = AMD_IP_BLOCK_TYPE_VCN,1430 .major = 5,1431 .minor = 0,1432 .rev = 0,1433 .funcs = &vcn_v5_0_0_ip_funcs,1434};1435