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