1 /* 2 * Copyright 2014 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 #include <drm/drmP.h> 30 #include "amdgpu.h" 31 #include "amdgpu_vce.h" 32 #include "vid.h" 33 #include "vce/vce_3_0_d.h" 34 #include "vce/vce_3_0_sh_mask.h" 35 #include "oss/oss_3_0_d.h" 36 #include "oss/oss_3_0_sh_mask.h" 37 #include "gca/gfx_8_0_d.h" 38 #include "smu/smu_7_1_2_d.h" 39 #include "smu/smu_7_1_2_sh_mask.h" 40 41 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 42 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 43 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 0x8616 44 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 0x8617 45 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 0x8618 46 47 #define VCE_V3_0_FW_SIZE (384 * 1024) 48 #define VCE_V3_0_STACK_SIZE (64 * 1024) 49 #define VCE_V3_0_DATA_SIZE ((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024)) 50 51 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx); 52 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev); 53 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev); 54 55 /** 56 * vce_v3_0_ring_get_rptr - get read pointer 57 * 58 * @ring: amdgpu_ring pointer 59 * 60 * Returns the current hardware read pointer 61 */ 62 static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) 63 { 64 struct amdgpu_device *adev = ring->adev; 65 66 if (ring == &adev->vce.ring[0]) 67 return RREG32(mmVCE_RB_RPTR); 68 else 69 return RREG32(mmVCE_RB_RPTR2); 70 } 71 72 /** 73 * vce_v3_0_ring_get_wptr - get write pointer 74 * 75 * @ring: amdgpu_ring pointer 76 * 77 * Returns the current hardware write pointer 78 */ 79 static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) 80 { 81 struct amdgpu_device *adev = ring->adev; 82 83 if (ring == &adev->vce.ring[0]) 84 return RREG32(mmVCE_RB_WPTR); 85 else 86 return RREG32(mmVCE_RB_WPTR2); 87 } 88 89 /** 90 * vce_v3_0_ring_set_wptr - set write pointer 91 * 92 * @ring: amdgpu_ring pointer 93 * 94 * Commits the write pointer to the hardware 95 */ 96 static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) 97 { 98 struct amdgpu_device *adev = ring->adev; 99 100 if (ring == &adev->vce.ring[0]) 101 WREG32(mmVCE_RB_WPTR, ring->wptr); 102 else 103 WREG32(mmVCE_RB_WPTR2, ring->wptr); 104 } 105 106 static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) 107 { 108 u32 tmp, data; 109 110 tmp = data = RREG32(mmVCE_RB_ARB_CTRL); 111 if (override) 112 data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; 113 else 114 data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; 115 116 if (tmp != data) 117 WREG32(mmVCE_RB_ARB_CTRL, data); 118 } 119 120 static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev, 121 bool gated) 122 { 123 u32 tmp, data; 124 /* Set Override to disable Clock Gating */ 125 vce_v3_0_override_vce_clock_gating(adev, true); 126 127 if (!gated) { 128 /* Force CLOCK ON for VCE_CLOCK_GATING_B, 129 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} 130 * VREG can be FORCE ON or set to Dynamic, but can't be OFF 131 */ 132 tmp = data = RREG32(mmVCE_CLOCK_GATING_B); 133 data |= 0x1ff; 134 data &= ~0xef0000; 135 if (tmp != data) 136 WREG32(mmVCE_CLOCK_GATING_B, data); 137 138 /* Force CLOCK ON for VCE_UENC_CLOCK_GATING, 139 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} 140 */ 141 tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); 142 data |= 0x3ff000; 143 data &= ~0xffc00000; 144 if (tmp != data) 145 WREG32(mmVCE_UENC_CLOCK_GATING, data); 146 147 /* set VCE_UENC_CLOCK_GATING_2 */ 148 tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); 149 data |= 0x2; 150 data &= ~0x2; 151 if (tmp != data) 152 WREG32(mmVCE_UENC_CLOCK_GATING_2, data); 153 154 /* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */ 155 tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 156 data |= 0x37f; 157 if (tmp != data) 158 WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); 159 160 /* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */ 161 tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); 162 data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | 163 VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | 164 VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | 165 0x8; 166 if (tmp != data) 167 WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); 168 } else { 169 /* Force CLOCK OFF for VCE_CLOCK_GATING_B, 170 * {*, *_FORCE_OFF} = {*, 1} 171 * set VREG to Dynamic, as it can't be OFF 172 */ 173 tmp = data = RREG32(mmVCE_CLOCK_GATING_B); 174 data &= ~0x80010; 175 data |= 0xe70008; 176 if (tmp != data) 177 WREG32(mmVCE_CLOCK_GATING_B, data); 178 /* Force CLOCK OFF for VCE_UENC_CLOCK_GATING, 179 * Force ClOCK OFF takes precedent over Force CLOCK ON setting. 180 * {*_FORCE_ON, *_FORCE_OFF} = {*, 1} 181 */ 182 tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); 183 data |= 0xffc00000; 184 if (tmp != data) 185 WREG32(mmVCE_UENC_CLOCK_GATING, data); 186 /* Set VCE_UENC_CLOCK_GATING_2 */ 187 tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); 188 data |= 0x10000; 189 if (tmp != data) 190 WREG32(mmVCE_UENC_CLOCK_GATING_2, data); 191 /* Set VCE_UENC_REG_CLOCK_GATING to dynamic */ 192 tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); 193 data &= ~0xffc00000; 194 if (tmp != data) 195 WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); 196 /* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */ 197 tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); 198 data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | 199 VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | 200 VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | 201 0x8); 202 if (tmp != data) 203 WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); 204 } 205 vce_v3_0_override_vce_clock_gating(adev, false); 206 } 207 208 /** 209 * vce_v3_0_start - start VCE block 210 * 211 * @adev: amdgpu_device pointer 212 * 213 * Setup and start the VCE block 214 */ 215 static int vce_v3_0_start(struct amdgpu_device *adev) 216 { 217 struct amdgpu_ring *ring; 218 int idx, i, j, r; 219 220 mutex_lock(&adev->grbm_idx_mutex); 221 for (idx = 0; idx < 2; ++idx) { 222 223 if (adev->vce.harvest_config & (1 << idx)) 224 continue; 225 226 if (idx == 0) 227 WREG32_P(mmGRBM_GFX_INDEX, 0, 228 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 229 else 230 WREG32_P(mmGRBM_GFX_INDEX, 231 GRBM_GFX_INDEX__VCE_INSTANCE_MASK, 232 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 233 234 vce_v3_0_mc_resume(adev, idx); 235 236 /* set BUSY flag */ 237 WREG32_P(mmVCE_STATUS, 1, ~1); 238 if (adev->asic_type >= CHIP_STONEY) 239 WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001); 240 else 241 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, 242 ~VCE_VCPU_CNTL__CLK_EN_MASK); 243 244 WREG32_P(mmVCE_SOFT_RESET, 245 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 246 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 247 248 mdelay(100); 249 250 WREG32_P(mmVCE_SOFT_RESET, 0, 251 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 252 253 for (i = 0; i < 10; ++i) { 254 uint32_t status; 255 for (j = 0; j < 100; ++j) { 256 status = RREG32(mmVCE_STATUS); 257 if (status & 2) 258 break; 259 mdelay(10); 260 } 261 r = 0; 262 if (status & 2) 263 break; 264 265 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); 266 WREG32_P(mmVCE_SOFT_RESET, 267 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 268 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 269 mdelay(10); 270 WREG32_P(mmVCE_SOFT_RESET, 0, 271 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); 272 mdelay(10); 273 r = -1; 274 } 275 276 /* clear BUSY flag */ 277 WREG32_P(mmVCE_STATUS, 0, ~1); 278 279 /* Set Clock-Gating off */ 280 if (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG) 281 vce_v3_0_set_vce_sw_clock_gating(adev, false); 282 283 if (r) { 284 DRM_ERROR("VCE not responding, giving up!!!\n"); 285 mutex_unlock(&adev->grbm_idx_mutex); 286 return r; 287 } 288 } 289 290 WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 291 mutex_unlock(&adev->grbm_idx_mutex); 292 293 ring = &adev->vce.ring[0]; 294 WREG32(mmVCE_RB_RPTR, ring->wptr); 295 WREG32(mmVCE_RB_WPTR, ring->wptr); 296 WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); 297 WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 298 WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); 299 300 ring = &adev->vce.ring[1]; 301 WREG32(mmVCE_RB_RPTR2, ring->wptr); 302 WREG32(mmVCE_RB_WPTR2, ring->wptr); 303 WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); 304 WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 305 WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); 306 307 return 0; 308 } 309 310 #define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074 311 #define VCE_HARVEST_FUSE_MACRO__SHIFT 27 312 #define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000 313 314 static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev) 315 { 316 u32 tmp; 317 unsigned ret; 318 319 /* Fiji, Stoney are single pipe */ 320 if ((adev->asic_type == CHIP_FIJI) || 321 (adev->asic_type == CHIP_STONEY)){ 322 ret = AMDGPU_VCE_HARVEST_VCE1; 323 return ret; 324 } 325 326 /* Tonga and CZ are dual or single pipe */ 327 if (adev->flags & AMD_IS_APU) 328 tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) & 329 VCE_HARVEST_FUSE_MACRO__MASK) >> 330 VCE_HARVEST_FUSE_MACRO__SHIFT; 331 else 332 tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) & 333 CC_HARVEST_FUSES__VCE_DISABLE_MASK) >> 334 CC_HARVEST_FUSES__VCE_DISABLE__SHIFT; 335 336 switch (tmp) { 337 case 1: 338 ret = AMDGPU_VCE_HARVEST_VCE0; 339 break; 340 case 2: 341 ret = AMDGPU_VCE_HARVEST_VCE1; 342 break; 343 case 3: 344 ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1; 345 break; 346 default: 347 ret = 0; 348 } 349 350 return ret; 351 } 352 353 static int vce_v3_0_early_init(void *handle) 354 { 355 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 356 357 adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev); 358 359 if ((adev->vce.harvest_config & 360 (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) == 361 (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) 362 return -ENOENT; 363 364 vce_v3_0_set_ring_funcs(adev); 365 vce_v3_0_set_irq_funcs(adev); 366 367 return 0; 368 } 369 370 static int vce_v3_0_sw_init(void *handle) 371 { 372 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 373 struct amdgpu_ring *ring; 374 int r; 375 376 /* VCE */ 377 r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq); 378 if (r) 379 return r; 380 381 r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE + 382 (VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2); 383 if (r) 384 return r; 385 386 r = amdgpu_vce_resume(adev); 387 if (r) 388 return r; 389 390 ring = &adev->vce.ring[0]; 391 sprintf(ring->name, "vce0"); 392 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 393 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 394 if (r) 395 return r; 396 397 ring = &adev->vce.ring[1]; 398 sprintf(ring->name, "vce1"); 399 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf, 400 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); 401 if (r) 402 return r; 403 404 return r; 405 } 406 407 static int vce_v3_0_sw_fini(void *handle) 408 { 409 int r; 410 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 411 412 r = amdgpu_vce_suspend(adev); 413 if (r) 414 return r; 415 416 r = amdgpu_vce_sw_fini(adev); 417 if (r) 418 return r; 419 420 return r; 421 } 422 423 static int vce_v3_0_hw_init(void *handle) 424 { 425 struct amdgpu_ring *ring; 426 int r; 427 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 428 429 r = vce_v3_0_start(adev); 430 if (r) 431 return r; 432 433 ring = &adev->vce.ring[0]; 434 ring->ready = true; 435 r = amdgpu_ring_test_ring(ring); 436 if (r) { 437 ring->ready = false; 438 return r; 439 } 440 441 ring = &adev->vce.ring[1]; 442 ring->ready = true; 443 r = amdgpu_ring_test_ring(ring); 444 if (r) { 445 ring->ready = false; 446 return r; 447 } 448 449 DRM_INFO("VCE initialized successfully.\n"); 450 451 return 0; 452 } 453 454 static int vce_v3_0_hw_fini(void *handle) 455 { 456 return 0; 457 } 458 459 static int vce_v3_0_suspend(void *handle) 460 { 461 int r; 462 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 463 464 r = vce_v3_0_hw_fini(adev); 465 if (r) 466 return r; 467 468 r = amdgpu_vce_suspend(adev); 469 if (r) 470 return r; 471 472 return r; 473 } 474 475 static int vce_v3_0_resume(void *handle) 476 { 477 int r; 478 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 479 480 r = amdgpu_vce_resume(adev); 481 if (r) 482 return r; 483 484 r = vce_v3_0_hw_init(adev); 485 if (r) 486 return r; 487 488 return r; 489 } 490 491 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx) 492 { 493 uint32_t offset, size; 494 495 WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16)); 496 WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 497 WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 498 WREG32(mmVCE_CLOCK_GATING_B, 0xf7); 499 500 WREG32(mmVCE_LMI_CTRL, 0x00398000); 501 WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1); 502 WREG32(mmVCE_LMI_SWAP_CNTL, 0); 503 WREG32(mmVCE_LMI_SWAP_CNTL1, 0); 504 WREG32(mmVCE_LMI_VM_CTRL, 0); 505 if (adev->asic_type >= CHIP_STONEY) { 506 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8)); 507 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8)); 508 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8)); 509 } else 510 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8)); 511 offset = AMDGPU_VCE_FIRMWARE_OFFSET; 512 size = VCE_V3_0_FW_SIZE; 513 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff); 514 WREG32(mmVCE_VCPU_CACHE_SIZE0, size); 515 516 if (idx == 0) { 517 offset += size; 518 size = VCE_V3_0_STACK_SIZE; 519 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff); 520 WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 521 offset += size; 522 size = VCE_V3_0_DATA_SIZE; 523 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff); 524 WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 525 } else { 526 offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE; 527 size = VCE_V3_0_STACK_SIZE; 528 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff); 529 WREG32(mmVCE_VCPU_CACHE_SIZE1, size); 530 offset += size; 531 size = VCE_V3_0_DATA_SIZE; 532 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff); 533 WREG32(mmVCE_VCPU_CACHE_SIZE2, size); 534 } 535 536 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); 537 538 WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK, 539 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 540 } 541 542 static bool vce_v3_0_is_idle(void *handle) 543 { 544 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 545 u32 mask = 0; 546 int idx; 547 548 for (idx = 0; idx < 2; ++idx) { 549 if (adev->vce.harvest_config & (1 << idx)) 550 continue; 551 552 if (idx == 0) 553 mask |= SRBM_STATUS2__VCE0_BUSY_MASK; 554 else 555 mask |= SRBM_STATUS2__VCE1_BUSY_MASK; 556 } 557 558 return !(RREG32(mmSRBM_STATUS2) & mask); 559 } 560 561 static int vce_v3_0_wait_for_idle(void *handle) 562 { 563 unsigned i; 564 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 565 u32 mask = 0; 566 int idx; 567 568 for (idx = 0; idx < 2; ++idx) { 569 if (adev->vce.harvest_config & (1 << idx)) 570 continue; 571 572 if (idx == 0) 573 mask |= SRBM_STATUS2__VCE0_BUSY_MASK; 574 else 575 mask |= SRBM_STATUS2__VCE1_BUSY_MASK; 576 } 577 578 for (i = 0; i < adev->usec_timeout; i++) { 579 if (!(RREG32(mmSRBM_STATUS2) & mask)) 580 return 0; 581 } 582 return -ETIMEDOUT; 583 } 584 585 static int vce_v3_0_soft_reset(void *handle) 586 { 587 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 588 u32 mask = 0; 589 int idx; 590 591 for (idx = 0; idx < 2; ++idx) { 592 if (adev->vce.harvest_config & (1 << idx)) 593 continue; 594 595 if (idx == 0) 596 mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK; 597 else 598 mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK; 599 } 600 WREG32_P(mmSRBM_SOFT_RESET, mask, 601 ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK | 602 SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK)); 603 mdelay(5); 604 605 return vce_v3_0_start(adev); 606 } 607 608 static void vce_v3_0_print_status(void *handle) 609 { 610 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 611 612 dev_info(adev->dev, "VCE 3.0 registers\n"); 613 dev_info(adev->dev, " VCE_STATUS=0x%08X\n", 614 RREG32(mmVCE_STATUS)); 615 dev_info(adev->dev, " VCE_VCPU_CNTL=0x%08X\n", 616 RREG32(mmVCE_VCPU_CNTL)); 617 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET0=0x%08X\n", 618 RREG32(mmVCE_VCPU_CACHE_OFFSET0)); 619 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE0=0x%08X\n", 620 RREG32(mmVCE_VCPU_CACHE_SIZE0)); 621 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET1=0x%08X\n", 622 RREG32(mmVCE_VCPU_CACHE_OFFSET1)); 623 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE1=0x%08X\n", 624 RREG32(mmVCE_VCPU_CACHE_SIZE1)); 625 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET2=0x%08X\n", 626 RREG32(mmVCE_VCPU_CACHE_OFFSET2)); 627 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE2=0x%08X\n", 628 RREG32(mmVCE_VCPU_CACHE_SIZE2)); 629 dev_info(adev->dev, " VCE_SOFT_RESET=0x%08X\n", 630 RREG32(mmVCE_SOFT_RESET)); 631 dev_info(adev->dev, " VCE_RB_BASE_LO2=0x%08X\n", 632 RREG32(mmVCE_RB_BASE_LO2)); 633 dev_info(adev->dev, " VCE_RB_BASE_HI2=0x%08X\n", 634 RREG32(mmVCE_RB_BASE_HI2)); 635 dev_info(adev->dev, " VCE_RB_SIZE2=0x%08X\n", 636 RREG32(mmVCE_RB_SIZE2)); 637 dev_info(adev->dev, " VCE_RB_RPTR2=0x%08X\n", 638 RREG32(mmVCE_RB_RPTR2)); 639 dev_info(adev->dev, " VCE_RB_WPTR2=0x%08X\n", 640 RREG32(mmVCE_RB_WPTR2)); 641 dev_info(adev->dev, " VCE_RB_BASE_LO=0x%08X\n", 642 RREG32(mmVCE_RB_BASE_LO)); 643 dev_info(adev->dev, " VCE_RB_BASE_HI=0x%08X\n", 644 RREG32(mmVCE_RB_BASE_HI)); 645 dev_info(adev->dev, " VCE_RB_SIZE=0x%08X\n", 646 RREG32(mmVCE_RB_SIZE)); 647 dev_info(adev->dev, " VCE_RB_RPTR=0x%08X\n", 648 RREG32(mmVCE_RB_RPTR)); 649 dev_info(adev->dev, " VCE_RB_WPTR=0x%08X\n", 650 RREG32(mmVCE_RB_WPTR)); 651 dev_info(adev->dev, " VCE_CLOCK_GATING_A=0x%08X\n", 652 RREG32(mmVCE_CLOCK_GATING_A)); 653 dev_info(adev->dev, " VCE_CLOCK_GATING_B=0x%08X\n", 654 RREG32(mmVCE_CLOCK_GATING_B)); 655 dev_info(adev->dev, " VCE_UENC_CLOCK_GATING=0x%08X\n", 656 RREG32(mmVCE_UENC_CLOCK_GATING)); 657 dev_info(adev->dev, " VCE_UENC_REG_CLOCK_GATING=0x%08X\n", 658 RREG32(mmVCE_UENC_REG_CLOCK_GATING)); 659 dev_info(adev->dev, " VCE_SYS_INT_EN=0x%08X\n", 660 RREG32(mmVCE_SYS_INT_EN)); 661 dev_info(adev->dev, " VCE_LMI_CTRL2=0x%08X\n", 662 RREG32(mmVCE_LMI_CTRL2)); 663 dev_info(adev->dev, " VCE_LMI_CTRL=0x%08X\n", 664 RREG32(mmVCE_LMI_CTRL)); 665 dev_info(adev->dev, " VCE_LMI_VM_CTRL=0x%08X\n", 666 RREG32(mmVCE_LMI_VM_CTRL)); 667 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL=0x%08X\n", 668 RREG32(mmVCE_LMI_SWAP_CNTL)); 669 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL1=0x%08X\n", 670 RREG32(mmVCE_LMI_SWAP_CNTL1)); 671 dev_info(adev->dev, " VCE_LMI_CACHE_CTRL=0x%08X\n", 672 RREG32(mmVCE_LMI_CACHE_CTRL)); 673 } 674 675 static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev, 676 struct amdgpu_irq_src *source, 677 unsigned type, 678 enum amdgpu_interrupt_state state) 679 { 680 uint32_t val = 0; 681 682 if (state == AMDGPU_IRQ_STATE_ENABLE) 683 val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK; 684 685 WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); 686 return 0; 687 } 688 689 static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, 690 struct amdgpu_irq_src *source, 691 struct amdgpu_iv_entry *entry) 692 { 693 DRM_DEBUG("IH: VCE\n"); 694 695 WREG32_P(mmVCE_SYS_INT_STATUS, 696 VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK, 697 ~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK); 698 699 switch (entry->src_data) { 700 case 0: 701 amdgpu_fence_process(&adev->vce.ring[0]); 702 break; 703 case 1: 704 amdgpu_fence_process(&adev->vce.ring[1]); 705 break; 706 default: 707 DRM_ERROR("Unhandled interrupt: %d %d\n", 708 entry->src_id, entry->src_data); 709 break; 710 } 711 712 return 0; 713 } 714 715 static int vce_v3_0_set_clockgating_state(void *handle, 716 enum amd_clockgating_state state) 717 { 718 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 719 bool enable = (state == AMD_CG_STATE_GATE) ? true : false; 720 int i; 721 722 if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)) 723 return 0; 724 725 mutex_lock(&adev->grbm_idx_mutex); 726 for (i = 0; i < 2; i++) { 727 /* Program VCE Instance 0 or 1 if not harvested */ 728 if (adev->vce.harvest_config & (1 << i)) 729 continue; 730 731 if (i == 0) 732 WREG32_P(mmGRBM_GFX_INDEX, 0, 733 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 734 else 735 WREG32_P(mmGRBM_GFX_INDEX, 736 GRBM_GFX_INDEX__VCE_INSTANCE_MASK, 737 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 738 739 if (enable) { 740 /* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */ 741 uint32_t data = RREG32(mmVCE_CLOCK_GATING_A); 742 data &= ~(0xf | 0xff0); 743 data |= ((0x0 << 0) | (0x04 << 4)); 744 WREG32(mmVCE_CLOCK_GATING_A, data); 745 746 /* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */ 747 data = RREG32(mmVCE_UENC_CLOCK_GATING); 748 data &= ~(0xf | 0xff0); 749 data |= ((0x0 << 0) | (0x04 << 4)); 750 WREG32(mmVCE_UENC_CLOCK_GATING, data); 751 } 752 753 vce_v3_0_set_vce_sw_clock_gating(adev, enable); 754 } 755 756 WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); 757 mutex_unlock(&adev->grbm_idx_mutex); 758 759 return 0; 760 } 761 762 static int vce_v3_0_set_powergating_state(void *handle, 763 enum amd_powergating_state state) 764 { 765 /* This doesn't actually powergate the VCE block. 766 * That's done in the dpm code via the SMC. This 767 * just re-inits the block as necessary. The actual 768 * gating still happens in the dpm code. We should 769 * revisit this when there is a cleaner line between 770 * the smc and the hw blocks 771 */ 772 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 773 774 if (state == AMD_PG_STATE_GATE) 775 /* XXX do we need a vce_v3_0_stop()? */ 776 return 0; 777 else 778 return vce_v3_0_start(adev); 779 } 780 781 const struct amd_ip_funcs vce_v3_0_ip_funcs = { 782 .early_init = vce_v3_0_early_init, 783 .late_init = NULL, 784 .sw_init = vce_v3_0_sw_init, 785 .sw_fini = vce_v3_0_sw_fini, 786 .hw_init = vce_v3_0_hw_init, 787 .hw_fini = vce_v3_0_hw_fini, 788 .suspend = vce_v3_0_suspend, 789 .resume = vce_v3_0_resume, 790 .is_idle = vce_v3_0_is_idle, 791 .wait_for_idle = vce_v3_0_wait_for_idle, 792 .soft_reset = vce_v3_0_soft_reset, 793 .print_status = vce_v3_0_print_status, 794 .set_clockgating_state = vce_v3_0_set_clockgating_state, 795 .set_powergating_state = vce_v3_0_set_powergating_state, 796 }; 797 798 static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { 799 .get_rptr = vce_v3_0_ring_get_rptr, 800 .get_wptr = vce_v3_0_ring_get_wptr, 801 .set_wptr = vce_v3_0_ring_set_wptr, 802 .parse_cs = amdgpu_vce_ring_parse_cs, 803 .emit_ib = amdgpu_vce_ring_emit_ib, 804 .emit_fence = amdgpu_vce_ring_emit_fence, 805 .emit_semaphore = amdgpu_vce_ring_emit_semaphore, 806 .test_ring = amdgpu_vce_ring_test_ring, 807 .test_ib = amdgpu_vce_ring_test_ib, 808 .insert_nop = amdgpu_ring_insert_nop, 809 }; 810 811 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) 812 { 813 adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs; 814 adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs; 815 } 816 817 static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { 818 .set = vce_v3_0_set_interrupt_state, 819 .process = vce_v3_0_process_interrupt, 820 }; 821 822 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev) 823 { 824 adev->vce.irq.num_types = 1; 825 adev->vce.irq.funcs = &vce_v3_0_irq_funcs; 826 }; 827