xref: /dragonfly/sys/dev/drm/radeon/uvd_v1_0.c (revision c6f73aab)
1 /*
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Christian König <christian.koenig@amd.com>
23  */
24 
25 #include <drm/drmP.h>
26 #include "radeon.h"
27 #include "radeon_asic.h"
28 #include "r600d.h"
29 
30 /**
31  * uvd_v1_0_get_rptr - get read pointer
32  *
33  * @rdev: radeon_device pointer
34  * @ring: radeon_ring pointer
35  *
36  * Returns the current hardware read pointer
37  */
38 uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
39 			   struct radeon_ring *ring)
40 {
41 	return RREG32(UVD_RBC_RB_RPTR);
42 }
43 
44 /**
45  * uvd_v1_0_get_wptr - get write pointer
46  *
47  * @rdev: radeon_device pointer
48  * @ring: radeon_ring pointer
49  *
50  * Returns the current hardware write pointer
51  */
52 uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
53 			   struct radeon_ring *ring)
54 {
55 	return RREG32(UVD_RBC_RB_WPTR);
56 }
57 
58 /**
59  * uvd_v1_0_set_wptr - set write pointer
60  *
61  * @rdev: radeon_device pointer
62  * @ring: radeon_ring pointer
63  *
64  * Commits the write pointer to the hardware
65  */
66 void uvd_v1_0_set_wptr(struct radeon_device *rdev,
67 		       struct radeon_ring *ring)
68 {
69 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
70 }
71 
72 /**
73  * uvd_v1_0_init - start and test UVD block
74  *
75  * @rdev: radeon_device pointer
76  *
77  * Initialize the hardware, boot up the VCPU and do some testing
78  */
79 int uvd_v1_0_init(struct radeon_device *rdev)
80 {
81 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
82 	uint32_t tmp;
83 	int r;
84 
85 	/* raise clocks while booting up the VCPU */
86 	if (rdev->family < CHIP_RV740)
87 		radeon_set_uvd_clocks(rdev, 10000, 10000);
88 	else
89 		radeon_set_uvd_clocks(rdev, 53300, 40000);
90 
91 	r = uvd_v1_0_start(rdev);
92 	if (r)
93 		goto done;
94 
95 	ring->ready = true;
96 	r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
97 	if (r) {
98 		ring->ready = false;
99 		goto done;
100 	}
101 
102 	r = radeon_ring_lock(rdev, ring, 10);
103 	if (r) {
104 		DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
105 		goto done;
106 	}
107 
108 	tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
109 	radeon_ring_write(ring, tmp);
110 	radeon_ring_write(ring, 0xFFFFF);
111 
112 	tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
113 	radeon_ring_write(ring, tmp);
114 	radeon_ring_write(ring, 0xFFFFF);
115 
116 	tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
117 	radeon_ring_write(ring, tmp);
118 	radeon_ring_write(ring, 0xFFFFF);
119 
120 	/* Clear timeout status bits */
121 	radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
122 	radeon_ring_write(ring, 0x8);
123 
124 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
125 	radeon_ring_write(ring, 3);
126 
127 	radeon_ring_unlock_commit(rdev, ring, false);
128 
129 done:
130 	/* lower clocks again */
131 	radeon_set_uvd_clocks(rdev, 0, 0);
132 
133 	if (!r)
134 		DRM_INFO("UVD initialized successfully.\n");
135 
136 	return r;
137 }
138 
139 /**
140  * uvd_v1_0_fini - stop the hardware block
141  *
142  * @rdev: radeon_device pointer
143  *
144  * Stop the UVD block, mark ring as not ready any more
145  */
146 void uvd_v1_0_fini(struct radeon_device *rdev)
147 {
148 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
149 
150 	uvd_v1_0_stop(rdev);
151 	ring->ready = false;
152 }
153 
154 /**
155  * uvd_v1_0_start - start UVD block
156  *
157  * @rdev: radeon_device pointer
158  *
159  * Setup and start the UVD block
160  */
161 int uvd_v1_0_start(struct radeon_device *rdev)
162 {
163 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
164 	uint32_t rb_bufsz;
165 	int i, j, r;
166 
167 	/* disable byte swapping */
168 	u32 lmi_swap_cntl = 0;
169 	u32 mp_swap_cntl = 0;
170 
171 	/* disable clock gating */
172 	WREG32(UVD_CGC_GATE, 0);
173 
174 	/* disable interupt */
175 	WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
176 
177 	/* Stall UMC and register bus before resetting VCPU */
178 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
179 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
180 	mdelay(1);
181 
182 	/* put LMI, VCPU, RBC etc... into reset */
183 	WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
184 	       LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
185 	       CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
186 	mdelay(5);
187 
188 	/* take UVD block out of reset */
189 	WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
190 	mdelay(5);
191 
192 	/* initialize UVD memory controller */
193 	WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
194 			     (1 << 21) | (1 << 9) | (1 << 20));
195 
196 #ifdef __BIG_ENDIAN
197 	/* swap (8 in 32) RB and IB */
198 	lmi_swap_cntl = 0xa;
199 	mp_swap_cntl = 0;
200 #endif
201 	WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl);
202 	WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl);
203 
204 	WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
205 	WREG32(UVD_MPC_SET_MUXA1, 0x0);
206 	WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
207 	WREG32(UVD_MPC_SET_MUXB1, 0x0);
208 	WREG32(UVD_MPC_SET_ALU, 0);
209 	WREG32(UVD_MPC_SET_MUX, 0x88);
210 
211 	/* take all subblocks out of reset, except VCPU */
212 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
213 	mdelay(5);
214 
215 	/* enable VCPU clock */
216 	WREG32(UVD_VCPU_CNTL,  1 << 9);
217 
218 	/* enable UMC */
219 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
220 
221 	/* boot up the VCPU */
222 	WREG32(UVD_SOFT_RESET, 0);
223 	mdelay(10);
224 
225 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
226 
227 	for (i = 0; i < 10; ++i) {
228 		uint32_t status;
229 		for (j = 0; j < 100; ++j) {
230 			status = RREG32(UVD_STATUS);
231 			if (status & 2)
232 				break;
233 			mdelay(10);
234 		}
235 		r = 0;
236 		if (status & 2)
237 			break;
238 
239 		DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
240 		WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
241 		mdelay(10);
242 		WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
243 		mdelay(10);
244 		r = -1;
245 	}
246 
247 	if (r) {
248 		DRM_ERROR("UVD not responding, giving up!!!\n");
249 		return r;
250 	}
251 
252 	/* enable interupt */
253 	WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
254 
255 	/* force RBC into idle state */
256 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
257 
258 	/* Set the write pointer delay */
259 	WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
260 
261 	/* programm the 4GB memory segment for rptr and ring buffer */
262 	WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
263 				   (0x7 << 16) | (0x1 << 31));
264 
265 	/* Initialize the ring buffer's read and write pointers */
266 	WREG32(UVD_RBC_RB_RPTR, 0x0);
267 
268 	ring->wptr = RREG32(UVD_RBC_RB_RPTR);
269 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
270 
271 	/* set the ring address */
272 	WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
273 
274 	/* Set ring buffer size */
275 	rb_bufsz = order_base_2(ring->ring_size);
276 	rb_bufsz = (0x1 << 8) | rb_bufsz;
277 	WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
278 
279 	return 0;
280 }
281 
282 /**
283  * uvd_v1_0_stop - stop UVD block
284  *
285  * @rdev: radeon_device pointer
286  *
287  * stop the UVD block
288  */
289 void uvd_v1_0_stop(struct radeon_device *rdev)
290 {
291 	/* force RBC into idle state */
292 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
293 
294 	/* Stall UMC and register bus before resetting VCPU */
295 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
296 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
297 	mdelay(1);
298 
299 	/* put VCPU into reset */
300 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
301 	mdelay(5);
302 
303 	/* disable VCPU clock */
304 	WREG32(UVD_VCPU_CNTL, 0x0);
305 
306 	/* Unstall UMC and register bus */
307 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
308 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
309 }
310 
311 /**
312  * uvd_v1_0_ring_test - register write test
313  *
314  * @rdev: radeon_device pointer
315  * @ring: radeon_ring pointer
316  *
317  * Test if we can successfully write to the context register
318  */
319 int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
320 {
321 	uint32_t tmp = 0;
322 	unsigned i;
323 	int r;
324 
325 	WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
326 	r = radeon_ring_lock(rdev, ring, 3);
327 	if (r) {
328 		DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
329 			  ring->idx, r);
330 		return r;
331 	}
332 	radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
333 	radeon_ring_write(ring, 0xDEADBEEF);
334 	radeon_ring_unlock_commit(rdev, ring, false);
335 	for (i = 0; i < rdev->usec_timeout; i++) {
336 		tmp = RREG32(UVD_CONTEXT_ID);
337 		if (tmp == 0xDEADBEEF)
338 			break;
339 		DRM_UDELAY(1);
340 	}
341 
342 	if (i < rdev->usec_timeout) {
343 		DRM_INFO("ring test on %d succeeded in %d usecs\n",
344 			 ring->idx, i);
345 	} else {
346 		DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
347 			  ring->idx, tmp);
348 		r = -EINVAL;
349 	}
350 	return r;
351 }
352 
353 /**
354  * uvd_v1_0_semaphore_emit - emit semaphore command
355  *
356  * @rdev: radeon_device pointer
357  * @ring: radeon_ring pointer
358  * @semaphore: semaphore to emit commands for
359  * @emit_wait: true if we should emit a wait command
360  *
361  * Emit a semaphore command (either wait or signal) to the UVD ring.
362  */
363 bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
364 			     struct radeon_ring *ring,
365 			     struct radeon_semaphore *semaphore,
366 			     bool emit_wait)
367 {
368 	uint64_t addr = semaphore->gpu_addr;
369 
370 	radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
371 	radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
372 
373 	radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
374 	radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
375 
376 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
377 	radeon_ring_write(ring, emit_wait ? 1 : 0);
378 
379 	return true;
380 }
381 
382 /**
383  * uvd_v1_0_ib_execute - execute indirect buffer
384  *
385  * @rdev: radeon_device pointer
386  * @ib: indirect buffer to execute
387  *
388  * Write ring commands to execute the indirect buffer
389  */
390 void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
391 {
392 	struct radeon_ring *ring = &rdev->ring[ib->ring];
393 
394 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
395 	radeon_ring_write(ring, ib->gpu_addr);
396 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
397 	radeon_ring_write(ring, ib->length_dw);
398 }
399 
400 /**
401  * uvd_v1_0_ib_test - test ib execution
402  *
403  * @rdev: radeon_device pointer
404  * @ring: radeon_ring pointer
405  *
406  * Test if we can successfully execute an IB
407  */
408 int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
409 {
410 	struct radeon_fence *fence = NULL;
411 	int r;
412 
413 	if (rdev->family < CHIP_RV740)
414 		r = radeon_set_uvd_clocks(rdev, 10000, 10000);
415 	else
416 		r = radeon_set_uvd_clocks(rdev, 53300, 40000);
417 	if (r) {
418 		DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
419 		return r;
420 	}
421 
422 	r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
423 	if (r) {
424 		DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
425 		goto error;
426 	}
427 
428 	r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
429 	if (r) {
430 		DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
431 		goto error;
432 	}
433 
434 	r = radeon_fence_wait(fence, false);
435 	if (r) {
436 		DRM_ERROR("radeon: fence wait failed (%d).\n", r);
437 		goto error;
438 	}
439 	DRM_INFO("ib test on ring %d succeeded\n",  ring->idx);
440 error:
441 	radeon_fence_unref(&fence);
442 	radeon_set_uvd_clocks(rdev, 0, 0);
443 	return r;
444 }
445