2
* Copyright 2008 Advanced Micro Devices, Inc.
3
* Copyright 2008 Red Hat Inc.
4
* Copyright 2009 Jerome Glisse.
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:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
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.
24
* Authors: Dave Airlie
30
#include "radeon_drm.h"
31
#include "radeon_reg.h"
33
#include "radeon_asic.h"
36
#include "r200_reg_safe.h"
38
#include "r100_track.h"
40
static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
45
if (vtx_fmt_0 & R200_VTX_Z0)
47
if (vtx_fmt_0 & R200_VTX_W0)
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)
54
if (vtx_fmt_0 & R200_VTX_N0)
56
if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
58
if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
60
if (vtx_fmt_0 & R200_VTX_SHININESS_0)
62
if (vtx_fmt_0 & R200_VTX_SHININESS_1)
64
for (i = 0; i < 8; i++) {
65
int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
68
case 1: vtx_size++; break;
69
case 2: vtx_size += 3; break;
70
case 3: vtx_size += 4; break;
73
if (vtx_fmt_0 & R200_VTX_XY1)
75
if (vtx_fmt_0 & R200_VTX_Z1)
77
if (vtx_fmt_0 & R200_VTX_W1)
79
if (vtx_fmt_0 & R200_VTX_N1)
84
int r200_copy_dma(struct radeon_device *rdev,
87
unsigned num_gpu_pages,
88
struct radeon_fence *fence)
95
/* radeon pitch is /64 */
96
size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
97
num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
98
r = radeon_ring_lock(rdev, num_loops * 4 + 64);
100
DRM_ERROR("radeon: moving bo (%d).\n", r);
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++) {
108
if (cur_size > 0x1FFFFF) {
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;
119
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
120
radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
122
r = radeon_fence_emit(rdev, fence);
124
radeon_ring_unlock_commit(rdev);
129
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
131
int vtx_size, i, tex_size;
133
for (i = 0; i < 6; i++) {
134
tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
137
vtx_size += tex_size;
142
int r200_packet0_check(struct radeon_cs_parser *p,
143
struct radeon_cs_packet *pkt,
144
unsigned idx, unsigned reg)
146
struct radeon_cs_reloc *reloc;
147
struct r100_cs_track *track;
148
volatile uint32_t *ib;
157
track = (struct r100_cs_track *)p->track;
158
idx_value = radeon_get_ib_value(p, idx);
160
case RADEON_CRTC_GUI_TRIG_VLINE:
161
r = r100_cs_packet_parse_vline(p);
163
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
165
r100_cs_dump_packet(p, pkt);
169
/* FIXME: only allow PACKET3 blit? easier to check for out of
171
case RADEON_DST_PITCH_OFFSET:
172
case RADEON_SRC_PITCH_OFFSET:
173
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
177
case RADEON_RB3D_DEPTHOFFSET:
178
r = r100_cs_packet_next_reloc(p, &reloc);
180
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
182
r100_cs_dump_packet(p, pkt);
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);
190
case RADEON_RB3D_COLOROFFSET:
191
r = r100_cs_packet_next_reloc(p, &reloc);
193
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
195
r100_cs_dump_packet(p, pkt);
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);
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);
212
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
214
r100_cs_dump_packet(p, pkt);
217
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
218
track->textures[i].robj = reloc->robj;
219
track->tex_dirty = true;
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);
255
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
257
r100_cs_dump_packet(p, pkt);
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;
265
case RADEON_RE_WIDTH_HEIGHT:
266
track->maxy = ((idx_value >> 16) & 0x7FF);
267
track->cb_dirty = true;
268
track->zb_dirty = true;
270
case RADEON_RB3D_COLORPITCH:
271
r = r100_cs_packet_next_reloc(p, &reloc);
273
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
275
r100_cs_dump_packet(p, pkt);
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;
284
tmp = idx_value & ~(0x7 << 16);
288
track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
289
track->cb_dirty = true;
291
case RADEON_RB3D_DEPTHPITCH:
292
track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
293
track->zb_dirty = true;
295
case RADEON_RB3D_CNTL:
296
switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
302
track->cb[0].cpp = 1;
307
track->cb[0].cpp = 2;
310
track->cb[0].cpp = 4;
313
DRM_ERROR("Invalid color buffer format (%d) !\n",
314
((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
317
if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
318
DRM_ERROR("No support for depth xy offset in kms\n");
322
track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
323
track->cb_dirty = true;
324
track->zb_dirty = true;
326
case RADEON_RB3D_ZSTENCILCNTL:
327
switch (idx_value & 0xf) {
342
track->zb_dirty = true;
344
case RADEON_RB3D_ZPASS_ADDR:
345
r = r100_cs_packet_next_reloc(p, &reloc);
347
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
349
r100_cs_dump_packet(p, pkt);
352
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
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;
362
case RADEON_SE_VF_CNTL:
363
track->vap_vf_cntl = idx_value;
366
/* VAP_VF_MAX_VTX_INDX */
367
track->max_indx = idx_value & 0x00FFFFFFUL;
369
case R200_SE_VTX_FMT_0:
370
track->vtx_size = r200_get_vtx_size_0(idx_value);
372
case R200_SE_VTX_FMT_1:
373
track->vtx_size += r200_get_vtx_size_1(idx_value);
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;
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;
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;
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;
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;
439
track->textures[i].tex_coord_type = 0;
443
track->textures[i].tex_coord_type = 2;
447
track->textures[i].tex_coord_type = 1;
450
track->tex_dirty = true;
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;
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);
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;
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;
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;
495
case R200_TXFORMAT_DXT1:
496
track->textures[i].cpp = 1;
497
track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
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;
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;
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:
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);
521
track->tex_dirty = true;
524
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
531
void r200_set_safe_registers(struct radeon_device *rdev)
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);