drm/amdgpu: recalculate VCE firmware BO size
[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"
35#include "oss/oss_2_0_d.h"
36#include "oss/oss_2_0_sh_mask.h"
37
e9822622
LL
38#define VCE_V3_0_FW_SIZE (384 * 1024)
39#define VCE_V3_0_STACK_SIZE (64 * 1024)
40#define VCE_V3_0_DATA_SIZE ((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
41
aaa36a97
AD
42static void vce_v3_0_mc_resume(struct amdgpu_device *adev);
43static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
44static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
45
46/**
47 * vce_v3_0_ring_get_rptr - get read pointer
48 *
49 * @ring: amdgpu_ring pointer
50 *
51 * Returns the current hardware read pointer
52 */
53static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
54{
55 struct amdgpu_device *adev = ring->adev;
56
57 if (ring == &adev->vce.ring[0])
58 return RREG32(mmVCE_RB_RPTR);
59 else
60 return RREG32(mmVCE_RB_RPTR2);
61}
62
63/**
64 * vce_v3_0_ring_get_wptr - get write pointer
65 *
66 * @ring: amdgpu_ring pointer
67 *
68 * Returns the current hardware write pointer
69 */
70static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
71{
72 struct amdgpu_device *adev = ring->adev;
73
74 if (ring == &adev->vce.ring[0])
75 return RREG32(mmVCE_RB_WPTR);
76 else
77 return RREG32(mmVCE_RB_WPTR2);
78}
79
80/**
81 * vce_v3_0_ring_set_wptr - set write pointer
82 *
83 * @ring: amdgpu_ring pointer
84 *
85 * Commits the write pointer to the hardware
86 */
87static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
88{
89 struct amdgpu_device *adev = ring->adev;
90
91 if (ring == &adev->vce.ring[0])
92 WREG32(mmVCE_RB_WPTR, ring->wptr);
93 else
94 WREG32(mmVCE_RB_WPTR2, ring->wptr);
95}
96
97/**
98 * vce_v3_0_start - start VCE block
99 *
100 * @adev: amdgpu_device pointer
101 *
102 * Setup and start the VCE block
103 */
104static int vce_v3_0_start(struct amdgpu_device *adev)
105{
106 struct amdgpu_ring *ring;
107 int i, j, r;
108
109 vce_v3_0_mc_resume(adev);
110
111 /* set BUSY flag */
112 WREG32_P(mmVCE_STATUS, 1, ~1);
113
114 ring = &adev->vce.ring[0];
115 WREG32(mmVCE_RB_RPTR, ring->wptr);
116 WREG32(mmVCE_RB_WPTR, ring->wptr);
117 WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
118 WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
119 WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
120
121 ring = &adev->vce.ring[1];
122 WREG32(mmVCE_RB_RPTR2, ring->wptr);
123 WREG32(mmVCE_RB_WPTR2, ring->wptr);
124 WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
125 WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
126 WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
127
128 WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK);
129
130 WREG32_P(mmVCE_SOFT_RESET,
131 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
132 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
133
134 mdelay(100);
135
136 WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
137
138 for (i = 0; i < 10; ++i) {
139 uint32_t status;
140 for (j = 0; j < 100; ++j) {
141 status = RREG32(mmVCE_STATUS);
142 if (status & 2)
143 break;
144 mdelay(10);
145 }
146 r = 0;
147 if (status & 2)
148 break;
149
150 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
151 WREG32_P(mmVCE_SOFT_RESET, VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
152 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
153 mdelay(10);
154 WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
155 mdelay(10);
156 r = -1;
157 }
158
159 /* clear BUSY flag */
160 WREG32_P(mmVCE_STATUS, 0, ~1);
161
162 if (r) {
163 DRM_ERROR("VCE not responding, giving up!!!\n");
164 return r;
165 }
166
167 return 0;
168}
169
170static int vce_v3_0_early_init(struct amdgpu_device *adev)
171{
172 vce_v3_0_set_ring_funcs(adev);
173 vce_v3_0_set_irq_funcs(adev);
174
175 return 0;
176}
177
178static int vce_v3_0_sw_init(struct amdgpu_device *adev)
179{
180 struct amdgpu_ring *ring;
181 int r;
182
183 /* VCE */
184 r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
185 if (r)
186 return r;
187
e9822622
LL
188 r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
189 (VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
aaa36a97
AD
190 if (r)
191 return r;
192
193 r = amdgpu_vce_resume(adev);
194 if (r)
195 return r;
196
197 ring = &adev->vce.ring[0];
198 sprintf(ring->name, "vce0");
199 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
200 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
201 if (r)
202 return r;
203
204 ring = &adev->vce.ring[1];
205 sprintf(ring->name, "vce1");
206 r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
207 &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
208 if (r)
209 return r;
210
211 return r;
212}
213
214static int vce_v3_0_sw_fini(struct amdgpu_device *adev)
215{
216 int r;
217
218 r = amdgpu_vce_suspend(adev);
219 if (r)
220 return r;
221
222 r = amdgpu_vce_sw_fini(adev);
223 if (r)
224 return r;
225
226 return r;
227}
228
229static int vce_v3_0_hw_init(struct amdgpu_device *adev)
230{
231 struct amdgpu_ring *ring;
232 int r;
233
234 r = vce_v3_0_start(adev);
235 if (r)
236 return r;
237
238 ring = &adev->vce.ring[0];
239 ring->ready = true;
240 r = amdgpu_ring_test_ring(ring);
241 if (r) {
242 ring->ready = false;
243 return r;
244 }
245
246 ring = &adev->vce.ring[1];
247 ring->ready = true;
248 r = amdgpu_ring_test_ring(ring);
249 if (r) {
250 ring->ready = false;
251 return r;
252 }
253
254 DRM_INFO("VCE initialized successfully.\n");
255
256 return 0;
257}
258
259static int vce_v3_0_hw_fini(struct amdgpu_device *adev)
260{
261 // TODO
262 return 0;
263}
264
265static int vce_v3_0_suspend(struct amdgpu_device *adev)
266{
267 int r;
268
269 r = vce_v3_0_hw_fini(adev);
270 if (r)
271 return r;
272
273 r = amdgpu_vce_suspend(adev);
274 if (r)
275 return r;
276
277 return r;
278}
279
280static int vce_v3_0_resume(struct amdgpu_device *adev)
281{
282 int r;
283
284 r = amdgpu_vce_resume(adev);
285 if (r)
286 return r;
287
288 r = vce_v3_0_hw_init(adev);
289 if (r)
290 return r;
291
292 return r;
293}
294
295static void vce_v3_0_mc_resume(struct amdgpu_device *adev)
296{
297 uint32_t offset, size;
298
299 WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
300 WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
301 WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
302 WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
303
304 WREG32(mmVCE_LMI_CTRL, 0x00398000);
305 WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
306 WREG32(mmVCE_LMI_SWAP_CNTL, 0);
307 WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
308 WREG32(mmVCE_LMI_VM_CTRL, 0);
309
310 WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
311 offset = AMDGPU_VCE_FIRMWARE_OFFSET;
e9822622 312 size = VCE_V3_0_FW_SIZE;
aaa36a97
AD
313 WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
314 WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
315
316 offset += size;
e9822622 317 size = VCE_V3_0_STACK_SIZE;
aaa36a97
AD
318 WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
319 WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
320
321 offset += size;
e9822622 322 size = VCE_V3_0_DATA_SIZE;
aaa36a97
AD
323 WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
324 WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
325
326 WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
327
328 WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
329 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
330}
331
332static bool vce_v3_0_is_idle(struct amdgpu_device *adev)
333{
334 return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
335}
336
337static int vce_v3_0_wait_for_idle(struct amdgpu_device *adev)
338{
339 unsigned i;
340
341 for (i = 0; i < adev->usec_timeout; i++) {
342 if (!(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK))
343 return 0;
344 }
345 return -ETIMEDOUT;
346}
347
348static int vce_v3_0_soft_reset(struct amdgpu_device *adev)
349{
350 WREG32_P(mmSRBM_SOFT_RESET, SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK,
351 ~SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK);
352 mdelay(5);
353
354 return vce_v3_0_start(adev);
355}
356
357static void vce_v3_0_print_status(struct amdgpu_device *adev)
358{
359 dev_info(adev->dev, "VCE 3.0 registers\n");
360 dev_info(adev->dev, " VCE_STATUS=0x%08X\n",
361 RREG32(mmVCE_STATUS));
362 dev_info(adev->dev, " VCE_VCPU_CNTL=0x%08X\n",
363 RREG32(mmVCE_VCPU_CNTL));
364 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
365 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
366 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE0=0x%08X\n",
367 RREG32(mmVCE_VCPU_CACHE_SIZE0));
368 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
369 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
370 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE1=0x%08X\n",
371 RREG32(mmVCE_VCPU_CACHE_SIZE1));
372 dev_info(adev->dev, " VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
373 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
374 dev_info(adev->dev, " VCE_VCPU_CACHE_SIZE2=0x%08X\n",
375 RREG32(mmVCE_VCPU_CACHE_SIZE2));
376 dev_info(adev->dev, " VCE_SOFT_RESET=0x%08X\n",
377 RREG32(mmVCE_SOFT_RESET));
378 dev_info(adev->dev, " VCE_RB_BASE_LO2=0x%08X\n",
379 RREG32(mmVCE_RB_BASE_LO2));
380 dev_info(adev->dev, " VCE_RB_BASE_HI2=0x%08X\n",
381 RREG32(mmVCE_RB_BASE_HI2));
382 dev_info(adev->dev, " VCE_RB_SIZE2=0x%08X\n",
383 RREG32(mmVCE_RB_SIZE2));
384 dev_info(adev->dev, " VCE_RB_RPTR2=0x%08X\n",
385 RREG32(mmVCE_RB_RPTR2));
386 dev_info(adev->dev, " VCE_RB_WPTR2=0x%08X\n",
387 RREG32(mmVCE_RB_WPTR2));
388 dev_info(adev->dev, " VCE_RB_BASE_LO=0x%08X\n",
389 RREG32(mmVCE_RB_BASE_LO));
390 dev_info(adev->dev, " VCE_RB_BASE_HI=0x%08X\n",
391 RREG32(mmVCE_RB_BASE_HI));
392 dev_info(adev->dev, " VCE_RB_SIZE=0x%08X\n",
393 RREG32(mmVCE_RB_SIZE));
394 dev_info(adev->dev, " VCE_RB_RPTR=0x%08X\n",
395 RREG32(mmVCE_RB_RPTR));
396 dev_info(adev->dev, " VCE_RB_WPTR=0x%08X\n",
397 RREG32(mmVCE_RB_WPTR));
398 dev_info(adev->dev, " VCE_CLOCK_GATING_A=0x%08X\n",
399 RREG32(mmVCE_CLOCK_GATING_A));
400 dev_info(adev->dev, " VCE_CLOCK_GATING_B=0x%08X\n",
401 RREG32(mmVCE_CLOCK_GATING_B));
402 dev_info(adev->dev, " VCE_UENC_CLOCK_GATING=0x%08X\n",
403 RREG32(mmVCE_UENC_CLOCK_GATING));
404 dev_info(adev->dev, " VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
405 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
406 dev_info(adev->dev, " VCE_SYS_INT_EN=0x%08X\n",
407 RREG32(mmVCE_SYS_INT_EN));
408 dev_info(adev->dev, " VCE_LMI_CTRL2=0x%08X\n",
409 RREG32(mmVCE_LMI_CTRL2));
410 dev_info(adev->dev, " VCE_LMI_CTRL=0x%08X\n",
411 RREG32(mmVCE_LMI_CTRL));
412 dev_info(adev->dev, " VCE_LMI_VM_CTRL=0x%08X\n",
413 RREG32(mmVCE_LMI_VM_CTRL));
414 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL=0x%08X\n",
415 RREG32(mmVCE_LMI_SWAP_CNTL));
416 dev_info(adev->dev, " VCE_LMI_SWAP_CNTL1=0x%08X\n",
417 RREG32(mmVCE_LMI_SWAP_CNTL1));
418 dev_info(adev->dev, " VCE_LMI_CACHE_CTRL=0x%08X\n",
419 RREG32(mmVCE_LMI_CACHE_CTRL));
420}
421
422static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
423 struct amdgpu_irq_src *source,
424 unsigned type,
425 enum amdgpu_interrupt_state state)
426{
427 uint32_t val = 0;
428
429 if (state == AMDGPU_IRQ_STATE_ENABLE)
430 val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
431
432 WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
433 return 0;
434}
435
436static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
437 struct amdgpu_irq_src *source,
438 struct amdgpu_iv_entry *entry)
439{
440 DRM_DEBUG("IH: VCE\n");
441 switch (entry->src_data) {
442 case 0:
443 amdgpu_fence_process(&adev->vce.ring[0]);
444 break;
445 case 1:
446 amdgpu_fence_process(&adev->vce.ring[1]);
447 break;
448 default:
449 DRM_ERROR("Unhandled interrupt: %d %d\n",
450 entry->src_id, entry->src_data);
451 break;
452 }
453
454 return 0;
455}
456
457static int vce_v3_0_set_clockgating_state(struct amdgpu_device *adev,
458 enum amdgpu_clockgating_state state)
459{
460 //TODO
461 return 0;
462}
463
464static int vce_v3_0_set_powergating_state(struct amdgpu_device *adev,
465 enum amdgpu_powergating_state state)
466{
467 /* This doesn't actually powergate the VCE block.
468 * That's done in the dpm code via the SMC. This
469 * just re-inits the block as necessary. The actual
470 * gating still happens in the dpm code. We should
471 * revisit this when there is a cleaner line between
472 * the smc and the hw blocks
473 */
474 if (state == AMDGPU_PG_STATE_GATE)
475 /* XXX do we need a vce_v3_0_stop()? */
476 return 0;
477 else
478 return vce_v3_0_start(adev);
479}
480
481const struct amdgpu_ip_funcs vce_v3_0_ip_funcs = {
482 .early_init = vce_v3_0_early_init,
483 .late_init = NULL,
484 .sw_init = vce_v3_0_sw_init,
485 .sw_fini = vce_v3_0_sw_fini,
486 .hw_init = vce_v3_0_hw_init,
487 .hw_fini = vce_v3_0_hw_fini,
488 .suspend = vce_v3_0_suspend,
489 .resume = vce_v3_0_resume,
490 .is_idle = vce_v3_0_is_idle,
491 .wait_for_idle = vce_v3_0_wait_for_idle,
492 .soft_reset = vce_v3_0_soft_reset,
493 .print_status = vce_v3_0_print_status,
494 .set_clockgating_state = vce_v3_0_set_clockgating_state,
495 .set_powergating_state = vce_v3_0_set_powergating_state,
496};
497
498static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
499 .get_rptr = vce_v3_0_ring_get_rptr,
500 .get_wptr = vce_v3_0_ring_get_wptr,
501 .set_wptr = vce_v3_0_ring_set_wptr,
502 .parse_cs = amdgpu_vce_ring_parse_cs,
503 .emit_ib = amdgpu_vce_ring_emit_ib,
504 .emit_fence = amdgpu_vce_ring_emit_fence,
505 .emit_semaphore = amdgpu_vce_ring_emit_semaphore,
506 .test_ring = amdgpu_vce_ring_test_ring,
507 .test_ib = amdgpu_vce_ring_test_ib,
508 .is_lockup = amdgpu_ring_test_lockup,
509};
510
511static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
512{
513 adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
514 adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
515}
516
517static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
518 .set = vce_v3_0_set_interrupt_state,
519 .process = vce_v3_0_process_interrupt,
520};
521
522static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
523{
524 adev->vce.irq.num_types = 1;
525 adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
526};