Subversion Repositories Kolibri OS

Rev

Rev 5271 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5078 serge 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 
23
 */
24
 
25
#include 
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
}