1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2013 Advanced Micro Devices, Inc. 4 * Copyright 2025 Valve Corporation 5 * Copyright 2025 Alexandre Demers 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * The above copyright notice and this permission notice (including the 25 * next paragraph) shall be included in all copies or substantial portions 26 * of the Software. 27 * 28 * Authors: Christian König <christian.koenig@amd.com> 29 * Timur Kristóf <timur.kristof@gmail.com> 30 * Alexandre Demers <alexandre.f.demers@gmail.com> 31 */ 32 33 #include <linux/firmware.h> 34 35 #include "amdgpu.h" 36 #include "amdgpu_vce.h" 37 #include "sid.h" 38 #include "vce_v1_0.h" 39 #include "vce/vce_1_0_d.h" 40 #include "vce/vce_1_0_sh_mask.h" 41 #include "oss/oss_1_0_d.h" 42 #include "oss/oss_1_0_sh_mask.h" 43 44 #define VCE_V1_0_FW_SIZE (256 * 1024) 45 #define VCE_V1_0_STACK_SIZE (64 * 1024) 46 #define VCE_V1_0_DATA_SIZE (7808 * (AMDGPU_MAX_VCE_HANDLES + 1)) 47 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02 48 49 static void vce_v1_0_set_ring_funcs(struct amdgpu_device *adev); 50 static void vce_v1_0_set_irq_funcs(struct amdgpu_device *adev); 51 52 struct vce_v1_0_fw_signature { 53 int32_t offset; 54 uint32_t length; 55 int32_t number; 56 struct { 57 uint32_t chip_id; 58 uint32_t keyselect; 59 uint32_t nonce[4]; 60 uint32_t sigval[4]; 61 } val[8]; 62 }; 63 64 /** 65 * vce_v1_0_ring_get_rptr - get read pointer 66 * 67 * @ring: amdgpu_ring pointer 68 * 69 * Returns the current hardware read pointer 70 */ 71 static uint64_t vce_v1_0_ring_get_rptr(struct amdgpu_ring *ring) 72 { 73 struct amdgpu_device *adev = ring->adev; 74 75 if (ring->me == 0) 76 return RREG32(mmVCE_RB_RPTR); 77 else 78 return RREG32(mmVCE_RB_RPTR2); 79 } 80 81 /** 82 * vce_v1_0_ring_get_wptr - get write pointer 83 * 84 * @ring: amdgpu_ring pointer 85 * 86 * Returns the current hardware write pointer 87 */ 88 static uint64_t vce_v1_0_ring_get_wptr(struct amdgpu_ring *ring) 89 { 90 struct amdgpu_device *adev = ring->adev; 91 92 if (ring->me == 0) 93 return RREG32(mmVCE_RB_WPTR); 94 else 95 return RREG32(mmVCE_RB_WPTR2); 96 } 97 98 /** 99 * vce_v1_0_ring_set_wptr - set write pointer 100 * 101 * @ring: amdgpu_ring pointer 102 * 103 * Commits the write pointer to the hardware 104 */ 105 static void vce_v1_0_ring_set_wptr(struct amdgpu_ring *ring) 106 { 107 struct amdgpu_device *adev = ring->adev; 108 109 if (ring->me == 0) 110 WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); 111 else 112 WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); 113 } 114 115 static int vce_v1_0_lmi_clean(struct amdgpu_device *adev) 116 { 117 int i, j; 118 119 for (i = 0; i < 10; ++i) { 120 for (j = 0; j < 100; ++j) { 121 if (RREG32(mmVCE_LMI_STATUS) & 0x337f) 122 return 0; 123 124 mdelay(10); 125 } 126 } 127 128 return -ETIMEDOUT; 129 } 130 131 static int vce_v1_0_firmware_loaded(struct amdgpu_device *adev) 132 { 133 int i, j; 134 135 for (i = 0; i < 10; ++i) { 136 for (j = 0; j < 100; ++j) { 137 if (RREG32(mmVCE_STATUS) & VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK) 138 return 0; 139 mdelay(10); 140 } 141 142 dev_err(adev->dev, "VCE not responding, trying to reset the ECPU\n"); 143 144 WREG32_P(mmVCE_SOFT_RESET, 145 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 146 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 147 mdelay(10); 148 WREG32_P(mmVCE_SOFT_RESET, 0, 149 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 150 mdelay(10); 151 } 152 153 return -ETIMEDOUT; 154 } 155 156 static void vce_v1_0_init_cg(struct amdgpu_device *adev) 157 { 158 u32 tmp; 159 160 tmp = RREG32(mmVCE_CLOCK_GATING_A); 161 tmp |= VCE_CLOCK_GATING_A__CGC_DYN_CLOCK_MODE_MASK; 162 WREG32(mmVCE_CLOCK_GATING_A, tmp); 163 164 tmp = RREG32(mmVCE_CLOCK_GATING_B); 165 tmp |= 0x1e; 166 tmp &= ~0xe100e1; 167 WREG32(mmVCE_CLOCK_GATING_B, tmp); 168 169 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 170 tmp &= ~0xff9ff000; 171 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 172 173 tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 174 tmp &= ~0x3ff; 175 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 176 } 177 178 /** 179 * vce_v1_0_load_fw_signature - load firmware signature into VCPU BO 180 * 181 * @adev: amdgpu_device pointer 182 * 183 * The VCE1 firmware validation mechanism needs a firmware signature. 184 * This function finds the signature appropriate for the current 185 * ASIC and writes that into the VCPU BO. 186 */ 187 static int vce_v1_0_load_fw_signature(struct amdgpu_device *adev) 188 { 189 const struct common_firmware_header *hdr; 190 struct vce_v1_0_fw_signature *sign; 191 unsigned int ucode_offset; 192 uint32_t chip_id; 193 u32 *cpu_addr; 194 int i; 195 196 hdr = (const struct common_firmware_header *)adev->vce.fw->data; 197 ucode_offset = le32_to_cpu(hdr->ucode_array_offset_bytes); 198 cpu_addr = adev->vce.cpu_addr; 199 200 sign = (void *)adev->vce.fw->data + ucode_offset; 201 202 switch (adev->asic_type) { 203 case CHIP_TAHITI: 204 chip_id = 0x01000014; 205 break; 206 case CHIP_VERDE: 207 chip_id = 0x01000015; 208 break; 209 case CHIP_PITCAIRN: 210 chip_id = 0x01000016; 211 break; 212 default: 213 dev_err(adev->dev, "asic_type %#010x was not found!", adev->asic_type); 214 return -EINVAL; 215 } 216 217 for (i = 0; i < le32_to_cpu(sign->number); ++i) { 218 if (le32_to_cpu(sign->val[i].chip_id) == chip_id) 219 break; 220 } 221 222 if (i == le32_to_cpu(sign->number)) { 223 dev_err(adev->dev, "chip_id 0x%x for %s was not found in VCE firmware", 224 chip_id, amdgpu_asic_name[adev->asic_type]); 225 return -EINVAL; 226 } 227 228 cpu_addr += (256 - 64) / 4; 229 memcpy_toio(&cpu_addr[0], &sign->val[i].nonce[0], 16); 230 cpu_addr[4] = cpu_to_le32(le32_to_cpu(sign->length) + 64); 231 232 memset_io(&cpu_addr[5], 0, 44); 233 memcpy_toio(&cpu_addr[16], &sign[1], hdr->ucode_size_bytes - sizeof(*sign)); 234 235 cpu_addr += (le32_to_cpu(sign->length) + 64) / 4; 236 memcpy_toio(&cpu_addr[0], &sign->val[i].sigval[0], 16); 237 238 adev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect); 239 240 return 0; 241 } 242 243 static int vce_v1_0_wait_for_fw_validation(struct amdgpu_device *adev) 244 { 245 int i; 246 247 dev_dbg(adev->dev, "VCE keyselect: %d", adev->vce.keyselect); 248 WREG32(mmVCE_LMI_FW_START_KEYSEL, adev->vce.keyselect); 249 250 for (i = 0; i < 10; ++i) { 251 mdelay(10); 252 if (RREG32(mmVCE_FW_REG_STATUS) & VCE_FW_REG_STATUS__DONE_MASK) 253 break; 254 } 255 256 if (!(RREG32(mmVCE_FW_REG_STATUS) & VCE_FW_REG_STATUS__DONE_MASK)) { 257 dev_err(adev->dev, "VCE FW validation timeout\n"); 258 return -ETIMEDOUT; 259 } 260 261 if (!(RREG32(mmVCE_FW_REG_STATUS) & VCE_FW_REG_STATUS__PASS_MASK)) { 262 dev_err(adev->dev, "VCE FW validation failed\n"); 263 return -EINVAL; 264 } 265 266 for (i = 0; i < 10; ++i) { 267 mdelay(10); 268 if (!(RREG32(mmVCE_FW_REG_STATUS) & VCE_FW_REG_STATUS__BUSY_MASK)) 269 break; 270 } 271 272 if (RREG32(mmVCE_FW_REG_STATUS) & VCE_FW_REG_STATUS__BUSY_MASK) { 273 dev_err(adev->dev, "VCE FW busy timeout\n"); 274 return -ETIMEDOUT; 275 } 276 277 return 0; 278 } 279 280 static int vce_v1_0_mc_resume(struct amdgpu_device *adev) 281 { 282 uint32_t offset; 283 uint32_t size; 284 285 /* 286 * When the keyselect is already set, don't perturb VCE FW. 287 * Validation seems to always fail the second time. 288 */ 289 if (RREG32(mmVCE_LMI_FW_START_KEYSEL)) { 290 dev_dbg(adev->dev, "keyselect already set: 0x%x (on CPU: 0x%x)\n", 291 RREG32(mmVCE_LMI_FW_START_KEYSEL), adev->vce.keyselect); 292 293 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 294 return 0; 295 } 296 297 WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16)); 298 WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 299 WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 300 WREG32(mmVCE_CLOCK_GATING_B, 0); 301 302 WREG32_P(mmVCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4); 303 304 WREG32(mmVCE_LMI_CTRL, 0x00398000); 305 306 WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1); 307 WREG32(mmVCE_LMI_SWAP_CNTL, 0); 308 WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 309 WREG32(mmVCE_LMI_VM_CTRL, 0); 310 311 WREG32(mmVCE_VCPU_SCRATCH7, AMDGPU_MAX_VCE_HANDLES); 312 313 offset = adev->vce.gpu_addr + AMDGPU_VCE_FIRMWARE_OFFSET; 314 size = VCE_V1_0_FW_SIZE; 315 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 316 WREG32(mmVCE_VCPU_CACHE_SIZE0, size); 317 318 offset += size; 319 size = VCE_V1_0_STACK_SIZE; 320 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff); 321 WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 322 323 offset += size; 324 size = VCE_V1_0_DATA_SIZE; 325 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff); 326 WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 327 328 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 329 330 return vce_v1_0_wait_for_fw_validation(adev); 331 } 332 333 /** 334 * vce_v1_0_is_idle() - Check idle status of VCE1 IP block 335 * 336 * @ip_block: amdgpu_ip_block pointer 337 * 338 * Check whether VCE is busy according to VCE_STATUS. 339 * Also check whether the SRBM thinks VCE is busy, although 340 * SRBM_STATUS.VCE_BUSY seems to be bogus because it 341 * appears to mirror the VCE_STATUS.VCPU_REPORT_FW_LOADED bit. 342 */ 343 static bool vce_v1_0_is_idle(struct amdgpu_ip_block *ip_block) 344 { 345 struct amdgpu_device *adev = ip_block->adev; 346 bool busy = 347 (RREG32(mmVCE_STATUS) & (VCE_STATUS__JOB_BUSY_MASK | VCE_STATUS__UENC_BUSY_MASK)) || 348 (RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK); 349 350 return !busy; 351 } 352 353 static int vce_v1_0_wait_for_idle(struct amdgpu_ip_block *ip_block) 354 { 355 struct amdgpu_device *adev = ip_block->adev; 356 unsigned int i; 357 358 for (i = 0; i < adev->usec_timeout; i++) { 359 udelay(1); 360 if (vce_v1_0_is_idle(ip_block)) 361 return 0; 362 } 363 return -ETIMEDOUT; 364 } 365 366 /** 367 * vce_v1_0_start - start VCE block 368 * 369 * @adev: amdgpu_device pointer 370 * 371 * Setup and start the VCE block 372 */ 373 static int vce_v1_0_start(struct amdgpu_device *adev) 374 { 375 struct amdgpu_ring *ring; 376 int r; 377 378 WREG32_P(mmVCE_STATUS, 1, ~1); 379 380 r = vce_v1_0_mc_resume(adev); 381 if (r) 382 return r; 383 384 ring = &adev->vce.ring[0]; 385 WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); 386 WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); 387 WREG32(mmVCE_RB_BASE_LO, lower_32_bits(ring->gpu_addr)); 388 WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 389 WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); 390 391 ring = &adev->vce.ring[1]; 392 WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); 393 WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); 394 WREG32(mmVCE_RB_BASE_LO2, lower_32_bits(ring->gpu_addr)); 395 WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 396 WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); 397 398 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, 399 ~VCE_VCPU_CNTL__CLK_EN_MASK); 400 401 WREG32_P(mmVCE_SOFT_RESET, 402 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK | 403 VCE_SOFT_RESET__FME_SOFT_RESET_MASK, 404 ~(VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK | 405 VCE_SOFT_RESET__FME_SOFT_RESET_MASK)); 406 407 mdelay(100); 408 409 WREG32_P(mmVCE_SOFT_RESET, 0, 410 ~(VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK | 411 VCE_SOFT_RESET__FME_SOFT_RESET_MASK)); 412 413 r = vce_v1_0_firmware_loaded(adev); 414 415 /* Clear VCE_STATUS, otherwise SRBM thinks VCE1 is busy. */ 416 WREG32(mmVCE_STATUS, 0); 417 418 if (r) { 419 dev_err(adev->dev, "VCE not responding, giving up\n"); 420 return r; 421 } 422 423 return 0; 424 } 425 426 static int vce_v1_0_stop(struct amdgpu_device *adev) 427 { 428 struct amdgpu_ip_block *ip_block; 429 int status; 430 int i; 431 432 ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE); 433 if (!ip_block) 434 return -EINVAL; 435 436 if (vce_v1_0_lmi_clean(adev)) 437 dev_warn(adev->dev, "VCE not idle\n"); 438 439 if (vce_v1_0_wait_for_idle(ip_block)) 440 dev_warn(adev->dev, "VCE busy: VCE_STATUS=0x%x, SRBM_STATUS2=0x%x\n", 441 RREG32(mmVCE_STATUS), RREG32(mmSRBM_STATUS2)); 442 443 /* Stall UMC and register bus before resetting VCPU */ 444 WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8)); 445 446 for (i = 0; i < 100; ++i) { 447 status = RREG32(mmVCE_LMI_STATUS); 448 if (status & 0x240) 449 break; 450 mdelay(1); 451 } 452 453 WREG32_P(mmVCE_VCPU_CNTL, 0, ~VCE_VCPU_CNTL__CLK_EN_MASK); 454 455 WREG32_P(mmVCE_SOFT_RESET, 456 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK | 457 VCE_SOFT_RESET__FME_SOFT_RESET_MASK, 458 ~(VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK | 459 VCE_SOFT_RESET__FME_SOFT_RESET_MASK)); 460 461 WREG32(mmVCE_STATUS, 0); 462 463 return 0; 464 } 465 466 static void vce_v1_0_enable_mgcg(struct amdgpu_device *adev, bool enable) 467 { 468 u32 tmp; 469 470 if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) { 471 tmp = RREG32(mmVCE_CLOCK_GATING_A); 472 tmp |= VCE_CLOCK_GATING_A__CGC_DYN_CLOCK_MODE_MASK; 473 WREG32(mmVCE_CLOCK_GATING_A, tmp); 474 475 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 476 tmp &= ~0x1ff000; 477 tmp |= 0xff800000; 478 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 479 480 tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 481 tmp &= ~0x3ff; 482 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 483 } else { 484 tmp = RREG32(mmVCE_CLOCK_GATING_A); 485 tmp &= ~VCE_CLOCK_GATING_A__CGC_DYN_CLOCK_MODE_MASK; 486 WREG32(mmVCE_CLOCK_GATING_A, tmp); 487 488 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 489 tmp |= 0x1ff000; 490 tmp &= ~0xff800000; 491 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 492 493 tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 494 tmp |= 0x3ff; 495 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 496 } 497 } 498 499 static int vce_v1_0_early_init(struct amdgpu_ip_block *ip_block) 500 { 501 struct amdgpu_device *adev = ip_block->adev; 502 int r; 503 504 r = amdgpu_vce_early_init(adev); 505 if (r) 506 return r; 507 508 adev->vce.num_rings = 2; 509 510 vce_v1_0_set_ring_funcs(adev); 511 vce_v1_0_set_irq_funcs(adev); 512 513 return 0; 514 } 515 516 static int vce_v1_0_sw_init(struct amdgpu_ip_block *ip_block) 517 { 518 struct amdgpu_device *adev = ip_block->adev; 519 struct amdgpu_ring *ring; 520 int r, i; 521 522 r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 167, &adev->vce.irq); 523 if (r) 524 return r; 525 526 r = amdgpu_vce_sw_init(adev, VCE_V1_0_FW_SIZE + 527 VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE); 528 if (r) 529 return r; 530 531 r = amdgpu_vce_resume(adev); 532 if (r) 533 return r; 534 r = vce_v1_0_load_fw_signature(adev); 535 if (r) 536 return r; 537 538 for (i = 0; i < adev->vce.num_rings; i++) { 539 enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i); 540 541 ring = &adev->vce.ring[i]; 542 sprintf(ring->name, "vce%d", i); 543 r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0, 544 hw_prio, NULL); 545 if (r) 546 return r; 547 } 548 549 return r; 550 } 551 552 static int vce_v1_0_sw_fini(struct amdgpu_ip_block *ip_block) 553 { 554 struct amdgpu_device *adev = ip_block->adev; 555 int r; 556 557 r = amdgpu_vce_suspend(adev); 558 if (r) 559 return r; 560 561 return amdgpu_vce_sw_fini(adev); 562 } 563 564 /** 565 * vce_v1_0_hw_init - start and test VCE block 566 * 567 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. 568 * 569 * Initialize the hardware, boot up the VCPU and do some testing 570 */ 571 static int vce_v1_0_hw_init(struct amdgpu_ip_block *ip_block) 572 { 573 struct amdgpu_device *adev = ip_block->adev; 574 int i, r; 575 576 if (adev->pm.dpm_enabled) 577 amdgpu_dpm_enable_vce(adev, true); 578 else 579 amdgpu_asic_set_vce_clocks(adev, 10000, 10000); 580 581 for (i = 0; i < adev->vce.num_rings; i++) { 582 r = amdgpu_ring_test_helper(&adev->vce.ring[i]); 583 if (r) 584 return r; 585 } 586 587 dev_info(adev->dev, "VCE initialized successfully.\n"); 588 589 return 0; 590 } 591 592 static int vce_v1_0_hw_fini(struct amdgpu_ip_block *ip_block) 593 { 594 int r; 595 596 r = vce_v1_0_stop(ip_block->adev); 597 if (r) 598 return r; 599 600 cancel_delayed_work_sync(&ip_block->adev->vce.idle_work); 601 return 0; 602 } 603 604 static int vce_v1_0_suspend(struct amdgpu_ip_block *ip_block) 605 { 606 struct amdgpu_device *adev = ip_block->adev; 607 int r; 608 609 /* 610 * Proper cleanups before halting the HW engine: 611 * - cancel the delayed idle work 612 * - enable powergating 613 * - enable clockgating 614 * - disable dpm 615 * 616 * TODO: to align with the VCN implementation, move the 617 * jobs for clockgating/powergating/dpm setting to 618 * ->set_powergating_state(). 619 */ 620 cancel_delayed_work_sync(&adev->vce.idle_work); 621 622 if (adev->pm.dpm_enabled) { 623 amdgpu_dpm_enable_vce(adev, false); 624 } else { 625 amdgpu_asic_set_vce_clocks(adev, 0, 0); 626 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 627 AMD_PG_STATE_GATE); 628 amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 629 AMD_CG_STATE_GATE); 630 } 631 632 r = vce_v1_0_hw_fini(ip_block); 633 if (r) { 634 dev_err(adev->dev, "vce_v1_0_hw_fini() failed with error %i", r); 635 return r; 636 } 637 638 return amdgpu_vce_suspend(adev); 639 } 640 641 static int vce_v1_0_resume(struct amdgpu_ip_block *ip_block) 642 { 643 struct amdgpu_device *adev = ip_block->adev; 644 int r; 645 646 r = amdgpu_vce_resume(adev); 647 if (r) 648 return r; 649 r = vce_v1_0_load_fw_signature(adev); 650 if (r) 651 return r; 652 653 return vce_v1_0_hw_init(ip_block); 654 } 655 656 static int vce_v1_0_set_interrupt_state(struct amdgpu_device *adev, 657 struct amdgpu_irq_src *source, 658 unsigned int type, 659 enum amdgpu_interrupt_state state) 660 { 661 uint32_t val = 0; 662 663 if (state == AMDGPU_IRQ_STATE_ENABLE) 664 val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK; 665 666 WREG32_P(mmVCE_SYS_INT_EN, val, 667 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 668 return 0; 669 } 670 671 static int vce_v1_0_process_interrupt(struct amdgpu_device *adev, 672 struct amdgpu_irq_src *source, 673 struct amdgpu_iv_entry *entry) 674 { 675 dev_dbg(adev->dev, "IH: VCE\n"); 676 switch (entry->src_data[0]) { 677 case 0: 678 case 1: 679 amdgpu_fence_process(&adev->vce.ring[entry->src_data[0]]); 680 break; 681 default: 682 dev_err(adev->dev, "Unhandled interrupt: %d %d\n", 683 entry->src_id, entry->src_data[0]); 684 break; 685 } 686 687 return 0; 688 } 689 690 static int vce_v1_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, 691 enum amd_clockgating_state state) 692 { 693 struct amdgpu_device *adev = ip_block->adev; 694 695 vce_v1_0_init_cg(adev); 696 vce_v1_0_enable_mgcg(adev, state == AMD_CG_STATE_GATE); 697 698 return 0; 699 } 700 701 static int vce_v1_0_set_powergating_state(struct amdgpu_ip_block *ip_block, 702 enum amd_powergating_state state) 703 { 704 struct amdgpu_device *adev = ip_block->adev; 705 706 /* 707 * This doesn't actually powergate the VCE block. 708 * That's done in the dpm code via the SMC. This 709 * just re-inits the block as necessary. The actual 710 * gating still happens in the dpm code. We should 711 * revisit this when there is a cleaner line between 712 * the smc and the hw blocks 713 */ 714 if (state == AMD_PG_STATE_GATE) 715 return vce_v1_0_stop(adev); 716 else 717 return vce_v1_0_start(adev); 718 } 719 720 static const struct amd_ip_funcs vce_v1_0_ip_funcs = { 721 .name = "vce_v1_0", 722 .early_init = vce_v1_0_early_init, 723 .sw_init = vce_v1_0_sw_init, 724 .sw_fini = vce_v1_0_sw_fini, 725 .hw_init = vce_v1_0_hw_init, 726 .hw_fini = vce_v1_0_hw_fini, 727 .suspend = vce_v1_0_suspend, 728 .resume = vce_v1_0_resume, 729 .is_idle = vce_v1_0_is_idle, 730 .wait_for_idle = vce_v1_0_wait_for_idle, 731 .set_clockgating_state = vce_v1_0_set_clockgating_state, 732 .set_powergating_state = vce_v1_0_set_powergating_state, 733 }; 734 735 static const struct amdgpu_ring_funcs vce_v1_0_ring_funcs = { 736 .type = AMDGPU_RING_TYPE_VCE, 737 .align_mask = 0xf, 738 .nop = VCE_CMD_NO_OP, 739 .support_64bit_ptrs = false, 740 .no_user_fence = true, 741 .get_rptr = vce_v1_0_ring_get_rptr, 742 .get_wptr = vce_v1_0_ring_get_wptr, 743 .set_wptr = vce_v1_0_ring_set_wptr, 744 .parse_cs = amdgpu_vce_ring_parse_cs, 745 .emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */ 746 .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ 747 .emit_ib = amdgpu_vce_ring_emit_ib, 748 .emit_fence = amdgpu_vce_ring_emit_fence, 749 .test_ring = amdgpu_vce_ring_test_ring, 750 .test_ib = amdgpu_vce_ring_test_ib, 751 .insert_nop = amdgpu_ring_insert_nop, 752 .pad_ib = amdgpu_ring_generic_pad_ib, 753 .begin_use = amdgpu_vce_ring_begin_use, 754 .end_use = amdgpu_vce_ring_end_use, 755 }; 756 757 static void vce_v1_0_set_ring_funcs(struct amdgpu_device *adev) 758 { 759 int i; 760 761 for (i = 0; i < adev->vce.num_rings; i++) { 762 adev->vce.ring[i].funcs = &vce_v1_0_ring_funcs; 763 adev->vce.ring[i].me = i; 764 } 765 }; 766 767 static const struct amdgpu_irq_src_funcs vce_v1_0_irq_funcs = { 768 .set = vce_v1_0_set_interrupt_state, 769 .process = vce_v1_0_process_interrupt, 770 }; 771 772 static void vce_v1_0_set_irq_funcs(struct amdgpu_device *adev) 773 { 774 adev->vce.irq.num_types = 1; 775 adev->vce.irq.funcs = &vce_v1_0_irq_funcs; 776 }; 777 778 const struct amdgpu_ip_block_version vce_v1_0_ip_block = { 779 .type = AMD_IP_BLOCK_TYPE_VCE, 780 .major = 1, 781 .minor = 0, 782 .rev = 0, 783 .funcs = &vce_v1_0_ip_funcs, 784 }; 785