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