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"
34 #include "r200_reg_safe.h"
36 #include "r100_track.h"
38 static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
43 if (vtx_fmt_0 & R200_VTX_Z0)
45 if (vtx_fmt_0 & R200_VTX_W0)
48 if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
49 vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
50 if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
52 if (vtx_fmt_0 & R200_VTX_N0)
54 if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
56 if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
58 if (vtx_fmt_0 & R200_VTX_SHININESS_0)
60 if (vtx_fmt_0 & R200_VTX_SHININESS_1)
62 for (i = 0; i < 8; i++) {
63 int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
66 case 1: vtx_size++; break;
67 case 2: vtx_size += 3; break;
68 case 3: vtx_size += 4; break;
71 if (vtx_fmt_0 & R200_VTX_XY1)
73 if (vtx_fmt_0 & R200_VTX_Z1)
75 if (vtx_fmt_0 & R200_VTX_W1)
77 if (vtx_fmt_0 & R200_VTX_N1)
82 static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
84 int vtx_size, i, tex_size;
86 for (i = 0; i < 6; i++) {
87 tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
95 int r200_packet0_check(struct radeon_cs_parser *p,
96 struct radeon_cs_packet *pkt,
97 unsigned idx, unsigned reg)
99 struct radeon_cs_chunk *ib_chunk;
100 struct radeon_cs_reloc *reloc;
101 struct r100_cs_track *track;
102 volatile uint32_t *ib;
110 ib_chunk = &p->chunks[p->chunk_ib_idx];
111 track = (struct r100_cs_track *)p->track;
114 case RADEON_CRTC_GUI_TRIG_VLINE:
115 r = r100_cs_packet_parse_vline(p);
117 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
119 r100_cs_dump_packet(p, pkt);
123 /* FIXME: only allow PACKET3 blit? easier to check for out of
125 case RADEON_DST_PITCH_OFFSET:
126 case RADEON_SRC_PITCH_OFFSET:
127 r = r100_reloc_pitch_offset(p, pkt, idx, reg);
131 case RADEON_RB3D_DEPTHOFFSET:
132 r = r100_cs_packet_next_reloc(p, &reloc);
134 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
136 r100_cs_dump_packet(p, pkt);
139 track->zb.robj = reloc->robj;
140 track->zb.offset = ib_chunk->kdata[idx];
141 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
143 case RADEON_RB3D_COLOROFFSET:
144 r = r100_cs_packet_next_reloc(p, &reloc);
146 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
148 r100_cs_dump_packet(p, pkt);
151 track->cb[0].robj = reloc->robj;
152 track->cb[0].offset = ib_chunk->kdata[idx];
153 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
155 case R200_PP_TXOFFSET_0:
156 case R200_PP_TXOFFSET_1:
157 case R200_PP_TXOFFSET_2:
158 case R200_PP_TXOFFSET_3:
159 case R200_PP_TXOFFSET_4:
160 case R200_PP_TXOFFSET_5:
161 i = (reg - R200_PP_TXOFFSET_0) / 24;
162 r = r100_cs_packet_next_reloc(p, &reloc);
164 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
166 r100_cs_dump_packet(p, pkt);
169 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
170 track->textures[i].robj = reloc->robj;
172 case R200_PP_CUBIC_OFFSET_F1_0:
173 case R200_PP_CUBIC_OFFSET_F2_0:
174 case R200_PP_CUBIC_OFFSET_F3_0:
175 case R200_PP_CUBIC_OFFSET_F4_0:
176 case R200_PP_CUBIC_OFFSET_F5_0:
177 case R200_PP_CUBIC_OFFSET_F1_1:
178 case R200_PP_CUBIC_OFFSET_F2_1:
179 case R200_PP_CUBIC_OFFSET_F3_1:
180 case R200_PP_CUBIC_OFFSET_F4_1:
181 case R200_PP_CUBIC_OFFSET_F5_1:
182 case R200_PP_CUBIC_OFFSET_F1_2:
183 case R200_PP_CUBIC_OFFSET_F2_2:
184 case R200_PP_CUBIC_OFFSET_F3_2:
185 case R200_PP_CUBIC_OFFSET_F4_2:
186 case R200_PP_CUBIC_OFFSET_F5_2:
187 case R200_PP_CUBIC_OFFSET_F1_3:
188 case R200_PP_CUBIC_OFFSET_F2_3:
189 case R200_PP_CUBIC_OFFSET_F3_3:
190 case R200_PP_CUBIC_OFFSET_F4_3:
191 case R200_PP_CUBIC_OFFSET_F5_3:
192 case R200_PP_CUBIC_OFFSET_F1_4:
193 case R200_PP_CUBIC_OFFSET_F2_4:
194 case R200_PP_CUBIC_OFFSET_F3_4:
195 case R200_PP_CUBIC_OFFSET_F4_4:
196 case R200_PP_CUBIC_OFFSET_F5_4:
197 case R200_PP_CUBIC_OFFSET_F1_5:
198 case R200_PP_CUBIC_OFFSET_F2_5:
199 case R200_PP_CUBIC_OFFSET_F3_5:
200 case R200_PP_CUBIC_OFFSET_F4_5:
201 case R200_PP_CUBIC_OFFSET_F5_5:
202 i = (reg - R200_PP_TXOFFSET_0) / 24;
203 face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
204 r = r100_cs_packet_next_reloc(p, &reloc);
206 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
208 r100_cs_dump_packet(p, pkt);
211 track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx];
212 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
213 track->textures[i].cube_info[face - 1].robj = reloc->robj;
215 case RADEON_RE_WIDTH_HEIGHT:
216 track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
218 case RADEON_RB3D_COLORPITCH:
219 r = r100_cs_packet_next_reloc(p, &reloc);
221 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
223 r100_cs_dump_packet(p, pkt);
227 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
228 tile_flags |= RADEON_COLOR_TILE_ENABLE;
229 if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
230 tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
232 tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
236 track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
238 case RADEON_RB3D_DEPTHPITCH:
239 track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
241 case RADEON_RB3D_CNTL:
242 switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
248 track->cb[0].cpp = 1;
253 track->cb[0].cpp = 2;
256 track->cb[0].cpp = 4;
259 DRM_ERROR("Invalid color buffer format (%d) !\n",
260 ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
263 if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) {
264 DRM_ERROR("No support for depth xy offset in kms\n");
268 track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
270 case RADEON_RB3D_ZSTENCILCNTL:
271 switch (ib_chunk->kdata[idx] & 0xf) {
287 case RADEON_RB3D_ZPASS_ADDR:
288 r = r100_cs_packet_next_reloc(p, &reloc);
290 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
292 r100_cs_dump_packet(p, pkt);
295 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
299 uint32_t temp = ib_chunk->kdata[idx] >> 4;
300 for (i = 0; i < track->num_texture; i++)
301 track->textures[i].enabled = !!(temp & (1 << i));
304 case RADEON_SE_VF_CNTL:
305 track->vap_vf_cntl = ib_chunk->kdata[idx];
308 /* VAP_VF_MAX_VTX_INDX */
309 track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
311 case R200_SE_VTX_FMT_0:
312 track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]);
314 case R200_SE_VTX_FMT_1:
315 track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]);
317 case R200_PP_TXSIZE_0:
318 case R200_PP_TXSIZE_1:
319 case R200_PP_TXSIZE_2:
320 case R200_PP_TXSIZE_3:
321 case R200_PP_TXSIZE_4:
322 case R200_PP_TXSIZE_5:
323 i = (reg - R200_PP_TXSIZE_0) / 32;
324 track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
325 track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
327 case R200_PP_TXPITCH_0:
328 case R200_PP_TXPITCH_1:
329 case R200_PP_TXPITCH_2:
330 case R200_PP_TXPITCH_3:
331 case R200_PP_TXPITCH_4:
332 case R200_PP_TXPITCH_5:
333 i = (reg - R200_PP_TXPITCH_0) / 32;
334 track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
336 case R200_PP_TXFILTER_0:
337 case R200_PP_TXFILTER_1:
338 case R200_PP_TXFILTER_2:
339 case R200_PP_TXFILTER_3:
340 case R200_PP_TXFILTER_4:
341 case R200_PP_TXFILTER_5:
342 i = (reg - R200_PP_TXFILTER_0) / 32;
343 track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK)
344 >> R200_MAX_MIP_LEVEL_SHIFT);
345 tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
346 if (tmp == 2 || tmp == 6)
347 track->textures[i].roundup_w = false;
348 tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
349 if (tmp == 2 || tmp == 6)
350 track->textures[i].roundup_h = false;
352 case R200_PP_TXMULTI_CTL_0:
353 case R200_PP_TXMULTI_CTL_1:
354 case R200_PP_TXMULTI_CTL_2:
355 case R200_PP_TXMULTI_CTL_3:
356 case R200_PP_TXMULTI_CTL_4:
357 case R200_PP_TXMULTI_CTL_5:
358 i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
360 case R200_PP_TXFORMAT_X_0:
361 case R200_PP_TXFORMAT_X_1:
362 case R200_PP_TXFORMAT_X_2:
363 case R200_PP_TXFORMAT_X_3:
364 case R200_PP_TXFORMAT_X_4:
365 case R200_PP_TXFORMAT_X_5:
366 i = (reg - R200_PP_TXFORMAT_X_0) / 32;
367 track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7;
368 tmp = (ib_chunk->kdata[idx] >> 16) & 0x3;
375 track->textures[i].tex_coord_type = 0;
378 track->textures[i].tex_coord_type = 1;
381 track->textures[i].tex_coord_type = 2;
385 case R200_PP_TXFORMAT_0:
386 case R200_PP_TXFORMAT_1:
387 case R200_PP_TXFORMAT_2:
388 case R200_PP_TXFORMAT_3:
389 case R200_PP_TXFORMAT_4:
390 case R200_PP_TXFORMAT_5:
391 i = (reg - R200_PP_TXFORMAT_0) / 32;
392 if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) {
393 track->textures[i].use_pitch = 1;
395 track->textures[i].use_pitch = 0;
396 track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
397 track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
399 switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
400 case R200_TXFORMAT_I8:
401 case R200_TXFORMAT_RGB332:
402 case R200_TXFORMAT_Y8:
403 track->textures[i].cpp = 1;
405 case R200_TXFORMAT_DXT1:
406 case R200_TXFORMAT_AI88:
407 case R200_TXFORMAT_ARGB1555:
408 case R200_TXFORMAT_RGB565:
409 case R200_TXFORMAT_ARGB4444:
410 case R200_TXFORMAT_VYUY422:
411 case R200_TXFORMAT_YVYU422:
412 case R200_TXFORMAT_LDVDU655:
413 case R200_TXFORMAT_DVDU88:
414 case R200_TXFORMAT_AVYU4444:
415 track->textures[i].cpp = 2;
417 case R200_TXFORMAT_ARGB8888:
418 case R200_TXFORMAT_RGBA8888:
419 case R200_TXFORMAT_ABGR8888:
420 case R200_TXFORMAT_BGR111110:
421 case R200_TXFORMAT_LDVDU8888:
422 case R200_TXFORMAT_DXT23:
423 case R200_TXFORMAT_DXT45:
424 track->textures[i].cpp = 4;
427 track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
428 track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
430 case R200_PP_CUBIC_FACES_0:
431 case R200_PP_CUBIC_FACES_1:
432 case R200_PP_CUBIC_FACES_2:
433 case R200_PP_CUBIC_FACES_3:
434 case R200_PP_CUBIC_FACES_4:
435 case R200_PP_CUBIC_FACES_5:
436 tmp = ib_chunk->kdata[idx];
437 i = (reg - R200_PP_CUBIC_FACES_0) / 32;
438 for (face = 0; face < 4; face++) {
439 track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
440 track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
444 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
451 int r200_init(struct radeon_device *rdev)
453 rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
454 rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);