1 /* 2 * Copyright 2013 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19 * USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * The above copyright notice and this permission notice (including the 22 * next paragraph) shall be included in all copies or substantial portions 23 * of the Software. 24 * 25 * Authors: Christian König <christian.koenig@amd.com> 26 */ 27 28 #include <linux/firmware.h> 29 30 #include "amdgpu.h" 31 #include "amdgpu_vce.h" 32 #include "cikd.h" 33 #include "vce/vce_2_0_d.h" 34 #include "vce/vce_2_0_sh_mask.h" 35 #include "smu/smu_7_0_1_d.h" 36 #include "smu/smu_7_0_1_sh_mask.h" 37 #include "oss/oss_2_0_d.h" 38 #include "oss/oss_2_0_sh_mask.h" 39 40 41 /* Use 24K to be safe. The FW supposedly only requires 23744 bytes. */ 42 #define VCE_V2_0_DATA_ENTRY_SIZE (24 * 1024) 43 44 #define VCE_V2_0_FW_SIZE (256 * 1024) 45 #define VCE_V2_0_STACK_SIZE (64 * 1024) 46 #define VCE_V2_0_DATA_SIZE (VCE_V2_0_DATA_ENTRY_SIZE * (AMDGPU_MAX_VCE_HANDLES + 1)) 47 48 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02 49 50 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev); 51 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev); 52 53 /** 54 * vce_v2_0_ring_get_rptr - get read pointer 55 * 56 * @ring: amdgpu_ring pointer 57 * 58 * Returns the current hardware read pointer 59 */ 60 static uint64_t vce_v2_0_ring_get_rptr(struct amdgpu_ring *ring) 61 { 62 struct amdgpu_device *adev = ring->adev; 63 64 if (ring->me == 0) 65 return RREG32(mmVCE_RB_RPTR); 66 else 67 return RREG32(mmVCE_RB_RPTR2); 68 } 69 70 /** 71 * vce_v2_0_ring_get_wptr - get write pointer 72 * 73 * @ring: amdgpu_ring pointer 74 * 75 * Returns the current hardware write pointer 76 */ 77 static uint64_t vce_v2_0_ring_get_wptr(struct amdgpu_ring *ring) 78 { 79 struct amdgpu_device *adev = ring->adev; 80 81 if (ring->me == 0) 82 return RREG32(mmVCE_RB_WPTR); 83 else 84 return RREG32(mmVCE_RB_WPTR2); 85 } 86 87 /** 88 * vce_v2_0_ring_set_wptr - set write pointer 89 * 90 * @ring: amdgpu_ring pointer 91 * 92 * Commits the write pointer to the hardware 93 */ 94 static void vce_v2_0_ring_set_wptr(struct amdgpu_ring *ring) 95 { 96 struct amdgpu_device *adev = ring->adev; 97 98 if (ring->me == 0) 99 WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); 100 else 101 WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); 102 } 103 104 static int vce_v2_0_lmi_clean(struct amdgpu_device *adev) 105 { 106 int i, j; 107 108 for (i = 0; i < 10; ++i) { 109 for (j = 0; j < 100; ++j) { 110 uint32_t status = RREG32(mmVCE_LMI_STATUS); 111 112 if (status & 0x337f) 113 return 0; 114 mdelay(10); 115 } 116 } 117 118 return -ETIMEDOUT; 119 } 120 121 static int vce_v2_0_firmware_loaded(struct amdgpu_device *adev) 122 { 123 int i, j; 124 125 for (i = 0; i < 10; ++i) { 126 for (j = 0; j < 100; ++j) { 127 uint32_t status = RREG32(mmVCE_STATUS); 128 129 if (status & VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK) 130 return 0; 131 mdelay(10); 132 } 133 134 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); 135 WREG32_P(mmVCE_SOFT_RESET, 136 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 137 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 138 mdelay(10); 139 WREG32_P(mmVCE_SOFT_RESET, 0, 140 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 141 mdelay(10); 142 } 143 144 return -ETIMEDOUT; 145 } 146 147 static void vce_v2_0_disable_cg(struct amdgpu_device *adev) 148 { 149 WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7); 150 } 151 152 static void vce_v2_0_init_cg(struct amdgpu_device *adev) 153 { 154 u32 tmp; 155 156 tmp = RREG32(mmVCE_CLOCK_GATING_A); 157 tmp &= ~0xfff; 158 tmp |= ((0 << 0) | (4 << 4)); 159 tmp |= 0x40000; 160 WREG32(mmVCE_CLOCK_GATING_A, tmp); 161 162 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 163 tmp &= ~0xfff; 164 tmp |= ((0 << 0) | (4 << 4)); 165 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 166 167 tmp = RREG32(mmVCE_CLOCK_GATING_B); 168 tmp |= 0x10; 169 tmp &= ~0x100000; 170 WREG32(mmVCE_CLOCK_GATING_B, tmp); 171 } 172 173 static void vce_v2_0_mc_resume(struct amdgpu_device *adev) 174 { 175 uint32_t size, offset; 176 177 WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16)); 178 WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 179 WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 180 WREG32(mmVCE_CLOCK_GATING_B, 0xf7); 181 182 WREG32(mmVCE_LMI_CTRL, 0x00398000); 183 WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1); 184 WREG32(mmVCE_LMI_SWAP_CNTL, 0); 185 WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 186 WREG32(mmVCE_LMI_VM_CTRL, 0); 187 188 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8)); 189 190 offset = AMDGPU_VCE_FIRMWARE_OFFSET; 191 size = VCE_V2_0_FW_SIZE - AMDGPU_VCE_FIRMWARE_OFFSET; 192 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 193 WREG32(mmVCE_VCPU_CACHE_SIZE0, size); 194 195 offset += size; 196 size = VCE_V2_0_STACK_SIZE; 197 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff); 198 WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 199 200 offset += size; 201 size = VCE_V2_0_DATA_SIZE; 202 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff); 203 WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 204 205 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 206 WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1); 207 } 208 209 static bool vce_v2_0_is_idle(struct amdgpu_ip_block *ip_block) 210 { 211 struct amdgpu_device *adev = ip_block->adev; 212 213 return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK); 214 } 215 216 static int vce_v2_0_wait_for_idle(struct amdgpu_ip_block *ip_block) 217 { 218 struct amdgpu_device *adev = ip_block->adev; 219 unsigned i; 220 221 for (i = 0; i < adev->usec_timeout; i++) { 222 if (vce_v2_0_is_idle(ip_block)) 223 return 0; 224 } 225 return -ETIMEDOUT; 226 } 227 228 /** 229 * vce_v2_0_start - start VCE block 230 * 231 * @adev: amdgpu_device pointer 232 * 233 * Setup and start the VCE block 234 */ 235 static int vce_v2_0_start(struct amdgpu_device *adev) 236 { 237 struct amdgpu_ring *ring; 238 int r; 239 240 /* set BUSY flag */ 241 WREG32_P(mmVCE_STATUS, 1, ~1); 242 243 vce_v2_0_init_cg(adev); 244 vce_v2_0_disable_cg(adev); 245 246 vce_v2_0_mc_resume(adev); 247 248 ring = &adev->vce.ring[0]; 249 WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); 250 WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); 251 WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); 252 WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 253 WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); 254 255 ring = &adev->vce.ring[1]; 256 WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); 257 WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); 258 WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); 259 WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 260 WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); 261 262 WREG32_FIELD(VCE_VCPU_CNTL, CLK_EN, 1); 263 WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 1); 264 mdelay(100); 265 WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 0); 266 267 r = vce_v2_0_firmware_loaded(adev); 268 269 /* clear BUSY flag */ 270 WREG32_P(mmVCE_STATUS, 0, ~1); 271 272 if (r) { 273 DRM_ERROR("VCE not responding, giving up!!!\n"); 274 return r; 275 } 276 277 return 0; 278 } 279 280 static int vce_v2_0_stop(struct amdgpu_device *adev) 281 { 282 struct amdgpu_ip_block *ip_block; 283 int i; 284 int status; 285 286 287 if (vce_v2_0_lmi_clean(adev)) { 288 drm_info(adev_to_drm(adev), "VCE is not idle\n"); 289 return 0; 290 } 291 292 ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE); 293 if (!ip_block) 294 return -EINVAL; 295 296 if (vce_v2_0_wait_for_idle(ip_block)) { 297 drm_info(adev_to_drm(adev), "VCE is busy, Can't set clock gating"); 298 return 0; 299 } 300 301 /* Stall UMC and register bus before resetting VCPU */ 302 WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8)); 303 304 for (i = 0; i < 100; ++i) { 305 status = RREG32(mmVCE_LMI_STATUS); 306 if (status & 0x240) 307 break; 308 mdelay(1); 309 } 310 311 WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x80001); 312 313 /* put LMI, VCPU, RBC etc... into reset */ 314 WREG32_P(mmVCE_SOFT_RESET, 1, ~0x1); 315 316 WREG32(mmVCE_STATUS, 0); 317 318 return 0; 319 } 320 321 static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated) 322 { 323 u32 tmp; 324 325 if (gated) { 326 tmp = RREG32(mmVCE_CLOCK_GATING_B); 327 tmp |= 0xe70000; 328 WREG32(mmVCE_CLOCK_GATING_B, tmp); 329 330 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 331 tmp |= 0xff000000; 332 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 333 334 tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 335 tmp &= ~0x3fc; 336 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 337 338 WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0); 339 } else { 340 tmp = RREG32(mmVCE_CLOCK_GATING_B); 341 tmp |= 0xe7; 342 tmp &= ~0xe70000; 343 WREG32(mmVCE_CLOCK_GATING_B, tmp); 344 345 tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 346 tmp |= 0x1fe000; 347 tmp &= ~0xff000000; 348 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 349 350 tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 351 tmp |= 0x3fc; 352 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 353 } 354 } 355 356 static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated) 357 { 358 u32 orig, tmp; 359 360 /* LMI_MC/LMI_UMC always set in dynamic, 361 * set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0} 362 */ 363 tmp = RREG32(mmVCE_CLOCK_GATING_B); 364 tmp &= ~0x00060006; 365 366 /* Exception for ECPU, IH, SEM, SYS blocks needs to be turned on/off by SW */ 367 if (gated) { 368 tmp |= 0xe10000; 369 WREG32(mmVCE_CLOCK_GATING_B, tmp); 370 } else { 371 tmp |= 0xe1; 372 tmp &= ~0xe10000; 373 WREG32(mmVCE_CLOCK_GATING_B, tmp); 374 } 375 376 orig = tmp = RREG32(mmVCE_UENC_CLOCK_GATING); 377 tmp &= ~0x1fe000; 378 tmp &= ~0xff000000; 379 if (tmp != orig) 380 WREG32(mmVCE_UENC_CLOCK_GATING, tmp); 381 382 orig = tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 383 tmp &= ~0x3fc; 384 if (tmp != orig) 385 WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); 386 387 /* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */ 388 WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00); 389 390 if(gated) 391 WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0); 392 } 393 394 static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable, 395 bool sw_cg) 396 { 397 if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) { 398 if (sw_cg) 399 vce_v2_0_set_sw_cg(adev, true); 400 else 401 vce_v2_0_set_dyn_cg(adev, true); 402 } else { 403 vce_v2_0_disable_cg(adev); 404 405 if (sw_cg) 406 vce_v2_0_set_sw_cg(adev, false); 407 else 408 vce_v2_0_set_dyn_cg(adev, false); 409 } 410 } 411 412 static int vce_v2_0_early_init(struct amdgpu_ip_block *ip_block) 413 { 414 struct amdgpu_device *adev = ip_block->adev; 415 int r; 416 417 r = amdgpu_vce_early_init(adev); 418 if (r) 419 return r; 420 421 adev->vce.num_rings = 2; 422 423 vce_v2_0_set_ring_funcs(adev); 424 vce_v2_0_set_irq_funcs(adev); 425 426 return 0; 427 } 428 429 static int vce_v2_0_sw_init(struct amdgpu_ip_block *ip_block) 430 { 431 struct amdgpu_ring *ring; 432 int r, i; 433 struct amdgpu_device *adev = ip_block->adev; 434 435 /* VCE */ 436 r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 167, &adev->vce.irq); 437 if (r) 438 return r; 439 440 r = amdgpu_vce_sw_init(adev, VCE_V2_0_FW_SIZE + 441 VCE_V2_0_STACK_SIZE + VCE_V2_0_DATA_SIZE); 442 if (r) 443 return r; 444 445 r = amdgpu_vce_resume(adev); 446 if (r) 447 return r; 448 449 for (i = 0; i < adev->vce.num_rings; i++) { 450 enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i); 451 452 ring = &adev->vce.ring[i]; 453 sprintf(ring->name, "vce%d", i); 454 r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0, 455 hw_prio, NULL); 456 if (r) 457 return r; 458 } 459 460 return r; 461 } 462 463 static int vce_v2_0_sw_fini(struct amdgpu_ip_block *ip_block) 464 { 465 int r; 466 struct amdgpu_device *adev = ip_block->adev; 467 468 r = amdgpu_vce_suspend(adev); 469 if (r) 470 return r; 471 472 return amdgpu_vce_sw_fini(adev); 473 } 474 475 static int vce_v2_0_hw_init(struct amdgpu_ip_block *ip_block) 476 { 477 int r, i; 478 struct amdgpu_device *adev = ip_block->adev; 479 480 amdgpu_asic_set_vce_clocks(adev, 10000, 10000); 481 vce_v2_0_enable_mgcg(adev, true, false); 482 483 for (i = 0; i < adev->vce.num_rings; i++) { 484 r = amdgpu_ring_test_helper(&adev->vce.ring[i]); 485 if (r) 486 return r; 487 } 488 489 drm_info(adev_to_drm(adev), "VCE initialized successfully.\n"); 490 491 return 0; 492 } 493 494 static int vce_v2_0_hw_fini(struct amdgpu_ip_block *ip_block) 495 { 496 cancel_delayed_work_sync(&ip_block->adev->vce.idle_work); 497 498 return 0; 499 } 500 501 static int vce_v2_0_suspend(struct amdgpu_ip_block *ip_block) 502 { 503 int r; 504 struct amdgpu_device *adev = ip_block->adev; 505 506 507 /* 508 * Proper cleanups before halting the HW engine: 509 * - cancel the delayed idle work 510 * - enable powergating 511 * - enable clockgating 512 * - disable dpm 513 * 514 * TODO: to align with the VCN implementation, move the 515 * jobs for clockgating/powergating/dpm setting to 516 * ->set_powergating_state(). 517 */ 518 cancel_delayed_work_sync(&adev->vce.idle_work); 519 520 if (adev->pm.dpm_enabled) { 521 amdgpu_dpm_enable_vce(adev, false); 522 } else { 523 amdgpu_asic_set_vce_clocks(adev, 0, 0); 524 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 525 AMD_PG_STATE_GATE); 526 amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 527 AMD_CG_STATE_GATE); 528 } 529 530 r = vce_v2_0_hw_fini(ip_block); 531 if (r) 532 return r; 533 534 return amdgpu_vce_suspend(adev); 535 } 536 537 static int vce_v2_0_resume(struct amdgpu_ip_block *ip_block) 538 { 539 int r; 540 541 r = amdgpu_vce_resume(ip_block->adev); 542 if (r) 543 return r; 544 545 return vce_v2_0_hw_init(ip_block); 546 } 547 548 static int vce_v2_0_soft_reset(struct amdgpu_ip_block *ip_block) 549 { 550 struct amdgpu_device *adev = ip_block->adev; 551 552 WREG32_FIELD(SRBM_SOFT_RESET, SOFT_RESET_VCE, 1); 553 mdelay(5); 554 555 return vce_v2_0_start(adev); 556 } 557 558 static int vce_v2_0_set_interrupt_state(struct amdgpu_device *adev, 559 struct amdgpu_irq_src *source, 560 unsigned type, 561 enum amdgpu_interrupt_state state) 562 { 563 uint32_t val = 0; 564 565 if (state == AMDGPU_IRQ_STATE_ENABLE) 566 val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK; 567 568 WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 569 return 0; 570 } 571 572 static int vce_v2_0_process_interrupt(struct amdgpu_device *adev, 573 struct amdgpu_irq_src *source, 574 struct amdgpu_iv_entry *entry) 575 { 576 DRM_DEBUG("IH: VCE\n"); 577 switch (entry->src_data[0]) { 578 case 0: 579 case 1: 580 amdgpu_fence_process(&adev->vce.ring[entry->src_data[0]]); 581 break; 582 default: 583 DRM_ERROR("Unhandled interrupt: %d %d\n", 584 entry->src_id, entry->src_data[0]); 585 break; 586 } 587 588 return 0; 589 } 590 591 static int vce_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block, 592 enum amd_clockgating_state state) 593 { 594 bool gate = false; 595 bool sw_cg = false; 596 597 struct amdgpu_device *adev = ip_block->adev; 598 599 if (state == AMD_CG_STATE_GATE) { 600 gate = true; 601 sw_cg = true; 602 } 603 604 vce_v2_0_enable_mgcg(adev, gate, sw_cg); 605 606 return 0; 607 } 608 609 static int vce_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block, 610 enum amd_powergating_state state) 611 { 612 /* This doesn't actually powergate the VCE block. 613 * That's done in the dpm code via the SMC. This 614 * just re-inits the block as necessary. The actual 615 * gating still happens in the dpm code. We should 616 * revisit this when there is a cleaner line between 617 * the smc and the hw blocks 618 */ 619 struct amdgpu_device *adev = ip_block->adev; 620 621 if (state == AMD_PG_STATE_GATE) 622 return vce_v2_0_stop(adev); 623 else 624 return vce_v2_0_start(adev); 625 } 626 627 static const struct amd_ip_funcs vce_v2_0_ip_funcs = { 628 .name = "vce_v2_0", 629 .early_init = vce_v2_0_early_init, 630 .sw_init = vce_v2_0_sw_init, 631 .sw_fini = vce_v2_0_sw_fini, 632 .hw_init = vce_v2_0_hw_init, 633 .hw_fini = vce_v2_0_hw_fini, 634 .suspend = vce_v2_0_suspend, 635 .resume = vce_v2_0_resume, 636 .is_idle = vce_v2_0_is_idle, 637 .wait_for_idle = vce_v2_0_wait_for_idle, 638 .soft_reset = vce_v2_0_soft_reset, 639 .set_clockgating_state = vce_v2_0_set_clockgating_state, 640 .set_powergating_state = vce_v2_0_set_powergating_state, 641 }; 642 643 static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { 644 .type = AMDGPU_RING_TYPE_VCE, 645 .align_mask = 0xf, 646 .nop = VCE_CMD_NO_OP, 647 .support_64bit_ptrs = false, 648 .no_user_fence = true, 649 .get_rptr = vce_v2_0_ring_get_rptr, 650 .get_wptr = vce_v2_0_ring_get_wptr, 651 .set_wptr = vce_v2_0_ring_set_wptr, 652 .parse_cs = amdgpu_vce_ring_parse_cs, 653 .emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence x1 no user fence */ 654 .emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */ 655 .emit_ib = amdgpu_vce_ring_emit_ib, 656 .emit_fence = amdgpu_vce_ring_emit_fence, 657 .test_ring = amdgpu_vce_ring_test_ring, 658 .test_ib = amdgpu_vce_ring_test_ib, 659 .insert_nop = amdgpu_ring_insert_nop, 660 .pad_ib = amdgpu_ring_generic_pad_ib, 661 .begin_use = amdgpu_vce_ring_begin_use, 662 .end_use = amdgpu_vce_ring_end_use, 663 }; 664 665 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev) 666 { 667 int i; 668 669 for (i = 0; i < adev->vce.num_rings; i++) { 670 adev->vce.ring[i].funcs = &vce_v2_0_ring_funcs; 671 adev->vce.ring[i].me = i; 672 } 673 } 674 675 static const struct amdgpu_irq_src_funcs vce_v2_0_irq_funcs = { 676 .set = vce_v2_0_set_interrupt_state, 677 .process = vce_v2_0_process_interrupt, 678 }; 679 680 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev) 681 { 682 adev->vce.irq.num_types = 1; 683 adev->vce.irq.funcs = &vce_v2_0_irq_funcs; 684 }; 685 686 const struct amdgpu_ip_block_version vce_v2_0_ip_block = 687 { 688 .type = AMD_IP_BLOCK_TYPE_VCE, 689 .major = 2, 690 .minor = 0, 691 .rev = 0, 692 .funcs = &vce_v2_0_ip_funcs, 693 }; 694