1 /* 2 * Copyright 2024 Advanced Micro Devices, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 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 #include "vcn_v4_0_3.h" 33 34 #include "vcn/vcn_5_0_0_offset.h" 35 #include "vcn/vcn_5_0_0_sh_mask.h" 36 #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h" 37 #include "vcn_v5_0_0.h" 38 #include "vcn_v5_0_1.h" 39 40 #include <drm/drm_drv.h> 41 42 static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev); 43 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev); 44 static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, 45 enum amd_powergating_state state); 46 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring); 47 48 /** 49 * vcn_v5_0_1_early_init - set function pointers and load microcode 50 * 51 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 52 * 53 * Set ring and irq function pointers 54 * Load microcode from filesystem 55 */ 56 static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) 57 { 58 struct amdgpu_device *adev = ip_block->adev; 59 int i, r; 60 61 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) 62 /* re-use enc ring as unified ring */ 63 adev->vcn.inst[i].num_enc_rings = 1; 64 65 vcn_v5_0_1_set_unified_ring_funcs(adev); 66 vcn_v5_0_1_set_irq_funcs(adev); 67 68 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 69 adev->vcn.inst[i].set_pg_state = vcn_v5_0_1_set_pg_state; 70 71 r = amdgpu_vcn_early_init(adev, i); 72 if (r) 73 return r; 74 } 75 76 return 0; 77 } 78 79 static void vcn_v5_0_1_fw_shared_init(struct amdgpu_device *adev, int inst_idx) 80 { 81 struct amdgpu_vcn5_fw_shared *fw_shared; 82 83 fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; 84 85 if (fw_shared->sq.is_enabled) 86 return; 87 fw_shared->present_flag_0 = 88 cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); 89 fw_shared->sq.is_enabled = 1; 90 91 if (amdgpu_vcnfw_log) 92 amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]); 93 } 94 95 /** 96 * vcn_v5_0_1_sw_init - sw init for VCN block 97 * 98 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 99 * 100 * Load firmware and sw initialization 101 */ 102 static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) 103 { 104 struct amdgpu_device *adev = ip_block->adev; 105 struct amdgpu_ring *ring; 106 int i, r, vcn_inst; 107 108 /* VCN UNIFIED TRAP */ 109 r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 110 VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst->irq); 111 if (r) 112 return r; 113 114 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 115 vcn_inst = GET_INST(VCN, i); 116 117 r = amdgpu_vcn_sw_init(adev, i); 118 if (r) 119 return r; 120 121 amdgpu_vcn_setup_ucode(adev, i); 122 123 r = amdgpu_vcn_resume(adev, i); 124 if (r) 125 return r; 126 127 ring = &adev->vcn.inst[i].ring_enc[0]; 128 ring->use_doorbell = true; 129 ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 9 * vcn_inst; 130 131 ring->vm_hub = AMDGPU_MMHUB0(adev->vcn.inst[i].aid_id); 132 sprintf(ring->name, "vcn_unified_%d", adev->vcn.inst[i].aid_id); 133 134 r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, 135 AMDGPU_RING_PRIO_DEFAULT, &adev->vcn.inst[i].sched_score); 136 if (r) 137 return r; 138 139 vcn_v5_0_1_fw_shared_init(adev, i); 140 } 141 142 /* TODO: Add queue reset mask when FW fully supports it */ 143 adev->vcn.supported_reset = 144 amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]); 145 146 vcn_v5_0_0_alloc_ip_dump(adev); 147 148 return amdgpu_vcn_sysfs_reset_mask_init(adev); 149 } 150 151 /** 152 * vcn_v5_0_1_sw_fini - sw fini for VCN block 153 * 154 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 155 * 156 * VCN suspend and free up sw allocation 157 */ 158 static int vcn_v5_0_1_sw_fini(struct amdgpu_ip_block *ip_block) 159 { 160 struct amdgpu_device *adev = ip_block->adev; 161 int i, r, idx; 162 163 if (drm_dev_enter(adev_to_drm(adev), &idx)) { 164 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 165 volatile struct amdgpu_vcn5_fw_shared *fw_shared; 166 167 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 168 fw_shared->present_flag_0 = 0; 169 fw_shared->sq.is_enabled = 0; 170 } 171 172 drm_dev_exit(idx); 173 } 174 175 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 176 r = amdgpu_vcn_suspend(adev, i); 177 if (r) 178 return r; 179 } 180 181 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 182 r = amdgpu_vcn_sw_fini(adev, i); 183 if (r) 184 return r; 185 } 186 187 amdgpu_vcn_sysfs_reset_mask_fini(adev); 188 189 kfree(adev->vcn.ip_dump); 190 191 return 0; 192 } 193 194 /** 195 * vcn_v5_0_1_hw_init - start and test VCN block 196 * 197 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 198 * 199 * Initialize the hardware, boot up the VCPU and do some testing 200 */ 201 static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) 202 { 203 struct amdgpu_device *adev = ip_block->adev; 204 struct amdgpu_ring *ring; 205 int i, r, vcn_inst; 206 207 if (RREG32_SOC15(VCN, GET_INST(VCN, 0), regVCN_RRMT_CNTL) & 0x100) 208 adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED); 209 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 210 vcn_inst = GET_INST(VCN, i); 211 ring = &adev->vcn.inst[i].ring_enc[0]; 212 213 if (ring->use_doorbell) 214 adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell, 215 ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 216 9 * vcn_inst), 217 adev->vcn.inst[i].aid_id); 218 219 /* Re-init fw_shared, if required */ 220 vcn_v5_0_1_fw_shared_init(adev, i); 221 222 r = amdgpu_ring_test_helper(ring); 223 if (r) 224 return r; 225 } 226 227 return 0; 228 } 229 230 /** 231 * vcn_v5_0_1_hw_fini - stop the hardware block 232 * 233 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 234 * 235 * Stop the VCN block, mark ring as not ready any more 236 */ 237 static int vcn_v5_0_1_hw_fini(struct amdgpu_ip_block *ip_block) 238 { 239 struct amdgpu_device *adev = ip_block->adev; 240 int i; 241 242 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 243 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; 244 245 cancel_delayed_work_sync(&adev->vcn.inst[i].idle_work); 246 if (vinst->cur_state != AMD_PG_STATE_GATE) 247 vinst->set_pg_state(vinst, AMD_PG_STATE_GATE); 248 } 249 250 return 0; 251 } 252 253 /** 254 * vcn_v5_0_1_suspend - suspend VCN block 255 * 256 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 257 * 258 * HW fini and suspend VCN block 259 */ 260 static int vcn_v5_0_1_suspend(struct amdgpu_ip_block *ip_block) 261 { 262 struct amdgpu_device *adev = ip_block->adev; 263 int r, i; 264 265 r = vcn_v5_0_1_hw_fini(ip_block); 266 if (r) 267 return r; 268 269 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 270 r = amdgpu_vcn_suspend(ip_block->adev, i); 271 if (r) 272 return r; 273 } 274 275 return r; 276 } 277 278 /** 279 * vcn_v5_0_1_resume - resume VCN block 280 * 281 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 282 * 283 * Resume firmware and hw init VCN block 284 */ 285 static int vcn_v5_0_1_resume(struct amdgpu_ip_block *ip_block) 286 { 287 struct amdgpu_device *adev = ip_block->adev; 288 int r, i; 289 290 for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 291 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; 292 293 if (amdgpu_in_reset(adev)) 294 vinst->cur_state = AMD_PG_STATE_GATE; 295 296 r = amdgpu_vcn_resume(ip_block->adev, i); 297 if (r) 298 return r; 299 } 300 301 r = vcn_v5_0_1_hw_init(ip_block); 302 303 return r; 304 } 305 306 /** 307 * vcn_v5_0_1_mc_resume - memory controller programming 308 * 309 * @vinst: VCN instance 310 * 311 * Let the VCN memory controller know it's offsets 312 */ 313 static void vcn_v5_0_1_mc_resume(struct amdgpu_vcn_inst *vinst) 314 { 315 struct amdgpu_device *adev = vinst->adev; 316 int inst = vinst->inst; 317 uint32_t offset, size, vcn_inst; 318 const struct common_firmware_header *hdr; 319 320 hdr = (const struct common_firmware_header *)adev->vcn.inst[inst].fw->data; 321 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); 322 323 vcn_inst = GET_INST(VCN, inst); 324 /* cache window 0: fw */ 325 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 326 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, 327 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo)); 328 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, 329 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi)); 330 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0, 0); 331 offset = 0; 332 } else { 333 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, 334 lower_32_bits(adev->vcn.inst[inst].gpu_addr)); 335 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, 336 upper_32_bits(adev->vcn.inst[inst].gpu_addr)); 337 offset = size; 338 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET0, 339 AMDGPU_UVD_FIRMWARE_OFFSET >> 3); 340 } 341 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE0, size); 342 343 /* cache window 1: stack */ 344 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW, 345 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); 346 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH, 347 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset)); 348 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET1, 0); 349 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE); 350 351 /* cache window 2: context */ 352 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW, 353 lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); 354 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH, 355 upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); 356 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_OFFSET2, 0); 357 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE); 358 359 /* non-cache window */ 360 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW, 361 lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); 362 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH, 363 upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); 364 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_OFFSET0, 0); 365 WREG32_SOC15(VCN, vcn_inst, regUVD_VCPU_NONCACHE_SIZE0, 366 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared))); 367 } 368 369 /** 370 * vcn_v5_0_1_mc_resume_dpg_mode - memory controller programming for dpg mode 371 * 372 * @vinst: VCN instance 373 * @indirect: indirectly write sram 374 * 375 * Let the VCN memory controller know it's offsets with dpg mode 376 */ 377 static void vcn_v5_0_1_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst, 378 bool indirect) 379 { 380 struct amdgpu_device *adev = vinst->adev; 381 int inst_idx = vinst->inst; 382 uint32_t offset, size; 383 const struct common_firmware_header *hdr; 384 385 hdr = (const struct common_firmware_header *)adev->vcn.inst[inst_idx].fw->data; 386 size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); 387 388 /* cache window 0: fw */ 389 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 390 if (!indirect) { 391 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 392 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 393 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + 394 inst_idx].tmr_mc_addr_lo), 0, indirect); 395 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 396 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 397 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + 398 inst_idx].tmr_mc_addr_hi), 0, indirect); 399 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 400 VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); 401 } else { 402 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 403 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect); 404 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 405 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect); 406 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 407 VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect); 408 } 409 offset = 0; 410 } else { 411 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 412 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 413 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); 414 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 415 VCN, 0, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 416 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect); 417 offset = size; 418 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 419 VCN, 0, regUVD_VCPU_CACHE_OFFSET0), 420 AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect); 421 } 422 423 if (!indirect) 424 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 425 VCN, 0, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect); 426 else 427 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 428 VCN, 0, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect); 429 430 /* cache window 1: stack */ 431 if (!indirect) { 432 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 433 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 434 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); 435 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 436 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 437 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect); 438 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 439 VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); 440 } else { 441 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 442 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect); 443 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 444 VCN, 0, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect); 445 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 446 VCN, 0, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect); 447 } 448 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 449 VCN, 0, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect); 450 451 /* cache window 2: context */ 452 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 453 VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), 454 lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + 455 AMDGPU_VCN_STACK_SIZE), 0, indirect); 456 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 457 VCN, 0, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), 458 upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + 459 AMDGPU_VCN_STACK_SIZE), 0, indirect); 460 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 461 VCN, 0, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect); 462 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 463 VCN, 0, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect); 464 465 /* non-cache window */ 466 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 467 VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW), 468 lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); 469 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 470 VCN, 0, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH), 471 upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect); 472 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 473 VCN, 0, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect); 474 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 475 VCN, 0, regUVD_VCPU_NONCACHE_SIZE0), 476 AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect); 477 478 /* VCN global tiling registers */ 479 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 480 VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); 481 } 482 483 /** 484 * vcn_v5_0_1_disable_clock_gating - disable VCN clock gating 485 * 486 * @vinst: VCN instance 487 * 488 * Disable clock gating for VCN block 489 */ 490 static void vcn_v5_0_1_disable_clock_gating(struct amdgpu_vcn_inst *vinst) 491 { 492 } 493 494 /** 495 * vcn_v5_0_1_enable_clock_gating - enable VCN clock gating 496 * 497 * @vinst: VCN instance 498 * 499 * Enable clock gating for VCN block 500 */ 501 static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst) 502 { 503 } 504 505 /** 506 * vcn_v5_0_1_pause_dpg_mode - VCN pause with dpg mode 507 * 508 * @vinst: VCN instance 509 * @new_state: pause state 510 * 511 * Pause dpg mode for VCN block 512 */ 513 static int vcn_v5_0_1_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, 514 struct dpg_pause_state *new_state) 515 { 516 struct amdgpu_device *adev = vinst->adev; 517 uint32_t reg_data = 0; 518 int vcn_inst; 519 520 vcn_inst = GET_INST(VCN, vinst->inst); 521 522 /* pause/unpause if state is changed */ 523 if (vinst->pause_state.fw_based != new_state->fw_based) { 524 DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d %s\n", 525 vinst->pause_state.fw_based, new_state->fw_based, 526 new_state->fw_based ? "VCN_DPG_STATE__PAUSE" : "VCN_DPG_STATE__UNPAUSE"); 527 reg_data = RREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE) & 528 (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); 529 530 if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { 531 /* pause DPG */ 532 reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 533 WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data); 534 535 /* wait for ACK */ 536 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_DPG_PAUSE, 537 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, 538 UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); 539 } else { 540 /* unpause DPG, no need to wait */ 541 reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 542 WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data); 543 } 544 vinst->pause_state.fw_based = new_state->fw_based; 545 } 546 547 return 0; 548 } 549 550 551 /** 552 * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode 553 * 554 * @vinst: VCN instance 555 * @indirect: indirectly write sram 556 * 557 * Start VCN block with dpg mode 558 */ 559 static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst, 560 bool indirect) 561 { 562 struct amdgpu_device *adev = vinst->adev; 563 int inst_idx = vinst->inst; 564 volatile struct amdgpu_vcn5_fw_shared *fw_shared = 565 adev->vcn.inst[inst_idx].fw_shared.cpu_addr; 566 struct amdgpu_ring *ring; 567 struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE}; 568 int vcn_inst; 569 uint32_t tmp; 570 571 vcn_inst = GET_INST(VCN, inst_idx); 572 573 /* disable register anti-hang mechanism */ 574 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 1, 575 ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 576 577 /* enable dynamic power gating mode */ 578 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS); 579 tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK; 580 WREG32_SOC15(VCN, vcn_inst, regUVD_POWER_STATUS, tmp); 581 582 if (indirect) { 583 adev->vcn.inst[inst_idx].dpg_sram_curr_addr = 584 (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr; 585 /* Use dummy register 0xDEADBEEF passing AID selection to PSP FW */ 586 WREG32_SOC24_DPG_MODE(inst_idx, 0xDEADBEEF, 587 adev->vcn.inst[inst_idx].aid_id, 0, true); 588 } 589 590 /* enable VCPU clock */ 591 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); 592 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK; 593 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 594 VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect); 595 596 /* disable master interrupt */ 597 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 598 VCN, 0, regUVD_MASTINT_EN), 0, 0, indirect); 599 600 /* setup regUVD_LMI_CTRL */ 601 tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | 602 UVD_LMI_CTRL__REQ_MODE_MASK | 603 UVD_LMI_CTRL__CRC_RESET_MASK | 604 UVD_LMI_CTRL__MASK_MC_URGENT_MASK | 605 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | 606 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK | 607 (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) | 608 0x00100000L); 609 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 610 VCN, 0, regUVD_LMI_CTRL), tmp, 0, indirect); 611 612 vcn_v5_0_1_mc_resume_dpg_mode(vinst, indirect); 613 614 tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT); 615 tmp |= UVD_VCPU_CNTL__CLK_EN_MASK; 616 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 617 VCN, 0, regUVD_VCPU_CNTL), tmp, 0, indirect); 618 619 /* enable LMI MC and UMC channels */ 620 tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT; 621 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 622 VCN, 0, regUVD_LMI_CTRL2), tmp, 0, indirect); 623 624 /* enable master interrupt */ 625 WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( 626 VCN, 0, regUVD_MASTINT_EN), 627 UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect); 628 629 if (indirect) 630 amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM); 631 632 /* Pause dpg */ 633 vcn_v5_0_1_pause_dpg_mode(vinst, &state); 634 635 ring = &adev->vcn.inst[inst_idx].ring_enc[0]; 636 637 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, lower_32_bits(ring->gpu_addr)); 638 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 639 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / sizeof(uint32_t)); 640 641 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); 642 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); 643 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); 644 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; 645 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); 646 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); 647 648 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR); 649 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp); 650 ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); 651 652 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); 653 tmp |= VCN_RB_ENABLE__RB1_EN_MASK; 654 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); 655 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); 656 657 WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL, 658 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | 659 VCN_RB1_DB_CTRL__EN_MASK); 660 /* Read DB_CTRL to flush the write DB_CTRL command. */ 661 RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL); 662 663 return 0; 664 } 665 666 /** 667 * vcn_v5_0_1_start - VCN start 668 * 669 * @vinst: VCN instance 670 * 671 * Start VCN block 672 */ 673 static int vcn_v5_0_1_start(struct amdgpu_vcn_inst *vinst) 674 { 675 struct amdgpu_device *adev = vinst->adev; 676 int i = vinst->inst; 677 volatile struct amdgpu_vcn5_fw_shared *fw_shared; 678 struct amdgpu_ring *ring; 679 uint32_t tmp; 680 int j, k, r, vcn_inst; 681 682 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 683 684 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) 685 return vcn_v5_0_1_start_dpg_mode(vinst, adev->vcn.inst[i].indirect_sram); 686 687 vcn_inst = GET_INST(VCN, i); 688 689 /* set VCN status busy */ 690 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS) | UVD_STATUS__UVD_BUSY; 691 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, tmp); 692 693 /* enable VCPU clock */ 694 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 695 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK); 696 697 /* disable master interrupt */ 698 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 0, 699 ~UVD_MASTINT_EN__VCPU_EN_MASK); 700 701 /* enable LMI MC and UMC channels */ 702 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_LMI_CTRL2), 0, 703 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); 704 705 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); 706 tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; 707 tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; 708 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); 709 710 /* setup regUVD_LMI_CTRL */ 711 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL); 712 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL, tmp | 713 UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | 714 UVD_LMI_CTRL__MASK_MC_URGENT_MASK | 715 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | 716 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK); 717 718 vcn_v5_0_1_mc_resume(vinst); 719 720 /* VCN global tiling registers */ 721 WREG32_SOC15(VCN, vcn_inst, regUVD_GFX10_ADDR_CONFIG, 722 adev->gfx.config.gb_addr_config); 723 724 /* unblock VCPU register access */ 725 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 0, 726 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); 727 728 /* release VCPU reset to boot */ 729 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, 730 ~UVD_VCPU_CNTL__BLK_RST_MASK); 731 732 for (j = 0; j < 10; ++j) { 733 uint32_t status; 734 735 for (k = 0; k < 100; ++k) { 736 status = RREG32_SOC15(VCN, vcn_inst, regUVD_STATUS); 737 if (status & 2) 738 break; 739 mdelay(100); 740 if (amdgpu_emu_mode == 1) 741 msleep(20); 742 } 743 744 if (amdgpu_emu_mode == 1) { 745 r = -1; 746 if (status & 2) { 747 r = 0; 748 break; 749 } 750 } else { 751 r = 0; 752 if (status & 2) 753 break; 754 755 dev_err(adev->dev, 756 "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i); 757 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 758 UVD_VCPU_CNTL__BLK_RST_MASK, 759 ~UVD_VCPU_CNTL__BLK_RST_MASK); 760 mdelay(10); 761 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, 762 ~UVD_VCPU_CNTL__BLK_RST_MASK); 763 764 mdelay(10); 765 r = -1; 766 } 767 } 768 769 if (r) { 770 dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i); 771 return r; 772 } 773 774 /* enable master interrupt */ 775 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_MASTINT_EN), 776 UVD_MASTINT_EN__VCPU_EN_MASK, 777 ~UVD_MASTINT_EN__VCPU_EN_MASK); 778 779 /* clear the busy bit of VCN_STATUS */ 780 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_STATUS), 0, 781 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT)); 782 783 ring = &adev->vcn.inst[i].ring_enc[0]; 784 785 WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL, 786 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | 787 VCN_RB1_DB_CTRL__EN_MASK); 788 789 /* Read DB_CTRL to flush the write DB_CTRL command. */ 790 RREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL); 791 792 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, ring->gpu_addr); 793 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 794 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_SIZE, ring->ring_size / 4); 795 796 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); 797 tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); 798 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); 799 fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; 800 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); 801 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); 802 803 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR); 804 WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, tmp); 805 ring->wptr = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); 806 807 tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); 808 tmp |= VCN_RB_ENABLE__RB1_EN_MASK; 809 WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); 810 fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); 811 812 return 0; 813 } 814 815 /** 816 * vcn_v5_0_1_stop_dpg_mode - VCN stop with dpg mode 817 * 818 * @vinst: VCN instance 819 * 820 * Stop VCN block with dpg mode 821 */ 822 static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst) 823 { 824 struct amdgpu_device *adev = vinst->adev; 825 int inst_idx = vinst->inst; 826 uint32_t tmp; 827 int vcn_inst; 828 struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; 829 830 vcn_inst = GET_INST(VCN, inst_idx); 831 832 /* Unpause dpg */ 833 vcn_v5_0_1_pause_dpg_mode(vinst, &state); 834 835 /* Wait for power status to be 1 */ 836 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1, 837 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); 838 839 /* wait for read ptr to be equal to write ptr */ 840 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR); 841 SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_RB_RPTR, tmp, 0xFFFFFFFF); 842 843 /* disable dynamic power gating mode */ 844 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_POWER_STATUS), 0, 845 ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); 846 } 847 848 /** 849 * vcn_v5_0_1_stop - VCN stop 850 * 851 * @vinst: VCN instance 852 * 853 * Stop VCN block 854 */ 855 static int vcn_v5_0_1_stop(struct amdgpu_vcn_inst *vinst) 856 { 857 struct amdgpu_device *adev = vinst->adev; 858 int i = vinst->inst; 859 volatile struct amdgpu_vcn5_fw_shared *fw_shared; 860 uint32_t tmp; 861 int r = 0, vcn_inst; 862 863 vcn_inst = GET_INST(VCN, i); 864 865 fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; 866 fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; 867 868 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { 869 vcn_v5_0_1_stop_dpg_mode(vinst); 870 return 0; 871 } 872 873 /* wait for vcn idle */ 874 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_STATUS, UVD_STATUS__IDLE, 0x7); 875 if (r) 876 return r; 877 878 tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK | 879 UVD_LMI_STATUS__READ_CLEAN_MASK | 880 UVD_LMI_STATUS__WRITE_CLEAN_MASK | 881 UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK; 882 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); 883 if (r) 884 return r; 885 886 /* disable LMI UMC channel */ 887 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2); 888 tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK; 889 WREG32_SOC15(VCN, vcn_inst, regUVD_LMI_CTRL2, tmp); 890 tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK | 891 UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK; 892 r = SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_LMI_STATUS, tmp, tmp); 893 if (r) 894 return r; 895 896 /* block VCPU register access */ 897 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_RB_ARB_CTRL), 898 UVD_RB_ARB_CTRL__VCPU_DIS_MASK, 899 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK); 900 901 /* reset VCPU */ 902 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 903 UVD_VCPU_CNTL__BLK_RST_MASK, 904 ~UVD_VCPU_CNTL__BLK_RST_MASK); 905 906 /* disable VCPU clock */ 907 WREG32_P(SOC15_REG_OFFSET(VCN, vcn_inst, regUVD_VCPU_CNTL), 0, 908 ~(UVD_VCPU_CNTL__CLK_EN_MASK)); 909 910 /* apply soft reset */ 911 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); 912 tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK; 913 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); 914 tmp = RREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET); 915 tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK; 916 WREG32_SOC15(VCN, vcn_inst, regUVD_SOFT_RESET, tmp); 917 918 /* clear status */ 919 WREG32_SOC15(VCN, vcn_inst, regUVD_STATUS, 0); 920 921 return 0; 922 } 923 924 /** 925 * vcn_v5_0_1_unified_ring_get_rptr - get unified read pointer 926 * 927 * @ring: amdgpu_ring pointer 928 * 929 * Returns the current hardware unified read pointer 930 */ 931 static uint64_t vcn_v5_0_1_unified_ring_get_rptr(struct amdgpu_ring *ring) 932 { 933 struct amdgpu_device *adev = ring->adev; 934 935 if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 936 DRM_ERROR("wrong ring id is identified in %s", __func__); 937 938 return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_RPTR); 939 } 940 941 /** 942 * vcn_v5_0_1_unified_ring_get_wptr - get unified write pointer 943 * 944 * @ring: amdgpu_ring pointer 945 * 946 * Returns the current hardware unified write pointer 947 */ 948 static uint64_t vcn_v5_0_1_unified_ring_get_wptr(struct amdgpu_ring *ring) 949 { 950 struct amdgpu_device *adev = ring->adev; 951 952 if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 953 DRM_ERROR("wrong ring id is identified in %s", __func__); 954 955 if (ring->use_doorbell) 956 return *ring->wptr_cpu_addr; 957 else 958 return RREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR); 959 } 960 961 /** 962 * vcn_v5_0_1_unified_ring_set_wptr - set enc write pointer 963 * 964 * @ring: amdgpu_ring pointer 965 * 966 * Commits the enc write pointer to the hardware 967 */ 968 static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring) 969 { 970 struct amdgpu_device *adev = ring->adev; 971 972 if (ring != &adev->vcn.inst[ring->me].ring_enc[0]) 973 DRM_ERROR("wrong ring id is identified in %s", __func__); 974 975 if (ring->use_doorbell) { 976 *ring->wptr_cpu_addr = lower_32_bits(ring->wptr); 977 WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); 978 } else { 979 WREG32_SOC15(VCN, GET_INST(VCN, ring->me), regUVD_RB_WPTR, 980 lower_32_bits(ring->wptr)); 981 } 982 } 983 984 static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = { 985 .type = AMDGPU_RING_TYPE_VCN_ENC, 986 .align_mask = 0x3f, 987 .nop = VCN_ENC_CMD_NO_OP, 988 .get_rptr = vcn_v5_0_1_unified_ring_get_rptr, 989 .get_wptr = vcn_v5_0_1_unified_ring_get_wptr, 990 .set_wptr = vcn_v5_0_1_unified_ring_set_wptr, 991 .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + 992 SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + 993 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ 994 5 + 995 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ 996 1, /* vcn_v2_0_enc_ring_insert_end */ 997 .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */ 998 .emit_ib = vcn_v2_0_enc_ring_emit_ib, 999 .emit_fence = vcn_v2_0_enc_ring_emit_fence, 1000 .emit_vm_flush = vcn_v4_0_3_enc_ring_emit_vm_flush, 1001 .emit_hdp_flush = vcn_v4_0_3_ring_emit_hdp_flush, 1002 .test_ring = amdgpu_vcn_enc_ring_test_ring, 1003 .test_ib = amdgpu_vcn_unified_ring_test_ib, 1004 .insert_nop = amdgpu_ring_insert_nop, 1005 .insert_end = vcn_v2_0_enc_ring_insert_end, 1006 .pad_ib = amdgpu_ring_generic_pad_ib, 1007 .begin_use = amdgpu_vcn_ring_begin_use, 1008 .end_use = amdgpu_vcn_ring_end_use, 1009 .emit_wreg = vcn_v4_0_3_enc_ring_emit_wreg, 1010 .emit_reg_wait = vcn_v4_0_3_enc_ring_emit_reg_wait, 1011 .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, 1012 }; 1013 1014 /** 1015 * vcn_v5_0_1_set_unified_ring_funcs - set unified ring functions 1016 * 1017 * @adev: amdgpu_device pointer 1018 * 1019 * Set unified ring functions 1020 */ 1021 static void vcn_v5_0_1_set_unified_ring_funcs(struct amdgpu_device *adev) 1022 { 1023 int i, vcn_inst; 1024 1025 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 1026 adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v5_0_1_unified_ring_vm_funcs; 1027 adev->vcn.inst[i].ring_enc[0].me = i; 1028 vcn_inst = GET_INST(VCN, i); 1029 adev->vcn.inst[i].aid_id = vcn_inst / adev->vcn.num_inst_per_aid; 1030 } 1031 } 1032 1033 /** 1034 * vcn_v5_0_1_is_idle - check VCN block is idle 1035 * 1036 * @ip_block: Pointer to the amdgpu_ip_block structure 1037 * 1038 * Check whether VCN block is idle 1039 */ 1040 static bool vcn_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block) 1041 { 1042 struct amdgpu_device *adev = ip_block->adev; 1043 int i, ret = 1; 1044 1045 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) 1046 ret &= (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) == UVD_STATUS__IDLE); 1047 1048 return ret; 1049 } 1050 1051 /** 1052 * vcn_v5_0_1_wait_for_idle - wait for VCN block idle 1053 * 1054 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 1055 * 1056 * Wait for VCN block idle 1057 */ 1058 static int vcn_v5_0_1_wait_for_idle(struct amdgpu_ip_block *ip_block) 1059 { 1060 struct amdgpu_device *adev = ip_block->adev; 1061 int i, ret = 0; 1062 1063 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 1064 ret = SOC15_WAIT_ON_RREG(VCN, GET_INST(VCN, i), regUVD_STATUS, UVD_STATUS__IDLE, 1065 UVD_STATUS__IDLE); 1066 if (ret) 1067 return ret; 1068 } 1069 1070 return ret; 1071 } 1072 1073 /** 1074 * vcn_v5_0_1_set_clockgating_state - set VCN block clockgating state 1075 * 1076 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 1077 * @state: clock gating state 1078 * 1079 * Set VCN block clockgating state 1080 */ 1081 static int vcn_v5_0_1_set_clockgating_state(struct amdgpu_ip_block *ip_block, 1082 enum amd_clockgating_state state) 1083 { 1084 struct amdgpu_device *adev = ip_block->adev; 1085 bool enable = state == AMD_CG_STATE_GATE; 1086 int i; 1087 1088 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { 1089 struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[i]; 1090 1091 if (enable) { 1092 if (RREG32_SOC15(VCN, GET_INST(VCN, i), regUVD_STATUS) != UVD_STATUS__IDLE) 1093 return -EBUSY; 1094 vcn_v5_0_1_enable_clock_gating(vinst); 1095 } else { 1096 vcn_v5_0_1_disable_clock_gating(vinst); 1097 } 1098 } 1099 1100 return 0; 1101 } 1102 1103 static int vcn_v5_0_1_set_pg_state(struct amdgpu_vcn_inst *vinst, 1104 enum amd_powergating_state state) 1105 { 1106 int ret = 0; 1107 1108 if (state == vinst->cur_state) 1109 return 0; 1110 1111 if (state == AMD_PG_STATE_GATE) 1112 ret = vcn_v5_0_1_stop(vinst); 1113 else 1114 ret = vcn_v5_0_1_start(vinst); 1115 1116 if (!ret) 1117 vinst->cur_state = state; 1118 1119 return ret; 1120 } 1121 1122 /** 1123 * vcn_v5_0_1_process_interrupt - process VCN block interrupt 1124 * 1125 * @adev: amdgpu_device pointer 1126 * @source: interrupt sources 1127 * @entry: interrupt entry from clients and sources 1128 * 1129 * Process VCN block interrupt 1130 */ 1131 static int vcn_v5_0_1_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, 1132 struct amdgpu_iv_entry *entry) 1133 { 1134 uint32_t i, inst; 1135 1136 i = node_id_to_phys_map[entry->node_id]; 1137 1138 DRM_DEV_DEBUG(adev->dev, "IH: VCN TRAP\n"); 1139 1140 for (inst = 0; inst < adev->vcn.num_vcn_inst; ++inst) 1141 if (adev->vcn.inst[inst].aid_id == i) 1142 break; 1143 if (inst >= adev->vcn.num_vcn_inst) { 1144 dev_WARN_ONCE(adev->dev, 1, 1145 "Interrupt received for unknown VCN instance %d", 1146 entry->node_id); 1147 return 0; 1148 } 1149 1150 switch (entry->src_id) { 1151 case VCN_5_0__SRCID__UVD_ENC_GENERAL_PURPOSE: 1152 amdgpu_fence_process(&adev->vcn.inst[inst].ring_enc[0]); 1153 break; 1154 default: 1155 DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n", 1156 entry->src_id, entry->src_data[0]); 1157 break; 1158 } 1159 1160 return 0; 1161 } 1162 1163 static const struct amdgpu_irq_src_funcs vcn_v5_0_1_irq_funcs = { 1164 .process = vcn_v5_0_1_process_interrupt, 1165 }; 1166 1167 /** 1168 * vcn_v5_0_1_set_irq_funcs - set VCN block interrupt irq functions 1169 * 1170 * @adev: amdgpu_device pointer 1171 * 1172 * Set VCN block interrupt irq functions 1173 */ 1174 static void vcn_v5_0_1_set_irq_funcs(struct amdgpu_device *adev) 1175 { 1176 int i; 1177 1178 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) 1179 adev->vcn.inst->irq.num_types++; 1180 adev->vcn.inst->irq.funcs = &vcn_v5_0_1_irq_funcs; 1181 } 1182 1183 static const struct amd_ip_funcs vcn_v5_0_1_ip_funcs = { 1184 .name = "vcn_v5_0_1", 1185 .early_init = vcn_v5_0_1_early_init, 1186 .late_init = NULL, 1187 .sw_init = vcn_v5_0_1_sw_init, 1188 .sw_fini = vcn_v5_0_1_sw_fini, 1189 .hw_init = vcn_v5_0_1_hw_init, 1190 .hw_fini = vcn_v5_0_1_hw_fini, 1191 .suspend = vcn_v5_0_1_suspend, 1192 .resume = vcn_v5_0_1_resume, 1193 .is_idle = vcn_v5_0_1_is_idle, 1194 .wait_for_idle = vcn_v5_0_1_wait_for_idle, 1195 .check_soft_reset = NULL, 1196 .pre_soft_reset = NULL, 1197 .soft_reset = NULL, 1198 .post_soft_reset = NULL, 1199 .set_clockgating_state = vcn_v5_0_1_set_clockgating_state, 1200 .set_powergating_state = vcn_set_powergating_state, 1201 .dump_ip_state = vcn_v5_0_0_dump_ip_state, 1202 .print_ip_state = vcn_v5_0_0_print_ip_state, 1203 }; 1204 1205 const struct amdgpu_ip_block_version vcn_v5_0_1_ip_block = { 1206 .type = AMD_IP_BLOCK_TYPE_VCN, 1207 .major = 5, 1208 .minor = 0, 1209 .rev = 1, 1210 .funcs = &vcn_v5_0_1_ip_funcs, 1211 }; 1212