Linux 2.6.33-rc6
[cris-mirror.git] / drivers / gpu / drm / radeon / r200.c
blobff1e0cd608bf11d23981511f017782b4fa383be8
1 /*
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
25 * Alex Deucher
26 * Jerome Glisse
28 #include "drmP.h"
29 #include "drm.h"
30 #include "radeon_drm.h"
31 #include "radeon_reg.h"
32 #include "radeon.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)
40 int vtx_size, i;
41 vtx_size = 2;
43 if (vtx_fmt_0 & R200_VTX_Z0)
44 vtx_size++;
45 if (vtx_fmt_0 & R200_VTX_W0)
46 vtx_size++;
47 /* blend weight */
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)
51 vtx_size++;
52 if (vtx_fmt_0 & R200_VTX_N0)
53 vtx_size += 3;
54 if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
55 vtx_size++;
56 if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
57 vtx_size++;
58 if (vtx_fmt_0 & R200_VTX_SHININESS_0)
59 vtx_size++;
60 if (vtx_fmt_0 & R200_VTX_SHININESS_1)
61 vtx_size++;
62 for (i = 0; i < 8; i++) {
63 int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
64 switch (color_size) {
65 case 0: break;
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)
72 vtx_size += 2;
73 if (vtx_fmt_0 & R200_VTX_Z1)
74 vtx_size++;
75 if (vtx_fmt_0 & R200_VTX_W1)
76 vtx_size++;
77 if (vtx_fmt_0 & R200_VTX_N1)
78 vtx_size += 3;
79 return vtx_size;
82 static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
84 int vtx_size, i, tex_size;
85 vtx_size = 0;
86 for (i = 0; i < 6; i++) {
87 tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
88 if (tex_size > 4)
89 continue;
90 vtx_size += tex_size;
92 return vtx_size;
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_reloc *reloc;
100 struct r100_cs_track *track;
101 volatile uint32_t *ib;
102 uint32_t tmp;
103 int r;
104 int i;
105 int face;
106 u32 tile_flags = 0;
107 u32 idx_value;
109 ib = p->ib->ptr;
110 track = (struct r100_cs_track *)p->track;
111 idx_value = radeon_get_ib_value(p, idx);
112 switch (reg) {
113 case RADEON_CRTC_GUI_TRIG_VLINE:
114 r = r100_cs_packet_parse_vline(p);
115 if (r) {
116 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
117 idx, reg);
118 r100_cs_dump_packet(p, pkt);
119 return r;
121 break;
122 /* FIXME: only allow PACKET3 blit? easier to check for out of
123 * range access */
124 case RADEON_DST_PITCH_OFFSET:
125 case RADEON_SRC_PITCH_OFFSET:
126 r = r100_reloc_pitch_offset(p, pkt, idx, reg);
127 if (r)
128 return r;
129 break;
130 case RADEON_RB3D_DEPTHOFFSET:
131 r = r100_cs_packet_next_reloc(p, &reloc);
132 if (r) {
133 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
134 idx, reg);
135 r100_cs_dump_packet(p, pkt);
136 return r;
138 track->zb.robj = reloc->robj;
139 track->zb.offset = idx_value;
140 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
141 break;
142 case RADEON_RB3D_COLOROFFSET:
143 r = r100_cs_packet_next_reloc(p, &reloc);
144 if (r) {
145 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
146 idx, reg);
147 r100_cs_dump_packet(p, pkt);
148 return r;
150 track->cb[0].robj = reloc->robj;
151 track->cb[0].offset = idx_value;
152 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
153 break;
154 case R200_PP_TXOFFSET_0:
155 case R200_PP_TXOFFSET_1:
156 case R200_PP_TXOFFSET_2:
157 case R200_PP_TXOFFSET_3:
158 case R200_PP_TXOFFSET_4:
159 case R200_PP_TXOFFSET_5:
160 i = (reg - R200_PP_TXOFFSET_0) / 24;
161 r = r100_cs_packet_next_reloc(p, &reloc);
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;
168 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
169 track->textures[i].robj = reloc->robj;
170 break;
171 case R200_PP_CUBIC_OFFSET_F1_0:
172 case R200_PP_CUBIC_OFFSET_F2_0:
173 case R200_PP_CUBIC_OFFSET_F3_0:
174 case R200_PP_CUBIC_OFFSET_F4_0:
175 case R200_PP_CUBIC_OFFSET_F5_0:
176 case R200_PP_CUBIC_OFFSET_F1_1:
177 case R200_PP_CUBIC_OFFSET_F2_1:
178 case R200_PP_CUBIC_OFFSET_F3_1:
179 case R200_PP_CUBIC_OFFSET_F4_1:
180 case R200_PP_CUBIC_OFFSET_F5_1:
181 case R200_PP_CUBIC_OFFSET_F1_2:
182 case R200_PP_CUBIC_OFFSET_F2_2:
183 case R200_PP_CUBIC_OFFSET_F3_2:
184 case R200_PP_CUBIC_OFFSET_F4_2:
185 case R200_PP_CUBIC_OFFSET_F5_2:
186 case R200_PP_CUBIC_OFFSET_F1_3:
187 case R200_PP_CUBIC_OFFSET_F2_3:
188 case R200_PP_CUBIC_OFFSET_F3_3:
189 case R200_PP_CUBIC_OFFSET_F4_3:
190 case R200_PP_CUBIC_OFFSET_F5_3:
191 case R200_PP_CUBIC_OFFSET_F1_4:
192 case R200_PP_CUBIC_OFFSET_F2_4:
193 case R200_PP_CUBIC_OFFSET_F3_4:
194 case R200_PP_CUBIC_OFFSET_F4_4:
195 case R200_PP_CUBIC_OFFSET_F5_4:
196 case R200_PP_CUBIC_OFFSET_F1_5:
197 case R200_PP_CUBIC_OFFSET_F2_5:
198 case R200_PP_CUBIC_OFFSET_F3_5:
199 case R200_PP_CUBIC_OFFSET_F4_5:
200 case R200_PP_CUBIC_OFFSET_F5_5:
201 i = (reg - R200_PP_TXOFFSET_0) / 24;
202 face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
203 r = r100_cs_packet_next_reloc(p, &reloc);
204 if (r) {
205 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
206 idx, reg);
207 r100_cs_dump_packet(p, pkt);
208 return r;
210 track->textures[i].cube_info[face - 1].offset = idx_value;
211 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
212 track->textures[i].cube_info[face - 1].robj = reloc->robj;
213 break;
214 case RADEON_RE_WIDTH_HEIGHT:
215 track->maxy = ((idx_value >> 16) & 0x7FF);
216 break;
217 case RADEON_RB3D_COLORPITCH:
218 r = r100_cs_packet_next_reloc(p, &reloc);
219 if (r) {
220 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
221 idx, reg);
222 r100_cs_dump_packet(p, pkt);
223 return r;
226 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
227 tile_flags |= RADEON_COLOR_TILE_ENABLE;
228 if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
229 tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
231 tmp = idx_value & ~(0x7 << 16);
232 tmp |= tile_flags;
233 ib[idx] = tmp;
235 track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
236 break;
237 case RADEON_RB3D_DEPTHPITCH:
238 track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
239 break;
240 case RADEON_RB3D_CNTL:
241 switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
242 case 7:
243 case 8:
244 case 9:
245 case 11:
246 case 12:
247 track->cb[0].cpp = 1;
248 break;
249 case 3:
250 case 4:
251 case 15:
252 track->cb[0].cpp = 2;
253 break;
254 case 6:
255 track->cb[0].cpp = 4;
256 break;
257 default:
258 DRM_ERROR("Invalid color buffer format (%d) !\n",
259 ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
260 return -EINVAL;
262 if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
263 DRM_ERROR("No support for depth xy offset in kms\n");
264 return -EINVAL;
267 track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
268 break;
269 case RADEON_RB3D_ZSTENCILCNTL:
270 switch (idx_value & 0xf) {
271 case 0:
272 track->zb.cpp = 2;
273 break;
274 case 2:
275 case 3:
276 case 4:
277 case 5:
278 case 9:
279 case 11:
280 track->zb.cpp = 4;
281 break;
282 default:
283 break;
285 break;
286 case RADEON_RB3D_ZPASS_ADDR:
287 r = r100_cs_packet_next_reloc(p, &reloc);
288 if (r) {
289 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
290 idx, reg);
291 r100_cs_dump_packet(p, pkt);
292 return r;
294 ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
295 break;
296 case RADEON_PP_CNTL:
298 uint32_t temp = idx_value >> 4;
299 for (i = 0; i < track->num_texture; i++)
300 track->textures[i].enabled = !!(temp & (1 << i));
302 break;
303 case RADEON_SE_VF_CNTL:
304 track->vap_vf_cntl = idx_value;
305 break;
306 case 0x210c:
307 /* VAP_VF_MAX_VTX_INDX */
308 track->max_indx = idx_value & 0x00FFFFFFUL;
309 break;
310 case R200_SE_VTX_FMT_0:
311 track->vtx_size = r200_get_vtx_size_0(idx_value);
312 break;
313 case R200_SE_VTX_FMT_1:
314 track->vtx_size += r200_get_vtx_size_1(idx_value);
315 break;
316 case R200_PP_TXSIZE_0:
317 case R200_PP_TXSIZE_1:
318 case R200_PP_TXSIZE_2:
319 case R200_PP_TXSIZE_3:
320 case R200_PP_TXSIZE_4:
321 case R200_PP_TXSIZE_5:
322 i = (reg - R200_PP_TXSIZE_0) / 32;
323 track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
324 track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
325 break;
326 case R200_PP_TXPITCH_0:
327 case R200_PP_TXPITCH_1:
328 case R200_PP_TXPITCH_2:
329 case R200_PP_TXPITCH_3:
330 case R200_PP_TXPITCH_4:
331 case R200_PP_TXPITCH_5:
332 i = (reg - R200_PP_TXPITCH_0) / 32;
333 track->textures[i].pitch = idx_value + 32;
334 break;
335 case R200_PP_TXFILTER_0:
336 case R200_PP_TXFILTER_1:
337 case R200_PP_TXFILTER_2:
338 case R200_PP_TXFILTER_3:
339 case R200_PP_TXFILTER_4:
340 case R200_PP_TXFILTER_5:
341 i = (reg - R200_PP_TXFILTER_0) / 32;
342 track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
343 >> R200_MAX_MIP_LEVEL_SHIFT);
344 tmp = (idx_value >> 23) & 0x7;
345 if (tmp == 2 || tmp == 6)
346 track->textures[i].roundup_w = false;
347 tmp = (idx_value >> 27) & 0x7;
348 if (tmp == 2 || tmp == 6)
349 track->textures[i].roundup_h = false;
350 break;
351 case R200_PP_TXMULTI_CTL_0:
352 case R200_PP_TXMULTI_CTL_1:
353 case R200_PP_TXMULTI_CTL_2:
354 case R200_PP_TXMULTI_CTL_3:
355 case R200_PP_TXMULTI_CTL_4:
356 case R200_PP_TXMULTI_CTL_5:
357 i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
358 break;
359 case R200_PP_TXFORMAT_X_0:
360 case R200_PP_TXFORMAT_X_1:
361 case R200_PP_TXFORMAT_X_2:
362 case R200_PP_TXFORMAT_X_3:
363 case R200_PP_TXFORMAT_X_4:
364 case R200_PP_TXFORMAT_X_5:
365 i = (reg - R200_PP_TXFORMAT_X_0) / 32;
366 track->textures[i].txdepth = idx_value & 0x7;
367 tmp = (idx_value >> 16) & 0x3;
368 /* 2D, 3D, CUBE */
369 switch (tmp) {
370 case 0:
371 case 5:
372 case 6:
373 case 7:
374 /* 1D/2D */
375 track->textures[i].tex_coord_type = 0;
376 break;
377 case 1:
378 /* CUBE */
379 track->textures[i].tex_coord_type = 2;
380 break;
381 case 2:
382 /* 3D */
383 track->textures[i].tex_coord_type = 1;
384 break;
386 break;
387 case R200_PP_TXFORMAT_0:
388 case R200_PP_TXFORMAT_1:
389 case R200_PP_TXFORMAT_2:
390 case R200_PP_TXFORMAT_3:
391 case R200_PP_TXFORMAT_4:
392 case R200_PP_TXFORMAT_5:
393 i = (reg - R200_PP_TXFORMAT_0) / 32;
394 if (idx_value & R200_TXFORMAT_NON_POWER2) {
395 track->textures[i].use_pitch = 1;
396 } else {
397 track->textures[i].use_pitch = 0;
398 track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
399 track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
401 switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
402 case R200_TXFORMAT_I8:
403 case R200_TXFORMAT_RGB332:
404 case R200_TXFORMAT_Y8:
405 track->textures[i].cpp = 1;
406 break;
407 case R200_TXFORMAT_AI88:
408 case R200_TXFORMAT_ARGB1555:
409 case R200_TXFORMAT_RGB565:
410 case R200_TXFORMAT_ARGB4444:
411 case R200_TXFORMAT_VYUY422:
412 case R200_TXFORMAT_YVYU422:
413 case R200_TXFORMAT_LDVDU655:
414 case R200_TXFORMAT_DVDU88:
415 case R200_TXFORMAT_AVYU4444:
416 track->textures[i].cpp = 2;
417 break;
418 case R200_TXFORMAT_ARGB8888:
419 case R200_TXFORMAT_RGBA8888:
420 case R200_TXFORMAT_ABGR8888:
421 case R200_TXFORMAT_BGR111110:
422 case R200_TXFORMAT_LDVDU8888:
423 track->textures[i].cpp = 4;
424 break;
425 case R200_TXFORMAT_DXT1:
426 track->textures[i].cpp = 1;
427 track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
428 break;
429 case R200_TXFORMAT_DXT23:
430 case R200_TXFORMAT_DXT45:
431 track->textures[i].cpp = 1;
432 track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
433 break;
435 track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
436 track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
437 break;
438 case R200_PP_CUBIC_FACES_0:
439 case R200_PP_CUBIC_FACES_1:
440 case R200_PP_CUBIC_FACES_2:
441 case R200_PP_CUBIC_FACES_3:
442 case R200_PP_CUBIC_FACES_4:
443 case R200_PP_CUBIC_FACES_5:
444 tmp = idx_value;
445 i = (reg - R200_PP_CUBIC_FACES_0) / 32;
446 for (face = 0; face < 4; face++) {
447 track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
448 track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
450 break;
451 default:
452 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
453 reg, idx);
454 return -EINVAL;
456 return 0;
459 void r200_set_safe_registers(struct radeon_device *rdev)
461 rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
462 rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);