blob: 370c6c9d81c26550302b974a4b794ed464090b65 [file] [log] [blame]
Alex Deucheraaa36a9762015-04-20 17:31:14 -04001/*
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"
Alex Deucherbe4f38e2015-09-03 19:03:11 -040035#include "oss/oss_3_0_d.h"
36#include "oss/oss_3_0_sh_mask.h"
Leo Liu5bbc5532015-05-06 15:20:41 -040037#include "gca/gfx_8_0_d.h"
Alex Deucher6a585772015-07-10 14:16:24 -040038#include "smu/smu_7_1_2_d.h"
39#include "smu/smu_7_1_2_sh_mask.h"
Leo Liu5bbc5532015-05-06 15:20:41 -040040
41#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
42#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
Leo Liu3c0ff9f2015-11-17 10:25:31 -050043#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
Alex Deucheraaa36a9762015-04-20 17:31:14 -040046
Leo Liue9822622015-05-06 14:31:27 -040047#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
Leo Liu5bbc5532015-05-06 15:20:41 -040051static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
Alex Deucheraaa36a9762015-04-20 17:31:14 -040052static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
53static 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 */
62static 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 */
79static 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 */
96static 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/**
107 * vce_v3_0_start - start VCE block
108 *
109 * @adev: amdgpu_device pointer
110 *
111 * Setup and start the VCE block
112 */
113static int vce_v3_0_start(struct amdgpu_device *adev)
114{
115 struct amdgpu_ring *ring;
Leo Liu5bbc5532015-05-06 15:20:41 -0400116 int idx, i, j, r;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400117
Leo Liu5bbc5532015-05-06 15:20:41 -0400118 mutex_lock(&adev->grbm_idx_mutex);
119 for (idx = 0; idx < 2; ++idx) {
Alex Deucher6a585772015-07-10 14:16:24 -0400120
121 if (adev->vce.harvest_config & (1 << idx))
122 continue;
123
Leo Liu5bbc5532015-05-06 15:20:41 -0400124 if(idx == 0)
125 WREG32_P(mmGRBM_GFX_INDEX, 0,
126 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
127 else
128 WREG32_P(mmGRBM_GFX_INDEX,
129 GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
130 ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400131
Leo Liu5bbc5532015-05-06 15:20:41 -0400132 vce_v3_0_mc_resume(adev, idx);
133
134 /* set BUSY flag */
135 WREG32_P(mmVCE_STATUS, 1, ~1);
Leo Liu3c0ff9f2015-11-17 10:25:31 -0500136 if (adev->asic_type >= CHIP_STONEY)
137 WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
138 else
139 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
140 ~VCE_VCPU_CNTL__CLK_EN_MASK);
Leo Liu5bbc5532015-05-06 15:20:41 -0400141
142 WREG32_P(mmVCE_SOFT_RESET,
143 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
144 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
145
146 mdelay(100);
147
148 WREG32_P(mmVCE_SOFT_RESET, 0,
149 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
150
151 for (i = 0; i < 10; ++i) {
152 uint32_t status;
153 for (j = 0; j < 100; ++j) {
154 status = RREG32(mmVCE_STATUS);
155 if (status & 2)
156 break;
157 mdelay(10);
158 }
159 r = 0;
160 if (status & 2)
161 break;
162
163 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
164 WREG32_P(mmVCE_SOFT_RESET,
165 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
166 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
167 mdelay(10);
168 WREG32_P(mmVCE_SOFT_RESET, 0,
169 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
170 mdelay(10);
171 r = -1;
172 }
173
174 /* clear BUSY flag */
175 WREG32_P(mmVCE_STATUS, 0, ~1);
176
177 if (r) {
178 DRM_ERROR("VCE not responding, giving up!!!\n");
179 mutex_unlock(&adev->grbm_idx_mutex);
180 return r;
181 }
182 }
183
184 WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
185 mutex_unlock(&adev->grbm_idx_mutex);
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400186
187 ring = &adev->vce.ring[0];
188 WREG32(mmVCE_RB_RPTR, ring->wptr);
189 WREG32(mmVCE_RB_WPTR, ring->wptr);
190 WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
191 WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
192 WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
193
194 ring = &adev->vce.ring[1];
195 WREG32(mmVCE_RB_RPTR2, ring->wptr);
196 WREG32(mmVCE_RB_WPTR2, ring->wptr);
197 WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
198 WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
199 WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
200
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400201 return 0;
202}
203
Alex Deucher6a585772015-07-10 14:16:24 -0400204#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
205#define VCE_HARVEST_FUSE_MACRO__SHIFT 27
206#define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000
207
208static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
209{
210 u32 tmp;
211 unsigned ret;
212
Samuel Licfaba562015-10-08 16:27:55 -0400213 /* Fiji, Stoney are single pipe */
214 if ((adev->asic_type == CHIP_FIJI) ||
215 (adev->asic_type == CHIP_STONEY)){
Alex Deucher188a9bc2015-07-27 14:24:14 -0400216 ret = AMDGPU_VCE_HARVEST_VCE1;
217 return ret;
218 }
219
220 /* Tonga and CZ are dual or single pipe */
Jammy Zhou2f7d10b2015-07-22 11:29:01 +0800221 if (adev->flags & AMD_IS_APU)
Alex Deucher6a585772015-07-10 14:16:24 -0400222 tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
223 VCE_HARVEST_FUSE_MACRO__MASK) >>
224 VCE_HARVEST_FUSE_MACRO__SHIFT;
225 else
226 tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
227 CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
228 CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
229
230 switch (tmp) {
231 case 1:
232 ret = AMDGPU_VCE_HARVEST_VCE0;
233 break;
234 case 2:
235 ret = AMDGPU_VCE_HARVEST_VCE1;
236 break;
237 case 3:
238 ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
239 break;
240 default:
241 ret = 0;
242 }
243
244 return ret;
245}
246
yanyang15fc3aee2015-05-22 14:39:35 -0400247static int vce_v3_0_early_init(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400248{
yanyang15fc3aee2015-05-22 14:39:35 -0400249 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
250
Alex Deucher6a585772015-07-10 14:16:24 -0400251 adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
252
253 if ((adev->vce.harvest_config &
254 (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
255 (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
256 return -ENOENT;
257
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400258 vce_v3_0_set_ring_funcs(adev);
259 vce_v3_0_set_irq_funcs(adev);
260
261 return 0;
262}
263
yanyang15fc3aee2015-05-22 14:39:35 -0400264static int vce_v3_0_sw_init(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400265{
yanyang15fc3aee2015-05-22 14:39:35 -0400266 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400267 struct amdgpu_ring *ring;
268 int r;
269
270 /* VCE */
271 r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
272 if (r)
273 return r;
274
Leo Liue9822622015-05-06 14:31:27 -0400275 r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
276 (VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400277 if (r)
278 return r;
279
280 r = amdgpu_vce_resume(adev);
281 if (r)
282 return r;
283
284 ring = &adev->vce.ring[0];
285 sprintf(ring->name, "vce0");
286 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
287 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
288 if (r)
289 return r;
290
291 ring = &adev->vce.ring[1];
292 sprintf(ring->name, "vce1");
293 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
294 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
295 if (r)
296 return r;
297
298 return r;
299}
300
yanyang15fc3aee2015-05-22 14:39:35 -0400301static int vce_v3_0_sw_fini(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400302{
303 int r;
yanyang15fc3aee2015-05-22 14:39:35 -0400304 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400305
306 r = amdgpu_vce_suspend(adev);
307 if (r)
308 return r;
309
310 r = amdgpu_vce_sw_fini(adev);
311 if (r)
312 return r;
313
314 return r;
315}
316
yanyang15fc3aee2015-05-22 14:39:35 -0400317static int vce_v3_0_hw_init(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400318{
319 struct amdgpu_ring *ring;
320 int r;
yanyang15fc3aee2015-05-22 14:39:35 -0400321 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400322
323 r = vce_v3_0_start(adev);
324 if (r)
325 return r;
326
327 ring = &adev->vce.ring[0];
328 ring->ready = true;
329 r = amdgpu_ring_test_ring(ring);
330 if (r) {
331 ring->ready = false;
332 return r;
333 }
334
335 ring = &adev->vce.ring[1];
336 ring->ready = true;
337 r = amdgpu_ring_test_ring(ring);
338 if (r) {
339 ring->ready = false;
340 return r;
341 }
342
343 DRM_INFO("VCE initialized successfully.\n");
344
345 return 0;
346}
347
yanyang15fc3aee2015-05-22 14:39:35 -0400348static int vce_v3_0_hw_fini(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400349{
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400350 return 0;
351}
352
yanyang15fc3aee2015-05-22 14:39:35 -0400353static int vce_v3_0_suspend(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400354{
355 int r;
yanyang15fc3aee2015-05-22 14:39:35 -0400356 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400357
358 r = vce_v3_0_hw_fini(adev);
359 if (r)
360 return r;
361
362 r = amdgpu_vce_suspend(adev);
363 if (r)
364 return r;
365
366 return r;
367}
368
yanyang15fc3aee2015-05-22 14:39:35 -0400369static int vce_v3_0_resume(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400370{
371 int r;
yanyang15fc3aee2015-05-22 14:39:35 -0400372 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400373
374 r = amdgpu_vce_resume(adev);
375 if (r)
376 return r;
377
378 r = vce_v3_0_hw_init(adev);
379 if (r)
380 return r;
381
382 return r;
383}
384
Leo Liu5bbc5532015-05-06 15:20:41 -0400385static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400386{
387 uint32_t offset, size;
388
389 WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
390 WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
391 WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
392 WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
393
394 WREG32(mmVCE_LMI_CTRL, 0x00398000);
395 WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
396 WREG32(mmVCE_LMI_SWAP_CNTL, 0);
397 WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
398 WREG32(mmVCE_LMI_VM_CTRL, 0);
Leo Liu3c0ff9f2015-11-17 10:25:31 -0500399 if (adev->asic_type >= CHIP_STONEY) {
400 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
401 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
402 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
403 } else
404 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400405 offset = AMDGPU_VCE_FIRMWARE_OFFSET;
Leo Liue9822622015-05-06 14:31:27 -0400406 size = VCE_V3_0_FW_SIZE;
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400407 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
408 WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
409
Leo Liu5bbc5532015-05-06 15:20:41 -0400410 if (idx == 0) {
411 offset += size;
412 size = VCE_V3_0_STACK_SIZE;
413 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
414 WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
415 offset += size;
416 size = VCE_V3_0_DATA_SIZE;
417 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
418 WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
419 } else {
420 offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
421 size = VCE_V3_0_STACK_SIZE;
422 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
423 WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
424 offset += size;
425 size = VCE_V3_0_DATA_SIZE;
426 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
427 WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
428 }
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400429
430 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
431
432 WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
433 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
434}
435
yanyang15fc3aee2015-05-22 14:39:35 -0400436static bool vce_v3_0_is_idle(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400437{
yanyang15fc3aee2015-05-22 14:39:35 -0400438 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400439 u32 mask = 0;
440 int idx;
yanyang15fc3aee2015-05-22 14:39:35 -0400441
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400442 for (idx = 0; idx < 2; ++idx) {
443 if (adev->vce.harvest_config & (1 << idx))
444 continue;
445
446 if (idx == 0)
447 mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
448 else
449 mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
450 }
451
452 return !(RREG32(mmSRBM_STATUS2) & mask);
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400453}
454
yanyang15fc3aee2015-05-22 14:39:35 -0400455static int vce_v3_0_wait_for_idle(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400456{
457 unsigned i;
yanyang15fc3aee2015-05-22 14:39:35 -0400458 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400459 u32 mask = 0;
460 int idx;
461
462 for (idx = 0; idx < 2; ++idx) {
463 if (adev->vce.harvest_config & (1 << idx))
464 continue;
465
466 if (idx == 0)
467 mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
468 else
469 mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
470 }
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400471
472 for (i = 0; i < adev->usec_timeout; i++) {
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400473 if (!(RREG32(mmSRBM_STATUS2) & mask))
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400474 return 0;
475 }
476 return -ETIMEDOUT;
477}
478
yanyang15fc3aee2015-05-22 14:39:35 -0400479static int vce_v3_0_soft_reset(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400480{
yanyang15fc3aee2015-05-22 14:39:35 -0400481 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400482 u32 mask = 0;
483 int idx;
yanyang15fc3aee2015-05-22 14:39:35 -0400484
Alex Deucherbe4f38e2015-09-03 19:03:11 -0400485 for (idx = 0; idx < 2; ++idx) {
486 if (adev->vce.harvest_config & (1 << idx))
487 continue;
488
489 if (idx == 0)
490 mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
491 else
492 mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
493 }
494 WREG32_P(mmSRBM_SOFT_RESET, mask,
495 ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
496 SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400497 mdelay(5);
498
499 return vce_v3_0_start(adev);
500}
501
yanyang15fc3aee2015-05-22 14:39:35 -0400502static void vce_v3_0_print_status(void *handle)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400503{
yanyang15fc3aee2015-05-22 14:39:35 -0400504 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
505
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400506 dev_info(adev->dev, "VCE 3.0 registers\n");
507 dev_info(adev->dev, " VCE_STATUS=0x%08X\n",
508 RREG32(mmVCE_STATUS));
509 dev_info(adev->dev, " VCE_VCPU_CNTL=0x%08X\n",
510 RREG32(mmVCE_VCPU_CNTL));
511 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
512 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
513 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE0=0x%08X\n",
514 RREG32(mmVCE_VCPU_CACHE_SIZE0));
515 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
516 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
517 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE1=0x%08X\n",
518 RREG32(mmVCE_VCPU_CACHE_SIZE1));
519 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
520 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
521 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE2=0x%08X\n",
522 RREG32(mmVCE_VCPU_CACHE_SIZE2));
523 dev_info(adev->dev, " VCE_SOFT_RESET=0x%08X\n",
524 RREG32(mmVCE_SOFT_RESET));
525 dev_info(adev->dev, " VCE_RB_BASE_LO2=0x%08X\n",
526 RREG32(mmVCE_RB_BASE_LO2));
527 dev_info(adev->dev, " VCE_RB_BASE_HI2=0x%08X\n",
528 RREG32(mmVCE_RB_BASE_HI2));
529 dev_info(adev->dev, " VCE_RB_SIZE2=0x%08X\n",
530 RREG32(mmVCE_RB_SIZE2));
531 dev_info(adev->dev, " VCE_RB_RPTR2=0x%08X\n",
532 RREG32(mmVCE_RB_RPTR2));
533 dev_info(adev->dev, " VCE_RB_WPTR2=0x%08X\n",
534 RREG32(mmVCE_RB_WPTR2));
535 dev_info(adev->dev, " VCE_RB_BASE_LO=0x%08X\n",
536 RREG32(mmVCE_RB_BASE_LO));
537 dev_info(adev->dev, " VCE_RB_BASE_HI=0x%08X\n",
538 RREG32(mmVCE_RB_BASE_HI));
539 dev_info(adev->dev, " VCE_RB_SIZE=0x%08X\n",
540 RREG32(mmVCE_RB_SIZE));
541 dev_info(adev->dev, " VCE_RB_RPTR=0x%08X\n",
542 RREG32(mmVCE_RB_RPTR));
543 dev_info(adev->dev, " VCE_RB_WPTR=0x%08X\n",
544 RREG32(mmVCE_RB_WPTR));
545 dev_info(adev->dev, " VCE_CLOCK_GATING_A=0x%08X\n",
546 RREG32(mmVCE_CLOCK_GATING_A));
547 dev_info(adev->dev, " VCE_CLOCK_GATING_B=0x%08X\n",
548 RREG32(mmVCE_CLOCK_GATING_B));
549 dev_info(adev->dev, " VCE_UENC_CLOCK_GATING=0x%08X\n",
550 RREG32(mmVCE_UENC_CLOCK_GATING));
551 dev_info(adev->dev, " VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
552 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
553 dev_info(adev->dev, " VCE_SYS_INT_EN=0x%08X\n",
554 RREG32(mmVCE_SYS_INT_EN));
555 dev_info(adev->dev, " VCE_LMI_CTRL2=0x%08X\n",
556 RREG32(mmVCE_LMI_CTRL2));
557 dev_info(adev->dev, " VCE_LMI_CTRL=0x%08X\n",
558 RREG32(mmVCE_LMI_CTRL));
559 dev_info(adev->dev, " VCE_LMI_VM_CTRL=0x%08X\n",
560 RREG32(mmVCE_LMI_VM_CTRL));
561 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL=0x%08X\n",
562 RREG32(mmVCE_LMI_SWAP_CNTL));
563 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL1=0x%08X\n",
564 RREG32(mmVCE_LMI_SWAP_CNTL1));
565 dev_info(adev->dev, " VCE_LMI_CACHE_CTRL=0x%08X\n",
566 RREG32(mmVCE_LMI_CACHE_CTRL));
567}
568
569static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
570 struct amdgpu_irq_src *source,
571 unsigned type,
572 enum amdgpu_interrupt_state state)
573{
574 uint32_t val = 0;
575
576 if (state == AMDGPU_IRQ_STATE_ENABLE)
577 val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
578
579 WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
580 return 0;
581}
582
583static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
584 struct amdgpu_irq_src *source,
585 struct amdgpu_iv_entry *entry)
586{
587 DRM_DEBUG("IH: VCE\n");
Leo Liud6c29c32015-11-17 09:28:29 -0500588
589 WREG32_P(mmVCE_SYS_INT_STATUS,
590 VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK,
591 ~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK);
592
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400593 switch (entry->src_data) {
594 case 0:
595 amdgpu_fence_process(&adev->vce.ring[0]);
596 break;
597 case 1:
598 amdgpu_fence_process(&adev->vce.ring[1]);
599 break;
600 default:
601 DRM_ERROR("Unhandled interrupt: %d %d\n",
602 entry->src_id, entry->src_data);
603 break;
604 }
605
606 return 0;
607}
608
yanyang15fc3aee2015-05-22 14:39:35 -0400609static int vce_v3_0_set_clockgating_state(void *handle,
610 enum amd_clockgating_state state)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400611{
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400612 return 0;
613}
614
yanyang15fc3aee2015-05-22 14:39:35 -0400615static int vce_v3_0_set_powergating_state(void *handle,
616 enum amd_powergating_state state)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400617{
618 /* This doesn't actually powergate the VCE block.
619 * That's done in the dpm code via the SMC. This
620 * just re-inits the block as necessary. The actual
621 * gating still happens in the dpm code. We should
622 * revisit this when there is a cleaner line between
623 * the smc and the hw blocks
624 */
yanyang15fc3aee2015-05-22 14:39:35 -0400625 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
626
627 if (state == AMD_PG_STATE_GATE)
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400628 /* XXX do we need a vce_v3_0_stop()? */
629 return 0;
630 else
631 return vce_v3_0_start(adev);
632}
633
yanyang15fc3aee2015-05-22 14:39:35 -0400634const struct amd_ip_funcs vce_v3_0_ip_funcs = {
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400635 .early_init = vce_v3_0_early_init,
636 .late_init = NULL,
637 .sw_init = vce_v3_0_sw_init,
638 .sw_fini = vce_v3_0_sw_fini,
639 .hw_init = vce_v3_0_hw_init,
640 .hw_fini = vce_v3_0_hw_fini,
641 .suspend = vce_v3_0_suspend,
642 .resume = vce_v3_0_resume,
643 .is_idle = vce_v3_0_is_idle,
644 .wait_for_idle = vce_v3_0_wait_for_idle,
645 .soft_reset = vce_v3_0_soft_reset,
646 .print_status = vce_v3_0_print_status,
647 .set_clockgating_state = vce_v3_0_set_clockgating_state,
648 .set_powergating_state = vce_v3_0_set_powergating_state,
649};
650
651static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
652 .get_rptr = vce_v3_0_ring_get_rptr,
653 .get_wptr = vce_v3_0_ring_get_wptr,
654 .set_wptr = vce_v3_0_ring_set_wptr,
655 .parse_cs = amdgpu_vce_ring_parse_cs,
656 .emit_ib = amdgpu_vce_ring_emit_ib,
657 .emit_fence = amdgpu_vce_ring_emit_fence,
658 .emit_semaphore = amdgpu_vce_ring_emit_semaphore,
659 .test_ring = amdgpu_vce_ring_test_ring,
660 .test_ib = amdgpu_vce_ring_test_ib,
Jammy Zhouedff0e22015-09-01 13:04:08 +0800661 .insert_nop = amdgpu_ring_insert_nop,
Alex Deucheraaa36a9762015-04-20 17:31:14 -0400662};
663
664static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
665{
666 adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
667 adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
668}
669
670static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
671 .set = vce_v3_0_set_interrupt_state,
672 .process = vce_v3_0_process_interrupt,
673};
674
675static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
676{
677 adev->vce.irq.num_types = 1;
678 adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
679};