Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/gpu/drm/radeon/r200.c
15112 views
1
/*
2
* Copyright 2008 Advanced Micro Devices, Inc.
3
* Copyright 2008 Red Hat Inc.
4
* Copyright 2009 Jerome Glisse.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
12
*
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
* OTHER DEALINGS IN THE SOFTWARE.
23
*
24
* Authors: Dave Airlie
25
* Alex Deucher
26
* Jerome Glisse
27
*/
28
#include "drmP.h"
29
#include "drm.h"
30
#include "radeon_drm.h"
31
#include "radeon_reg.h"
32
#include "radeon.h"
33
#include "radeon_asic.h"
34
35
#include "r100d.h"
36
#include "r200_reg_safe.h"
37
38
#include "r100_track.h"
39
40
static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
41
{
42
int vtx_size, i;
43
vtx_size = 2;
44
45
if (vtx_fmt_0 & R200_VTX_Z0)
46
vtx_size++;
47
if (vtx_fmt_0 & R200_VTX_W0)
48
vtx_size++;
49
/* blend weight */
50
if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
51
vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
52
if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
53
vtx_size++;
54
if (vtx_fmt_0 & R200_VTX_N0)
55
vtx_size += 3;
56
if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
57
vtx_size++;
58
if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
59
vtx_size++;
60
if (vtx_fmt_0 & R200_VTX_SHININESS_0)
61
vtx_size++;
62
if (vtx_fmt_0 & R200_VTX_SHININESS_1)
63
vtx_size++;
64
for (i = 0; i < 8; i++) {
65
int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
66
switch (color_size) {
67
case 0: break;
68
case 1: vtx_size++; break;
69
case 2: vtx_size += 3; break;
70
case 3: vtx_size += 4; break;
71
}
72
}
73
if (vtx_fmt_0 & R200_VTX_XY1)
74
vtx_size += 2;
75
if (vtx_fmt_0 & R200_VTX_Z1)
76
vtx_size++;
77
if (vtx_fmt_0 & R200_VTX_W1)
78
vtx_size++;
79
if (vtx_fmt_0 & R200_VTX_N1)
80
vtx_size += 3;
81
return vtx_size;
82
}
83
84
int r200_copy_dma(struct radeon_device *rdev,
85
uint64_t src_offset,
86
uint64_t dst_offset,
87
unsigned num_pages,
88
struct radeon_fence *fence)
89
{
90
uint32_t size;
91
uint32_t cur_size;
92
int i, num_loops;
93
int r = 0;
94
95
/* radeon pitch is /64 */
96
size = num_pages << PAGE_SHIFT;
97
num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
98
r = radeon_ring_lock(rdev, num_loops * 4 + 64);
99
if (r) {
100
DRM_ERROR("radeon: moving bo (%d).\n", r);
101
return r;
102
}
103
/* Must wait for 2D idle & clean before DMA or hangs might happen */
104
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
105
radeon_ring_write(rdev, (1 << 16));
106
for (i = 0; i < num_loops; i++) {
107
cur_size = size;
108
if (cur_size > 0x1FFFFF) {
109
cur_size = 0x1FFFFF;
110
}
111
size -= cur_size;
112
radeon_ring_write(rdev, PACKET0(0x720, 2));
113
radeon_ring_write(rdev, src_offset);
114
radeon_ring_write(rdev, dst_offset);
115
radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
116
src_offset += cur_size;
117
dst_offset += cur_size;
118
}
119
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
120
radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
121
if (fence) {
122
r = radeon_fence_emit(rdev, fence);
123
}
124
radeon_ring_unlock_commit(rdev);
125
return r;
126
}
127
128
129
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
130
{
131
int vtx_size, i, tex_size;
132
vtx_size = 0;
133
for (i = 0; i < 6; i++) {
134
tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
135
if (tex_size > 4)
136
continue;
137
vtx_size += tex_size;
138
}
139
return vtx_size;
140
}
141
142
int r200_packet0_check(struct radeon_cs_parser *p,
143
struct radeon_cs_packet *pkt,
144
unsigned idx, unsigned reg)
145
{
146
struct radeon_cs_reloc *reloc;
147
struct r100_cs_track *track;
148
volatile uint32_t *ib;
149
uint32_t tmp;
150
int r;
151
int i;
152
int face;
153
u32 tile_flags = 0;
154
u32 idx_value;
155
156
ib = p->ib->ptr;
157
track = (struct r100_cs_track *)p->track;
158
idx_value = radeon_get_ib_value(p, idx);
159
switch (reg) {
160
case RADEON_CRTC_GUI_TRIG_VLINE:
161
r = r100_cs_packet_parse_vline(p);
162
if (r) {
163
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
164
idx, reg);
165
r100_cs_dump_packet(p, pkt);
166
return r;
167
}
168
break;
169
/* FIXME: only allow PACKET3 blit? easier to check for out of
170
* range access */
171
case RADEON_DST_PITCH_OFFSET:
172
case RADEON_SRC_PITCH_OFFSET:
173
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
174
if (r)
175
return r;
176
break;
177
case RADEON_RB3D_DEPTHOFFSET:
178
r = r100_cs_packet_next_reloc(p, &reloc);
179
if (r) {
180
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
181
idx, reg);
182
r100_cs_dump_packet(p, pkt);
183
return r;
184
}
185
track->zb.robj = reloc->robj;
186
track->zb.offset = idx_value;
187
track->zb_dirty = true;
188
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
189
break;
190
case RADEON_RB3D_COLOROFFSET:
191
r = r100_cs_packet_next_reloc(p, &reloc);
192
if (r) {
193
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
194
idx, reg);
195
r100_cs_dump_packet(p, pkt);
196
return r;
197
}
198
track->cb[0].robj = reloc->robj;
199
track->cb[0].offset = idx_value;
200
track->cb_dirty = true;
201
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
202
break;
203
case R200_PP_TXOFFSET_0:
204
case R200_PP_TXOFFSET_1:
205
case R200_PP_TXOFFSET_2:
206
case R200_PP_TXOFFSET_3:
207
case R200_PP_TXOFFSET_4:
208
case R200_PP_TXOFFSET_5:
209
i = (reg - R200_PP_TXOFFSET_0) / 24;
210
r = r100_cs_packet_next_reloc(p, &reloc);
211
if (r) {
212
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
213
idx, reg);
214
r100_cs_dump_packet(p, pkt);
215
return r;
216
}
217
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
218
track->textures[i].robj = reloc->robj;
219
track->tex_dirty = true;
220
break;
221
case R200_PP_CUBIC_OFFSET_F1_0:
222
case R200_PP_CUBIC_OFFSET_F2_0:
223
case R200_PP_CUBIC_OFFSET_F3_0:
224
case R200_PP_CUBIC_OFFSET_F4_0:
225
case R200_PP_CUBIC_OFFSET_F5_0:
226
case R200_PP_CUBIC_OFFSET_F1_1:
227
case R200_PP_CUBIC_OFFSET_F2_1:
228
case R200_PP_CUBIC_OFFSET_F3_1:
229
case R200_PP_CUBIC_OFFSET_F4_1:
230
case R200_PP_CUBIC_OFFSET_F5_1:
231
case R200_PP_CUBIC_OFFSET_F1_2:
232
case R200_PP_CUBIC_OFFSET_F2_2:
233
case R200_PP_CUBIC_OFFSET_F3_2:
234
case R200_PP_CUBIC_OFFSET_F4_2:
235
case R200_PP_CUBIC_OFFSET_F5_2:
236
case R200_PP_CUBIC_OFFSET_F1_3:
237
case R200_PP_CUBIC_OFFSET_F2_3:
238
case R200_PP_CUBIC_OFFSET_F3_3:
239
case R200_PP_CUBIC_OFFSET_F4_3:
240
case R200_PP_CUBIC_OFFSET_F5_3:
241
case R200_PP_CUBIC_OFFSET_F1_4:
242
case R200_PP_CUBIC_OFFSET_F2_4:
243
case R200_PP_CUBIC_OFFSET_F3_4:
244
case R200_PP_CUBIC_OFFSET_F4_4:
245
case R200_PP_CUBIC_OFFSET_F5_4:
246
case R200_PP_CUBIC_OFFSET_F1_5:
247
case R200_PP_CUBIC_OFFSET_F2_5:
248
case R200_PP_CUBIC_OFFSET_F3_5:
249
case R200_PP_CUBIC_OFFSET_F4_5:
250
case R200_PP_CUBIC_OFFSET_F5_5:
251
i = (reg - R200_PP_TXOFFSET_0) / 24;
252
face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
253
r = r100_cs_packet_next_reloc(p, &reloc);
254
if (r) {
255
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
256
idx, reg);
257
r100_cs_dump_packet(p, pkt);
258
return r;
259
}
260
track->textures[i].cube_info[face - 1].offset = idx_value;
261
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
262
track->textures[i].cube_info[face - 1].robj = reloc->robj;
263
track->tex_dirty = true;
264
break;
265
case RADEON_RE_WIDTH_HEIGHT:
266
track->maxy = ((idx_value >> 16) & 0x7FF);
267
track->cb_dirty = true;
268
track->zb_dirty = true;
269
break;
270
case RADEON_RB3D_COLORPITCH:
271
r = r100_cs_packet_next_reloc(p, &reloc);
272
if (r) {
273
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
274
idx, reg);
275
r100_cs_dump_packet(p, pkt);
276
return r;
277
}
278
279
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
280
tile_flags |= RADEON_COLOR_TILE_ENABLE;
281
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
282
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
283
284
tmp = idx_value & ~(0x7 << 16);
285
tmp |= tile_flags;
286
ib[idx] = tmp;
287
288
track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
289
track->cb_dirty = true;
290
break;
291
case RADEON_RB3D_DEPTHPITCH:
292
track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
293
track->zb_dirty = true;
294
break;
295
case RADEON_RB3D_CNTL:
296
switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
297
case 7:
298
case 8:
299
case 9:
300
case 11:
301
case 12:
302
track->cb[0].cpp = 1;
303
break;
304
case 3:
305
case 4:
306
case 15:
307
track->cb[0].cpp = 2;
308
break;
309
case 6:
310
track->cb[0].cpp = 4;
311
break;
312
default:
313
DRM_ERROR("Invalid color buffer format (%d) !\n",
314
((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
315
return -EINVAL;
316
}
317
if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
318
DRM_ERROR("No support for depth xy offset in kms\n");
319
return -EINVAL;
320
}
321
322
track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
323
track->cb_dirty = true;
324
track->zb_dirty = true;
325
break;
326
case RADEON_RB3D_ZSTENCILCNTL:
327
switch (idx_value & 0xf) {
328
case 0:
329
track->zb.cpp = 2;
330
break;
331
case 2:
332
case 3:
333
case 4:
334
case 5:
335
case 9:
336
case 11:
337
track->zb.cpp = 4;
338
break;
339
default:
340
break;
341
}
342
track->zb_dirty = true;
343
break;
344
case RADEON_RB3D_ZPASS_ADDR:
345
r = r100_cs_packet_next_reloc(p, &reloc);
346
if (r) {
347
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
348
idx, reg);
349
r100_cs_dump_packet(p, pkt);
350
return r;
351
}
352
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
353
break;
354
case RADEON_PP_CNTL:
355
{
356
uint32_t temp = idx_value >> 4;
357
for (i = 0; i < track->num_texture; i++)
358
track->textures[i].enabled = !!(temp & (1 << i));
359
track->tex_dirty = true;
360
}
361
break;
362
case RADEON_SE_VF_CNTL:
363
track->vap_vf_cntl = idx_value;
364
break;
365
case 0x210c:
366
/* VAP_VF_MAX_VTX_INDX */
367
track->max_indx = idx_value & 0x00FFFFFFUL;
368
break;
369
case R200_SE_VTX_FMT_0:
370
track->vtx_size = r200_get_vtx_size_0(idx_value);
371
break;
372
case R200_SE_VTX_FMT_1:
373
track->vtx_size += r200_get_vtx_size_1(idx_value);
374
break;
375
case R200_PP_TXSIZE_0:
376
case R200_PP_TXSIZE_1:
377
case R200_PP_TXSIZE_2:
378
case R200_PP_TXSIZE_3:
379
case R200_PP_TXSIZE_4:
380
case R200_PP_TXSIZE_5:
381
i = (reg - R200_PP_TXSIZE_0) / 32;
382
track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
383
track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
384
track->tex_dirty = true;
385
break;
386
case R200_PP_TXPITCH_0:
387
case R200_PP_TXPITCH_1:
388
case R200_PP_TXPITCH_2:
389
case R200_PP_TXPITCH_3:
390
case R200_PP_TXPITCH_4:
391
case R200_PP_TXPITCH_5:
392
i = (reg - R200_PP_TXPITCH_0) / 32;
393
track->textures[i].pitch = idx_value + 32;
394
track->tex_dirty = true;
395
break;
396
case R200_PP_TXFILTER_0:
397
case R200_PP_TXFILTER_1:
398
case R200_PP_TXFILTER_2:
399
case R200_PP_TXFILTER_3:
400
case R200_PP_TXFILTER_4:
401
case R200_PP_TXFILTER_5:
402
i = (reg - R200_PP_TXFILTER_0) / 32;
403
track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
404
>> R200_MAX_MIP_LEVEL_SHIFT);
405
tmp = (idx_value >> 23) & 0x7;
406
if (tmp == 2 || tmp == 6)
407
track->textures[i].roundup_w = false;
408
tmp = (idx_value >> 27) & 0x7;
409
if (tmp == 2 || tmp == 6)
410
track->textures[i].roundup_h = false;
411
track->tex_dirty = true;
412
break;
413
case R200_PP_TXMULTI_CTL_0:
414
case R200_PP_TXMULTI_CTL_1:
415
case R200_PP_TXMULTI_CTL_2:
416
case R200_PP_TXMULTI_CTL_3:
417
case R200_PP_TXMULTI_CTL_4:
418
case R200_PP_TXMULTI_CTL_5:
419
i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
420
break;
421
case R200_PP_TXFORMAT_X_0:
422
case R200_PP_TXFORMAT_X_1:
423
case R200_PP_TXFORMAT_X_2:
424
case R200_PP_TXFORMAT_X_3:
425
case R200_PP_TXFORMAT_X_4:
426
case R200_PP_TXFORMAT_X_5:
427
i = (reg - R200_PP_TXFORMAT_X_0) / 32;
428
track->textures[i].txdepth = idx_value & 0x7;
429
tmp = (idx_value >> 16) & 0x3;
430
/* 2D, 3D, CUBE */
431
switch (tmp) {
432
case 0:
433
case 3:
434
case 4:
435
case 5:
436
case 6:
437
case 7:
438
/* 1D/2D */
439
track->textures[i].tex_coord_type = 0;
440
break;
441
case 1:
442
/* CUBE */
443
track->textures[i].tex_coord_type = 2;
444
break;
445
case 2:
446
/* 3D */
447
track->textures[i].tex_coord_type = 1;
448
break;
449
}
450
track->tex_dirty = true;
451
break;
452
case R200_PP_TXFORMAT_0:
453
case R200_PP_TXFORMAT_1:
454
case R200_PP_TXFORMAT_2:
455
case R200_PP_TXFORMAT_3:
456
case R200_PP_TXFORMAT_4:
457
case R200_PP_TXFORMAT_5:
458
i = (reg - R200_PP_TXFORMAT_0) / 32;
459
if (idx_value & R200_TXFORMAT_NON_POWER2) {
460
track->textures[i].use_pitch = 1;
461
} else {
462
track->textures[i].use_pitch = 0;
463
track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
464
track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
465
}
466
if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
467
track->textures[i].lookup_disable = true;
468
switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
469
case R200_TXFORMAT_I8:
470
case R200_TXFORMAT_RGB332:
471
case R200_TXFORMAT_Y8:
472
track->textures[i].cpp = 1;
473
track->textures[i].compress_format = R100_TRACK_COMP_NONE;
474
break;
475
case R200_TXFORMAT_AI88:
476
case R200_TXFORMAT_ARGB1555:
477
case R200_TXFORMAT_RGB565:
478
case R200_TXFORMAT_ARGB4444:
479
case R200_TXFORMAT_VYUY422:
480
case R200_TXFORMAT_YVYU422:
481
case R200_TXFORMAT_LDVDU655:
482
case R200_TXFORMAT_DVDU88:
483
case R200_TXFORMAT_AVYU4444:
484
track->textures[i].cpp = 2;
485
track->textures[i].compress_format = R100_TRACK_COMP_NONE;
486
break;
487
case R200_TXFORMAT_ARGB8888:
488
case R200_TXFORMAT_RGBA8888:
489
case R200_TXFORMAT_ABGR8888:
490
case R200_TXFORMAT_BGR111110:
491
case R200_TXFORMAT_LDVDU8888:
492
track->textures[i].cpp = 4;
493
track->textures[i].compress_format = R100_TRACK_COMP_NONE;
494
break;
495
case R200_TXFORMAT_DXT1:
496
track->textures[i].cpp = 1;
497
track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
498
break;
499
case R200_TXFORMAT_DXT23:
500
case R200_TXFORMAT_DXT45:
501
track->textures[i].cpp = 1;
502
track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
503
break;
504
}
505
track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
506
track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
507
track->tex_dirty = true;
508
break;
509
case R200_PP_CUBIC_FACES_0:
510
case R200_PP_CUBIC_FACES_1:
511
case R200_PP_CUBIC_FACES_2:
512
case R200_PP_CUBIC_FACES_3:
513
case R200_PP_CUBIC_FACES_4:
514
case R200_PP_CUBIC_FACES_5:
515
tmp = idx_value;
516
i = (reg - R200_PP_CUBIC_FACES_0) / 32;
517
for (face = 0; face < 4; face++) {
518
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
519
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
520
}
521
track->tex_dirty = true;
522
break;
523
default:
524
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
525
reg, idx);
526
return -EINVAL;
527
}
528
return 0;
529
}
530
531
void r200_set_safe_registers(struct radeon_device *rdev)
532
{
533
rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
534
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
535
}
536
537