diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r300_cmdbuf.c | 1071 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r300_reg.h | 1772 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 1773 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 126 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.h | 1406 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ioc32.c | 424 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq.c | 320 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mem.c | 302 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_microcode.h | 1844 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_state.c | 3203 |
11 files changed, 12251 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile new file mode 100644 index 000000000000..feb521ebc393 --- /dev/null +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for the drm device driver. This driver provides support for the | ||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | ||
4 | |||
5 | ccflags-y := -Iinclude/drm | ||
6 | radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o | ||
7 | |||
8 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | ||
9 | |||
10 | obj-$(CONFIG_DRM_RADEON)+= radeon.o | ||
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c new file mode 100644 index 000000000000..702df45320f7 --- /dev/null +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c | |||
@@ -0,0 +1,1071 @@ | |||
1 | /* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*- | ||
2 | * | ||
3 | * Copyright (C) The Weather Channel, Inc. 2002. | ||
4 | * Copyright (C) 2004 Nicolai Haehnle. | ||
5 | * All Rights Reserved. | ||
6 | * | ||
7 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | ||
8 | * initial release of the Radeon 8500 driver under the XFree86 license. | ||
9 | * This notice must be preserved. | ||
10 | * | ||
11 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
12 | * copy of this software and associated documentation files (the "Software"), | ||
13 | * to deal in the Software without restriction, including without limitation | ||
14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
15 | * and/or sell copies of the Software, and to permit persons to whom the | ||
16 | * Software is furnished to do so, subject to the following conditions: | ||
17 | * | ||
18 | * The above copyright notice and this permission notice (including the next | ||
19 | * paragraph) shall be included in all copies or substantial portions of the | ||
20 | * Software. | ||
21 | * | ||
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
25 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
26 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
27 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
28 | * DEALINGS IN THE SOFTWARE. | ||
29 | * | ||
30 | * Authors: | ||
31 | * Nicolai Haehnle <prefect_@gmx.net> | ||
32 | */ | ||
33 | |||
34 | #include "drmP.h" | ||
35 | #include "drm.h" | ||
36 | #include "radeon_drm.h" | ||
37 | #include "radeon_drv.h" | ||
38 | #include "r300_reg.h" | ||
39 | |||
40 | #define R300_SIMULTANEOUS_CLIPRECTS 4 | ||
41 | |||
42 | /* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects | ||
43 | */ | ||
44 | static const int r300_cliprect_cntl[4] = { | ||
45 | 0xAAAA, | ||
46 | 0xEEEE, | ||
47 | 0xFEFE, | ||
48 | 0xFFFE | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command | ||
53 | * buffer, starting with index n. | ||
54 | */ | ||
55 | static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, | ||
56 | drm_radeon_kcmd_buffer_t *cmdbuf, int n) | ||
57 | { | ||
58 | struct drm_clip_rect box; | ||
59 | int nr; | ||
60 | int i; | ||
61 | RING_LOCALS; | ||
62 | |||
63 | nr = cmdbuf->nbox - n; | ||
64 | if (nr > R300_SIMULTANEOUS_CLIPRECTS) | ||
65 | nr = R300_SIMULTANEOUS_CLIPRECTS; | ||
66 | |||
67 | DRM_DEBUG("%i cliprects\n", nr); | ||
68 | |||
69 | if (nr) { | ||
70 | BEGIN_RING(6 + nr * 2); | ||
71 | OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); | ||
72 | |||
73 | for (i = 0; i < nr; ++i) { | ||
74 | if (DRM_COPY_FROM_USER_UNCHECKED | ||
75 | (&box, &cmdbuf->boxes[n + i], sizeof(box))) { | ||
76 | DRM_ERROR("copy cliprect faulted\n"); | ||
77 | return -EFAULT; | ||
78 | } | ||
79 | |||
80 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { | ||
81 | box.x1 = (box.x1) & | ||
82 | R300_CLIPRECT_MASK; | ||
83 | box.y1 = (box.y1) & | ||
84 | R300_CLIPRECT_MASK; | ||
85 | box.x2 = (box.x2) & | ||
86 | R300_CLIPRECT_MASK; | ||
87 | box.y2 = (box.y2) & | ||
88 | R300_CLIPRECT_MASK; | ||
89 | } else { | ||
90 | box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & | ||
91 | R300_CLIPRECT_MASK; | ||
92 | box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & | ||
93 | R300_CLIPRECT_MASK; | ||
94 | box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & | ||
95 | R300_CLIPRECT_MASK; | ||
96 | box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & | ||
97 | R300_CLIPRECT_MASK; | ||
98 | |||
99 | } | ||
100 | OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | | ||
101 | (box.y1 << R300_CLIPRECT_Y_SHIFT)); | ||
102 | OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | | ||
103 | (box.y2 << R300_CLIPRECT_Y_SHIFT)); | ||
104 | |||
105 | } | ||
106 | |||
107 | OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]); | ||
108 | |||
109 | /* TODO/SECURITY: Force scissors to a safe value, otherwise the | ||
110 | * client might be able to trample over memory. | ||
111 | * The impact should be very limited, but I'd rather be safe than | ||
112 | * sorry. | ||
113 | */ | ||
114 | OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1)); | ||
115 | OUT_RING(0); | ||
116 | OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK); | ||
117 | ADVANCE_RING(); | ||
118 | } else { | ||
119 | /* Why we allow zero cliprect rendering: | ||
120 | * There are some commands in a command buffer that must be submitted | ||
121 | * even when there are no cliprects, e.g. DMA buffer discard | ||
122 | * or state setting (though state setting could be avoided by | ||
123 | * simulating a loss of context). | ||
124 | * | ||
125 | * Now since the cmdbuf interface is so chaotic right now (and is | ||
126 | * bound to remain that way for a bit until things settle down), | ||
127 | * it is basically impossible to filter out the commands that are | ||
128 | * necessary and those that aren't. | ||
129 | * | ||
130 | * So I choose the safe way and don't do any filtering at all; | ||
131 | * instead, I simply set up the engine so that all rendering | ||
132 | * can't produce any fragments. | ||
133 | */ | ||
134 | BEGIN_RING(2); | ||
135 | OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0); | ||
136 | ADVANCE_RING(); | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static u8 r300_reg_flags[0x10000 >> 2]; | ||
143 | |||
144 | void r300_init_reg_flags(struct drm_device *dev) | ||
145 | { | ||
146 | int i; | ||
147 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
148 | |||
149 | memset(r300_reg_flags, 0, 0x10000 >> 2); | ||
150 | #define ADD_RANGE_MARK(reg, count,mark) \ | ||
151 | for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ | ||
152 | r300_reg_flags[i]|=(mark); | ||
153 | |||
154 | #define MARK_SAFE 1 | ||
155 | #define MARK_CHECK_OFFSET 2 | ||
156 | |||
157 | #define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE) | ||
158 | |||
159 | /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */ | ||
160 | ADD_RANGE(R300_SE_VPORT_XSCALE, 6); | ||
161 | ADD_RANGE(R300_VAP_CNTL, 1); | ||
162 | ADD_RANGE(R300_SE_VTE_CNTL, 2); | ||
163 | ADD_RANGE(0x2134, 2); | ||
164 | ADD_RANGE(R300_VAP_CNTL_STATUS, 1); | ||
165 | ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2); | ||
166 | ADD_RANGE(0x21DC, 1); | ||
167 | ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); | ||
168 | ADD_RANGE(R300_VAP_CLIP_X_0, 4); | ||
169 | ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1); | ||
170 | ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); | ||
171 | ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); | ||
172 | ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); | ||
173 | ADD_RANGE(R300_GB_ENABLE, 1); | ||
174 | ADD_RANGE(R300_GB_MSPOS0, 5); | ||
175 | ADD_RANGE(R300_TX_CNTL, 1); | ||
176 | ADD_RANGE(R300_TX_ENABLE, 1); | ||
177 | ADD_RANGE(0x4200, 4); | ||
178 | ADD_RANGE(0x4214, 1); | ||
179 | ADD_RANGE(R300_RE_POINTSIZE, 1); | ||
180 | ADD_RANGE(0x4230, 3); | ||
181 | ADD_RANGE(R300_RE_LINE_CNT, 1); | ||
182 | ADD_RANGE(R300_RE_UNK4238, 1); | ||
183 | ADD_RANGE(0x4260, 3); | ||
184 | ADD_RANGE(R300_RE_SHADE, 4); | ||
185 | ADD_RANGE(R300_RE_POLYGON_MODE, 5); | ||
186 | ADD_RANGE(R300_RE_ZBIAS_CNTL, 1); | ||
187 | ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4); | ||
188 | ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1); | ||
189 | ADD_RANGE(R300_RE_CULL_CNTL, 1); | ||
190 | ADD_RANGE(0x42C0, 2); | ||
191 | ADD_RANGE(R300_RS_CNTL_0, 2); | ||
192 | |||
193 | ADD_RANGE(R300_SC_HYPERZ, 2); | ||
194 | ADD_RANGE(0x43E8, 1); | ||
195 | |||
196 | ADD_RANGE(0x46A4, 5); | ||
197 | |||
198 | ADD_RANGE(R300_RE_FOG_STATE, 1); | ||
199 | ADD_RANGE(R300_FOG_COLOR_R, 3); | ||
200 | ADD_RANGE(R300_PP_ALPHA_TEST, 2); | ||
201 | ADD_RANGE(0x4BD8, 1); | ||
202 | ADD_RANGE(R300_PFS_PARAM_0_X, 64); | ||
203 | ADD_RANGE(0x4E00, 1); | ||
204 | ADD_RANGE(R300_RB3D_CBLEND, 2); | ||
205 | ADD_RANGE(R300_RB3D_COLORMASK, 1); | ||
206 | ADD_RANGE(R300_RB3D_BLEND_COLOR, 3); | ||
207 | ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */ | ||
208 | ADD_RANGE(R300_RB3D_COLORPITCH0, 1); | ||
209 | ADD_RANGE(0x4E50, 9); | ||
210 | ADD_RANGE(0x4E88, 1); | ||
211 | ADD_RANGE(0x4EA0, 2); | ||
212 | ADD_RANGE(R300_ZB_CNTL, 3); | ||
213 | ADD_RANGE(R300_ZB_FORMAT, 4); | ||
214 | ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */ | ||
215 | ADD_RANGE(R300_ZB_DEPTHPITCH, 1); | ||
216 | ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1); | ||
217 | ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13); | ||
218 | |||
219 | ADD_RANGE(R300_TX_FILTER_0, 16); | ||
220 | ADD_RANGE(R300_TX_FILTER1_0, 16); | ||
221 | ADD_RANGE(R300_TX_SIZE_0, 16); | ||
222 | ADD_RANGE(R300_TX_FORMAT_0, 16); | ||
223 | ADD_RANGE(R300_TX_PITCH_0, 16); | ||
224 | /* Texture offset is dangerous and needs more checking */ | ||
225 | ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); | ||
226 | ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); | ||
227 | ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); | ||
228 | |||
229 | /* Sporadic registers used as primitives are emitted */ | ||
230 | ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1); | ||
231 | ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1); | ||
232 | ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); | ||
233 | ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); | ||
234 | |||
235 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { | ||
236 | ADD_RANGE(R500_VAP_INDEX_OFFSET, 1); | ||
237 | ADD_RANGE(R500_US_CONFIG, 2); | ||
238 | ADD_RANGE(R500_US_CODE_ADDR, 3); | ||
239 | ADD_RANGE(R500_US_FC_CTRL, 1); | ||
240 | ADD_RANGE(R500_RS_IP_0, 16); | ||
241 | ADD_RANGE(R500_RS_INST_0, 16); | ||
242 | ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); | ||
243 | ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2); | ||
244 | ADD_RANGE(R500_ZB_FIFO_SIZE, 2); | ||
245 | } else { | ||
246 | ADD_RANGE(R300_PFS_CNTL_0, 3); | ||
247 | ADD_RANGE(R300_PFS_NODE_0, 4); | ||
248 | ADD_RANGE(R300_PFS_TEXI_0, 64); | ||
249 | ADD_RANGE(R300_PFS_INSTR0_0, 64); | ||
250 | ADD_RANGE(R300_PFS_INSTR1_0, 64); | ||
251 | ADD_RANGE(R300_PFS_INSTR2_0, 64); | ||
252 | ADD_RANGE(R300_PFS_INSTR3_0, 64); | ||
253 | ADD_RANGE(R300_RS_INTERP_0, 8); | ||
254 | ADD_RANGE(R300_RS_ROUTE_0, 8); | ||
255 | |||
256 | } | ||
257 | } | ||
258 | |||
259 | static __inline__ int r300_check_range(unsigned reg, int count) | ||
260 | { | ||
261 | int i; | ||
262 | if (reg & ~0xffff) | ||
263 | return -1; | ||
264 | for (i = (reg >> 2); i < (reg >> 2) + count; i++) | ||
265 | if (r300_reg_flags[i] != MARK_SAFE) | ||
266 | return 1; | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * | ||
271 | dev_priv, | ||
272 | drm_radeon_kcmd_buffer_t | ||
273 | * cmdbuf, | ||
274 | drm_r300_cmd_header_t | ||
275 | header) | ||
276 | { | ||
277 | int reg; | ||
278 | int sz; | ||
279 | int i; | ||
280 | int values[64]; | ||
281 | RING_LOCALS; | ||
282 | |||
283 | sz = header.packet0.count; | ||
284 | reg = (header.packet0.reghi << 8) | header.packet0.reglo; | ||
285 | |||
286 | if ((sz > 64) || (sz < 0)) { | ||
287 | DRM_ERROR | ||
288 | ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", | ||
289 | reg, sz); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | for (i = 0; i < sz; i++) { | ||
293 | values[i] = ((int *)cmdbuf->buf)[i]; | ||
294 | switch (r300_reg_flags[(reg >> 2) + i]) { | ||
295 | case MARK_SAFE: | ||
296 | break; | ||
297 | case MARK_CHECK_OFFSET: | ||
298 | if (!radeon_check_offset(dev_priv, (u32) values[i])) { | ||
299 | DRM_ERROR | ||
300 | ("Offset failed range check (reg=%04x sz=%d)\n", | ||
301 | reg, sz); | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | break; | ||
305 | default: | ||
306 | DRM_ERROR("Register %04x failed check as flag=%02x\n", | ||
307 | reg + i * 4, r300_reg_flags[(reg >> 2) + i]); | ||
308 | return -EINVAL; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | BEGIN_RING(1 + sz); | ||
313 | OUT_RING(CP_PACKET0(reg, sz - 1)); | ||
314 | OUT_RING_TABLE(values, sz); | ||
315 | ADVANCE_RING(); | ||
316 | |||
317 | cmdbuf->buf += sz * 4; | ||
318 | cmdbuf->bufsz -= sz * 4; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * Emits a packet0 setting arbitrary registers. | ||
325 | * Called by r300_do_cp_cmdbuf. | ||
326 | * | ||
327 | * Note that checks are performed on contents and addresses of the registers | ||
328 | */ | ||
329 | static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, | ||
330 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
331 | drm_r300_cmd_header_t header) | ||
332 | { | ||
333 | int reg; | ||
334 | int sz; | ||
335 | RING_LOCALS; | ||
336 | |||
337 | sz = header.packet0.count; | ||
338 | reg = (header.packet0.reghi << 8) | header.packet0.reglo; | ||
339 | |||
340 | if (!sz) | ||
341 | return 0; | ||
342 | |||
343 | if (sz * 4 > cmdbuf->bufsz) | ||
344 | return -EINVAL; | ||
345 | |||
346 | if (reg + sz * 4 >= 0x10000) { | ||
347 | DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, | ||
348 | sz); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | |||
352 | if (r300_check_range(reg, sz)) { | ||
353 | /* go and check everything */ | ||
354 | return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, | ||
355 | header); | ||
356 | } | ||
357 | /* the rest of the data is safe to emit, whatever the values the user passed */ | ||
358 | |||
359 | BEGIN_RING(1 + sz); | ||
360 | OUT_RING(CP_PACKET0(reg, sz - 1)); | ||
361 | OUT_RING_TABLE((int *)cmdbuf->buf, sz); | ||
362 | ADVANCE_RING(); | ||
363 | |||
364 | cmdbuf->buf += sz * 4; | ||
365 | cmdbuf->bufsz -= sz * 4; | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * Uploads user-supplied vertex program instructions or parameters onto | ||
372 | * the graphics card. | ||
373 | * Called by r300_do_cp_cmdbuf. | ||
374 | */ | ||
375 | static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, | ||
376 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
377 | drm_r300_cmd_header_t header) | ||
378 | { | ||
379 | int sz; | ||
380 | int addr; | ||
381 | RING_LOCALS; | ||
382 | |||
383 | sz = header.vpu.count; | ||
384 | addr = (header.vpu.adrhi << 8) | header.vpu.adrlo; | ||
385 | |||
386 | if (!sz) | ||
387 | return 0; | ||
388 | if (sz * 16 > cmdbuf->bufsz) | ||
389 | return -EINVAL; | ||
390 | |||
391 | BEGIN_RING(5 + sz * 4); | ||
392 | /* Wait for VAP to come to senses.. */ | ||
393 | /* there is no need to emit it multiple times, (only once before VAP is programmed, | ||
394 | but this optimization is for later */ | ||
395 | OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0); | ||
396 | OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); | ||
397 | OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); | ||
398 | OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); | ||
399 | |||
400 | ADVANCE_RING(); | ||
401 | |||
402 | cmdbuf->buf += sz * 16; | ||
403 | cmdbuf->bufsz -= sz * 16; | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | /** | ||
409 | * Emit a clear packet from userspace. | ||
410 | * Called by r300_emit_packet3. | ||
411 | */ | ||
412 | static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, | ||
413 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
414 | { | ||
415 | RING_LOCALS; | ||
416 | |||
417 | if (8 * 4 > cmdbuf->bufsz) | ||
418 | return -EINVAL; | ||
419 | |||
420 | BEGIN_RING(10); | ||
421 | OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8)); | ||
422 | OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING | | ||
423 | (1 << R300_PRIM_NUM_VERTICES_SHIFT)); | ||
424 | OUT_RING_TABLE((int *)cmdbuf->buf, 8); | ||
425 | ADVANCE_RING(); | ||
426 | |||
427 | cmdbuf->buf += 8 * 4; | ||
428 | cmdbuf->bufsz -= 8 * 4; | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, | ||
434 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
435 | u32 header) | ||
436 | { | ||
437 | int count, i, k; | ||
438 | #define MAX_ARRAY_PACKET 64 | ||
439 | u32 payload[MAX_ARRAY_PACKET]; | ||
440 | u32 narrays; | ||
441 | RING_LOCALS; | ||
442 | |||
443 | count = (header >> 16) & 0x3fff; | ||
444 | |||
445 | if ((count + 1) > MAX_ARRAY_PACKET) { | ||
446 | DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", | ||
447 | count); | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | memset(payload, 0, MAX_ARRAY_PACKET * 4); | ||
451 | memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4); | ||
452 | |||
453 | /* carefully check packet contents */ | ||
454 | |||
455 | narrays = payload[0]; | ||
456 | k = 0; | ||
457 | i = 1; | ||
458 | while ((k < narrays) && (i < (count + 1))) { | ||
459 | i++; /* skip attribute field */ | ||
460 | if (!radeon_check_offset(dev_priv, payload[i])) { | ||
461 | DRM_ERROR | ||
462 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", | ||
463 | k, i); | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | k++; | ||
467 | i++; | ||
468 | if (k == narrays) | ||
469 | break; | ||
470 | /* have one more to process, they come in pairs */ | ||
471 | if (!radeon_check_offset(dev_priv, payload[i])) { | ||
472 | DRM_ERROR | ||
473 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", | ||
474 | k, i); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | k++; | ||
478 | i++; | ||
479 | } | ||
480 | /* do the counts match what we expect ? */ | ||
481 | if ((k != narrays) || (i != (count + 1))) { | ||
482 | DRM_ERROR | ||
483 | ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", | ||
484 | k, i, narrays, count + 1); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | /* all clear, output packet */ | ||
489 | |||
490 | BEGIN_RING(count + 2); | ||
491 | OUT_RING(header); | ||
492 | OUT_RING_TABLE(payload, count + 1); | ||
493 | ADVANCE_RING(); | ||
494 | |||
495 | cmdbuf->buf += (count + 2) * 4; | ||
496 | cmdbuf->bufsz -= (count + 2) * 4; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | ||
502 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
503 | { | ||
504 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
505 | int count, ret; | ||
506 | RING_LOCALS; | ||
507 | |||
508 | count=(cmd[0]>>16) & 0x3fff; | ||
509 | |||
510 | if (cmd[0] & 0x8000) { | ||
511 | u32 offset; | ||
512 | |||
513 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | ||
514 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | ||
515 | offset = cmd[2] << 10; | ||
516 | ret = !radeon_check_offset(dev_priv, offset); | ||
517 | if (ret) { | ||
518 | DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); | ||
519 | return -EINVAL; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && | ||
524 | (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | ||
525 | offset = cmd[3] << 10; | ||
526 | ret = !radeon_check_offset(dev_priv, offset); | ||
527 | if (ret) { | ||
528 | DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); | ||
529 | return -EINVAL; | ||
530 | } | ||
531 | |||
532 | } | ||
533 | } | ||
534 | |||
535 | BEGIN_RING(count+2); | ||
536 | OUT_RING(cmd[0]); | ||
537 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
538 | ADVANCE_RING(); | ||
539 | |||
540 | cmdbuf->buf += (count+2)*4; | ||
541 | cmdbuf->bufsz -= (count+2)*4; | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | ||
547 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
548 | { | ||
549 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
550 | int count, ret; | ||
551 | RING_LOCALS; | ||
552 | |||
553 | count=(cmd[0]>>16) & 0x3fff; | ||
554 | |||
555 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
556 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
557 | return -EINVAL; | ||
558 | } | ||
559 | ret = !radeon_check_offset(dev_priv, cmd[2]); | ||
560 | if (ret) { | ||
561 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | BEGIN_RING(count+2); | ||
566 | OUT_RING(cmd[0]); | ||
567 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
568 | ADVANCE_RING(); | ||
569 | |||
570 | cmdbuf->buf += (count+2)*4; | ||
571 | cmdbuf->bufsz -= (count+2)*4; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | ||
577 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
578 | { | ||
579 | u32 header; | ||
580 | int count; | ||
581 | RING_LOCALS; | ||
582 | |||
583 | if (4 > cmdbuf->bufsz) | ||
584 | return -EINVAL; | ||
585 | |||
586 | /* Fixme !! This simply emits a packet without much checking. | ||
587 | We need to be smarter. */ | ||
588 | |||
589 | /* obtain first word - actual packet3 header */ | ||
590 | header = *(u32 *) cmdbuf->buf; | ||
591 | |||
592 | /* Is it packet 3 ? */ | ||
593 | if ((header >> 30) != 0x3) { | ||
594 | DRM_ERROR("Not a packet3 header (0x%08x)\n", header); | ||
595 | return -EINVAL; | ||
596 | } | ||
597 | |||
598 | count = (header >> 16) & 0x3fff; | ||
599 | |||
600 | /* Check again now that we know how much data to expect */ | ||
601 | if ((count + 2) * 4 > cmdbuf->bufsz) { | ||
602 | DRM_ERROR | ||
603 | ("Expected packet3 of length %d but have only %d bytes left\n", | ||
604 | (count + 2) * 4, cmdbuf->bufsz); | ||
605 | return -EINVAL; | ||
606 | } | ||
607 | |||
608 | /* Is it a packet type we know about ? */ | ||
609 | switch (header & 0xff00) { | ||
610 | case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ | ||
611 | return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header); | ||
612 | |||
613 | case RADEON_CNTL_BITBLT_MULTI: | ||
614 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | ||
615 | |||
616 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
617 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | ||
618 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ | ||
619 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ | ||
620 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ | ||
621 | case RADEON_WAIT_FOR_IDLE: | ||
622 | case RADEON_CP_NOP: | ||
623 | /* these packets are safe */ | ||
624 | break; | ||
625 | default: | ||
626 | DRM_ERROR("Unknown packet3 header (0x%08x)\n", header); | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | |||
630 | BEGIN_RING(count + 2); | ||
631 | OUT_RING(header); | ||
632 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
633 | ADVANCE_RING(); | ||
634 | |||
635 | cmdbuf->buf += (count + 2) * 4; | ||
636 | cmdbuf->bufsz -= (count + 2) * 4; | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * Emit a rendering packet3 from userspace. | ||
643 | * Called by r300_do_cp_cmdbuf. | ||
644 | */ | ||
645 | static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, | ||
646 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
647 | drm_r300_cmd_header_t header) | ||
648 | { | ||
649 | int n; | ||
650 | int ret; | ||
651 | char *orig_buf = cmdbuf->buf; | ||
652 | int orig_bufsz = cmdbuf->bufsz; | ||
653 | |||
654 | /* This is a do-while-loop so that we run the interior at least once, | ||
655 | * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale. | ||
656 | */ | ||
657 | n = 0; | ||
658 | do { | ||
659 | if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) { | ||
660 | ret = r300_emit_cliprects(dev_priv, cmdbuf, n); | ||
661 | if (ret) | ||
662 | return ret; | ||
663 | |||
664 | cmdbuf->buf = orig_buf; | ||
665 | cmdbuf->bufsz = orig_bufsz; | ||
666 | } | ||
667 | |||
668 | switch (header.packet3.packet) { | ||
669 | case R300_CMD_PACKET3_CLEAR: | ||
670 | DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n"); | ||
671 | ret = r300_emit_clear(dev_priv, cmdbuf); | ||
672 | if (ret) { | ||
673 | DRM_ERROR("r300_emit_clear failed\n"); | ||
674 | return ret; | ||
675 | } | ||
676 | break; | ||
677 | |||
678 | case R300_CMD_PACKET3_RAW: | ||
679 | DRM_DEBUG("R300_CMD_PACKET3_RAW\n"); | ||
680 | ret = r300_emit_raw_packet3(dev_priv, cmdbuf); | ||
681 | if (ret) { | ||
682 | DRM_ERROR("r300_emit_raw_packet3 failed\n"); | ||
683 | return ret; | ||
684 | } | ||
685 | break; | ||
686 | |||
687 | default: | ||
688 | DRM_ERROR("bad packet3 type %i at %p\n", | ||
689 | header.packet3.packet, | ||
690 | cmdbuf->buf - sizeof(header)); | ||
691 | return -EINVAL; | ||
692 | } | ||
693 | |||
694 | n += R300_SIMULTANEOUS_CLIPRECTS; | ||
695 | } while (n < cmdbuf->nbox); | ||
696 | |||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | /* Some of the R300 chips seem to be extremely touchy about the two registers | ||
701 | * that are configured in r300_pacify. | ||
702 | * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace | ||
703 | * sends a command buffer that contains only state setting commands and a | ||
704 | * vertex program/parameter upload sequence, this will eventually lead to a | ||
705 | * lockup, unless the sequence is bracketed by calls to r300_pacify. | ||
706 | * So we should take great care to *always* call r300_pacify before | ||
707 | * *anything* 3D related, and again afterwards. This is what the | ||
708 | * call bracket in r300_do_cp_cmdbuf is for. | ||
709 | */ | ||
710 | |||
711 | /** | ||
712 | * Emit the sequence to pacify R300. | ||
713 | */ | ||
714 | static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) | ||
715 | { | ||
716 | RING_LOCALS; | ||
717 | |||
718 | BEGIN_RING(6); | ||
719 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
720 | OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A); | ||
721 | OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); | ||
722 | OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE| | ||
723 | R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); | ||
724 | OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0)); | ||
725 | OUT_RING(0x0); | ||
726 | ADVANCE_RING(); | ||
727 | } | ||
728 | |||
729 | /** | ||
730 | * Called by r300_do_cp_cmdbuf to update the internal buffer age and state. | ||
731 | * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must | ||
732 | * be careful about how this function is called. | ||
733 | */ | ||
734 | static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) | ||
735 | { | ||
736 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
737 | drm_radeon_buf_priv_t *buf_priv = buf->dev_private; | ||
738 | |||
739 | buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; | ||
740 | buf->pending = 1; | ||
741 | buf->used = 0; | ||
742 | } | ||
743 | |||
744 | static void r300_cmd_wait(drm_radeon_private_t * dev_priv, | ||
745 | drm_r300_cmd_header_t header) | ||
746 | { | ||
747 | u32 wait_until; | ||
748 | RING_LOCALS; | ||
749 | |||
750 | if (!header.wait.flags) | ||
751 | return; | ||
752 | |||
753 | wait_until = 0; | ||
754 | |||
755 | switch(header.wait.flags) { | ||
756 | case R300_WAIT_2D: | ||
757 | wait_until = RADEON_WAIT_2D_IDLE; | ||
758 | break; | ||
759 | case R300_WAIT_3D: | ||
760 | wait_until = RADEON_WAIT_3D_IDLE; | ||
761 | break; | ||
762 | case R300_NEW_WAIT_2D_3D: | ||
763 | wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE; | ||
764 | break; | ||
765 | case R300_NEW_WAIT_2D_2D_CLEAN: | ||
766 | wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; | ||
767 | break; | ||
768 | case R300_NEW_WAIT_3D_3D_CLEAN: | ||
769 | wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; | ||
770 | break; | ||
771 | case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN: | ||
772 | wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; | ||
773 | wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; | ||
774 | break; | ||
775 | default: | ||
776 | return; | ||
777 | } | ||
778 | |||
779 | BEGIN_RING(2); | ||
780 | OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
781 | OUT_RING(wait_until); | ||
782 | ADVANCE_RING(); | ||
783 | } | ||
784 | |||
785 | static int r300_scratch(drm_radeon_private_t *dev_priv, | ||
786 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
787 | drm_r300_cmd_header_t header) | ||
788 | { | ||
789 | u32 *ref_age_base; | ||
790 | u32 i, buf_idx, h_pending; | ||
791 | RING_LOCALS; | ||
792 | |||
793 | if (cmdbuf->bufsz < | ||
794 | (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { | ||
795 | return -EINVAL; | ||
796 | } | ||
797 | |||
798 | if (header.scratch.reg >= 5) { | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | |||
802 | dev_priv->scratch_ages[header.scratch.reg]++; | ||
803 | |||
804 | ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf); | ||
805 | |||
806 | cmdbuf->buf += sizeof(u64); | ||
807 | cmdbuf->bufsz -= sizeof(u64); | ||
808 | |||
809 | for (i=0; i < header.scratch.n_bufs; i++) { | ||
810 | buf_idx = *(u32 *)cmdbuf->buf; | ||
811 | buf_idx *= 2; /* 8 bytes per buf */ | ||
812 | |||
813 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | |||
817 | if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { | ||
818 | return -EINVAL; | ||
819 | } | ||
820 | |||
821 | if (h_pending == 0) { | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | |||
825 | h_pending--; | ||
826 | |||
827 | if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { | ||
828 | return -EINVAL; | ||
829 | } | ||
830 | |||
831 | cmdbuf->buf += sizeof(buf_idx); | ||
832 | cmdbuf->bufsz -= sizeof(buf_idx); | ||
833 | } | ||
834 | |||
835 | BEGIN_RING(2); | ||
836 | OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) ); | ||
837 | OUT_RING( dev_priv->scratch_ages[header.scratch.reg] ); | ||
838 | ADVANCE_RING(); | ||
839 | |||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | /** | ||
844 | * Uploads user-supplied vertex program instructions or parameters onto | ||
845 | * the graphics card. | ||
846 | * Called by r300_do_cp_cmdbuf. | ||
847 | */ | ||
848 | static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, | ||
849 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
850 | drm_r300_cmd_header_t header) | ||
851 | { | ||
852 | int sz; | ||
853 | int addr; | ||
854 | int type; | ||
855 | int clamp; | ||
856 | int stride; | ||
857 | RING_LOCALS; | ||
858 | |||
859 | sz = header.r500fp.count; | ||
860 | /* address is 9 bits 0 - 8, bit 1 of flags is part of address */ | ||
861 | addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; | ||
862 | |||
863 | type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); | ||
864 | clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); | ||
865 | |||
866 | addr |= (type << 16); | ||
867 | addr |= (clamp << 17); | ||
868 | |||
869 | stride = type ? 4 : 6; | ||
870 | |||
871 | DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type); | ||
872 | if (!sz) | ||
873 | return 0; | ||
874 | if (sz * stride * 4 > cmdbuf->bufsz) | ||
875 | return -EINVAL; | ||
876 | |||
877 | BEGIN_RING(3 + sz * stride); | ||
878 | OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); | ||
879 | OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1)); | ||
880 | OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride); | ||
881 | |||
882 | ADVANCE_RING(); | ||
883 | |||
884 | cmdbuf->buf += sz * stride * 4; | ||
885 | cmdbuf->bufsz -= sz * stride * 4; | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | |||
891 | /** | ||
892 | * Parses and validates a user-supplied command buffer and emits appropriate | ||
893 | * commands on the DMA ring buffer. | ||
894 | * Called by the ioctl handler function radeon_cp_cmdbuf. | ||
895 | */ | ||
896 | int r300_do_cp_cmdbuf(struct drm_device *dev, | ||
897 | struct drm_file *file_priv, | ||
898 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
899 | { | ||
900 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
901 | struct drm_device_dma *dma = dev->dma; | ||
902 | struct drm_buf *buf = NULL; | ||
903 | int emit_dispatch_age = 0; | ||
904 | int ret = 0; | ||
905 | |||
906 | DRM_DEBUG("\n"); | ||
907 | |||
908 | /* See the comment above r300_emit_begin3d for why this call must be here, | ||
909 | * and what the cleanup gotos are for. */ | ||
910 | r300_pacify(dev_priv); | ||
911 | |||
912 | if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { | ||
913 | ret = r300_emit_cliprects(dev_priv, cmdbuf, 0); | ||
914 | if (ret) | ||
915 | goto cleanup; | ||
916 | } | ||
917 | |||
918 | while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) { | ||
919 | int idx; | ||
920 | drm_r300_cmd_header_t header; | ||
921 | |||
922 | header.u = *(unsigned int *)cmdbuf->buf; | ||
923 | |||
924 | cmdbuf->buf += sizeof(header); | ||
925 | cmdbuf->bufsz -= sizeof(header); | ||
926 | |||
927 | switch (header.header.cmd_type) { | ||
928 | case R300_CMD_PACKET0: | ||
929 | DRM_DEBUG("R300_CMD_PACKET0\n"); | ||
930 | ret = r300_emit_packet0(dev_priv, cmdbuf, header); | ||
931 | if (ret) { | ||
932 | DRM_ERROR("r300_emit_packet0 failed\n"); | ||
933 | goto cleanup; | ||
934 | } | ||
935 | break; | ||
936 | |||
937 | case R300_CMD_VPU: | ||
938 | DRM_DEBUG("R300_CMD_VPU\n"); | ||
939 | ret = r300_emit_vpu(dev_priv, cmdbuf, header); | ||
940 | if (ret) { | ||
941 | DRM_ERROR("r300_emit_vpu failed\n"); | ||
942 | goto cleanup; | ||
943 | } | ||
944 | break; | ||
945 | |||
946 | case R300_CMD_PACKET3: | ||
947 | DRM_DEBUG("R300_CMD_PACKET3\n"); | ||
948 | ret = r300_emit_packet3(dev_priv, cmdbuf, header); | ||
949 | if (ret) { | ||
950 | DRM_ERROR("r300_emit_packet3 failed\n"); | ||
951 | goto cleanup; | ||
952 | } | ||
953 | break; | ||
954 | |||
955 | case R300_CMD_END3D: | ||
956 | DRM_DEBUG("R300_CMD_END3D\n"); | ||
957 | /* TODO: | ||
958 | Ideally userspace driver should not need to issue this call, | ||
959 | i.e. the drm driver should issue it automatically and prevent | ||
960 | lockups. | ||
961 | |||
962 | In practice, we do not understand why this call is needed and what | ||
963 | it does (except for some vague guesses that it has to do with cache | ||
964 | coherence) and so the user space driver does it. | ||
965 | |||
966 | Once we are sure which uses prevent lockups the code could be moved | ||
967 | into the kernel and the userspace driver will not | ||
968 | need to use this command. | ||
969 | |||
970 | Note that issuing this command does not hurt anything | ||
971 | except, possibly, performance */ | ||
972 | r300_pacify(dev_priv); | ||
973 | break; | ||
974 | |||
975 | case R300_CMD_CP_DELAY: | ||
976 | /* simple enough, we can do it here */ | ||
977 | DRM_DEBUG("R300_CMD_CP_DELAY\n"); | ||
978 | { | ||
979 | int i; | ||
980 | RING_LOCALS; | ||
981 | |||
982 | BEGIN_RING(header.delay.count); | ||
983 | for (i = 0; i < header.delay.count; i++) | ||
984 | OUT_RING(RADEON_CP_PACKET2); | ||
985 | ADVANCE_RING(); | ||
986 | } | ||
987 | break; | ||
988 | |||
989 | case R300_CMD_DMA_DISCARD: | ||
990 | DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); | ||
991 | idx = header.dma.buf_idx; | ||
992 | if (idx < 0 || idx >= dma->buf_count) { | ||
993 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
994 | idx, dma->buf_count - 1); | ||
995 | ret = -EINVAL; | ||
996 | goto cleanup; | ||
997 | } | ||
998 | |||
999 | buf = dma->buflist[idx]; | ||
1000 | if (buf->file_priv != file_priv || buf->pending) { | ||
1001 | DRM_ERROR("bad buffer %p %p %d\n", | ||
1002 | buf->file_priv, file_priv, | ||
1003 | buf->pending); | ||
1004 | ret = -EINVAL; | ||
1005 | goto cleanup; | ||
1006 | } | ||
1007 | |||
1008 | emit_dispatch_age = 1; | ||
1009 | r300_discard_buffer(dev, buf); | ||
1010 | break; | ||
1011 | |||
1012 | case R300_CMD_WAIT: | ||
1013 | DRM_DEBUG("R300_CMD_WAIT\n"); | ||
1014 | r300_cmd_wait(dev_priv, header); | ||
1015 | break; | ||
1016 | |||
1017 | case R300_CMD_SCRATCH: | ||
1018 | DRM_DEBUG("R300_CMD_SCRATCH\n"); | ||
1019 | ret = r300_scratch(dev_priv, cmdbuf, header); | ||
1020 | if (ret) { | ||
1021 | DRM_ERROR("r300_scratch failed\n"); | ||
1022 | goto cleanup; | ||
1023 | } | ||
1024 | break; | ||
1025 | |||
1026 | case R300_CMD_R500FP: | ||
1027 | if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { | ||
1028 | DRM_ERROR("Calling r500 command on r300 card\n"); | ||
1029 | ret = -EINVAL; | ||
1030 | goto cleanup; | ||
1031 | } | ||
1032 | DRM_DEBUG("R300_CMD_R500FP\n"); | ||
1033 | ret = r300_emit_r500fp(dev_priv, cmdbuf, header); | ||
1034 | if (ret) { | ||
1035 | DRM_ERROR("r300_emit_r500fp failed\n"); | ||
1036 | goto cleanup; | ||
1037 | } | ||
1038 | break; | ||
1039 | default: | ||
1040 | DRM_ERROR("bad cmd_type %i at %p\n", | ||
1041 | header.header.cmd_type, | ||
1042 | cmdbuf->buf - sizeof(header)); | ||
1043 | ret = -EINVAL; | ||
1044 | goto cleanup; | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | DRM_DEBUG("END\n"); | ||
1049 | |||
1050 | cleanup: | ||
1051 | r300_pacify(dev_priv); | ||
1052 | |||
1053 | /* We emit the vertex buffer age here, outside the pacifier "brackets" | ||
1054 | * for two reasons: | ||
1055 | * (1) This may coalesce multiple age emissions into a single one and | ||
1056 | * (2) more importantly, some chips lock up hard when scratch registers | ||
1057 | * are written inside the pacifier bracket. | ||
1058 | */ | ||
1059 | if (emit_dispatch_age) { | ||
1060 | RING_LOCALS; | ||
1061 | |||
1062 | /* Emit the vertex buffer age */ | ||
1063 | BEGIN_RING(2); | ||
1064 | RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch); | ||
1065 | ADVANCE_RING(); | ||
1066 | } | ||
1067 | |||
1068 | COMMIT_RING(); | ||
1069 | |||
1070 | return ret; | ||
1071 | } | ||
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h new file mode 100644 index 000000000000..a6802f26afc4 --- /dev/null +++ b/drivers/gpu/drm/radeon/r300_reg.h | |||
@@ -0,0 +1,1772 @@ | |||
1 | /************************************************************************** | ||
2 | |||
3 | Copyright (C) 2004-2005 Nicolai Haehnle et al. | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | copy of this software and associated documentation files (the "Software"), | ||
7 | to deal in the Software without restriction, including without limitation | ||
8 | on the rights to use, copy, modify, merge, publish, distribute, sub | ||
9 | license, and/or sell copies of the Software, and to permit persons to whom | ||
10 | the Software is furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice (including the next | ||
13 | paragraph) shall be included in all copies or substantial portions of the | ||
14 | 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 NON-INFRINGEMENT. IN NO EVENT SHALL | ||
19 | THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
21 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
22 | USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
23 | |||
24 | **************************************************************************/ | ||
25 | |||
26 | #ifndef _R300_REG_H | ||
27 | #define _R300_REG_H | ||
28 | |||
29 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 | ||
30 | # define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 | ||
31 | # define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4 | ||
32 | # define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8 | ||
33 | # define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12 | ||
34 | # define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16 | ||
35 | # define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20 | ||
36 | # define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24 | ||
37 | # define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28 | ||
38 | |||
39 | #define R300_MC_INIT_GFX_LAT_TIMER 0x154 | ||
40 | # define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0 | ||
41 | # define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4 | ||
42 | # define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8 | ||
43 | # define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12 | ||
44 | # define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16 | ||
45 | # define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20 | ||
46 | # define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24 | ||
47 | # define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28 | ||
48 | |||
49 | /* | ||
50 | * This file contains registers and constants for the R300. They have been | ||
51 | * found mostly by examining command buffers captured using glxtest, as well | ||
52 | * as by extrapolating some known registers and constants from the R200. | ||
53 | * I am fairly certain that they are correct unless stated otherwise | ||
54 | * in comments. | ||
55 | */ | ||
56 | |||
57 | #define R300_SE_VPORT_XSCALE 0x1D98 | ||
58 | #define R300_SE_VPORT_XOFFSET 0x1D9C | ||
59 | #define R300_SE_VPORT_YSCALE 0x1DA0 | ||
60 | #define R300_SE_VPORT_YOFFSET 0x1DA4 | ||
61 | #define R300_SE_VPORT_ZSCALE 0x1DA8 | ||
62 | #define R300_SE_VPORT_ZOFFSET 0x1DAC | ||
63 | |||
64 | |||
65 | /* | ||
66 | * Vertex Array Processing (VAP) Control | ||
67 | * Stolen from r200 code from Christoph Brill (It's a guess!) | ||
68 | */ | ||
69 | #define R300_VAP_CNTL 0x2080 | ||
70 | |||
71 | /* This register is written directly and also starts data section | ||
72 | * in many 3d CP_PACKET3's | ||
73 | */ | ||
74 | #define R300_VAP_VF_CNTL 0x2084 | ||
75 | # define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0 | ||
76 | # define R300_VAP_VF_CNTL__PRIM_NONE (0<<0) | ||
77 | # define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0) | ||
78 | # define R300_VAP_VF_CNTL__PRIM_LINES (2<<0) | ||
79 | # define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0) | ||
80 | # define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0) | ||
81 | # define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0) | ||
82 | # define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0) | ||
83 | # define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0) | ||
84 | # define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0) | ||
85 | # define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0) | ||
86 | # define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0) | ||
87 | |||
88 | # define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4 | ||
89 | /* State based - direct writes to registers trigger vertex | ||
90 | generation */ | ||
91 | # define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4) | ||
92 | # define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4) | ||
93 | # define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4) | ||
94 | # define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4) | ||
95 | |||
96 | /* I don't think I saw these three used.. */ | ||
97 | # define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6 | ||
98 | # define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9 | ||
99 | # define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10 | ||
100 | |||
101 | /* index size - when not set the indices are assumed to be 16 bit */ | ||
102 | # define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11) | ||
103 | /* number of vertices */ | ||
104 | # define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16 | ||
105 | |||
106 | /* BEGIN: Wild guesses */ | ||
107 | #define R300_VAP_OUTPUT_VTX_FMT_0 0x2090 | ||
108 | # define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0) | ||
109 | # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1) | ||
110 | # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */ | ||
111 | # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */ | ||
112 | # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */ | ||
113 | # define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */ | ||
114 | |||
115 | #define R300_VAP_OUTPUT_VTX_FMT_1 0x2094 | ||
116 | /* each of the following is 3 bits wide, specifies number | ||
117 | of components */ | ||
118 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 | ||
119 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 | ||
120 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 | ||
121 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 | ||
122 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 | ||
123 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 | ||
124 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 | ||
125 | # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 | ||
126 | /* END: Wild guesses */ | ||
127 | |||
128 | #define R300_SE_VTE_CNTL 0x20b0 | ||
129 | # define R300_VPORT_X_SCALE_ENA 0x00000001 | ||
130 | # define R300_VPORT_X_OFFSET_ENA 0x00000002 | ||
131 | # define R300_VPORT_Y_SCALE_ENA 0x00000004 | ||
132 | # define R300_VPORT_Y_OFFSET_ENA 0x00000008 | ||
133 | # define R300_VPORT_Z_SCALE_ENA 0x00000010 | ||
134 | # define R300_VPORT_Z_OFFSET_ENA 0x00000020 | ||
135 | # define R300_VTX_XY_FMT 0x00000100 | ||
136 | # define R300_VTX_Z_FMT 0x00000200 | ||
137 | # define R300_VTX_W0_FMT 0x00000400 | ||
138 | # define R300_VTX_W0_NORMALIZE 0x00000800 | ||
139 | # define R300_VTX_ST_DENORMALIZED 0x00001000 | ||
140 | |||
141 | /* BEGIN: Vertex data assembly - lots of uncertainties */ | ||
142 | |||
143 | /* gap */ | ||
144 | |||
145 | #define R300_VAP_CNTL_STATUS 0x2140 | ||
146 | # define R300_VC_NO_SWAP (0 << 0) | ||
147 | # define R300_VC_16BIT_SWAP (1 << 0) | ||
148 | # define R300_VC_32BIT_SWAP (2 << 0) | ||
149 | # define R300_VAP_TCL_BYPASS (1 << 8) | ||
150 | |||
151 | /* gap */ | ||
152 | |||
153 | /* Where do we get our vertex data? | ||
154 | * | ||
155 | * Vertex data either comes either from immediate mode registers or from | ||
156 | * vertex arrays. | ||
157 | * There appears to be no mixed mode (though we can force the pitch of | ||
158 | * vertex arrays to 0, effectively reusing the same element over and over | ||
159 | * again). | ||
160 | * | ||
161 | * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure | ||
162 | * if these registers influence vertex array processing. | ||
163 | * | ||
164 | * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3. | ||
165 | * | ||
166 | * In both cases, vertex attributes are then passed through INPUT_ROUTE. | ||
167 | * | ||
168 | * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data | ||
169 | * into the vertex processor's input registers. | ||
170 | * The first word routes the first input, the second word the second, etc. | ||
171 | * The corresponding input is routed into the register with the given index. | ||
172 | * The list is ended by a word with INPUT_ROUTE_END set. | ||
173 | * | ||
174 | * Always set COMPONENTS_4 in immediate mode. | ||
175 | */ | ||
176 | |||
177 | #define R300_VAP_INPUT_ROUTE_0_0 0x2150 | ||
178 | # define R300_INPUT_ROUTE_COMPONENTS_1 (0 << 0) | ||
179 | # define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0) | ||
180 | # define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0) | ||
181 | # define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0) | ||
182 | # define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */ | ||
183 | # define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8 | ||
184 | # define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */ | ||
185 | # define R300_VAP_INPUT_ROUTE_END (1 << 13) | ||
186 | # define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */ | ||
187 | # define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */ | ||
188 | # define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */ | ||
189 | # define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */ | ||
190 | #define R300_VAP_INPUT_ROUTE_0_1 0x2154 | ||
191 | #define R300_VAP_INPUT_ROUTE_0_2 0x2158 | ||
192 | #define R300_VAP_INPUT_ROUTE_0_3 0x215C | ||
193 | #define R300_VAP_INPUT_ROUTE_0_4 0x2160 | ||
194 | #define R300_VAP_INPUT_ROUTE_0_5 0x2164 | ||
195 | #define R300_VAP_INPUT_ROUTE_0_6 0x2168 | ||
196 | #define R300_VAP_INPUT_ROUTE_0_7 0x216C | ||
197 | |||
198 | /* gap */ | ||
199 | |||
200 | /* Notes: | ||
201 | * - always set up to produce at least two attributes: | ||
202 | * if vertex program uses only position, fglrx will set normal, too | ||
203 | * - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal. | ||
204 | */ | ||
205 | #define R300_VAP_INPUT_CNTL_0 0x2180 | ||
206 | # define R300_INPUT_CNTL_0_COLOR 0x00000001 | ||
207 | #define R300_VAP_INPUT_CNTL_1 0x2184 | ||
208 | # define R300_INPUT_CNTL_POS 0x00000001 | ||
209 | # define R300_INPUT_CNTL_NORMAL 0x00000002 | ||
210 | # define R300_INPUT_CNTL_COLOR 0x00000004 | ||
211 | # define R300_INPUT_CNTL_TC0 0x00000400 | ||
212 | # define R300_INPUT_CNTL_TC1 0x00000800 | ||
213 | # define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */ | ||
214 | # define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */ | ||
215 | # define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */ | ||
216 | # define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */ | ||
217 | # define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */ | ||
218 | # define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */ | ||
219 | |||
220 | /* gap */ | ||
221 | |||
222 | /* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0 | ||
223 | * are set to a swizzling bit pattern, other words are 0. | ||
224 | * | ||
225 | * In immediate mode, the pattern is always set to xyzw. In vertex array | ||
226 | * mode, the swizzling pattern is e.g. used to set zw components in texture | ||
227 | * coordinates with only tweo components. | ||
228 | */ | ||
229 | #define R300_VAP_INPUT_ROUTE_1_0 0x21E0 | ||
230 | # define R300_INPUT_ROUTE_SELECT_X 0 | ||
231 | # define R300_INPUT_ROUTE_SELECT_Y 1 | ||
232 | # define R300_INPUT_ROUTE_SELECT_Z 2 | ||
233 | # define R300_INPUT_ROUTE_SELECT_W 3 | ||
234 | # define R300_INPUT_ROUTE_SELECT_ZERO 4 | ||
235 | # define R300_INPUT_ROUTE_SELECT_ONE 5 | ||
236 | # define R300_INPUT_ROUTE_SELECT_MASK 7 | ||
237 | # define R300_INPUT_ROUTE_X_SHIFT 0 | ||
238 | # define R300_INPUT_ROUTE_Y_SHIFT 3 | ||
239 | # define R300_INPUT_ROUTE_Z_SHIFT 6 | ||
240 | # define R300_INPUT_ROUTE_W_SHIFT 9 | ||
241 | # define R300_INPUT_ROUTE_ENABLE (15 << 12) | ||
242 | #define R300_VAP_INPUT_ROUTE_1_1 0x21E4 | ||
243 | #define R300_VAP_INPUT_ROUTE_1_2 0x21E8 | ||
244 | #define R300_VAP_INPUT_ROUTE_1_3 0x21EC | ||
245 | #define R300_VAP_INPUT_ROUTE_1_4 0x21F0 | ||
246 | #define R300_VAP_INPUT_ROUTE_1_5 0x21F4 | ||
247 | #define R300_VAP_INPUT_ROUTE_1_6 0x21F8 | ||
248 | #define R300_VAP_INPUT_ROUTE_1_7 0x21FC | ||
249 | |||
250 | /* END: Vertex data assembly */ | ||
251 | |||
252 | /* gap */ | ||
253 | |||
254 | /* BEGIN: Upload vertex program and data */ | ||
255 | |||
256 | /* | ||
257 | * The programmable vertex shader unit has a memory bank of unknown size | ||
258 | * that can be written to in 16 byte units by writing the address into | ||
259 | * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs). | ||
260 | * | ||
261 | * Pointers into the memory bank are always in multiples of 16 bytes. | ||
262 | * | ||
263 | * The memory bank is divided into areas with fixed meaning. | ||
264 | * | ||
265 | * Starting at address UPLOAD_PROGRAM: Vertex program instructions. | ||
266 | * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB), | ||
267 | * whereas the difference between known addresses suggests size 512. | ||
268 | * | ||
269 | * Starting at address UPLOAD_PARAMETERS: Vertex program parameters. | ||
270 | * Native reported limits and the VPI layout suggest size 256, whereas | ||
271 | * difference between known addresses suggests size 512. | ||
272 | * | ||
273 | * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the | ||
274 | * floating point pointsize. The exact purpose of this state is uncertain, | ||
275 | * as there is also the R300_RE_POINTSIZE register. | ||
276 | * | ||
277 | * Multiple vertex programs and parameter sets can be loaded at once, | ||
278 | * which could explain the size discrepancy. | ||
279 | */ | ||
280 | #define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200 | ||
281 | # define R300_PVS_UPLOAD_PROGRAM 0x00000000 | ||
282 | # define R300_PVS_UPLOAD_PARAMETERS 0x00000200 | ||
283 | # define R300_PVS_UPLOAD_POINTSIZE 0x00000406 | ||
284 | |||
285 | /* gap */ | ||
286 | |||
287 | #define R300_VAP_PVS_UPLOAD_DATA 0x2208 | ||
288 | |||
289 | /* END: Upload vertex program and data */ | ||
290 | |||
291 | /* gap */ | ||
292 | |||
293 | /* I do not know the purpose of this register. However, I do know that | ||
294 | * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL | ||
295 | * for normal rendering. | ||
296 | */ | ||
297 | #define R300_VAP_UNKNOWN_221C 0x221C | ||
298 | # define R300_221C_NORMAL 0x00000000 | ||
299 | # define R300_221C_CLEAR 0x0001C000 | ||
300 | |||
301 | /* These seem to be per-pixel and per-vertex X and Y clipping planes. The first | ||
302 | * plane is per-pixel and the second plane is per-vertex. | ||
303 | * | ||
304 | * This was determined by experimentation alone but I believe it is correct. | ||
305 | * | ||
306 | * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest. | ||
307 | */ | ||
308 | #define R300_VAP_CLIP_X_0 0x2220 | ||
309 | #define R300_VAP_CLIP_X_1 0x2224 | ||
310 | #define R300_VAP_CLIP_Y_0 0x2228 | ||
311 | #define R300_VAP_CLIP_Y_1 0x2230 | ||
312 | |||
313 | /* gap */ | ||
314 | |||
315 | /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between | ||
316 | * rendering commands and overwriting vertex program parameters. | ||
317 | * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and | ||
318 | * avoids bugs caused by still running shaders reading bad data from memory. | ||
319 | */ | ||
320 | #define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */ | ||
321 | |||
322 | /* Absolutely no clue what this register is about. */ | ||
323 | #define R300_VAP_UNKNOWN_2288 0x2288 | ||
324 | # define R300_2288_R300 0x00750000 /* -- nh */ | ||
325 | # define R300_2288_RV350 0x0000FFFF /* -- Vladimir */ | ||
326 | |||
327 | /* gap */ | ||
328 | |||
329 | /* Addresses are relative to the vertex program instruction area of the | ||
330 | * memory bank. PROGRAM_END points to the last instruction of the active | ||
331 | * program | ||
332 | * | ||
333 | * The meaning of the two UNKNOWN fields is obviously not known. However, | ||
334 | * experiments so far have shown that both *must* point to an instruction | ||
335 | * inside the vertex program, otherwise the GPU locks up. | ||
336 | * | ||
337 | * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and | ||
338 | * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to | ||
339 | * position takes place. | ||
340 | * | ||
341 | * Most likely this is used to ignore rest of the program in cases | ||
342 | * where group of verts arent visible. For some reason this "section" | ||
343 | * is sometimes accepted other instruction that have no relationship with | ||
344 | * position calculations. | ||
345 | */ | ||
346 | #define R300_VAP_PVS_CNTL_1 0x22D0 | ||
347 | # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 | ||
348 | # define R300_PVS_CNTL_1_POS_END_SHIFT 10 | ||
349 | # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 | ||
350 | /* Addresses are relative the the vertex program parameters area. */ | ||
351 | #define R300_VAP_PVS_CNTL_2 0x22D4 | ||
352 | # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 | ||
353 | # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 | ||
354 | #define R300_VAP_PVS_CNTL_3 0x22D8 | ||
355 | # define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10 | ||
356 | # define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0 | ||
357 | |||
358 | /* The entire range from 0x2300 to 0x2AC inclusive seems to be used for | ||
359 | * immediate vertices | ||
360 | */ | ||
361 | #define R300_VAP_VTX_COLOR_R 0x2464 | ||
362 | #define R300_VAP_VTX_COLOR_G 0x2468 | ||
363 | #define R300_VAP_VTX_COLOR_B 0x246C | ||
364 | #define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */ | ||
365 | #define R300_VAP_VTX_POS_0_Y_1 0x2494 | ||
366 | #define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */ | ||
367 | #define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */ | ||
368 | #define R300_VAP_VTX_POS_0_Y_2 0x24A4 | ||
369 | #define R300_VAP_VTX_POS_0_Z_2 0x24A8 | ||
370 | /* write 0 to indicate end of packet? */ | ||
371 | #define R300_VAP_VTX_END_OF_PKT 0x24AC | ||
372 | |||
373 | /* gap */ | ||
374 | |||
375 | /* These are values from r300_reg/r300_reg.h - they are known to be correct | ||
376 | * and are here so we can use one register file instead of several | ||
377 | * - Vladimir | ||
378 | */ | ||
379 | #define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000 | ||
380 | # define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0) | ||
381 | # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1) | ||
382 | # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2) | ||
383 | # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3) | ||
384 | # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4) | ||
385 | # define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5) | ||
386 | # define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16) | ||
387 | |||
388 | #define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004 | ||
389 | /* each of the following is 3 bits wide, specifies number | ||
390 | of components */ | ||
391 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 | ||
392 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 | ||
393 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 | ||
394 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9 | ||
395 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12 | ||
396 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15 | ||
397 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18 | ||
398 | # define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21 | ||
399 | |||
400 | /* UNK30 seems to enables point to quad transformation on textures | ||
401 | * (or something closely related to that). | ||
402 | * This bit is rather fatal at the time being due to lackings at pixel | ||
403 | * shader side | ||
404 | */ | ||
405 | #define R300_GB_ENABLE 0x4008 | ||
406 | # define R300_GB_POINT_STUFF_ENABLE (1<<0) | ||
407 | # define R300_GB_LINE_STUFF_ENABLE (1<<1) | ||
408 | # define R300_GB_TRIANGLE_STUFF_ENABLE (1<<2) | ||
409 | # define R300_GB_STENCIL_AUTO_ENABLE (1<<4) | ||
410 | # define R300_GB_UNK31 (1<<31) | ||
411 | /* each of the following is 2 bits wide */ | ||
412 | #define R300_GB_TEX_REPLICATE 0 | ||
413 | #define R300_GB_TEX_ST 1 | ||
414 | #define R300_GB_TEX_STR 2 | ||
415 | # define R300_GB_TEX0_SOURCE_SHIFT 16 | ||
416 | # define R300_GB_TEX1_SOURCE_SHIFT 18 | ||
417 | # define R300_GB_TEX2_SOURCE_SHIFT 20 | ||
418 | # define R300_GB_TEX3_SOURCE_SHIFT 22 | ||
419 | # define R300_GB_TEX4_SOURCE_SHIFT 24 | ||
420 | # define R300_GB_TEX5_SOURCE_SHIFT 26 | ||
421 | # define R300_GB_TEX6_SOURCE_SHIFT 28 | ||
422 | # define R300_GB_TEX7_SOURCE_SHIFT 30 | ||
423 | |||
424 | /* MSPOS - positions for multisample antialiasing (?) */ | ||
425 | #define R300_GB_MSPOS0 0x4010 | ||
426 | /* shifts - each of the fields is 4 bits */ | ||
427 | # define R300_GB_MSPOS0__MS_X0_SHIFT 0 | ||
428 | # define R300_GB_MSPOS0__MS_Y0_SHIFT 4 | ||
429 | # define R300_GB_MSPOS0__MS_X1_SHIFT 8 | ||
430 | # define R300_GB_MSPOS0__MS_Y1_SHIFT 12 | ||
431 | # define R300_GB_MSPOS0__MS_X2_SHIFT 16 | ||
432 | # define R300_GB_MSPOS0__MS_Y2_SHIFT 20 | ||
433 | # define R300_GB_MSPOS0__MSBD0_Y 24 | ||
434 | # define R300_GB_MSPOS0__MSBD0_X 28 | ||
435 | |||
436 | #define R300_GB_MSPOS1 0x4014 | ||
437 | # define R300_GB_MSPOS1__MS_X3_SHIFT 0 | ||
438 | # define R300_GB_MSPOS1__MS_Y3_SHIFT 4 | ||
439 | # define R300_GB_MSPOS1__MS_X4_SHIFT 8 | ||
440 | # define R300_GB_MSPOS1__MS_Y4_SHIFT 12 | ||
441 | # define R300_GB_MSPOS1__MS_X5_SHIFT 16 | ||
442 | # define R300_GB_MSPOS1__MS_Y5_SHIFT 20 | ||
443 | # define R300_GB_MSPOS1__MSBD1 24 | ||
444 | |||
445 | |||
446 | #define R300_GB_TILE_CONFIG 0x4018 | ||
447 | # define R300_GB_TILE_ENABLE (1<<0) | ||
448 | # define R300_GB_TILE_PIPE_COUNT_RV300 0 | ||
449 | # define R300_GB_TILE_PIPE_COUNT_R300 (3<<1) | ||
450 | # define R300_GB_TILE_PIPE_COUNT_R420 (7<<1) | ||
451 | # define R300_GB_TILE_PIPE_COUNT_RV410 (3<<1) | ||
452 | # define R300_GB_TILE_SIZE_8 0 | ||
453 | # define R300_GB_TILE_SIZE_16 (1<<4) | ||
454 | # define R300_GB_TILE_SIZE_32 (2<<4) | ||
455 | # define R300_GB_SUPER_SIZE_1 (0<<6) | ||
456 | # define R300_GB_SUPER_SIZE_2 (1<<6) | ||
457 | # define R300_GB_SUPER_SIZE_4 (2<<6) | ||
458 | # define R300_GB_SUPER_SIZE_8 (3<<6) | ||
459 | # define R300_GB_SUPER_SIZE_16 (4<<6) | ||
460 | # define R300_GB_SUPER_SIZE_32 (5<<6) | ||
461 | # define R300_GB_SUPER_SIZE_64 (6<<6) | ||
462 | # define R300_GB_SUPER_SIZE_128 (7<<6) | ||
463 | # define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */ | ||
464 | # define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */ | ||
465 | # define R300_GB_SUPER_TILE_A 0 | ||
466 | # define R300_GB_SUPER_TILE_B (1<<15) | ||
467 | # define R300_GB_SUBPIXEL_1_12 0 | ||
468 | # define R300_GB_SUBPIXEL_1_16 (1<<16) | ||
469 | |||
470 | #define R300_GB_FIFO_SIZE 0x4024 | ||
471 | /* each of the following is 2 bits wide */ | ||
472 | #define R300_GB_FIFO_SIZE_32 0 | ||
473 | #define R300_GB_FIFO_SIZE_64 1 | ||
474 | #define R300_GB_FIFO_SIZE_128 2 | ||
475 | #define R300_GB_FIFO_SIZE_256 3 | ||
476 | # define R300_SC_IFIFO_SIZE_SHIFT 0 | ||
477 | # define R300_SC_TZFIFO_SIZE_SHIFT 2 | ||
478 | # define R300_SC_BFIFO_SIZE_SHIFT 4 | ||
479 | |||
480 | # define R300_US_OFIFO_SIZE_SHIFT 12 | ||
481 | # define R300_US_WFIFO_SIZE_SHIFT 14 | ||
482 | /* the following use the same constants as above, but meaning is | ||
483 | is times 2 (i.e. instead of 32 words it means 64 */ | ||
484 | # define R300_RS_TFIFO_SIZE_SHIFT 6 | ||
485 | # define R300_RS_CFIFO_SIZE_SHIFT 8 | ||
486 | # define R300_US_RAM_SIZE_SHIFT 10 | ||
487 | /* watermarks, 3 bits wide */ | ||
488 | # define R300_RS_HIGHWATER_COL_SHIFT 16 | ||
489 | # define R300_RS_HIGHWATER_TEX_SHIFT 19 | ||
490 | # define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ | ||
491 | # define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 | ||
492 | |||
493 | #define R300_GB_SELECT 0x401C | ||
494 | # define R300_GB_FOG_SELECT_C0A 0 | ||
495 | # define R300_GB_FOG_SELECT_C1A 1 | ||
496 | # define R300_GB_FOG_SELECT_C2A 2 | ||
497 | # define R300_GB_FOG_SELECT_C3A 3 | ||
498 | # define R300_GB_FOG_SELECT_1_1_W 4 | ||
499 | # define R300_GB_FOG_SELECT_Z 5 | ||
500 | # define R300_GB_DEPTH_SELECT_Z 0 | ||
501 | # define R300_GB_DEPTH_SELECT_1_1_W (1<<3) | ||
502 | # define R300_GB_W_SELECT_1_W 0 | ||
503 | # define R300_GB_W_SELECT_1 (1<<4) | ||
504 | |||
505 | #define R300_GB_AA_CONFIG 0x4020 | ||
506 | # define R300_AA_DISABLE 0x00 | ||
507 | # define R300_AA_ENABLE 0x01 | ||
508 | # define R300_AA_SUBSAMPLES_2 0 | ||
509 | # define R300_AA_SUBSAMPLES_3 (1<<1) | ||
510 | # define R300_AA_SUBSAMPLES_4 (2<<1) | ||
511 | # define R300_AA_SUBSAMPLES_6 (3<<1) | ||
512 | |||
513 | /* gap */ | ||
514 | |||
515 | /* Zero to flush caches. */ | ||
516 | #define R300_TX_CNTL 0x4100 | ||
517 | #define R300_TX_FLUSH 0x0 | ||
518 | |||
519 | /* The upper enable bits are guessed, based on fglrx reported limits. */ | ||
520 | #define R300_TX_ENABLE 0x4104 | ||
521 | # define R300_TX_ENABLE_0 (1 << 0) | ||
522 | # define R300_TX_ENABLE_1 (1 << 1) | ||
523 | # define R300_TX_ENABLE_2 (1 << 2) | ||
524 | # define R300_TX_ENABLE_3 (1 << 3) | ||
525 | # define R300_TX_ENABLE_4 (1 << 4) | ||
526 | # define R300_TX_ENABLE_5 (1 << 5) | ||
527 | # define R300_TX_ENABLE_6 (1 << 6) | ||
528 | # define R300_TX_ENABLE_7 (1 << 7) | ||
529 | # define R300_TX_ENABLE_8 (1 << 8) | ||
530 | # define R300_TX_ENABLE_9 (1 << 9) | ||
531 | # define R300_TX_ENABLE_10 (1 << 10) | ||
532 | # define R300_TX_ENABLE_11 (1 << 11) | ||
533 | # define R300_TX_ENABLE_12 (1 << 12) | ||
534 | # define R300_TX_ENABLE_13 (1 << 13) | ||
535 | # define R300_TX_ENABLE_14 (1 << 14) | ||
536 | # define R300_TX_ENABLE_15 (1 << 15) | ||
537 | |||
538 | /* The pointsize is given in multiples of 6. The pointsize can be | ||
539 | * enormous: Clear() renders a single point that fills the entire | ||
540 | * framebuffer. | ||
541 | */ | ||
542 | #define R300_RE_POINTSIZE 0x421C | ||
543 | # define R300_POINTSIZE_Y_SHIFT 0 | ||
544 | # define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */ | ||
545 | # define R300_POINTSIZE_X_SHIFT 16 | ||
546 | # define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */ | ||
547 | # define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6) | ||
548 | |||
549 | /* The line width is given in multiples of 6. | ||
550 | * In default mode lines are classified as vertical lines. | ||
551 | * HO: horizontal | ||
552 | * VE: vertical or horizontal | ||
553 | * HO & VE: no classification | ||
554 | */ | ||
555 | #define R300_RE_LINE_CNT 0x4234 | ||
556 | # define R300_LINESIZE_SHIFT 0 | ||
557 | # define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */ | ||
558 | # define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6) | ||
559 | # define R300_LINE_CNT_HO (1 << 16) | ||
560 | # define R300_LINE_CNT_VE (1 << 17) | ||
561 | |||
562 | /* Some sort of scale or clamp value for texcoordless textures. */ | ||
563 | #define R300_RE_UNK4238 0x4238 | ||
564 | |||
565 | /* Something shade related */ | ||
566 | #define R300_RE_SHADE 0x4274 | ||
567 | |||
568 | #define R300_RE_SHADE_MODEL 0x4278 | ||
569 | # define R300_RE_SHADE_MODEL_SMOOTH 0x3aaaa | ||
570 | # define R300_RE_SHADE_MODEL_FLAT 0x39595 | ||
571 | |||
572 | /* Dangerous */ | ||
573 | #define R300_RE_POLYGON_MODE 0x4288 | ||
574 | # define R300_PM_ENABLED (1 << 0) | ||
575 | # define R300_PM_FRONT_POINT (0 << 0) | ||
576 | # define R300_PM_BACK_POINT (0 << 0) | ||
577 | # define R300_PM_FRONT_LINE (1 << 4) | ||
578 | # define R300_PM_FRONT_FILL (1 << 5) | ||
579 | # define R300_PM_BACK_LINE (1 << 7) | ||
580 | # define R300_PM_BACK_FILL (1 << 8) | ||
581 | |||
582 | /* Fog parameters */ | ||
583 | #define R300_RE_FOG_SCALE 0x4294 | ||
584 | #define R300_RE_FOG_START 0x4298 | ||
585 | |||
586 | /* Not sure why there are duplicate of factor and constant values. | ||
587 | * My best guess so far is that there are separate zbiases for test and write. | ||
588 | * Ordering might be wrong. | ||
589 | * Some of the tests indicate that fgl has a fallback implementation of zbias | ||
590 | * via pixel shaders. | ||
591 | */ | ||
592 | #define R300_RE_ZBIAS_CNTL 0x42A0 /* GUESS */ | ||
593 | #define R300_RE_ZBIAS_T_FACTOR 0x42A4 | ||
594 | #define R300_RE_ZBIAS_T_CONSTANT 0x42A8 | ||
595 | #define R300_RE_ZBIAS_W_FACTOR 0x42AC | ||
596 | #define R300_RE_ZBIAS_W_CONSTANT 0x42B0 | ||
597 | |||
598 | /* This register needs to be set to (1<<1) for RV350 to correctly | ||
599 | * perform depth test (see --vb-triangles in r300_demo) | ||
600 | * Don't know about other chips. - Vladimir | ||
601 | * This is set to 3 when GL_POLYGON_OFFSET_FILL is on. | ||
602 | * My guess is that there are two bits for each zbias primitive | ||
603 | * (FILL, LINE, POINT). | ||
604 | * One to enable depth test and one for depth write. | ||
605 | * Yet this doesnt explain why depth writes work ... | ||
606 | */ | ||
607 | #define R300_RE_OCCLUSION_CNTL 0x42B4 | ||
608 | # define R300_OCCLUSION_ON (1<<1) | ||
609 | |||
610 | #define R300_RE_CULL_CNTL 0x42B8 | ||
611 | # define R300_CULL_FRONT (1 << 0) | ||
612 | # define R300_CULL_BACK (1 << 1) | ||
613 | # define R300_FRONT_FACE_CCW (0 << 2) | ||
614 | # define R300_FRONT_FACE_CW (1 << 2) | ||
615 | |||
616 | |||
617 | /* BEGIN: Rasterization / Interpolators - many guesses */ | ||
618 | |||
619 | /* 0_UNKNOWN_18 has always been set except for clear operations. | ||
620 | * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends | ||
621 | * on the vertex program, *not* the fragment program) | ||
622 | */ | ||
623 | #define R300_RS_CNTL_0 0x4300 | ||
624 | # define R300_RS_CNTL_TC_CNT_SHIFT 2 | ||
625 | # define R300_RS_CNTL_TC_CNT_MASK (7 << 2) | ||
626 | /* number of color interpolators used */ | ||
627 | # define R300_RS_CNTL_CI_CNT_SHIFT 7 | ||
628 | # define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18) | ||
629 | /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n | ||
630 | register. */ | ||
631 | #define R300_RS_CNTL_1 0x4304 | ||
632 | |||
633 | /* gap */ | ||
634 | |||
635 | /* Only used for texture coordinates. | ||
636 | * Use the source field to route texture coordinate input from the | ||
637 | * vertex program to the desired interpolator. Note that the source | ||
638 | * field is relative to the outputs the vertex program *actually* | ||
639 | * writes. If a vertex program only writes texcoord[1], this will | ||
640 | * be source index 0. | ||
641 | * Set INTERP_USED on all interpolators that produce data used by | ||
642 | * the fragment program. INTERP_USED looks like a swizzling mask, | ||
643 | * but I haven't seen it used that way. | ||
644 | * | ||
645 | * Note: The _UNKNOWN constants are always set in their respective | ||
646 | * register. I don't know if this is necessary. | ||
647 | */ | ||
648 | #define R300_RS_INTERP_0 0x4310 | ||
649 | #define R300_RS_INTERP_1 0x4314 | ||
650 | # define R300_RS_INTERP_1_UNKNOWN 0x40 | ||
651 | #define R300_RS_INTERP_2 0x4318 | ||
652 | # define R300_RS_INTERP_2_UNKNOWN 0x80 | ||
653 | #define R300_RS_INTERP_3 0x431C | ||
654 | # define R300_RS_INTERP_3_UNKNOWN 0xC0 | ||
655 | #define R300_RS_INTERP_4 0x4320 | ||
656 | #define R300_RS_INTERP_5 0x4324 | ||
657 | #define R300_RS_INTERP_6 0x4328 | ||
658 | #define R300_RS_INTERP_7 0x432C | ||
659 | # define R300_RS_INTERP_SRC_SHIFT 2 | ||
660 | # define R300_RS_INTERP_SRC_MASK (7 << 2) | ||
661 | # define R300_RS_INTERP_USED 0x00D10000 | ||
662 | |||
663 | /* These DWORDs control how vertex data is routed into fragment program | ||
664 | * registers, after interpolators. | ||
665 | */ | ||
666 | #define R300_RS_ROUTE_0 0x4330 | ||
667 | #define R300_RS_ROUTE_1 0x4334 | ||
668 | #define R300_RS_ROUTE_2 0x4338 | ||
669 | #define R300_RS_ROUTE_3 0x433C /* GUESS */ | ||
670 | #define R300_RS_ROUTE_4 0x4340 /* GUESS */ | ||
671 | #define R300_RS_ROUTE_5 0x4344 /* GUESS */ | ||
672 | #define R300_RS_ROUTE_6 0x4348 /* GUESS */ | ||
673 | #define R300_RS_ROUTE_7 0x434C /* GUESS */ | ||
674 | # define R300_RS_ROUTE_SOURCE_INTERP_0 0 | ||
675 | # define R300_RS_ROUTE_SOURCE_INTERP_1 1 | ||
676 | # define R300_RS_ROUTE_SOURCE_INTERP_2 2 | ||
677 | # define R300_RS_ROUTE_SOURCE_INTERP_3 3 | ||
678 | # define R300_RS_ROUTE_SOURCE_INTERP_4 4 | ||
679 | # define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */ | ||
680 | # define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */ | ||
681 | # define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */ | ||
682 | # define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */ | ||
683 | # define R300_RS_ROUTE_DEST_SHIFT 6 | ||
684 | # define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */ | ||
685 | |||
686 | /* Special handling for color: When the fragment program uses color, | ||
687 | * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the | ||
688 | * color register index. | ||
689 | * | ||
690 | * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any | ||
691 | * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state. | ||
692 | * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly | ||
693 | * correct or not. - Oliver. | ||
694 | */ | ||
695 | # define R300_RS_ROUTE_0_COLOR (1 << 14) | ||
696 | # define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17 | ||
697 | # define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */ | ||
698 | /* As above, but for secondary color */ | ||
699 | # define R300_RS_ROUTE_1_COLOR1 (1 << 14) | ||
700 | # define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17 | ||
701 | # define R300_RS_ROUTE_1_COLOR1_DEST_MASK (31 << 17) | ||
702 | # define R300_RS_ROUTE_1_UNKNOWN11 (1 << 11) | ||
703 | /* END: Rasterization / Interpolators - many guesses */ | ||
704 | |||
705 | /* Hierarchical Z Enable */ | ||
706 | #define R300_SC_HYPERZ 0x43a4 | ||
707 | # define R300_SC_HYPERZ_DISABLE (0 << 0) | ||
708 | # define R300_SC_HYPERZ_ENABLE (1 << 0) | ||
709 | # define R300_SC_HYPERZ_MIN (0 << 1) | ||
710 | # define R300_SC_HYPERZ_MAX (1 << 1) | ||
711 | # define R300_SC_HYPERZ_ADJ_256 (0 << 2) | ||
712 | # define R300_SC_HYPERZ_ADJ_128 (1 << 2) | ||
713 | # define R300_SC_HYPERZ_ADJ_64 (2 << 2) | ||
714 | # define R300_SC_HYPERZ_ADJ_32 (3 << 2) | ||
715 | # define R300_SC_HYPERZ_ADJ_16 (4 << 2) | ||
716 | # define R300_SC_HYPERZ_ADJ_8 (5 << 2) | ||
717 | # define R300_SC_HYPERZ_ADJ_4 (6 << 2) | ||
718 | # define R300_SC_HYPERZ_ADJ_2 (7 << 2) | ||
719 | # define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5) | ||
720 | # define R300_SC_HYPERZ_HZ_Z0MIN (1 << 5) | ||
721 | # define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6) | ||
722 | # define R300_SC_HYPERZ_HZ_Z0MAX (1 << 6) | ||
723 | |||
724 | #define R300_SC_EDGERULE 0x43a8 | ||
725 | |||
726 | /* BEGIN: Scissors and cliprects */ | ||
727 | |||
728 | /* There are four clipping rectangles. Their corner coordinates are inclusive. | ||
729 | * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending | ||
730 | * on whether the pixel is inside cliprects 0-3, respectively. For example, | ||
731 | * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned | ||
732 | * the number 3 (binary 0011). | ||
733 | * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set, | ||
734 | * the pixel is rasterized. | ||
735 | * | ||
736 | * In addition to this, there is a scissors rectangle. Only pixels inside the | ||
737 | * scissors rectangle are drawn. (coordinates are inclusive) | ||
738 | * | ||
739 | * For some reason, the top-left corner of the framebuffer is at (1440, 1440) | ||
740 | * for the purpose of clipping and scissors. | ||
741 | */ | ||
742 | #define R300_RE_CLIPRECT_TL_0 0x43B0 | ||
743 | #define R300_RE_CLIPRECT_BR_0 0x43B4 | ||
744 | #define R300_RE_CLIPRECT_TL_1 0x43B8 | ||
745 | #define R300_RE_CLIPRECT_BR_1 0x43BC | ||
746 | #define R300_RE_CLIPRECT_TL_2 0x43C0 | ||
747 | #define R300_RE_CLIPRECT_BR_2 0x43C4 | ||
748 | #define R300_RE_CLIPRECT_TL_3 0x43C8 | ||
749 | #define R300_RE_CLIPRECT_BR_3 0x43CC | ||
750 | # define R300_CLIPRECT_OFFSET 1440 | ||
751 | # define R300_CLIPRECT_MASK 0x1FFF | ||
752 | # define R300_CLIPRECT_X_SHIFT 0 | ||
753 | # define R300_CLIPRECT_X_MASK (0x1FFF << 0) | ||
754 | # define R300_CLIPRECT_Y_SHIFT 13 | ||
755 | # define R300_CLIPRECT_Y_MASK (0x1FFF << 13) | ||
756 | #define R300_RE_CLIPRECT_CNTL 0x43D0 | ||
757 | # define R300_CLIP_OUT (1 << 0) | ||
758 | # define R300_CLIP_0 (1 << 1) | ||
759 | # define R300_CLIP_1 (1 << 2) | ||
760 | # define R300_CLIP_10 (1 << 3) | ||
761 | # define R300_CLIP_2 (1 << 4) | ||
762 | # define R300_CLIP_20 (1 << 5) | ||
763 | # define R300_CLIP_21 (1 << 6) | ||
764 | # define R300_CLIP_210 (1 << 7) | ||
765 | # define R300_CLIP_3 (1 << 8) | ||
766 | # define R300_CLIP_30 (1 << 9) | ||
767 | # define R300_CLIP_31 (1 << 10) | ||
768 | # define R300_CLIP_310 (1 << 11) | ||
769 | # define R300_CLIP_32 (1 << 12) | ||
770 | # define R300_CLIP_320 (1 << 13) | ||
771 | # define R300_CLIP_321 (1 << 14) | ||
772 | # define R300_CLIP_3210 (1 << 15) | ||
773 | |||
774 | /* gap */ | ||
775 | |||
776 | #define R300_RE_SCISSORS_TL 0x43E0 | ||
777 | #define R300_RE_SCISSORS_BR 0x43E4 | ||
778 | # define R300_SCISSORS_OFFSET 1440 | ||
779 | # define R300_SCISSORS_X_SHIFT 0 | ||
780 | # define R300_SCISSORS_X_MASK (0x1FFF << 0) | ||
781 | # define R300_SCISSORS_Y_SHIFT 13 | ||
782 | # define R300_SCISSORS_Y_MASK (0x1FFF << 13) | ||
783 | /* END: Scissors and cliprects */ | ||
784 | |||
785 | /* BEGIN: Texture specification */ | ||
786 | |||
787 | /* | ||
788 | * The texture specification dwords are grouped by meaning and not by texture | ||
789 | * unit. This means that e.g. the offset for texture image unit N is found in | ||
790 | * register TX_OFFSET_0 + (4*N) | ||
791 | */ | ||
792 | #define R300_TX_FILTER_0 0x4400 | ||
793 | # define R300_TX_REPEAT 0 | ||
794 | # define R300_TX_MIRRORED 1 | ||
795 | # define R300_TX_CLAMP 4 | ||
796 | # define R300_TX_CLAMP_TO_EDGE 2 | ||
797 | # define R300_TX_CLAMP_TO_BORDER 6 | ||
798 | # define R300_TX_WRAP_S_SHIFT 0 | ||
799 | # define R300_TX_WRAP_S_MASK (7 << 0) | ||
800 | # define R300_TX_WRAP_T_SHIFT 3 | ||
801 | # define R300_TX_WRAP_T_MASK (7 << 3) | ||
802 | # define R300_TX_WRAP_Q_SHIFT 6 | ||
803 | # define R300_TX_WRAP_Q_MASK (7 << 6) | ||
804 | # define R300_TX_MAG_FILTER_NEAREST (1 << 9) | ||
805 | # define R300_TX_MAG_FILTER_LINEAR (2 << 9) | ||
806 | # define R300_TX_MAG_FILTER_MASK (3 << 9) | ||
807 | # define R300_TX_MIN_FILTER_NEAREST (1 << 11) | ||
808 | # define R300_TX_MIN_FILTER_LINEAR (2 << 11) | ||
809 | # define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST (5 << 11) | ||
810 | # define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR (9 << 11) | ||
811 | # define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 11) | ||
812 | # define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR (10 << 11) | ||
813 | |||
814 | /* NOTE: NEAREST doesnt seem to exist. | ||
815 | * Im not seting MAG_FILTER_MASK and (3 << 11) on for all | ||
816 | * anisotropy modes because that would void selected mag filter | ||
817 | */ | ||
818 | # define R300_TX_MIN_FILTER_ANISO_NEAREST (0 << 13) | ||
819 | # define R300_TX_MIN_FILTER_ANISO_LINEAR (0 << 13) | ||
820 | # define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13) | ||
821 | # define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (2 << 13) | ||
822 | # define R300_TX_MIN_FILTER_MASK ( (15 << 11) | (3 << 13) ) | ||
823 | # define R300_TX_MAX_ANISO_1_TO_1 (0 << 21) | ||
824 | # define R300_TX_MAX_ANISO_2_TO_1 (2 << 21) | ||
825 | # define R300_TX_MAX_ANISO_4_TO_1 (4 << 21) | ||
826 | # define R300_TX_MAX_ANISO_8_TO_1 (6 << 21) | ||
827 | # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) | ||
828 | # define R300_TX_MAX_ANISO_MASK (14 << 21) | ||
829 | |||
830 | #define R300_TX_FILTER1_0 0x4440 | ||
831 | # define R300_CHROMA_KEY_MODE_DISABLE 0 | ||
832 | # define R300_CHROMA_KEY_FORCE 1 | ||
833 | # define R300_CHROMA_KEY_BLEND 2 | ||
834 | # define R300_MC_ROUND_NORMAL (0<<2) | ||
835 | # define R300_MC_ROUND_MPEG4 (1<<2) | ||
836 | # define R300_LOD_BIAS_MASK 0x1fff | ||
837 | # define R300_EDGE_ANISO_EDGE_DIAG (0<<13) | ||
838 | # define R300_EDGE_ANISO_EDGE_ONLY (1<<13) | ||
839 | # define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) | ||
840 | # define R300_MC_COORD_TRUNCATE_MPEG (1<<14) | ||
841 | # define R300_TX_TRI_PERF_0_8 (0<<15) | ||
842 | # define R300_TX_TRI_PERF_1_8 (1<<15) | ||
843 | # define R300_TX_TRI_PERF_1_4 (2<<15) | ||
844 | # define R300_TX_TRI_PERF_3_8 (3<<15) | ||
845 | # define R300_ANISO_THRESHOLD_MASK (7<<17) | ||
846 | |||
847 | #define R300_TX_SIZE_0 0x4480 | ||
848 | # define R300_TX_WIDTHMASK_SHIFT 0 | ||
849 | # define R300_TX_WIDTHMASK_MASK (2047 << 0) | ||
850 | # define R300_TX_HEIGHTMASK_SHIFT 11 | ||
851 | # define R300_TX_HEIGHTMASK_MASK (2047 << 11) | ||
852 | # define R300_TX_UNK23 (1 << 23) | ||
853 | # define R300_TX_MAX_MIP_LEVEL_SHIFT 26 | ||
854 | # define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26) | ||
855 | # define R300_TX_SIZE_PROJECTED (1<<30) | ||
856 | # define R300_TX_SIZE_TXPITCH_EN (1<<31) | ||
857 | #define R300_TX_FORMAT_0 0x44C0 | ||
858 | /* The interpretation of the format word by Wladimir van der Laan */ | ||
859 | /* The X, Y, Z and W refer to the layout of the components. | ||
860 | They are given meanings as R, G, B and Alpha by the swizzle | ||
861 | specification */ | ||
862 | # define R300_TX_FORMAT_X8 0x0 | ||
863 | # define R300_TX_FORMAT_X16 0x1 | ||
864 | # define R300_TX_FORMAT_Y4X4 0x2 | ||
865 | # define R300_TX_FORMAT_Y8X8 0x3 | ||
866 | # define R300_TX_FORMAT_Y16X16 0x4 | ||
867 | # define R300_TX_FORMAT_Z3Y3X2 0x5 | ||
868 | # define R300_TX_FORMAT_Z5Y6X5 0x6 | ||
869 | # define R300_TX_FORMAT_Z6Y5X5 0x7 | ||
870 | # define R300_TX_FORMAT_Z11Y11X10 0x8 | ||
871 | # define R300_TX_FORMAT_Z10Y11X11 0x9 | ||
872 | # define R300_TX_FORMAT_W4Z4Y4X4 0xA | ||
873 | # define R300_TX_FORMAT_W1Z5Y5X5 0xB | ||
874 | # define R300_TX_FORMAT_W8Z8Y8X8 0xC | ||
875 | # define R300_TX_FORMAT_W2Z10Y10X10 0xD | ||
876 | # define R300_TX_FORMAT_W16Z16Y16X16 0xE | ||
877 | # define R300_TX_FORMAT_DXT1 0xF | ||
878 | # define R300_TX_FORMAT_DXT3 0x10 | ||
879 | # define R300_TX_FORMAT_DXT5 0x11 | ||
880 | # define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ | ||
881 | # define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ | ||
882 | # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ | ||
883 | # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ | ||
884 | /* 0x16 - some 16 bit green format.. ?? */ | ||
885 | # define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ | ||
886 | # define R300_TX_FORMAT_CUBIC_MAP (1 << 26) | ||
887 | |||
888 | /* gap */ | ||
889 | /* Floating point formats */ | ||
890 | /* Note - hardware supports both 16 and 32 bit floating point */ | ||
891 | # define R300_TX_FORMAT_FL_I16 0x18 | ||
892 | # define R300_TX_FORMAT_FL_I16A16 0x19 | ||
893 | # define R300_TX_FORMAT_FL_R16G16B16A16 0x1A | ||
894 | # define R300_TX_FORMAT_FL_I32 0x1B | ||
895 | # define R300_TX_FORMAT_FL_I32A32 0x1C | ||
896 | # define R300_TX_FORMAT_FL_R32G32B32A32 0x1D | ||
897 | /* alpha modes, convenience mostly */ | ||
898 | /* if you have alpha, pick constant appropriate to the | ||
899 | number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ | ||
900 | # define R300_TX_FORMAT_ALPHA_1CH 0x000 | ||
901 | # define R300_TX_FORMAT_ALPHA_2CH 0x200 | ||
902 | # define R300_TX_FORMAT_ALPHA_4CH 0x600 | ||
903 | # define R300_TX_FORMAT_ALPHA_NONE 0xA00 | ||
904 | /* Swizzling */ | ||
905 | /* constants */ | ||
906 | # define R300_TX_FORMAT_X 0 | ||
907 | # define R300_TX_FORMAT_Y 1 | ||
908 | # define R300_TX_FORMAT_Z 2 | ||
909 | # define R300_TX_FORMAT_W 3 | ||
910 | # define R300_TX_FORMAT_ZERO 4 | ||
911 | # define R300_TX_FORMAT_ONE 5 | ||
912 | /* 2.0*Z, everything above 1.0 is set to 0.0 */ | ||
913 | # define R300_TX_FORMAT_CUT_Z 6 | ||
914 | /* 2.0*W, everything above 1.0 is set to 0.0 */ | ||
915 | # define R300_TX_FORMAT_CUT_W 7 | ||
916 | |||
917 | # define R300_TX_FORMAT_B_SHIFT 18 | ||
918 | # define R300_TX_FORMAT_G_SHIFT 15 | ||
919 | # define R300_TX_FORMAT_R_SHIFT 12 | ||
920 | # define R300_TX_FORMAT_A_SHIFT 9 | ||
921 | /* Convenience macro to take care of layout and swizzling */ | ||
922 | # define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \ | ||
923 | ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \ | ||
924 | | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \ | ||
925 | | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \ | ||
926 | | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \ | ||
927 | | (R300_TX_FORMAT_##FMT) \ | ||
928 | ) | ||
929 | /* These can be ORed with result of R300_EASY_TX_FORMAT() | ||
930 | We don't really know what they do. Take values from a | ||
931 | constant color ? */ | ||
932 | # define R300_TX_FORMAT_CONST_X (1<<5) | ||
933 | # define R300_TX_FORMAT_CONST_Y (2<<5) | ||
934 | # define R300_TX_FORMAT_CONST_Z (4<<5) | ||
935 | # define R300_TX_FORMAT_CONST_W (8<<5) | ||
936 | |||
937 | # define R300_TX_FORMAT_YUV_MODE 0x00800000 | ||
938 | |||
939 | #define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */ | ||
940 | #define R300_TX_OFFSET_0 0x4540 | ||
941 | /* BEGIN: Guess from R200 */ | ||
942 | # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) | ||
943 | # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) | ||
944 | # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) | ||
945 | # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) | ||
946 | # define R300_TXO_MACRO_TILE (1 << 2) | ||
947 | # define R300_TXO_MICRO_TILE (1 << 3) | ||
948 | # define R300_TXO_OFFSET_MASK 0xffffffe0 | ||
949 | # define R300_TXO_OFFSET_SHIFT 5 | ||
950 | /* END: Guess from R200 */ | ||
951 | |||
952 | /* 32 bit chroma key */ | ||
953 | #define R300_TX_CHROMA_KEY_0 0x4580 | ||
954 | /* ff00ff00 == { 0, 1.0, 0, 1.0 } */ | ||
955 | #define R300_TX_BORDER_COLOR_0 0x45C0 | ||
956 | |||
957 | /* END: Texture specification */ | ||
958 | |||
959 | /* BEGIN: Fragment program instruction set */ | ||
960 | |||
961 | /* Fragment programs are written directly into register space. | ||
962 | * There are separate instruction streams for texture instructions and ALU | ||
963 | * instructions. | ||
964 | * In order to synchronize these streams, the program is divided into up | ||
965 | * to 4 nodes. Each node begins with a number of TEX operations, followed | ||
966 | * by a number of ALU operations. | ||
967 | * The first node can have zero TEX ops, all subsequent nodes must have at | ||
968 | * least | ||
969 | * one TEX ops. | ||
970 | * All nodes must have at least one ALU op. | ||
971 | * | ||
972 | * The index of the last node is stored in PFS_CNTL_0: A value of 0 means | ||
973 | * 1 node, a value of 3 means 4 nodes. | ||
974 | * The total amount of instructions is defined in PFS_CNTL_2. The offsets are | ||
975 | * offsets into the respective instruction streams, while *_END points to the | ||
976 | * last instruction relative to this offset. | ||
977 | */ | ||
978 | #define R300_PFS_CNTL_0 0x4600 | ||
979 | # define R300_PFS_CNTL_LAST_NODES_SHIFT 0 | ||
980 | # define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0) | ||
981 | # define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3) | ||
982 | #define R300_PFS_CNTL_1 0x4604 | ||
983 | /* There is an unshifted value here which has so far always been equal to the | ||
984 | * index of the highest used temporary register. | ||
985 | */ | ||
986 | #define R300_PFS_CNTL_2 0x4608 | ||
987 | # define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0 | ||
988 | # define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0) | ||
989 | # define R300_PFS_CNTL_ALU_END_SHIFT 6 | ||
990 | # define R300_PFS_CNTL_ALU_END_MASK (63 << 6) | ||
991 | # define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12 | ||
992 | # define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */ | ||
993 | # define R300_PFS_CNTL_TEX_END_SHIFT 18 | ||
994 | # define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */ | ||
995 | |||
996 | /* gap */ | ||
997 | |||
998 | /* Nodes are stored backwards. The last active node is always stored in | ||
999 | * PFS_NODE_3. | ||
1000 | * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The | ||
1001 | * first node is stored in NODE_2, the second node is stored in NODE_3. | ||
1002 | * | ||
1003 | * Offsets are relative to the master offset from PFS_CNTL_2. | ||
1004 | */ | ||
1005 | #define R300_PFS_NODE_0 0x4610 | ||
1006 | #define R300_PFS_NODE_1 0x4614 | ||
1007 | #define R300_PFS_NODE_2 0x4618 | ||
1008 | #define R300_PFS_NODE_3 0x461C | ||
1009 | # define R300_PFS_NODE_ALU_OFFSET_SHIFT 0 | ||
1010 | # define R300_PFS_NODE_ALU_OFFSET_MASK (63 << 0) | ||
1011 | # define R300_PFS_NODE_ALU_END_SHIFT 6 | ||
1012 | # define R300_PFS_NODE_ALU_END_MASK (63 << 6) | ||
1013 | # define R300_PFS_NODE_TEX_OFFSET_SHIFT 12 | ||
1014 | # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) | ||
1015 | # define R300_PFS_NODE_TEX_END_SHIFT 17 | ||
1016 | # define R300_PFS_NODE_TEX_END_MASK (31 << 17) | ||
1017 | # define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) | ||
1018 | # define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) | ||
1019 | |||
1020 | /* TEX | ||
1021 | * As far as I can tell, texture instructions cannot write into output | ||
1022 | * registers directly. A subsequent ALU instruction is always necessary, | ||
1023 | * even if it's just MAD o0, r0, 1, 0 | ||
1024 | */ | ||
1025 | #define R300_PFS_TEXI_0 0x4620 | ||
1026 | # define R300_FPITX_SRC_SHIFT 0 | ||
1027 | # define R300_FPITX_SRC_MASK (31 << 0) | ||
1028 | /* GUESS */ | ||
1029 | # define R300_FPITX_SRC_CONST (1 << 5) | ||
1030 | # define R300_FPITX_DST_SHIFT 6 | ||
1031 | # define R300_FPITX_DST_MASK (31 << 6) | ||
1032 | # define R300_FPITX_IMAGE_SHIFT 11 | ||
1033 | /* GUESS based on layout and native limits */ | ||
1034 | # define R300_FPITX_IMAGE_MASK (15 << 11) | ||
1035 | /* Unsure if these are opcodes, or some kind of bitfield, but this is how | ||
1036 | * they were set when I checked | ||
1037 | */ | ||
1038 | # define R300_FPITX_OPCODE_SHIFT 15 | ||
1039 | # define R300_FPITX_OP_TEX 1 | ||
1040 | # define R300_FPITX_OP_KIL 2 | ||
1041 | # define R300_FPITX_OP_TXP 3 | ||
1042 | # define R300_FPITX_OP_TXB 4 | ||
1043 | # define R300_FPITX_OPCODE_MASK (7 << 15) | ||
1044 | |||
1045 | /* ALU | ||
1046 | * The ALU instructions register blocks are enumerated according to the order | ||
1047 | * in which fglrx. I assume there is space for 64 instructions, since | ||
1048 | * each block has space for a maximum of 64 DWORDs, and this matches reported | ||
1049 | * native limits. | ||
1050 | * | ||
1051 | * The basic functional block seems to be one MAD for each color and alpha, | ||
1052 | * and an adder that adds all components after the MUL. | ||
1053 | * - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands | ||
1054 | * - DP4: Use OUTC_DP4, OUTA_DP4 | ||
1055 | * - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands | ||
1056 | * - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands | ||
1057 | * - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1 | ||
1058 | * - CMP: If ARG2 < 0, return ARG1, else return ARG0 | ||
1059 | * - FLR: use FRC+MAD | ||
1060 | * - XPD: use MAD+MAD | ||
1061 | * - SGE, SLT: use MAD+CMP | ||
1062 | * - RSQ: use ABS modifier for argument | ||
1063 | * - Use OUTC_REPL_ALPHA to write results of an alpha-only operation | ||
1064 | * (e.g. RCP) into color register | ||
1065 | * - apparently, there's no quick DST operation | ||
1066 | * - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2" | ||
1067 | * - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0" | ||
1068 | * - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1" | ||
1069 | * | ||
1070 | * Operand selection | ||
1071 | * First stage selects three sources from the available registers and | ||
1072 | * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha). | ||
1073 | * fglrx sorts the three source fields: Registers before constants, | ||
1074 | * lower indices before higher indices; I do not know whether this is | ||
1075 | * necessary. | ||
1076 | * | ||
1077 | * fglrx fills unused sources with "read constant 0" | ||
1078 | * According to specs, you cannot select more than two different constants. | ||
1079 | * | ||
1080 | * Second stage selects the operands from the sources. This is defined in | ||
1081 | * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants | ||
1082 | * zero and one. | ||
1083 | * Swizzling and negation happens in this stage, as well. | ||
1084 | * | ||
1085 | * Important: Color and alpha seem to be mostly separate, i.e. their sources | ||
1086 | * selection appears to be fully independent (the register storage is probably | ||
1087 | * physically split into a color and an alpha section). | ||
1088 | * However (because of the apparent physical split), there is some interaction | ||
1089 | * WRT swizzling. If, for example, you want to load an R component into an | ||
1090 | * Alpha operand, this R component is taken from a *color* source, not from | ||
1091 | * an alpha source. The corresponding register doesn't even have to appear in | ||
1092 | * the alpha sources list. (I hope this all makes sense to you) | ||
1093 | * | ||
1094 | * Destination selection | ||
1095 | * The destination register index is in FPI1 (color) and FPI3 (alpha) | ||
1096 | * together with enable bits. | ||
1097 | * There are separate enable bits for writing into temporary registers | ||
1098 | * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_* | ||
1099 | * /DSTA_OUTPUT). You can write to both at once, or not write at all (the | ||
1100 | * same index must be used for both). | ||
1101 | * | ||
1102 | * Note: There is a special form for LRP | ||
1103 | * - Argument order is the same as in ARB_fragment_program. | ||
1104 | * - Operation is MAD | ||
1105 | * - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP | ||
1106 | * - Set FPI0/FPI2_SPECIAL_LRP | ||
1107 | * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD | ||
1108 | */ | ||
1109 | #define R300_PFS_INSTR1_0 0x46C0 | ||
1110 | # define R300_FPI1_SRC0C_SHIFT 0 | ||
1111 | # define R300_FPI1_SRC0C_MASK (31 << 0) | ||
1112 | # define R300_FPI1_SRC0C_CONST (1 << 5) | ||
1113 | # define R300_FPI1_SRC1C_SHIFT 6 | ||
1114 | # define R300_FPI1_SRC1C_MASK (31 << 6) | ||
1115 | # define R300_FPI1_SRC1C_CONST (1 << 11) | ||
1116 | # define R300_FPI1_SRC2C_SHIFT 12 | ||
1117 | # define R300_FPI1_SRC2C_MASK (31 << 12) | ||
1118 | # define R300_FPI1_SRC2C_CONST (1 << 17) | ||
1119 | # define R300_FPI1_SRC_MASK 0x0003ffff | ||
1120 | # define R300_FPI1_DSTC_SHIFT 18 | ||
1121 | # define R300_FPI1_DSTC_MASK (31 << 18) | ||
1122 | # define R300_FPI1_DSTC_REG_MASK_SHIFT 23 | ||
1123 | # define R300_FPI1_DSTC_REG_X (1 << 23) | ||
1124 | # define R300_FPI1_DSTC_REG_Y (1 << 24) | ||
1125 | # define R300_FPI1_DSTC_REG_Z (1 << 25) | ||
1126 | # define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 | ||
1127 | # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) | ||
1128 | # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) | ||
1129 | # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) | ||
1130 | |||
1131 | #define R300_PFS_INSTR3_0 0x47C0 | ||
1132 | # define R300_FPI3_SRC0A_SHIFT 0 | ||
1133 | # define R300_FPI3_SRC0A_MASK (31 << 0) | ||
1134 | # define R300_FPI3_SRC0A_CONST (1 << 5) | ||
1135 | # define R300_FPI3_SRC1A_SHIFT 6 | ||
1136 | # define R300_FPI3_SRC1A_MASK (31 << 6) | ||
1137 | # define R300_FPI3_SRC1A_CONST (1 << 11) | ||
1138 | # define R300_FPI3_SRC2A_SHIFT 12 | ||
1139 | # define R300_FPI3_SRC2A_MASK (31 << 12) | ||
1140 | # define R300_FPI3_SRC2A_CONST (1 << 17) | ||
1141 | # define R300_FPI3_SRC_MASK 0x0003ffff | ||
1142 | # define R300_FPI3_DSTA_SHIFT 18 | ||
1143 | # define R300_FPI3_DSTA_MASK (31 << 18) | ||
1144 | # define R300_FPI3_DSTA_REG (1 << 23) | ||
1145 | # define R300_FPI3_DSTA_OUTPUT (1 << 24) | ||
1146 | # define R300_FPI3_DSTA_DEPTH (1 << 27) | ||
1147 | |||
1148 | #define R300_PFS_INSTR0_0 0x48C0 | ||
1149 | # define R300_FPI0_ARGC_SRC0C_XYZ 0 | ||
1150 | # define R300_FPI0_ARGC_SRC0C_XXX 1 | ||
1151 | # define R300_FPI0_ARGC_SRC0C_YYY 2 | ||
1152 | # define R300_FPI0_ARGC_SRC0C_ZZZ 3 | ||
1153 | # define R300_FPI0_ARGC_SRC1C_XYZ 4 | ||
1154 | # define R300_FPI0_ARGC_SRC1C_XXX 5 | ||
1155 | # define R300_FPI0_ARGC_SRC1C_YYY 6 | ||
1156 | # define R300_FPI0_ARGC_SRC1C_ZZZ 7 | ||
1157 | # define R300_FPI0_ARGC_SRC2C_XYZ 8 | ||
1158 | # define R300_FPI0_ARGC_SRC2C_XXX 9 | ||
1159 | # define R300_FPI0_ARGC_SRC2C_YYY 10 | ||
1160 | # define R300_FPI0_ARGC_SRC2C_ZZZ 11 | ||
1161 | # define R300_FPI0_ARGC_SRC0A 12 | ||
1162 | # define R300_FPI0_ARGC_SRC1A 13 | ||
1163 | # define R300_FPI0_ARGC_SRC2A 14 | ||
1164 | # define R300_FPI0_ARGC_SRC1C_LRP 15 | ||
1165 | # define R300_FPI0_ARGC_ZERO 20 | ||
1166 | # define R300_FPI0_ARGC_ONE 21 | ||
1167 | /* GUESS */ | ||
1168 | # define R300_FPI0_ARGC_HALF 22 | ||
1169 | # define R300_FPI0_ARGC_SRC0C_YZX 23 | ||
1170 | # define R300_FPI0_ARGC_SRC1C_YZX 24 | ||
1171 | # define R300_FPI0_ARGC_SRC2C_YZX 25 | ||
1172 | # define R300_FPI0_ARGC_SRC0C_ZXY 26 | ||
1173 | # define R300_FPI0_ARGC_SRC1C_ZXY 27 | ||
1174 | # define R300_FPI0_ARGC_SRC2C_ZXY 28 | ||
1175 | # define R300_FPI0_ARGC_SRC0CA_WZY 29 | ||
1176 | # define R300_FPI0_ARGC_SRC1CA_WZY 30 | ||
1177 | # define R300_FPI0_ARGC_SRC2CA_WZY 31 | ||
1178 | |||
1179 | # define R300_FPI0_ARG0C_SHIFT 0 | ||
1180 | # define R300_FPI0_ARG0C_MASK (31 << 0) | ||
1181 | # define R300_FPI0_ARG0C_NEG (1 << 5) | ||
1182 | # define R300_FPI0_ARG0C_ABS (1 << 6) | ||
1183 | # define R300_FPI0_ARG1C_SHIFT 7 | ||
1184 | # define R300_FPI0_ARG1C_MASK (31 << 7) | ||
1185 | # define R300_FPI0_ARG1C_NEG (1 << 12) | ||
1186 | # define R300_FPI0_ARG1C_ABS (1 << 13) | ||
1187 | # define R300_FPI0_ARG2C_SHIFT 14 | ||
1188 | # define R300_FPI0_ARG2C_MASK (31 << 14) | ||
1189 | # define R300_FPI0_ARG2C_NEG (1 << 19) | ||
1190 | # define R300_FPI0_ARG2C_ABS (1 << 20) | ||
1191 | # define R300_FPI0_SPECIAL_LRP (1 << 21) | ||
1192 | # define R300_FPI0_OUTC_MAD (0 << 23) | ||
1193 | # define R300_FPI0_OUTC_DP3 (1 << 23) | ||
1194 | # define R300_FPI0_OUTC_DP4 (2 << 23) | ||
1195 | # define R300_FPI0_OUTC_MIN (4 << 23) | ||
1196 | # define R300_FPI0_OUTC_MAX (5 << 23) | ||
1197 | # define R300_FPI0_OUTC_CMPH (7 << 23) | ||
1198 | # define R300_FPI0_OUTC_CMP (8 << 23) | ||
1199 | # define R300_FPI0_OUTC_FRC (9 << 23) | ||
1200 | # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) | ||
1201 | # define R300_FPI0_OUTC_SAT (1 << 30) | ||
1202 | # define R300_FPI0_INSERT_NOP (1 << 31) | ||
1203 | |||
1204 | #define R300_PFS_INSTR2_0 0x49C0 | ||
1205 | # define R300_FPI2_ARGA_SRC0C_X 0 | ||
1206 | # define R300_FPI2_ARGA_SRC0C_Y 1 | ||
1207 | # define R300_FPI2_ARGA_SRC0C_Z 2 | ||
1208 | # define R300_FPI2_ARGA_SRC1C_X 3 | ||
1209 | # define R300_FPI2_ARGA_SRC1C_Y 4 | ||
1210 | # define R300_FPI2_ARGA_SRC1C_Z 5 | ||
1211 | # define R300_FPI2_ARGA_SRC2C_X 6 | ||
1212 | # define R300_FPI2_ARGA_SRC2C_Y 7 | ||
1213 | # define R300_FPI2_ARGA_SRC2C_Z 8 | ||
1214 | # define R300_FPI2_ARGA_SRC0A 9 | ||
1215 | # define R300_FPI2_ARGA_SRC1A 10 | ||
1216 | # define R300_FPI2_ARGA_SRC2A 11 | ||
1217 | # define R300_FPI2_ARGA_SRC1A_LRP 15 | ||
1218 | # define R300_FPI2_ARGA_ZERO 16 | ||
1219 | # define R300_FPI2_ARGA_ONE 17 | ||
1220 | /* GUESS */ | ||
1221 | # define R300_FPI2_ARGA_HALF 18 | ||
1222 | # define R300_FPI2_ARG0A_SHIFT 0 | ||
1223 | # define R300_FPI2_ARG0A_MASK (31 << 0) | ||
1224 | # define R300_FPI2_ARG0A_NEG (1 << 5) | ||
1225 | /* GUESS */ | ||
1226 | # define R300_FPI2_ARG0A_ABS (1 << 6) | ||
1227 | # define R300_FPI2_ARG1A_SHIFT 7 | ||
1228 | # define R300_FPI2_ARG1A_MASK (31 << 7) | ||
1229 | # define R300_FPI2_ARG1A_NEG (1 << 12) | ||
1230 | /* GUESS */ | ||
1231 | # define R300_FPI2_ARG1A_ABS (1 << 13) | ||
1232 | # define R300_FPI2_ARG2A_SHIFT 14 | ||
1233 | # define R300_FPI2_ARG2A_MASK (31 << 14) | ||
1234 | # define R300_FPI2_ARG2A_NEG (1 << 19) | ||
1235 | /* GUESS */ | ||
1236 | # define R300_FPI2_ARG2A_ABS (1 << 20) | ||
1237 | # define R300_FPI2_SPECIAL_LRP (1 << 21) | ||
1238 | # define R300_FPI2_OUTA_MAD (0 << 23) | ||
1239 | # define R300_FPI2_OUTA_DP4 (1 << 23) | ||
1240 | # define R300_FPI2_OUTA_MIN (2 << 23) | ||
1241 | # define R300_FPI2_OUTA_MAX (3 << 23) | ||
1242 | # define R300_FPI2_OUTA_CMP (6 << 23) | ||
1243 | # define R300_FPI2_OUTA_FRC (7 << 23) | ||
1244 | # define R300_FPI2_OUTA_EX2 (8 << 23) | ||
1245 | # define R300_FPI2_OUTA_LG2 (9 << 23) | ||
1246 | # define R300_FPI2_OUTA_RCP (10 << 23) | ||
1247 | # define R300_FPI2_OUTA_RSQ (11 << 23) | ||
1248 | # define R300_FPI2_OUTA_SAT (1 << 30) | ||
1249 | # define R300_FPI2_UNKNOWN_31 (1 << 31) | ||
1250 | /* END: Fragment program instruction set */ | ||
1251 | |||
1252 | /* Fog state and color */ | ||
1253 | #define R300_RE_FOG_STATE 0x4BC0 | ||
1254 | # define R300_FOG_ENABLE (1 << 0) | ||
1255 | # define R300_FOG_MODE_LINEAR (0 << 1) | ||
1256 | # define R300_FOG_MODE_EXP (1 << 1) | ||
1257 | # define R300_FOG_MODE_EXP2 (2 << 1) | ||
1258 | # define R300_FOG_MODE_MASK (3 << 1) | ||
1259 | #define R300_FOG_COLOR_R 0x4BC8 | ||
1260 | #define R300_FOG_COLOR_G 0x4BCC | ||
1261 | #define R300_FOG_COLOR_B 0x4BD0 | ||
1262 | |||
1263 | #define R300_PP_ALPHA_TEST 0x4BD4 | ||
1264 | # define R300_REF_ALPHA_MASK 0x000000ff | ||
1265 | # define R300_ALPHA_TEST_FAIL (0 << 8) | ||
1266 | # define R300_ALPHA_TEST_LESS (1 << 8) | ||
1267 | # define R300_ALPHA_TEST_LEQUAL (3 << 8) | ||
1268 | # define R300_ALPHA_TEST_EQUAL (2 << 8) | ||
1269 | # define R300_ALPHA_TEST_GEQUAL (6 << 8) | ||
1270 | # define R300_ALPHA_TEST_GREATER (4 << 8) | ||
1271 | # define R300_ALPHA_TEST_NEQUAL (5 << 8) | ||
1272 | # define R300_ALPHA_TEST_PASS (7 << 8) | ||
1273 | # define R300_ALPHA_TEST_OP_MASK (7 << 8) | ||
1274 | # define R300_ALPHA_TEST_ENABLE (1 << 11) | ||
1275 | |||
1276 | /* gap */ | ||
1277 | |||
1278 | /* Fragment program parameters in 7.16 floating point */ | ||
1279 | #define R300_PFS_PARAM_0_X 0x4C00 | ||
1280 | #define R300_PFS_PARAM_0_Y 0x4C04 | ||
1281 | #define R300_PFS_PARAM_0_Z 0x4C08 | ||
1282 | #define R300_PFS_PARAM_0_W 0x4C0C | ||
1283 | /* GUESS: PARAM_31 is last, based on native limits reported by fglrx */ | ||
1284 | #define R300_PFS_PARAM_31_X 0x4DF0 | ||
1285 | #define R300_PFS_PARAM_31_Y 0x4DF4 | ||
1286 | #define R300_PFS_PARAM_31_Z 0x4DF8 | ||
1287 | #define R300_PFS_PARAM_31_W 0x4DFC | ||
1288 | |||
1289 | /* Notes: | ||
1290 | * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in | ||
1291 | * the application | ||
1292 | * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND | ||
1293 | * are set to the same | ||
1294 | * function (both registers are always set up completely in any case) | ||
1295 | * - Most blend flags are simply copied from R200 and not tested yet | ||
1296 | */ | ||
1297 | #define R300_RB3D_CBLEND 0x4E04 | ||
1298 | #define R300_RB3D_ABLEND 0x4E08 | ||
1299 | /* the following only appear in CBLEND */ | ||
1300 | # define R300_BLEND_ENABLE (1 << 0) | ||
1301 | # define R300_BLEND_UNKNOWN (3 << 1) | ||
1302 | # define R300_BLEND_NO_SEPARATE (1 << 3) | ||
1303 | /* the following are shared between CBLEND and ABLEND */ | ||
1304 | # define R300_FCN_MASK (3 << 12) | ||
1305 | # define R300_COMB_FCN_ADD_CLAMP (0 << 12) | ||
1306 | # define R300_COMB_FCN_ADD_NOCLAMP (1 << 12) | ||
1307 | # define R300_COMB_FCN_SUB_CLAMP (2 << 12) | ||
1308 | # define R300_COMB_FCN_SUB_NOCLAMP (3 << 12) | ||
1309 | # define R300_COMB_FCN_MIN (4 << 12) | ||
1310 | # define R300_COMB_FCN_MAX (5 << 12) | ||
1311 | # define R300_COMB_FCN_RSUB_CLAMP (6 << 12) | ||
1312 | # define R300_COMB_FCN_RSUB_NOCLAMP (7 << 12) | ||
1313 | # define R300_BLEND_GL_ZERO (32) | ||
1314 | # define R300_BLEND_GL_ONE (33) | ||
1315 | # define R300_BLEND_GL_SRC_COLOR (34) | ||
1316 | # define R300_BLEND_GL_ONE_MINUS_SRC_COLOR (35) | ||
1317 | # define R300_BLEND_GL_DST_COLOR (36) | ||
1318 | # define R300_BLEND_GL_ONE_MINUS_DST_COLOR (37) | ||
1319 | # define R300_BLEND_GL_SRC_ALPHA (38) | ||
1320 | # define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA (39) | ||
1321 | # define R300_BLEND_GL_DST_ALPHA (40) | ||
1322 | # define R300_BLEND_GL_ONE_MINUS_DST_ALPHA (41) | ||
1323 | # define R300_BLEND_GL_SRC_ALPHA_SATURATE (42) | ||
1324 | # define R300_BLEND_GL_CONST_COLOR (43) | ||
1325 | # define R300_BLEND_GL_ONE_MINUS_CONST_COLOR (44) | ||
1326 | # define R300_BLEND_GL_CONST_ALPHA (45) | ||
1327 | # define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA (46) | ||
1328 | # define R300_BLEND_MASK (63) | ||
1329 | # define R300_SRC_BLEND_SHIFT (16) | ||
1330 | # define R300_DST_BLEND_SHIFT (24) | ||
1331 | #define R300_RB3D_BLEND_COLOR 0x4E10 | ||
1332 | #define R300_RB3D_COLORMASK 0x4E0C | ||
1333 | # define R300_COLORMASK0_B (1<<0) | ||
1334 | # define R300_COLORMASK0_G (1<<1) | ||
1335 | # define R300_COLORMASK0_R (1<<2) | ||
1336 | # define R300_COLORMASK0_A (1<<3) | ||
1337 | |||
1338 | /* gap */ | ||
1339 | |||
1340 | #define R300_RB3D_COLOROFFSET0 0x4E28 | ||
1341 | # define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */ | ||
1342 | #define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */ | ||
1343 | #define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */ | ||
1344 | #define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */ | ||
1345 | |||
1346 | /* gap */ | ||
1347 | |||
1348 | /* Bit 16: Larger tiles | ||
1349 | * Bit 17: 4x2 tiles | ||
1350 | * Bit 18: Extremely weird tile like, but some pixels duplicated? | ||
1351 | */ | ||
1352 | #define R300_RB3D_COLORPITCH0 0x4E38 | ||
1353 | # define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */ | ||
1354 | # define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */ | ||
1355 | # define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */ | ||
1356 | # define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */ | ||
1357 | # define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */ | ||
1358 | # define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */ | ||
1359 | # define R300_COLOR_FORMAT_RGB565 (2 << 22) | ||
1360 | # define R300_COLOR_FORMAT_ARGB8888 (3 << 22) | ||
1361 | #define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */ | ||
1362 | #define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ | ||
1363 | #define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ | ||
1364 | |||
1365 | /* gap */ | ||
1366 | |||
1367 | /* Guess by Vladimir. | ||
1368 | * Set to 0A before 3D operations, set to 02 afterwards. | ||
1369 | */ | ||
1370 | /*#define R300_RB3D_DSTCACHE_CTLSTAT 0x4E4C*/ | ||
1371 | # define R300_RB3D_DSTCACHE_UNKNOWN_02 0x00000002 | ||
1372 | # define R300_RB3D_DSTCACHE_UNKNOWN_0A 0x0000000A | ||
1373 | |||
1374 | /* gap */ | ||
1375 | /* There seems to be no "write only" setting, so use Z-test = ALWAYS | ||
1376 | * for this. | ||
1377 | * Bit (1<<8) is the "test" bit. so plain write is 6 - vd | ||
1378 | */ | ||
1379 | #define R300_ZB_CNTL 0x4F00 | ||
1380 | # define R300_STENCIL_ENABLE (1 << 0) | ||
1381 | # define R300_Z_ENABLE (1 << 1) | ||
1382 | # define R300_Z_WRITE_ENABLE (1 << 2) | ||
1383 | # define R300_Z_SIGNED_COMPARE (1 << 3) | ||
1384 | # define R300_STENCIL_FRONT_BACK (1 << 4) | ||
1385 | |||
1386 | #define R300_ZB_ZSTENCILCNTL 0x4f04 | ||
1387 | /* functions */ | ||
1388 | # define R300_ZS_NEVER 0 | ||
1389 | # define R300_ZS_LESS 1 | ||
1390 | # define R300_ZS_LEQUAL 2 | ||
1391 | # define R300_ZS_EQUAL 3 | ||
1392 | # define R300_ZS_GEQUAL 4 | ||
1393 | # define R300_ZS_GREATER 5 | ||
1394 | # define R300_ZS_NOTEQUAL 6 | ||
1395 | # define R300_ZS_ALWAYS 7 | ||
1396 | # define R300_ZS_MASK 7 | ||
1397 | /* operations */ | ||
1398 | # define R300_ZS_KEEP 0 | ||
1399 | # define R300_ZS_ZERO 1 | ||
1400 | # define R300_ZS_REPLACE 2 | ||
1401 | # define R300_ZS_INCR 3 | ||
1402 | # define R300_ZS_DECR 4 | ||
1403 | # define R300_ZS_INVERT 5 | ||
1404 | # define R300_ZS_INCR_WRAP 6 | ||
1405 | # define R300_ZS_DECR_WRAP 7 | ||
1406 | # define R300_Z_FUNC_SHIFT 0 | ||
1407 | /* front and back refer to operations done for front | ||
1408 | and back faces, i.e. separate stencil function support */ | ||
1409 | # define R300_S_FRONT_FUNC_SHIFT 3 | ||
1410 | # define R300_S_FRONT_SFAIL_OP_SHIFT 6 | ||
1411 | # define R300_S_FRONT_ZPASS_OP_SHIFT 9 | ||
1412 | # define R300_S_FRONT_ZFAIL_OP_SHIFT 12 | ||
1413 | # define R300_S_BACK_FUNC_SHIFT 15 | ||
1414 | # define R300_S_BACK_SFAIL_OP_SHIFT 18 | ||
1415 | # define R300_S_BACK_ZPASS_OP_SHIFT 21 | ||
1416 | # define R300_S_BACK_ZFAIL_OP_SHIFT 24 | ||
1417 | |||
1418 | #define R300_ZB_STENCILREFMASK 0x4f08 | ||
1419 | # define R300_STENCILREF_SHIFT 0 | ||
1420 | # define R300_STENCILREF_MASK 0x000000ff | ||
1421 | # define R300_STENCILMASK_SHIFT 8 | ||
1422 | # define R300_STENCILMASK_MASK 0x0000ff00 | ||
1423 | # define R300_STENCILWRITEMASK_SHIFT 16 | ||
1424 | # define R300_STENCILWRITEMASK_MASK 0x00ff0000 | ||
1425 | |||
1426 | /* gap */ | ||
1427 | |||
1428 | #define R300_ZB_FORMAT 0x4f10 | ||
1429 | # define R300_DEPTHFORMAT_16BIT_INT_Z (0 << 0) | ||
1430 | # define R300_DEPTHFORMAT_16BIT_13E3 (1 << 0) | ||
1431 | # define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL (2 << 0) | ||
1432 | /* reserved up to (15 << 0) */ | ||
1433 | # define R300_INVERT_13E3_LEADING_ONES (0 << 4) | ||
1434 | # define R300_INVERT_13E3_LEADING_ZEROS (1 << 4) | ||
1435 | |||
1436 | #define R300_ZB_ZTOP 0x4F14 | ||
1437 | # define R300_ZTOP_DISABLE (0 << 0) | ||
1438 | # define R300_ZTOP_ENABLE (1 << 0) | ||
1439 | |||
1440 | /* gap */ | ||
1441 | |||
1442 | #define R300_ZB_ZCACHE_CTLSTAT 0x4f18 | ||
1443 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT (0 << 0) | ||
1444 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0) | ||
1445 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT (0 << 1) | ||
1446 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE (1 << 1) | ||
1447 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE (0 << 31) | ||
1448 | # define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY (1 << 31) | ||
1449 | |||
1450 | #define R300_ZB_BW_CNTL 0x4f1c | ||
1451 | # define R300_HIZ_DISABLE (0 << 0) | ||
1452 | # define R300_HIZ_ENABLE (1 << 0) | ||
1453 | # define R300_HIZ_MIN (0 << 1) | ||
1454 | # define R300_HIZ_MAX (1 << 1) | ||
1455 | # define R300_FAST_FILL_DISABLE (0 << 2) | ||
1456 | # define R300_FAST_FILL_ENABLE (1 << 2) | ||
1457 | # define R300_RD_COMP_DISABLE (0 << 3) | ||
1458 | # define R300_RD_COMP_ENABLE (1 << 3) | ||
1459 | # define R300_WR_COMP_DISABLE (0 << 4) | ||
1460 | # define R300_WR_COMP_ENABLE (1 << 4) | ||
1461 | # define R300_ZB_CB_CLEAR_RMW (0 << 5) | ||
1462 | # define R300_ZB_CB_CLEAR_CACHE_LINEAR (1 << 5) | ||
1463 | # define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE (0 << 6) | ||
1464 | # define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE (1 << 6) | ||
1465 | |||
1466 | # define R500_ZEQUAL_OPTIMIZE_ENABLE (0 << 7) | ||
1467 | # define R500_ZEQUAL_OPTIMIZE_DISABLE (1 << 7) | ||
1468 | # define R500_SEQUAL_OPTIMIZE_ENABLE (0 << 8) | ||
1469 | # define R500_SEQUAL_OPTIMIZE_DISABLE (1 << 8) | ||
1470 | |||
1471 | # define R500_BMASK_ENABLE (0 << 10) | ||
1472 | # define R500_BMASK_DISABLE (1 << 10) | ||
1473 | # define R500_HIZ_EQUAL_REJECT_DISABLE (0 << 11) | ||
1474 | # define R500_HIZ_EQUAL_REJECT_ENABLE (1 << 11) | ||
1475 | # define R500_HIZ_FP_EXP_BITS_DISABLE (0 << 12) | ||
1476 | # define R500_HIZ_FP_EXP_BITS_1 (1 << 12) | ||
1477 | # define R500_HIZ_FP_EXP_BITS_2 (2 << 12) | ||
1478 | # define R500_HIZ_FP_EXP_BITS_3 (3 << 12) | ||
1479 | # define R500_HIZ_FP_EXP_BITS_4 (4 << 12) | ||
1480 | # define R500_HIZ_FP_EXP_BITS_5 (5 << 12) | ||
1481 | # define R500_HIZ_FP_INVERT_LEADING_ONES (0 << 15) | ||
1482 | # define R500_HIZ_FP_INVERT_LEADING_ZEROS (1 << 15) | ||
1483 | # define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE (0 << 16) | ||
1484 | # define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE (1 << 16) | ||
1485 | # define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE (0 << 17) | ||
1486 | # define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE (1 << 17) | ||
1487 | # define R500_PEQ_PACKING_DISABLE (0 << 18) | ||
1488 | # define R500_PEQ_PACKING_ENABLE (1 << 18) | ||
1489 | # define R500_COVERED_PTR_MASKING_DISABLE (0 << 18) | ||
1490 | # define R500_COVERED_PTR_MASKING_ENABLE (1 << 18) | ||
1491 | |||
1492 | |||
1493 | /* gap */ | ||
1494 | |||
1495 | /* Z Buffer Address Offset. | ||
1496 | * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles. | ||
1497 | */ | ||
1498 | #define R300_ZB_DEPTHOFFSET 0x4f20 | ||
1499 | |||
1500 | /* Z Buffer Pitch and Endian Control */ | ||
1501 | #define R300_ZB_DEPTHPITCH 0x4f24 | ||
1502 | # define R300_DEPTHPITCH_MASK 0x00003FFC | ||
1503 | # define R300_DEPTHMACROTILE_DISABLE (0 << 16) | ||
1504 | # define R300_DEPTHMACROTILE_ENABLE (1 << 16) | ||
1505 | # define R300_DEPTHMICROTILE_LINEAR (0 << 17) | ||
1506 | # define R300_DEPTHMICROTILE_TILED (1 << 17) | ||
1507 | # define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17) | ||
1508 | # define R300_DEPTHENDIAN_NO_SWAP (0 << 18) | ||
1509 | # define R300_DEPTHENDIAN_WORD_SWAP (1 << 18) | ||
1510 | # define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18) | ||
1511 | # define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18) | ||
1512 | |||
1513 | /* Z Buffer Clear Value */ | ||
1514 | #define R300_ZB_DEPTHCLEARVALUE 0x4f28 | ||
1515 | |||
1516 | #define R300_ZB_ZMASK_OFFSET 0x4f30 | ||
1517 | #define R300_ZB_ZMASK_PITCH 0x4f34 | ||
1518 | #define R300_ZB_ZMASK_WRINDEX 0x4f38 | ||
1519 | #define R300_ZB_ZMASK_DWORD 0x4f3c | ||
1520 | #define R300_ZB_ZMASK_RDINDEX 0x4f40 | ||
1521 | |||
1522 | /* Hierarchical Z Memory Offset */ | ||
1523 | #define R300_ZB_HIZ_OFFSET 0x4f44 | ||
1524 | |||
1525 | /* Hierarchical Z Write Index */ | ||
1526 | #define R300_ZB_HIZ_WRINDEX 0x4f48 | ||
1527 | |||
1528 | /* Hierarchical Z Data */ | ||
1529 | #define R300_ZB_HIZ_DWORD 0x4f4c | ||
1530 | |||
1531 | /* Hierarchical Z Read Index */ | ||
1532 | #define R300_ZB_HIZ_RDINDEX 0x4f50 | ||
1533 | |||
1534 | /* Hierarchical Z Pitch */ | ||
1535 | #define R300_ZB_HIZ_PITCH 0x4f54 | ||
1536 | |||
1537 | /* Z Buffer Z Pass Counter Data */ | ||
1538 | #define R300_ZB_ZPASS_DATA 0x4f58 | ||
1539 | |||
1540 | /* Z Buffer Z Pass Counter Address */ | ||
1541 | #define R300_ZB_ZPASS_ADDR 0x4f5c | ||
1542 | |||
1543 | /* Depth buffer X and Y coordinate offset */ | ||
1544 | #define R300_ZB_DEPTHXY_OFFSET 0x4f60 | ||
1545 | # define R300_DEPTHX_OFFSET_SHIFT 1 | ||
1546 | # define R300_DEPTHX_OFFSET_MASK 0x000007FE | ||
1547 | # define R300_DEPTHY_OFFSET_SHIFT 17 | ||
1548 | # define R300_DEPTHY_OFFSET_MASK 0x07FE0000 | ||
1549 | |||
1550 | /* Sets the fifo sizes */ | ||
1551 | #define R500_ZB_FIFO_SIZE 0x4fd0 | ||
1552 | # define R500_OP_FIFO_SIZE_FULL (0 << 0) | ||
1553 | # define R500_OP_FIFO_SIZE_HALF (1 << 0) | ||
1554 | # define R500_OP_FIFO_SIZE_QUATER (2 << 0) | ||
1555 | # define R500_OP_FIFO_SIZE_EIGTHS (4 << 0) | ||
1556 | |||
1557 | /* Stencil Reference Value and Mask for backfacing quads */ | ||
1558 | /* R300_ZB_STENCILREFMASK handles front face */ | ||
1559 | #define R500_ZB_STENCILREFMASK_BF 0x4fd4 | ||
1560 | # define R500_STENCILREF_SHIFT 0 | ||
1561 | # define R500_STENCILREF_MASK 0x000000ff | ||
1562 | # define R500_STENCILMASK_SHIFT 8 | ||
1563 | # define R500_STENCILMASK_MASK 0x0000ff00 | ||
1564 | # define R500_STENCILWRITEMASK_SHIFT 16 | ||
1565 | # define R500_STENCILWRITEMASK_MASK 0x00ff0000 | ||
1566 | |||
1567 | /* BEGIN: Vertex program instruction set */ | ||
1568 | |||
1569 | /* Every instruction is four dwords long: | ||
1570 | * DWORD 0: output and opcode | ||
1571 | * DWORD 1: first argument | ||
1572 | * DWORD 2: second argument | ||
1573 | * DWORD 3: third argument | ||
1574 | * | ||
1575 | * Notes: | ||
1576 | * - ABS r, a is implemented as MAX r, a, -a | ||
1577 | * - MOV is implemented as ADD to zero | ||
1578 | * - XPD is implemented as MUL + MAD | ||
1579 | * - FLR is implemented as FRC + ADD | ||
1580 | * - apparently, fglrx tries to schedule instructions so that there is at | ||
1581 | * least one instruction between the write to a temporary and the first | ||
1582 | * read from said temporary; however, violations of this scheduling are | ||
1583 | * allowed | ||
1584 | * - register indices seem to be unrelated with OpenGL aliasing to | ||
1585 | * conventional state | ||
1586 | * - only one attribute and one parameter can be loaded at a time; however, | ||
1587 | * the same attribute/parameter can be used for more than one argument | ||
1588 | * - the second software argument for POW is the third hardware argument | ||
1589 | * (no idea why) | ||
1590 | * - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2 | ||
1591 | * | ||
1592 | * There is some magic surrounding LIT: | ||
1593 | * The single argument is replicated across all three inputs, but swizzled: | ||
1594 | * First argument: xyzy | ||
1595 | * Second argument: xyzx | ||
1596 | * Third argument: xyzw | ||
1597 | * Whenever the result is used later in the fragment program, fglrx forces | ||
1598 | * x and w to be 1.0 in the input selection; I don't know whether this is | ||
1599 | * strictly necessary | ||
1600 | */ | ||
1601 | #define R300_VPI_OUT_OP_DOT (1 << 0) | ||
1602 | #define R300_VPI_OUT_OP_MUL (2 << 0) | ||
1603 | #define R300_VPI_OUT_OP_ADD (3 << 0) | ||
1604 | #define R300_VPI_OUT_OP_MAD (4 << 0) | ||
1605 | #define R300_VPI_OUT_OP_DST (5 << 0) | ||
1606 | #define R300_VPI_OUT_OP_FRC (6 << 0) | ||
1607 | #define R300_VPI_OUT_OP_MAX (7 << 0) | ||
1608 | #define R300_VPI_OUT_OP_MIN (8 << 0) | ||
1609 | #define R300_VPI_OUT_OP_SGE (9 << 0) | ||
1610 | #define R300_VPI_OUT_OP_SLT (10 << 0) | ||
1611 | /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */ | ||
1612 | #define R300_VPI_OUT_OP_UNK12 (12 << 0) | ||
1613 | #define R300_VPI_OUT_OP_ARL (13 << 0) | ||
1614 | #define R300_VPI_OUT_OP_EXP (65 << 0) | ||
1615 | #define R300_VPI_OUT_OP_LOG (66 << 0) | ||
1616 | /* Used in fog computations, scalar(scalar) */ | ||
1617 | #define R300_VPI_OUT_OP_UNK67 (67 << 0) | ||
1618 | #define R300_VPI_OUT_OP_LIT (68 << 0) | ||
1619 | #define R300_VPI_OUT_OP_POW (69 << 0) | ||
1620 | #define R300_VPI_OUT_OP_RCP (70 << 0) | ||
1621 | #define R300_VPI_OUT_OP_RSQ (72 << 0) | ||
1622 | /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */ | ||
1623 | #define R300_VPI_OUT_OP_UNK73 (73 << 0) | ||
1624 | #define R300_VPI_OUT_OP_EX2 (75 << 0) | ||
1625 | #define R300_VPI_OUT_OP_LG2 (76 << 0) | ||
1626 | #define R300_VPI_OUT_OP_MAD_2 (128 << 0) | ||
1627 | /* all temps, vector(scalar, vector, vector) */ | ||
1628 | #define R300_VPI_OUT_OP_UNK129 (129 << 0) | ||
1629 | |||
1630 | #define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8) | ||
1631 | #define R300_VPI_OUT_REG_CLASS_ADDR (1 << 8) | ||
1632 | #define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8) | ||
1633 | #define R300_VPI_OUT_REG_CLASS_MASK (31 << 8) | ||
1634 | |||
1635 | #define R300_VPI_OUT_REG_INDEX_SHIFT 13 | ||
1636 | /* GUESS based on fglrx native limits */ | ||
1637 | #define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) | ||
1638 | |||
1639 | #define R300_VPI_OUT_WRITE_X (1 << 20) | ||
1640 | #define R300_VPI_OUT_WRITE_Y (1 << 21) | ||
1641 | #define R300_VPI_OUT_WRITE_Z (1 << 22) | ||
1642 | #define R300_VPI_OUT_WRITE_W (1 << 23) | ||
1643 | |||
1644 | #define R300_VPI_IN_REG_CLASS_TEMPORARY (0 << 0) | ||
1645 | #define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0) | ||
1646 | #define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0) | ||
1647 | #define R300_VPI_IN_REG_CLASS_NONE (9 << 0) | ||
1648 | #define R300_VPI_IN_REG_CLASS_MASK (31 << 0) | ||
1649 | |||
1650 | #define R300_VPI_IN_REG_INDEX_SHIFT 5 | ||
1651 | /* GUESS based on fglrx native limits */ | ||
1652 | #define R300_VPI_IN_REG_INDEX_MASK (255 << 5) | ||
1653 | |||
1654 | /* The R300 can select components from the input register arbitrarily. | ||
1655 | * Use the following constants, shifted by the component shift you | ||
1656 | * want to select | ||
1657 | */ | ||
1658 | #define R300_VPI_IN_SELECT_X 0 | ||
1659 | #define R300_VPI_IN_SELECT_Y 1 | ||
1660 | #define R300_VPI_IN_SELECT_Z 2 | ||
1661 | #define R300_VPI_IN_SELECT_W 3 | ||
1662 | #define R300_VPI_IN_SELECT_ZERO 4 | ||
1663 | #define R300_VPI_IN_SELECT_ONE 5 | ||
1664 | #define R300_VPI_IN_SELECT_MASK 7 | ||
1665 | |||
1666 | #define R300_VPI_IN_X_SHIFT 13 | ||
1667 | #define R300_VPI_IN_Y_SHIFT 16 | ||
1668 | #define R300_VPI_IN_Z_SHIFT 19 | ||
1669 | #define R300_VPI_IN_W_SHIFT 22 | ||
1670 | |||
1671 | #define R300_VPI_IN_NEG_X (1 << 25) | ||
1672 | #define R300_VPI_IN_NEG_Y (1 << 26) | ||
1673 | #define R300_VPI_IN_NEG_Z (1 << 27) | ||
1674 | #define R300_VPI_IN_NEG_W (1 << 28) | ||
1675 | /* END: Vertex program instruction set */ | ||
1676 | |||
1677 | /* BEGIN: Packet 3 commands */ | ||
1678 | |||
1679 | /* A primitive emission dword. */ | ||
1680 | #define R300_PRIM_TYPE_NONE (0 << 0) | ||
1681 | #define R300_PRIM_TYPE_POINT (1 << 0) | ||
1682 | #define R300_PRIM_TYPE_LINE (2 << 0) | ||
1683 | #define R300_PRIM_TYPE_LINE_STRIP (3 << 0) | ||
1684 | #define R300_PRIM_TYPE_TRI_LIST (4 << 0) | ||
1685 | #define R300_PRIM_TYPE_TRI_FAN (5 << 0) | ||
1686 | #define R300_PRIM_TYPE_TRI_STRIP (6 << 0) | ||
1687 | #define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0) | ||
1688 | #define R300_PRIM_TYPE_RECT_LIST (8 << 0) | ||
1689 | #define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) | ||
1690 | #define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) | ||
1691 | /* GUESS (based on r200) */ | ||
1692 | #define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) | ||
1693 | #define R300_PRIM_TYPE_LINE_LOOP (12 << 0) | ||
1694 | #define R300_PRIM_TYPE_QUADS (13 << 0) | ||
1695 | #define R300_PRIM_TYPE_QUAD_STRIP (14 << 0) | ||
1696 | #define R300_PRIM_TYPE_POLYGON (15 << 0) | ||
1697 | #define R300_PRIM_TYPE_MASK 0xF | ||
1698 | #define R300_PRIM_WALK_IND (1 << 4) | ||
1699 | #define R300_PRIM_WALK_LIST (2 << 4) | ||
1700 | #define R300_PRIM_WALK_RING (3 << 4) | ||
1701 | #define R300_PRIM_WALK_MASK (3 << 4) | ||
1702 | /* GUESS (based on r200) */ | ||
1703 | #define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) | ||
1704 | #define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) | ||
1705 | #define R300_PRIM_NUM_VERTICES_SHIFT 16 | ||
1706 | #define R300_PRIM_NUM_VERTICES_MASK 0xffff | ||
1707 | |||
1708 | /* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR. | ||
1709 | * Two parameter dwords: | ||
1710 | * 0. The first parameter appears to be always 0 | ||
1711 | * 1. The second parameter is a standard primitive emission dword. | ||
1712 | */ | ||
1713 | #define R300_PACKET3_3D_DRAW_VBUF 0x00002800 | ||
1714 | |||
1715 | /* Specify the full set of vertex arrays as (address, stride). | ||
1716 | * The first parameter is the number of vertex arrays specified. | ||
1717 | * The rest of the command is a variable length list of blocks, where | ||
1718 | * each block is three dwords long and specifies two arrays. | ||
1719 | * The first dword of a block is split into two words, the lower significant | ||
1720 | * word refers to the first array, the more significant word to the second | ||
1721 | * array in the block. | ||
1722 | * The low byte of each word contains the size of an array entry in dwords, | ||
1723 | * the high byte contains the stride of the array. | ||
1724 | * The second dword of a block contains the pointer to the first array, | ||
1725 | * the third dword of a block contains the pointer to the second array. | ||
1726 | * Note that if the total number of arrays is odd, the third dword of | ||
1727 | * the last block is omitted. | ||
1728 | */ | ||
1729 | #define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00 | ||
1730 | |||
1731 | #define R300_PACKET3_INDX_BUFFER 0x00003300 | ||
1732 | # define R300_EB_UNK1_SHIFT 24 | ||
1733 | # define R300_EB_UNK1 (0x80<<24) | ||
1734 | # define R300_EB_UNK2 0x0810 | ||
1735 | #define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400 | ||
1736 | #define R300_PACKET3_3D_DRAW_INDX_2 0x00003600 | ||
1737 | |||
1738 | /* END: Packet 3 commands */ | ||
1739 | |||
1740 | |||
1741 | /* Color formats for 2d packets | ||
1742 | */ | ||
1743 | #define R300_CP_COLOR_FORMAT_CI8 2 | ||
1744 | #define R300_CP_COLOR_FORMAT_ARGB1555 3 | ||
1745 | #define R300_CP_COLOR_FORMAT_RGB565 4 | ||
1746 | #define R300_CP_COLOR_FORMAT_ARGB8888 6 | ||
1747 | #define R300_CP_COLOR_FORMAT_RGB332 7 | ||
1748 | #define R300_CP_COLOR_FORMAT_RGB8 9 | ||
1749 | #define R300_CP_COLOR_FORMAT_ARGB4444 15 | ||
1750 | |||
1751 | /* | ||
1752 | * CP type-3 packets | ||
1753 | */ | ||
1754 | #define R300_CP_CMD_BITBLT_MULTI 0xC0009B00 | ||
1755 | |||
1756 | #define R500_VAP_INDEX_OFFSET 0x208c | ||
1757 | |||
1758 | #define R500_GA_US_VECTOR_INDEX 0x4250 | ||
1759 | #define R500_GA_US_VECTOR_DATA 0x4254 | ||
1760 | |||
1761 | #define R500_RS_IP_0 0x4074 | ||
1762 | #define R500_RS_INST_0 0x4320 | ||
1763 | |||
1764 | #define R500_US_CONFIG 0x4600 | ||
1765 | |||
1766 | #define R500_US_FC_CTRL 0x4624 | ||
1767 | #define R500_US_CODE_ADDR 0x4630 | ||
1768 | |||
1769 | #define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46c0 | ||
1770 | #define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8 | ||
1771 | |||
1772 | #endif /* _R300_REG_H */ | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c new file mode 100644 index 000000000000..e53158f0ecb5 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
@@ -0,0 +1,1773 @@ | |||
1 | /* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */ | ||
2 | /* | ||
3 | * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. | ||
4 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. | ||
5 | * Copyright 2007 Advanced Micro Devices, Inc. | ||
6 | * All Rights Reserved. | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
25 | * DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | * Authors: | ||
28 | * Kevin E. Martin <martin@valinux.com> | ||
29 | * Gareth Hughes <gareth@valinux.com> | ||
30 | */ | ||
31 | |||
32 | #include "drmP.h" | ||
33 | #include "drm.h" | ||
34 | #include "radeon_drm.h" | ||
35 | #include "radeon_drv.h" | ||
36 | #include "r300_reg.h" | ||
37 | |||
38 | #include "radeon_microcode.h" | ||
39 | |||
40 | #define RADEON_FIFO_DEBUG 0 | ||
41 | |||
42 | static int radeon_do_cleanup_cp(struct drm_device * dev); | ||
43 | |||
44 | static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) | ||
45 | { | ||
46 | u32 ret; | ||
47 | RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); | ||
48 | ret = RADEON_READ(R520_MC_IND_DATA); | ||
49 | RADEON_WRITE(R520_MC_IND_INDEX, 0); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) | ||
54 | { | ||
55 | u32 ret; | ||
56 | RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff); | ||
57 | ret = RADEON_READ(RS480_NB_MC_DATA); | ||
58 | RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) | ||
63 | { | ||
64 | u32 ret; | ||
65 | RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); | ||
66 | ret = RADEON_READ(RS690_MC_DATA); | ||
67 | RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) | ||
72 | { | ||
73 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) | ||
74 | return RS690_READ_MCIND(dev_priv, addr); | ||
75 | else | ||
76 | return RS480_READ_MCIND(dev_priv, addr); | ||
77 | } | ||
78 | |||
79 | u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) | ||
80 | { | ||
81 | |||
82 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) | ||
83 | return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); | ||
84 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) | ||
85 | return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); | ||
86 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) | ||
87 | return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); | ||
88 | else | ||
89 | return RADEON_READ(RADEON_MC_FB_LOCATION); | ||
90 | } | ||
91 | |||
92 | static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) | ||
93 | { | ||
94 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) | ||
95 | R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); | ||
96 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) | ||
97 | RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); | ||
98 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) | ||
99 | R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); | ||
100 | else | ||
101 | RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); | ||
102 | } | ||
103 | |||
104 | static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) | ||
105 | { | ||
106 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) | ||
107 | R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); | ||
108 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) | ||
109 | RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); | ||
110 | else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) | ||
111 | R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); | ||
112 | else | ||
113 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); | ||
114 | } | ||
115 | |||
116 | static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) | ||
117 | { | ||
118 | u32 agp_base_hi = upper_32_bits(agp_base); | ||
119 | u32 agp_base_lo = agp_base & 0xffffffff; | ||
120 | |||
121 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) { | ||
122 | R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo); | ||
123 | R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi); | ||
124 | } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { | ||
125 | RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo); | ||
126 | RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi); | ||
127 | } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) { | ||
128 | R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo); | ||
129 | R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi); | ||
130 | } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480) { | ||
131 | RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); | ||
132 | RADEON_WRITE(RS480_AGP_BASE_2, 0); | ||
133 | } else { | ||
134 | RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); | ||
135 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200) | ||
136 | RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static int RADEON_READ_PLL(struct drm_device * dev, int addr) | ||
141 | { | ||
142 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
143 | |||
144 | RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); | ||
145 | return RADEON_READ(RADEON_CLOCK_CNTL_DATA); | ||
146 | } | ||
147 | |||
148 | static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) | ||
149 | { | ||
150 | RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); | ||
151 | return RADEON_READ(RADEON_PCIE_DATA); | ||
152 | } | ||
153 | |||
154 | #if RADEON_FIFO_DEBUG | ||
155 | static void radeon_status(drm_radeon_private_t * dev_priv) | ||
156 | { | ||
157 | printk("%s:\n", __func__); | ||
158 | printk("RBBM_STATUS = 0x%08x\n", | ||
159 | (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); | ||
160 | printk("CP_RB_RTPR = 0x%08x\n", | ||
161 | (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); | ||
162 | printk("CP_RB_WTPR = 0x%08x\n", | ||
163 | (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); | ||
164 | printk("AIC_CNTL = 0x%08x\n", | ||
165 | (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); | ||
166 | printk("AIC_STAT = 0x%08x\n", | ||
167 | (unsigned int)RADEON_READ(RADEON_AIC_STAT)); | ||
168 | printk("AIC_PT_BASE = 0x%08x\n", | ||
169 | (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); | ||
170 | printk("TLB_ADDR = 0x%08x\n", | ||
171 | (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); | ||
172 | printk("TLB_DATA = 0x%08x\n", | ||
173 | (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); | ||
174 | } | ||
175 | #endif | ||
176 | |||
177 | /* ================================================================ | ||
178 | * Engine, FIFO control | ||
179 | */ | ||
180 | |||
181 | static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) | ||
182 | { | ||
183 | u32 tmp; | ||
184 | int i; | ||
185 | |||
186 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
187 | |||
188 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { | ||
189 | tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); | ||
190 | tmp |= RADEON_RB3D_DC_FLUSH_ALL; | ||
191 | RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); | ||
192 | |||
193 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
194 | if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) | ||
195 | & RADEON_RB3D_DC_BUSY)) { | ||
196 | return 0; | ||
197 | } | ||
198 | DRM_UDELAY(1); | ||
199 | } | ||
200 | } else { | ||
201 | /* 3D */ | ||
202 | tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT); | ||
203 | tmp |= RADEON_RB3D_DC_FLUSH_ALL; | ||
204 | RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp); | ||
205 | |||
206 | /* 2D */ | ||
207 | tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT); | ||
208 | tmp |= RADEON_RB3D_DC_FLUSH_ALL; | ||
209 | RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp); | ||
210 | |||
211 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
212 | if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT) | ||
213 | & RADEON_RB3D_DC_BUSY)) { | ||
214 | return 0; | ||
215 | } | ||
216 | DRM_UDELAY(1); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | #if RADEON_FIFO_DEBUG | ||
221 | DRM_ERROR("failed!\n"); | ||
222 | radeon_status(dev_priv); | ||
223 | #endif | ||
224 | return -EBUSY; | ||
225 | } | ||
226 | |||
227 | static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) | ||
228 | { | ||
229 | int i; | ||
230 | |||
231 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
232 | |||
233 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
234 | int slots = (RADEON_READ(RADEON_RBBM_STATUS) | ||
235 | & RADEON_RBBM_FIFOCNT_MASK); | ||
236 | if (slots >= entries) | ||
237 | return 0; | ||
238 | DRM_UDELAY(1); | ||
239 | } | ||
240 | |||
241 | #if RADEON_FIFO_DEBUG | ||
242 | DRM_ERROR("failed!\n"); | ||
243 | radeon_status(dev_priv); | ||
244 | #endif | ||
245 | return -EBUSY; | ||
246 | } | ||
247 | |||
248 | static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) | ||
249 | { | ||
250 | int i, ret; | ||
251 | |||
252 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
253 | |||
254 | ret = radeon_do_wait_for_fifo(dev_priv, 64); | ||
255 | if (ret) | ||
256 | return ret; | ||
257 | |||
258 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
259 | if (!(RADEON_READ(RADEON_RBBM_STATUS) | ||
260 | & RADEON_RBBM_ACTIVE)) { | ||
261 | radeon_do_pixcache_flush(dev_priv); | ||
262 | return 0; | ||
263 | } | ||
264 | DRM_UDELAY(1); | ||
265 | } | ||
266 | |||
267 | #if RADEON_FIFO_DEBUG | ||
268 | DRM_ERROR("failed!\n"); | ||
269 | radeon_status(dev_priv); | ||
270 | #endif | ||
271 | return -EBUSY; | ||
272 | } | ||
273 | |||
274 | static void radeon_init_pipes(drm_radeon_private_t *dev_priv) | ||
275 | { | ||
276 | uint32_t gb_tile_config, gb_pipe_sel = 0; | ||
277 | |||
278 | /* RS4xx/RS6xx/R4xx/R5xx */ | ||
279 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { | ||
280 | gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); | ||
281 | dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; | ||
282 | } else { | ||
283 | /* R3xx */ | ||
284 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || | ||
285 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) { | ||
286 | dev_priv->num_gb_pipes = 2; | ||
287 | } else { | ||
288 | /* R3Vxx */ | ||
289 | dev_priv->num_gb_pipes = 1; | ||
290 | } | ||
291 | } | ||
292 | DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes); | ||
293 | |||
294 | gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/); | ||
295 | |||
296 | switch (dev_priv->num_gb_pipes) { | ||
297 | case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; | ||
298 | case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; | ||
299 | case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; | ||
300 | default: | ||
301 | case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; | ||
302 | } | ||
303 | |||
304 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { | ||
305 | RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); | ||
306 | RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1)); | ||
307 | } | ||
308 | RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config); | ||
309 | radeon_do_wait_for_idle(dev_priv); | ||
310 | RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); | ||
311 | RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) | | ||
312 | R300_DC_AUTOFLUSH_ENABLE | | ||
313 | R300_DC_DC_DISABLE_IGNORE_PE)); | ||
314 | |||
315 | |||
316 | } | ||
317 | |||
318 | /* ================================================================ | ||
319 | * CP control, initialization | ||
320 | */ | ||
321 | |||
322 | /* Load the microcode for the CP */ | ||
323 | static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) | ||
324 | { | ||
325 | int i; | ||
326 | DRM_DEBUG("\n"); | ||
327 | |||
328 | radeon_do_wait_for_idle(dev_priv); | ||
329 | |||
330 | RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0); | ||
331 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) || | ||
332 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) || | ||
333 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) || | ||
334 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) || | ||
335 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) { | ||
336 | DRM_INFO("Loading R100 Microcode\n"); | ||
337 | for (i = 0; i < 256; i++) { | ||
338 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
339 | R100_cp_microcode[i][1]); | ||
340 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
341 | R100_cp_microcode[i][0]); | ||
342 | } | ||
343 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) || | ||
344 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) || | ||
345 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) || | ||
346 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) { | ||
347 | DRM_INFO("Loading R200 Microcode\n"); | ||
348 | for (i = 0; i < 256; i++) { | ||
349 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
350 | R200_cp_microcode[i][1]); | ||
351 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
352 | R200_cp_microcode[i][0]); | ||
353 | } | ||
354 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || | ||
355 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) || | ||
356 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) || | ||
357 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || | ||
358 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { | ||
359 | DRM_INFO("Loading R300 Microcode\n"); | ||
360 | for (i = 0; i < 256; i++) { | ||
361 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
362 | R300_cp_microcode[i][1]); | ||
363 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
364 | R300_cp_microcode[i][0]); | ||
365 | } | ||
366 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || | ||
367 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) { | ||
368 | DRM_INFO("Loading R400 Microcode\n"); | ||
369 | for (i = 0; i < 256; i++) { | ||
370 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
371 | R420_cp_microcode[i][1]); | ||
372 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
373 | R420_cp_microcode[i][0]); | ||
374 | } | ||
375 | } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { | ||
376 | DRM_INFO("Loading RS690 Microcode\n"); | ||
377 | for (i = 0; i < 256; i++) { | ||
378 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
379 | RS690_cp_microcode[i][1]); | ||
380 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
381 | RS690_cp_microcode[i][0]); | ||
382 | } | ||
383 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) || | ||
384 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) || | ||
385 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) || | ||
386 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) || | ||
387 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) || | ||
388 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) { | ||
389 | DRM_INFO("Loading R500 Microcode\n"); | ||
390 | for (i = 0; i < 256; i++) { | ||
391 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, | ||
392 | R520_cp_microcode[i][1]); | ||
393 | RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, | ||
394 | R520_cp_microcode[i][0]); | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /* Flush any pending commands to the CP. This should only be used just | ||
400 | * prior to a wait for idle, as it informs the engine that the command | ||
401 | * stream is ending. | ||
402 | */ | ||
403 | static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv) | ||
404 | { | ||
405 | DRM_DEBUG("\n"); | ||
406 | #if 0 | ||
407 | u32 tmp; | ||
408 | |||
409 | tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31); | ||
410 | RADEON_WRITE(RADEON_CP_RB_WPTR, tmp); | ||
411 | #endif | ||
412 | } | ||
413 | |||
414 | /* Wait for the CP to go idle. | ||
415 | */ | ||
416 | int radeon_do_cp_idle(drm_radeon_private_t * dev_priv) | ||
417 | { | ||
418 | RING_LOCALS; | ||
419 | DRM_DEBUG("\n"); | ||
420 | |||
421 | BEGIN_RING(6); | ||
422 | |||
423 | RADEON_PURGE_CACHE(); | ||
424 | RADEON_PURGE_ZCACHE(); | ||
425 | RADEON_WAIT_UNTIL_IDLE(); | ||
426 | |||
427 | ADVANCE_RING(); | ||
428 | COMMIT_RING(); | ||
429 | |||
430 | return radeon_do_wait_for_idle(dev_priv); | ||
431 | } | ||
432 | |||
433 | /* Start the Command Processor. | ||
434 | */ | ||
435 | static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) | ||
436 | { | ||
437 | RING_LOCALS; | ||
438 | DRM_DEBUG("\n"); | ||
439 | |||
440 | radeon_do_wait_for_idle(dev_priv); | ||
441 | |||
442 | RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode); | ||
443 | |||
444 | dev_priv->cp_running = 1; | ||
445 | |||
446 | BEGIN_RING(6); | ||
447 | |||
448 | RADEON_PURGE_CACHE(); | ||
449 | RADEON_PURGE_ZCACHE(); | ||
450 | RADEON_WAIT_UNTIL_IDLE(); | ||
451 | |||
452 | ADVANCE_RING(); | ||
453 | COMMIT_RING(); | ||
454 | } | ||
455 | |||
456 | /* Reset the Command Processor. This will not flush any pending | ||
457 | * commands, so you must wait for the CP command stream to complete | ||
458 | * before calling this routine. | ||
459 | */ | ||
460 | static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) | ||
461 | { | ||
462 | u32 cur_read_ptr; | ||
463 | DRM_DEBUG("\n"); | ||
464 | |||
465 | cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); | ||
466 | RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); | ||
467 | SET_RING_HEAD(dev_priv, cur_read_ptr); | ||
468 | dev_priv->ring.tail = cur_read_ptr; | ||
469 | } | ||
470 | |||
471 | /* Stop the Command Processor. This will not flush any pending | ||
472 | * commands, so you must flush the command stream and wait for the CP | ||
473 | * to go idle before calling this routine. | ||
474 | */ | ||
475 | static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) | ||
476 | { | ||
477 | DRM_DEBUG("\n"); | ||
478 | |||
479 | RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); | ||
480 | |||
481 | dev_priv->cp_running = 0; | ||
482 | } | ||
483 | |||
484 | /* Reset the engine. This will stop the CP if it is running. | ||
485 | */ | ||
486 | static int radeon_do_engine_reset(struct drm_device * dev) | ||
487 | { | ||
488 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
489 | u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset; | ||
490 | DRM_DEBUG("\n"); | ||
491 | |||
492 | radeon_do_pixcache_flush(dev_priv); | ||
493 | |||
494 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { | ||
495 | /* may need something similar for newer chips */ | ||
496 | clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); | ||
497 | mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); | ||
498 | |||
499 | RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | | ||
500 | RADEON_FORCEON_MCLKA | | ||
501 | RADEON_FORCEON_MCLKB | | ||
502 | RADEON_FORCEON_YCLKA | | ||
503 | RADEON_FORCEON_YCLKB | | ||
504 | RADEON_FORCEON_MC | | ||
505 | RADEON_FORCEON_AIC)); | ||
506 | } | ||
507 | |||
508 | rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); | ||
509 | |||
510 | RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | | ||
511 | RADEON_SOFT_RESET_CP | | ||
512 | RADEON_SOFT_RESET_HI | | ||
513 | RADEON_SOFT_RESET_SE | | ||
514 | RADEON_SOFT_RESET_RE | | ||
515 | RADEON_SOFT_RESET_PP | | ||
516 | RADEON_SOFT_RESET_E2 | | ||
517 | RADEON_SOFT_RESET_RB)); | ||
518 | RADEON_READ(RADEON_RBBM_SOFT_RESET); | ||
519 | RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & | ||
520 | ~(RADEON_SOFT_RESET_CP | | ||
521 | RADEON_SOFT_RESET_HI | | ||
522 | RADEON_SOFT_RESET_SE | | ||
523 | RADEON_SOFT_RESET_RE | | ||
524 | RADEON_SOFT_RESET_PP | | ||
525 | RADEON_SOFT_RESET_E2 | | ||
526 | RADEON_SOFT_RESET_RB))); | ||
527 | RADEON_READ(RADEON_RBBM_SOFT_RESET); | ||
528 | |||
529 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { | ||
530 | RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); | ||
531 | RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); | ||
532 | RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); | ||
533 | } | ||
534 | |||
535 | /* setup the raster pipes */ | ||
536 | if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300) | ||
537 | radeon_init_pipes(dev_priv); | ||
538 | |||
539 | /* Reset the CP ring */ | ||
540 | radeon_do_cp_reset(dev_priv); | ||
541 | |||
542 | /* The CP is no longer running after an engine reset */ | ||
543 | dev_priv->cp_running = 0; | ||
544 | |||
545 | /* Reset any pending vertex, indirect buffers */ | ||
546 | radeon_freelist_reset(dev); | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static void radeon_cp_init_ring_buffer(struct drm_device * dev, | ||
552 | drm_radeon_private_t * dev_priv) | ||
553 | { | ||
554 | u32 ring_start, cur_read_ptr; | ||
555 | u32 tmp; | ||
556 | |||
557 | /* Initialize the memory controller. With new memory map, the fb location | ||
558 | * is not changed, it should have been properly initialized already. Part | ||
559 | * of the problem is that the code below is bogus, assuming the GART is | ||
560 | * always appended to the fb which is not necessarily the case | ||
561 | */ | ||
562 | if (!dev_priv->new_memmap) | ||
563 | radeon_write_fb_location(dev_priv, | ||
564 | ((dev_priv->gart_vm_start - 1) & 0xffff0000) | ||
565 | | (dev_priv->fb_location >> 16)); | ||
566 | |||
567 | #if __OS_HAS_AGP | ||
568 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
569 | radeon_write_agp_base(dev_priv, dev->agp->base); | ||
570 | |||
571 | radeon_write_agp_location(dev_priv, | ||
572 | (((dev_priv->gart_vm_start - 1 + | ||
573 | dev_priv->gart_size) & 0xffff0000) | | ||
574 | (dev_priv->gart_vm_start >> 16))); | ||
575 | |||
576 | ring_start = (dev_priv->cp_ring->offset | ||
577 | - dev->agp->base | ||
578 | + dev_priv->gart_vm_start); | ||
579 | } else | ||
580 | #endif | ||
581 | ring_start = (dev_priv->cp_ring->offset | ||
582 | - (unsigned long)dev->sg->virtual | ||
583 | + dev_priv->gart_vm_start); | ||
584 | |||
585 | RADEON_WRITE(RADEON_CP_RB_BASE, ring_start); | ||
586 | |||
587 | /* Set the write pointer delay */ | ||
588 | RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0); | ||
589 | |||
590 | /* Initialize the ring buffer's read and write pointers */ | ||
591 | cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); | ||
592 | RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); | ||
593 | SET_RING_HEAD(dev_priv, cur_read_ptr); | ||
594 | dev_priv->ring.tail = cur_read_ptr; | ||
595 | |||
596 | #if __OS_HAS_AGP | ||
597 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
598 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, | ||
599 | dev_priv->ring_rptr->offset | ||
600 | - dev->agp->base + dev_priv->gart_vm_start); | ||
601 | } else | ||
602 | #endif | ||
603 | { | ||
604 | struct drm_sg_mem *entry = dev->sg; | ||
605 | unsigned long tmp_ofs, page_ofs; | ||
606 | |||
607 | tmp_ofs = dev_priv->ring_rptr->offset - | ||
608 | (unsigned long)dev->sg->virtual; | ||
609 | page_ofs = tmp_ofs >> PAGE_SHIFT; | ||
610 | |||
611 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); | ||
612 | DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n", | ||
613 | (unsigned long)entry->busaddr[page_ofs], | ||
614 | entry->handle + tmp_ofs); | ||
615 | } | ||
616 | |||
617 | /* Set ring buffer size */ | ||
618 | #ifdef __BIG_ENDIAN | ||
619 | RADEON_WRITE(RADEON_CP_RB_CNTL, | ||
620 | RADEON_BUF_SWAP_32BIT | | ||
621 | (dev_priv->ring.fetch_size_l2ow << 18) | | ||
622 | (dev_priv->ring.rptr_update_l2qw << 8) | | ||
623 | dev_priv->ring.size_l2qw); | ||
624 | #else | ||
625 | RADEON_WRITE(RADEON_CP_RB_CNTL, | ||
626 | (dev_priv->ring.fetch_size_l2ow << 18) | | ||
627 | (dev_priv->ring.rptr_update_l2qw << 8) | | ||
628 | dev_priv->ring.size_l2qw); | ||
629 | #endif | ||
630 | |||
631 | /* Start with assuming that writeback doesn't work */ | ||
632 | dev_priv->writeback_works = 0; | ||
633 | |||
634 | /* Initialize the scratch register pointer. This will cause | ||
635 | * the scratch register values to be written out to memory | ||
636 | * whenever they are updated. | ||
637 | * | ||
638 | * We simply put this behind the ring read pointer, this works | ||
639 | * with PCI GART as well as (whatever kind of) AGP GART | ||
640 | */ | ||
641 | RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) | ||
642 | + RADEON_SCRATCH_REG_OFFSET); | ||
643 | |||
644 | dev_priv->scratch = ((__volatile__ u32 *) | ||
645 | dev_priv->ring_rptr->handle + | ||
646 | (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); | ||
647 | |||
648 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); | ||
649 | |||
650 | /* Turn on bus mastering */ | ||
651 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
652 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); | ||
653 | |||
654 | dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; | ||
655 | RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); | ||
656 | |||
657 | dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; | ||
658 | RADEON_WRITE(RADEON_LAST_DISPATCH_REG, | ||
659 | dev_priv->sarea_priv->last_dispatch); | ||
660 | |||
661 | dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; | ||
662 | RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); | ||
663 | |||
664 | radeon_do_wait_for_idle(dev_priv); | ||
665 | |||
666 | /* Sync everything up */ | ||
667 | RADEON_WRITE(RADEON_ISYNC_CNTL, | ||
668 | (RADEON_ISYNC_ANY2D_IDLE3D | | ||
669 | RADEON_ISYNC_ANY3D_IDLE2D | | ||
670 | RADEON_ISYNC_WAIT_IDLEGUI | | ||
671 | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); | ||
672 | |||
673 | } | ||
674 | |||
675 | static void radeon_test_writeback(drm_radeon_private_t * dev_priv) | ||
676 | { | ||
677 | u32 tmp; | ||
678 | |||
679 | /* Writeback doesn't seem to work everywhere, test it here and possibly | ||
680 | * enable it if it appears to work | ||
681 | */ | ||
682 | DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); | ||
683 | RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); | ||
684 | |||
685 | for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { | ||
686 | if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == | ||
687 | 0xdeadbeef) | ||
688 | break; | ||
689 | DRM_UDELAY(1); | ||
690 | } | ||
691 | |||
692 | if (tmp < dev_priv->usec_timeout) { | ||
693 | dev_priv->writeback_works = 1; | ||
694 | DRM_INFO("writeback test succeeded in %d usecs\n", tmp); | ||
695 | } else { | ||
696 | dev_priv->writeback_works = 0; | ||
697 | DRM_INFO("writeback test failed\n"); | ||
698 | } | ||
699 | if (radeon_no_wb == 1) { | ||
700 | dev_priv->writeback_works = 0; | ||
701 | DRM_INFO("writeback forced off\n"); | ||
702 | } | ||
703 | |||
704 | if (!dev_priv->writeback_works) { | ||
705 | /* Disable writeback to avoid unnecessary bus master transfer */ | ||
706 | RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | | ||
707 | RADEON_RB_NO_UPDATE); | ||
708 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); | ||
709 | } | ||
710 | } | ||
711 | |||
712 | /* Enable or disable IGP GART on the chip */ | ||
713 | static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) | ||
714 | { | ||
715 | u32 temp; | ||
716 | |||
717 | if (on) { | ||
718 | DRM_DEBUG("programming igp gart %08X %08lX %08X\n", | ||
719 | dev_priv->gart_vm_start, | ||
720 | (long)dev_priv->gart_info.bus_addr, | ||
721 | dev_priv->gart_size); | ||
722 | |||
723 | temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL); | ||
724 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) | ||
725 | IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN | | ||
726 | RS690_BLOCK_GFX_D3_EN)); | ||
727 | else | ||
728 | IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); | ||
729 | |||
730 | IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | | ||
731 | RS480_VA_SIZE_32MB)); | ||
732 | |||
733 | temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID); | ||
734 | IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN | | ||
735 | RS480_TLB_ENABLE | | ||
736 | RS480_GTW_LAC_EN | | ||
737 | RS480_1LEVEL_GART)); | ||
738 | |||
739 | temp = dev_priv->gart_info.bus_addr & 0xfffff000; | ||
740 | temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4; | ||
741 | IGP_WRITE_MCIND(RS480_GART_BASE, temp); | ||
742 | |||
743 | temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL); | ||
744 | IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) | | ||
745 | RS480_REQ_TYPE_SNOOP_DIS)); | ||
746 | |||
747 | radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start); | ||
748 | |||
749 | dev_priv->gart_size = 32*1024*1024; | ||
750 | temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & | ||
751 | 0xffff0000) | (dev_priv->gart_vm_start >> 16)); | ||
752 | |||
753 | radeon_write_agp_location(dev_priv, temp); | ||
754 | |||
755 | temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE); | ||
756 | IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | | ||
757 | RS480_VA_SIZE_32MB)); | ||
758 | |||
759 | do { | ||
760 | temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); | ||
761 | if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) | ||
762 | break; | ||
763 | DRM_UDELAY(1); | ||
764 | } while (1); | ||
765 | |||
766 | IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, | ||
767 | RS480_GART_CACHE_INVALIDATE); | ||
768 | |||
769 | do { | ||
770 | temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); | ||
771 | if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) | ||
772 | break; | ||
773 | DRM_UDELAY(1); | ||
774 | } while (1); | ||
775 | |||
776 | IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0); | ||
777 | } else { | ||
778 | IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) | ||
783 | { | ||
784 | u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); | ||
785 | if (on) { | ||
786 | |||
787 | DRM_DEBUG("programming pcie %08X %08lX %08X\n", | ||
788 | dev_priv->gart_vm_start, | ||
789 | (long)dev_priv->gart_info.bus_addr, | ||
790 | dev_priv->gart_size); | ||
791 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, | ||
792 | dev_priv->gart_vm_start); | ||
793 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, | ||
794 | dev_priv->gart_info.bus_addr); | ||
795 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, | ||
796 | dev_priv->gart_vm_start); | ||
797 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, | ||
798 | dev_priv->gart_vm_start + | ||
799 | dev_priv->gart_size - 1); | ||
800 | |||
801 | radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */ | ||
802 | |||
803 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, | ||
804 | RADEON_PCIE_TX_GART_EN); | ||
805 | } else { | ||
806 | RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, | ||
807 | tmp & ~RADEON_PCIE_TX_GART_EN); | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* Enable or disable PCI GART on the chip */ | ||
812 | static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) | ||
813 | { | ||
814 | u32 tmp; | ||
815 | |||
816 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || | ||
817 | (dev_priv->flags & RADEON_IS_IGPGART)) { | ||
818 | radeon_set_igpgart(dev_priv, on); | ||
819 | return; | ||
820 | } | ||
821 | |||
822 | if (dev_priv->flags & RADEON_IS_PCIE) { | ||
823 | radeon_set_pciegart(dev_priv, on); | ||
824 | return; | ||
825 | } | ||
826 | |||
827 | tmp = RADEON_READ(RADEON_AIC_CNTL); | ||
828 | |||
829 | if (on) { | ||
830 | RADEON_WRITE(RADEON_AIC_CNTL, | ||
831 | tmp | RADEON_PCIGART_TRANSLATE_EN); | ||
832 | |||
833 | /* set PCI GART page-table base address | ||
834 | */ | ||
835 | RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr); | ||
836 | |||
837 | /* set address range for PCI address translate | ||
838 | */ | ||
839 | RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start); | ||
840 | RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start | ||
841 | + dev_priv->gart_size - 1); | ||
842 | |||
843 | /* Turn off AGP aperture -- is this required for PCI GART? | ||
844 | */ | ||
845 | radeon_write_agp_location(dev_priv, 0xffffffc0); | ||
846 | RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */ | ||
847 | } else { | ||
848 | RADEON_WRITE(RADEON_AIC_CNTL, | ||
849 | tmp & ~RADEON_PCIGART_TRANSLATE_EN); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) | ||
854 | { | ||
855 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
856 | |||
857 | DRM_DEBUG("\n"); | ||
858 | |||
859 | /* if we require new memory map but we don't have it fail */ | ||
860 | if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { | ||
861 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); | ||
862 | radeon_do_cleanup_cp(dev); | ||
863 | return -EINVAL; | ||
864 | } | ||
865 | |||
866 | if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { | ||
867 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); | ||
868 | dev_priv->flags &= ~RADEON_IS_AGP; | ||
869 | } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) | ||
870 | && !init->is_pci) { | ||
871 | DRM_DEBUG("Restoring AGP flag\n"); | ||
872 | dev_priv->flags |= RADEON_IS_AGP; | ||
873 | } | ||
874 | |||
875 | if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { | ||
876 | DRM_ERROR("PCI GART memory not allocated!\n"); | ||
877 | radeon_do_cleanup_cp(dev); | ||
878 | return -EINVAL; | ||
879 | } | ||
880 | |||
881 | dev_priv->usec_timeout = init->usec_timeout; | ||
882 | if (dev_priv->usec_timeout < 1 || | ||
883 | dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { | ||
884 | DRM_DEBUG("TIMEOUT problem!\n"); | ||
885 | radeon_do_cleanup_cp(dev); | ||
886 | return -EINVAL; | ||
887 | } | ||
888 | |||
889 | /* Enable vblank on CRTC1 for older X servers | ||
890 | */ | ||
891 | dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; | ||
892 | |||
893 | switch(init->func) { | ||
894 | case RADEON_INIT_R200_CP: | ||
895 | dev_priv->microcode_version = UCODE_R200; | ||
896 | break; | ||
897 | case RADEON_INIT_R300_CP: | ||
898 | dev_priv->microcode_version = UCODE_R300; | ||
899 | break; | ||
900 | default: | ||
901 | dev_priv->microcode_version = UCODE_R100; | ||
902 | } | ||
903 | |||
904 | dev_priv->do_boxes = 0; | ||
905 | dev_priv->cp_mode = init->cp_mode; | ||
906 | |||
907 | /* We don't support anything other than bus-mastering ring mode, | ||
908 | * but the ring can be in either AGP or PCI space for the ring | ||
909 | * read pointer. | ||
910 | */ | ||
911 | if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && | ||
912 | (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { | ||
913 | DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); | ||
914 | radeon_do_cleanup_cp(dev); | ||
915 | return -EINVAL; | ||
916 | } | ||
917 | |||
918 | switch (init->fb_bpp) { | ||
919 | case 16: | ||
920 | dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; | ||
921 | break; | ||
922 | case 32: | ||
923 | default: | ||
924 | dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; | ||
925 | break; | ||
926 | } | ||
927 | dev_priv->front_offset = init->front_offset; | ||
928 | dev_priv->front_pitch = init->front_pitch; | ||
929 | dev_priv->back_offset = init->back_offset; | ||
930 | dev_priv->back_pitch = init->back_pitch; | ||
931 | |||
932 | switch (init->depth_bpp) { | ||
933 | case 16: | ||
934 | dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; | ||
935 | break; | ||
936 | case 32: | ||
937 | default: | ||
938 | dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; | ||
939 | break; | ||
940 | } | ||
941 | dev_priv->depth_offset = init->depth_offset; | ||
942 | dev_priv->depth_pitch = init->depth_pitch; | ||
943 | |||
944 | /* Hardware state for depth clears. Remove this if/when we no | ||
945 | * longer clear the depth buffer with a 3D rectangle. Hard-code | ||
946 | * all values to prevent unwanted 3D state from slipping through | ||
947 | * and screwing with the clear operation. | ||
948 | */ | ||
949 | dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | | ||
950 | (dev_priv->color_fmt << 10) | | ||
951 | (dev_priv->microcode_version == | ||
952 | UCODE_R100 ? RADEON_ZBLOCK16 : 0)); | ||
953 | |||
954 | dev_priv->depth_clear.rb3d_zstencilcntl = | ||
955 | (dev_priv->depth_fmt | | ||
956 | RADEON_Z_TEST_ALWAYS | | ||
957 | RADEON_STENCIL_TEST_ALWAYS | | ||
958 | RADEON_STENCIL_S_FAIL_REPLACE | | ||
959 | RADEON_STENCIL_ZPASS_REPLACE | | ||
960 | RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE); | ||
961 | |||
962 | dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | | ||
963 | RADEON_BFACE_SOLID | | ||
964 | RADEON_FFACE_SOLID | | ||
965 | RADEON_FLAT_SHADE_VTX_LAST | | ||
966 | RADEON_DIFFUSE_SHADE_FLAT | | ||
967 | RADEON_ALPHA_SHADE_FLAT | | ||
968 | RADEON_SPECULAR_SHADE_FLAT | | ||
969 | RADEON_FOG_SHADE_FLAT | | ||
970 | RADEON_VTX_PIX_CENTER_OGL | | ||
971 | RADEON_ROUND_MODE_TRUNC | | ||
972 | RADEON_ROUND_PREC_8TH_PIX); | ||
973 | |||
974 | |||
975 | dev_priv->ring_offset = init->ring_offset; | ||
976 | dev_priv->ring_rptr_offset = init->ring_rptr_offset; | ||
977 | dev_priv->buffers_offset = init->buffers_offset; | ||
978 | dev_priv->gart_textures_offset = init->gart_textures_offset; | ||
979 | |||
980 | dev_priv->sarea = drm_getsarea(dev); | ||
981 | if (!dev_priv->sarea) { | ||
982 | DRM_ERROR("could not find sarea!\n"); | ||
983 | radeon_do_cleanup_cp(dev); | ||
984 | return -EINVAL; | ||
985 | } | ||
986 | |||
987 | dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); | ||
988 | if (!dev_priv->cp_ring) { | ||
989 | DRM_ERROR("could not find cp ring region!\n"); | ||
990 | radeon_do_cleanup_cp(dev); | ||
991 | return -EINVAL; | ||
992 | } | ||
993 | dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); | ||
994 | if (!dev_priv->ring_rptr) { | ||
995 | DRM_ERROR("could not find ring read pointer!\n"); | ||
996 | radeon_do_cleanup_cp(dev); | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | dev->agp_buffer_token = init->buffers_offset; | ||
1000 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); | ||
1001 | if (!dev->agp_buffer_map) { | ||
1002 | DRM_ERROR("could not find dma buffer region!\n"); | ||
1003 | radeon_do_cleanup_cp(dev); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | |||
1007 | if (init->gart_textures_offset) { | ||
1008 | dev_priv->gart_textures = | ||
1009 | drm_core_findmap(dev, init->gart_textures_offset); | ||
1010 | if (!dev_priv->gart_textures) { | ||
1011 | DRM_ERROR("could not find GART texture region!\n"); | ||
1012 | radeon_do_cleanup_cp(dev); | ||
1013 | return -EINVAL; | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | dev_priv->sarea_priv = | ||
1018 | (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle + | ||
1019 | init->sarea_priv_offset); | ||
1020 | |||
1021 | #if __OS_HAS_AGP | ||
1022 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
1023 | drm_core_ioremap(dev_priv->cp_ring, dev); | ||
1024 | drm_core_ioremap(dev_priv->ring_rptr, dev); | ||
1025 | drm_core_ioremap(dev->agp_buffer_map, dev); | ||
1026 | if (!dev_priv->cp_ring->handle || | ||
1027 | !dev_priv->ring_rptr->handle || | ||
1028 | !dev->agp_buffer_map->handle) { | ||
1029 | DRM_ERROR("could not find ioremap agp regions!\n"); | ||
1030 | radeon_do_cleanup_cp(dev); | ||
1031 | return -EINVAL; | ||
1032 | } | ||
1033 | } else | ||
1034 | #endif | ||
1035 | { | ||
1036 | dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset; | ||
1037 | dev_priv->ring_rptr->handle = | ||
1038 | (void *)dev_priv->ring_rptr->offset; | ||
1039 | dev->agp_buffer_map->handle = | ||
1040 | (void *)dev->agp_buffer_map->offset; | ||
1041 | |||
1042 | DRM_DEBUG("dev_priv->cp_ring->handle %p\n", | ||
1043 | dev_priv->cp_ring->handle); | ||
1044 | DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", | ||
1045 | dev_priv->ring_rptr->handle); | ||
1046 | DRM_DEBUG("dev->agp_buffer_map->handle %p\n", | ||
1047 | dev->agp_buffer_map->handle); | ||
1048 | } | ||
1049 | |||
1050 | dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; | ||
1051 | dev_priv->fb_size = | ||
1052 | ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) | ||
1053 | - dev_priv->fb_location; | ||
1054 | |||
1055 | dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | | ||
1056 | ((dev_priv->front_offset | ||
1057 | + dev_priv->fb_location) >> 10)); | ||
1058 | |||
1059 | dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | | ||
1060 | ((dev_priv->back_offset | ||
1061 | + dev_priv->fb_location) >> 10)); | ||
1062 | |||
1063 | dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | | ||
1064 | ((dev_priv->depth_offset | ||
1065 | + dev_priv->fb_location) >> 10)); | ||
1066 | |||
1067 | dev_priv->gart_size = init->gart_size; | ||
1068 | |||
1069 | /* New let's set the memory map ... */ | ||
1070 | if (dev_priv->new_memmap) { | ||
1071 | u32 base = 0; | ||
1072 | |||
1073 | DRM_INFO("Setting GART location based on new memory map\n"); | ||
1074 | |||
1075 | /* If using AGP, try to locate the AGP aperture at the same | ||
1076 | * location in the card and on the bus, though we have to | ||
1077 | * align it down. | ||
1078 | */ | ||
1079 | #if __OS_HAS_AGP | ||
1080 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
1081 | base = dev->agp->base; | ||
1082 | /* Check if valid */ | ||
1083 | if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && | ||
1084 | base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { | ||
1085 | DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", | ||
1086 | dev->agp->base); | ||
1087 | base = 0; | ||
1088 | } | ||
1089 | } | ||
1090 | #endif | ||
1091 | /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ | ||
1092 | if (base == 0) { | ||
1093 | base = dev_priv->fb_location + dev_priv->fb_size; | ||
1094 | if (base < dev_priv->fb_location || | ||
1095 | ((base + dev_priv->gart_size) & 0xfffffffful) < base) | ||
1096 | base = dev_priv->fb_location | ||
1097 | - dev_priv->gart_size; | ||
1098 | } | ||
1099 | dev_priv->gart_vm_start = base & 0xffc00000u; | ||
1100 | if (dev_priv->gart_vm_start != base) | ||
1101 | DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", | ||
1102 | base, dev_priv->gart_vm_start); | ||
1103 | } else { | ||
1104 | DRM_INFO("Setting GART location based on old memory map\n"); | ||
1105 | dev_priv->gart_vm_start = dev_priv->fb_location + | ||
1106 | RADEON_READ(RADEON_CONFIG_APER_SIZE); | ||
1107 | } | ||
1108 | |||
1109 | #if __OS_HAS_AGP | ||
1110 | if (dev_priv->flags & RADEON_IS_AGP) | ||
1111 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset | ||
1112 | - dev->agp->base | ||
1113 | + dev_priv->gart_vm_start); | ||
1114 | else | ||
1115 | #endif | ||
1116 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset | ||
1117 | - (unsigned long)dev->sg->virtual | ||
1118 | + dev_priv->gart_vm_start); | ||
1119 | |||
1120 | DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); | ||
1121 | DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start); | ||
1122 | DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n", | ||
1123 | dev_priv->gart_buffers_offset); | ||
1124 | |||
1125 | dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; | ||
1126 | dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle | ||
1127 | + init->ring_size / sizeof(u32)); | ||
1128 | dev_priv->ring.size = init->ring_size; | ||
1129 | dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); | ||
1130 | |||
1131 | dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; | ||
1132 | dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8); | ||
1133 | |||
1134 | dev_priv->ring.fetch_size = /* init->fetch_size */ 32; | ||
1135 | dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16); | ||
1136 | dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; | ||
1137 | |||
1138 | dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; | ||
1139 | |||
1140 | #if __OS_HAS_AGP | ||
1141 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
1142 | /* Turn off PCI GART */ | ||
1143 | radeon_set_pcigart(dev_priv, 0); | ||
1144 | } else | ||
1145 | #endif | ||
1146 | { | ||
1147 | dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); | ||
1148 | /* if we have an offset set from userspace */ | ||
1149 | if (dev_priv->pcigart_offset_set) { | ||
1150 | dev_priv->gart_info.bus_addr = | ||
1151 | dev_priv->pcigart_offset + dev_priv->fb_location; | ||
1152 | dev_priv->gart_info.mapping.offset = | ||
1153 | dev_priv->pcigart_offset + dev_priv->fb_aper_offset; | ||
1154 | dev_priv->gart_info.mapping.size = | ||
1155 | dev_priv->gart_info.table_size; | ||
1156 | |||
1157 | drm_core_ioremap(&dev_priv->gart_info.mapping, dev); | ||
1158 | dev_priv->gart_info.addr = | ||
1159 | dev_priv->gart_info.mapping.handle; | ||
1160 | |||
1161 | if (dev_priv->flags & RADEON_IS_PCIE) | ||
1162 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; | ||
1163 | else | ||
1164 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; | ||
1165 | dev_priv->gart_info.gart_table_location = | ||
1166 | DRM_ATI_GART_FB; | ||
1167 | |||
1168 | DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", | ||
1169 | dev_priv->gart_info.addr, | ||
1170 | dev_priv->pcigart_offset); | ||
1171 | } else { | ||
1172 | if (dev_priv->flags & RADEON_IS_IGPGART) | ||
1173 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; | ||
1174 | else | ||
1175 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; | ||
1176 | dev_priv->gart_info.gart_table_location = | ||
1177 | DRM_ATI_GART_MAIN; | ||
1178 | dev_priv->gart_info.addr = NULL; | ||
1179 | dev_priv->gart_info.bus_addr = 0; | ||
1180 | if (dev_priv->flags & RADEON_IS_PCIE) { | ||
1181 | DRM_ERROR | ||
1182 | ("Cannot use PCI Express without GART in FB memory\n"); | ||
1183 | radeon_do_cleanup_cp(dev); | ||
1184 | return -EINVAL; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { | ||
1189 | DRM_ERROR("failed to init PCI GART!\n"); | ||
1190 | radeon_do_cleanup_cp(dev); | ||
1191 | return -ENOMEM; | ||
1192 | } | ||
1193 | |||
1194 | /* Turn on PCI GART */ | ||
1195 | radeon_set_pcigart(dev_priv, 1); | ||
1196 | } | ||
1197 | |||
1198 | radeon_cp_load_microcode(dev_priv); | ||
1199 | radeon_cp_init_ring_buffer(dev, dev_priv); | ||
1200 | |||
1201 | dev_priv->last_buf = 0; | ||
1202 | |||
1203 | radeon_do_engine_reset(dev); | ||
1204 | radeon_test_writeback(dev_priv); | ||
1205 | |||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | static int radeon_do_cleanup_cp(struct drm_device * dev) | ||
1210 | { | ||
1211 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1212 | DRM_DEBUG("\n"); | ||
1213 | |||
1214 | /* Make sure interrupts are disabled here because the uninstall ioctl | ||
1215 | * may not have been called from userspace and after dev_private | ||
1216 | * is freed, it's too late. | ||
1217 | */ | ||
1218 | if (dev->irq_enabled) | ||
1219 | drm_irq_uninstall(dev); | ||
1220 | |||
1221 | #if __OS_HAS_AGP | ||
1222 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
1223 | if (dev_priv->cp_ring != NULL) { | ||
1224 | drm_core_ioremapfree(dev_priv->cp_ring, dev); | ||
1225 | dev_priv->cp_ring = NULL; | ||
1226 | } | ||
1227 | if (dev_priv->ring_rptr != NULL) { | ||
1228 | drm_core_ioremapfree(dev_priv->ring_rptr, dev); | ||
1229 | dev_priv->ring_rptr = NULL; | ||
1230 | } | ||
1231 | if (dev->agp_buffer_map != NULL) { | ||
1232 | drm_core_ioremapfree(dev->agp_buffer_map, dev); | ||
1233 | dev->agp_buffer_map = NULL; | ||
1234 | } | ||
1235 | } else | ||
1236 | #endif | ||
1237 | { | ||
1238 | |||
1239 | if (dev_priv->gart_info.bus_addr) { | ||
1240 | /* Turn off PCI GART */ | ||
1241 | radeon_set_pcigart(dev_priv, 0); | ||
1242 | if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) | ||
1243 | DRM_ERROR("failed to cleanup PCI GART!\n"); | ||
1244 | } | ||
1245 | |||
1246 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) | ||
1247 | { | ||
1248 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); | ||
1249 | dev_priv->gart_info.addr = 0; | ||
1250 | } | ||
1251 | } | ||
1252 | /* only clear to the start of flags */ | ||
1253 | memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); | ||
1254 | |||
1255 | return 0; | ||
1256 | } | ||
1257 | |||
1258 | /* This code will reinit the Radeon CP hardware after a resume from disc. | ||
1259 | * AFAIK, it would be very difficult to pickle the state at suspend time, so | ||
1260 | * here we make sure that all Radeon hardware initialisation is re-done without | ||
1261 | * affecting running applications. | ||
1262 | * | ||
1263 | * Charl P. Botha <http://cpbotha.net> | ||
1264 | */ | ||
1265 | static int radeon_do_resume_cp(struct drm_device * dev) | ||
1266 | { | ||
1267 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1268 | |||
1269 | if (!dev_priv) { | ||
1270 | DRM_ERROR("Called with no initialization\n"); | ||
1271 | return -EINVAL; | ||
1272 | } | ||
1273 | |||
1274 | DRM_DEBUG("Starting radeon_do_resume_cp()\n"); | ||
1275 | |||
1276 | #if __OS_HAS_AGP | ||
1277 | if (dev_priv->flags & RADEON_IS_AGP) { | ||
1278 | /* Turn off PCI GART */ | ||
1279 | radeon_set_pcigart(dev_priv, 0); | ||
1280 | } else | ||
1281 | #endif | ||
1282 | { | ||
1283 | /* Turn on PCI GART */ | ||
1284 | radeon_set_pcigart(dev_priv, 1); | ||
1285 | } | ||
1286 | |||
1287 | radeon_cp_load_microcode(dev_priv); | ||
1288 | radeon_cp_init_ring_buffer(dev, dev_priv); | ||
1289 | |||
1290 | radeon_do_engine_reset(dev); | ||
1291 | radeon_enable_interrupt(dev); | ||
1292 | |||
1293 | DRM_DEBUG("radeon_do_resume_cp() complete\n"); | ||
1294 | |||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1299 | { | ||
1300 | drm_radeon_init_t *init = data; | ||
1301 | |||
1302 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1303 | |||
1304 | if (init->func == RADEON_INIT_R300_CP) | ||
1305 | r300_init_reg_flags(dev); | ||
1306 | |||
1307 | switch (init->func) { | ||
1308 | case RADEON_INIT_CP: | ||
1309 | case RADEON_INIT_R200_CP: | ||
1310 | case RADEON_INIT_R300_CP: | ||
1311 | return radeon_do_init_cp(dev, init); | ||
1312 | case RADEON_CLEANUP_CP: | ||
1313 | return radeon_do_cleanup_cp(dev); | ||
1314 | } | ||
1315 | |||
1316 | return -EINVAL; | ||
1317 | } | ||
1318 | |||
1319 | int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1320 | { | ||
1321 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1322 | DRM_DEBUG("\n"); | ||
1323 | |||
1324 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1325 | |||
1326 | if (dev_priv->cp_running) { | ||
1327 | DRM_DEBUG("while CP running\n"); | ||
1328 | return 0; | ||
1329 | } | ||
1330 | if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { | ||
1331 | DRM_DEBUG("called with bogus CP mode (%d)\n", | ||
1332 | dev_priv->cp_mode); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | radeon_do_cp_start(dev_priv); | ||
1337 | |||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | /* Stop the CP. The engine must have been idled before calling this | ||
1342 | * routine. | ||
1343 | */ | ||
1344 | int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1345 | { | ||
1346 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1347 | drm_radeon_cp_stop_t *stop = data; | ||
1348 | int ret; | ||
1349 | DRM_DEBUG("\n"); | ||
1350 | |||
1351 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1352 | |||
1353 | if (!dev_priv->cp_running) | ||
1354 | return 0; | ||
1355 | |||
1356 | /* Flush any pending CP commands. This ensures any outstanding | ||
1357 | * commands are exectuted by the engine before we turn it off. | ||
1358 | */ | ||
1359 | if (stop->flush) { | ||
1360 | radeon_do_cp_flush(dev_priv); | ||
1361 | } | ||
1362 | |||
1363 | /* If we fail to make the engine go idle, we return an error | ||
1364 | * code so that the DRM ioctl wrapper can try again. | ||
1365 | */ | ||
1366 | if (stop->idle) { | ||
1367 | ret = radeon_do_cp_idle(dev_priv); | ||
1368 | if (ret) | ||
1369 | return ret; | ||
1370 | } | ||
1371 | |||
1372 | /* Finally, we can turn off the CP. If the engine isn't idle, | ||
1373 | * we will get some dropped triangles as they won't be fully | ||
1374 | * rendered before the CP is shut down. | ||
1375 | */ | ||
1376 | radeon_do_cp_stop(dev_priv); | ||
1377 | |||
1378 | /* Reset the engine */ | ||
1379 | radeon_do_engine_reset(dev); | ||
1380 | |||
1381 | return 0; | ||
1382 | } | ||
1383 | |||
1384 | void radeon_do_release(struct drm_device * dev) | ||
1385 | { | ||
1386 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1387 | int i, ret; | ||
1388 | |||
1389 | if (dev_priv) { | ||
1390 | if (dev_priv->cp_running) { | ||
1391 | /* Stop the cp */ | ||
1392 | while ((ret = radeon_do_cp_idle(dev_priv)) != 0) { | ||
1393 | DRM_DEBUG("radeon_do_cp_idle %d\n", ret); | ||
1394 | #ifdef __linux__ | ||
1395 | schedule(); | ||
1396 | #else | ||
1397 | tsleep(&ret, PZERO, "rdnrel", 1); | ||
1398 | #endif | ||
1399 | } | ||
1400 | radeon_do_cp_stop(dev_priv); | ||
1401 | radeon_do_engine_reset(dev); | ||
1402 | } | ||
1403 | |||
1404 | /* Disable *all* interrupts */ | ||
1405 | if (dev_priv->mmio) /* remove this after permanent addmaps */ | ||
1406 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); | ||
1407 | |||
1408 | if (dev_priv->mmio) { /* remove all surfaces */ | ||
1409 | for (i = 0; i < RADEON_MAX_SURFACES; i++) { | ||
1410 | RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0); | ||
1411 | RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + | ||
1412 | 16 * i, 0); | ||
1413 | RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + | ||
1414 | 16 * i, 0); | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | /* Free memory heap structures */ | ||
1419 | radeon_mem_takedown(&(dev_priv->gart_heap)); | ||
1420 | radeon_mem_takedown(&(dev_priv->fb_heap)); | ||
1421 | |||
1422 | /* deallocate kernel resources */ | ||
1423 | radeon_do_cleanup_cp(dev); | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | /* Just reset the CP ring. Called as part of an X Server engine reset. | ||
1428 | */ | ||
1429 | int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1430 | { | ||
1431 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1432 | DRM_DEBUG("\n"); | ||
1433 | |||
1434 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1435 | |||
1436 | if (!dev_priv) { | ||
1437 | DRM_DEBUG("called before init done\n"); | ||
1438 | return -EINVAL; | ||
1439 | } | ||
1440 | |||
1441 | radeon_do_cp_reset(dev_priv); | ||
1442 | |||
1443 | /* The CP is no longer running after an engine reset */ | ||
1444 | dev_priv->cp_running = 0; | ||
1445 | |||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1450 | { | ||
1451 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1452 | DRM_DEBUG("\n"); | ||
1453 | |||
1454 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1455 | |||
1456 | return radeon_do_cp_idle(dev_priv); | ||
1457 | } | ||
1458 | |||
1459 | /* Added by Charl P. Botha to call radeon_do_resume_cp(). | ||
1460 | */ | ||
1461 | int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1462 | { | ||
1463 | |||
1464 | return radeon_do_resume_cp(dev); | ||
1465 | } | ||
1466 | |||
1467 | int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1468 | { | ||
1469 | DRM_DEBUG("\n"); | ||
1470 | |||
1471 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1472 | |||
1473 | return radeon_do_engine_reset(dev); | ||
1474 | } | ||
1475 | |||
1476 | /* ================================================================ | ||
1477 | * Fullscreen mode | ||
1478 | */ | ||
1479 | |||
1480 | /* KW: Deprecated to say the least: | ||
1481 | */ | ||
1482 | int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1483 | { | ||
1484 | return 0; | ||
1485 | } | ||
1486 | |||
1487 | /* ================================================================ | ||
1488 | * Freelist management | ||
1489 | */ | ||
1490 | |||
1491 | /* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through | ||
1492 | * bufs until freelist code is used. Note this hides a problem with | ||
1493 | * the scratch register * (used to keep track of last buffer | ||
1494 | * completed) being written to before * the last buffer has actually | ||
1495 | * completed rendering. | ||
1496 | * | ||
1497 | * KW: It's also a good way to find free buffers quickly. | ||
1498 | * | ||
1499 | * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't | ||
1500 | * sleep. However, bugs in older versions of radeon_accel.c mean that | ||
1501 | * we essentially have to do this, else old clients will break. | ||
1502 | * | ||
1503 | * However, it does leave open a potential deadlock where all the | ||
1504 | * buffers are held by other clients, which can't release them because | ||
1505 | * they can't get the lock. | ||
1506 | */ | ||
1507 | |||
1508 | struct drm_buf *radeon_freelist_get(struct drm_device * dev) | ||
1509 | { | ||
1510 | struct drm_device_dma *dma = dev->dma; | ||
1511 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1512 | drm_radeon_buf_priv_t *buf_priv; | ||
1513 | struct drm_buf *buf; | ||
1514 | int i, t; | ||
1515 | int start; | ||
1516 | |||
1517 | if (++dev_priv->last_buf >= dma->buf_count) | ||
1518 | dev_priv->last_buf = 0; | ||
1519 | |||
1520 | start = dev_priv->last_buf; | ||
1521 | |||
1522 | for (t = 0; t < dev_priv->usec_timeout; t++) { | ||
1523 | u32 done_age = GET_SCRATCH(1); | ||
1524 | DRM_DEBUG("done_age = %d\n", done_age); | ||
1525 | for (i = start; i < dma->buf_count; i++) { | ||
1526 | buf = dma->buflist[i]; | ||
1527 | buf_priv = buf->dev_private; | ||
1528 | if (buf->file_priv == NULL || (buf->pending && | ||
1529 | buf_priv->age <= | ||
1530 | done_age)) { | ||
1531 | dev_priv->stats.requested_bufs++; | ||
1532 | buf->pending = 0; | ||
1533 | return buf; | ||
1534 | } | ||
1535 | start = 0; | ||
1536 | } | ||
1537 | |||
1538 | if (t) { | ||
1539 | DRM_UDELAY(1); | ||
1540 | dev_priv->stats.freelist_loops++; | ||
1541 | } | ||
1542 | } | ||
1543 | |||
1544 | DRM_DEBUG("returning NULL!\n"); | ||
1545 | return NULL; | ||
1546 | } | ||
1547 | |||
1548 | #if 0 | ||
1549 | struct drm_buf *radeon_freelist_get(struct drm_device * dev) | ||
1550 | { | ||
1551 | struct drm_device_dma *dma = dev->dma; | ||
1552 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1553 | drm_radeon_buf_priv_t *buf_priv; | ||
1554 | struct drm_buf *buf; | ||
1555 | int i, t; | ||
1556 | int start; | ||
1557 | u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)); | ||
1558 | |||
1559 | if (++dev_priv->last_buf >= dma->buf_count) | ||
1560 | dev_priv->last_buf = 0; | ||
1561 | |||
1562 | start = dev_priv->last_buf; | ||
1563 | dev_priv->stats.freelist_loops++; | ||
1564 | |||
1565 | for (t = 0; t < 2; t++) { | ||
1566 | for (i = start; i < dma->buf_count; i++) { | ||
1567 | buf = dma->buflist[i]; | ||
1568 | buf_priv = buf->dev_private; | ||
1569 | if (buf->file_priv == 0 || (buf->pending && | ||
1570 | buf_priv->age <= | ||
1571 | done_age)) { | ||
1572 | dev_priv->stats.requested_bufs++; | ||
1573 | buf->pending = 0; | ||
1574 | return buf; | ||
1575 | } | ||
1576 | } | ||
1577 | start = 0; | ||
1578 | } | ||
1579 | |||
1580 | return NULL; | ||
1581 | } | ||
1582 | #endif | ||
1583 | |||
1584 | void radeon_freelist_reset(struct drm_device * dev) | ||
1585 | { | ||
1586 | struct drm_device_dma *dma = dev->dma; | ||
1587 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1588 | int i; | ||
1589 | |||
1590 | dev_priv->last_buf = 0; | ||
1591 | for (i = 0; i < dma->buf_count; i++) { | ||
1592 | struct drm_buf *buf = dma->buflist[i]; | ||
1593 | drm_radeon_buf_priv_t *buf_priv = buf->dev_private; | ||
1594 | buf_priv->age = 0; | ||
1595 | } | ||
1596 | } | ||
1597 | |||
1598 | /* ================================================================ | ||
1599 | * CP command submission | ||
1600 | */ | ||
1601 | |||
1602 | int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) | ||
1603 | { | ||
1604 | drm_radeon_ring_buffer_t *ring = &dev_priv->ring; | ||
1605 | int i; | ||
1606 | u32 last_head = GET_RING_HEAD(dev_priv); | ||
1607 | |||
1608 | for (i = 0; i < dev_priv->usec_timeout; i++) { | ||
1609 | u32 head = GET_RING_HEAD(dev_priv); | ||
1610 | |||
1611 | ring->space = (head - ring->tail) * sizeof(u32); | ||
1612 | if (ring->space <= 0) | ||
1613 | ring->space += ring->size; | ||
1614 | if (ring->space > n) | ||
1615 | return 0; | ||
1616 | |||
1617 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
1618 | |||
1619 | if (head != last_head) | ||
1620 | i = 0; | ||
1621 | last_head = head; | ||
1622 | |||
1623 | DRM_UDELAY(1); | ||
1624 | } | ||
1625 | |||
1626 | /* FIXME: This return value is ignored in the BEGIN_RING macro! */ | ||
1627 | #if RADEON_FIFO_DEBUG | ||
1628 | radeon_status(dev_priv); | ||
1629 | DRM_ERROR("failed!\n"); | ||
1630 | #endif | ||
1631 | return -EBUSY; | ||
1632 | } | ||
1633 | |||
1634 | static int radeon_cp_get_buffers(struct drm_device *dev, | ||
1635 | struct drm_file *file_priv, | ||
1636 | struct drm_dma * d) | ||
1637 | { | ||
1638 | int i; | ||
1639 | struct drm_buf *buf; | ||
1640 | |||
1641 | for (i = d->granted_count; i < d->request_count; i++) { | ||
1642 | buf = radeon_freelist_get(dev); | ||
1643 | if (!buf) | ||
1644 | return -EBUSY; /* NOTE: broken client */ | ||
1645 | |||
1646 | buf->file_priv = file_priv; | ||
1647 | |||
1648 | if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, | ||
1649 | sizeof(buf->idx))) | ||
1650 | return -EFAULT; | ||
1651 | if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, | ||
1652 | sizeof(buf->total))) | ||
1653 | return -EFAULT; | ||
1654 | |||
1655 | d->granted_count++; | ||
1656 | } | ||
1657 | return 0; | ||
1658 | } | ||
1659 | |||
1660 | int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
1661 | { | ||
1662 | struct drm_device_dma *dma = dev->dma; | ||
1663 | int ret = 0; | ||
1664 | struct drm_dma *d = data; | ||
1665 | |||
1666 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1667 | |||
1668 | /* Please don't send us buffers. | ||
1669 | */ | ||
1670 | if (d->send_count != 0) { | ||
1671 | DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", | ||
1672 | DRM_CURRENTPID, d->send_count); | ||
1673 | return -EINVAL; | ||
1674 | } | ||
1675 | |||
1676 | /* We'll send you buffers. | ||
1677 | */ | ||
1678 | if (d->request_count < 0 || d->request_count > dma->buf_count) { | ||
1679 | DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", | ||
1680 | DRM_CURRENTPID, d->request_count, dma->buf_count); | ||
1681 | return -EINVAL; | ||
1682 | } | ||
1683 | |||
1684 | d->granted_count = 0; | ||
1685 | |||
1686 | if (d->request_count) { | ||
1687 | ret = radeon_cp_get_buffers(dev, file_priv, d); | ||
1688 | } | ||
1689 | |||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
1693 | int radeon_driver_load(struct drm_device *dev, unsigned long flags) | ||
1694 | { | ||
1695 | drm_radeon_private_t *dev_priv; | ||
1696 | int ret = 0; | ||
1697 | |||
1698 | dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER); | ||
1699 | if (dev_priv == NULL) | ||
1700 | return -ENOMEM; | ||
1701 | |||
1702 | memset(dev_priv, 0, sizeof(drm_radeon_private_t)); | ||
1703 | dev->dev_private = (void *)dev_priv; | ||
1704 | dev_priv->flags = flags; | ||
1705 | |||
1706 | switch (flags & RADEON_FAMILY_MASK) { | ||
1707 | case CHIP_R100: | ||
1708 | case CHIP_RV200: | ||
1709 | case CHIP_R200: | ||
1710 | case CHIP_R300: | ||
1711 | case CHIP_R350: | ||
1712 | case CHIP_R420: | ||
1713 | case CHIP_RV410: | ||
1714 | case CHIP_RV515: | ||
1715 | case CHIP_R520: | ||
1716 | case CHIP_RV570: | ||
1717 | case CHIP_R580: | ||
1718 | dev_priv->flags |= RADEON_HAS_HIERZ; | ||
1719 | break; | ||
1720 | default: | ||
1721 | /* all other chips have no hierarchical z buffer */ | ||
1722 | break; | ||
1723 | } | ||
1724 | |||
1725 | if (drm_device_is_agp(dev)) | ||
1726 | dev_priv->flags |= RADEON_IS_AGP; | ||
1727 | else if (drm_device_is_pcie(dev)) | ||
1728 | dev_priv->flags |= RADEON_IS_PCIE; | ||
1729 | else | ||
1730 | dev_priv->flags |= RADEON_IS_PCI; | ||
1731 | |||
1732 | DRM_DEBUG("%s card detected\n", | ||
1733 | ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); | ||
1734 | return ret; | ||
1735 | } | ||
1736 | |||
1737 | /* Create mappings for registers and framebuffer so userland doesn't necessarily | ||
1738 | * have to find them. | ||
1739 | */ | ||
1740 | int radeon_driver_firstopen(struct drm_device *dev) | ||
1741 | { | ||
1742 | int ret; | ||
1743 | drm_local_map_t *map; | ||
1744 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1745 | |||
1746 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; | ||
1747 | |||
1748 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), | ||
1749 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, | ||
1750 | _DRM_READ_ONLY, &dev_priv->mmio); | ||
1751 | if (ret != 0) | ||
1752 | return ret; | ||
1753 | |||
1754 | dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); | ||
1755 | ret = drm_addmap(dev, dev_priv->fb_aper_offset, | ||
1756 | drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, | ||
1757 | _DRM_WRITE_COMBINING, &map); | ||
1758 | if (ret != 0) | ||
1759 | return ret; | ||
1760 | |||
1761 | return 0; | ||
1762 | } | ||
1763 | |||
1764 | int radeon_driver_unload(struct drm_device *dev) | ||
1765 | { | ||
1766 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1767 | |||
1768 | DRM_DEBUG("\n"); | ||
1769 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); | ||
1770 | |||
1771 | dev->dev_private = NULL; | ||
1772 | return 0; | ||
1773 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c new file mode 100644 index 000000000000..349ac3d3b848 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /** | ||
2 | * \file radeon_drv.c | ||
3 | * ATI Radeon driver | ||
4 | * | ||
5 | * \author Gareth Hughes <gareth@valinux.com> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
10 | * All Rights Reserved. | ||
11 | * | ||
12 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
13 | * copy of this software and associated documentation files (the "Software"), | ||
14 | * to deal in the Software without restriction, including without limitation | ||
15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
16 | * and/or sell copies of the Software, and to permit persons to whom the | ||
17 | * Software is furnished to do so, subject to the following conditions: | ||
18 | * | ||
19 | * The above copyright notice and this permission notice (including the next | ||
20 | * paragraph) shall be included in all copies or substantial portions of the | ||
21 | * Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
26 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
29 | * OTHER DEALINGS IN THE SOFTWARE. | ||
30 | */ | ||
31 | |||
32 | #include "drmP.h" | ||
33 | #include "drm.h" | ||
34 | #include "radeon_drm.h" | ||
35 | #include "radeon_drv.h" | ||
36 | |||
37 | #include "drm_pciids.h" | ||
38 | |||
39 | int radeon_no_wb; | ||
40 | |||
41 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n"); | ||
42 | module_param_named(no_wb, radeon_no_wb, int, 0444); | ||
43 | |||
44 | static int dri_library_name(struct drm_device *dev, char *buf) | ||
45 | { | ||
46 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
47 | int family = dev_priv->flags & RADEON_FAMILY_MASK; | ||
48 | |||
49 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
50 | (family < CHIP_R200) ? "radeon" : | ||
51 | ((family < CHIP_R300) ? "r200" : | ||
52 | "r300")); | ||
53 | } | ||
54 | |||
55 | static struct pci_device_id pciidlist[] = { | ||
56 | radeon_PCI_IDS | ||
57 | }; | ||
58 | |||
59 | static struct drm_driver driver = { | ||
60 | .driver_features = | ||
61 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | | ||
62 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | | ||
63 | DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2, | ||
64 | .dev_priv_size = sizeof(drm_radeon_buf_priv_t), | ||
65 | .load = radeon_driver_load, | ||
66 | .firstopen = radeon_driver_firstopen, | ||
67 | .open = radeon_driver_open, | ||
68 | .preclose = radeon_driver_preclose, | ||
69 | .postclose = radeon_driver_postclose, | ||
70 | .lastclose = radeon_driver_lastclose, | ||
71 | .unload = radeon_driver_unload, | ||
72 | .vblank_wait = radeon_driver_vblank_wait, | ||
73 | .vblank_wait2 = radeon_driver_vblank_wait2, | ||
74 | .dri_library_name = dri_library_name, | ||
75 | .irq_preinstall = radeon_driver_irq_preinstall, | ||
76 | .irq_postinstall = radeon_driver_irq_postinstall, | ||
77 | .irq_uninstall = radeon_driver_irq_uninstall, | ||
78 | .irq_handler = radeon_driver_irq_handler, | ||
79 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
80 | .get_map_ofs = drm_core_get_map_ofs, | ||
81 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
82 | .ioctls = radeon_ioctls, | ||
83 | .dma_ioctl = radeon_cp_buffers, | ||
84 | .fops = { | ||
85 | .owner = THIS_MODULE, | ||
86 | .open = drm_open, | ||
87 | .release = drm_release, | ||
88 | .ioctl = drm_ioctl, | ||
89 | .mmap = drm_mmap, | ||
90 | .poll = drm_poll, | ||
91 | .fasync = drm_fasync, | ||
92 | #ifdef CONFIG_COMPAT | ||
93 | .compat_ioctl = radeon_compat_ioctl, | ||
94 | #endif | ||
95 | }, | ||
96 | |||
97 | .pci_driver = { | ||
98 | .name = DRIVER_NAME, | ||
99 | .id_table = pciidlist, | ||
100 | }, | ||
101 | |||
102 | .name = DRIVER_NAME, | ||
103 | .desc = DRIVER_DESC, | ||
104 | .date = DRIVER_DATE, | ||
105 | .major = DRIVER_MAJOR, | ||
106 | .minor = DRIVER_MINOR, | ||
107 | .patchlevel = DRIVER_PATCHLEVEL, | ||
108 | }; | ||
109 | |||
110 | static int __init radeon_init(void) | ||
111 | { | ||
112 | driver.num_ioctls = radeon_max_ioctl; | ||
113 | return drm_init(&driver); | ||
114 | } | ||
115 | |||
116 | static void __exit radeon_exit(void) | ||
117 | { | ||
118 | drm_exit(&driver); | ||
119 | } | ||
120 | |||
121 | module_init(radeon_init); | ||
122 | module_exit(radeon_exit); | ||
123 | |||
124 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
125 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
126 | MODULE_LICENSE("GPL and additional rights"); | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h new file mode 100644 index 000000000000..3f0eca957aa7 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
@@ -0,0 +1,1406 @@ | |||
1 | /* radeon_drv.h -- Private header for radeon driver -*- linux-c -*- | ||
2 | * | ||
3 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
4 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
8 | * copy of this software and associated documentation files (the "Software"), | ||
9 | * to deal in the Software without restriction, including without limitation | ||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
12 | * Software is furnished to do so, subject to the following conditions: | ||
13 | * | ||
14 | * The above copyright notice and this permission notice (including the next | ||
15 | * paragraph) shall be included in all copies or substantial portions of the | ||
16 | * Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
21 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
24 | * DEALINGS IN THE SOFTWARE. | ||
25 | * | ||
26 | * Authors: | ||
27 | * Kevin E. Martin <martin@valinux.com> | ||
28 | * Gareth Hughes <gareth@valinux.com> | ||
29 | */ | ||
30 | |||
31 | #ifndef __RADEON_DRV_H__ | ||
32 | #define __RADEON_DRV_H__ | ||
33 | |||
34 | /* General customization: | ||
35 | */ | ||
36 | |||
37 | #define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." | ||
38 | |||
39 | #define DRIVER_NAME "radeon" | ||
40 | #define DRIVER_DESC "ATI Radeon" | ||
41 | #define DRIVER_DATE "20080528" | ||
42 | |||
43 | /* Interface history: | ||
44 | * | ||
45 | * 1.1 - ?? | ||
46 | * 1.2 - Add vertex2 ioctl (keith) | ||
47 | * - Add stencil capability to clear ioctl (gareth, keith) | ||
48 | * - Increase MAX_TEXTURE_LEVELS (brian) | ||
49 | * 1.3 - Add cmdbuf ioctl (keith) | ||
50 | * - Add support for new radeon packets (keith) | ||
51 | * - Add getparam ioctl (keith) | ||
52 | * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). | ||
53 | * 1.4 - Add scratch registers to get_param ioctl. | ||
54 | * 1.5 - Add r200 packets to cmdbuf ioctl | ||
55 | * - Add r200 function to init ioctl | ||
56 | * - Add 'scalar2' instruction to cmdbuf | ||
57 | * 1.6 - Add static GART memory manager | ||
58 | * Add irq handler (won't be turned on unless X server knows to) | ||
59 | * Add irq ioctls and irq_active getparam. | ||
60 | * Add wait command for cmdbuf ioctl | ||
61 | * Add GART offset query for getparam | ||
62 | * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] | ||
63 | * and R200_PP_CUBIC_OFFSET_F1_[0..5]. | ||
64 | * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and | ||
65 | * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) | ||
66 | * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) | ||
67 | * Add 'GET' queries for starting additional clients on different VT's. | ||
68 | * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl. | ||
69 | * Add texture rectangle support for r100. | ||
70 | * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which | ||
71 | * clients use to tell the DRM where they think the framebuffer is | ||
72 | * located in the card's address space | ||
73 | * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color | ||
74 | * and GL_EXT_blend_[func|equation]_separate on r200 | ||
75 | * 1.12- Add R300 CP microcode support - this just loads the CP on r300 | ||
76 | * (No 3D support yet - just microcode loading). | ||
77 | * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters | ||
78 | * - Add hyperz support, add hyperz flags to clear ioctl. | ||
79 | * 1.14- Add support for color tiling | ||
80 | * - Add R100/R200 surface allocation/free support | ||
81 | * 1.15- Add support for texture micro tiling | ||
82 | * - Add support for r100 cube maps | ||
83 | * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear | ||
84 | * texture filtering on r200 | ||
85 | * 1.17- Add initial support for R300 (3D). | ||
86 | * 1.18- Add support for GL_ATI_fragment_shader, new packets | ||
87 | * R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces | ||
88 | * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR | ||
89 | * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) | ||
90 | * 1.19- Add support for gart table in FB memory and PCIE r300 | ||
91 | * 1.20- Add support for r300 texrect | ||
92 | * 1.21- Add support for card type getparam | ||
93 | * 1.22- Add support for texture cache flushes (R300_TX_CNTL) | ||
94 | * 1.23- Add new radeon memory map work from benh | ||
95 | * 1.24- Add general-purpose packet for manipulating scratch registers (r300) | ||
96 | * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, | ||
97 | * new packet type) | ||
98 | * 1.26- Add support for variable size PCI(E) gart aperture | ||
99 | * 1.27- Add support for IGP GART | ||
100 | * 1.28- Add support for VBL on CRTC2 | ||
101 | * 1.29- R500 3D cmd buffer support | ||
102 | */ | ||
103 | #define DRIVER_MAJOR 1 | ||
104 | #define DRIVER_MINOR 29 | ||
105 | #define DRIVER_PATCHLEVEL 0 | ||
106 | |||
107 | /* | ||
108 | * Radeon chip families | ||
109 | */ | ||
110 | enum radeon_family { | ||
111 | CHIP_R100, | ||
112 | CHIP_RV100, | ||
113 | CHIP_RS100, | ||
114 | CHIP_RV200, | ||
115 | CHIP_RS200, | ||
116 | CHIP_R200, | ||
117 | CHIP_RV250, | ||
118 | CHIP_RS300, | ||
119 | CHIP_RV280, | ||
120 | CHIP_R300, | ||
121 | CHIP_R350, | ||
122 | CHIP_RV350, | ||
123 | CHIP_RV380, | ||
124 | CHIP_R420, | ||
125 | CHIP_RV410, | ||
126 | CHIP_RS480, | ||
127 | CHIP_RS690, | ||
128 | CHIP_RV515, | ||
129 | CHIP_R520, | ||
130 | CHIP_RV530, | ||
131 | CHIP_RV560, | ||
132 | CHIP_RV570, | ||
133 | CHIP_R580, | ||
134 | CHIP_LAST, | ||
135 | }; | ||
136 | |||
137 | enum radeon_cp_microcode_version { | ||
138 | UCODE_R100, | ||
139 | UCODE_R200, | ||
140 | UCODE_R300, | ||
141 | }; | ||
142 | |||
143 | /* | ||
144 | * Chip flags | ||
145 | */ | ||
146 | enum radeon_chip_flags { | ||
147 | RADEON_FAMILY_MASK = 0x0000ffffUL, | ||
148 | RADEON_FLAGS_MASK = 0xffff0000UL, | ||
149 | RADEON_IS_MOBILITY = 0x00010000UL, | ||
150 | RADEON_IS_IGP = 0x00020000UL, | ||
151 | RADEON_SINGLE_CRTC = 0x00040000UL, | ||
152 | RADEON_IS_AGP = 0x00080000UL, | ||
153 | RADEON_HAS_HIERZ = 0x00100000UL, | ||
154 | RADEON_IS_PCIE = 0x00200000UL, | ||
155 | RADEON_NEW_MEMMAP = 0x00400000UL, | ||
156 | RADEON_IS_PCI = 0x00800000UL, | ||
157 | RADEON_IS_IGPGART = 0x01000000UL, | ||
158 | }; | ||
159 | |||
160 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ | ||
161 | DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR)) | ||
162 | #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) | ||
163 | |||
164 | typedef struct drm_radeon_freelist { | ||
165 | unsigned int age; | ||
166 | struct drm_buf *buf; | ||
167 | struct drm_radeon_freelist *next; | ||
168 | struct drm_radeon_freelist *prev; | ||
169 | } drm_radeon_freelist_t; | ||
170 | |||
171 | typedef struct drm_radeon_ring_buffer { | ||
172 | u32 *start; | ||
173 | u32 *end; | ||
174 | int size; | ||
175 | int size_l2qw; | ||
176 | |||
177 | int rptr_update; /* Double Words */ | ||
178 | int rptr_update_l2qw; /* log2 Quad Words */ | ||
179 | |||
180 | int fetch_size; /* Double Words */ | ||
181 | int fetch_size_l2ow; /* log2 Oct Words */ | ||
182 | |||
183 | u32 tail; | ||
184 | u32 tail_mask; | ||
185 | int space; | ||
186 | |||
187 | int high_mark; | ||
188 | } drm_radeon_ring_buffer_t; | ||
189 | |||
190 | typedef struct drm_radeon_depth_clear_t { | ||
191 | u32 rb3d_cntl; | ||
192 | u32 rb3d_zstencilcntl; | ||
193 | u32 se_cntl; | ||
194 | } drm_radeon_depth_clear_t; | ||
195 | |||
196 | struct drm_radeon_driver_file_fields { | ||
197 | int64_t radeon_fb_delta; | ||
198 | }; | ||
199 | |||
200 | struct mem_block { | ||
201 | struct mem_block *next; | ||
202 | struct mem_block *prev; | ||
203 | int start; | ||
204 | int size; | ||
205 | struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ | ||
206 | }; | ||
207 | |||
208 | struct radeon_surface { | ||
209 | int refcount; | ||
210 | u32 lower; | ||
211 | u32 upper; | ||
212 | u32 flags; | ||
213 | }; | ||
214 | |||
215 | struct radeon_virt_surface { | ||
216 | int surface_index; | ||
217 | u32 lower; | ||
218 | u32 upper; | ||
219 | u32 flags; | ||
220 | struct drm_file *file_priv; | ||
221 | }; | ||
222 | |||
223 | typedef struct drm_radeon_private { | ||
224 | drm_radeon_ring_buffer_t ring; | ||
225 | drm_radeon_sarea_t *sarea_priv; | ||
226 | |||
227 | u32 fb_location; | ||
228 | u32 fb_size; | ||
229 | int new_memmap; | ||
230 | |||
231 | int gart_size; | ||
232 | u32 gart_vm_start; | ||
233 | unsigned long gart_buffers_offset; | ||
234 | |||
235 | int cp_mode; | ||
236 | int cp_running; | ||
237 | |||
238 | drm_radeon_freelist_t *head; | ||
239 | drm_radeon_freelist_t *tail; | ||
240 | int last_buf; | ||
241 | volatile u32 *scratch; | ||
242 | int writeback_works; | ||
243 | |||
244 | int usec_timeout; | ||
245 | |||
246 | int microcode_version; | ||
247 | |||
248 | struct { | ||
249 | u32 boxes; | ||
250 | int freelist_timeouts; | ||
251 | int freelist_loops; | ||
252 | int requested_bufs; | ||
253 | int last_frame_reads; | ||
254 | int last_clear_reads; | ||
255 | int clears; | ||
256 | int texture_uploads; | ||
257 | } stats; | ||
258 | |||
259 | int do_boxes; | ||
260 | int page_flipping; | ||
261 | |||
262 | u32 color_fmt; | ||
263 | unsigned int front_offset; | ||
264 | unsigned int front_pitch; | ||
265 | unsigned int back_offset; | ||
266 | unsigned int back_pitch; | ||
267 | |||
268 | u32 depth_fmt; | ||
269 | unsigned int depth_offset; | ||
270 | unsigned int depth_pitch; | ||
271 | |||
272 | u32 front_pitch_offset; | ||
273 | u32 back_pitch_offset; | ||
274 | u32 depth_pitch_offset; | ||
275 | |||
276 | drm_radeon_depth_clear_t depth_clear; | ||
277 | |||
278 | unsigned long ring_offset; | ||
279 | unsigned long ring_rptr_offset; | ||
280 | unsigned long buffers_offset; | ||
281 | unsigned long gart_textures_offset; | ||
282 | |||
283 | drm_local_map_t *sarea; | ||
284 | drm_local_map_t *mmio; | ||
285 | drm_local_map_t *cp_ring; | ||
286 | drm_local_map_t *ring_rptr; | ||
287 | drm_local_map_t *gart_textures; | ||
288 | |||
289 | struct mem_block *gart_heap; | ||
290 | struct mem_block *fb_heap; | ||
291 | |||
292 | /* SW interrupt */ | ||
293 | wait_queue_head_t swi_queue; | ||
294 | atomic_t swi_emitted; | ||
295 | int vblank_crtc; | ||
296 | uint32_t irq_enable_reg; | ||
297 | int irq_enabled; | ||
298 | uint32_t r500_disp_irq_reg; | ||
299 | |||
300 | struct radeon_surface surfaces[RADEON_MAX_SURFACES]; | ||
301 | struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; | ||
302 | |||
303 | unsigned long pcigart_offset; | ||
304 | unsigned int pcigart_offset_set; | ||
305 | struct drm_ati_pcigart_info gart_info; | ||
306 | |||
307 | u32 scratch_ages[5]; | ||
308 | |||
309 | /* starting from here on, data is preserved accross an open */ | ||
310 | uint32_t flags; /* see radeon_chip_flags */ | ||
311 | unsigned long fb_aper_offset; | ||
312 | |||
313 | int num_gb_pipes; | ||
314 | } drm_radeon_private_t; | ||
315 | |||
316 | typedef struct drm_radeon_buf_priv { | ||
317 | u32 age; | ||
318 | } drm_radeon_buf_priv_t; | ||
319 | |||
320 | typedef struct drm_radeon_kcmd_buffer { | ||
321 | int bufsz; | ||
322 | char *buf; | ||
323 | int nbox; | ||
324 | struct drm_clip_rect __user *boxes; | ||
325 | } drm_radeon_kcmd_buffer_t; | ||
326 | |||
327 | extern int radeon_no_wb; | ||
328 | extern struct drm_ioctl_desc radeon_ioctls[]; | ||
329 | extern int radeon_max_ioctl; | ||
330 | |||
331 | /* Check whether the given hardware address is inside the framebuffer or the | ||
332 | * GART area. | ||
333 | */ | ||
334 | static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv, | ||
335 | u64 off) | ||
336 | { | ||
337 | u32 fb_start = dev_priv->fb_location; | ||
338 | u32 fb_end = fb_start + dev_priv->fb_size - 1; | ||
339 | u32 gart_start = dev_priv->gart_vm_start; | ||
340 | u32 gart_end = gart_start + dev_priv->gart_size - 1; | ||
341 | |||
342 | return ((off >= fb_start && off <= fb_end) || | ||
343 | (off >= gart_start && off <= gart_end)); | ||
344 | } | ||
345 | |||
346 | /* radeon_cp.c */ | ||
347 | extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
348 | extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
349 | extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
350 | extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
351 | extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
352 | extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
353 | extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
354 | extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
355 | extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
356 | extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv); | ||
357 | |||
358 | extern void radeon_freelist_reset(struct drm_device * dev); | ||
359 | extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); | ||
360 | |||
361 | extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n); | ||
362 | |||
363 | extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv); | ||
364 | |||
365 | extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); | ||
366 | extern int radeon_presetup(struct drm_device *dev); | ||
367 | extern int radeon_driver_postcleanup(struct drm_device *dev); | ||
368 | |||
369 | extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
370 | extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
371 | extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
372 | extern void radeon_mem_takedown(struct mem_block **heap); | ||
373 | extern void radeon_mem_release(struct drm_file *file_priv, | ||
374 | struct mem_block *heap); | ||
375 | |||
376 | /* radeon_irq.c */ | ||
377 | extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
378 | extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
379 | |||
380 | extern void radeon_do_release(struct drm_device * dev); | ||
381 | extern int radeon_driver_vblank_wait(struct drm_device * dev, | ||
382 | unsigned int *sequence); | ||
383 | extern int radeon_driver_vblank_wait2(struct drm_device * dev, | ||
384 | unsigned int *sequence); | ||
385 | extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); | ||
386 | extern void radeon_driver_irq_preinstall(struct drm_device * dev); | ||
387 | extern void radeon_driver_irq_postinstall(struct drm_device * dev); | ||
388 | extern void radeon_driver_irq_uninstall(struct drm_device * dev); | ||
389 | extern void radeon_enable_interrupt(struct drm_device *dev); | ||
390 | extern int radeon_vblank_crtc_get(struct drm_device *dev); | ||
391 | extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); | ||
392 | |||
393 | extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); | ||
394 | extern int radeon_driver_unload(struct drm_device *dev); | ||
395 | extern int radeon_driver_firstopen(struct drm_device *dev); | ||
396 | extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv); | ||
397 | extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp); | ||
398 | extern void radeon_driver_lastclose(struct drm_device * dev); | ||
399 | extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv); | ||
400 | extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, | ||
401 | unsigned long arg); | ||
402 | |||
403 | /* r300_cmdbuf.c */ | ||
404 | extern void r300_init_reg_flags(struct drm_device *dev); | ||
405 | |||
406 | extern int r300_do_cp_cmdbuf(struct drm_device * dev, | ||
407 | struct drm_file *file_priv, | ||
408 | drm_radeon_kcmd_buffer_t * cmdbuf); | ||
409 | |||
410 | /* Flags for stats.boxes | ||
411 | */ | ||
412 | #define RADEON_BOX_DMA_IDLE 0x1 | ||
413 | #define RADEON_BOX_RING_FULL 0x2 | ||
414 | #define RADEON_BOX_FLIP 0x4 | ||
415 | #define RADEON_BOX_WAIT_IDLE 0x8 | ||
416 | #define RADEON_BOX_TEXTURE_LOAD 0x10 | ||
417 | |||
418 | /* Register definitions, register access macros and drmAddMap constants | ||
419 | * for Radeon kernel driver. | ||
420 | */ | ||
421 | |||
422 | #define RADEON_AGP_COMMAND 0x0f60 | ||
423 | #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */ | ||
424 | # define RADEON_AGP_ENABLE (1<<8) | ||
425 | #define RADEON_AUX_SCISSOR_CNTL 0x26f0 | ||
426 | # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) | ||
427 | # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) | ||
428 | # define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26) | ||
429 | # define RADEON_SCISSOR_0_ENABLE (1 << 28) | ||
430 | # define RADEON_SCISSOR_1_ENABLE (1 << 29) | ||
431 | # define RADEON_SCISSOR_2_ENABLE (1 << 30) | ||
432 | |||
433 | #define RADEON_BUS_CNTL 0x0030 | ||
434 | # define RADEON_BUS_MASTER_DIS (1 << 6) | ||
435 | |||
436 | #define RADEON_CLOCK_CNTL_DATA 0x000c | ||
437 | # define RADEON_PLL_WR_EN (1 << 7) | ||
438 | #define RADEON_CLOCK_CNTL_INDEX 0x0008 | ||
439 | #define RADEON_CONFIG_APER_SIZE 0x0108 | ||
440 | #define RADEON_CONFIG_MEMSIZE 0x00f8 | ||
441 | #define RADEON_CRTC_OFFSET 0x0224 | ||
442 | #define RADEON_CRTC_OFFSET_CNTL 0x0228 | ||
443 | # define RADEON_CRTC_TILE_EN (1 << 15) | ||
444 | # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) | ||
445 | #define RADEON_CRTC2_OFFSET 0x0324 | ||
446 | #define RADEON_CRTC2_OFFSET_CNTL 0x0328 | ||
447 | |||
448 | #define RADEON_PCIE_INDEX 0x0030 | ||
449 | #define RADEON_PCIE_DATA 0x0034 | ||
450 | #define RADEON_PCIE_TX_GART_CNTL 0x10 | ||
451 | # define RADEON_PCIE_TX_GART_EN (1 << 0) | ||
452 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1) | ||
453 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1 << 1) | ||
454 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3 << 1) | ||
455 | # define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0 << 3) | ||
456 | # define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1 << 3) | ||
457 | # define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1 << 5) | ||
458 | # define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1 << 8) | ||
459 | #define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 | ||
460 | #define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 | ||
461 | #define RADEON_PCIE_TX_GART_BASE 0x13 | ||
462 | #define RADEON_PCIE_TX_GART_START_LO 0x14 | ||
463 | #define RADEON_PCIE_TX_GART_START_HI 0x15 | ||
464 | #define RADEON_PCIE_TX_GART_END_LO 0x16 | ||
465 | #define RADEON_PCIE_TX_GART_END_HI 0x17 | ||
466 | |||
467 | #define RS480_NB_MC_INDEX 0x168 | ||
468 | # define RS480_NB_MC_IND_WR_EN (1 << 8) | ||
469 | #define RS480_NB_MC_DATA 0x16c | ||
470 | |||
471 | #define RS690_MC_INDEX 0x78 | ||
472 | # define RS690_MC_INDEX_MASK 0x1ff | ||
473 | # define RS690_MC_INDEX_WR_EN (1 << 9) | ||
474 | # define RS690_MC_INDEX_WR_ACK 0x7f | ||
475 | #define RS690_MC_DATA 0x7c | ||
476 | |||
477 | /* MC indirect registers */ | ||
478 | #define RS480_MC_MISC_CNTL 0x18 | ||
479 | # define RS480_DISABLE_GTW (1 << 1) | ||
480 | /* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */ | ||
481 | # define RS480_GART_INDEX_REG_EN (1 << 12) | ||
482 | # define RS690_BLOCK_GFX_D3_EN (1 << 14) | ||
483 | #define RS480_K8_FB_LOCATION 0x1e | ||
484 | #define RS480_GART_FEATURE_ID 0x2b | ||
485 | # define RS480_HANG_EN (1 << 11) | ||
486 | # define RS480_TLB_ENABLE (1 << 18) | ||
487 | # define RS480_P2P_ENABLE (1 << 19) | ||
488 | # define RS480_GTW_LAC_EN (1 << 25) | ||
489 | # define RS480_2LEVEL_GART (0 << 30) | ||
490 | # define RS480_1LEVEL_GART (1 << 30) | ||
491 | # define RS480_PDC_EN (1 << 31) | ||
492 | #define RS480_GART_BASE 0x2c | ||
493 | #define RS480_GART_CACHE_CNTRL 0x2e | ||
494 | # define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */ | ||
495 | #define RS480_AGP_ADDRESS_SPACE_SIZE 0x38 | ||
496 | # define RS480_GART_EN (1 << 0) | ||
497 | # define RS480_VA_SIZE_32MB (0 << 1) | ||
498 | # define RS480_VA_SIZE_64MB (1 << 1) | ||
499 | # define RS480_VA_SIZE_128MB (2 << 1) | ||
500 | # define RS480_VA_SIZE_256MB (3 << 1) | ||
501 | # define RS480_VA_SIZE_512MB (4 << 1) | ||
502 | # define RS480_VA_SIZE_1GB (5 << 1) | ||
503 | # define RS480_VA_SIZE_2GB (6 << 1) | ||
504 | #define RS480_AGP_MODE_CNTL 0x39 | ||
505 | # define RS480_POST_GART_Q_SIZE (1 << 18) | ||
506 | # define RS480_NONGART_SNOOP (1 << 19) | ||
507 | # define RS480_AGP_RD_BUF_SIZE (1 << 20) | ||
508 | # define RS480_REQ_TYPE_SNOOP_SHIFT 22 | ||
509 | # define RS480_REQ_TYPE_SNOOP_MASK 0x3 | ||
510 | # define RS480_REQ_TYPE_SNOOP_DIS (1 << 24) | ||
511 | #define RS480_MC_MISC_UMA_CNTL 0x5f | ||
512 | #define RS480_MC_MCLK_CNTL 0x7a | ||
513 | #define RS480_MC_UMA_DUALCH_CNTL 0x86 | ||
514 | |||
515 | #define RS690_MC_FB_LOCATION 0x100 | ||
516 | #define RS690_MC_AGP_LOCATION 0x101 | ||
517 | #define RS690_MC_AGP_BASE 0x102 | ||
518 | #define RS690_MC_AGP_BASE_2 0x103 | ||
519 | |||
520 | #define R520_MC_IND_INDEX 0x70 | ||
521 | #define R520_MC_IND_WR_EN (1 << 24) | ||
522 | #define R520_MC_IND_DATA 0x74 | ||
523 | |||
524 | #define RV515_MC_FB_LOCATION 0x01 | ||
525 | #define RV515_MC_AGP_LOCATION 0x02 | ||
526 | #define RV515_MC_AGP_BASE 0x03 | ||
527 | #define RV515_MC_AGP_BASE_2 0x04 | ||
528 | |||
529 | #define R520_MC_FB_LOCATION 0x04 | ||
530 | #define R520_MC_AGP_LOCATION 0x05 | ||
531 | #define R520_MC_AGP_BASE 0x06 | ||
532 | #define R520_MC_AGP_BASE_2 0x07 | ||
533 | |||
534 | #define RADEON_MPP_TB_CONFIG 0x01c0 | ||
535 | #define RADEON_MEM_CNTL 0x0140 | ||
536 | #define RADEON_MEM_SDRAM_MODE_REG 0x0158 | ||
537 | #define RADEON_AGP_BASE_2 0x015c /* r200+ only */ | ||
538 | #define RS480_AGP_BASE_2 0x0164 | ||
539 | #define RADEON_AGP_BASE 0x0170 | ||
540 | |||
541 | /* pipe config regs */ | ||
542 | #define R400_GB_PIPE_SELECT 0x402c | ||
543 | #define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ | ||
544 | #define R500_SU_REG_DEST 0x42c8 | ||
545 | #define R300_GB_TILE_CONFIG 0x4018 | ||
546 | # define R300_ENABLE_TILING (1 << 0) | ||
547 | # define R300_PIPE_COUNT_RV350 (0 << 1) | ||
548 | # define R300_PIPE_COUNT_R300 (3 << 1) | ||
549 | # define R300_PIPE_COUNT_R420_3P (6 << 1) | ||
550 | # define R300_PIPE_COUNT_R420 (7 << 1) | ||
551 | # define R300_TILE_SIZE_8 (0 << 4) | ||
552 | # define R300_TILE_SIZE_16 (1 << 4) | ||
553 | # define R300_TILE_SIZE_32 (2 << 4) | ||
554 | # define R300_SUBPIXEL_1_12 (0 << 16) | ||
555 | # define R300_SUBPIXEL_1_16 (1 << 16) | ||
556 | #define R300_DST_PIPE_CONFIG 0x170c | ||
557 | # define R300_PIPE_AUTO_CONFIG (1 << 31) | ||
558 | #define R300_RB2D_DSTCACHE_MODE 0x3428 | ||
559 | # define R300_DC_AUTOFLUSH_ENABLE (1 << 8) | ||
560 | # define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17) | ||
561 | |||
562 | #define RADEON_RB3D_COLOROFFSET 0x1c40 | ||
563 | #define RADEON_RB3D_COLORPITCH 0x1c48 | ||
564 | |||
565 | #define RADEON_SRC_X_Y 0x1590 | ||
566 | |||
567 | #define RADEON_DP_GUI_MASTER_CNTL 0x146c | ||
568 | # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) | ||
569 | # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) | ||
570 | # define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) | ||
571 | # define RADEON_GMC_BRUSH_NONE (15 << 4) | ||
572 | # define RADEON_GMC_DST_16BPP (4 << 8) | ||
573 | # define RADEON_GMC_DST_24BPP (5 << 8) | ||
574 | # define RADEON_GMC_DST_32BPP (6 << 8) | ||
575 | # define RADEON_GMC_DST_DATATYPE_SHIFT 8 | ||
576 | # define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) | ||
577 | # define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) | ||
578 | # define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) | ||
579 | # define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) | ||
580 | # define RADEON_GMC_WR_MSK_DIS (1 << 30) | ||
581 | # define RADEON_ROP3_S 0x00cc0000 | ||
582 | # define RADEON_ROP3_P 0x00f00000 | ||
583 | #define RADEON_DP_WRITE_MASK 0x16cc | ||
584 | #define RADEON_SRC_PITCH_OFFSET 0x1428 | ||
585 | #define RADEON_DST_PITCH_OFFSET 0x142c | ||
586 | #define RADEON_DST_PITCH_OFFSET_C 0x1c80 | ||
587 | # define RADEON_DST_TILE_LINEAR (0 << 30) | ||
588 | # define RADEON_DST_TILE_MACRO (1 << 30) | ||
589 | # define RADEON_DST_TILE_MICRO (2 << 30) | ||
590 | # define RADEON_DST_TILE_BOTH (3 << 30) | ||
591 | |||
592 | #define RADEON_SCRATCH_REG0 0x15e0 | ||
593 | #define RADEON_SCRATCH_REG1 0x15e4 | ||
594 | #define RADEON_SCRATCH_REG2 0x15e8 | ||
595 | #define RADEON_SCRATCH_REG3 0x15ec | ||
596 | #define RADEON_SCRATCH_REG4 0x15f0 | ||
597 | #define RADEON_SCRATCH_REG5 0x15f4 | ||
598 | #define RADEON_SCRATCH_UMSK 0x0770 | ||
599 | #define RADEON_SCRATCH_ADDR 0x0774 | ||
600 | |||
601 | #define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) | ||
602 | |||
603 | #define GET_SCRATCH( x ) (dev_priv->writeback_works \ | ||
604 | ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ | ||
605 | : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) | ||
606 | |||
607 | #define RADEON_GEN_INT_CNTL 0x0040 | ||
608 | # define RADEON_CRTC_VBLANK_MASK (1 << 0) | ||
609 | # define RADEON_CRTC2_VBLANK_MASK (1 << 9) | ||
610 | # define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) | ||
611 | # define RADEON_SW_INT_ENABLE (1 << 25) | ||
612 | |||
613 | #define RADEON_GEN_INT_STATUS 0x0044 | ||
614 | # define RADEON_CRTC_VBLANK_STAT (1 << 0) | ||
615 | # define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) | ||
616 | # define RADEON_CRTC2_VBLANK_STAT (1 << 9) | ||
617 | # define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) | ||
618 | # define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) | ||
619 | # define RADEON_SW_INT_TEST (1 << 25) | ||
620 | # define RADEON_SW_INT_TEST_ACK (1 << 25) | ||
621 | # define RADEON_SW_INT_FIRE (1 << 26) | ||
622 | |||
623 | #define RADEON_HOST_PATH_CNTL 0x0130 | ||
624 | # define RADEON_HDP_SOFT_RESET (1 << 26) | ||
625 | # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) | ||
626 | # define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28) | ||
627 | |||
628 | #define RADEON_ISYNC_CNTL 0x1724 | ||
629 | # define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) | ||
630 | # define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) | ||
631 | # define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) | ||
632 | # define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) | ||
633 | # define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) | ||
634 | # define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) | ||
635 | |||
636 | #define RADEON_RBBM_GUICNTL 0x172c | ||
637 | # define RADEON_HOST_DATA_SWAP_NONE (0 << 0) | ||
638 | # define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) | ||
639 | # define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) | ||
640 | # define RADEON_HOST_DATA_SWAP_HDW (3 << 0) | ||
641 | |||
642 | #define RADEON_MC_AGP_LOCATION 0x014c | ||
643 | #define RADEON_MC_FB_LOCATION 0x0148 | ||
644 | #define RADEON_MCLK_CNTL 0x0012 | ||
645 | # define RADEON_FORCEON_MCLKA (1 << 16) | ||
646 | # define RADEON_FORCEON_MCLKB (1 << 17) | ||
647 | # define RADEON_FORCEON_YCLKA (1 << 18) | ||
648 | # define RADEON_FORCEON_YCLKB (1 << 19) | ||
649 | # define RADEON_FORCEON_MC (1 << 20) | ||
650 | # define RADEON_FORCEON_AIC (1 << 21) | ||
651 | |||
652 | #define RADEON_PP_BORDER_COLOR_0 0x1d40 | ||
653 | #define RADEON_PP_BORDER_COLOR_1 0x1d44 | ||
654 | #define RADEON_PP_BORDER_COLOR_2 0x1d48 | ||
655 | #define RADEON_PP_CNTL 0x1c38 | ||
656 | # define RADEON_SCISSOR_ENABLE (1 << 1) | ||
657 | #define RADEON_PP_LUM_MATRIX 0x1d00 | ||
658 | #define RADEON_PP_MISC 0x1c14 | ||
659 | #define RADEON_PP_ROT_MATRIX_0 0x1d58 | ||
660 | #define RADEON_PP_TXFILTER_0 0x1c54 | ||
661 | #define RADEON_PP_TXOFFSET_0 0x1c5c | ||
662 | #define RADEON_PP_TXFILTER_1 0x1c6c | ||
663 | #define RADEON_PP_TXFILTER_2 0x1c84 | ||
664 | |||
665 | #define R300_RB2D_DSTCACHE_CTLSTAT 0x342c /* use R300_DSTCACHE_CTLSTAT */ | ||
666 | #define R300_DSTCACHE_CTLSTAT 0x1714 | ||
667 | # define R300_RB2D_DC_FLUSH (3 << 0) | ||
668 | # define R300_RB2D_DC_FREE (3 << 2) | ||
669 | # define R300_RB2D_DC_FLUSH_ALL 0xf | ||
670 | # define R300_RB2D_DC_BUSY (1 << 31) | ||
671 | #define RADEON_RB3D_CNTL 0x1c3c | ||
672 | # define RADEON_ALPHA_BLEND_ENABLE (1 << 0) | ||
673 | # define RADEON_PLANE_MASK_ENABLE (1 << 1) | ||
674 | # define RADEON_DITHER_ENABLE (1 << 2) | ||
675 | # define RADEON_ROUND_ENABLE (1 << 3) | ||
676 | # define RADEON_SCALE_DITHER_ENABLE (1 << 4) | ||
677 | # define RADEON_DITHER_INIT (1 << 5) | ||
678 | # define RADEON_ROP_ENABLE (1 << 6) | ||
679 | # define RADEON_STENCIL_ENABLE (1 << 7) | ||
680 | # define RADEON_Z_ENABLE (1 << 8) | ||
681 | # define RADEON_ZBLOCK16 (1 << 15) | ||
682 | #define RADEON_RB3D_DEPTHOFFSET 0x1c24 | ||
683 | #define RADEON_RB3D_DEPTHCLEARVALUE 0x3230 | ||
684 | #define RADEON_RB3D_DEPTHPITCH 0x1c28 | ||
685 | #define RADEON_RB3D_PLANEMASK 0x1d84 | ||
686 | #define RADEON_RB3D_STENCILREFMASK 0x1d7c | ||
687 | #define RADEON_RB3D_ZCACHE_MODE 0x3250 | ||
688 | #define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 | ||
689 | # define RADEON_RB3D_ZC_FLUSH (1 << 0) | ||
690 | # define RADEON_RB3D_ZC_FREE (1 << 2) | ||
691 | # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 | ||
692 | # define RADEON_RB3D_ZC_BUSY (1 << 31) | ||
693 | #define R300_ZB_ZCACHE_CTLSTAT 0x4f18 | ||
694 | # define R300_ZC_FLUSH (1 << 0) | ||
695 | # define R300_ZC_FREE (1 << 1) | ||
696 | # define R300_ZC_FLUSH_ALL 0x3 | ||
697 | # define R300_ZC_BUSY (1 << 31) | ||
698 | #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c | ||
699 | # define RADEON_RB3D_DC_FLUSH (3 << 0) | ||
700 | # define RADEON_RB3D_DC_FREE (3 << 2) | ||
701 | # define RADEON_RB3D_DC_FLUSH_ALL 0xf | ||
702 | # define RADEON_RB3D_DC_BUSY (1 << 31) | ||
703 | #define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c | ||
704 | # define R300_RB3D_DC_FINISH (1 << 4) | ||
705 | #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c | ||
706 | # define RADEON_Z_TEST_MASK (7 << 4) | ||
707 | # define RADEON_Z_TEST_ALWAYS (7 << 4) | ||
708 | # define RADEON_Z_HIERARCHY_ENABLE (1 << 8) | ||
709 | # define RADEON_STENCIL_TEST_ALWAYS (7 << 12) | ||
710 | # define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16) | ||
711 | # define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) | ||
712 | # define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) | ||
713 | # define RADEON_Z_COMPRESSION_ENABLE (1 << 28) | ||
714 | # define RADEON_FORCE_Z_DIRTY (1 << 29) | ||
715 | # define RADEON_Z_WRITE_ENABLE (1 << 30) | ||
716 | # define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31) | ||
717 | #define RADEON_RBBM_SOFT_RESET 0x00f0 | ||
718 | # define RADEON_SOFT_RESET_CP (1 << 0) | ||
719 | # define RADEON_SOFT_RESET_HI (1 << 1) | ||
720 | # define RADEON_SOFT_RESET_SE (1 << 2) | ||
721 | # define RADEON_SOFT_RESET_RE (1 << 3) | ||
722 | # define RADEON_SOFT_RESET_PP (1 << 4) | ||
723 | # define RADEON_SOFT_RESET_E2 (1 << 5) | ||
724 | # define RADEON_SOFT_RESET_RB (1 << 6) | ||
725 | # define RADEON_SOFT_RESET_HDP (1 << 7) | ||
726 | /* | ||
727 | * 6:0 Available slots in the FIFO | ||
728 | * 8 Host Interface active | ||
729 | * 9 CP request active | ||
730 | * 10 FIFO request active | ||
731 | * 11 Host Interface retry active | ||
732 | * 12 CP retry active | ||
733 | * 13 FIFO retry active | ||
734 | * 14 FIFO pipeline busy | ||
735 | * 15 Event engine busy | ||
736 | * 16 CP command stream busy | ||
737 | * 17 2D engine busy | ||
738 | * 18 2D portion of render backend busy | ||
739 | * 20 3D setup engine busy | ||
740 | * 26 GA engine busy | ||
741 | * 27 CBA 2D engine busy | ||
742 | * 31 2D engine busy or 3D engine busy or FIFO not empty or CP busy or | ||
743 | * command stream queue not empty or Ring Buffer not empty | ||
744 | */ | ||
745 | #define RADEON_RBBM_STATUS 0x0e40 | ||
746 | /* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register. */ | ||
747 | /* #define RADEON_RBBM_STATUS 0x1740 */ | ||
748 | /* bits 6:0 are dword slots available in the cmd fifo */ | ||
749 | # define RADEON_RBBM_FIFOCNT_MASK 0x007f | ||
750 | # define RADEON_HIRQ_ON_RBB (1 << 8) | ||
751 | # define RADEON_CPRQ_ON_RBB (1 << 9) | ||
752 | # define RADEON_CFRQ_ON_RBB (1 << 10) | ||
753 | # define RADEON_HIRQ_IN_RTBUF (1 << 11) | ||
754 | # define RADEON_CPRQ_IN_RTBUF (1 << 12) | ||
755 | # define RADEON_CFRQ_IN_RTBUF (1 << 13) | ||
756 | # define RADEON_PIPE_BUSY (1 << 14) | ||
757 | # define RADEON_ENG_EV_BUSY (1 << 15) | ||
758 | # define RADEON_CP_CMDSTRM_BUSY (1 << 16) | ||
759 | # define RADEON_E2_BUSY (1 << 17) | ||
760 | # define RADEON_RB2D_BUSY (1 << 18) | ||
761 | # define RADEON_RB3D_BUSY (1 << 19) /* not used on r300 */ | ||
762 | # define RADEON_VAP_BUSY (1 << 20) | ||
763 | # define RADEON_RE_BUSY (1 << 21) /* not used on r300 */ | ||
764 | # define RADEON_TAM_BUSY (1 << 22) /* not used on r300 */ | ||
765 | # define RADEON_TDM_BUSY (1 << 23) /* not used on r300 */ | ||
766 | # define RADEON_PB_BUSY (1 << 24) /* not used on r300 */ | ||
767 | # define RADEON_TIM_BUSY (1 << 25) /* not used on r300 */ | ||
768 | # define RADEON_GA_BUSY (1 << 26) | ||
769 | # define RADEON_CBA2D_BUSY (1 << 27) | ||
770 | # define RADEON_RBBM_ACTIVE (1 << 31) | ||
771 | #define RADEON_RE_LINE_PATTERN 0x1cd0 | ||
772 | #define RADEON_RE_MISC 0x26c4 | ||
773 | #define RADEON_RE_TOP_LEFT 0x26c0 | ||
774 | #define RADEON_RE_WIDTH_HEIGHT 0x1c44 | ||
775 | #define RADEON_RE_STIPPLE_ADDR 0x1cc8 | ||
776 | #define RADEON_RE_STIPPLE_DATA 0x1ccc | ||
777 | |||
778 | #define RADEON_SCISSOR_TL_0 0x1cd8 | ||
779 | #define RADEON_SCISSOR_BR_0 0x1cdc | ||
780 | #define RADEON_SCISSOR_TL_1 0x1ce0 | ||
781 | #define RADEON_SCISSOR_BR_1 0x1ce4 | ||
782 | #define RADEON_SCISSOR_TL_2 0x1ce8 | ||
783 | #define RADEON_SCISSOR_BR_2 0x1cec | ||
784 | #define RADEON_SE_COORD_FMT 0x1c50 | ||
785 | #define RADEON_SE_CNTL 0x1c4c | ||
786 | # define RADEON_FFACE_CULL_CW (0 << 0) | ||
787 | # define RADEON_BFACE_SOLID (3 << 1) | ||
788 | # define RADEON_FFACE_SOLID (3 << 3) | ||
789 | # define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) | ||
790 | # define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) | ||
791 | # define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) | ||
792 | # define RADEON_ALPHA_SHADE_FLAT (1 << 10) | ||
793 | # define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) | ||
794 | # define RADEON_SPECULAR_SHADE_FLAT (1 << 12) | ||
795 | # define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) | ||
796 | # define RADEON_FOG_SHADE_FLAT (1 << 14) | ||
797 | # define RADEON_FOG_SHADE_GOURAUD (2 << 14) | ||
798 | # define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) | ||
799 | # define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) | ||
800 | # define RADEON_VTX_PIX_CENTER_OGL (1 << 27) | ||
801 | # define RADEON_ROUND_MODE_TRUNC (0 << 28) | ||
802 | # define RADEON_ROUND_PREC_8TH_PIX (1 << 30) | ||
803 | #define RADEON_SE_CNTL_STATUS 0x2140 | ||
804 | #define RADEON_SE_LINE_WIDTH 0x1db8 | ||
805 | #define RADEON_SE_VPORT_XSCALE 0x1d98 | ||
806 | #define RADEON_SE_ZBIAS_FACTOR 0x1db0 | ||
807 | #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 | ||
808 | #define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 | ||
809 | #define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 | ||
810 | # define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 | ||
811 | # define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 | ||
812 | #define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 | ||
813 | #define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 | ||
814 | # define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 | ||
815 | #define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C | ||
816 | #define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 | ||
817 | #define RADEON_SURFACE_ACCESS_CLR 0x0bfc | ||
818 | #define RADEON_SURFACE_CNTL 0x0b00 | ||
819 | # define RADEON_SURF_TRANSLATION_DIS (1 << 8) | ||
820 | # define RADEON_NONSURF_AP0_SWP_MASK (3 << 20) | ||
821 | # define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20) | ||
822 | # define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20) | ||
823 | # define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20) | ||
824 | # define RADEON_NONSURF_AP1_SWP_MASK (3 << 22) | ||
825 | # define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22) | ||
826 | # define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22) | ||
827 | # define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22) | ||
828 | #define RADEON_SURFACE0_INFO 0x0b0c | ||
829 | # define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0) | ||
830 | # define RADEON_SURF_TILE_MODE_MASK (3 << 16) | ||
831 | # define RADEON_SURF_TILE_MODE_MACRO (0 << 16) | ||
832 | # define RADEON_SURF_TILE_MODE_MICRO (1 << 16) | ||
833 | # define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16) | ||
834 | # define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16) | ||
835 | #define RADEON_SURFACE0_LOWER_BOUND 0x0b04 | ||
836 | #define RADEON_SURFACE0_UPPER_BOUND 0x0b08 | ||
837 | # define RADEON_SURF_ADDRESS_FIXED_MASK (0x3ff << 0) | ||
838 | #define RADEON_SURFACE1_INFO 0x0b1c | ||
839 | #define RADEON_SURFACE1_LOWER_BOUND 0x0b14 | ||
840 | #define RADEON_SURFACE1_UPPER_BOUND 0x0b18 | ||
841 | #define RADEON_SURFACE2_INFO 0x0b2c | ||
842 | #define RADEON_SURFACE2_LOWER_BOUND 0x0b24 | ||
843 | #define RADEON_SURFACE2_UPPER_BOUND 0x0b28 | ||
844 | #define RADEON_SURFACE3_INFO 0x0b3c | ||
845 | #define RADEON_SURFACE3_LOWER_BOUND 0x0b34 | ||
846 | #define RADEON_SURFACE3_UPPER_BOUND 0x0b38 | ||
847 | #define RADEON_SURFACE4_INFO 0x0b4c | ||
848 | #define RADEON_SURFACE4_LOWER_BOUND 0x0b44 | ||
849 | #define RADEON_SURFACE4_UPPER_BOUND 0x0b48 | ||
850 | #define RADEON_SURFACE5_INFO 0x0b5c | ||
851 | #define RADEON_SURFACE5_LOWER_BOUND 0x0b54 | ||
852 | #define RADEON_SURFACE5_UPPER_BOUND 0x0b58 | ||
853 | #define RADEON_SURFACE6_INFO 0x0b6c | ||
854 | #define RADEON_SURFACE6_LOWER_BOUND 0x0b64 | ||
855 | #define RADEON_SURFACE6_UPPER_BOUND 0x0b68 | ||
856 | #define RADEON_SURFACE7_INFO 0x0b7c | ||
857 | #define RADEON_SURFACE7_LOWER_BOUND 0x0b74 | ||
858 | #define RADEON_SURFACE7_UPPER_BOUND 0x0b78 | ||
859 | #define RADEON_SW_SEMAPHORE 0x013c | ||
860 | |||
861 | #define RADEON_WAIT_UNTIL 0x1720 | ||
862 | # define RADEON_WAIT_CRTC_PFLIP (1 << 0) | ||
863 | # define RADEON_WAIT_2D_IDLE (1 << 14) | ||
864 | # define RADEON_WAIT_3D_IDLE (1 << 15) | ||
865 | # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) | ||
866 | # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) | ||
867 | # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) | ||
868 | |||
869 | #define RADEON_RB3D_ZMASKOFFSET 0x3234 | ||
870 | #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c | ||
871 | # define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) | ||
872 | # define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) | ||
873 | |||
874 | /* CP registers */ | ||
875 | #define RADEON_CP_ME_RAM_ADDR 0x07d4 | ||
876 | #define RADEON_CP_ME_RAM_RADDR 0x07d8 | ||
877 | #define RADEON_CP_ME_RAM_DATAH 0x07dc | ||
878 | #define RADEON_CP_ME_RAM_DATAL 0x07e0 | ||
879 | |||
880 | #define RADEON_CP_RB_BASE 0x0700 | ||
881 | #define RADEON_CP_RB_CNTL 0x0704 | ||
882 | # define RADEON_BUF_SWAP_32BIT (2 << 16) | ||
883 | # define RADEON_RB_NO_UPDATE (1 << 27) | ||
884 | #define RADEON_CP_RB_RPTR_ADDR 0x070c | ||
885 | #define RADEON_CP_RB_RPTR 0x0710 | ||
886 | #define RADEON_CP_RB_WPTR 0x0714 | ||
887 | |||
888 | #define RADEON_CP_RB_WPTR_DELAY 0x0718 | ||
889 | # define RADEON_PRE_WRITE_TIMER_SHIFT 0 | ||
890 | # define RADEON_PRE_WRITE_LIMIT_SHIFT 23 | ||
891 | |||
892 | #define RADEON_CP_IB_BASE 0x0738 | ||
893 | |||
894 | #define RADEON_CP_CSQ_CNTL 0x0740 | ||
895 | # define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) | ||
896 | # define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) | ||
897 | # define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) | ||
898 | # define RADEON_CSQ_PRIBM_INDDIS (2 << 28) | ||
899 | # define RADEON_CSQ_PRIPIO_INDBM (3 << 28) | ||
900 | # define RADEON_CSQ_PRIBM_INDBM (4 << 28) | ||
901 | # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) | ||
902 | |||
903 | #define RADEON_AIC_CNTL 0x01d0 | ||
904 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) | ||
905 | #define RADEON_AIC_STAT 0x01d4 | ||
906 | #define RADEON_AIC_PT_BASE 0x01d8 | ||
907 | #define RADEON_AIC_LO_ADDR 0x01dc | ||
908 | #define RADEON_AIC_HI_ADDR 0x01e0 | ||
909 | #define RADEON_AIC_TLB_ADDR 0x01e4 | ||
910 | #define RADEON_AIC_TLB_DATA 0x01e8 | ||
911 | |||
912 | /* CP command packets */ | ||
913 | #define RADEON_CP_PACKET0 0x00000000 | ||
914 | # define RADEON_ONE_REG_WR (1 << 15) | ||
915 | #define RADEON_CP_PACKET1 0x40000000 | ||
916 | #define RADEON_CP_PACKET2 0x80000000 | ||
917 | #define RADEON_CP_PACKET3 0xC0000000 | ||
918 | # define RADEON_CP_NOP 0x00001000 | ||
919 | # define RADEON_CP_NEXT_CHAR 0x00001900 | ||
920 | # define RADEON_CP_PLY_NEXTSCAN 0x00001D00 | ||
921 | # define RADEON_CP_SET_SCISSORS 0x00001E00 | ||
922 | /* GEN_INDX_PRIM is unsupported starting with R300 */ | ||
923 | # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 | ||
924 | # define RADEON_WAIT_FOR_IDLE 0x00002600 | ||
925 | # define RADEON_3D_DRAW_VBUF 0x00002800 | ||
926 | # define RADEON_3D_DRAW_IMMD 0x00002900 | ||
927 | # define RADEON_3D_DRAW_INDX 0x00002A00 | ||
928 | # define RADEON_CP_LOAD_PALETTE 0x00002C00 | ||
929 | # define RADEON_3D_LOAD_VBPNTR 0x00002F00 | ||
930 | # define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000 | ||
931 | # define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100 | ||
932 | # define RADEON_3D_CLEAR_ZMASK 0x00003200 | ||
933 | # define RADEON_CP_INDX_BUFFER 0x00003300 | ||
934 | # define RADEON_CP_3D_DRAW_VBUF_2 0x00003400 | ||
935 | # define RADEON_CP_3D_DRAW_IMMD_2 0x00003500 | ||
936 | # define RADEON_CP_3D_DRAW_INDX_2 0x00003600 | ||
937 | # define RADEON_3D_CLEAR_HIZ 0x00003700 | ||
938 | # define RADEON_CP_3D_CLEAR_CMASK 0x00003802 | ||
939 | # define RADEON_CNTL_HOSTDATA_BLT 0x00009400 | ||
940 | # define RADEON_CNTL_PAINT_MULTI 0x00009A00 | ||
941 | # define RADEON_CNTL_BITBLT_MULTI 0x00009B00 | ||
942 | # define RADEON_CNTL_SET_SCISSORS 0xC0001E00 | ||
943 | |||
944 | #define RADEON_CP_PACKET_MASK 0xC0000000 | ||
945 | #define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 | ||
946 | #define RADEON_CP_PACKET0_REG_MASK 0x000007ff | ||
947 | #define RADEON_CP_PACKET1_REG0_MASK 0x000007ff | ||
948 | #define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 | ||
949 | |||
950 | #define RADEON_VTX_Z_PRESENT (1 << 31) | ||
951 | #define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) | ||
952 | |||
953 | #define RADEON_PRIM_TYPE_NONE (0 << 0) | ||
954 | #define RADEON_PRIM_TYPE_POINT (1 << 0) | ||
955 | #define RADEON_PRIM_TYPE_LINE (2 << 0) | ||
956 | #define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0) | ||
957 | #define RADEON_PRIM_TYPE_TRI_LIST (4 << 0) | ||
958 | #define RADEON_PRIM_TYPE_TRI_FAN (5 << 0) | ||
959 | #define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0) | ||
960 | #define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0) | ||
961 | #define RADEON_PRIM_TYPE_RECT_LIST (8 << 0) | ||
962 | #define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) | ||
963 | #define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) | ||
964 | #define RADEON_PRIM_TYPE_MASK 0xf | ||
965 | #define RADEON_PRIM_WALK_IND (1 << 4) | ||
966 | #define RADEON_PRIM_WALK_LIST (2 << 4) | ||
967 | #define RADEON_PRIM_WALK_RING (3 << 4) | ||
968 | #define RADEON_COLOR_ORDER_BGRA (0 << 6) | ||
969 | #define RADEON_COLOR_ORDER_RGBA (1 << 6) | ||
970 | #define RADEON_MAOS_ENABLE (1 << 7) | ||
971 | #define RADEON_VTX_FMT_R128_MODE (0 << 8) | ||
972 | #define RADEON_VTX_FMT_RADEON_MODE (1 << 8) | ||
973 | #define RADEON_NUM_VERTICES_SHIFT 16 | ||
974 | |||
975 | #define RADEON_COLOR_FORMAT_CI8 2 | ||
976 | #define RADEON_COLOR_FORMAT_ARGB1555 3 | ||
977 | #define RADEON_COLOR_FORMAT_RGB565 4 | ||
978 | #define RADEON_COLOR_FORMAT_ARGB8888 6 | ||
979 | #define RADEON_COLOR_FORMAT_RGB332 7 | ||
980 | #define RADEON_COLOR_FORMAT_RGB8 9 | ||
981 | #define RADEON_COLOR_FORMAT_ARGB4444 15 | ||
982 | |||
983 | #define RADEON_TXFORMAT_I8 0 | ||
984 | #define RADEON_TXFORMAT_AI88 1 | ||
985 | #define RADEON_TXFORMAT_RGB332 2 | ||
986 | #define RADEON_TXFORMAT_ARGB1555 3 | ||
987 | #define RADEON_TXFORMAT_RGB565 4 | ||
988 | #define RADEON_TXFORMAT_ARGB4444 5 | ||
989 | #define RADEON_TXFORMAT_ARGB8888 6 | ||
990 | #define RADEON_TXFORMAT_RGBA8888 7 | ||
991 | #define RADEON_TXFORMAT_Y8 8 | ||
992 | #define RADEON_TXFORMAT_VYUY422 10 | ||
993 | #define RADEON_TXFORMAT_YVYU422 11 | ||
994 | #define RADEON_TXFORMAT_DXT1 12 | ||
995 | #define RADEON_TXFORMAT_DXT23 14 | ||
996 | #define RADEON_TXFORMAT_DXT45 15 | ||
997 | |||
998 | #define R200_PP_TXCBLEND_0 0x2f00 | ||
999 | #define R200_PP_TXCBLEND_1 0x2f10 | ||
1000 | #define R200_PP_TXCBLEND_2 0x2f20 | ||
1001 | #define R200_PP_TXCBLEND_3 0x2f30 | ||
1002 | #define R200_PP_TXCBLEND_4 0x2f40 | ||
1003 | #define R200_PP_TXCBLEND_5 0x2f50 | ||
1004 | #define R200_PP_TXCBLEND_6 0x2f60 | ||
1005 | #define R200_PP_TXCBLEND_7 0x2f70 | ||
1006 | #define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 | ||
1007 | #define R200_PP_TFACTOR_0 0x2ee0 | ||
1008 | #define R200_SE_VTX_FMT_0 0x2088 | ||
1009 | #define R200_SE_VAP_CNTL 0x2080 | ||
1010 | #define R200_SE_TCL_MATRIX_SEL_0 0x2230 | ||
1011 | #define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 | ||
1012 | #define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 | ||
1013 | #define R200_PP_TXFILTER_5 0x2ca0 | ||
1014 | #define R200_PP_TXFILTER_4 0x2c80 | ||
1015 | #define R200_PP_TXFILTER_3 0x2c60 | ||
1016 | #define R200_PP_TXFILTER_2 0x2c40 | ||
1017 | #define R200_PP_TXFILTER_1 0x2c20 | ||
1018 | #define R200_PP_TXFILTER_0 0x2c00 | ||
1019 | #define R200_PP_TXOFFSET_5 0x2d78 | ||
1020 | #define R200_PP_TXOFFSET_4 0x2d60 | ||
1021 | #define R200_PP_TXOFFSET_3 0x2d48 | ||
1022 | #define R200_PP_TXOFFSET_2 0x2d30 | ||
1023 | #define R200_PP_TXOFFSET_1 0x2d18 | ||
1024 | #define R200_PP_TXOFFSET_0 0x2d00 | ||
1025 | |||
1026 | #define R200_PP_CUBIC_FACES_0 0x2c18 | ||
1027 | #define R200_PP_CUBIC_FACES_1 0x2c38 | ||
1028 | #define R200_PP_CUBIC_FACES_2 0x2c58 | ||
1029 | #define R200_PP_CUBIC_FACES_3 0x2c78 | ||
1030 | #define R200_PP_CUBIC_FACES_4 0x2c98 | ||
1031 | #define R200_PP_CUBIC_FACES_5 0x2cb8 | ||
1032 | #define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 | ||
1033 | #define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 | ||
1034 | #define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c | ||
1035 | #define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 | ||
1036 | #define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 | ||
1037 | #define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c | ||
1038 | #define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 | ||
1039 | #define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 | ||
1040 | #define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 | ||
1041 | #define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c | ||
1042 | #define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 | ||
1043 | #define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 | ||
1044 | #define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c | ||
1045 | #define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 | ||
1046 | #define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 | ||
1047 | #define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c | ||
1048 | #define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 | ||
1049 | #define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 | ||
1050 | #define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 | ||
1051 | #define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c | ||
1052 | #define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 | ||
1053 | #define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 | ||
1054 | #define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c | ||
1055 | #define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 | ||
1056 | #define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 | ||
1057 | #define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c | ||
1058 | #define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 | ||
1059 | #define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 | ||
1060 | #define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 | ||
1061 | #define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c | ||
1062 | |||
1063 | #define R200_RE_AUX_SCISSOR_CNTL 0x26f0 | ||
1064 | #define R200_SE_VTE_CNTL 0x20b0 | ||
1065 | #define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 | ||
1066 | #define R200_PP_TAM_DEBUG3 0x2d9c | ||
1067 | #define R200_PP_CNTL_X 0x2cc4 | ||
1068 | #define R200_SE_VAP_CNTL_STATUS 0x2140 | ||
1069 | #define R200_RE_SCISSOR_TL_0 0x1cd8 | ||
1070 | #define R200_RE_SCISSOR_TL_1 0x1ce0 | ||
1071 | #define R200_RE_SCISSOR_TL_2 0x1ce8 | ||
1072 | #define R200_RB3D_DEPTHXY_OFFSET 0x1d60 | ||
1073 | #define R200_RE_AUX_SCISSOR_CNTL 0x26f0 | ||
1074 | #define R200_SE_VTX_STATE_CNTL 0x2180 | ||
1075 | #define R200_RE_POINTSIZE 0x2648 | ||
1076 | #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 | ||
1077 | |||
1078 | #define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ | ||
1079 | #define RADEON_PP_TEX_SIZE_1 0x1d0c | ||
1080 | #define RADEON_PP_TEX_SIZE_2 0x1d14 | ||
1081 | |||
1082 | #define RADEON_PP_CUBIC_FACES_0 0x1d24 | ||
1083 | #define RADEON_PP_CUBIC_FACES_1 0x1d28 | ||
1084 | #define RADEON_PP_CUBIC_FACES_2 0x1d2c | ||
1085 | #define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ | ||
1086 | #define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 | ||
1087 | #define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 | ||
1088 | |||
1089 | #define RADEON_SE_TCL_STATE_FLUSH 0x2284 | ||
1090 | |||
1091 | #define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 | ||
1092 | #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 | ||
1093 | #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 | ||
1094 | #define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 | ||
1095 | #define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 | ||
1096 | #define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 | ||
1097 | #define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 | ||
1098 | #define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b | ||
1099 | #define R200_3D_DRAW_IMMD_2 0xC0003500 | ||
1100 | #define R200_SE_VTX_FMT_1 0x208c | ||
1101 | #define R200_RE_CNTL 0x1c50 | ||
1102 | |||
1103 | #define R200_RB3D_BLENDCOLOR 0x3218 | ||
1104 | |||
1105 | #define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 | ||
1106 | |||
1107 | #define R200_PP_TRI_PERF 0x2cf8 | ||
1108 | |||
1109 | #define R200_PP_AFS_0 0x2f80 | ||
1110 | #define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ | ||
1111 | |||
1112 | #define R200_VAP_PVS_CNTL_1 0x22D0 | ||
1113 | |||
1114 | #define R500_D1CRTC_STATUS 0x609c | ||
1115 | #define R500_D2CRTC_STATUS 0x689c | ||
1116 | #define R500_CRTC_V_BLANK (1<<0) | ||
1117 | |||
1118 | #define R500_D1CRTC_FRAME_COUNT 0x60a4 | ||
1119 | #define R500_D2CRTC_FRAME_COUNT 0x68a4 | ||
1120 | |||
1121 | #define R500_D1MODE_V_COUNTER 0x6530 | ||
1122 | #define R500_D2MODE_V_COUNTER 0x6d30 | ||
1123 | |||
1124 | #define R500_D1MODE_VBLANK_STATUS 0x6534 | ||
1125 | #define R500_D2MODE_VBLANK_STATUS 0x6d34 | ||
1126 | #define R500_VBLANK_OCCURED (1<<0) | ||
1127 | #define R500_VBLANK_ACK (1<<4) | ||
1128 | #define R500_VBLANK_STAT (1<<12) | ||
1129 | #define R500_VBLANK_INT (1<<16) | ||
1130 | |||
1131 | #define R500_DxMODE_INT_MASK 0x6540 | ||
1132 | #define R500_D1MODE_INT_MASK (1<<0) | ||
1133 | #define R500_D2MODE_INT_MASK (1<<8) | ||
1134 | |||
1135 | #define R500_DISP_INTERRUPT_STATUS 0x7edc | ||
1136 | #define R500_D1_VBLANK_INTERRUPT (1 << 4) | ||
1137 | #define R500_D2_VBLANK_INTERRUPT (1 << 5) | ||
1138 | |||
1139 | /* Constants */ | ||
1140 | #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ | ||
1141 | |||
1142 | #define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 | ||
1143 | #define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 | ||
1144 | #define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 | ||
1145 | #define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3 | ||
1146 | #define RADEON_LAST_DISPATCH 1 | ||
1147 | |||
1148 | #define RADEON_MAX_VB_AGE 0x7fffffff | ||
1149 | #define RADEON_MAX_VB_VERTS (0xffff) | ||
1150 | |||
1151 | #define RADEON_RING_HIGH_MARK 128 | ||
1152 | |||
1153 | #define RADEON_PCIGART_TABLE_SIZE (32*1024) | ||
1154 | |||
1155 | #define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) | ||
1156 | #define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) | ||
1157 | #define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) | ||
1158 | #define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) | ||
1159 | |||
1160 | #define RADEON_WRITE_PLL(addr, val) \ | ||
1161 | do { \ | ||
1162 | RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \ | ||
1163 | ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \ | ||
1164 | RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val)); \ | ||
1165 | } while (0) | ||
1166 | |||
1167 | #define RADEON_WRITE_PCIE(addr, val) \ | ||
1168 | do { \ | ||
1169 | RADEON_WRITE8(RADEON_PCIE_INDEX, \ | ||
1170 | ((addr) & 0xff)); \ | ||
1171 | RADEON_WRITE(RADEON_PCIE_DATA, (val)); \ | ||
1172 | } while (0) | ||
1173 | |||
1174 | #define R500_WRITE_MCIND(addr, val) \ | ||
1175 | do { \ | ||
1176 | RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \ | ||
1177 | RADEON_WRITE(R520_MC_IND_DATA, (val)); \ | ||
1178 | RADEON_WRITE(R520_MC_IND_INDEX, 0); \ | ||
1179 | } while (0) | ||
1180 | |||
1181 | #define RS480_WRITE_MCIND(addr, val) \ | ||
1182 | do { \ | ||
1183 | RADEON_WRITE(RS480_NB_MC_INDEX, \ | ||
1184 | ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN); \ | ||
1185 | RADEON_WRITE(RS480_NB_MC_DATA, (val)); \ | ||
1186 | RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); \ | ||
1187 | } while (0) | ||
1188 | |||
1189 | #define RS690_WRITE_MCIND(addr, val) \ | ||
1190 | do { \ | ||
1191 | RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK)); \ | ||
1192 | RADEON_WRITE(RS690_MC_DATA, val); \ | ||
1193 | RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ | ||
1194 | } while (0) | ||
1195 | |||
1196 | #define IGP_WRITE_MCIND(addr, val) \ | ||
1197 | do { \ | ||
1198 | if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) \ | ||
1199 | RS690_WRITE_MCIND(addr, val); \ | ||
1200 | else \ | ||
1201 | RS480_WRITE_MCIND(addr, val); \ | ||
1202 | } while (0) | ||
1203 | |||
1204 | #define CP_PACKET0( reg, n ) \ | ||
1205 | (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) | ||
1206 | #define CP_PACKET0_TABLE( reg, n ) \ | ||
1207 | (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2)) | ||
1208 | #define CP_PACKET1( reg0, reg1 ) \ | ||
1209 | (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2)) | ||
1210 | #define CP_PACKET2() \ | ||
1211 | (RADEON_CP_PACKET2) | ||
1212 | #define CP_PACKET3( pkt, n ) \ | ||
1213 | (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) | ||
1214 | |||
1215 | /* ================================================================ | ||
1216 | * Engine control helper macros | ||
1217 | */ | ||
1218 | |||
1219 | #define RADEON_WAIT_UNTIL_2D_IDLE() do { \ | ||
1220 | OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ | ||
1221 | OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ | ||
1222 | RADEON_WAIT_HOST_IDLECLEAN) ); \ | ||
1223 | } while (0) | ||
1224 | |||
1225 | #define RADEON_WAIT_UNTIL_3D_IDLE() do { \ | ||
1226 | OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ | ||
1227 | OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \ | ||
1228 | RADEON_WAIT_HOST_IDLECLEAN) ); \ | ||
1229 | } while (0) | ||
1230 | |||
1231 | #define RADEON_WAIT_UNTIL_IDLE() do { \ | ||
1232 | OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ | ||
1233 | OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ | ||
1234 | RADEON_WAIT_3D_IDLECLEAN | \ | ||
1235 | RADEON_WAIT_HOST_IDLECLEAN) ); \ | ||
1236 | } while (0) | ||
1237 | |||
1238 | #define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \ | ||
1239 | OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ | ||
1240 | OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \ | ||
1241 | } while (0) | ||
1242 | |||
1243 | #define RADEON_FLUSH_CACHE() do { \ | ||
1244 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ | ||
1245 | OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ | ||
1246 | OUT_RING(RADEON_RB3D_DC_FLUSH); \ | ||
1247 | } else { \ | ||
1248 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ | ||
1249 | OUT_RING(RADEON_RB3D_DC_FLUSH); \ | ||
1250 | } \ | ||
1251 | } while (0) | ||
1252 | |||
1253 | #define RADEON_PURGE_CACHE() do { \ | ||
1254 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ | ||
1255 | OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ | ||
1256 | OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ | ||
1257 | } else { \ | ||
1258 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ | ||
1259 | OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ | ||
1260 | } \ | ||
1261 | } while (0) | ||
1262 | |||
1263 | #define RADEON_FLUSH_ZCACHE() do { \ | ||
1264 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ | ||
1265 | OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ | ||
1266 | OUT_RING(RADEON_RB3D_ZC_FLUSH); \ | ||
1267 | } else { \ | ||
1268 | OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ | ||
1269 | OUT_RING(R300_ZC_FLUSH); \ | ||
1270 | } \ | ||
1271 | } while (0) | ||
1272 | |||
1273 | #define RADEON_PURGE_ZCACHE() do { \ | ||
1274 | if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ | ||
1275 | OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ | ||
1276 | OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \ | ||
1277 | } else { \ | ||
1278 | OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ | ||
1279 | OUT_RING(R300_ZC_FLUSH_ALL); \ | ||
1280 | } \ | ||
1281 | } while (0) | ||
1282 | |||
1283 | /* ================================================================ | ||
1284 | * Misc helper macros | ||
1285 | */ | ||
1286 | |||
1287 | /* Perfbox functionality only. | ||
1288 | */ | ||
1289 | #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ | ||
1290 | do { \ | ||
1291 | if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ | ||
1292 | u32 head = GET_RING_HEAD( dev_priv ); \ | ||
1293 | if (head == dev_priv->ring.tail) \ | ||
1294 | dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ | ||
1295 | } \ | ||
1296 | } while (0) | ||
1297 | |||
1298 | #define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ | ||
1299 | do { \ | ||
1300 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \ | ||
1301 | if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ | ||
1302 | int __ret = radeon_do_cp_idle( dev_priv ); \ | ||
1303 | if ( __ret ) return __ret; \ | ||
1304 | sarea_priv->last_dispatch = 0; \ | ||
1305 | radeon_freelist_reset( dev ); \ | ||
1306 | } \ | ||
1307 | } while (0) | ||
1308 | |||
1309 | #define RADEON_DISPATCH_AGE( age ) do { \ | ||
1310 | OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \ | ||
1311 | OUT_RING( age ); \ | ||
1312 | } while (0) | ||
1313 | |||
1314 | #define RADEON_FRAME_AGE( age ) do { \ | ||
1315 | OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \ | ||
1316 | OUT_RING( age ); \ | ||
1317 | } while (0) | ||
1318 | |||
1319 | #define RADEON_CLEAR_AGE( age ) do { \ | ||
1320 | OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \ | ||
1321 | OUT_RING( age ); \ | ||
1322 | } while (0) | ||
1323 | |||
1324 | /* ================================================================ | ||
1325 | * Ring control | ||
1326 | */ | ||
1327 | |||
1328 | #define RADEON_VERBOSE 0 | ||
1329 | |||
1330 | #define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring; | ||
1331 | |||
1332 | #define BEGIN_RING( n ) do { \ | ||
1333 | if ( RADEON_VERBOSE ) { \ | ||
1334 | DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ | ||
1335 | } \ | ||
1336 | if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ | ||
1337 | COMMIT_RING(); \ | ||
1338 | radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \ | ||
1339 | } \ | ||
1340 | _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ | ||
1341 | ring = dev_priv->ring.start; \ | ||
1342 | write = dev_priv->ring.tail; \ | ||
1343 | mask = dev_priv->ring.tail_mask; \ | ||
1344 | } while (0) | ||
1345 | |||
1346 | #define ADVANCE_RING() do { \ | ||
1347 | if ( RADEON_VERBOSE ) { \ | ||
1348 | DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ | ||
1349 | write, dev_priv->ring.tail ); \ | ||
1350 | } \ | ||
1351 | if (((dev_priv->ring.tail + _nr) & mask) != write) { \ | ||
1352 | DRM_ERROR( \ | ||
1353 | "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ | ||
1354 | ((dev_priv->ring.tail + _nr) & mask), \ | ||
1355 | write, __LINE__); \ | ||
1356 | } else \ | ||
1357 | dev_priv->ring.tail = write; \ | ||
1358 | } while (0) | ||
1359 | |||
1360 | #define COMMIT_RING() do { \ | ||
1361 | /* Flush writes to ring */ \ | ||
1362 | DRM_MEMORYBARRIER(); \ | ||
1363 | GET_RING_HEAD( dev_priv ); \ | ||
1364 | RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ | ||
1365 | /* read from PCI bus to ensure correct posting */ \ | ||
1366 | RADEON_READ( RADEON_CP_RB_RPTR ); \ | ||
1367 | } while (0) | ||
1368 | |||
1369 | #define OUT_RING( x ) do { \ | ||
1370 | if ( RADEON_VERBOSE ) { \ | ||
1371 | DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ | ||
1372 | (unsigned int)(x), write ); \ | ||
1373 | } \ | ||
1374 | ring[write++] = (x); \ | ||
1375 | write &= mask; \ | ||
1376 | } while (0) | ||
1377 | |||
1378 | #define OUT_RING_REG( reg, val ) do { \ | ||
1379 | OUT_RING( CP_PACKET0( reg, 0 ) ); \ | ||
1380 | OUT_RING( val ); \ | ||
1381 | } while (0) | ||
1382 | |||
1383 | #define OUT_RING_TABLE( tab, sz ) do { \ | ||
1384 | int _size = (sz); \ | ||
1385 | int *_tab = (int *)(tab); \ | ||
1386 | \ | ||
1387 | if (write + _size > mask) { \ | ||
1388 | int _i = (mask+1) - write; \ | ||
1389 | _size -= _i; \ | ||
1390 | while (_i > 0 ) { \ | ||
1391 | *(int *)(ring + write) = *_tab++; \ | ||
1392 | write++; \ | ||
1393 | _i--; \ | ||
1394 | } \ | ||
1395 | write = 0; \ | ||
1396 | _tab += _i; \ | ||
1397 | } \ | ||
1398 | while (_size > 0) { \ | ||
1399 | *(ring + write) = *_tab++; \ | ||
1400 | write++; \ | ||
1401 | _size--; \ | ||
1402 | } \ | ||
1403 | write &= mask; \ | ||
1404 | } while (0) | ||
1405 | |||
1406 | #endif /* __RADEON_DRV_H__ */ | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c new file mode 100644 index 000000000000..56decda2a71f --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c | |||
@@ -0,0 +1,424 @@ | |||
1 | /** | ||
2 | * \file radeon_ioc32.c | ||
3 | * | ||
4 | * 32-bit ioctl compatibility routines for the Radeon DRM. | ||
5 | * | ||
6 | * \author Paul Mackerras <paulus@samba.org> | ||
7 | * | ||
8 | * Copyright (C) Paul Mackerras 2005 | ||
9 | * All Rights Reserved. | ||
10 | * | ||
11 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
12 | * copy of this software and associated documentation files (the "Software"), | ||
13 | * to deal in the Software without restriction, including without limitation | ||
14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
15 | * and/or sell copies of the Software, and to permit persons to whom the | ||
16 | * Software is furnished to do so, subject to the following conditions: | ||
17 | * | ||
18 | * The above copyright notice and this permission notice (including the next | ||
19 | * paragraph) shall be included in all copies or substantial portions of the | ||
20 | * Software. | ||
21 | * | ||
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
25 | * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
28 | * IN THE SOFTWARE. | ||
29 | */ | ||
30 | #include <linux/compat.h> | ||
31 | |||
32 | #include "drmP.h" | ||
33 | #include "drm.h" | ||
34 | #include "radeon_drm.h" | ||
35 | #include "radeon_drv.h" | ||
36 | |||
37 | typedef struct drm_radeon_init32 { | ||
38 | int func; | ||
39 | u32 sarea_priv_offset; | ||
40 | int is_pci; | ||
41 | int cp_mode; | ||
42 | int gart_size; | ||
43 | int ring_size; | ||
44 | int usec_timeout; | ||
45 | |||
46 | unsigned int fb_bpp; | ||
47 | unsigned int front_offset, front_pitch; | ||
48 | unsigned int back_offset, back_pitch; | ||
49 | unsigned int depth_bpp; | ||
50 | unsigned int depth_offset, depth_pitch; | ||
51 | |||
52 | u32 fb_offset; | ||
53 | u32 mmio_offset; | ||
54 | u32 ring_offset; | ||
55 | u32 ring_rptr_offset; | ||
56 | u32 buffers_offset; | ||
57 | u32 gart_textures_offset; | ||
58 | } drm_radeon_init32_t; | ||
59 | |||
60 | static int compat_radeon_cp_init(struct file *file, unsigned int cmd, | ||
61 | unsigned long arg) | ||
62 | { | ||
63 | drm_radeon_init32_t init32; | ||
64 | drm_radeon_init_t __user *init; | ||
65 | |||
66 | if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) | ||
67 | return -EFAULT; | ||
68 | |||
69 | init = compat_alloc_user_space(sizeof(*init)); | ||
70 | if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) | ||
71 | || __put_user(init32.func, &init->func) | ||
72 | || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) | ||
73 | || __put_user(init32.is_pci, &init->is_pci) | ||
74 | || __put_user(init32.cp_mode, &init->cp_mode) | ||
75 | || __put_user(init32.gart_size, &init->gart_size) | ||
76 | || __put_user(init32.ring_size, &init->ring_size) | ||
77 | || __put_user(init32.usec_timeout, &init->usec_timeout) | ||
78 | || __put_user(init32.fb_bpp, &init->fb_bpp) | ||
79 | || __put_user(init32.front_offset, &init->front_offset) | ||
80 | || __put_user(init32.front_pitch, &init->front_pitch) | ||
81 | || __put_user(init32.back_offset, &init->back_offset) | ||
82 | || __put_user(init32.back_pitch, &init->back_pitch) | ||
83 | || __put_user(init32.depth_bpp, &init->depth_bpp) | ||
84 | || __put_user(init32.depth_offset, &init->depth_offset) | ||
85 | || __put_user(init32.depth_pitch, &init->depth_pitch) | ||
86 | || __put_user(init32.fb_offset, &init->fb_offset) | ||
87 | || __put_user(init32.mmio_offset, &init->mmio_offset) | ||
88 | || __put_user(init32.ring_offset, &init->ring_offset) | ||
89 | || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) | ||
90 | || __put_user(init32.buffers_offset, &init->buffers_offset) | ||
91 | || __put_user(init32.gart_textures_offset, | ||
92 | &init->gart_textures_offset)) | ||
93 | return -EFAULT; | ||
94 | |||
95 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
96 | DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); | ||
97 | } | ||
98 | |||
99 | typedef struct drm_radeon_clear32 { | ||
100 | unsigned int flags; | ||
101 | unsigned int clear_color; | ||
102 | unsigned int clear_depth; | ||
103 | unsigned int color_mask; | ||
104 | unsigned int depth_mask; /* misnamed field: should be stencil */ | ||
105 | u32 depth_boxes; | ||
106 | } drm_radeon_clear32_t; | ||
107 | |||
108 | static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, | ||
109 | unsigned long arg) | ||
110 | { | ||
111 | drm_radeon_clear32_t clr32; | ||
112 | drm_radeon_clear_t __user *clr; | ||
113 | |||
114 | if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32))) | ||
115 | return -EFAULT; | ||
116 | |||
117 | clr = compat_alloc_user_space(sizeof(*clr)); | ||
118 | if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr)) | ||
119 | || __put_user(clr32.flags, &clr->flags) | ||
120 | || __put_user(clr32.clear_color, &clr->clear_color) | ||
121 | || __put_user(clr32.clear_depth, &clr->clear_depth) | ||
122 | || __put_user(clr32.color_mask, &clr->color_mask) | ||
123 | || __put_user(clr32.depth_mask, &clr->depth_mask) | ||
124 | || __put_user((void __user *)(unsigned long)clr32.depth_boxes, | ||
125 | &clr->depth_boxes)) | ||
126 | return -EFAULT; | ||
127 | |||
128 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
129 | DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); | ||
130 | } | ||
131 | |||
132 | typedef struct drm_radeon_stipple32 { | ||
133 | u32 mask; | ||
134 | } drm_radeon_stipple32_t; | ||
135 | |||
136 | static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, | ||
137 | unsigned long arg) | ||
138 | { | ||
139 | drm_radeon_stipple32_t __user *argp = (void __user *)arg; | ||
140 | drm_radeon_stipple_t __user *request; | ||
141 | u32 mask; | ||
142 | |||
143 | if (get_user(mask, &argp->mask)) | ||
144 | return -EFAULT; | ||
145 | |||
146 | request = compat_alloc_user_space(sizeof(*request)); | ||
147 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
148 | || __put_user((unsigned int __user *)(unsigned long)mask, | ||
149 | &request->mask)) | ||
150 | return -EFAULT; | ||
151 | |||
152 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
153 | DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); | ||
154 | } | ||
155 | |||
156 | typedef struct drm_radeon_tex_image32 { | ||
157 | unsigned int x, y; /* Blit coordinates */ | ||
158 | unsigned int width, height; | ||
159 | u32 data; | ||
160 | } drm_radeon_tex_image32_t; | ||
161 | |||
162 | typedef struct drm_radeon_texture32 { | ||
163 | unsigned int offset; | ||
164 | int pitch; | ||
165 | int format; | ||
166 | int width; /* Texture image coordinates */ | ||
167 | int height; | ||
168 | u32 image; | ||
169 | } drm_radeon_texture32_t; | ||
170 | |||
171 | static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, | ||
172 | unsigned long arg) | ||
173 | { | ||
174 | drm_radeon_texture32_t req32; | ||
175 | drm_radeon_texture_t __user *request; | ||
176 | drm_radeon_tex_image32_t img32; | ||
177 | drm_radeon_tex_image_t __user *image; | ||
178 | |||
179 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
180 | return -EFAULT; | ||
181 | if (req32.image == 0) | ||
182 | return -EINVAL; | ||
183 | if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image, | ||
184 | sizeof(img32))) | ||
185 | return -EFAULT; | ||
186 | |||
187 | request = compat_alloc_user_space(sizeof(*request) + sizeof(*image)); | ||
188 | if (!access_ok(VERIFY_WRITE, request, | ||
189 | sizeof(*request) + sizeof(*image))) | ||
190 | return -EFAULT; | ||
191 | image = (drm_radeon_tex_image_t __user *) (request + 1); | ||
192 | |||
193 | if (__put_user(req32.offset, &request->offset) | ||
194 | || __put_user(req32.pitch, &request->pitch) | ||
195 | || __put_user(req32.format, &request->format) | ||
196 | || __put_user(req32.width, &request->width) | ||
197 | || __put_user(req32.height, &request->height) | ||
198 | || __put_user(image, &request->image) | ||
199 | || __put_user(img32.x, &image->x) | ||
200 | || __put_user(img32.y, &image->y) | ||
201 | || __put_user(img32.width, &image->width) | ||
202 | || __put_user(img32.height, &image->height) | ||
203 | || __put_user((const void __user *)(unsigned long)img32.data, | ||
204 | &image->data)) | ||
205 | return -EFAULT; | ||
206 | |||
207 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
208 | DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); | ||
209 | } | ||
210 | |||
211 | typedef struct drm_radeon_vertex2_32 { | ||
212 | int idx; /* Index of vertex buffer */ | ||
213 | int discard; /* Client finished with buffer? */ | ||
214 | int nr_states; | ||
215 | u32 state; | ||
216 | int nr_prims; | ||
217 | u32 prim; | ||
218 | } drm_radeon_vertex2_32_t; | ||
219 | |||
220 | static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, | ||
221 | unsigned long arg) | ||
222 | { | ||
223 | drm_radeon_vertex2_32_t req32; | ||
224 | drm_radeon_vertex2_t __user *request; | ||
225 | |||
226 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
227 | return -EFAULT; | ||
228 | |||
229 | request = compat_alloc_user_space(sizeof(*request)); | ||
230 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
231 | || __put_user(req32.idx, &request->idx) | ||
232 | || __put_user(req32.discard, &request->discard) | ||
233 | || __put_user(req32.nr_states, &request->nr_states) | ||
234 | || __put_user((void __user *)(unsigned long)req32.state, | ||
235 | &request->state) | ||
236 | || __put_user(req32.nr_prims, &request->nr_prims) | ||
237 | || __put_user((void __user *)(unsigned long)req32.prim, | ||
238 | &request->prim)) | ||
239 | return -EFAULT; | ||
240 | |||
241 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
242 | DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); | ||
243 | } | ||
244 | |||
245 | typedef struct drm_radeon_cmd_buffer32 { | ||
246 | int bufsz; | ||
247 | u32 buf; | ||
248 | int nbox; | ||
249 | u32 boxes; | ||
250 | } drm_radeon_cmd_buffer32_t; | ||
251 | |||
252 | static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, | ||
253 | unsigned long arg) | ||
254 | { | ||
255 | drm_radeon_cmd_buffer32_t req32; | ||
256 | drm_radeon_cmd_buffer_t __user *request; | ||
257 | |||
258 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
259 | return -EFAULT; | ||
260 | |||
261 | request = compat_alloc_user_space(sizeof(*request)); | ||
262 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
263 | || __put_user(req32.bufsz, &request->bufsz) | ||
264 | || __put_user((void __user *)(unsigned long)req32.buf, | ||
265 | &request->buf) | ||
266 | || __put_user(req32.nbox, &request->nbox) | ||
267 | || __put_user((void __user *)(unsigned long)req32.boxes, | ||
268 | &request->boxes)) | ||
269 | return -EFAULT; | ||
270 | |||
271 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
272 | DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); | ||
273 | } | ||
274 | |||
275 | typedef struct drm_radeon_getparam32 { | ||
276 | int param; | ||
277 | u32 value; | ||
278 | } drm_radeon_getparam32_t; | ||
279 | |||
280 | static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, | ||
281 | unsigned long arg) | ||
282 | { | ||
283 | drm_radeon_getparam32_t req32; | ||
284 | drm_radeon_getparam_t __user *request; | ||
285 | |||
286 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
287 | return -EFAULT; | ||
288 | |||
289 | request = compat_alloc_user_space(sizeof(*request)); | ||
290 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
291 | || __put_user(req32.param, &request->param) | ||
292 | || __put_user((void __user *)(unsigned long)req32.value, | ||
293 | &request->value)) | ||
294 | return -EFAULT; | ||
295 | |||
296 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
297 | DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); | ||
298 | } | ||
299 | |||
300 | typedef struct drm_radeon_mem_alloc32 { | ||
301 | int region; | ||
302 | int alignment; | ||
303 | int size; | ||
304 | u32 region_offset; /* offset from start of fb or GART */ | ||
305 | } drm_radeon_mem_alloc32_t; | ||
306 | |||
307 | static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, | ||
308 | unsigned long arg) | ||
309 | { | ||
310 | drm_radeon_mem_alloc32_t req32; | ||
311 | drm_radeon_mem_alloc_t __user *request; | ||
312 | |||
313 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
314 | return -EFAULT; | ||
315 | |||
316 | request = compat_alloc_user_space(sizeof(*request)); | ||
317 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
318 | || __put_user(req32.region, &request->region) | ||
319 | || __put_user(req32.alignment, &request->alignment) | ||
320 | || __put_user(req32.size, &request->size) | ||
321 | || __put_user((int __user *)(unsigned long)req32.region_offset, | ||
322 | &request->region_offset)) | ||
323 | return -EFAULT; | ||
324 | |||
325 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
326 | DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); | ||
327 | } | ||
328 | |||
329 | typedef struct drm_radeon_irq_emit32 { | ||
330 | u32 irq_seq; | ||
331 | } drm_radeon_irq_emit32_t; | ||
332 | |||
333 | static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, | ||
334 | unsigned long arg) | ||
335 | { | ||
336 | drm_radeon_irq_emit32_t req32; | ||
337 | drm_radeon_irq_emit_t __user *request; | ||
338 | |||
339 | if (copy_from_user(&req32, (void __user *)arg, sizeof(req32))) | ||
340 | return -EFAULT; | ||
341 | |||
342 | request = compat_alloc_user_space(sizeof(*request)); | ||
343 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
344 | || __put_user((int __user *)(unsigned long)req32.irq_seq, | ||
345 | &request->irq_seq)) | ||
346 | return -EFAULT; | ||
347 | |||
348 | return drm_ioctl(file->f_path.dentry->d_inode, file, | ||
349 | DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); | ||
350 | } | ||
351 | |||
352 | /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ | ||
353 | #if defined (CONFIG_X86_64) || defined(CONFIG_IA64) | ||
354 | typedef struct drm_radeon_setparam32 { | ||
355 | int param; | ||
356 | u64 value; | ||
357 | } __attribute__((packed)) drm_radeon_setparam32_t; | ||
358 | |||
359 | static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, | ||
360 | unsigned long arg) | ||
361 | { | ||
362 | drm_radeon_setparam32_t req32; | ||
363 | drm_radeon_setparam_t __user *request; | ||
364 | |||
365 | if (copy_from_user(&req32, (void __user *) arg, sizeof(req32))) | ||
366 | return -EFAULT; | ||
367 | |||
368 | request = compat_alloc_user_space(sizeof(*request)); | ||
369 | if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) | ||
370 | || __put_user(req32.param, &request->param) | ||
371 | || __put_user((void __user *)(unsigned long)req32.value, | ||
372 | &request->value)) | ||
373 | return -EFAULT; | ||
374 | |||
375 | return drm_ioctl(file->f_dentry->d_inode, file, | ||
376 | DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); | ||
377 | } | ||
378 | #else | ||
379 | #define compat_radeon_cp_setparam NULL | ||
380 | #endif /* X86_64 || IA64 */ | ||
381 | |||
382 | drm_ioctl_compat_t *radeon_compat_ioctls[] = { | ||
383 | [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, | ||
384 | [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, | ||
385 | [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, | ||
386 | [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture, | ||
387 | [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2, | ||
388 | [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf, | ||
389 | [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam, | ||
390 | [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam, | ||
391 | [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc, | ||
392 | [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit, | ||
393 | }; | ||
394 | |||
395 | /** | ||
396 | * Called whenever a 32-bit process running under a 64-bit kernel | ||
397 | * performs an ioctl on /dev/dri/card<n>. | ||
398 | * | ||
399 | * \param filp file pointer. | ||
400 | * \param cmd command. | ||
401 | * \param arg user argument. | ||
402 | * \return zero on success or negative number on failure. | ||
403 | */ | ||
404 | long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
405 | { | ||
406 | unsigned int nr = DRM_IOCTL_NR(cmd); | ||
407 | drm_ioctl_compat_t *fn = NULL; | ||
408 | int ret; | ||
409 | |||
410 | if (nr < DRM_COMMAND_BASE) | ||
411 | return drm_compat_ioctl(filp, cmd, arg); | ||
412 | |||
413 | if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) | ||
414 | fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; | ||
415 | |||
416 | lock_kernel(); /* XXX for now */ | ||
417 | if (fn != NULL) | ||
418 | ret = (*fn) (filp, cmd, arg); | ||
419 | else | ||
420 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); | ||
421 | unlock_kernel(); | ||
422 | |||
423 | return ret; | ||
424 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c new file mode 100644 index 000000000000..ee40d197deb7 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_irq.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */ | ||
2 | /* | ||
3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | ||
4 | * | ||
5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | ||
6 | * initial release of the Radeon 8500 driver under the XFree86 license. | ||
7 | * This notice must be preserved. | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
10 | * copy of this software and associated documentation files (the "Software"), | ||
11 | * to deal in the Software without restriction, including without limitation | ||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
13 | * and/or sell copies of the Software, and to permit persons to whom the | ||
14 | * Software is furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice (including the next | ||
17 | * paragraph) shall be included in all copies or substantial portions of the | ||
18 | * Software. | ||
19 | * | ||
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
23 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
24 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
25 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
26 | * DEALINGS IN THE SOFTWARE. | ||
27 | * | ||
28 | * Authors: | ||
29 | * Keith Whitwell <keith@tungstengraphics.com> | ||
30 | * Michel Dänzer <michel@daenzer.net> | ||
31 | */ | ||
32 | |||
33 | #include "drmP.h" | ||
34 | #include "drm.h" | ||
35 | #include "radeon_drm.h" | ||
36 | #include "radeon_drv.h" | ||
37 | |||
38 | static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, | ||
39 | u32 mask) | ||
40 | { | ||
41 | u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; | ||
42 | if (irqs) | ||
43 | RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); | ||
44 | return irqs; | ||
45 | } | ||
46 | |||
47 | /* Interrupts - Used for device synchronization and flushing in the | ||
48 | * following circumstances: | ||
49 | * | ||
50 | * - Exclusive FB access with hw idle: | ||
51 | * - Wait for GUI Idle (?) interrupt, then do normal flush. | ||
52 | * | ||
53 | * - Frame throttling, NV_fence: | ||
54 | * - Drop marker irq's into command stream ahead of time. | ||
55 | * - Wait on irq's with lock *not held* | ||
56 | * - Check each for termination condition | ||
57 | * | ||
58 | * - Internally in cp_getbuffer, etc: | ||
59 | * - as above, but wait with lock held??? | ||
60 | * | ||
61 | * NOTE: These functions are misleadingly named -- the irq's aren't | ||
62 | * tied to dma at all, this is just a hangover from dri prehistory. | ||
63 | */ | ||
64 | |||
65 | irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) | ||
66 | { | ||
67 | struct drm_device *dev = (struct drm_device *) arg; | ||
68 | drm_radeon_private_t *dev_priv = | ||
69 | (drm_radeon_private_t *) dev->dev_private; | ||
70 | u32 stat; | ||
71 | |||
72 | /* Only consider the bits we're interested in - others could be used | ||
73 | * outside the DRM | ||
74 | */ | ||
75 | stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | | ||
76 | RADEON_CRTC_VBLANK_STAT | | ||
77 | RADEON_CRTC2_VBLANK_STAT)); | ||
78 | if (!stat) | ||
79 | return IRQ_NONE; | ||
80 | |||
81 | stat &= dev_priv->irq_enable_reg; | ||
82 | |||
83 | /* SW interrupt */ | ||
84 | if (stat & RADEON_SW_INT_TEST) { | ||
85 | DRM_WAKEUP(&dev_priv->swi_queue); | ||
86 | } | ||
87 | |||
88 | /* VBLANK interrupt */ | ||
89 | if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { | ||
90 | int vblank_crtc = dev_priv->vblank_crtc; | ||
91 | |||
92 | if ((vblank_crtc & | ||
93 | (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == | ||
94 | (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { | ||
95 | if (stat & RADEON_CRTC_VBLANK_STAT) | ||
96 | atomic_inc(&dev->vbl_received); | ||
97 | if (stat & RADEON_CRTC2_VBLANK_STAT) | ||
98 | atomic_inc(&dev->vbl_received2); | ||
99 | } else if (((stat & RADEON_CRTC_VBLANK_STAT) && | ||
100 | (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || | ||
101 | ((stat & RADEON_CRTC2_VBLANK_STAT) && | ||
102 | (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) | ||
103 | atomic_inc(&dev->vbl_received); | ||
104 | |||
105 | DRM_WAKEUP(&dev->vbl_queue); | ||
106 | drm_vbl_send_signals(dev); | ||
107 | } | ||
108 | |||
109 | return IRQ_HANDLED; | ||
110 | } | ||
111 | |||
112 | static int radeon_emit_irq(struct drm_device * dev) | ||
113 | { | ||
114 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
115 | unsigned int ret; | ||
116 | RING_LOCALS; | ||
117 | |||
118 | atomic_inc(&dev_priv->swi_emitted); | ||
119 | ret = atomic_read(&dev_priv->swi_emitted); | ||
120 | |||
121 | BEGIN_RING(4); | ||
122 | OUT_RING_REG(RADEON_LAST_SWI_REG, ret); | ||
123 | OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); | ||
124 | ADVANCE_RING(); | ||
125 | COMMIT_RING(); | ||
126 | |||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static int radeon_wait_irq(struct drm_device * dev, int swi_nr) | ||
131 | { | ||
132 | drm_radeon_private_t *dev_priv = | ||
133 | (drm_radeon_private_t *) dev->dev_private; | ||
134 | int ret = 0; | ||
135 | |||
136 | if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) | ||
137 | return 0; | ||
138 | |||
139 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
140 | |||
141 | DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, | ||
142 | RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static int radeon_driver_vblank_do_wait(struct drm_device * dev, | ||
148 | unsigned int *sequence, int crtc) | ||
149 | { | ||
150 | drm_radeon_private_t *dev_priv = | ||
151 | (drm_radeon_private_t *) dev->dev_private; | ||
152 | unsigned int cur_vblank; | ||
153 | int ret = 0; | ||
154 | int ack = 0; | ||
155 | atomic_t *counter; | ||
156 | if (!dev_priv) { | ||
157 | DRM_ERROR("called with no initialization\n"); | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | if (crtc == DRM_RADEON_VBLANK_CRTC1) { | ||
162 | counter = &dev->vbl_received; | ||
163 | ack |= RADEON_CRTC_VBLANK_STAT; | ||
164 | } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { | ||
165 | counter = &dev->vbl_received2; | ||
166 | ack |= RADEON_CRTC2_VBLANK_STAT; | ||
167 | } else | ||
168 | return -EINVAL; | ||
169 | |||
170 | radeon_acknowledge_irqs(dev_priv, ack); | ||
171 | |||
172 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
173 | |||
174 | /* Assume that the user has missed the current sequence number | ||
175 | * by about a day rather than she wants to wait for years | ||
176 | * using vertical blanks... | ||
177 | */ | ||
178 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | ||
179 | (((cur_vblank = atomic_read(counter)) | ||
180 | - *sequence) <= (1 << 23))); | ||
181 | |||
182 | *sequence = cur_vblank; | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) | ||
188 | { | ||
189 | return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1); | ||
190 | } | ||
191 | |||
192 | int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) | ||
193 | { | ||
194 | return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); | ||
195 | } | ||
196 | |||
197 | /* Needs the lock as it touches the ring. | ||
198 | */ | ||
199 | int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
200 | { | ||
201 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
202 | drm_radeon_irq_emit_t *emit = data; | ||
203 | int result; | ||
204 | |||
205 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
206 | |||
207 | if (!dev_priv) { | ||
208 | DRM_ERROR("called with no initialization\n"); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | |||
212 | result = radeon_emit_irq(dev); | ||
213 | |||
214 | if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { | ||
215 | DRM_ERROR("copy_to_user\n"); | ||
216 | return -EFAULT; | ||
217 | } | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* Doesn't need the hardware lock. | ||
223 | */ | ||
224 | int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
225 | { | ||
226 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
227 | drm_radeon_irq_wait_t *irqwait = data; | ||
228 | |||
229 | if (!dev_priv) { | ||
230 | DRM_ERROR("called with no initialization\n"); | ||
231 | return -EINVAL; | ||
232 | } | ||
233 | |||
234 | return radeon_wait_irq(dev, irqwait->irq_seq); | ||
235 | } | ||
236 | |||
237 | void radeon_enable_interrupt(struct drm_device *dev) | ||
238 | { | ||
239 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
240 | |||
241 | dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; | ||
242 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) | ||
243 | dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; | ||
244 | |||
245 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) | ||
246 | dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; | ||
247 | |||
248 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); | ||
249 | dev_priv->irq_enabled = 1; | ||
250 | } | ||
251 | |||
252 | /* drm_dma.h hooks | ||
253 | */ | ||
254 | void radeon_driver_irq_preinstall(struct drm_device * dev) | ||
255 | { | ||
256 | drm_radeon_private_t *dev_priv = | ||
257 | (drm_radeon_private_t *) dev->dev_private; | ||
258 | |||
259 | /* Disable *all* interrupts */ | ||
260 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); | ||
261 | |||
262 | /* Clear bits if they're already high */ | ||
263 | radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | | ||
264 | RADEON_CRTC_VBLANK_STAT | | ||
265 | RADEON_CRTC2_VBLANK_STAT)); | ||
266 | } | ||
267 | |||
268 | void radeon_driver_irq_postinstall(struct drm_device * dev) | ||
269 | { | ||
270 | drm_radeon_private_t *dev_priv = | ||
271 | (drm_radeon_private_t *) dev->dev_private; | ||
272 | |||
273 | atomic_set(&dev_priv->swi_emitted, 0); | ||
274 | DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); | ||
275 | |||
276 | radeon_enable_interrupt(dev); | ||
277 | } | ||
278 | |||
279 | void radeon_driver_irq_uninstall(struct drm_device * dev) | ||
280 | { | ||
281 | drm_radeon_private_t *dev_priv = | ||
282 | (drm_radeon_private_t *) dev->dev_private; | ||
283 | if (!dev_priv) | ||
284 | return; | ||
285 | |||
286 | dev_priv->irq_enabled = 0; | ||
287 | |||
288 | /* Disable *all* interrupts */ | ||
289 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); | ||
290 | } | ||
291 | |||
292 | |||
293 | int radeon_vblank_crtc_get(struct drm_device *dev) | ||
294 | { | ||
295 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
296 | u32 flag; | ||
297 | u32 value; | ||
298 | |||
299 | flag = RADEON_READ(RADEON_GEN_INT_CNTL); | ||
300 | value = 0; | ||
301 | |||
302 | if (flag & RADEON_CRTC_VBLANK_MASK) | ||
303 | value |= DRM_RADEON_VBLANK_CRTC1; | ||
304 | |||
305 | if (flag & RADEON_CRTC2_VBLANK_MASK) | ||
306 | value |= DRM_RADEON_VBLANK_CRTC2; | ||
307 | return value; | ||
308 | } | ||
309 | |||
310 | int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) | ||
311 | { | ||
312 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
313 | if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { | ||
314 | DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | dev_priv->vblank_crtc = (unsigned int)value; | ||
318 | radeon_enable_interrupt(dev); | ||
319 | return 0; | ||
320 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c new file mode 100644 index 000000000000..4af5286a36fb --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_mem.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */ | ||
2 | /* | ||
3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | ||
4 | * | ||
5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | ||
6 | * initial release of the Radeon 8500 driver under the XFree86 license. | ||
7 | * This notice must be preserved. | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
10 | * copy of this software and associated documentation files (the "Software"), | ||
11 | * to deal in the Software without restriction, including without limitation | ||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
13 | * and/or sell copies of the Software, and to permit persons to whom the | ||
14 | * Software is furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice (including the next | ||
17 | * paragraph) shall be included in all copies or substantial portions of the | ||
18 | * Software. | ||
19 | * | ||
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
23 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
24 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
25 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
26 | * DEALINGS IN THE SOFTWARE. | ||
27 | * | ||
28 | * Authors: | ||
29 | * Keith Whitwell <keith@tungstengraphics.com> | ||
30 | */ | ||
31 | |||
32 | #include "drmP.h" | ||
33 | #include "drm.h" | ||
34 | #include "radeon_drm.h" | ||
35 | #include "radeon_drv.h" | ||
36 | |||
37 | /* Very simple allocator for GART memory, working on a static range | ||
38 | * already mapped into each client's address space. | ||
39 | */ | ||
40 | |||
41 | static struct mem_block *split_block(struct mem_block *p, int start, int size, | ||
42 | struct drm_file *file_priv) | ||
43 | { | ||
44 | /* Maybe cut off the start of an existing block */ | ||
45 | if (start > p->start) { | ||
46 | struct mem_block *newblock = | ||
47 | drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); | ||
48 | if (!newblock) | ||
49 | goto out; | ||
50 | newblock->start = start; | ||
51 | newblock->size = p->size - (start - p->start); | ||
52 | newblock->file_priv = NULL; | ||
53 | newblock->next = p->next; | ||
54 | newblock->prev = p; | ||
55 | p->next->prev = newblock; | ||
56 | p->next = newblock; | ||
57 | p->size -= newblock->size; | ||
58 | p = newblock; | ||
59 | } | ||
60 | |||
61 | /* Maybe cut off the end of an existing block */ | ||
62 | if (size < p->size) { | ||
63 | struct mem_block *newblock = | ||
64 | drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); | ||
65 | if (!newblock) | ||
66 | goto out; | ||
67 | newblock->start = start + size; | ||
68 | newblock->size = p->size - size; | ||
69 | newblock->file_priv = NULL; | ||
70 | newblock->next = p->next; | ||
71 | newblock->prev = p; | ||
72 | p->next->prev = newblock; | ||
73 | p->next = newblock; | ||
74 | p->size = size; | ||
75 | } | ||
76 | |||
77 | out: | ||
78 | /* Our block is in the middle */ | ||
79 | p->file_priv = file_priv; | ||
80 | return p; | ||
81 | } | ||
82 | |||
83 | static struct mem_block *alloc_block(struct mem_block *heap, int size, | ||
84 | int align2, struct drm_file *file_priv) | ||
85 | { | ||
86 | struct mem_block *p; | ||
87 | int mask = (1 << align2) - 1; | ||
88 | |||
89 | list_for_each(p, heap) { | ||
90 | int start = (p->start + mask) & ~mask; | ||
91 | if (p->file_priv == NULL && start + size <= p->start + p->size) | ||
92 | return split_block(p, start, size, file_priv); | ||
93 | } | ||
94 | |||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | static struct mem_block *find_block(struct mem_block *heap, int start) | ||
99 | { | ||
100 | struct mem_block *p; | ||
101 | |||
102 | list_for_each(p, heap) | ||
103 | if (p->start == start) | ||
104 | return p; | ||
105 | |||
106 | return NULL; | ||
107 | } | ||
108 | |||
109 | static void free_block(struct mem_block *p) | ||
110 | { | ||
111 | p->file_priv = NULL; | ||
112 | |||
113 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
114 | * 'heap' to stop it being subsumed. | ||
115 | */ | ||
116 | if (p->next->file_priv == NULL) { | ||
117 | struct mem_block *q = p->next; | ||
118 | p->size += q->size; | ||
119 | p->next = q->next; | ||
120 | p->next->prev = p; | ||
121 | drm_free(q, sizeof(*q), DRM_MEM_BUFS); | ||
122 | } | ||
123 | |||
124 | if (p->prev->file_priv == NULL) { | ||
125 | struct mem_block *q = p->prev; | ||
126 | q->size += p->size; | ||
127 | q->next = p->next; | ||
128 | q->next->prev = q; | ||
129 | drm_free(p, sizeof(*q), DRM_MEM_BUFS); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | /* Initialize. How to check for an uninitialized heap? | ||
134 | */ | ||
135 | static int init_heap(struct mem_block **heap, int start, int size) | ||
136 | { | ||
137 | struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS); | ||
138 | |||
139 | if (!blocks) | ||
140 | return -ENOMEM; | ||
141 | |||
142 | *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); | ||
143 | if (!*heap) { | ||
144 | drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); | ||
145 | return -ENOMEM; | ||
146 | } | ||
147 | |||
148 | blocks->start = start; | ||
149 | blocks->size = size; | ||
150 | blocks->file_priv = NULL; | ||
151 | blocks->next = blocks->prev = *heap; | ||
152 | |||
153 | memset(*heap, 0, sizeof(**heap)); | ||
154 | (*heap)->file_priv = (struct drm_file *) - 1; | ||
155 | (*heap)->next = (*heap)->prev = blocks; | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* Free all blocks associated with the releasing file. | ||
160 | */ | ||
161 | void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) | ||
162 | { | ||
163 | struct mem_block *p; | ||
164 | |||
165 | if (!heap || !heap->next) | ||
166 | return; | ||
167 | |||
168 | list_for_each(p, heap) { | ||
169 | if (p->file_priv == file_priv) | ||
170 | p->file_priv = NULL; | ||
171 | } | ||
172 | |||
173 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
174 | * 'heap' to stop it being subsumed. | ||
175 | */ | ||
176 | list_for_each(p, heap) { | ||
177 | while (p->file_priv == NULL && p->next->file_priv == NULL) { | ||
178 | struct mem_block *q = p->next; | ||
179 | p->size += q->size; | ||
180 | p->next = q->next; | ||
181 | p->next->prev = p; | ||
182 | drm_free(q, sizeof(*q), DRM_MEM_DRIVER); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* Shutdown. | ||
188 | */ | ||
189 | void radeon_mem_takedown(struct mem_block **heap) | ||
190 | { | ||
191 | struct mem_block *p; | ||
192 | |||
193 | if (!*heap) | ||
194 | return; | ||
195 | |||
196 | for (p = (*heap)->next; p != *heap;) { | ||
197 | struct mem_block *q = p; | ||
198 | p = p->next; | ||
199 | drm_free(q, sizeof(*q), DRM_MEM_DRIVER); | ||
200 | } | ||
201 | |||
202 | drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER); | ||
203 | *heap = NULL; | ||
204 | } | ||
205 | |||
206 | /* IOCTL HANDLERS */ | ||
207 | |||
208 | static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) | ||
209 | { | ||
210 | switch (region) { | ||
211 | case RADEON_MEM_REGION_GART: | ||
212 | return &dev_priv->gart_heap; | ||
213 | case RADEON_MEM_REGION_FB: | ||
214 | return &dev_priv->fb_heap; | ||
215 | default: | ||
216 | return NULL; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
221 | { | ||
222 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
223 | drm_radeon_mem_alloc_t *alloc = data; | ||
224 | struct mem_block *block, **heap; | ||
225 | |||
226 | if (!dev_priv) { | ||
227 | DRM_ERROR("called with no initialization\n"); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | |||
231 | heap = get_heap(dev_priv, alloc->region); | ||
232 | if (!heap || !*heap) | ||
233 | return -EFAULT; | ||
234 | |||
235 | /* Make things easier on ourselves: all allocations at least | ||
236 | * 4k aligned. | ||
237 | */ | ||
238 | if (alloc->alignment < 12) | ||
239 | alloc->alignment = 12; | ||
240 | |||
241 | block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); | ||
242 | |||
243 | if (!block) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, | ||
247 | sizeof(int))) { | ||
248 | DRM_ERROR("copy_to_user\n"); | ||
249 | return -EFAULT; | ||
250 | } | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
256 | { | ||
257 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
258 | drm_radeon_mem_free_t *memfree = data; | ||
259 | struct mem_block *block, **heap; | ||
260 | |||
261 | if (!dev_priv) { | ||
262 | DRM_ERROR("called with no initialization\n"); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
266 | heap = get_heap(dev_priv, memfree->region); | ||
267 | if (!heap || !*heap) | ||
268 | return -EFAULT; | ||
269 | |||
270 | block = find_block(*heap, memfree->region_offset); | ||
271 | if (!block) | ||
272 | return -EFAULT; | ||
273 | |||
274 | if (block->file_priv != file_priv) | ||
275 | return -EPERM; | ||
276 | |||
277 | free_block(block); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
282 | { | ||
283 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
284 | drm_radeon_mem_init_heap_t *initheap = data; | ||
285 | struct mem_block **heap; | ||
286 | |||
287 | if (!dev_priv) { | ||
288 | DRM_ERROR("called with no initialization\n"); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | heap = get_heap(dev_priv, initheap->region); | ||
293 | if (!heap) | ||
294 | return -EFAULT; | ||
295 | |||
296 | if (*heap) { | ||
297 | DRM_ERROR("heap already initialized?"); | ||
298 | return -EFAULT; | ||
299 | } | ||
300 | |||
301 | return init_heap(heap, initheap->start, initheap->size); | ||
302 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_microcode.h b/drivers/gpu/drm/radeon/radeon_microcode.h new file mode 100644 index 000000000000..a348c9e7db1c --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_microcode.h | |||
@@ -0,0 +1,1844 @@ | |||
1 | /* | ||
2 | * Copyright 2007 Advanced Micro Devices, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * 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 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | ||
20 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
21 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
22 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef RADEON_MICROCODE_H | ||
27 | #define RADEON_MICROCODE_H | ||
28 | |||
29 | /* production radeon ucode r1xx-r6xx */ | ||
30 | static const u32 R100_cp_microcode[][2] = { | ||
31 | { 0x21007000, 0000000000 }, | ||
32 | { 0x20007000, 0000000000 }, | ||
33 | { 0x000000b4, 0x00000004 }, | ||
34 | { 0x000000b8, 0x00000004 }, | ||
35 | { 0x6f5b4d4c, 0000000000 }, | ||
36 | { 0x4c4c427f, 0000000000 }, | ||
37 | { 0x5b568a92, 0000000000 }, | ||
38 | { 0x4ca09c6d, 0000000000 }, | ||
39 | { 0xad4c4c4c, 0000000000 }, | ||
40 | { 0x4ce1af3d, 0000000000 }, | ||
41 | { 0xd8afafaf, 0000000000 }, | ||
42 | { 0xd64c4cdc, 0000000000 }, | ||
43 | { 0x4cd10d10, 0000000000 }, | ||
44 | { 0x000f0000, 0x00000016 }, | ||
45 | { 0x362f242d, 0000000000 }, | ||
46 | { 0x00000012, 0x00000004 }, | ||
47 | { 0x000f0000, 0x00000016 }, | ||
48 | { 0x362f282d, 0000000000 }, | ||
49 | { 0x000380e7, 0x00000002 }, | ||
50 | { 0x04002c97, 0x00000002 }, | ||
51 | { 0x000f0001, 0x00000016 }, | ||
52 | { 0x333a3730, 0000000000 }, | ||
53 | { 0x000077ef, 0x00000002 }, | ||
54 | { 0x00061000, 0x00000002 }, | ||
55 | { 0x00000021, 0x0000001a }, | ||
56 | { 0x00004000, 0x0000001e }, | ||
57 | { 0x00061000, 0x00000002 }, | ||
58 | { 0x00000021, 0x0000001a }, | ||
59 | { 0x00004000, 0x0000001e }, | ||
60 | { 0x00061000, 0x00000002 }, | ||
61 | { 0x00000021, 0x0000001a }, | ||
62 | { 0x00004000, 0x0000001e }, | ||
63 | { 0x00000017, 0x00000004 }, | ||
64 | { 0x0003802b, 0x00000002 }, | ||
65 | { 0x040067e0, 0x00000002 }, | ||
66 | { 0x00000017, 0x00000004 }, | ||
67 | { 0x000077e0, 0x00000002 }, | ||
68 | { 0x00065000, 0x00000002 }, | ||
69 | { 0x000037e1, 0x00000002 }, | ||
70 | { 0x040067e1, 0x00000006 }, | ||
71 | { 0x000077e0, 0x00000002 }, | ||
72 | { 0x000077e1, 0x00000002 }, | ||
73 | { 0x000077e1, 0x00000006 }, | ||
74 | { 0xffffffff, 0000000000 }, | ||
75 | { 0x10000000, 0000000000 }, | ||
76 | { 0x0003802b, 0x00000002 }, | ||
77 | { 0x040067e0, 0x00000006 }, | ||
78 | { 0x00007675, 0x00000002 }, | ||
79 | { 0x00007676, 0x00000002 }, | ||
80 | { 0x00007677, 0x00000002 }, | ||
81 | { 0x00007678, 0x00000006 }, | ||
82 | { 0x0003802c, 0x00000002 }, | ||
83 | { 0x04002676, 0x00000002 }, | ||
84 | { 0x00007677, 0x00000002 }, | ||
85 | { 0x00007678, 0x00000006 }, | ||
86 | { 0x0000002f, 0x00000018 }, | ||
87 | { 0x0000002f, 0x00000018 }, | ||
88 | { 0000000000, 0x00000006 }, | ||
89 | { 0x00000030, 0x00000018 }, | ||
90 | { 0x00000030, 0x00000018 }, | ||
91 | { 0000000000, 0x00000006 }, | ||
92 | { 0x01605000, 0x00000002 }, | ||
93 | { 0x00065000, 0x00000002 }, | ||
94 | { 0x00098000, 0x00000002 }, | ||
95 | { 0x00061000, 0x00000002 }, | ||
96 | { 0x64c0603e, 0x00000004 }, | ||
97 | { 0x000380e6, 0x00000002 }, | ||
98 | { 0x040025c5, 0x00000002 }, | ||
99 | { 0x00080000, 0x00000016 }, | ||
100 | { 0000000000, 0000000000 }, | ||
101 | { 0x0400251d, 0x00000002 }, | ||
102 | { 0x00007580, 0x00000002 }, | ||
103 | { 0x00067581, 0x00000002 }, | ||
104 | { 0x04002580, 0x00000002 }, | ||
105 | { 0x00067581, 0x00000002 }, | ||
106 | { 0x00000049, 0x00000004 }, | ||
107 | { 0x00005000, 0000000000 }, | ||
108 | { 0x000380e6, 0x00000002 }, | ||
109 | { 0x040025c5, 0x00000002 }, | ||
110 | { 0x00061000, 0x00000002 }, | ||
111 | { 0x0000750e, 0x00000002 }, | ||
112 | { 0x00019000, 0x00000002 }, | ||
113 | { 0x00011055, 0x00000014 }, | ||
114 | { 0x00000055, 0x00000012 }, | ||
115 | { 0x0400250f, 0x00000002 }, | ||
116 | { 0x0000504f, 0x00000004 }, | ||
117 | { 0x000380e6, 0x00000002 }, | ||
118 | { 0x040025c5, 0x00000002 }, | ||
119 | { 0x00007565, 0x00000002 }, | ||
120 | { 0x00007566, 0x00000002 }, | ||
121 | { 0x00000058, 0x00000004 }, | ||
122 | { 0x000380e6, 0x00000002 }, | ||
123 | { 0x040025c5, 0x00000002 }, | ||
124 | { 0x01e655b4, 0x00000002 }, | ||
125 | { 0x4401b0e4, 0x00000002 }, | ||
126 | { 0x01c110e4, 0x00000002 }, | ||
127 | { 0x26667066, 0x00000018 }, | ||
128 | { 0x040c2565, 0x00000002 }, | ||
129 | { 0x00000066, 0x00000018 }, | ||
130 | { 0x04002564, 0x00000002 }, | ||
131 | { 0x00007566, 0x00000002 }, | ||
132 | { 0x0000005d, 0x00000004 }, | ||
133 | { 0x00401069, 0x00000008 }, | ||
134 | { 0x00101000, 0x00000002 }, | ||
135 | { 0x000d80ff, 0x00000002 }, | ||
136 | { 0x0080006c, 0x00000008 }, | ||
137 | { 0x000f9000, 0x00000002 }, | ||
138 | { 0x000e00ff, 0x00000002 }, | ||
139 | { 0000000000, 0x00000006 }, | ||
140 | { 0x0000008f, 0x00000018 }, | ||
141 | { 0x0000005b, 0x00000004 }, | ||
142 | { 0x000380e6, 0x00000002 }, | ||
143 | { 0x040025c5, 0x00000002 }, | ||
144 | { 0x00007576, 0x00000002 }, | ||
145 | { 0x00065000, 0x00000002 }, | ||
146 | { 0x00009000, 0x00000002 }, | ||
147 | { 0x00041000, 0x00000002 }, | ||
148 | { 0x0c00350e, 0x00000002 }, | ||
149 | { 0x00049000, 0x00000002 }, | ||
150 | { 0x00051000, 0x00000002 }, | ||
151 | { 0x01e785f8, 0x00000002 }, | ||
152 | { 0x00200000, 0x00000002 }, | ||
153 | { 0x0060007e, 0x0000000c }, | ||
154 | { 0x00007563, 0x00000002 }, | ||
155 | { 0x006075f0, 0x00000021 }, | ||
156 | { 0x20007073, 0x00000004 }, | ||
157 | { 0x00005073, 0x00000004 }, | ||
158 | { 0x000380e6, 0x00000002 }, | ||
159 | { 0x040025c5, 0x00000002 }, | ||
160 | { 0x00007576, 0x00000002 }, | ||
161 | { 0x00007577, 0x00000002 }, | ||
162 | { 0x0000750e, 0x00000002 }, | ||
163 | { 0x0000750f, 0x00000002 }, | ||
164 | { 0x00a05000, 0x00000002 }, | ||
165 | { 0x00600083, 0x0000000c }, | ||
166 | { 0x006075f0, 0x00000021 }, | ||
167 | { 0x000075f8, 0x00000002 }, | ||
168 | { 0x00000083, 0x00000004 }, | ||
169 | { 0x000a750e, 0x00000002 }, | ||
170 | { 0x000380e6, 0x00000002 }, | ||
171 | { 0x040025c5, 0x00000002 }, | ||
172 | { 0x0020750f, 0x00000002 }, | ||
173 | { 0x00600086, 0x00000004 }, | ||
174 | { 0x00007570, 0x00000002 }, | ||
175 | { 0x00007571, 0x00000002 }, | ||
176 | { 0x00007572, 0x00000006 }, | ||
177 | { 0x000380e6, 0x00000002 }, | ||
178 | { 0x040025c5, 0x00000002 }, | ||
179 | { 0x00005000, 0x00000002 }, | ||
180 | { 0x00a05000, 0x00000002 }, | ||
181 | { 0x00007568, 0x00000002 }, | ||
182 | { 0x00061000, 0x00000002 }, | ||
183 | { 0x00000095, 0x0000000c }, | ||
184 | { 0x00058000, 0x00000002 }, | ||
185 | { 0x0c607562, 0x00000002 }, | ||
186 | { 0x00000097, 0x00000004 }, | ||
187 | { 0x000380e6, 0x00000002 }, | ||
188 | { 0x040025c5, 0x00000002 }, | ||
189 | { 0x00600096, 0x00000004 }, | ||
190 | { 0x400070e5, 0000000000 }, | ||
191 | { 0x000380e6, 0x00000002 }, | ||
192 | { 0x040025c5, 0x00000002 }, | ||
193 | { 0x000380e5, 0x00000002 }, | ||
194 | { 0x000000a8, 0x0000001c }, | ||
195 | { 0x000650aa, 0x00000018 }, | ||
196 | { 0x040025bb, 0x00000002 }, | ||
197 | { 0x000610ab, 0x00000018 }, | ||
198 | { 0x040075bc, 0000000000 }, | ||
199 | { 0x000075bb, 0x00000002 }, | ||
200 | { 0x000075bc, 0000000000 }, | ||
201 | { 0x00090000, 0x00000006 }, | ||
202 | { 0x00090000, 0x00000002 }, | ||
203 | { 0x000d8002, 0x00000006 }, | ||
204 | { 0x00007832, 0x00000002 }, | ||
205 | { 0x00005000, 0x00000002 }, | ||
206 | { 0x000380e7, 0x00000002 }, | ||
207 | { 0x04002c97, 0x00000002 }, | ||
208 | { 0x00007820, 0x00000002 }, | ||
209 | { 0x00007821, 0x00000002 }, | ||
210 | { 0x00007800, 0000000000 }, | ||
211 | { 0x01200000, 0x00000002 }, | ||
212 | { 0x20077000, 0x00000002 }, | ||
213 | { 0x01200000, 0x00000002 }, | ||
214 | { 0x20007000, 0x00000002 }, | ||
215 | { 0x00061000, 0x00000002 }, | ||
216 | { 0x0120751b, 0x00000002 }, | ||
217 | { 0x8040750a, 0x00000002 }, | ||
218 | { 0x8040750b, 0x00000002 }, | ||
219 | { 0x00110000, 0x00000002 }, | ||
220 | { 0x000380e5, 0x00000002 }, | ||
221 | { 0x000000c6, 0x0000001c }, | ||
222 | { 0x000610ab, 0x00000018 }, | ||
223 | { 0x844075bd, 0x00000002 }, | ||
224 | { 0x000610aa, 0x00000018 }, | ||
225 | { 0x840075bb, 0x00000002 }, | ||
226 | { 0x000610ab, 0x00000018 }, | ||
227 | { 0x844075bc, 0x00000002 }, | ||
228 | { 0x000000c9, 0x00000004 }, | ||
229 | { 0x804075bd, 0x00000002 }, | ||
230 | { 0x800075bb, 0x00000002 }, | ||
231 | { 0x804075bc, 0x00000002 }, | ||
232 | { 0x00108000, 0x00000002 }, | ||
233 | { 0x01400000, 0x00000002 }, | ||
234 | { 0x006000cd, 0x0000000c }, | ||
235 | { 0x20c07000, 0x00000020 }, | ||
236 | { 0x000000cf, 0x00000012 }, | ||
237 | { 0x00800000, 0x00000006 }, | ||
238 | { 0x0080751d, 0x00000006 }, | ||
239 | { 0000000000, 0000000000 }, | ||
240 | { 0x0000775c, 0x00000002 }, | ||
241 | { 0x00a05000, 0x00000002 }, | ||
242 | { 0x00661000, 0x00000002 }, | ||
243 | { 0x0460275d, 0x00000020 }, | ||
244 | { 0x00004000, 0000000000 }, | ||
245 | { 0x01e00830, 0x00000002 }, | ||
246 | { 0x21007000, 0000000000 }, | ||
247 | { 0x6464614d, 0000000000 }, | ||
248 | { 0x69687420, 0000000000 }, | ||
249 | { 0x00000073, 0000000000 }, | ||
250 | { 0000000000, 0000000000 }, | ||
251 | { 0x00005000, 0x00000002 }, | ||
252 | { 0x000380d0, 0x00000002 }, | ||
253 | { 0x040025e0, 0x00000002 }, | ||
254 | { 0x000075e1, 0000000000 }, | ||
255 | { 0x00000001, 0000000000 }, | ||
256 | { 0x000380e0, 0x00000002 }, | ||
257 | { 0x04002394, 0x00000002 }, | ||
258 | { 0x00005000, 0000000000 }, | ||
259 | { 0000000000, 0000000000 }, | ||
260 | { 0000000000, 0000000000 }, | ||
261 | { 0x00000008, 0000000000 }, | ||
262 | { 0x00000004, 0000000000 }, | ||
263 | { 0000000000, 0000000000 }, | ||
264 | { 0000000000, 0000000000 }, | ||
265 | { 0000000000, 0000000000 }, | ||
266 | { 0000000000, 0000000000 }, | ||
267 | { 0000000000, 0000000000 }, | ||
268 | { 0000000000, 0000000000 }, | ||
269 | { 0000000000, 0000000000 }, | ||
270 | { 0000000000, 0000000000 }, | ||
271 | { 0000000000, 0000000000 }, | ||
272 | { 0000000000, 0000000000 }, | ||
273 | { 0000000000, 0000000000 }, | ||
274 | { 0000000000, 0000000000 }, | ||
275 | { 0000000000, 0000000000 }, | ||
276 | { 0000000000, 0000000000 }, | ||
277 | { 0000000000, 0000000000 }, | ||
278 | { 0000000000, 0000000000 }, | ||
279 | { 0000000000, 0000000000 }, | ||
280 | { 0000000000, 0000000000 }, | ||
281 | { 0000000000, 0000000000 }, | ||
282 | { 0000000000, 0000000000 }, | ||
283 | { 0000000000, 0000000000 }, | ||
284 | { 0000000000, 0000000000 }, | ||
285 | { 0000000000, 0000000000 }, | ||
286 | { 0000000000, 0000000000 }, | ||
287 | }; | ||
288 | |||
289 | static const u32 R200_cp_microcode[][2] = { | ||
290 | { 0x21007000, 0000000000 }, | ||
291 | { 0x20007000, 0000000000 }, | ||
292 | { 0x000000bf, 0x00000004 }, | ||
293 | { 0x000000c3, 0x00000004 }, | ||
294 | { 0x7a685e5d, 0000000000 }, | ||
295 | { 0x5d5d5588, 0000000000 }, | ||
296 | { 0x68659197, 0000000000 }, | ||
297 | { 0x5da19f78, 0000000000 }, | ||
298 | { 0x5d5d5d5d, 0000000000 }, | ||
299 | { 0x5dee5d50, 0000000000 }, | ||
300 | { 0xf2acacac, 0000000000 }, | ||
301 | { 0xe75df9e9, 0000000000 }, | ||
302 | { 0xb1dd0e11, 0000000000 }, | ||
303 | { 0xe2afafaf, 0000000000 }, | ||
304 | { 0x000f0000, 0x00000016 }, | ||
305 | { 0x452f232d, 0000000000 }, | ||
306 | { 0x00000013, 0x00000004 }, | ||
307 | { 0x000f0000, 0x00000016 }, | ||
308 | { 0x452f272d, 0000000000 }, | ||
309 | { 0x000f0001, 0x00000016 }, | ||
310 | { 0x3e4d4a37, 0000000000 }, | ||
311 | { 0x000077ef, 0x00000002 }, | ||
312 | { 0x00061000, 0x00000002 }, | ||
313 | { 0x00000020, 0x0000001a }, | ||
314 | { 0x00004000, 0x0000001e }, | ||
315 | { 0x00061000, 0x00000002 }, | ||
316 | { 0x00000020, 0x0000001a }, | ||
317 | { 0x00004000, 0x0000001e }, | ||
318 | { 0x00061000, 0x00000002 }, | ||
319 | { 0x00000020, 0x0000001a }, | ||
320 | { 0x00004000, 0x0000001e }, | ||
321 | { 0x00000016, 0x00000004 }, | ||
322 | { 0x0003802a, 0x00000002 }, | ||
323 | { 0x040067e0, 0x00000002 }, | ||
324 | { 0x00000016, 0x00000004 }, | ||
325 | { 0x000077e0, 0x00000002 }, | ||
326 | { 0x00065000, 0x00000002 }, | ||
327 | { 0x000037e1, 0x00000002 }, | ||
328 | { 0x040067e1, 0x00000006 }, | ||
329 | { 0x000077e0, 0x00000002 }, | ||
330 | { 0x000077e1, 0x00000002 }, | ||
331 | { 0x000077e1, 0x00000006 }, | ||
332 | { 0xffffffff, 0000000000 }, | ||
333 | { 0x10000000, 0000000000 }, | ||
334 | { 0x07f007f0, 0000000000 }, | ||
335 | { 0x0003802a, 0x00000002 }, | ||
336 | { 0x040067e0, 0x00000006 }, | ||
337 | { 0x0003802c, 0x00000002 }, | ||
338 | { 0x04002741, 0x00000002 }, | ||
339 | { 0x04002741, 0x00000002 }, | ||
340 | { 0x04002743, 0x00000002 }, | ||
341 | { 0x00007675, 0x00000002 }, | ||
342 | { 0x00007676, 0x00000002 }, | ||
343 | { 0x00007677, 0x00000002 }, | ||
344 | { 0x00007678, 0x00000006 }, | ||
345 | { 0x0003802c, 0x00000002 }, | ||
346 | { 0x04002741, 0x00000002 }, | ||
347 | { 0x04002741, 0x00000002 }, | ||
348 | { 0x04002743, 0x00000002 }, | ||
349 | { 0x00007676, 0x00000002 }, | ||
350 | { 0x00007677, 0x00000002 }, | ||
351 | { 0x00007678, 0x00000006 }, | ||
352 | { 0x0003802b, 0x00000002 }, | ||
353 | { 0x04002676, 0x00000002 }, | ||
354 | { 0x00007677, 0x00000002 }, | ||
355 | { 0x0003802c, 0x00000002 }, | ||
356 | { 0x04002741, 0x00000002 }, | ||
357 | { 0x04002743, 0x00000002 }, | ||
358 | { 0x00007678, 0x00000006 }, | ||
359 | { 0x0003802c, 0x00000002 }, | ||
360 | { 0x04002741, 0x00000002 }, | ||
361 | { 0x04002741, 0x00000002 }, | ||
362 | { 0x04002743, 0x00000002 }, | ||
363 | { 0x00007678, 0x00000006 }, | ||
364 | { 0x0000002f, 0x00000018 }, | ||
365 | { 0x0000002f, 0x00000018 }, | ||
366 | { 0000000000, 0x00000006 }, | ||
367 | { 0x00000037, 0x00000018 }, | ||
368 | { 0x00000037, 0x00000018 }, | ||
369 | { 0000000000, 0x00000006 }, | ||
370 | { 0x01605000, 0x00000002 }, | ||
371 | { 0x00065000, 0x00000002 }, | ||
372 | { 0x00098000, 0x00000002 }, | ||
373 | { 0x00061000, 0x00000002 }, | ||
374 | { 0x64c06051, 0x00000004 }, | ||
375 | { 0x00080000, 0x00000016 }, | ||
376 | { 0000000000, 0000000000 }, | ||
377 | { 0x0400251d, 0x00000002 }, | ||
378 | { 0x00007580, 0x00000002 }, | ||
379 | { 0x00067581, 0x00000002 }, | ||
380 | { 0x04002580, 0x00000002 }, | ||
381 | { 0x00067581, 0x00000002 }, | ||
382 | { 0x0000005a, 0x00000004 }, | ||
383 | { 0x00005000, 0000000000 }, | ||
384 | { 0x00061000, 0x00000002 }, | ||
385 | { 0x0000750e, 0x00000002 }, | ||
386 | { 0x00019000, 0x00000002 }, | ||
387 | { 0x00011064, 0x00000014 }, | ||
388 | { 0x00000064, 0x00000012 }, | ||
389 | { 0x0400250f, 0x00000002 }, | ||
390 | { 0x0000505e, 0x00000004 }, | ||
391 | { 0x00007565, 0x00000002 }, | ||
392 | { 0x00007566, 0x00000002 }, | ||
393 | { 0x00000065, 0x00000004 }, | ||
394 | { 0x01e655b4, 0x00000002 }, | ||
395 | { 0x4401b0f0, 0x00000002 }, | ||
396 | { 0x01c110f0, 0x00000002 }, | ||
397 | { 0x26667071, 0x00000018 }, | ||
398 | { 0x040c2565, 0x00000002 }, | ||
399 | { 0x00000071, 0x00000018 }, | ||
400 | { 0x04002564, 0x00000002 }, | ||
401 | { 0x00007566, 0x00000002 }, | ||
402 | { 0x00000068, 0x00000004 }, | ||
403 | { 0x00401074, 0x00000008 }, | ||
404 | { 0x00101000, 0x00000002 }, | ||
405 | { 0x000d80ff, 0x00000002 }, | ||
406 | { 0x00800077, 0x00000008 }, | ||
407 | { 0x000f9000, 0x00000002 }, | ||
408 | { 0x000e00ff, 0x00000002 }, | ||
409 | { 0000000000, 0x00000006 }, | ||
410 | { 0x00000094, 0x00000018 }, | ||
411 | { 0x00000068, 0x00000004 }, | ||
412 | { 0x00007576, 0x00000002 }, | ||
413 | { 0x00065000, 0x00000002 }, | ||
414 | { 0x00009000, 0x00000002 }, | ||
415 | { 0x00041000, 0x00000002 }, | ||
416 | { 0x0c00350e, 0x00000002 }, | ||
417 | { 0x00049000, 0x00000002 }, | ||
418 | { 0x00051000, 0x00000002 }, | ||
419 | { 0x01e785f8, 0x00000002 }, | ||
420 | { 0x00200000, 0x00000002 }, | ||
421 | { 0x00600087, 0x0000000c }, | ||
422 | { 0x00007563, 0x00000002 }, | ||
423 | { 0x006075f0, 0x00000021 }, | ||
424 | { 0x2000707c, 0x00000004 }, | ||
425 | { 0x0000507c, 0x00000004 }, | ||
426 | { 0x00007576, 0x00000002 }, | ||
427 | { 0x00007577, 0x00000002 }, | ||
428 | { 0x0000750e, 0x00000002 }, | ||
429 | { 0x0000750f, 0x00000002 }, | ||
430 | { 0x00a05000, 0x00000002 }, | ||
431 | { 0x0060008a, 0x0000000c }, | ||
432 | { 0x006075f0, 0x00000021 }, | ||
433 | { 0x000075f8, 0x00000002 }, | ||
434 | { 0x0000008a, 0x00000004 }, | ||
435 | { 0x000a750e, 0x00000002 }, | ||
436 | { 0x0020750f, 0x00000002 }, | ||
437 | { 0x0060008d, 0x00000004 }, | ||
438 | { 0x00007570, 0x00000002 }, | ||
439 | { 0x00007571, 0x00000002 }, | ||
440 | { 0x00007572, 0x00000006 }, | ||
441 | { 0x00005000, 0x00000002 }, | ||
442 | { 0x00a05000, 0x00000002 }, | ||
443 | { 0x00007568, 0x00000002 }, | ||
444 | { 0x00061000, 0x00000002 }, | ||
445 | { 0x00000098, 0x0000000c }, | ||
446 | { 0x00058000, 0x00000002 }, | ||
447 | { 0x0c607562, 0x00000002 }, | ||
448 | { 0x0000009a, 0x00000004 }, | ||
449 | { 0x00600099, 0x00000004 }, | ||
450 | { 0x400070f1, 0000000000 }, | ||
451 | { 0x000380f1, 0x00000002 }, | ||
452 | { 0x000000a7, 0x0000001c }, | ||
453 | { 0x000650a9, 0x00000018 }, | ||
454 | { 0x040025bb, 0x00000002 }, | ||
455 | { 0x000610aa, 0x00000018 }, | ||
456 | { 0x040075bc, 0000000000 }, | ||
457 | { 0x000075bb, 0x00000002 }, | ||
458 | { 0x000075bc, 0000000000 }, | ||
459 | { 0x00090000, 0x00000006 }, | ||
460 | { 0x00090000, 0x00000002 }, | ||
461 | { 0x000d8002, 0x00000006 }, | ||
462 | { 0x00005000, 0x00000002 }, | ||
463 | { 0x00007821, 0x00000002 }, | ||
464 | { 0x00007800, 0000000000 }, | ||
465 | { 0x00007821, 0x00000002 }, | ||
466 | { 0x00007800, 0000000000 }, | ||
467 | { 0x01665000, 0x00000002 }, | ||
468 | { 0x000a0000, 0x00000002 }, | ||
469 | { 0x000671cc, 0x00000002 }, | ||
470 | { 0x0286f1cd, 0x00000002 }, | ||
471 | { 0x000000b7, 0x00000010 }, | ||
472 | { 0x21007000, 0000000000 }, | ||
473 | { 0x000000be, 0x0000001c }, | ||
474 | { 0x00065000, 0x00000002 }, | ||
475 | { 0x000a0000, 0x00000002 }, | ||
476 | { 0x00061000, 0x00000002 }, | ||
477 | { 0x000b0000, 0x00000002 }, | ||
478 | { 0x38067000, 0x00000002 }, | ||
479 | { 0x000a00ba, 0x00000004 }, | ||
480 | { 0x20007000, 0000000000 }, | ||
481 | { 0x01200000, 0x00000002 }, | ||
482 | { 0x20077000, 0x00000002 }, | ||
483 | { 0x01200000, 0x00000002 }, | ||
484 | { 0x20007000, 0000000000 }, | ||
485 | { 0x00061000, 0x00000002 }, | ||
486 | { 0x0120751b, 0x00000002 }, | ||
487 | { 0x8040750a, 0x00000002 }, | ||
488 | { 0x8040750b, 0x00000002 }, | ||
489 | { 0x00110000, 0x00000002 }, | ||
490 | { 0x000380f1, 0x00000002 }, | ||
491 | { 0x000000d1, 0x0000001c }, | ||
492 | { 0x000610aa, 0x00000018 }, | ||
493 | { 0x844075bd, 0x00000002 }, | ||
494 | { 0x000610a9, 0x00000018 }, | ||
495 | { 0x840075bb, 0x00000002 }, | ||
496 | { 0x000610aa, 0x00000018 }, | ||
497 | { 0x844075bc, 0x00000002 }, | ||
498 | { 0x000000d4, 0x00000004 }, | ||
499 | { 0x804075bd, 0x00000002 }, | ||
500 | { 0x800075bb, 0x00000002 }, | ||
501 | { 0x804075bc, 0x00000002 }, | ||
502 | { 0x00108000, 0x00000002 }, | ||
503 | { 0x01400000, 0x00000002 }, | ||
504 | { 0x006000d8, 0x0000000c }, | ||
505 | { 0x20c07000, 0x00000020 }, | ||
506 | { 0x000000da, 0x00000012 }, | ||
507 | { 0x00800000, 0x00000006 }, | ||
508 | { 0x0080751d, 0x00000006 }, | ||
509 | { 0x000025bb, 0x00000002 }, | ||
510 | { 0x000040d4, 0x00000004 }, | ||
511 | { 0x0000775c, 0x00000002 }, | ||
512 | { 0x00a05000, 0x00000002 }, | ||
513 | { 0x00661000, 0x00000002 }, | ||
514 | { 0x0460275d, 0x00000020 }, | ||
515 | { 0x00004000, 0000000000 }, | ||
516 | { 0x00007999, 0x00000002 }, | ||
517 | { 0x00a05000, 0x00000002 }, | ||
518 | { 0x00661000, 0x00000002 }, | ||
519 | { 0x0460299b, 0x00000020 }, | ||
520 | { 0x00004000, 0000000000 }, | ||
521 | { 0x01e00830, 0x00000002 }, | ||
522 | { 0x21007000, 0000000000 }, | ||
523 | { 0x00005000, 0x00000002 }, | ||
524 | { 0x00038056, 0x00000002 }, | ||
525 | { 0x040025e0, 0x00000002 }, | ||
526 | { 0x000075e1, 0000000000 }, | ||
527 | { 0x00000001, 0000000000 }, | ||
528 | { 0x000380ed, 0x00000002 }, | ||
529 | { 0x04007394, 0000000000 }, | ||
530 | { 0000000000, 0000000000 }, | ||
531 | { 0000000000, 0000000000 }, | ||
532 | { 0x000078c4, 0x00000002 }, | ||
533 | { 0x000078c5, 0x00000002 }, | ||
534 | { 0x000078c6, 0x00000002 }, | ||
535 | { 0x00007924, 0x00000002 }, | ||
536 | { 0x00007925, 0x00000002 }, | ||
537 | { 0x00007926, 0x00000002 }, | ||
538 | { 0x000000f2, 0x00000004 }, | ||
539 | { 0x00007924, 0x00000002 }, | ||
540 | { 0x00007925, 0x00000002 }, | ||
541 | { 0x00007926, 0x00000002 }, | ||
542 | { 0x000000f9, 0x00000004 }, | ||
543 | { 0000000000, 0000000000 }, | ||
544 | { 0000000000, 0000000000 }, | ||
545 | { 0000000000, 0000000000 }, | ||
546 | }; | ||
547 | |||
548 | static const u32 R300_cp_microcode[][2] = { | ||
549 | { 0x4200e000, 0000000000 }, | ||
550 | { 0x4000e000, 0000000000 }, | ||
551 | { 0x000000ae, 0x00000008 }, | ||
552 | { 0x000000b2, 0x00000008 }, | ||
553 | { 0x67554b4a, 0000000000 }, | ||
554 | { 0x4a4a4475, 0000000000 }, | ||
555 | { 0x55527d83, 0000000000 }, | ||
556 | { 0x4a8c8b65, 0000000000 }, | ||
557 | { 0x4aef4af6, 0000000000 }, | ||
558 | { 0x4ae14a4a, 0000000000 }, | ||
559 | { 0xe4979797, 0000000000 }, | ||
560 | { 0xdb4aebdd, 0000000000 }, | ||
561 | { 0x9ccc4a4a, 0000000000 }, | ||
562 | { 0xd1989898, 0000000000 }, | ||
563 | { 0x4a0f9ad6, 0000000000 }, | ||
564 | { 0x000ca000, 0x00000004 }, | ||
565 | { 0x000d0012, 0x00000038 }, | ||
566 | { 0x0000e8b4, 0x00000004 }, | ||
567 | { 0x000d0014, 0x00000038 }, | ||
568 | { 0x0000e8b6, 0x00000004 }, | ||
569 | { 0x000d0016, 0x00000038 }, | ||
570 | { 0x0000e854, 0x00000004 }, | ||
571 | { 0x000d0018, 0x00000038 }, | ||
572 | { 0x0000e855, 0x00000004 }, | ||
573 | { 0x000d001a, 0x00000038 }, | ||
574 | { 0x0000e856, 0x00000004 }, | ||
575 | { 0x000d001c, 0x00000038 }, | ||
576 | { 0x0000e857, 0x00000004 }, | ||
577 | { 0x000d001e, 0x00000038 }, | ||
578 | { 0x0000e824, 0x00000004 }, | ||
579 | { 0x000d0020, 0x00000038 }, | ||
580 | { 0x0000e825, 0x00000004 }, | ||
581 | { 0x000d0022, 0x00000038 }, | ||
582 | { 0x0000e830, 0x00000004 }, | ||
583 | { 0x000d0024, 0x00000038 }, | ||
584 | { 0x0000f0c0, 0x00000004 }, | ||
585 | { 0x000d0026, 0x00000038 }, | ||
586 | { 0x0000f0c1, 0x00000004 }, | ||
587 | { 0x000d0028, 0x00000038 }, | ||
588 | { 0x0000f041, 0x00000004 }, | ||
589 | { 0x000d002a, 0x00000038 }, | ||
590 | { 0x0000f184, 0x00000004 }, | ||
591 | { 0x000d002c, 0x00000038 }, | ||
592 | { 0x0000f185, 0x00000004 }, | ||
593 | { 0x000d002e, 0x00000038 }, | ||
594 | { 0x0000f186, 0x00000004 }, | ||
595 | { 0x000d0030, 0x00000038 }, | ||
596 | { 0x0000f187, 0x00000004 }, | ||
597 | { 0x000d0032, 0x00000038 }, | ||
598 | { 0x0000f180, 0x00000004 }, | ||
599 | { 0x000d0034, 0x00000038 }, | ||
600 | { 0x0000f393, 0x00000004 }, | ||
601 | { 0x000d0036, 0x00000038 }, | ||
602 | { 0x0000f38a, 0x00000004 }, | ||
603 | { 0x000d0038, 0x00000038 }, | ||
604 | { 0x0000f38e, 0x00000004 }, | ||
605 | { 0x0000e821, 0x00000004 }, | ||
606 | { 0x0140a000, 0x00000004 }, | ||
607 | { 0x00000043, 0x00000018 }, | ||
608 | { 0x00cce800, 0x00000004 }, | ||
609 | { 0x001b0001, 0x00000004 }, | ||
610 | { 0x08004800, 0x00000004 }, | ||
611 | { 0x001b0001, 0x00000004 }, | ||
612 | { 0x08004800, 0x00000004 }, | ||
613 | { 0x001b0001, 0x00000004 }, | ||
614 | { 0x08004800, 0x00000004 }, | ||
615 | { 0x0000003a, 0x00000008 }, | ||
616 | { 0x0000a000, 0000000000 }, | ||
617 | { 0x2000451d, 0x00000004 }, | ||
618 | { 0x0000e580, 0x00000004 }, | ||
619 | { 0x000ce581, 0x00000004 }, | ||
620 | { 0x08004580, 0x00000004 }, | ||
621 | { 0x000ce581, 0x00000004 }, | ||
622 | { 0x00000047, 0x00000008 }, | ||
623 | { 0x0000a000, 0000000000 }, | ||
624 | { 0x000c2000, 0x00000004 }, | ||
625 | { 0x0000e50e, 0x00000004 }, | ||
626 | { 0x00032000, 0x00000004 }, | ||
627 | { 0x00022051, 0x00000028 }, | ||
628 | { 0x00000051, 0x00000024 }, | ||
629 | { 0x0800450f, 0x00000004 }, | ||
630 | { 0x0000a04b, 0x00000008 }, | ||
631 | { 0x0000e565, 0x00000004 }, | ||
632 | { 0x0000e566, 0x00000004 }, | ||
633 | { 0x00000052, 0x00000008 }, | ||
634 | { 0x03cca5b4, 0x00000004 }, | ||
635 | { 0x05432000, 0x00000004 }, | ||
636 | { 0x00022000, 0x00000004 }, | ||
637 | { 0x4ccce05e, 0x00000030 }, | ||
638 | { 0x08274565, 0x00000004 }, | ||
639 | { 0x0000005e, 0x00000030 }, | ||
640 | { 0x08004564, 0x00000004 }, | ||
641 | { 0x0000e566, 0x00000004 }, | ||
642 | { 0x00000055, 0x00000008 }, | ||
643 | { 0x00802061, 0x00000010 }, | ||
644 | { 0x00202000, 0x00000004 }, | ||
645 | { 0x001b00ff, 0x00000004 }, | ||
646 | { 0x01000064, 0x00000010 }, | ||
647 | { 0x001f2000, 0x00000004 }, | ||
648 | { 0x001c00ff, 0x00000004 }, | ||
649 | { 0000000000, 0x0000000c }, | ||
650 | { 0x00000080, 0x00000030 }, | ||
651 | { 0x00000055, 0x00000008 }, | ||
652 | { 0x0000e576, 0x00000004 }, | ||
653 | { 0x000ca000, 0x00000004 }, | ||
654 | { 0x00012000, 0x00000004 }, | ||
655 | { 0x00082000, 0x00000004 }, | ||
656 | { 0x1800650e, 0x00000004 }, | ||
657 | { 0x00092000, 0x00000004 }, | ||
658 | { 0x000a2000, 0x00000004 }, | ||
659 | { 0x000f0000, 0x00000004 }, | ||
660 | { 0x00400000, 0x00000004 }, | ||
661 | { 0x00000074, 0x00000018 }, | ||
662 | { 0x0000e563, 0x00000004 }, | ||
663 | { 0x00c0e5f9, 0x000000c2 }, | ||
664 | { 0x00000069, 0x00000008 }, | ||
665 | { 0x0000a069, 0x00000008 }, | ||
666 | { 0x0000e576, 0x00000004 }, | ||
667 | { 0x0000e577, 0x00000004 }, | ||
668 | { 0x0000e50e, 0x00000004 }, | ||
669 | { 0x0000e50f, 0x00000004 }, | ||
670 | { 0x0140a000, 0x00000004 }, | ||
671 | { 0x00000077, 0x00000018 }, | ||
672 | { 0x00c0e5f9, 0x000000c2 }, | ||
673 | { 0x00000077, 0x00000008 }, | ||
674 | { 0x0014e50e, 0x00000004 }, | ||
675 | { 0x0040e50f, 0x00000004 }, | ||
676 | { 0x00c0007a, 0x00000008 }, | ||
677 | { 0x0000e570, 0x00000004 }, | ||
678 | { 0x0000e571, 0x00000004 }, | ||
679 | { 0x0000e572, 0x0000000c }, | ||
680 | { 0x0000a000, 0x00000004 }, | ||
681 | { 0x0140a000, 0x00000004 }, | ||
682 | { 0x0000e568, 0x00000004 }, | ||
683 | { 0x000c2000, 0x00000004 }, | ||
684 | { 0x00000084, 0x00000018 }, | ||
685 | { 0x000b0000, 0x00000004 }, | ||
686 | { 0x18c0e562, 0x00000004 }, | ||
687 | { 0x00000086, 0x00000008 }, | ||
688 | { 0x00c00085, 0x00000008 }, | ||
689 | { 0x000700e3, 0x00000004 }, | ||
690 | { 0x00000092, 0x00000038 }, | ||
691 | { 0x000ca094, 0x00000030 }, | ||
692 | { 0x080045bb, 0x00000004 }, | ||
693 | { 0x000c2095, 0x00000030 }, | ||
694 | { 0x0800e5bc, 0000000000 }, | ||
695 | { 0x0000e5bb, 0x00000004 }, | ||
696 | { 0x0000e5bc, 0000000000 }, | ||
697 | { 0x00120000, 0x0000000c }, | ||
698 | { 0x00120000, 0x00000004 }, | ||
699 | { 0x001b0002, 0x0000000c }, | ||
700 | { 0x0000a000, 0x00000004 }, | ||
701 | { 0x0000e821, 0x00000004 }, | ||
702 | { 0x0000e800, 0000000000 }, | ||
703 | { 0x0000e821, 0x00000004 }, | ||
704 | { 0x0000e82e, 0000000000 }, | ||
705 | { 0x02cca000, 0x00000004 }, | ||
706 | { 0x00140000, 0x00000004 }, | ||
707 | { 0x000ce1cc, 0x00000004 }, | ||
708 | { 0x050de1cd, 0x00000004 }, | ||
709 | { 0x00400000, 0x00000004 }, | ||
710 | { 0x000000a4, 0x00000018 }, | ||
711 | { 0x00c0a000, 0x00000004 }, | ||
712 | { 0x000000a1, 0x00000008 }, | ||
713 | { 0x000000a6, 0x00000020 }, | ||
714 | { 0x4200e000, 0000000000 }, | ||
715 | { 0x000000ad, 0x00000038 }, | ||
716 | { 0x000ca000, 0x00000004 }, | ||
717 | { 0x00140000, 0x00000004 }, | ||
718 | { 0x000c2000, 0x00000004 }, | ||
719 | { 0x00160000, 0x00000004 }, | ||
720 | { 0x700ce000, 0x00000004 }, | ||
721 | { 0x001400a9, 0x00000008 }, | ||
722 | { 0x4000e000, 0000000000 }, | ||
723 | { 0x02400000, 0x00000004 }, | ||
724 | { 0x400ee000, 0x00000004 }, | ||
725 | { 0x02400000, 0x00000004 }, | ||
726 | { 0x4000e000, 0000000000 }, | ||
727 | { 0x000c2000, 0x00000004 }, | ||
728 | { 0x0240e51b, 0x00000004 }, | ||
729 | { 0x0080e50a, 0x00000005 }, | ||
730 | { 0x0080e50b, 0x00000005 }, | ||
731 | { 0x00220000, 0x00000004 }, | ||
732 | { 0x000700e3, 0x00000004 }, | ||
733 | { 0x000000c0, 0x00000038 }, | ||
734 | { 0x000c2095, 0x00000030 }, | ||
735 | { 0x0880e5bd, 0x00000005 }, | ||
736 | { 0x000c2094, 0x00000030 }, | ||
737 | { 0x0800e5bb, 0x00000005 }, | ||
738 | { 0x000c2095, 0x00000030 }, | ||
739 | { 0x0880e5bc, 0x00000005 }, | ||
740 | { 0x000000c3, 0x00000008 }, | ||
741 | { 0x0080e5bd, 0x00000005 }, | ||
742 | { 0x0000e5bb, 0x00000005 }, | ||
743 | { 0x0080e5bc, 0x00000005 }, | ||
744 | { 0x00210000, 0x00000004 }, | ||
745 | { 0x02800000, 0x00000004 }, | ||
746 | { 0x00c000c7, 0x00000018 }, | ||
747 | { 0x4180e000, 0x00000040 }, | ||
748 | { 0x000000c9, 0x00000024 }, | ||
749 | { 0x01000000, 0x0000000c }, | ||
750 | { 0x0100e51d, 0x0000000c }, | ||
751 | { 0x000045bb, 0x00000004 }, | ||
752 | { 0x000080c3, 0x00000008 }, | ||
753 | { 0x0000f3ce, 0x00000004 }, | ||
754 | { 0x0140a000, 0x00000004 }, | ||
755 | { 0x00cc2000, 0x00000004 }, | ||
756 | { 0x08c053cf, 0x00000040 }, | ||
757 | { 0x00008000, 0000000000 }, | ||
758 | { 0x0000f3d2, 0x00000004 }, | ||
759 | { 0x0140a000, 0x00000004 }, | ||
760 | { 0x00cc2000, 0x00000004 }, | ||
761 | { 0x08c053d3, 0x00000040 }, | ||
762 | { 0x00008000, 0000000000 }, | ||
763 | { 0x0000f39d, 0x00000004 }, | ||
764 | { 0x0140a000, 0x00000004 }, | ||
765 | { 0x00cc2000, 0x00000004 }, | ||
766 | { 0x08c0539e, 0x00000040 }, | ||
767 | { 0x00008000, 0000000000 }, | ||
768 | { 0x03c00830, 0x00000004 }, | ||
769 | { 0x4200e000, 0000000000 }, | ||
770 | { 0x0000a000, 0x00000004 }, | ||
771 | { 0x200045e0, 0x00000004 }, | ||
772 | { 0x0000e5e1, 0000000000 }, | ||
773 | { 0x00000001, 0000000000 }, | ||
774 | { 0x000700e0, 0x00000004 }, | ||
775 | { 0x0800e394, 0000000000 }, | ||
776 | { 0000000000, 0000000000 }, | ||
777 | { 0x0000e8c4, 0x00000004 }, | ||
778 | { 0x0000e8c5, 0x00000004 }, | ||
779 | { 0x0000e8c6, 0x00000004 }, | ||
780 | { 0x0000e928, 0x00000004 }, | ||
781 | { 0x0000e929, 0x00000004 }, | ||
782 | { 0x0000e92a, 0x00000004 }, | ||
783 | { 0x000000e4, 0x00000008 }, | ||
784 | { 0x0000e928, 0x00000004 }, | ||
785 | { 0x0000e929, 0x00000004 }, | ||
786 | { 0x0000e92a, 0x00000004 }, | ||
787 | { 0x000000eb, 0x00000008 }, | ||
788 | { 0x02c02000, 0x00000004 }, | ||
789 | { 0x00060000, 0x00000004 }, | ||
790 | { 0x000000f3, 0x00000034 }, | ||
791 | { 0x000000f0, 0x00000008 }, | ||
792 | { 0x00008000, 0x00000004 }, | ||
793 | { 0xc000e000, 0000000000 }, | ||
794 | { 0000000000, 0000000000 }, | ||
795 | { 0x000c2000, 0x00000004 }, | ||
796 | { 0x001d0018, 0x00000004 }, | ||
797 | { 0x001a0001, 0x00000004 }, | ||
798 | { 0x000000fb, 0x00000034 }, | ||
799 | { 0x0000004a, 0x00000008 }, | ||
800 | { 0x0500a04a, 0x00000008 }, | ||
801 | { 0000000000, 0000000000 }, | ||
802 | { 0000000000, 0000000000 }, | ||
803 | { 0000000000, 0000000000 }, | ||
804 | { 0000000000, 0000000000 }, | ||
805 | }; | ||
806 | |||
807 | static const u32 R420_cp_microcode[][2] = { | ||
808 | { 0x4200e000, 0000000000 }, | ||
809 | { 0x4000e000, 0000000000 }, | ||
810 | { 0x00000099, 0x00000008 }, | ||
811 | { 0x0000009d, 0x00000008 }, | ||
812 | { 0x4a554b4a, 0000000000 }, | ||
813 | { 0x4a4a4467, 0000000000 }, | ||
814 | { 0x55526f75, 0000000000 }, | ||
815 | { 0x4a7e7d65, 0000000000 }, | ||
816 | { 0xd9d3dff6, 0000000000 }, | ||
817 | { 0x4ac54a4a, 0000000000 }, | ||
818 | { 0xc8828282, 0000000000 }, | ||
819 | { 0xbf4acfc1, 0000000000 }, | ||
820 | { 0x87b04a4a, 0000000000 }, | ||
821 | { 0xb5838383, 0000000000 }, | ||
822 | { 0x4a0f85ba, 0000000000 }, | ||
823 | { 0x000ca000, 0x00000004 }, | ||
824 | { 0x000d0012, 0x00000038 }, | ||
825 | { 0x0000e8b4, 0x00000004 }, | ||
826 | { 0x000d0014, 0x00000038 }, | ||
827 | { 0x0000e8b6, 0x00000004 }, | ||
828 | { 0x000d0016, 0x00000038 }, | ||
829 | { 0x0000e854, 0x00000004 }, | ||
830 | { 0x000d0018, 0x00000038 }, | ||
831 | { 0x0000e855, 0x00000004 }, | ||
832 | { 0x000d001a, 0x00000038 }, | ||
833 | { 0x0000e856, 0x00000004 }, | ||
834 | { 0x000d001c, 0x00000038 }, | ||
835 | { 0x0000e857, 0x00000004 }, | ||
836 | { 0x000d001e, 0x00000038 }, | ||
837 | { 0x0000e824, 0x00000004 }, | ||
838 | { 0x000d0020, 0x00000038 }, | ||
839 | { 0x0000e825, 0x00000004 }, | ||
840 | { 0x000d0022, 0x00000038 }, | ||
841 | { 0x0000e830, 0x00000004 }, | ||
842 | { 0x000d0024, 0x00000038 }, | ||
843 | { 0x0000f0c0, 0x00000004 }, | ||
844 | { 0x000d0026, 0x00000038 }, | ||
845 | { 0x0000f0c1, 0x00000004 }, | ||
846 | { 0x000d0028, 0x00000038 }, | ||
847 | { 0x0000f041, 0x00000004 }, | ||
848 | { 0x000d002a, 0x00000038 }, | ||
849 | { 0x0000f184, 0x00000004 }, | ||
850 | { 0x000d002c, 0x00000038 }, | ||
851 | { 0x0000f185, 0x00000004 }, | ||
852 | { 0x000d002e, 0x00000038 }, | ||
853 | { 0x0000f186, 0x00000004 }, | ||
854 | { 0x000d0030, 0x00000038 }, | ||
855 | { 0x0000f187, 0x00000004 }, | ||
856 | { 0x000d0032, 0x00000038 }, | ||
857 | { 0x0000f180, 0x00000004 }, | ||
858 | { 0x000d0034, 0x00000038 }, | ||
859 | { 0x0000f393, 0x00000004 }, | ||
860 | { 0x000d0036, 0x00000038 }, | ||
861 | { 0x0000f38a, 0x00000004 }, | ||
862 | { 0x000d0038, 0x00000038 }, | ||
863 | { 0x0000f38e, 0x00000004 }, | ||
864 | { 0x0000e821, 0x00000004 }, | ||
865 | { 0x0140a000, 0x00000004 }, | ||
866 | { 0x00000043, 0x00000018 }, | ||
867 | { 0x00cce800, 0x00000004 }, | ||
868 | { 0x001b0001, 0x00000004 }, | ||
869 | { 0x08004800, 0x00000004 }, | ||
870 | { 0x001b0001, 0x00000004 }, | ||
871 | { 0x08004800, 0x00000004 }, | ||
872 | { 0x001b0001, 0x00000004 }, | ||
873 | { 0x08004800, 0x00000004 }, | ||
874 | { 0x0000003a, 0x00000008 }, | ||
875 | { 0x0000a000, 0000000000 }, | ||
876 | { 0x2000451d, 0x00000004 }, | ||
877 | { 0x0000e580, 0x00000004 }, | ||
878 | { 0x000ce581, 0x00000004 }, | ||
879 | { 0x08004580, 0x00000004 }, | ||
880 | { 0x000ce581, 0x00000004 }, | ||
881 | { 0x00000047, 0x00000008 }, | ||
882 | { 0x0000a000, 0000000000 }, | ||
883 | { 0x000c2000, 0x00000004 }, | ||
884 | { 0x0000e50e, 0x00000004 }, | ||
885 | { 0x00032000, 0x00000004 }, | ||
886 | { 0x00022051, 0x00000028 }, | ||
887 | { 0x00000051, 0x00000024 }, | ||
888 | { 0x0800450f, 0x00000004 }, | ||
889 | { 0x0000a04b, 0x00000008 }, | ||
890 | { 0x0000e565, 0x00000004 }, | ||
891 | { 0x0000e566, 0x00000004 }, | ||
892 | { 0x00000052, 0x00000008 }, | ||
893 | { 0x03cca5b4, 0x00000004 }, | ||
894 | { 0x05432000, 0x00000004 }, | ||
895 | { 0x00022000, 0x00000004 }, | ||
896 | { 0x4ccce05e, 0x00000030 }, | ||
897 | { 0x08274565, 0x00000004 }, | ||
898 | { 0x0000005e, 0x00000030 }, | ||
899 | { 0x08004564, 0x00000004 }, | ||
900 | { 0x0000e566, 0x00000004 }, | ||
901 | { 0x00000055, 0x00000008 }, | ||
902 | { 0x00802061, 0x00000010 }, | ||
903 | { 0x00202000, 0x00000004 }, | ||
904 | { 0x001b00ff, 0x00000004 }, | ||
905 | { 0x01000064, 0x00000010 }, | ||
906 | { 0x001f2000, 0x00000004 }, | ||
907 | { 0x001c00ff, 0x00000004 }, | ||
908 | { 0000000000, 0x0000000c }, | ||
909 | { 0x00000072, 0x00000030 }, | ||
910 | { 0x00000055, 0x00000008 }, | ||
911 | { 0x0000e576, 0x00000004 }, | ||
912 | { 0x0000e577, 0x00000004 }, | ||
913 | { 0x0000e50e, 0x00000004 }, | ||
914 | { 0x0000e50f, 0x00000004 }, | ||
915 | { 0x0140a000, 0x00000004 }, | ||
916 | { 0x00000069, 0x00000018 }, | ||
917 | { 0x00c0e5f9, 0x000000c2 }, | ||
918 | { 0x00000069, 0x00000008 }, | ||
919 | { 0x0014e50e, 0x00000004 }, | ||
920 | { 0x0040e50f, 0x00000004 }, | ||
921 | { 0x00c0006c, 0x00000008 }, | ||
922 | { 0x0000e570, 0x00000004 }, | ||
923 | { 0x0000e571, 0x00000004 }, | ||
924 | { 0x0000e572, 0x0000000c }, | ||
925 | { 0x0000a000, 0x00000004 }, | ||
926 | { 0x0140a000, 0x00000004 }, | ||
927 | { 0x0000e568, 0x00000004 }, | ||
928 | { 0x000c2000, 0x00000004 }, | ||
929 | { 0x00000076, 0x00000018 }, | ||
930 | { 0x000b0000, 0x00000004 }, | ||
931 | { 0x18c0e562, 0x00000004 }, | ||
932 | { 0x00000078, 0x00000008 }, | ||
933 | { 0x00c00077, 0x00000008 }, | ||
934 | { 0x000700c7, 0x00000004 }, | ||
935 | { 0x00000080, 0x00000038 }, | ||
936 | { 0x0000e5bb, 0x00000004 }, | ||
937 | { 0x0000e5bc, 0000000000 }, | ||
938 | { 0x0000a000, 0x00000004 }, | ||
939 | { 0x0000e821, 0x00000004 }, | ||
940 | { 0x0000e800, 0000000000 }, | ||
941 | { 0x0000e821, 0x00000004 }, | ||
942 | { 0x0000e82e, 0000000000 }, | ||
943 | { 0x02cca000, 0x00000004 }, | ||
944 | { 0x00140000, 0x00000004 }, | ||
945 | { 0x000ce1cc, 0x00000004 }, | ||
946 | { 0x050de1cd, 0x00000004 }, | ||
947 | { 0x00400000, 0x00000004 }, | ||
948 | { 0x0000008f, 0x00000018 }, | ||
949 | { 0x00c0a000, 0x00000004 }, | ||
950 | { 0x0000008c, 0x00000008 }, | ||
951 | { 0x00000091, 0x00000020 }, | ||
952 | { 0x4200e000, 0000000000 }, | ||
953 | { 0x00000098, 0x00000038 }, | ||
954 | { 0x000ca000, 0x00000004 }, | ||
955 | { 0x00140000, 0x00000004 }, | ||
956 | { 0x000c2000, 0x00000004 }, | ||
957 | { 0x00160000, 0x00000004 }, | ||
958 | { 0x700ce000, 0x00000004 }, | ||
959 | { 0x00140094, 0x00000008 }, | ||
960 | { 0x4000e000, 0000000000 }, | ||
961 | { 0x02400000, 0x00000004 }, | ||
962 | { 0x400ee000, 0x00000004 }, | ||
963 | { 0x02400000, 0x00000004 }, | ||
964 | { 0x4000e000, 0000000000 }, | ||
965 | { 0x000c2000, 0x00000004 }, | ||
966 | { 0x0240e51b, 0x00000004 }, | ||
967 | { 0x0080e50a, 0x00000005 }, | ||
968 | { 0x0080e50b, 0x00000005 }, | ||
969 | { 0x00220000, 0x00000004 }, | ||
970 | { 0x000700c7, 0x00000004 }, | ||
971 | { 0x000000a4, 0x00000038 }, | ||
972 | { 0x0080e5bd, 0x00000005 }, | ||
973 | { 0x0000e5bb, 0x00000005 }, | ||
974 | { 0x0080e5bc, 0x00000005 }, | ||
975 | { 0x00210000, 0x00000004 }, | ||
976 | { 0x02800000, 0x00000004 }, | ||
977 | { 0x00c000ab, 0x00000018 }, | ||
978 | { 0x4180e000, 0x00000040 }, | ||
979 | { 0x000000ad, 0x00000024 }, | ||
980 | { 0x01000000, 0x0000000c }, | ||
981 | { 0x0100e51d, 0x0000000c }, | ||
982 | { 0x000045bb, 0x00000004 }, | ||
983 | { 0x000080a7, 0x00000008 }, | ||
984 | { 0x0000f3ce, 0x00000004 }, | ||
985 | { 0x0140a000, 0x00000004 }, | ||
986 | { 0x00cc2000, 0x00000004 }, | ||
987 | { 0x08c053cf, 0x00000040 }, | ||
988 | { 0x00008000, 0000000000 }, | ||
989 | { 0x0000f3d2, 0x00000004 }, | ||
990 | { 0x0140a000, 0x00000004 }, | ||
991 | { 0x00cc2000, 0x00000004 }, | ||
992 | { 0x08c053d3, 0x00000040 }, | ||
993 | { 0x00008000, 0000000000 }, | ||
994 | { 0x0000f39d, 0x00000004 }, | ||
995 | { 0x0140a000, 0x00000004 }, | ||
996 | { 0x00cc2000, 0x00000004 }, | ||
997 | { 0x08c0539e, 0x00000040 }, | ||
998 | { 0x00008000, 0000000000 }, | ||
999 | { 0x03c00830, 0x00000004 }, | ||
1000 | { 0x4200e000, 0000000000 }, | ||
1001 | { 0x0000a000, 0x00000004 }, | ||
1002 | { 0x200045e0, 0x00000004 }, | ||
1003 | { 0x0000e5e1, 0000000000 }, | ||
1004 | { 0x00000001, 0000000000 }, | ||
1005 | { 0x000700c4, 0x00000004 }, | ||
1006 | { 0x0800e394, 0000000000 }, | ||
1007 | { 0000000000, 0000000000 }, | ||
1008 | { 0x0000e8c4, 0x00000004 }, | ||
1009 | { 0x0000e8c5, 0x00000004 }, | ||
1010 | { 0x0000e8c6, 0x00000004 }, | ||
1011 | { 0x0000e928, 0x00000004 }, | ||
1012 | { 0x0000e929, 0x00000004 }, | ||
1013 | { 0x0000e92a, 0x00000004 }, | ||
1014 | { 0x000000c8, 0x00000008 }, | ||
1015 | { 0x0000e928, 0x00000004 }, | ||
1016 | { 0x0000e929, 0x00000004 }, | ||
1017 | { 0x0000e92a, 0x00000004 }, | ||
1018 | { 0x000000cf, 0x00000008 }, | ||
1019 | { 0x02c02000, 0x00000004 }, | ||
1020 | { 0x00060000, 0x00000004 }, | ||
1021 | { 0x000000d7, 0x00000034 }, | ||
1022 | { 0x000000d4, 0x00000008 }, | ||
1023 | { 0x00008000, 0x00000004 }, | ||
1024 | { 0xc000e000, 0000000000 }, | ||
1025 | { 0x0000e1cc, 0x00000004 }, | ||
1026 | { 0x0500e1cd, 0x00000004 }, | ||
1027 | { 0x000ca000, 0x00000004 }, | ||
1028 | { 0x000000de, 0x00000034 }, | ||
1029 | { 0x000000da, 0x00000008 }, | ||
1030 | { 0x0000a000, 0000000000 }, | ||
1031 | { 0x0019e1cc, 0x00000004 }, | ||
1032 | { 0x001b0001, 0x00000004 }, | ||
1033 | { 0x0500a000, 0x00000004 }, | ||
1034 | { 0x080041cd, 0x00000004 }, | ||
1035 | { 0x000ca000, 0x00000004 }, | ||
1036 | { 0x000000fb, 0x00000034 }, | ||
1037 | { 0x0000004a, 0x00000008 }, | ||
1038 | { 0000000000, 0000000000 }, | ||
1039 | { 0000000000, 0000000000 }, | ||
1040 | { 0000000000, 0000000000 }, | ||
1041 | { 0000000000, 0000000000 }, | ||
1042 | { 0000000000, 0000000000 }, | ||
1043 | { 0000000000, 0000000000 }, | ||
1044 | { 0000000000, 0000000000 }, | ||
1045 | { 0000000000, 0000000000 }, | ||
1046 | { 0000000000, 0000000000 }, | ||
1047 | { 0000000000, 0000000000 }, | ||
1048 | { 0000000000, 0000000000 }, | ||
1049 | { 0000000000, 0000000000 }, | ||
1050 | { 0000000000, 0000000000 }, | ||
1051 | { 0000000000, 0000000000 }, | ||
1052 | { 0000000000, 0000000000 }, | ||
1053 | { 0000000000, 0000000000 }, | ||
1054 | { 0x000c2000, 0x00000004 }, | ||
1055 | { 0x001d0018, 0x00000004 }, | ||
1056 | { 0x001a0001, 0x00000004 }, | ||
1057 | { 0x000000fb, 0x00000034 }, | ||
1058 | { 0x0000004a, 0x00000008 }, | ||
1059 | { 0x0500a04a, 0x00000008 }, | ||
1060 | { 0000000000, 0000000000 }, | ||
1061 | { 0000000000, 0000000000 }, | ||
1062 | { 0000000000, 0000000000 }, | ||
1063 | { 0000000000, 0000000000 }, | ||
1064 | }; | ||
1065 | |||
1066 | static const u32 RS600_cp_microcode[][2] = { | ||
1067 | { 0x4200e000, 0000000000 }, | ||
1068 | { 0x4000e000, 0000000000 }, | ||
1069 | { 0x000000a0, 0x00000008 }, | ||
1070 | { 0x000000a4, 0x00000008 }, | ||
1071 | { 0x4a554b4a, 0000000000 }, | ||
1072 | { 0x4a4a4467, 0000000000 }, | ||
1073 | { 0x55526f75, 0000000000 }, | ||
1074 | { 0x4a7e7d65, 0000000000 }, | ||
1075 | { 0x4ae74af6, 0000000000 }, | ||
1076 | { 0x4ad34a4a, 0000000000 }, | ||
1077 | { 0xd6898989, 0000000000 }, | ||
1078 | { 0xcd4addcf, 0000000000 }, | ||
1079 | { 0x8ebe4ae2, 0000000000 }, | ||
1080 | { 0xc38a8a8a, 0000000000 }, | ||
1081 | { 0x4a0f8cc8, 0000000000 }, | ||
1082 | { 0x000ca000, 0x00000004 }, | ||
1083 | { 0x000d0012, 0x00000038 }, | ||
1084 | { 0x0000e8b4, 0x00000004 }, | ||
1085 | { 0x000d0014, 0x00000038 }, | ||
1086 | { 0x0000e8b6, 0x00000004 }, | ||
1087 | { 0x000d0016, 0x00000038 }, | ||
1088 | { 0x0000e854, 0x00000004 }, | ||
1089 | { 0x000d0018, 0x00000038 }, | ||
1090 | { 0x0000e855, 0x00000004 }, | ||
1091 | { 0x000d001a, 0x00000038 }, | ||
1092 | { 0x0000e856, 0x00000004 }, | ||
1093 | { 0x000d001c, 0x00000038 }, | ||
1094 | { 0x0000e857, 0x00000004 }, | ||
1095 | { 0x000d001e, 0x00000038 }, | ||
1096 | { 0x0000e824, 0x00000004 }, | ||
1097 | { 0x000d0020, 0x00000038 }, | ||
1098 | { 0x0000e825, 0x00000004 }, | ||
1099 | { 0x000d0022, 0x00000038 }, | ||
1100 | { 0x0000e830, 0x00000004 }, | ||
1101 | { 0x000d0024, 0x00000038 }, | ||
1102 | { 0x0000f0c0, 0x00000004 }, | ||
1103 | { 0x000d0026, 0x00000038 }, | ||
1104 | { 0x0000f0c1, 0x00000004 }, | ||
1105 | { 0x000d0028, 0x00000038 }, | ||
1106 | { 0x0000f041, 0x00000004 }, | ||
1107 | { 0x000d002a, 0x00000038 }, | ||
1108 | { 0x0000f184, 0x00000004 }, | ||
1109 | { 0x000d002c, 0x00000038 }, | ||
1110 | { 0x0000f185, 0x00000004 }, | ||
1111 | { 0x000d002e, 0x00000038 }, | ||
1112 | { 0x0000f186, 0x00000004 }, | ||
1113 | { 0x000d0030, 0x00000038 }, | ||
1114 | { 0x0000f187, 0x00000004 }, | ||
1115 | { 0x000d0032, 0x00000038 }, | ||
1116 | { 0x0000f180, 0x00000004 }, | ||
1117 | { 0x000d0034, 0x00000038 }, | ||
1118 | { 0x0000f393, 0x00000004 }, | ||
1119 | { 0x000d0036, 0x00000038 }, | ||
1120 | { 0x0000f38a, 0x00000004 }, | ||
1121 | { 0x000d0038, 0x00000038 }, | ||
1122 | { 0x0000f38e, 0x00000004 }, | ||
1123 | { 0x0000e821, 0x00000004 }, | ||
1124 | { 0x0140a000, 0x00000004 }, | ||
1125 | { 0x00000043, 0x00000018 }, | ||
1126 | { 0x00cce800, 0x00000004 }, | ||
1127 | { 0x001b0001, 0x00000004 }, | ||
1128 | { 0x08004800, 0x00000004 }, | ||
1129 | { 0x001b0001, 0x00000004 }, | ||
1130 | { 0x08004800, 0x00000004 }, | ||
1131 | { 0x001b0001, 0x00000004 }, | ||
1132 | { 0x08004800, 0x00000004 }, | ||
1133 | { 0x0000003a, 0x00000008 }, | ||
1134 | { 0x0000a000, 0000000000 }, | ||
1135 | { 0x2000451d, 0x00000004 }, | ||
1136 | { 0x0000e580, 0x00000004 }, | ||
1137 | { 0x000ce581, 0x00000004 }, | ||
1138 | { 0x08004580, 0x00000004 }, | ||
1139 | { 0x000ce581, 0x00000004 }, | ||
1140 | { 0x00000047, 0x00000008 }, | ||
1141 | { 0x0000a000, 0000000000 }, | ||
1142 | { 0x000c2000, 0x00000004 }, | ||
1143 | { 0x0000e50e, 0x00000004 }, | ||
1144 | { 0x00032000, 0x00000004 }, | ||
1145 | { 0x00022051, 0x00000028 }, | ||
1146 | { 0x00000051, 0x00000024 }, | ||
1147 | { 0x0800450f, 0x00000004 }, | ||
1148 | { 0x0000a04b, 0x00000008 }, | ||
1149 | { 0x0000e565, 0x00000004 }, | ||
1150 | { 0x0000e566, 0x00000004 }, | ||
1151 | { 0x00000052, 0x00000008 }, | ||
1152 | { 0x03cca5b4, 0x00000004 }, | ||
1153 | { 0x05432000, 0x00000004 }, | ||
1154 | { 0x00022000, 0x00000004 }, | ||
1155 | { 0x4ccce05e, 0x00000030 }, | ||
1156 | { 0x08274565, 0x00000004 }, | ||
1157 | { 0x0000005e, 0x00000030 }, | ||
1158 | { 0x08004564, 0x00000004 }, | ||
1159 | { 0x0000e566, 0x00000004 }, | ||
1160 | { 0x00000055, 0x00000008 }, | ||
1161 | { 0x00802061, 0x00000010 }, | ||
1162 | { 0x00202000, 0x00000004 }, | ||
1163 | { 0x001b00ff, 0x00000004 }, | ||
1164 | { 0x01000064, 0x00000010 }, | ||
1165 | { 0x001f2000, 0x00000004 }, | ||
1166 | { 0x001c00ff, 0x00000004 }, | ||
1167 | { 0000000000, 0x0000000c }, | ||
1168 | { 0x00000072, 0x00000030 }, | ||
1169 | { 0x00000055, 0x00000008 }, | ||
1170 | { 0x0000e576, 0x00000004 }, | ||
1171 | { 0x0000e577, 0x00000004 }, | ||
1172 | { 0x0000e50e, 0x00000004 }, | ||
1173 | { 0x0000e50f, 0x00000004 }, | ||
1174 | { 0x0140a000, 0x00000004 }, | ||
1175 | { 0x00000069, 0x00000018 }, | ||
1176 | { 0x00c0e5f9, 0x000000c2 }, | ||
1177 | { 0x00000069, 0x00000008 }, | ||
1178 | { 0x0014e50e, 0x00000004 }, | ||
1179 | { 0x0040e50f, 0x00000004 }, | ||
1180 | { 0x00c0006c, 0x00000008 }, | ||
1181 | { 0x0000e570, 0x00000004 }, | ||
1182 | { 0x0000e571, 0x00000004 }, | ||
1183 | { 0x0000e572, 0x0000000c }, | ||
1184 | { 0x0000a000, 0x00000004 }, | ||
1185 | { 0x0140a000, 0x00000004 }, | ||
1186 | { 0x0000e568, 0x00000004 }, | ||
1187 | { 0x000c2000, 0x00000004 }, | ||
1188 | { 0x00000076, 0x00000018 }, | ||
1189 | { 0x000b0000, 0x00000004 }, | ||
1190 | { 0x18c0e562, 0x00000004 }, | ||
1191 | { 0x00000078, 0x00000008 }, | ||
1192 | { 0x00c00077, 0x00000008 }, | ||
1193 | { 0x000700d5, 0x00000004 }, | ||
1194 | { 0x00000084, 0x00000038 }, | ||
1195 | { 0x000ca086, 0x00000030 }, | ||
1196 | { 0x080045bb, 0x00000004 }, | ||
1197 | { 0x000c2087, 0x00000030 }, | ||
1198 | { 0x0800e5bc, 0000000000 }, | ||
1199 | { 0x0000e5bb, 0x00000004 }, | ||
1200 | { 0x0000e5bc, 0000000000 }, | ||
1201 | { 0x00120000, 0x0000000c }, | ||
1202 | { 0x00120000, 0x00000004 }, | ||
1203 | { 0x001b0002, 0x0000000c }, | ||
1204 | { 0x0000a000, 0x00000004 }, | ||
1205 | { 0x0000e821, 0x00000004 }, | ||
1206 | { 0x0000e800, 0000000000 }, | ||
1207 | { 0x0000e821, 0x00000004 }, | ||
1208 | { 0x0000e82e, 0000000000 }, | ||
1209 | { 0x02cca000, 0x00000004 }, | ||
1210 | { 0x00140000, 0x00000004 }, | ||
1211 | { 0x000ce1cc, 0x00000004 }, | ||
1212 | { 0x050de1cd, 0x00000004 }, | ||
1213 | { 0x00400000, 0x00000004 }, | ||
1214 | { 0x00000096, 0x00000018 }, | ||
1215 | { 0x00c0a000, 0x00000004 }, | ||
1216 | { 0x00000093, 0x00000008 }, | ||
1217 | { 0x00000098, 0x00000020 }, | ||
1218 | { 0x4200e000, 0000000000 }, | ||
1219 | { 0x0000009f, 0x00000038 }, | ||
1220 | { 0x000ca000, 0x00000004 }, | ||
1221 | { 0x00140000, 0x00000004 }, | ||
1222 | { 0x000c2000, 0x00000004 }, | ||
1223 | { 0x00160000, 0x00000004 }, | ||
1224 | { 0x700ce000, 0x00000004 }, | ||
1225 | { 0x0014009b, 0x00000008 }, | ||
1226 | { 0x4000e000, 0000000000 }, | ||
1227 | { 0x02400000, 0x00000004 }, | ||
1228 | { 0x400ee000, 0x00000004 }, | ||
1229 | { 0x02400000, 0x00000004 }, | ||
1230 | { 0x4000e000, 0000000000 }, | ||
1231 | { 0x000c2000, 0x00000004 }, | ||
1232 | { 0x0240e51b, 0x00000004 }, | ||
1233 | { 0x0080e50a, 0x00000005 }, | ||
1234 | { 0x0080e50b, 0x00000005 }, | ||
1235 | { 0x00220000, 0x00000004 }, | ||
1236 | { 0x000700d5, 0x00000004 }, | ||
1237 | { 0x000000b2, 0x00000038 }, | ||
1238 | { 0x000c2087, 0x00000030 }, | ||
1239 | { 0x0880e5bd, 0x00000005 }, | ||
1240 | { 0x000c2086, 0x00000030 }, | ||
1241 | { 0x0800e5bb, 0x00000005 }, | ||
1242 | { 0x000c2087, 0x00000030 }, | ||
1243 | { 0x0880e5bc, 0x00000005 }, | ||
1244 | { 0x000000b5, 0x00000008 }, | ||
1245 | { 0x0080e5bd, 0x00000005 }, | ||
1246 | { 0x0000e5bb, 0x00000005 }, | ||
1247 | { 0x0080e5bc, 0x00000005 }, | ||
1248 | { 0x00210000, 0x00000004 }, | ||
1249 | { 0x02800000, 0x00000004 }, | ||
1250 | { 0x00c000b9, 0x00000018 }, | ||
1251 | { 0x4180e000, 0x00000040 }, | ||
1252 | { 0x000000bb, 0x00000024 }, | ||
1253 | { 0x01000000, 0x0000000c }, | ||
1254 | { 0x0100e51d, 0x0000000c }, | ||
1255 | { 0x000045bb, 0x00000004 }, | ||
1256 | { 0x000080b5, 0x00000008 }, | ||
1257 | { 0x0000f3ce, 0x00000004 }, | ||
1258 | { 0x0140a000, 0x00000004 }, | ||
1259 | { 0x00cc2000, 0x00000004 }, | ||
1260 | { 0x08c053cf, 0x00000040 }, | ||
1261 | { 0x00008000, 0000000000 }, | ||
1262 | { 0x0000f3d2, 0x00000004 }, | ||
1263 | { 0x0140a000, 0x00000004 }, | ||
1264 | { 0x00cc2000, 0x00000004 }, | ||
1265 | { 0x08c053d3, 0x00000040 }, | ||
1266 | { 0x00008000, 0000000000 }, | ||
1267 | { 0x0000f39d, 0x00000004 }, | ||
1268 | { 0x0140a000, 0x00000004 }, | ||
1269 | { 0x00cc2000, 0x00000004 }, | ||
1270 | { 0x08c0539e, 0x00000040 }, | ||
1271 | { 0x00008000, 0000000000 }, | ||
1272 | { 0x03c00830, 0x00000004 }, | ||
1273 | { 0x4200e000, 0000000000 }, | ||
1274 | { 0x0000a000, 0x00000004 }, | ||
1275 | { 0x200045e0, 0x00000004 }, | ||
1276 | { 0x0000e5e1, 0000000000 }, | ||
1277 | { 0x00000001, 0000000000 }, | ||
1278 | { 0x000700d2, 0x00000004 }, | ||
1279 | { 0x0800e394, 0000000000 }, | ||
1280 | { 0000000000, 0000000000 }, | ||
1281 | { 0x0000e8c4, 0x00000004 }, | ||
1282 | { 0x0000e8c5, 0x00000004 }, | ||
1283 | { 0x0000e8c6, 0x00000004 }, | ||
1284 | { 0x0000e928, 0x00000004 }, | ||
1285 | { 0x0000e929, 0x00000004 }, | ||
1286 | { 0x0000e92a, 0x00000004 }, | ||
1287 | { 0x000000d6, 0x00000008 }, | ||
1288 | { 0x0000e928, 0x00000004 }, | ||
1289 | { 0x0000e929, 0x00000004 }, | ||
1290 | { 0x0000e92a, 0x00000004 }, | ||
1291 | { 0x000000dd, 0x00000008 }, | ||
1292 | { 0x00e00116, 0000000000 }, | ||
1293 | { 0x000700e1, 0x00000004 }, | ||
1294 | { 0x0800401c, 0x00000004 }, | ||
1295 | { 0x200050e7, 0x00000004 }, | ||
1296 | { 0x0000e01d, 0x00000004 }, | ||
1297 | { 0x000000e4, 0x00000008 }, | ||
1298 | { 0x02c02000, 0x00000004 }, | ||
1299 | { 0x00060000, 0x00000004 }, | ||
1300 | { 0x000000eb, 0x00000034 }, | ||
1301 | { 0x000000e8, 0x00000008 }, | ||
1302 | { 0x00008000, 0x00000004 }, | ||
1303 | { 0xc000e000, 0000000000 }, | ||
1304 | { 0000000000, 0000000000 }, | ||
1305 | { 0000000000, 0000000000 }, | ||
1306 | { 0000000000, 0000000000 }, | ||
1307 | { 0000000000, 0000000000 }, | ||
1308 | { 0000000000, 0000000000 }, | ||
1309 | { 0000000000, 0000000000 }, | ||
1310 | { 0000000000, 0000000000 }, | ||
1311 | { 0000000000, 0000000000 }, | ||
1312 | { 0000000000, 0000000000 }, | ||
1313 | { 0x000c2000, 0x00000004 }, | ||
1314 | { 0x001d0018, 0x00000004 }, | ||
1315 | { 0x001a0001, 0x00000004 }, | ||
1316 | { 0x000000fb, 0x00000034 }, | ||
1317 | { 0x0000004a, 0x00000008 }, | ||
1318 | { 0x0500a04a, 0x00000008 }, | ||
1319 | { 0000000000, 0000000000 }, | ||
1320 | { 0000000000, 0000000000 }, | ||
1321 | { 0000000000, 0000000000 }, | ||
1322 | { 0000000000, 0000000000 }, | ||
1323 | }; | ||
1324 | |||
1325 | static const u32 RS690_cp_microcode[][2] = { | ||
1326 | { 0x000000dd, 0x00000008 }, | ||
1327 | { 0x000000df, 0x00000008 }, | ||
1328 | { 0x000000a0, 0x00000008 }, | ||
1329 | { 0x000000a4, 0x00000008 }, | ||
1330 | { 0x4a554b4a, 0000000000 }, | ||
1331 | { 0x4a4a4467, 0000000000 }, | ||
1332 | { 0x55526f75, 0000000000 }, | ||
1333 | { 0x4a7e7d65, 0000000000 }, | ||
1334 | { 0x4ad74af6, 0000000000 }, | ||
1335 | { 0x4ac94a4a, 0000000000 }, | ||
1336 | { 0xcc898989, 0000000000 }, | ||
1337 | { 0xc34ad3c5, 0000000000 }, | ||
1338 | { 0x8e4a4a4a, 0000000000 }, | ||
1339 | { 0x4a8a8a8a, 0000000000 }, | ||
1340 | { 0x4a0f8c4a, 0000000000 }, | ||
1341 | { 0x000ca000, 0x00000004 }, | ||
1342 | { 0x000d0012, 0x00000038 }, | ||
1343 | { 0x0000e8b4, 0x00000004 }, | ||
1344 | { 0x000d0014, 0x00000038 }, | ||
1345 | { 0x0000e8b6, 0x00000004 }, | ||
1346 | { 0x000d0016, 0x00000038 }, | ||
1347 | { 0x0000e854, 0x00000004 }, | ||
1348 | { 0x000d0018, 0x00000038 }, | ||
1349 | { 0x0000e855, 0x00000004 }, | ||
1350 | { 0x000d001a, 0x00000038 }, | ||
1351 | { 0x0000e856, 0x00000004 }, | ||
1352 | { 0x000d001c, 0x00000038 }, | ||
1353 | { 0x0000e857, 0x00000004 }, | ||
1354 | { 0x000d001e, 0x00000038 }, | ||
1355 | { 0x0000e824, 0x00000004 }, | ||
1356 | { 0x000d0020, 0x00000038 }, | ||
1357 | { 0x0000e825, 0x00000004 }, | ||
1358 | { 0x000d0022, 0x00000038 }, | ||
1359 | { 0x0000e830, 0x00000004 }, | ||
1360 | { 0x000d0024, 0x00000038 }, | ||
1361 | { 0x0000f0c0, 0x00000004 }, | ||
1362 | { 0x000d0026, 0x00000038 }, | ||
1363 | { 0x0000f0c1, 0x00000004 }, | ||
1364 | { 0x000d0028, 0x00000038 }, | ||
1365 | { 0x0000f041, 0x00000004 }, | ||
1366 | { 0x000d002a, 0x00000038 }, | ||
1367 | { 0x0000f184, 0x00000004 }, | ||
1368 | { 0x000d002c, 0x00000038 }, | ||
1369 | { 0x0000f185, 0x00000004 }, | ||
1370 | { 0x000d002e, 0x00000038 }, | ||
1371 | { 0x0000f186, 0x00000004 }, | ||
1372 | { 0x000d0030, 0x00000038 }, | ||
1373 | { 0x0000f187, 0x00000004 }, | ||
1374 | { 0x000d0032, 0x00000038 }, | ||
1375 | { 0x0000f180, 0x00000004 }, | ||
1376 | { 0x000d0034, 0x00000038 }, | ||
1377 | { 0x0000f393, 0x00000004 }, | ||
1378 | { 0x000d0036, 0x00000038 }, | ||
1379 | { 0x0000f38a, 0x00000004 }, | ||
1380 | { 0x000d0038, 0x00000038 }, | ||
1381 | { 0x0000f38e, 0x00000004 }, | ||
1382 | { 0x0000e821, 0x00000004 }, | ||
1383 | { 0x0140a000, 0x00000004 }, | ||
1384 | { 0x00000043, 0x00000018 }, | ||
1385 | { 0x00cce800, 0x00000004 }, | ||
1386 | { 0x001b0001, 0x00000004 }, | ||
1387 | { 0x08004800, 0x00000004 }, | ||
1388 | { 0x001b0001, 0x00000004 }, | ||
1389 | { 0x08004800, 0x00000004 }, | ||
1390 | { 0x001b0001, 0x00000004 }, | ||
1391 | { 0x08004800, 0x00000004 }, | ||
1392 | { 0x0000003a, 0x00000008 }, | ||
1393 | { 0x0000a000, 0000000000 }, | ||
1394 | { 0x2000451d, 0x00000004 }, | ||
1395 | { 0x0000e580, 0x00000004 }, | ||
1396 | { 0x000ce581, 0x00000004 }, | ||
1397 | { 0x08004580, 0x00000004 }, | ||
1398 | { 0x000ce581, 0x00000004 }, | ||
1399 | { 0x00000047, 0x00000008 }, | ||
1400 | { 0x0000a000, 0000000000 }, | ||
1401 | { 0x000c2000, 0x00000004 }, | ||
1402 | { 0x0000e50e, 0x00000004 }, | ||
1403 | { 0x00032000, 0x00000004 }, | ||
1404 | { 0x00022051, 0x00000028 }, | ||
1405 | { 0x00000051, 0x00000024 }, | ||
1406 | { 0x0800450f, 0x00000004 }, | ||
1407 | { 0x0000a04b, 0x00000008 }, | ||
1408 | { 0x0000e565, 0x00000004 }, | ||
1409 | { 0x0000e566, 0x00000004 }, | ||
1410 | { 0x00000052, 0x00000008 }, | ||
1411 | { 0x03cca5b4, 0x00000004 }, | ||
1412 | { 0x05432000, 0x00000004 }, | ||
1413 | { 0x00022000, 0x00000004 }, | ||
1414 | { 0x4ccce05e, 0x00000030 }, | ||
1415 | { 0x08274565, 0x00000004 }, | ||
1416 | { 0x0000005e, 0x00000030 }, | ||
1417 | { 0x08004564, 0x00000004 }, | ||
1418 | { 0x0000e566, 0x00000004 }, | ||
1419 | { 0x00000055, 0x00000008 }, | ||
1420 | { 0x00802061, 0x00000010 }, | ||
1421 | { 0x00202000, 0x00000004 }, | ||
1422 | { 0x001b00ff, 0x00000004 }, | ||
1423 | { 0x01000064, 0x00000010 }, | ||
1424 | { 0x001f2000, 0x00000004 }, | ||
1425 | { 0x001c00ff, 0x00000004 }, | ||
1426 | { 0000000000, 0x0000000c }, | ||
1427 | { 0x00000072, 0x00000030 }, | ||
1428 | { 0x00000055, 0x00000008 }, | ||
1429 | { 0x0000e576, 0x00000004 }, | ||
1430 | { 0x0000e577, 0x00000004 }, | ||
1431 | { 0x0000e50e, 0x00000004 }, | ||
1432 | { 0x0000e50f, 0x00000004 }, | ||
1433 | { 0x0140a000, 0x00000004 }, | ||
1434 | { 0x00000069, 0x00000018 }, | ||
1435 | { 0x00c0e5f9, 0x000000c2 }, | ||
1436 | { 0x00000069, 0x00000008 }, | ||
1437 | { 0x0014e50e, 0x00000004 }, | ||
1438 | { 0x0040e50f, 0x00000004 }, | ||
1439 | { 0x00c0006c, 0x00000008 }, | ||
1440 | { 0x0000e570, 0x00000004 }, | ||
1441 | { 0x0000e571, 0x00000004 }, | ||
1442 | { 0x0000e572, 0x0000000c }, | ||
1443 | { 0x0000a000, 0x00000004 }, | ||
1444 | { 0x0140a000, 0x00000004 }, | ||
1445 | { 0x0000e568, 0x00000004 }, | ||
1446 | { 0x000c2000, 0x00000004 }, | ||
1447 | { 0x00000076, 0x00000018 }, | ||
1448 | { 0x000b0000, 0x00000004 }, | ||
1449 | { 0x18c0e562, 0x00000004 }, | ||
1450 | { 0x00000078, 0x00000008 }, | ||
1451 | { 0x00c00077, 0x00000008 }, | ||
1452 | { 0x000700cb, 0x00000004 }, | ||
1453 | { 0x00000084, 0x00000038 }, | ||
1454 | { 0x000ca086, 0x00000030 }, | ||
1455 | { 0x080045bb, 0x00000004 }, | ||
1456 | { 0x000c2087, 0x00000030 }, | ||
1457 | { 0x0800e5bc, 0000000000 }, | ||
1458 | { 0x0000e5bb, 0x00000004 }, | ||
1459 | { 0x0000e5bc, 0000000000 }, | ||
1460 | { 0x00120000, 0x0000000c }, | ||
1461 | { 0x00120000, 0x00000004 }, | ||
1462 | { 0x001b0002, 0x0000000c }, | ||
1463 | { 0x0000a000, 0x00000004 }, | ||
1464 | { 0x0000e821, 0x00000004 }, | ||
1465 | { 0x0000e800, 0000000000 }, | ||
1466 | { 0x0000e821, 0x00000004 }, | ||
1467 | { 0x0000e82e, 0000000000 }, | ||
1468 | { 0x02cca000, 0x00000004 }, | ||
1469 | { 0x00140000, 0x00000004 }, | ||
1470 | { 0x000ce1cc, 0x00000004 }, | ||
1471 | { 0x050de1cd, 0x00000004 }, | ||
1472 | { 0x00400000, 0x00000004 }, | ||
1473 | { 0x00000096, 0x00000018 }, | ||
1474 | { 0x00c0a000, 0x00000004 }, | ||
1475 | { 0x00000093, 0x00000008 }, | ||
1476 | { 0x00000098, 0x00000020 }, | ||
1477 | { 0x4200e000, 0000000000 }, | ||
1478 | { 0x0000009f, 0x00000038 }, | ||
1479 | { 0x000ca000, 0x00000004 }, | ||
1480 | { 0x00140000, 0x00000004 }, | ||
1481 | { 0x000c2000, 0x00000004 }, | ||
1482 | { 0x00160000, 0x00000004 }, | ||
1483 | { 0x700ce000, 0x00000004 }, | ||
1484 | { 0x0014009b, 0x00000008 }, | ||
1485 | { 0x4000e000, 0000000000 }, | ||
1486 | { 0x02400000, 0x00000004 }, | ||
1487 | { 0x400ee000, 0x00000004 }, | ||
1488 | { 0x02400000, 0x00000004 }, | ||
1489 | { 0x4000e000, 0000000000 }, | ||
1490 | { 0x00100000, 0x0000002c }, | ||
1491 | { 0x00004000, 0000000000 }, | ||
1492 | { 0x080045c8, 0x00000004 }, | ||
1493 | { 0x00240005, 0x00000004 }, | ||
1494 | { 0x08004d0b, 0x00000004 }, | ||
1495 | { 0x000c2000, 0x00000004 }, | ||
1496 | { 0x0240e51b, 0x00000004 }, | ||
1497 | { 0x0080e50a, 0x00000005 }, | ||
1498 | { 0x0080e50b, 0x00000005 }, | ||
1499 | { 0x00220000, 0x00000004 }, | ||
1500 | { 0x000700cb, 0x00000004 }, | ||
1501 | { 0x000000b7, 0x00000038 }, | ||
1502 | { 0x000c2087, 0x00000030 }, | ||
1503 | { 0x0880e5bd, 0x00000005 }, | ||
1504 | { 0x000c2086, 0x00000030 }, | ||
1505 | { 0x0800e5bb, 0x00000005 }, | ||
1506 | { 0x000c2087, 0x00000030 }, | ||
1507 | { 0x0880e5bc, 0x00000005 }, | ||
1508 | { 0x000000ba, 0x00000008 }, | ||
1509 | { 0x0080e5bd, 0x00000005 }, | ||
1510 | { 0x0000e5bb, 0x00000005 }, | ||
1511 | { 0x0080e5bc, 0x00000005 }, | ||
1512 | { 0x00210000, 0x00000004 }, | ||
1513 | { 0x02800000, 0x00000004 }, | ||
1514 | { 0x00c000be, 0x00000018 }, | ||
1515 | { 0x4180e000, 0x00000040 }, | ||
1516 | { 0x000000c0, 0x00000024 }, | ||
1517 | { 0x01000000, 0x0000000c }, | ||
1518 | { 0x0100e51d, 0x0000000c }, | ||
1519 | { 0x000045bb, 0x00000004 }, | ||
1520 | { 0x000080ba, 0x00000008 }, | ||
1521 | { 0x03c00830, 0x00000004 }, | ||
1522 | { 0x4200e000, 0000000000 }, | ||
1523 | { 0x0000a000, 0x00000004 }, | ||
1524 | { 0x200045e0, 0x00000004 }, | ||
1525 | { 0x0000e5e1, 0000000000 }, | ||
1526 | { 0x00000001, 0000000000 }, | ||
1527 | { 0x000700c8, 0x00000004 }, | ||
1528 | { 0x0800e394, 0000000000 }, | ||
1529 | { 0000000000, 0000000000 }, | ||
1530 | { 0x0000e8c4, 0x00000004 }, | ||
1531 | { 0x0000e8c5, 0x00000004 }, | ||
1532 | { 0x0000e8c6, 0x00000004 }, | ||
1533 | { 0x0000e928, 0x00000004 }, | ||
1534 | { 0x0000e929, 0x00000004 }, | ||
1535 | { 0x0000e92a, 0x00000004 }, | ||
1536 | { 0x000000cc, 0x00000008 }, | ||
1537 | { 0x0000e928, 0x00000004 }, | ||
1538 | { 0x0000e929, 0x00000004 }, | ||
1539 | { 0x0000e92a, 0x00000004 }, | ||
1540 | { 0x000000d3, 0x00000008 }, | ||
1541 | { 0x02c02000, 0x00000004 }, | ||
1542 | { 0x00060000, 0x00000004 }, | ||
1543 | { 0x000000db, 0x00000034 }, | ||
1544 | { 0x000000d8, 0x00000008 }, | ||
1545 | { 0x00008000, 0x00000004 }, | ||
1546 | { 0xc000e000, 0000000000 }, | ||
1547 | { 0x000000e1, 0x00000030 }, | ||
1548 | { 0x4200e000, 0000000000 }, | ||
1549 | { 0x000000e1, 0x00000030 }, | ||
1550 | { 0x4000e000, 0000000000 }, | ||
1551 | { 0x0025001b, 0x00000004 }, | ||
1552 | { 0x00230000, 0x00000004 }, | ||
1553 | { 0x00250005, 0x00000004 }, | ||
1554 | { 0x000000e6, 0x00000034 }, | ||
1555 | { 0000000000, 0x0000000c }, | ||
1556 | { 0x00244000, 0x00000004 }, | ||
1557 | { 0x080045c8, 0x00000004 }, | ||
1558 | { 0x00240005, 0x00000004 }, | ||
1559 | { 0x08004d0b, 0x0000000c }, | ||
1560 | { 0000000000, 0000000000 }, | ||
1561 | { 0000000000, 0000000000 }, | ||
1562 | { 0000000000, 0000000000 }, | ||
1563 | { 0000000000, 0000000000 }, | ||
1564 | { 0000000000, 0000000000 }, | ||
1565 | { 0000000000, 0000000000 }, | ||
1566 | { 0000000000, 0000000000 }, | ||
1567 | { 0000000000, 0000000000 }, | ||
1568 | { 0000000000, 0000000000 }, | ||
1569 | { 0000000000, 0000000000 }, | ||
1570 | { 0000000000, 0000000000 }, | ||
1571 | { 0000000000, 0000000000 }, | ||
1572 | { 0x000c2000, 0x00000004 }, | ||
1573 | { 0x001d0018, 0x00000004 }, | ||
1574 | { 0x001a0001, 0x00000004 }, | ||
1575 | { 0x000000fb, 0x00000034 }, | ||
1576 | { 0x0000004a, 0x00000008 }, | ||
1577 | { 0x0500a04a, 0x00000008 }, | ||
1578 | { 0000000000, 0000000000 }, | ||
1579 | { 0000000000, 0000000000 }, | ||
1580 | { 0000000000, 0000000000 }, | ||
1581 | { 0000000000, 0000000000 }, | ||
1582 | }; | ||
1583 | |||
1584 | static const u32 R520_cp_microcode[][2] = { | ||
1585 | { 0x4200e000, 0000000000 }, | ||
1586 | { 0x4000e000, 0000000000 }, | ||
1587 | { 0x00000099, 0x00000008 }, | ||
1588 | { 0x0000009d, 0x00000008 }, | ||
1589 | { 0x4a554b4a, 0000000000 }, | ||
1590 | { 0x4a4a4467, 0000000000 }, | ||
1591 | { 0x55526f75, 0000000000 }, | ||
1592 | { 0x4a7e7d65, 0000000000 }, | ||
1593 | { 0xe0dae6f6, 0000000000 }, | ||
1594 | { 0x4ac54a4a, 0000000000 }, | ||
1595 | { 0xc8828282, 0000000000 }, | ||
1596 | { 0xbf4acfc1, 0000000000 }, | ||
1597 | { 0x87b04ad5, 0000000000 }, | ||
1598 | { 0xb5838383, 0000000000 }, | ||
1599 | { 0x4a0f85ba, 0000000000 }, | ||
1600 | { 0x000ca000, 0x00000004 }, | ||
1601 | { 0x000d0012, 0x00000038 }, | ||
1602 | { 0x0000e8b4, 0x00000004 }, | ||
1603 | { 0x000d0014, 0x00000038 }, | ||
1604 | { 0x0000e8b6, 0x00000004 }, | ||
1605 | { 0x000d0016, 0x00000038 }, | ||
1606 | { 0x0000e854, 0x00000004 }, | ||
1607 | { 0x000d0018, 0x00000038 }, | ||
1608 | { 0x0000e855, 0x00000004 }, | ||
1609 | { 0x000d001a, 0x00000038 }, | ||
1610 | { 0x0000e856, 0x00000004 }, | ||
1611 | { 0x000d001c, 0x00000038 }, | ||
1612 | { 0x0000e857, 0x00000004 }, | ||
1613 | { 0x000d001e, 0x00000038 }, | ||
1614 | { 0x0000e824, 0x00000004 }, | ||
1615 | { 0x000d0020, 0x00000038 }, | ||
1616 | { 0x0000e825, 0x00000004 }, | ||
1617 | { 0x000d0022, 0x00000038 }, | ||
1618 | { 0x0000e830, 0x00000004 }, | ||
1619 | { 0x000d0024, 0x00000038 }, | ||
1620 | { 0x0000f0c0, 0x00000004 }, | ||
1621 | { 0x000d0026, 0x00000038 }, | ||
1622 | { 0x0000f0c1, 0x00000004 }, | ||
1623 | { 0x000d0028, 0x00000038 }, | ||
1624 | { 0x0000e000, 0x00000004 }, | ||
1625 | { 0x000d002a, 0x00000038 }, | ||
1626 | { 0x0000e000, 0x00000004 }, | ||
1627 | { 0x000d002c, 0x00000038 }, | ||
1628 | { 0x0000e000, 0x00000004 }, | ||
1629 | { 0x000d002e, 0x00000038 }, | ||
1630 | { 0x0000e000, 0x00000004 }, | ||
1631 | { 0x000d0030, 0x00000038 }, | ||
1632 | { 0x0000e000, 0x00000004 }, | ||
1633 | { 0x000d0032, 0x00000038 }, | ||
1634 | { 0x0000f180, 0x00000004 }, | ||
1635 | { 0x000d0034, 0x00000038 }, | ||
1636 | { 0x0000f393, 0x00000004 }, | ||
1637 | { 0x000d0036, 0x00000038 }, | ||
1638 | { 0x0000f38a, 0x00000004 }, | ||
1639 | { 0x000d0038, 0x00000038 }, | ||
1640 | { 0x0000f38e, 0x00000004 }, | ||
1641 | { 0x0000e821, 0x00000004 }, | ||
1642 | { 0x0140a000, 0x00000004 }, | ||
1643 | { 0x00000043, 0x00000018 }, | ||
1644 | { 0x00cce800, 0x00000004 }, | ||
1645 | { 0x001b0001, 0x00000004 }, | ||
1646 | { 0x08004800, 0x00000004 }, | ||
1647 | { 0x001b0001, 0x00000004 }, | ||
1648 | { 0x08004800, 0x00000004 }, | ||
1649 | { 0x001b0001, 0x00000004 }, | ||
1650 | { 0x08004800, 0x00000004 }, | ||
1651 | { 0x0000003a, 0x00000008 }, | ||
1652 | { 0x0000a000, 0000000000 }, | ||
1653 | { 0x2000451d, 0x00000004 }, | ||
1654 | { 0x0000e580, 0x00000004 }, | ||
1655 | { 0x000ce581, 0x00000004 }, | ||
1656 | { 0x08004580, 0x00000004 }, | ||
1657 | { 0x000ce581, 0x00000004 }, | ||
1658 | { 0x00000047, 0x00000008 }, | ||
1659 | { 0x0000a000, 0000000000 }, | ||
1660 | { 0x000c2000, 0x00000004 }, | ||
1661 | { 0x0000e50e, 0x00000004 }, | ||
1662 | { 0x00032000, 0x00000004 }, | ||
1663 | { 0x00022051, 0x00000028 }, | ||
1664 | { 0x00000051, 0x00000024 }, | ||
1665 | { 0x0800450f, 0x00000004 }, | ||
1666 | { 0x0000a04b, 0x00000008 }, | ||
1667 | { 0x0000e565, 0x00000004 }, | ||
1668 | { 0x0000e566, 0x00000004 }, | ||
1669 | { 0x00000052, 0x00000008 }, | ||
1670 | { 0x03cca5b4, 0x00000004 }, | ||
1671 | { 0x05432000, 0x00000004 }, | ||
1672 | { 0x00022000, 0x00000004 }, | ||
1673 | { 0x4ccce05e, 0x00000030 }, | ||
1674 | { 0x08274565, 0x00000004 }, | ||
1675 | { 0x0000005e, 0x00000030 }, | ||
1676 | { 0x08004564, 0x00000004 }, | ||
1677 | { 0x0000e566, 0x00000004 }, | ||
1678 | { 0x00000055, 0x00000008 }, | ||
1679 | { 0x00802061, 0x00000010 }, | ||
1680 | { 0x00202000, 0x00000004 }, | ||
1681 | { 0x001b00ff, 0x00000004 }, | ||
1682 | { 0x01000064, 0x00000010 }, | ||
1683 | { 0x001f2000, 0x00000004 }, | ||
1684 | { 0x001c00ff, 0x00000004 }, | ||
1685 | { 0000000000, 0x0000000c }, | ||
1686 | { 0x00000072, 0x00000030 }, | ||
1687 | { 0x00000055, 0x00000008 }, | ||
1688 | { 0x0000e576, 0x00000004 }, | ||
1689 | { 0x0000e577, 0x00000004 }, | ||
1690 | { 0x0000e50e, 0x00000004 }, | ||
1691 | { 0x0000e50f, 0x00000004 }, | ||
1692 | { 0x0140a000, 0x00000004 }, | ||
1693 | { 0x00000069, 0x00000018 }, | ||
1694 | { 0x00c0e5f9, 0x000000c2 }, | ||
1695 | { 0x00000069, 0x00000008 }, | ||
1696 | { 0x0014e50e, 0x00000004 }, | ||
1697 | { 0x0040e50f, 0x00000004 }, | ||
1698 | { 0x00c0006c, 0x00000008 }, | ||
1699 | { 0x0000e570, 0x00000004 }, | ||
1700 | { 0x0000e571, 0x00000004 }, | ||
1701 | { 0x0000e572, 0x0000000c }, | ||
1702 | { 0x0000a000, 0x00000004 }, | ||
1703 | { 0x0140a000, 0x00000004 }, | ||
1704 | { 0x0000e568, 0x00000004 }, | ||
1705 | { 0x000c2000, 0x00000004 }, | ||
1706 | { 0x00000076, 0x00000018 }, | ||
1707 | { 0x000b0000, 0x00000004 }, | ||
1708 | { 0x18c0e562, 0x00000004 }, | ||
1709 | { 0x00000078, 0x00000008 }, | ||
1710 | { 0x00c00077, 0x00000008 }, | ||
1711 | { 0x000700c7, 0x00000004 }, | ||
1712 | { 0x00000080, 0x00000038 }, | ||
1713 | { 0x0000e5bb, 0x00000004 }, | ||
1714 | { 0x0000e5bc, 0000000000 }, | ||
1715 | { 0x0000a000, 0x00000004 }, | ||
1716 | { 0x0000e821, 0x00000004 }, | ||
1717 | { 0x0000e800, 0000000000 }, | ||
1718 | { 0x0000e821, 0x00000004 }, | ||
1719 | { 0x0000e82e, 0000000000 }, | ||
1720 | { 0x02cca000, 0x00000004 }, | ||
1721 | { 0x00140000, 0x00000004 }, | ||
1722 | { 0x000ce1cc, 0x00000004 }, | ||
1723 | { 0x050de1cd, 0x00000004 }, | ||
1724 | { 0x00400000, 0x00000004 }, | ||
1725 | { 0x0000008f, 0x00000018 }, | ||
1726 | { 0x00c0a000, 0x00000004 }, | ||
1727 | { 0x0000008c, 0x00000008 }, | ||
1728 | { 0x00000091, 0x00000020 }, | ||
1729 | { 0x4200e000, 0000000000 }, | ||
1730 | { 0x00000098, 0x00000038 }, | ||
1731 | { 0x000ca000, 0x00000004 }, | ||
1732 | { 0x00140000, 0x00000004 }, | ||
1733 | { 0x000c2000, 0x00000004 }, | ||
1734 | { 0x00160000, 0x00000004 }, | ||
1735 | { 0x700ce000, 0x00000004 }, | ||
1736 | { 0x00140094, 0x00000008 }, | ||
1737 | { 0x4000e000, 0000000000 }, | ||
1738 | { 0x02400000, 0x00000004 }, | ||
1739 | { 0x400ee000, 0x00000004 }, | ||
1740 | { 0x02400000, 0x00000004 }, | ||
1741 | { 0x4000e000, 0000000000 }, | ||
1742 | { 0x000c2000, 0x00000004 }, | ||
1743 | { 0x0240e51b, 0x00000004 }, | ||
1744 | { 0x0080e50a, 0x00000005 }, | ||
1745 | { 0x0080e50b, 0x00000005 }, | ||
1746 | { 0x00220000, 0x00000004 }, | ||
1747 | { 0x000700c7, 0x00000004 }, | ||
1748 | { 0x000000a4, 0x00000038 }, | ||
1749 | { 0x0080e5bd, 0x00000005 }, | ||
1750 | { 0x0000e5bb, 0x00000005 }, | ||
1751 | { 0x0080e5bc, 0x00000005 }, | ||
1752 | { 0x00210000, 0x00000004 }, | ||
1753 | { 0x02800000, 0x00000004 }, | ||
1754 | { 0x00c000ab, 0x00000018 }, | ||
1755 | { 0x4180e000, 0x00000040 }, | ||
1756 | { 0x000000ad, 0x00000024 }, | ||
1757 | { 0x01000000, 0x0000000c }, | ||
1758 | { 0x0100e51d, 0x0000000c }, | ||
1759 | { 0x000045bb, 0x00000004 }, | ||
1760 | { 0x000080a7, 0x00000008 }, | ||
1761 | { 0x0000f3ce, 0x00000004 }, | ||
1762 | { 0x0140a000, 0x00000004 }, | ||
1763 | { 0x00cc2000, 0x00000004 }, | ||
1764 | { 0x08c053cf, 0x00000040 }, | ||
1765 | { 0x00008000, 0000000000 }, | ||
1766 | { 0x0000f3d2, 0x00000004 }, | ||
1767 | { 0x0140a000, 0x00000004 }, | ||
1768 | { 0x00cc2000, 0x00000004 }, | ||
1769 | { 0x08c053d3, 0x00000040 }, | ||
1770 | { 0x00008000, 0000000000 }, | ||
1771 | { 0x0000f39d, 0x00000004 }, | ||
1772 | { 0x0140a000, 0x00000004 }, | ||
1773 | { 0x00cc2000, 0x00000004 }, | ||
1774 | { 0x08c0539e, 0x00000040 }, | ||
1775 | { 0x00008000, 0000000000 }, | ||
1776 | { 0x03c00830, 0x00000004 }, | ||
1777 | { 0x4200e000, 0000000000 }, | ||
1778 | { 0x0000a000, 0x00000004 }, | ||
1779 | { 0x200045e0, 0x00000004 }, | ||
1780 | { 0x0000e5e1, 0000000000 }, | ||
1781 | { 0x00000001, 0000000000 }, | ||
1782 | { 0x000700c4, 0x00000004 }, | ||
1783 | { 0x0800e394, 0000000000 }, | ||
1784 | { 0000000000, 0000000000 }, | ||
1785 | { 0x0000e8c4, 0x00000004 }, | ||
1786 | { 0x0000e8c5, 0x00000004 }, | ||
1787 | { 0x0000e8c6, 0x00000004 }, | ||
1788 | { 0x0000e928, 0x00000004 }, | ||
1789 | { 0x0000e929, 0x00000004 }, | ||
1790 | { 0x0000e92a, 0x00000004 }, | ||
1791 | { 0x000000c8, 0x00000008 }, | ||
1792 | { 0x0000e928, 0x00000004 }, | ||
1793 | { 0x0000e929, 0x00000004 }, | ||
1794 | { 0x0000e92a, 0x00000004 }, | ||
1795 | { 0x000000cf, 0x00000008 }, | ||
1796 | { 0xdeadbeef, 0000000000 }, | ||
1797 | { 0x00000116, 0000000000 }, | ||
1798 | { 0x000700d3, 0x00000004 }, | ||
1799 | { 0x080050e7, 0x00000004 }, | ||
1800 | { 0x000700d4, 0x00000004 }, | ||
1801 | { 0x0800401c, 0x00000004 }, | ||
1802 | { 0x0000e01d, 0000000000 }, | ||
1803 | { 0x02c02000, 0x00000004 }, | ||
1804 | { 0x00060000, 0x00000004 }, | ||
1805 | { 0x000000de, 0x00000034 }, | ||
1806 | { 0x000000db, 0x00000008 }, | ||
1807 | { 0x00008000, 0x00000004 }, | ||
1808 | { 0xc000e000, 0000000000 }, | ||
1809 | { 0x0000e1cc, 0x00000004 }, | ||
1810 | { 0x0500e1cd, 0x00000004 }, | ||
1811 | { 0x000ca000, 0x00000004 }, | ||
1812 | { 0x000000e5, 0x00000034 }, | ||
1813 | { 0x000000e1, 0x00000008 }, | ||
1814 | { 0x0000a000, 0000000000 }, | ||
1815 | { 0x0019e1cc, 0x00000004 }, | ||
1816 | { 0x001b0001, 0x00000004 }, | ||
1817 | { 0x0500a000, 0x00000004 }, | ||
1818 | { 0x080041cd, 0x00000004 }, | ||
1819 | { 0x000ca000, 0x00000004 }, | ||
1820 | { 0x000000fb, 0x00000034 }, | ||
1821 | { 0x0000004a, 0x00000008 }, | ||
1822 | { 0000000000, 0000000000 }, | ||
1823 | { 0000000000, 0000000000 }, | ||
1824 | { 0000000000, 0000000000 }, | ||
1825 | { 0000000000, 0000000000 }, | ||
1826 | { 0000000000, 0000000000 }, | ||
1827 | { 0000000000, 0000000000 }, | ||
1828 | { 0000000000, 0000000000 }, | ||
1829 | { 0000000000, 0000000000 }, | ||
1830 | { 0000000000, 0000000000 }, | ||
1831 | { 0x000c2000, 0x00000004 }, | ||
1832 | { 0x001d0018, 0x00000004 }, | ||
1833 | { 0x001a0001, 0x00000004 }, | ||
1834 | { 0x000000fb, 0x00000034 }, | ||
1835 | { 0x0000004a, 0x00000008 }, | ||
1836 | { 0x0500a04a, 0x00000008 }, | ||
1837 | { 0000000000, 0000000000 }, | ||
1838 | { 0000000000, 0000000000 }, | ||
1839 | { 0000000000, 0000000000 }, | ||
1840 | { 0000000000, 0000000000 }, | ||
1841 | }; | ||
1842 | |||
1843 | |||
1844 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c new file mode 100644 index 000000000000..11c146b49211 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_state.c | |||
@@ -0,0 +1,3203 @@ | |||
1 | /* radeon_state.c -- State support for Radeon -*- linux-c -*- */ | ||
2 | /* | ||
3 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. | ||
4 | * All Rights Reserved. | ||
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 (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | * DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | * Authors: | ||
26 | * Gareth Hughes <gareth@valinux.com> | ||
27 | * Kevin E. Martin <martin@valinux.com> | ||
28 | */ | ||
29 | |||
30 | #include "drmP.h" | ||
31 | #include "drm.h" | ||
32 | #include "drm_sarea.h" | ||
33 | #include "radeon_drm.h" | ||
34 | #include "radeon_drv.h" | ||
35 | |||
36 | /* ================================================================ | ||
37 | * Helper functions for client state checking and fixup | ||
38 | */ | ||
39 | |||
40 | static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | ||
41 | dev_priv, | ||
42 | struct drm_file * file_priv, | ||
43 | u32 *offset) | ||
44 | { | ||
45 | u64 off = *offset; | ||
46 | u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1; | ||
47 | struct drm_radeon_driver_file_fields *radeon_priv; | ||
48 | |||
49 | /* Hrm ... the story of the offset ... So this function converts | ||
50 | * the various ideas of what userland clients might have for an | ||
51 | * offset in the card address space into an offset into the card | ||
52 | * address space :) So with a sane client, it should just keep | ||
53 | * the value intact and just do some boundary checking. However, | ||
54 | * not all clients are sane. Some older clients pass us 0 based | ||
55 | * offsets relative to the start of the framebuffer and some may | ||
56 | * assume the AGP aperture it appended to the framebuffer, so we | ||
57 | * try to detect those cases and fix them up. | ||
58 | * | ||
59 | * Note: It might be a good idea here to make sure the offset lands | ||
60 | * in some "allowed" area to protect things like the PCIE GART... | ||
61 | */ | ||
62 | |||
63 | /* First, the best case, the offset already lands in either the | ||
64 | * framebuffer or the GART mapped space | ||
65 | */ | ||
66 | if (radeon_check_offset(dev_priv, off)) | ||
67 | return 0; | ||
68 | |||
69 | /* Ok, that didn't happen... now check if we have a zero based | ||
70 | * offset that fits in the framebuffer + gart space, apply the | ||
71 | * magic offset we get from SETPARAM or calculated from fb_location | ||
72 | */ | ||
73 | if (off < (dev_priv->fb_size + dev_priv->gart_size)) { | ||
74 | radeon_priv = file_priv->driver_priv; | ||
75 | off += radeon_priv->radeon_fb_delta; | ||
76 | } | ||
77 | |||
78 | /* Finally, assume we aimed at a GART offset if beyond the fb */ | ||
79 | if (off > fb_end) | ||
80 | off = off - fb_end - 1 + dev_priv->gart_vm_start; | ||
81 | |||
82 | /* Now recheck and fail if out of bounds */ | ||
83 | if (radeon_check_offset(dev_priv, off)) { | ||
84 | DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); | ||
85 | *offset = off; | ||
86 | return 0; | ||
87 | } | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | ||
92 | dev_priv, | ||
93 | struct drm_file *file_priv, | ||
94 | int id, u32 *data) | ||
95 | { | ||
96 | switch (id) { | ||
97 | |||
98 | case RADEON_EMIT_PP_MISC: | ||
99 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
100 | &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { | ||
101 | DRM_ERROR("Invalid depth buffer offset\n"); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | break; | ||
105 | |||
106 | case RADEON_EMIT_PP_CNTL: | ||
107 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
108 | &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { | ||
109 | DRM_ERROR("Invalid colour buffer offset\n"); | ||
110 | return -EINVAL; | ||
111 | } | ||
112 | break; | ||
113 | |||
114 | case R200_EMIT_PP_TXOFFSET_0: | ||
115 | case R200_EMIT_PP_TXOFFSET_1: | ||
116 | case R200_EMIT_PP_TXOFFSET_2: | ||
117 | case R200_EMIT_PP_TXOFFSET_3: | ||
118 | case R200_EMIT_PP_TXOFFSET_4: | ||
119 | case R200_EMIT_PP_TXOFFSET_5: | ||
120 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
121 | &data[0])) { | ||
122 | DRM_ERROR("Invalid R200 texture offset\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | break; | ||
126 | |||
127 | case RADEON_EMIT_PP_TXFILTER_0: | ||
128 | case RADEON_EMIT_PP_TXFILTER_1: | ||
129 | case RADEON_EMIT_PP_TXFILTER_2: | ||
130 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
131 | &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { | ||
132 | DRM_ERROR("Invalid R100 texture offset\n"); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | break; | ||
136 | |||
137 | case R200_EMIT_PP_CUBIC_OFFSETS_0: | ||
138 | case R200_EMIT_PP_CUBIC_OFFSETS_1: | ||
139 | case R200_EMIT_PP_CUBIC_OFFSETS_2: | ||
140 | case R200_EMIT_PP_CUBIC_OFFSETS_3: | ||
141 | case R200_EMIT_PP_CUBIC_OFFSETS_4: | ||
142 | case R200_EMIT_PP_CUBIC_OFFSETS_5:{ | ||
143 | int i; | ||
144 | for (i = 0; i < 5; i++) { | ||
145 | if (radeon_check_and_fixup_offset(dev_priv, | ||
146 | file_priv, | ||
147 | &data[i])) { | ||
148 | DRM_ERROR | ||
149 | ("Invalid R200 cubic texture offset\n"); | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | } | ||
153 | break; | ||
154 | } | ||
155 | |||
156 | case RADEON_EMIT_PP_CUBIC_OFFSETS_T0: | ||
157 | case RADEON_EMIT_PP_CUBIC_OFFSETS_T1: | ||
158 | case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ | ||
159 | int i; | ||
160 | for (i = 0; i < 5; i++) { | ||
161 | if (radeon_check_and_fixup_offset(dev_priv, | ||
162 | file_priv, | ||
163 | &data[i])) { | ||
164 | DRM_ERROR | ||
165 | ("Invalid R100 cubic texture offset\n"); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | break; | ||
171 | |||
172 | case R200_EMIT_VAP_CTL:{ | ||
173 | RING_LOCALS; | ||
174 | BEGIN_RING(2); | ||
175 | OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); | ||
176 | ADVANCE_RING(); | ||
177 | } | ||
178 | break; | ||
179 | |||
180 | case RADEON_EMIT_RB3D_COLORPITCH: | ||
181 | case RADEON_EMIT_RE_LINE_PATTERN: | ||
182 | case RADEON_EMIT_SE_LINE_WIDTH: | ||
183 | case RADEON_EMIT_PP_LUM_MATRIX: | ||
184 | case RADEON_EMIT_PP_ROT_MATRIX_0: | ||
185 | case RADEON_EMIT_RB3D_STENCILREFMASK: | ||
186 | case RADEON_EMIT_SE_VPORT_XSCALE: | ||
187 | case RADEON_EMIT_SE_CNTL: | ||
188 | case RADEON_EMIT_SE_CNTL_STATUS: | ||
189 | case RADEON_EMIT_RE_MISC: | ||
190 | case RADEON_EMIT_PP_BORDER_COLOR_0: | ||
191 | case RADEON_EMIT_PP_BORDER_COLOR_1: | ||
192 | case RADEON_EMIT_PP_BORDER_COLOR_2: | ||
193 | case RADEON_EMIT_SE_ZBIAS_FACTOR: | ||
194 | case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: | ||
195 | case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: | ||
196 | case R200_EMIT_PP_TXCBLEND_0: | ||
197 | case R200_EMIT_PP_TXCBLEND_1: | ||
198 | case R200_EMIT_PP_TXCBLEND_2: | ||
199 | case R200_EMIT_PP_TXCBLEND_3: | ||
200 | case R200_EMIT_PP_TXCBLEND_4: | ||
201 | case R200_EMIT_PP_TXCBLEND_5: | ||
202 | case R200_EMIT_PP_TXCBLEND_6: | ||
203 | case R200_EMIT_PP_TXCBLEND_7: | ||
204 | case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: | ||
205 | case R200_EMIT_TFACTOR_0: | ||
206 | case R200_EMIT_VTX_FMT_0: | ||
207 | case R200_EMIT_MATRIX_SELECT_0: | ||
208 | case R200_EMIT_TEX_PROC_CTL_2: | ||
209 | case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: | ||
210 | case R200_EMIT_PP_TXFILTER_0: | ||
211 | case R200_EMIT_PP_TXFILTER_1: | ||
212 | case R200_EMIT_PP_TXFILTER_2: | ||
213 | case R200_EMIT_PP_TXFILTER_3: | ||
214 | case R200_EMIT_PP_TXFILTER_4: | ||
215 | case R200_EMIT_PP_TXFILTER_5: | ||
216 | case R200_EMIT_VTE_CNTL: | ||
217 | case R200_EMIT_OUTPUT_VTX_COMP_SEL: | ||
218 | case R200_EMIT_PP_TAM_DEBUG3: | ||
219 | case R200_EMIT_PP_CNTL_X: | ||
220 | case R200_EMIT_RB3D_DEPTHXY_OFFSET: | ||
221 | case R200_EMIT_RE_AUX_SCISSOR_CNTL: | ||
222 | case R200_EMIT_RE_SCISSOR_TL_0: | ||
223 | case R200_EMIT_RE_SCISSOR_TL_1: | ||
224 | case R200_EMIT_RE_SCISSOR_TL_2: | ||
225 | case R200_EMIT_SE_VAP_CNTL_STATUS: | ||
226 | case R200_EMIT_SE_VTX_STATE_CNTL: | ||
227 | case R200_EMIT_RE_POINTSIZE: | ||
228 | case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0: | ||
229 | case R200_EMIT_PP_CUBIC_FACES_0: | ||
230 | case R200_EMIT_PP_CUBIC_FACES_1: | ||
231 | case R200_EMIT_PP_CUBIC_FACES_2: | ||
232 | case R200_EMIT_PP_CUBIC_FACES_3: | ||
233 | case R200_EMIT_PP_CUBIC_FACES_4: | ||
234 | case R200_EMIT_PP_CUBIC_FACES_5: | ||
235 | case RADEON_EMIT_PP_TEX_SIZE_0: | ||
236 | case RADEON_EMIT_PP_TEX_SIZE_1: | ||
237 | case RADEON_EMIT_PP_TEX_SIZE_2: | ||
238 | case R200_EMIT_RB3D_BLENDCOLOR: | ||
239 | case R200_EMIT_TCL_POINT_SPRITE_CNTL: | ||
240 | case RADEON_EMIT_PP_CUBIC_FACES_0: | ||
241 | case RADEON_EMIT_PP_CUBIC_FACES_1: | ||
242 | case RADEON_EMIT_PP_CUBIC_FACES_2: | ||
243 | case R200_EMIT_PP_TRI_PERF_CNTL: | ||
244 | case R200_EMIT_PP_AFS_0: | ||
245 | case R200_EMIT_PP_AFS_1: | ||
246 | case R200_EMIT_ATF_TFACTOR: | ||
247 | case R200_EMIT_PP_TXCTLALL_0: | ||
248 | case R200_EMIT_PP_TXCTLALL_1: | ||
249 | case R200_EMIT_PP_TXCTLALL_2: | ||
250 | case R200_EMIT_PP_TXCTLALL_3: | ||
251 | case R200_EMIT_PP_TXCTLALL_4: | ||
252 | case R200_EMIT_PP_TXCTLALL_5: | ||
253 | case R200_EMIT_VAP_PVS_CNTL: | ||
254 | /* These packets don't contain memory offsets */ | ||
255 | break; | ||
256 | |||
257 | default: | ||
258 | DRM_ERROR("Unknown state packet ID %d\n", id); | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | ||
266 | dev_priv, | ||
267 | struct drm_file *file_priv, | ||
268 | drm_radeon_kcmd_buffer_t * | ||
269 | cmdbuf, | ||
270 | unsigned int *cmdsz) | ||
271 | { | ||
272 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
273 | u32 offset, narrays; | ||
274 | int count, i, k; | ||
275 | |||
276 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); | ||
277 | |||
278 | if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) { | ||
279 | DRM_ERROR("Not a type 3 packet\n"); | ||
280 | return -EINVAL; | ||
281 | } | ||
282 | |||
283 | if (4 * *cmdsz > cmdbuf->bufsz) { | ||
284 | DRM_ERROR("Packet size larger than size of data provided\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | switch(cmd[0] & 0xff00) { | ||
289 | /* XXX Are there old drivers needing other packets? */ | ||
290 | |||
291 | case RADEON_3D_DRAW_IMMD: | ||
292 | case RADEON_3D_DRAW_VBUF: | ||
293 | case RADEON_3D_DRAW_INDX: | ||
294 | case RADEON_WAIT_FOR_IDLE: | ||
295 | case RADEON_CP_NOP: | ||
296 | case RADEON_3D_CLEAR_ZMASK: | ||
297 | /* case RADEON_CP_NEXT_CHAR: | ||
298 | case RADEON_CP_PLY_NEXTSCAN: | ||
299 | case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ | ||
300 | /* these packets are safe */ | ||
301 | break; | ||
302 | |||
303 | case RADEON_CP_3D_DRAW_IMMD_2: | ||
304 | case RADEON_CP_3D_DRAW_VBUF_2: | ||
305 | case RADEON_CP_3D_DRAW_INDX_2: | ||
306 | case RADEON_3D_CLEAR_HIZ: | ||
307 | /* safe but r200 only */ | ||
308 | if (dev_priv->microcode_version != UCODE_R200) { | ||
309 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | break; | ||
313 | |||
314 | case RADEON_3D_LOAD_VBPNTR: | ||
315 | count = (cmd[0] >> 16) & 0x3fff; | ||
316 | |||
317 | if (count > 18) { /* 12 arrays max */ | ||
318 | DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", | ||
319 | count); | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | /* carefully check packet contents */ | ||
324 | narrays = cmd[1] & ~0xc000; | ||
325 | k = 0; | ||
326 | i = 2; | ||
327 | while ((k < narrays) && (i < (count + 2))) { | ||
328 | i++; /* skip attribute field */ | ||
329 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
330 | &cmd[i])) { | ||
331 | DRM_ERROR | ||
332 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
333 | k, i); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | k++; | ||
337 | i++; | ||
338 | if (k == narrays) | ||
339 | break; | ||
340 | /* have one more to process, they come in pairs */ | ||
341 | if (radeon_check_and_fixup_offset(dev_priv, | ||
342 | file_priv, &cmd[i])) | ||
343 | { | ||
344 | DRM_ERROR | ||
345 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
346 | k, i); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | k++; | ||
350 | i++; | ||
351 | } | ||
352 | /* do the counts match what we expect ? */ | ||
353 | if ((k != narrays) || (i != (count + 2))) { | ||
354 | DRM_ERROR | ||
355 | ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", | ||
356 | k, i, narrays, count + 1); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | break; | ||
360 | |||
361 | case RADEON_3D_RNDR_GEN_INDX_PRIM: | ||
362 | if (dev_priv->microcode_version != UCODE_R100) { | ||
363 | DRM_ERROR("Invalid 3d packet for r200-class chip\n"); | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { | ||
367 | DRM_ERROR("Invalid rndr_gen_indx offset\n"); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | break; | ||
371 | |||
372 | case RADEON_CP_INDX_BUFFER: | ||
373 | if (dev_priv->microcode_version != UCODE_R200) { | ||
374 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
378 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) { | ||
382 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | break; | ||
386 | |||
387 | case RADEON_CNTL_HOSTDATA_BLT: | ||
388 | case RADEON_CNTL_PAINT_MULTI: | ||
389 | case RADEON_CNTL_BITBLT_MULTI: | ||
390 | /* MSB of opcode: next DWORD GUI_CNTL */ | ||
391 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | ||
392 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | ||
393 | offset = cmd[2] << 10; | ||
394 | if (radeon_check_and_fixup_offset | ||
395 | (dev_priv, file_priv, &offset)) { | ||
396 | DRM_ERROR("Invalid first packet offset\n"); | ||
397 | return -EINVAL; | ||
398 | } | ||
399 | cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; | ||
400 | } | ||
401 | |||
402 | if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && | ||
403 | (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | ||
404 | offset = cmd[3] << 10; | ||
405 | if (radeon_check_and_fixup_offset | ||
406 | (dev_priv, file_priv, &offset)) { | ||
407 | DRM_ERROR("Invalid second packet offset\n"); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; | ||
411 | } | ||
412 | break; | ||
413 | |||
414 | default: | ||
415 | DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | /* ================================================================ | ||
423 | * CP hardware state programming functions | ||
424 | */ | ||
425 | |||
426 | static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv, | ||
427 | struct drm_clip_rect * box) | ||
428 | { | ||
429 | RING_LOCALS; | ||
430 | |||
431 | DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n", | ||
432 | box->x1, box->y1, box->x2, box->y2); | ||
433 | |||
434 | BEGIN_RING(4); | ||
435 | OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); | ||
436 | OUT_RING((box->y1 << 16) | box->x1); | ||
437 | OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); | ||
438 | OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1)); | ||
439 | ADVANCE_RING(); | ||
440 | } | ||
441 | |||
442 | /* Emit 1.1 state | ||
443 | */ | ||
444 | static int radeon_emit_state(drm_radeon_private_t * dev_priv, | ||
445 | struct drm_file *file_priv, | ||
446 | drm_radeon_context_regs_t * ctx, | ||
447 | drm_radeon_texture_regs_t * tex, | ||
448 | unsigned int dirty) | ||
449 | { | ||
450 | RING_LOCALS; | ||
451 | DRM_DEBUG("dirty=0x%08x\n", dirty); | ||
452 | |||
453 | if (dirty & RADEON_UPLOAD_CONTEXT) { | ||
454 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
455 | &ctx->rb3d_depthoffset)) { | ||
456 | DRM_ERROR("Invalid depth buffer offset\n"); | ||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
461 | &ctx->rb3d_coloroffset)) { | ||
462 | DRM_ERROR("Invalid depth buffer offset\n"); | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | |||
466 | BEGIN_RING(14); | ||
467 | OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6)); | ||
468 | OUT_RING(ctx->pp_misc); | ||
469 | OUT_RING(ctx->pp_fog_color); | ||
470 | OUT_RING(ctx->re_solid_color); | ||
471 | OUT_RING(ctx->rb3d_blendcntl); | ||
472 | OUT_RING(ctx->rb3d_depthoffset); | ||
473 | OUT_RING(ctx->rb3d_depthpitch); | ||
474 | OUT_RING(ctx->rb3d_zstencilcntl); | ||
475 | OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2)); | ||
476 | OUT_RING(ctx->pp_cntl); | ||
477 | OUT_RING(ctx->rb3d_cntl); | ||
478 | OUT_RING(ctx->rb3d_coloroffset); | ||
479 | OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); | ||
480 | OUT_RING(ctx->rb3d_colorpitch); | ||
481 | ADVANCE_RING(); | ||
482 | } | ||
483 | |||
484 | if (dirty & RADEON_UPLOAD_VERTFMT) { | ||
485 | BEGIN_RING(2); | ||
486 | OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0)); | ||
487 | OUT_RING(ctx->se_coord_fmt); | ||
488 | ADVANCE_RING(); | ||
489 | } | ||
490 | |||
491 | if (dirty & RADEON_UPLOAD_LINE) { | ||
492 | BEGIN_RING(5); | ||
493 | OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1)); | ||
494 | OUT_RING(ctx->re_line_pattern); | ||
495 | OUT_RING(ctx->re_line_state); | ||
496 | OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0)); | ||
497 | OUT_RING(ctx->se_line_width); | ||
498 | ADVANCE_RING(); | ||
499 | } | ||
500 | |||
501 | if (dirty & RADEON_UPLOAD_BUMPMAP) { | ||
502 | BEGIN_RING(5); | ||
503 | OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0)); | ||
504 | OUT_RING(ctx->pp_lum_matrix); | ||
505 | OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1)); | ||
506 | OUT_RING(ctx->pp_rot_matrix_0); | ||
507 | OUT_RING(ctx->pp_rot_matrix_1); | ||
508 | ADVANCE_RING(); | ||
509 | } | ||
510 | |||
511 | if (dirty & RADEON_UPLOAD_MASKS) { | ||
512 | BEGIN_RING(4); | ||
513 | OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2)); | ||
514 | OUT_RING(ctx->rb3d_stencilrefmask); | ||
515 | OUT_RING(ctx->rb3d_ropcntl); | ||
516 | OUT_RING(ctx->rb3d_planemask); | ||
517 | ADVANCE_RING(); | ||
518 | } | ||
519 | |||
520 | if (dirty & RADEON_UPLOAD_VIEWPORT) { | ||
521 | BEGIN_RING(7); | ||
522 | OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5)); | ||
523 | OUT_RING(ctx->se_vport_xscale); | ||
524 | OUT_RING(ctx->se_vport_xoffset); | ||
525 | OUT_RING(ctx->se_vport_yscale); | ||
526 | OUT_RING(ctx->se_vport_yoffset); | ||
527 | OUT_RING(ctx->se_vport_zscale); | ||
528 | OUT_RING(ctx->se_vport_zoffset); | ||
529 | ADVANCE_RING(); | ||
530 | } | ||
531 | |||
532 | if (dirty & RADEON_UPLOAD_SETUP) { | ||
533 | BEGIN_RING(4); | ||
534 | OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0)); | ||
535 | OUT_RING(ctx->se_cntl); | ||
536 | OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0)); | ||
537 | OUT_RING(ctx->se_cntl_status); | ||
538 | ADVANCE_RING(); | ||
539 | } | ||
540 | |||
541 | if (dirty & RADEON_UPLOAD_MISC) { | ||
542 | BEGIN_RING(2); | ||
543 | OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0)); | ||
544 | OUT_RING(ctx->re_misc); | ||
545 | ADVANCE_RING(); | ||
546 | } | ||
547 | |||
548 | if (dirty & RADEON_UPLOAD_TEX0) { | ||
549 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
550 | &tex[0].pp_txoffset)) { | ||
551 | DRM_ERROR("Invalid texture offset for unit 0\n"); | ||
552 | return -EINVAL; | ||
553 | } | ||
554 | |||
555 | BEGIN_RING(9); | ||
556 | OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5)); | ||
557 | OUT_RING(tex[0].pp_txfilter); | ||
558 | OUT_RING(tex[0].pp_txformat); | ||
559 | OUT_RING(tex[0].pp_txoffset); | ||
560 | OUT_RING(tex[0].pp_txcblend); | ||
561 | OUT_RING(tex[0].pp_txablend); | ||
562 | OUT_RING(tex[0].pp_tfactor); | ||
563 | OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0)); | ||
564 | OUT_RING(tex[0].pp_border_color); | ||
565 | ADVANCE_RING(); | ||
566 | } | ||
567 | |||
568 | if (dirty & RADEON_UPLOAD_TEX1) { | ||
569 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
570 | &tex[1].pp_txoffset)) { | ||
571 | DRM_ERROR("Invalid texture offset for unit 1\n"); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | BEGIN_RING(9); | ||
576 | OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5)); | ||
577 | OUT_RING(tex[1].pp_txfilter); | ||
578 | OUT_RING(tex[1].pp_txformat); | ||
579 | OUT_RING(tex[1].pp_txoffset); | ||
580 | OUT_RING(tex[1].pp_txcblend); | ||
581 | OUT_RING(tex[1].pp_txablend); | ||
582 | OUT_RING(tex[1].pp_tfactor); | ||
583 | OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0)); | ||
584 | OUT_RING(tex[1].pp_border_color); | ||
585 | ADVANCE_RING(); | ||
586 | } | ||
587 | |||
588 | if (dirty & RADEON_UPLOAD_TEX2) { | ||
589 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, | ||
590 | &tex[2].pp_txoffset)) { | ||
591 | DRM_ERROR("Invalid texture offset for unit 2\n"); | ||
592 | return -EINVAL; | ||
593 | } | ||
594 | |||
595 | BEGIN_RING(9); | ||
596 | OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5)); | ||
597 | OUT_RING(tex[2].pp_txfilter); | ||
598 | OUT_RING(tex[2].pp_txformat); | ||
599 | OUT_RING(tex[2].pp_txoffset); | ||
600 | OUT_RING(tex[2].pp_txcblend); | ||
601 | OUT_RING(tex[2].pp_txablend); | ||
602 | OUT_RING(tex[2].pp_tfactor); | ||
603 | OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0)); | ||
604 | OUT_RING(tex[2].pp_border_color); | ||
605 | ADVANCE_RING(); | ||
606 | } | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | /* Emit 1.2 state | ||
612 | */ | ||
613 | static int radeon_emit_state2(drm_radeon_private_t * dev_priv, | ||
614 | struct drm_file *file_priv, | ||
615 | drm_radeon_state_t * state) | ||
616 | { | ||
617 | RING_LOCALS; | ||
618 | |||
619 | if (state->dirty & RADEON_UPLOAD_ZBIAS) { | ||
620 | BEGIN_RING(3); | ||
621 | OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1)); | ||
622 | OUT_RING(state->context2.se_zbias_factor); | ||
623 | OUT_RING(state->context2.se_zbias_constant); | ||
624 | ADVANCE_RING(); | ||
625 | } | ||
626 | |||
627 | return radeon_emit_state(dev_priv, file_priv, &state->context, | ||
628 | state->tex, state->dirty); | ||
629 | } | ||
630 | |||
631 | /* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in | ||
632 | * 1.3 cmdbuffers allow all previous state to be updated as well as | ||
633 | * the tcl scalar and vector areas. | ||
634 | */ | ||
635 | static struct { | ||
636 | int start; | ||
637 | int len; | ||
638 | const char *name; | ||
639 | } packet[RADEON_MAX_STATE_PACKETS] = { | ||
640 | {RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, | ||
641 | {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, | ||
642 | {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, | ||
643 | {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, | ||
644 | {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, | ||
645 | {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, | ||
646 | {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, | ||
647 | {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, | ||
648 | {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, | ||
649 | {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, | ||
650 | {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, | ||
651 | {RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, | ||
652 | {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, | ||
653 | {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, | ||
654 | {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, | ||
655 | {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, | ||
656 | {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, | ||
657 | {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, | ||
658 | {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, | ||
659 | {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, | ||
660 | {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, | ||
661 | "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, | ||
662 | {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, | ||
663 | {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, | ||
664 | {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, | ||
665 | {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, | ||
666 | {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, | ||
667 | {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, | ||
668 | {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, | ||
669 | {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, | ||
670 | {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, | ||
671 | {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, | ||
672 | {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, | ||
673 | {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, | ||
674 | {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, | ||
675 | {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, | ||
676 | {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, | ||
677 | {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, | ||
678 | {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, | ||
679 | {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, | ||
680 | {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, | ||
681 | {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, | ||
682 | {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, | ||
683 | {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, | ||
684 | {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, | ||
685 | {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, | ||
686 | {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, | ||
687 | {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, | ||
688 | {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, | ||
689 | {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, | ||
690 | {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, | ||
691 | "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, | ||
692 | {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, | ||
693 | {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, | ||
694 | {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, | ||
695 | {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, | ||
696 | {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, | ||
697 | {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, | ||
698 | {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, | ||
699 | {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, | ||
700 | {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, | ||
701 | {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, | ||
702 | {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, | ||
703 | "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, | ||
704 | {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ | ||
705 | {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ | ||
706 | {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, | ||
707 | {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, | ||
708 | {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, | ||
709 | {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, | ||
710 | {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, | ||
711 | {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, | ||
712 | {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, | ||
713 | {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, | ||
714 | {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, | ||
715 | {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, | ||
716 | {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, | ||
717 | {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, | ||
718 | {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, | ||
719 | {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, | ||
720 | {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, | ||
721 | {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, | ||
722 | {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, | ||
723 | {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, | ||
724 | {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, | ||
725 | {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, | ||
726 | {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, | ||
727 | {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, | ||
728 | {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ | ||
729 | {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, | ||
730 | {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, | ||
731 | {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, | ||
732 | {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, | ||
733 | {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, | ||
734 | {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, | ||
735 | {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, | ||
736 | {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, | ||
737 | {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, | ||
738 | }; | ||
739 | |||
740 | /* ================================================================ | ||
741 | * Performance monitoring functions | ||
742 | */ | ||
743 | |||
744 | static void radeon_clear_box(drm_radeon_private_t * dev_priv, | ||
745 | int x, int y, int w, int h, int r, int g, int b) | ||
746 | { | ||
747 | u32 color; | ||
748 | RING_LOCALS; | ||
749 | |||
750 | x += dev_priv->sarea_priv->boxes[0].x1; | ||
751 | y += dev_priv->sarea_priv->boxes[0].y1; | ||
752 | |||
753 | switch (dev_priv->color_fmt) { | ||
754 | case RADEON_COLOR_FORMAT_RGB565: | ||
755 | color = (((r & 0xf8) << 8) | | ||
756 | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); | ||
757 | break; | ||
758 | case RADEON_COLOR_FORMAT_ARGB8888: | ||
759 | default: | ||
760 | color = (((0xff) << 24) | (r << 16) | (g << 8) | b); | ||
761 | break; | ||
762 | } | ||
763 | |||
764 | BEGIN_RING(4); | ||
765 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
766 | OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); | ||
767 | OUT_RING(0xffffffff); | ||
768 | ADVANCE_RING(); | ||
769 | |||
770 | BEGIN_RING(6); | ||
771 | |||
772 | OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4)); | ||
773 | OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
774 | RADEON_GMC_BRUSH_SOLID_COLOR | | ||
775 | (dev_priv->color_fmt << 8) | | ||
776 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
777 | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); | ||
778 | |||
779 | if (dev_priv->sarea_priv->pfCurrentPage == 1) { | ||
780 | OUT_RING(dev_priv->front_pitch_offset); | ||
781 | } else { | ||
782 | OUT_RING(dev_priv->back_pitch_offset); | ||
783 | } | ||
784 | |||
785 | OUT_RING(color); | ||
786 | |||
787 | OUT_RING((x << 16) | y); | ||
788 | OUT_RING((w << 16) | h); | ||
789 | |||
790 | ADVANCE_RING(); | ||
791 | } | ||
792 | |||
793 | static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) | ||
794 | { | ||
795 | /* Collapse various things into a wait flag -- trying to | ||
796 | * guess if userspase slept -- better just to have them tell us. | ||
797 | */ | ||
798 | if (dev_priv->stats.last_frame_reads > 1 || | ||
799 | dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { | ||
800 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
801 | } | ||
802 | |||
803 | if (dev_priv->stats.freelist_loops) { | ||
804 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
805 | } | ||
806 | |||
807 | /* Purple box for page flipping | ||
808 | */ | ||
809 | if (dev_priv->stats.boxes & RADEON_BOX_FLIP) | ||
810 | radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255); | ||
811 | |||
812 | /* Red box if we have to wait for idle at any point | ||
813 | */ | ||
814 | if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) | ||
815 | radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0); | ||
816 | |||
817 | /* Blue box: lost context? | ||
818 | */ | ||
819 | |||
820 | /* Yellow box for texture swaps | ||
821 | */ | ||
822 | if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) | ||
823 | radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0); | ||
824 | |||
825 | /* Green box if hardware never idles (as far as we can tell) | ||
826 | */ | ||
827 | if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) | ||
828 | radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); | ||
829 | |||
830 | /* Draw bars indicating number of buffers allocated | ||
831 | * (not a great measure, easily confused) | ||
832 | */ | ||
833 | if (dev_priv->stats.requested_bufs) { | ||
834 | if (dev_priv->stats.requested_bufs > 100) | ||
835 | dev_priv->stats.requested_bufs = 100; | ||
836 | |||
837 | radeon_clear_box(dev_priv, 4, 16, | ||
838 | dev_priv->stats.requested_bufs, 4, | ||
839 | 196, 128, 128); | ||
840 | } | ||
841 | |||
842 | memset(&dev_priv->stats, 0, sizeof(dev_priv->stats)); | ||
843 | |||
844 | } | ||
845 | |||
846 | /* ================================================================ | ||
847 | * CP command dispatch functions | ||
848 | */ | ||
849 | |||
850 | static void radeon_cp_dispatch_clear(struct drm_device * dev, | ||
851 | drm_radeon_clear_t * clear, | ||
852 | drm_radeon_clear_rect_t * depth_boxes) | ||
853 | { | ||
854 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
855 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
856 | drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; | ||
857 | int nbox = sarea_priv->nbox; | ||
858 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
859 | unsigned int flags = clear->flags; | ||
860 | u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0; | ||
861 | int i; | ||
862 | RING_LOCALS; | ||
863 | DRM_DEBUG("flags = 0x%x\n", flags); | ||
864 | |||
865 | dev_priv->stats.clears++; | ||
866 | |||
867 | if (dev_priv->sarea_priv->pfCurrentPage == 1) { | ||
868 | unsigned int tmp = flags; | ||
869 | |||
870 | flags &= ~(RADEON_FRONT | RADEON_BACK); | ||
871 | if (tmp & RADEON_FRONT) | ||
872 | flags |= RADEON_BACK; | ||
873 | if (tmp & RADEON_BACK) | ||
874 | flags |= RADEON_FRONT; | ||
875 | } | ||
876 | |||
877 | if (flags & (RADEON_FRONT | RADEON_BACK)) { | ||
878 | |||
879 | BEGIN_RING(4); | ||
880 | |||
881 | /* Ensure the 3D stream is idle before doing a | ||
882 | * 2D fill to clear the front or back buffer. | ||
883 | */ | ||
884 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
885 | |||
886 | OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); | ||
887 | OUT_RING(clear->color_mask); | ||
888 | |||
889 | ADVANCE_RING(); | ||
890 | |||
891 | /* Make sure we restore the 3D state next time. | ||
892 | */ | ||
893 | dev_priv->sarea_priv->ctx_owner = 0; | ||
894 | |||
895 | for (i = 0; i < nbox; i++) { | ||
896 | int x = pbox[i].x1; | ||
897 | int y = pbox[i].y1; | ||
898 | int w = pbox[i].x2 - x; | ||
899 | int h = pbox[i].y2 - y; | ||
900 | |||
901 | DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n", | ||
902 | x, y, w, h, flags); | ||
903 | |||
904 | if (flags & RADEON_FRONT) { | ||
905 | BEGIN_RING(6); | ||
906 | |||
907 | OUT_RING(CP_PACKET3 | ||
908 | (RADEON_CNTL_PAINT_MULTI, 4)); | ||
909 | OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
910 | RADEON_GMC_BRUSH_SOLID_COLOR | | ||
911 | (dev_priv-> | ||
912 | color_fmt << 8) | | ||
913 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
914 | RADEON_ROP3_P | | ||
915 | RADEON_GMC_CLR_CMP_CNTL_DIS); | ||
916 | |||
917 | OUT_RING(dev_priv->front_pitch_offset); | ||
918 | OUT_RING(clear->clear_color); | ||
919 | |||
920 | OUT_RING((x << 16) | y); | ||
921 | OUT_RING((w << 16) | h); | ||
922 | |||
923 | ADVANCE_RING(); | ||
924 | } | ||
925 | |||
926 | if (flags & RADEON_BACK) { | ||
927 | BEGIN_RING(6); | ||
928 | |||
929 | OUT_RING(CP_PACKET3 | ||
930 | (RADEON_CNTL_PAINT_MULTI, 4)); | ||
931 | OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
932 | RADEON_GMC_BRUSH_SOLID_COLOR | | ||
933 | (dev_priv-> | ||
934 | color_fmt << 8) | | ||
935 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
936 | RADEON_ROP3_P | | ||
937 | RADEON_GMC_CLR_CMP_CNTL_DIS); | ||
938 | |||
939 | OUT_RING(dev_priv->back_pitch_offset); | ||
940 | OUT_RING(clear->clear_color); | ||
941 | |||
942 | OUT_RING((x << 16) | y); | ||
943 | OUT_RING((w << 16) | h); | ||
944 | |||
945 | ADVANCE_RING(); | ||
946 | } | ||
947 | } | ||
948 | } | ||
949 | |||
950 | /* hyper z clear */ | ||
951 | /* no docs available, based on reverse engeneering by Stephane Marchesin */ | ||
952 | if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) | ||
953 | && (flags & RADEON_CLEAR_FASTZ)) { | ||
954 | |||
955 | int i; | ||
956 | int depthpixperline = | ||
957 | dev_priv->depth_fmt == | ||
958 | RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch / | ||
959 | 2) : (dev_priv-> | ||
960 | depth_pitch / 4); | ||
961 | |||
962 | u32 clearmask; | ||
963 | |||
964 | u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth | | ||
965 | ((clear->depth_mask & 0xff) << 24); | ||
966 | |||
967 | /* Make sure we restore the 3D state next time. | ||
968 | * we haven't touched any "normal" state - still need this? | ||
969 | */ | ||
970 | dev_priv->sarea_priv->ctx_owner = 0; | ||
971 | |||
972 | if ((dev_priv->flags & RADEON_HAS_HIERZ) | ||
973 | && (flags & RADEON_USE_HIERZ)) { | ||
974 | /* FIXME : reverse engineer that for Rx00 cards */ | ||
975 | /* FIXME : the mask supposedly contains low-res z values. So can't set | ||
976 | just to the max (0xff? or actually 0x3fff?), need to take z clear | ||
977 | value into account? */ | ||
978 | /* pattern seems to work for r100, though get slight | ||
979 | rendering errors with glxgears. If hierz is not enabled for r100, | ||
980 | only 4 bits which indicate clear (15,16,31,32, all zero) matter, the | ||
981 | other ones are ignored, and the same clear mask can be used. That's | ||
982 | very different behaviour than R200 which needs different clear mask | ||
983 | and different number of tiles to clear if hierz is enabled or not !?! | ||
984 | */ | ||
985 | clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f; | ||
986 | } else { | ||
987 | /* clear mask : chooses the clearing pattern. | ||
988 | rv250: could be used to clear only parts of macrotiles | ||
989 | (but that would get really complicated...)? | ||
990 | bit 0 and 1 (either or both of them ?!?!) are used to | ||
991 | not clear tile (or maybe one of the bits indicates if the tile is | ||
992 | compressed or not), bit 2 and 3 to not clear tile 1,...,. | ||
993 | Pattern is as follows: | ||
994 | | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29| | ||
995 | bits ------------------------------------------------- | ||
996 | | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31| | ||
997 | rv100: clearmask covers 2x8 4x1 tiles, but one clear still | ||
998 | covers 256 pixels ?!? | ||
999 | */ | ||
1000 | clearmask = 0x0; | ||
1001 | } | ||
1002 | |||
1003 | BEGIN_RING(8); | ||
1004 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1005 | OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE, | ||
1006 | tempRB3D_DEPTHCLEARVALUE); | ||
1007 | /* what offset is this exactly ? */ | ||
1008 | OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0); | ||
1009 | /* need ctlstat, otherwise get some strange black flickering */ | ||
1010 | OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT, | ||
1011 | RADEON_RB3D_ZC_FLUSH_ALL); | ||
1012 | ADVANCE_RING(); | ||
1013 | |||
1014 | for (i = 0; i < nbox; i++) { | ||
1015 | int tileoffset, nrtilesx, nrtilesy, j; | ||
1016 | /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ | ||
1017 | if ((dev_priv->flags & RADEON_HAS_HIERZ) | ||
1018 | && !(dev_priv->microcode_version == UCODE_R200)) { | ||
1019 | /* FIXME : figure this out for r200 (when hierz is enabled). Or | ||
1020 | maybe r200 actually doesn't need to put the low-res z value into | ||
1021 | the tile cache like r100, but just needs to clear the hi-level z-buffer? | ||
1022 | Works for R100, both with hierz and without. | ||
1023 | R100 seems to operate on 2x1 8x8 tiles, but... | ||
1024 | odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially | ||
1025 | problematic with resolutions which are not 64 pix aligned? */ | ||
1026 | tileoffset = | ||
1027 | ((pbox[i].y1 >> 3) * depthpixperline + | ||
1028 | pbox[i].x1) >> 6; | ||
1029 | nrtilesx = | ||
1030 | ((pbox[i].x2 & ~63) - | ||
1031 | (pbox[i].x1 & ~63)) >> 4; | ||
1032 | nrtilesy = | ||
1033 | (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); | ||
1034 | for (j = 0; j <= nrtilesy; j++) { | ||
1035 | BEGIN_RING(4); | ||
1036 | OUT_RING(CP_PACKET3 | ||
1037 | (RADEON_3D_CLEAR_ZMASK, 2)); | ||
1038 | /* first tile */ | ||
1039 | OUT_RING(tileoffset * 8); | ||
1040 | /* the number of tiles to clear */ | ||
1041 | OUT_RING(nrtilesx + 4); | ||
1042 | /* clear mask : chooses the clearing pattern. */ | ||
1043 | OUT_RING(clearmask); | ||
1044 | ADVANCE_RING(); | ||
1045 | tileoffset += depthpixperline >> 6; | ||
1046 | } | ||
1047 | } else if (dev_priv->microcode_version == UCODE_R200) { | ||
1048 | /* works for rv250. */ | ||
1049 | /* find first macro tile (8x2 4x4 z-pixels on rv250) */ | ||
1050 | tileoffset = | ||
1051 | ((pbox[i].y1 >> 3) * depthpixperline + | ||
1052 | pbox[i].x1) >> 5; | ||
1053 | nrtilesx = | ||
1054 | (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5); | ||
1055 | nrtilesy = | ||
1056 | (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); | ||
1057 | for (j = 0; j <= nrtilesy; j++) { | ||
1058 | BEGIN_RING(4); | ||
1059 | OUT_RING(CP_PACKET3 | ||
1060 | (RADEON_3D_CLEAR_ZMASK, 2)); | ||
1061 | /* first tile */ | ||
1062 | /* judging by the first tile offset needed, could possibly | ||
1063 | directly address/clear 4x4 tiles instead of 8x2 * 4x4 | ||
1064 | macro tiles, though would still need clear mask for | ||
1065 | right/bottom if truely 4x4 granularity is desired ? */ | ||
1066 | OUT_RING(tileoffset * 16); | ||
1067 | /* the number of tiles to clear */ | ||
1068 | OUT_RING(nrtilesx + 1); | ||
1069 | /* clear mask : chooses the clearing pattern. */ | ||
1070 | OUT_RING(clearmask); | ||
1071 | ADVANCE_RING(); | ||
1072 | tileoffset += depthpixperline >> 5; | ||
1073 | } | ||
1074 | } else { /* rv 100 */ | ||
1075 | /* rv100 might not need 64 pix alignment, who knows */ | ||
1076 | /* offsets are, hmm, weird */ | ||
1077 | tileoffset = | ||
1078 | ((pbox[i].y1 >> 4) * depthpixperline + | ||
1079 | pbox[i].x1) >> 6; | ||
1080 | nrtilesx = | ||
1081 | ((pbox[i].x2 & ~63) - | ||
1082 | (pbox[i].x1 & ~63)) >> 4; | ||
1083 | nrtilesy = | ||
1084 | (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4); | ||
1085 | for (j = 0; j <= nrtilesy; j++) { | ||
1086 | BEGIN_RING(4); | ||
1087 | OUT_RING(CP_PACKET3 | ||
1088 | (RADEON_3D_CLEAR_ZMASK, 2)); | ||
1089 | OUT_RING(tileoffset * 128); | ||
1090 | /* the number of tiles to clear */ | ||
1091 | OUT_RING(nrtilesx + 4); | ||
1092 | /* clear mask : chooses the clearing pattern. */ | ||
1093 | OUT_RING(clearmask); | ||
1094 | ADVANCE_RING(); | ||
1095 | tileoffset += depthpixperline >> 6; | ||
1096 | } | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | /* TODO don't always clear all hi-level z tiles */ | ||
1101 | if ((dev_priv->flags & RADEON_HAS_HIERZ) | ||
1102 | && (dev_priv->microcode_version == UCODE_R200) | ||
1103 | && (flags & RADEON_USE_HIERZ)) | ||
1104 | /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ | ||
1105 | /* FIXME : the mask supposedly contains low-res z values. So can't set | ||
1106 | just to the max (0xff? or actually 0x3fff?), need to take z clear | ||
1107 | value into account? */ | ||
1108 | { | ||
1109 | BEGIN_RING(4); | ||
1110 | OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2)); | ||
1111 | OUT_RING(0x0); /* First tile */ | ||
1112 | OUT_RING(0x3cc0); | ||
1113 | OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f); | ||
1114 | ADVANCE_RING(); | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | /* We have to clear the depth and/or stencil buffers by | ||
1119 | * rendering a quad into just those buffers. Thus, we have to | ||
1120 | * make sure the 3D engine is configured correctly. | ||
1121 | */ | ||
1122 | else if ((dev_priv->microcode_version == UCODE_R200) && | ||
1123 | (flags & (RADEON_DEPTH | RADEON_STENCIL))) { | ||
1124 | |||
1125 | int tempPP_CNTL; | ||
1126 | int tempRE_CNTL; | ||
1127 | int tempRB3D_CNTL; | ||
1128 | int tempRB3D_ZSTENCILCNTL; | ||
1129 | int tempRB3D_STENCILREFMASK; | ||
1130 | int tempRB3D_PLANEMASK; | ||
1131 | int tempSE_CNTL; | ||
1132 | int tempSE_VTE_CNTL; | ||
1133 | int tempSE_VTX_FMT_0; | ||
1134 | int tempSE_VTX_FMT_1; | ||
1135 | int tempSE_VAP_CNTL; | ||
1136 | int tempRE_AUX_SCISSOR_CNTL; | ||
1137 | |||
1138 | tempPP_CNTL = 0; | ||
1139 | tempRE_CNTL = 0; | ||
1140 | |||
1141 | tempRB3D_CNTL = depth_clear->rb3d_cntl; | ||
1142 | |||
1143 | tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; | ||
1144 | tempRB3D_STENCILREFMASK = 0x0; | ||
1145 | |||
1146 | tempSE_CNTL = depth_clear->se_cntl; | ||
1147 | |||
1148 | /* Disable TCL */ | ||
1149 | |||
1150 | tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ | ||
1151 | (0x9 << | ||
1152 | SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); | ||
1153 | |||
1154 | tempRB3D_PLANEMASK = 0x0; | ||
1155 | |||
1156 | tempRE_AUX_SCISSOR_CNTL = 0x0; | ||
1157 | |||
1158 | tempSE_VTE_CNTL = | ||
1159 | SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK; | ||
1160 | |||
1161 | /* Vertex format (X, Y, Z, W) */ | ||
1162 | tempSE_VTX_FMT_0 = | ||
1163 | SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | | ||
1164 | SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; | ||
1165 | tempSE_VTX_FMT_1 = 0x0; | ||
1166 | |||
1167 | /* | ||
1168 | * Depth buffer specific enables | ||
1169 | */ | ||
1170 | if (flags & RADEON_DEPTH) { | ||
1171 | /* Enable depth buffer */ | ||
1172 | tempRB3D_CNTL |= RADEON_Z_ENABLE; | ||
1173 | } else { | ||
1174 | /* Disable depth buffer */ | ||
1175 | tempRB3D_CNTL &= ~RADEON_Z_ENABLE; | ||
1176 | } | ||
1177 | |||
1178 | /* | ||
1179 | * Stencil buffer specific enables | ||
1180 | */ | ||
1181 | if (flags & RADEON_STENCIL) { | ||
1182 | tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; | ||
1183 | tempRB3D_STENCILREFMASK = clear->depth_mask; | ||
1184 | } else { | ||
1185 | tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; | ||
1186 | tempRB3D_STENCILREFMASK = 0x00000000; | ||
1187 | } | ||
1188 | |||
1189 | if (flags & RADEON_USE_COMP_ZBUF) { | ||
1190 | tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | | ||
1191 | RADEON_Z_DECOMPRESSION_ENABLE; | ||
1192 | } | ||
1193 | if (flags & RADEON_USE_HIERZ) { | ||
1194 | tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; | ||
1195 | } | ||
1196 | |||
1197 | BEGIN_RING(26); | ||
1198 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1199 | |||
1200 | OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL); | ||
1201 | OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL); | ||
1202 | OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL); | ||
1203 | OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); | ||
1204 | OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, | ||
1205 | tempRB3D_STENCILREFMASK); | ||
1206 | OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK); | ||
1207 | OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL); | ||
1208 | OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL); | ||
1209 | OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0); | ||
1210 | OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1); | ||
1211 | OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL); | ||
1212 | OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL); | ||
1213 | ADVANCE_RING(); | ||
1214 | |||
1215 | /* Make sure we restore the 3D state next time. | ||
1216 | */ | ||
1217 | dev_priv->sarea_priv->ctx_owner = 0; | ||
1218 | |||
1219 | for (i = 0; i < nbox; i++) { | ||
1220 | |||
1221 | /* Funny that this should be required -- | ||
1222 | * sets top-left? | ||
1223 | */ | ||
1224 | radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); | ||
1225 | |||
1226 | BEGIN_RING(14); | ||
1227 | OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12)); | ||
1228 | OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | | ||
1229 | RADEON_PRIM_WALK_RING | | ||
1230 | (3 << RADEON_NUM_VERTICES_SHIFT))); | ||
1231 | OUT_RING(depth_boxes[i].ui[CLEAR_X1]); | ||
1232 | OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); | ||
1233 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1234 | OUT_RING(0x3f800000); | ||
1235 | OUT_RING(depth_boxes[i].ui[CLEAR_X1]); | ||
1236 | OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); | ||
1237 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1238 | OUT_RING(0x3f800000); | ||
1239 | OUT_RING(depth_boxes[i].ui[CLEAR_X2]); | ||
1240 | OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); | ||
1241 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1242 | OUT_RING(0x3f800000); | ||
1243 | ADVANCE_RING(); | ||
1244 | } | ||
1245 | } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) { | ||
1246 | |||
1247 | int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; | ||
1248 | |||
1249 | rb3d_cntl = depth_clear->rb3d_cntl; | ||
1250 | |||
1251 | if (flags & RADEON_DEPTH) { | ||
1252 | rb3d_cntl |= RADEON_Z_ENABLE; | ||
1253 | } else { | ||
1254 | rb3d_cntl &= ~RADEON_Z_ENABLE; | ||
1255 | } | ||
1256 | |||
1257 | if (flags & RADEON_STENCIL) { | ||
1258 | rb3d_cntl |= RADEON_STENCIL_ENABLE; | ||
1259 | rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ | ||
1260 | } else { | ||
1261 | rb3d_cntl &= ~RADEON_STENCIL_ENABLE; | ||
1262 | rb3d_stencilrefmask = 0x00000000; | ||
1263 | } | ||
1264 | |||
1265 | if (flags & RADEON_USE_COMP_ZBUF) { | ||
1266 | tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | | ||
1267 | RADEON_Z_DECOMPRESSION_ENABLE; | ||
1268 | } | ||
1269 | if (flags & RADEON_USE_HIERZ) { | ||
1270 | tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; | ||
1271 | } | ||
1272 | |||
1273 | BEGIN_RING(13); | ||
1274 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1275 | |||
1276 | OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1)); | ||
1277 | OUT_RING(0x00000000); | ||
1278 | OUT_RING(rb3d_cntl); | ||
1279 | |||
1280 | OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); | ||
1281 | OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask); | ||
1282 | OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000); | ||
1283 | OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl); | ||
1284 | ADVANCE_RING(); | ||
1285 | |||
1286 | /* Make sure we restore the 3D state next time. | ||
1287 | */ | ||
1288 | dev_priv->sarea_priv->ctx_owner = 0; | ||
1289 | |||
1290 | for (i = 0; i < nbox; i++) { | ||
1291 | |||
1292 | /* Funny that this should be required -- | ||
1293 | * sets top-left? | ||
1294 | */ | ||
1295 | radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); | ||
1296 | |||
1297 | BEGIN_RING(15); | ||
1298 | |||
1299 | OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13)); | ||
1300 | OUT_RING(RADEON_VTX_Z_PRESENT | | ||
1301 | RADEON_VTX_PKCOLOR_PRESENT); | ||
1302 | OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | | ||
1303 | RADEON_PRIM_WALK_RING | | ||
1304 | RADEON_MAOS_ENABLE | | ||
1305 | RADEON_VTX_FMT_RADEON_MODE | | ||
1306 | (3 << RADEON_NUM_VERTICES_SHIFT))); | ||
1307 | |||
1308 | OUT_RING(depth_boxes[i].ui[CLEAR_X1]); | ||
1309 | OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); | ||
1310 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1311 | OUT_RING(0x0); | ||
1312 | |||
1313 | OUT_RING(depth_boxes[i].ui[CLEAR_X1]); | ||
1314 | OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); | ||
1315 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1316 | OUT_RING(0x0); | ||
1317 | |||
1318 | OUT_RING(depth_boxes[i].ui[CLEAR_X2]); | ||
1319 | OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); | ||
1320 | OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); | ||
1321 | OUT_RING(0x0); | ||
1322 | |||
1323 | ADVANCE_RING(); | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1327 | /* Increment the clear counter. The client-side 3D driver must | ||
1328 | * wait on this value before performing the clear ioctl. We | ||
1329 | * need this because the card's so damned fast... | ||
1330 | */ | ||
1331 | dev_priv->sarea_priv->last_clear++; | ||
1332 | |||
1333 | BEGIN_RING(4); | ||
1334 | |||
1335 | RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear); | ||
1336 | RADEON_WAIT_UNTIL_IDLE(); | ||
1337 | |||
1338 | ADVANCE_RING(); | ||
1339 | } | ||
1340 | |||
1341 | static void radeon_cp_dispatch_swap(struct drm_device * dev) | ||
1342 | { | ||
1343 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1344 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
1345 | int nbox = sarea_priv->nbox; | ||
1346 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
1347 | int i; | ||
1348 | RING_LOCALS; | ||
1349 | DRM_DEBUG("\n"); | ||
1350 | |||
1351 | /* Do some trivial performance monitoring... | ||
1352 | */ | ||
1353 | if (dev_priv->do_boxes) | ||
1354 | radeon_cp_performance_boxes(dev_priv); | ||
1355 | |||
1356 | /* Wait for the 3D stream to idle before dispatching the bitblt. | ||
1357 | * This will prevent data corruption between the two streams. | ||
1358 | */ | ||
1359 | BEGIN_RING(2); | ||
1360 | |||
1361 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
1362 | |||
1363 | ADVANCE_RING(); | ||
1364 | |||
1365 | for (i = 0; i < nbox; i++) { | ||
1366 | int x = pbox[i].x1; | ||
1367 | int y = pbox[i].y1; | ||
1368 | int w = pbox[i].x2 - x; | ||
1369 | int h = pbox[i].y2 - y; | ||
1370 | |||
1371 | DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); | ||
1372 | |||
1373 | BEGIN_RING(9); | ||
1374 | |||
1375 | OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); | ||
1376 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | ||
1377 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
1378 | RADEON_GMC_BRUSH_NONE | | ||
1379 | (dev_priv->color_fmt << 8) | | ||
1380 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
1381 | RADEON_ROP3_S | | ||
1382 | RADEON_DP_SRC_SOURCE_MEMORY | | ||
1383 | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); | ||
1384 | |||
1385 | /* Make this work even if front & back are flipped: | ||
1386 | */ | ||
1387 | OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); | ||
1388 | if (dev_priv->sarea_priv->pfCurrentPage == 0) { | ||
1389 | OUT_RING(dev_priv->back_pitch_offset); | ||
1390 | OUT_RING(dev_priv->front_pitch_offset); | ||
1391 | } else { | ||
1392 | OUT_RING(dev_priv->front_pitch_offset); | ||
1393 | OUT_RING(dev_priv->back_pitch_offset); | ||
1394 | } | ||
1395 | |||
1396 | OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); | ||
1397 | OUT_RING((x << 16) | y); | ||
1398 | OUT_RING((x << 16) | y); | ||
1399 | OUT_RING((w << 16) | h); | ||
1400 | |||
1401 | ADVANCE_RING(); | ||
1402 | } | ||
1403 | |||
1404 | /* Increment the frame counter. The client-side 3D driver must | ||
1405 | * throttle the framerate by waiting for this value before | ||
1406 | * performing the swapbuffer ioctl. | ||
1407 | */ | ||
1408 | dev_priv->sarea_priv->last_frame++; | ||
1409 | |||
1410 | BEGIN_RING(4); | ||
1411 | |||
1412 | RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); | ||
1413 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1414 | |||
1415 | ADVANCE_RING(); | ||
1416 | } | ||
1417 | |||
1418 | static void radeon_cp_dispatch_flip(struct drm_device * dev) | ||
1419 | { | ||
1420 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1421 | struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle; | ||
1422 | int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) | ||
1423 | ? dev_priv->front_offset : dev_priv->back_offset; | ||
1424 | RING_LOCALS; | ||
1425 | DRM_DEBUG("pfCurrentPage=%d\n", | ||
1426 | dev_priv->sarea_priv->pfCurrentPage); | ||
1427 | |||
1428 | /* Do some trivial performance monitoring... | ||
1429 | */ | ||
1430 | if (dev_priv->do_boxes) { | ||
1431 | dev_priv->stats.boxes |= RADEON_BOX_FLIP; | ||
1432 | radeon_cp_performance_boxes(dev_priv); | ||
1433 | } | ||
1434 | |||
1435 | /* Update the frame offsets for both CRTCs | ||
1436 | */ | ||
1437 | BEGIN_RING(6); | ||
1438 | |||
1439 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
1440 | OUT_RING_REG(RADEON_CRTC_OFFSET, | ||
1441 | ((sarea->frame.y * dev_priv->front_pitch + | ||
1442 | sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) | ||
1443 | + offset); | ||
1444 | OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base | ||
1445 | + offset); | ||
1446 | |||
1447 | ADVANCE_RING(); | ||
1448 | |||
1449 | /* Increment the frame counter. The client-side 3D driver must | ||
1450 | * throttle the framerate by waiting for this value before | ||
1451 | * performing the swapbuffer ioctl. | ||
1452 | */ | ||
1453 | dev_priv->sarea_priv->last_frame++; | ||
1454 | dev_priv->sarea_priv->pfCurrentPage = | ||
1455 | 1 - dev_priv->sarea_priv->pfCurrentPage; | ||
1456 | |||
1457 | BEGIN_RING(2); | ||
1458 | |||
1459 | RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); | ||
1460 | |||
1461 | ADVANCE_RING(); | ||
1462 | } | ||
1463 | |||
1464 | static int bad_prim_vertex_nr(int primitive, int nr) | ||
1465 | { | ||
1466 | switch (primitive & RADEON_PRIM_TYPE_MASK) { | ||
1467 | case RADEON_PRIM_TYPE_NONE: | ||
1468 | case RADEON_PRIM_TYPE_POINT: | ||
1469 | return nr < 1; | ||
1470 | case RADEON_PRIM_TYPE_LINE: | ||
1471 | return (nr & 1) || nr == 0; | ||
1472 | case RADEON_PRIM_TYPE_LINE_STRIP: | ||
1473 | return nr < 2; | ||
1474 | case RADEON_PRIM_TYPE_TRI_LIST: | ||
1475 | case RADEON_PRIM_TYPE_3VRT_POINT_LIST: | ||
1476 | case RADEON_PRIM_TYPE_3VRT_LINE_LIST: | ||
1477 | case RADEON_PRIM_TYPE_RECT_LIST: | ||
1478 | return nr % 3 || nr == 0; | ||
1479 | case RADEON_PRIM_TYPE_TRI_FAN: | ||
1480 | case RADEON_PRIM_TYPE_TRI_STRIP: | ||
1481 | return nr < 3; | ||
1482 | default: | ||
1483 | return 1; | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | typedef struct { | ||
1488 | unsigned int start; | ||
1489 | unsigned int finish; | ||
1490 | unsigned int prim; | ||
1491 | unsigned int numverts; | ||
1492 | unsigned int offset; | ||
1493 | unsigned int vc_format; | ||
1494 | } drm_radeon_tcl_prim_t; | ||
1495 | |||
1496 | static void radeon_cp_dispatch_vertex(struct drm_device * dev, | ||
1497 | struct drm_buf * buf, | ||
1498 | drm_radeon_tcl_prim_t * prim) | ||
1499 | { | ||
1500 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1501 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
1502 | int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; | ||
1503 | int numverts = (int)prim->numverts; | ||
1504 | int nbox = sarea_priv->nbox; | ||
1505 | int i = 0; | ||
1506 | RING_LOCALS; | ||
1507 | |||
1508 | DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", | ||
1509 | prim->prim, | ||
1510 | prim->vc_format, prim->start, prim->finish, prim->numverts); | ||
1511 | |||
1512 | if (bad_prim_vertex_nr(prim->prim, prim->numverts)) { | ||
1513 | DRM_ERROR("bad prim %x numverts %d\n", | ||
1514 | prim->prim, prim->numverts); | ||
1515 | return; | ||
1516 | } | ||
1517 | |||
1518 | do { | ||
1519 | /* Emit the next cliprect */ | ||
1520 | if (i < nbox) { | ||
1521 | radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); | ||
1522 | } | ||
1523 | |||
1524 | /* Emit the vertex buffer rendering commands */ | ||
1525 | BEGIN_RING(5); | ||
1526 | |||
1527 | OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3)); | ||
1528 | OUT_RING(offset); | ||
1529 | OUT_RING(numverts); | ||
1530 | OUT_RING(prim->vc_format); | ||
1531 | OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST | | ||
1532 | RADEON_COLOR_ORDER_RGBA | | ||
1533 | RADEON_VTX_FMT_RADEON_MODE | | ||
1534 | (numverts << RADEON_NUM_VERTICES_SHIFT)); | ||
1535 | |||
1536 | ADVANCE_RING(); | ||
1537 | |||
1538 | i++; | ||
1539 | } while (i < nbox); | ||
1540 | } | ||
1541 | |||
1542 | static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf) | ||
1543 | { | ||
1544 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1545 | drm_radeon_buf_priv_t *buf_priv = buf->dev_private; | ||
1546 | RING_LOCALS; | ||
1547 | |||
1548 | buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; | ||
1549 | |||
1550 | /* Emit the vertex buffer age */ | ||
1551 | BEGIN_RING(2); | ||
1552 | RADEON_DISPATCH_AGE(buf_priv->age); | ||
1553 | ADVANCE_RING(); | ||
1554 | |||
1555 | buf->pending = 1; | ||
1556 | buf->used = 0; | ||
1557 | } | ||
1558 | |||
1559 | static void radeon_cp_dispatch_indirect(struct drm_device * dev, | ||
1560 | struct drm_buf * buf, int start, int end) | ||
1561 | { | ||
1562 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1563 | RING_LOCALS; | ||
1564 | DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); | ||
1565 | |||
1566 | if (start != end) { | ||
1567 | int offset = (dev_priv->gart_buffers_offset | ||
1568 | + buf->offset + start); | ||
1569 | int dwords = (end - start + 3) / sizeof(u32); | ||
1570 | |||
1571 | /* Indirect buffer data must be an even number of | ||
1572 | * dwords, so if we've been given an odd number we must | ||
1573 | * pad the data with a Type-2 CP packet. | ||
1574 | */ | ||
1575 | if (dwords & 1) { | ||
1576 | u32 *data = (u32 *) | ||
1577 | ((char *)dev->agp_buffer_map->handle | ||
1578 | + buf->offset + start); | ||
1579 | data[dwords++] = RADEON_CP_PACKET2; | ||
1580 | } | ||
1581 | |||
1582 | /* Fire off the indirect buffer */ | ||
1583 | BEGIN_RING(3); | ||
1584 | |||
1585 | OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); | ||
1586 | OUT_RING(offset); | ||
1587 | OUT_RING(dwords); | ||
1588 | |||
1589 | ADVANCE_RING(); | ||
1590 | } | ||
1591 | } | ||
1592 | |||
1593 | static void radeon_cp_dispatch_indices(struct drm_device * dev, | ||
1594 | struct drm_buf * elt_buf, | ||
1595 | drm_radeon_tcl_prim_t * prim) | ||
1596 | { | ||
1597 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1598 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
1599 | int offset = dev_priv->gart_buffers_offset + prim->offset; | ||
1600 | u32 *data; | ||
1601 | int dwords; | ||
1602 | int i = 0; | ||
1603 | int start = prim->start + RADEON_INDEX_PRIM_OFFSET; | ||
1604 | int count = (prim->finish - start) / sizeof(u16); | ||
1605 | int nbox = sarea_priv->nbox; | ||
1606 | |||
1607 | DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", | ||
1608 | prim->prim, | ||
1609 | prim->vc_format, | ||
1610 | prim->start, prim->finish, prim->offset, prim->numverts); | ||
1611 | |||
1612 | if (bad_prim_vertex_nr(prim->prim, count)) { | ||
1613 | DRM_ERROR("bad prim %x count %d\n", prim->prim, count); | ||
1614 | return; | ||
1615 | } | ||
1616 | |||
1617 | if (start >= prim->finish || (prim->start & 0x7)) { | ||
1618 | DRM_ERROR("buffer prim %d\n", prim->prim); | ||
1619 | return; | ||
1620 | } | ||
1621 | |||
1622 | dwords = (prim->finish - prim->start + 3) / sizeof(u32); | ||
1623 | |||
1624 | data = (u32 *) ((char *)dev->agp_buffer_map->handle + | ||
1625 | elt_buf->offset + prim->start); | ||
1626 | |||
1627 | data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2); | ||
1628 | data[1] = offset; | ||
1629 | data[2] = prim->numverts; | ||
1630 | data[3] = prim->vc_format; | ||
1631 | data[4] = (prim->prim | | ||
1632 | RADEON_PRIM_WALK_IND | | ||
1633 | RADEON_COLOR_ORDER_RGBA | | ||
1634 | RADEON_VTX_FMT_RADEON_MODE | | ||
1635 | (count << RADEON_NUM_VERTICES_SHIFT)); | ||
1636 | |||
1637 | do { | ||
1638 | if (i < nbox) | ||
1639 | radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); | ||
1640 | |||
1641 | radeon_cp_dispatch_indirect(dev, elt_buf, | ||
1642 | prim->start, prim->finish); | ||
1643 | |||
1644 | i++; | ||
1645 | } while (i < nbox); | ||
1646 | |||
1647 | } | ||
1648 | |||
1649 | #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE | ||
1650 | |||
1651 | static int radeon_cp_dispatch_texture(struct drm_device * dev, | ||
1652 | struct drm_file *file_priv, | ||
1653 | drm_radeon_texture_t * tex, | ||
1654 | drm_radeon_tex_image_t * image) | ||
1655 | { | ||
1656 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1657 | struct drm_buf *buf; | ||
1658 | u32 format; | ||
1659 | u32 *buffer; | ||
1660 | const u8 __user *data; | ||
1661 | int size, dwords, tex_width, blit_width, spitch; | ||
1662 | u32 height; | ||
1663 | int i; | ||
1664 | u32 texpitch, microtile; | ||
1665 | u32 offset, byte_offset; | ||
1666 | RING_LOCALS; | ||
1667 | |||
1668 | if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { | ||
1669 | DRM_ERROR("Invalid destination offset\n"); | ||
1670 | return -EINVAL; | ||
1671 | } | ||
1672 | |||
1673 | dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; | ||
1674 | |||
1675 | /* Flush the pixel cache. This ensures no pixel data gets mixed | ||
1676 | * up with the texture data from the host data blit, otherwise | ||
1677 | * part of the texture image may be corrupted. | ||
1678 | */ | ||
1679 | BEGIN_RING(4); | ||
1680 | RADEON_FLUSH_CACHE(); | ||
1681 | RADEON_WAIT_UNTIL_IDLE(); | ||
1682 | ADVANCE_RING(); | ||
1683 | |||
1684 | /* The compiler won't optimize away a division by a variable, | ||
1685 | * even if the only legal values are powers of two. Thus, we'll | ||
1686 | * use a shift instead. | ||
1687 | */ | ||
1688 | switch (tex->format) { | ||
1689 | case RADEON_TXFORMAT_ARGB8888: | ||
1690 | case RADEON_TXFORMAT_RGBA8888: | ||
1691 | format = RADEON_COLOR_FORMAT_ARGB8888; | ||
1692 | tex_width = tex->width * 4; | ||
1693 | blit_width = image->width * 4; | ||
1694 | break; | ||
1695 | case RADEON_TXFORMAT_AI88: | ||
1696 | case RADEON_TXFORMAT_ARGB1555: | ||
1697 | case RADEON_TXFORMAT_RGB565: | ||
1698 | case RADEON_TXFORMAT_ARGB4444: | ||
1699 | case RADEON_TXFORMAT_VYUY422: | ||
1700 | case RADEON_TXFORMAT_YVYU422: | ||
1701 | format = RADEON_COLOR_FORMAT_RGB565; | ||
1702 | tex_width = tex->width * 2; | ||
1703 | blit_width = image->width * 2; | ||
1704 | break; | ||
1705 | case RADEON_TXFORMAT_I8: | ||
1706 | case RADEON_TXFORMAT_RGB332: | ||
1707 | format = RADEON_COLOR_FORMAT_CI8; | ||
1708 | tex_width = tex->width * 1; | ||
1709 | blit_width = image->width * 1; | ||
1710 | break; | ||
1711 | default: | ||
1712 | DRM_ERROR("invalid texture format %d\n", tex->format); | ||
1713 | return -EINVAL; | ||
1714 | } | ||
1715 | spitch = blit_width >> 6; | ||
1716 | if (spitch == 0 && image->height > 1) | ||
1717 | return -EINVAL; | ||
1718 | |||
1719 | texpitch = tex->pitch; | ||
1720 | if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { | ||
1721 | microtile = 1; | ||
1722 | if (tex_width < 64) { | ||
1723 | texpitch &= ~(RADEON_DST_TILE_MICRO >> 22); | ||
1724 | /* we got tiled coordinates, untile them */ | ||
1725 | image->x *= 2; | ||
1726 | } | ||
1727 | } else | ||
1728 | microtile = 0; | ||
1729 | |||
1730 | /* this might fail for zero-sized uploads - are those illegal? */ | ||
1731 | if (!radeon_check_offset(dev_priv, tex->offset + image->height * | ||
1732 | blit_width - 1)) { | ||
1733 | DRM_ERROR("Invalid final destination offset\n"); | ||
1734 | return -EINVAL; | ||
1735 | } | ||
1736 | |||
1737 | DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); | ||
1738 | |||
1739 | do { | ||
1740 | DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", | ||
1741 | tex->offset >> 10, tex->pitch, tex->format, | ||
1742 | image->x, image->y, image->width, image->height); | ||
1743 | |||
1744 | /* Make a copy of some parameters in case we have to | ||
1745 | * update them for a multi-pass texture blit. | ||
1746 | */ | ||
1747 | height = image->height; | ||
1748 | data = (const u8 __user *)image->data; | ||
1749 | |||
1750 | size = height * blit_width; | ||
1751 | |||
1752 | if (size > RADEON_MAX_TEXTURE_SIZE) { | ||
1753 | height = RADEON_MAX_TEXTURE_SIZE / blit_width; | ||
1754 | size = height * blit_width; | ||
1755 | } else if (size < 4 && size > 0) { | ||
1756 | size = 4; | ||
1757 | } else if (size == 0) { | ||
1758 | return 0; | ||
1759 | } | ||
1760 | |||
1761 | buf = radeon_freelist_get(dev); | ||
1762 | if (0 && !buf) { | ||
1763 | radeon_do_cp_idle(dev_priv); | ||
1764 | buf = radeon_freelist_get(dev); | ||
1765 | } | ||
1766 | if (!buf) { | ||
1767 | DRM_DEBUG("EAGAIN\n"); | ||
1768 | if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) | ||
1769 | return -EFAULT; | ||
1770 | return -EAGAIN; | ||
1771 | } | ||
1772 | |||
1773 | /* Dispatch the indirect buffer. | ||
1774 | */ | ||
1775 | buffer = | ||
1776 | (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); | ||
1777 | dwords = size / 4; | ||
1778 | |||
1779 | #define RADEON_COPY_MT(_buf, _data, _width) \ | ||
1780 | do { \ | ||
1781 | if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ | ||
1782 | DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ | ||
1783 | return -EFAULT; \ | ||
1784 | } \ | ||
1785 | } while(0) | ||
1786 | |||
1787 | if (microtile) { | ||
1788 | /* texture micro tiling in use, minimum texture width is thus 16 bytes. | ||
1789 | however, we cannot use blitter directly for texture width < 64 bytes, | ||
1790 | since minimum tex pitch is 64 bytes and we need this to match | ||
1791 | the texture width, otherwise the blitter will tile it wrong. | ||
1792 | Thus, tiling manually in this case. Additionally, need to special | ||
1793 | case tex height = 1, since our actual image will have height 2 | ||
1794 | and we need to ensure we don't read beyond the texture size | ||
1795 | from user space. */ | ||
1796 | if (tex->height == 1) { | ||
1797 | if (tex_width >= 64 || tex_width <= 16) { | ||
1798 | RADEON_COPY_MT(buffer, data, | ||
1799 | (int)(tex_width * sizeof(u32))); | ||
1800 | } else if (tex_width == 32) { | ||
1801 | RADEON_COPY_MT(buffer, data, 16); | ||
1802 | RADEON_COPY_MT(buffer + 8, | ||
1803 | data + 16, 16); | ||
1804 | } | ||
1805 | } else if (tex_width >= 64 || tex_width == 16) { | ||
1806 | RADEON_COPY_MT(buffer, data, | ||
1807 | (int)(dwords * sizeof(u32))); | ||
1808 | } else if (tex_width < 16) { | ||
1809 | for (i = 0; i < tex->height; i++) { | ||
1810 | RADEON_COPY_MT(buffer, data, tex_width); | ||
1811 | buffer += 4; | ||
1812 | data += tex_width; | ||
1813 | } | ||
1814 | } else if (tex_width == 32) { | ||
1815 | /* TODO: make sure this works when not fitting in one buffer | ||
1816 | (i.e. 32bytes x 2048...) */ | ||
1817 | for (i = 0; i < tex->height; i += 2) { | ||
1818 | RADEON_COPY_MT(buffer, data, 16); | ||
1819 | data += 16; | ||
1820 | RADEON_COPY_MT(buffer + 8, data, 16); | ||
1821 | data += 16; | ||
1822 | RADEON_COPY_MT(buffer + 4, data, 16); | ||
1823 | data += 16; | ||
1824 | RADEON_COPY_MT(buffer + 12, data, 16); | ||
1825 | data += 16; | ||
1826 | buffer += 16; | ||
1827 | } | ||
1828 | } | ||
1829 | } else { | ||
1830 | if (tex_width >= 32) { | ||
1831 | /* Texture image width is larger than the minimum, so we | ||
1832 | * can upload it directly. | ||
1833 | */ | ||
1834 | RADEON_COPY_MT(buffer, data, | ||
1835 | (int)(dwords * sizeof(u32))); | ||
1836 | } else { | ||
1837 | /* Texture image width is less than the minimum, so we | ||
1838 | * need to pad out each image scanline to the minimum | ||
1839 | * width. | ||
1840 | */ | ||
1841 | for (i = 0; i < tex->height; i++) { | ||
1842 | RADEON_COPY_MT(buffer, data, tex_width); | ||
1843 | buffer += 8; | ||
1844 | data += tex_width; | ||
1845 | } | ||
1846 | } | ||
1847 | } | ||
1848 | |||
1849 | #undef RADEON_COPY_MT | ||
1850 | byte_offset = (image->y & ~2047) * blit_width; | ||
1851 | buf->file_priv = file_priv; | ||
1852 | buf->used = size; | ||
1853 | offset = dev_priv->gart_buffers_offset + buf->offset; | ||
1854 | BEGIN_RING(9); | ||
1855 | OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); | ||
1856 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | ||
1857 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
1858 | RADEON_GMC_BRUSH_NONE | | ||
1859 | (format << 8) | | ||
1860 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
1861 | RADEON_ROP3_S | | ||
1862 | RADEON_DP_SRC_SOURCE_MEMORY | | ||
1863 | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); | ||
1864 | OUT_RING((spitch << 22) | (offset >> 10)); | ||
1865 | OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10))); | ||
1866 | OUT_RING(0); | ||
1867 | OUT_RING((image->x << 16) | (image->y % 2048)); | ||
1868 | OUT_RING((image->width << 16) | height); | ||
1869 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1870 | ADVANCE_RING(); | ||
1871 | COMMIT_RING(); | ||
1872 | |||
1873 | radeon_cp_discard_buffer(dev, buf); | ||
1874 | |||
1875 | /* Update the input parameters for next time */ | ||
1876 | image->y += height; | ||
1877 | image->height -= height; | ||
1878 | image->data = (const u8 __user *)image->data + size; | ||
1879 | } while (image->height > 0); | ||
1880 | |||
1881 | /* Flush the pixel cache after the blit completes. This ensures | ||
1882 | * the texture data is written out to memory before rendering | ||
1883 | * continues. | ||
1884 | */ | ||
1885 | BEGIN_RING(4); | ||
1886 | RADEON_FLUSH_CACHE(); | ||
1887 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
1888 | ADVANCE_RING(); | ||
1889 | COMMIT_RING(); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1894 | static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple) | ||
1895 | { | ||
1896 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
1897 | int i; | ||
1898 | RING_LOCALS; | ||
1899 | DRM_DEBUG("\n"); | ||
1900 | |||
1901 | BEGIN_RING(35); | ||
1902 | |||
1903 | OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0)); | ||
1904 | OUT_RING(0x00000000); | ||
1905 | |||
1906 | OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31)); | ||
1907 | for (i = 0; i < 32; i++) { | ||
1908 | OUT_RING(stipple[i]); | ||
1909 | } | ||
1910 | |||
1911 | ADVANCE_RING(); | ||
1912 | } | ||
1913 | |||
1914 | static void radeon_apply_surface_regs(int surf_index, | ||
1915 | drm_radeon_private_t *dev_priv) | ||
1916 | { | ||
1917 | if (!dev_priv->mmio) | ||
1918 | return; | ||
1919 | |||
1920 | radeon_do_cp_idle(dev_priv); | ||
1921 | |||
1922 | RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index, | ||
1923 | dev_priv->surfaces[surf_index].flags); | ||
1924 | RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index, | ||
1925 | dev_priv->surfaces[surf_index].lower); | ||
1926 | RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index, | ||
1927 | dev_priv->surfaces[surf_index].upper); | ||
1928 | } | ||
1929 | |||
1930 | /* Allocates a virtual surface | ||
1931 | * doesn't always allocate a real surface, will stretch an existing | ||
1932 | * surface when possible. | ||
1933 | * | ||
1934 | * Note that refcount can be at most 2, since during a free refcount=3 | ||
1935 | * might mean we have to allocate a new surface which might not always | ||
1936 | * be available. | ||
1937 | * For example : we allocate three contigous surfaces ABC. If B is | ||
1938 | * freed, we suddenly need two surfaces to store A and C, which might | ||
1939 | * not always be available. | ||
1940 | */ | ||
1941 | static int alloc_surface(drm_radeon_surface_alloc_t *new, | ||
1942 | drm_radeon_private_t *dev_priv, | ||
1943 | struct drm_file *file_priv) | ||
1944 | { | ||
1945 | struct radeon_virt_surface *s; | ||
1946 | int i; | ||
1947 | int virt_surface_index; | ||
1948 | uint32_t new_upper, new_lower; | ||
1949 | |||
1950 | new_lower = new->address; | ||
1951 | new_upper = new_lower + new->size - 1; | ||
1952 | |||
1953 | /* sanity check */ | ||
1954 | if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) || | ||
1955 | ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != | ||
1956 | RADEON_SURF_ADDRESS_FIXED_MASK) | ||
1957 | || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0)) | ||
1958 | return -1; | ||
1959 | |||
1960 | /* make sure there is no overlap with existing surfaces */ | ||
1961 | for (i = 0; i < RADEON_MAX_SURFACES; i++) { | ||
1962 | if ((dev_priv->surfaces[i].refcount != 0) && | ||
1963 | (((new_lower >= dev_priv->surfaces[i].lower) && | ||
1964 | (new_lower < dev_priv->surfaces[i].upper)) || | ||
1965 | ((new_lower < dev_priv->surfaces[i].lower) && | ||
1966 | (new_upper > dev_priv->surfaces[i].lower)))) { | ||
1967 | return -1; | ||
1968 | } | ||
1969 | } | ||
1970 | |||
1971 | /* find a virtual surface */ | ||
1972 | for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) | ||
1973 | if (dev_priv->virt_surfaces[i].file_priv == 0) | ||
1974 | break; | ||
1975 | if (i == 2 * RADEON_MAX_SURFACES) { | ||
1976 | return -1; | ||
1977 | } | ||
1978 | virt_surface_index = i; | ||
1979 | |||
1980 | /* try to reuse an existing surface */ | ||
1981 | for (i = 0; i < RADEON_MAX_SURFACES; i++) { | ||
1982 | /* extend before */ | ||
1983 | if ((dev_priv->surfaces[i].refcount == 1) && | ||
1984 | (new->flags == dev_priv->surfaces[i].flags) && | ||
1985 | (new_upper + 1 == dev_priv->surfaces[i].lower)) { | ||
1986 | s = &(dev_priv->virt_surfaces[virt_surface_index]); | ||
1987 | s->surface_index = i; | ||
1988 | s->lower = new_lower; | ||
1989 | s->upper = new_upper; | ||
1990 | s->flags = new->flags; | ||
1991 | s->file_priv = file_priv; | ||
1992 | dev_priv->surfaces[i].refcount++; | ||
1993 | dev_priv->surfaces[i].lower = s->lower; | ||
1994 | radeon_apply_surface_regs(s->surface_index, dev_priv); | ||
1995 | return virt_surface_index; | ||
1996 | } | ||
1997 | |||
1998 | /* extend after */ | ||
1999 | if ((dev_priv->surfaces[i].refcount == 1) && | ||
2000 | (new->flags == dev_priv->surfaces[i].flags) && | ||
2001 | (new_lower == dev_priv->surfaces[i].upper + 1)) { | ||
2002 | s = &(dev_priv->virt_surfaces[virt_surface_index]); | ||
2003 | s->surface_index = i; | ||
2004 | s->lower = new_lower; | ||
2005 | s->upper = new_upper; | ||
2006 | s->flags = new->flags; | ||
2007 | s->file_priv = file_priv; | ||
2008 | dev_priv->surfaces[i].refcount++; | ||
2009 | dev_priv->surfaces[i].upper = s->upper; | ||
2010 | radeon_apply_surface_regs(s->surface_index, dev_priv); | ||
2011 | return virt_surface_index; | ||
2012 | } | ||
2013 | } | ||
2014 | |||
2015 | /* okay, we need a new one */ | ||
2016 | for (i = 0; i < RADEON_MAX_SURFACES; i++) { | ||
2017 | if (dev_priv->surfaces[i].refcount == 0) { | ||
2018 | s = &(dev_priv->virt_surfaces[virt_surface_index]); | ||
2019 | s->surface_index = i; | ||
2020 | s->lower = new_lower; | ||
2021 | s->upper = new_upper; | ||
2022 | s->flags = new->flags; | ||
2023 | s->file_priv = file_priv; | ||
2024 | dev_priv->surfaces[i].refcount = 1; | ||
2025 | dev_priv->surfaces[i].lower = s->lower; | ||
2026 | dev_priv->surfaces[i].upper = s->upper; | ||
2027 | dev_priv->surfaces[i].flags = s->flags; | ||
2028 | radeon_apply_surface_regs(s->surface_index, dev_priv); | ||
2029 | return virt_surface_index; | ||
2030 | } | ||
2031 | } | ||
2032 | |||
2033 | /* we didn't find anything */ | ||
2034 | return -1; | ||
2035 | } | ||
2036 | |||
2037 | static int free_surface(struct drm_file *file_priv, | ||
2038 | drm_radeon_private_t * dev_priv, | ||
2039 | int lower) | ||
2040 | { | ||
2041 | struct radeon_virt_surface *s; | ||
2042 | int i; | ||
2043 | /* find the virtual surface */ | ||
2044 | for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { | ||
2045 | s = &(dev_priv->virt_surfaces[i]); | ||
2046 | if (s->file_priv) { | ||
2047 | if ((lower == s->lower) && (file_priv == s->file_priv)) | ||
2048 | { | ||
2049 | if (dev_priv->surfaces[s->surface_index]. | ||
2050 | lower == s->lower) | ||
2051 | dev_priv->surfaces[s->surface_index]. | ||
2052 | lower = s->upper; | ||
2053 | |||
2054 | if (dev_priv->surfaces[s->surface_index]. | ||
2055 | upper == s->upper) | ||
2056 | dev_priv->surfaces[s->surface_index]. | ||
2057 | upper = s->lower; | ||
2058 | |||
2059 | dev_priv->surfaces[s->surface_index].refcount--; | ||
2060 | if (dev_priv->surfaces[s->surface_index]. | ||
2061 | refcount == 0) | ||
2062 | dev_priv->surfaces[s->surface_index]. | ||
2063 | flags = 0; | ||
2064 | s->file_priv = NULL; | ||
2065 | radeon_apply_surface_regs(s->surface_index, | ||
2066 | dev_priv); | ||
2067 | return 0; | ||
2068 | } | ||
2069 | } | ||
2070 | } | ||
2071 | return 1; | ||
2072 | } | ||
2073 | |||
2074 | static void radeon_surfaces_release(struct drm_file *file_priv, | ||
2075 | drm_radeon_private_t * dev_priv) | ||
2076 | { | ||
2077 | int i; | ||
2078 | for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { | ||
2079 | if (dev_priv->virt_surfaces[i].file_priv == file_priv) | ||
2080 | free_surface(file_priv, dev_priv, | ||
2081 | dev_priv->virt_surfaces[i].lower); | ||
2082 | } | ||
2083 | } | ||
2084 | |||
2085 | /* ================================================================ | ||
2086 | * IOCTL functions | ||
2087 | */ | ||
2088 | static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2089 | { | ||
2090 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2091 | drm_radeon_surface_alloc_t *alloc = data; | ||
2092 | |||
2093 | if (alloc_surface(alloc, dev_priv, file_priv) == -1) | ||
2094 | return -EINVAL; | ||
2095 | else | ||
2096 | return 0; | ||
2097 | } | ||
2098 | |||
2099 | static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2100 | { | ||
2101 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2102 | drm_radeon_surface_free_t *memfree = data; | ||
2103 | |||
2104 | if (free_surface(file_priv, dev_priv, memfree->address)) | ||
2105 | return -EINVAL; | ||
2106 | else | ||
2107 | return 0; | ||
2108 | } | ||
2109 | |||
2110 | static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2111 | { | ||
2112 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2113 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
2114 | drm_radeon_clear_t *clear = data; | ||
2115 | drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; | ||
2116 | DRM_DEBUG("\n"); | ||
2117 | |||
2118 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2119 | |||
2120 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2121 | |||
2122 | if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) | ||
2123 | sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; | ||
2124 | |||
2125 | if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, | ||
2126 | sarea_priv->nbox * sizeof(depth_boxes[0]))) | ||
2127 | return -EFAULT; | ||
2128 | |||
2129 | radeon_cp_dispatch_clear(dev, clear, depth_boxes); | ||
2130 | |||
2131 | COMMIT_RING(); | ||
2132 | return 0; | ||
2133 | } | ||
2134 | |||
2135 | /* Not sure why this isn't set all the time: | ||
2136 | */ | ||
2137 | static int radeon_do_init_pageflip(struct drm_device * dev) | ||
2138 | { | ||
2139 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2140 | RING_LOCALS; | ||
2141 | |||
2142 | DRM_DEBUG("\n"); | ||
2143 | |||
2144 | BEGIN_RING(6); | ||
2145 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
2146 | OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0)); | ||
2147 | OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) | | ||
2148 | RADEON_CRTC_OFFSET_FLIP_CNTL); | ||
2149 | OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0)); | ||
2150 | OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) | | ||
2151 | RADEON_CRTC_OFFSET_FLIP_CNTL); | ||
2152 | ADVANCE_RING(); | ||
2153 | |||
2154 | dev_priv->page_flipping = 1; | ||
2155 | |||
2156 | if (dev_priv->sarea_priv->pfCurrentPage != 1) | ||
2157 | dev_priv->sarea_priv->pfCurrentPage = 0; | ||
2158 | |||
2159 | return 0; | ||
2160 | } | ||
2161 | |||
2162 | /* Swapping and flipping are different operations, need different ioctls. | ||
2163 | * They can & should be intermixed to support multiple 3d windows. | ||
2164 | */ | ||
2165 | static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2166 | { | ||
2167 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2168 | DRM_DEBUG("\n"); | ||
2169 | |||
2170 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2171 | |||
2172 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2173 | |||
2174 | if (!dev_priv->page_flipping) | ||
2175 | radeon_do_init_pageflip(dev); | ||
2176 | |||
2177 | radeon_cp_dispatch_flip(dev); | ||
2178 | |||
2179 | COMMIT_RING(); | ||
2180 | return 0; | ||
2181 | } | ||
2182 | |||
2183 | static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2184 | { | ||
2185 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2186 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
2187 | DRM_DEBUG("\n"); | ||
2188 | |||
2189 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2190 | |||
2191 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2192 | |||
2193 | if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) | ||
2194 | sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; | ||
2195 | |||
2196 | radeon_cp_dispatch_swap(dev); | ||
2197 | dev_priv->sarea_priv->ctx_owner = 0; | ||
2198 | |||
2199 | COMMIT_RING(); | ||
2200 | return 0; | ||
2201 | } | ||
2202 | |||
2203 | static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2204 | { | ||
2205 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2206 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
2207 | struct drm_device_dma *dma = dev->dma; | ||
2208 | struct drm_buf *buf; | ||
2209 | drm_radeon_vertex_t *vertex = data; | ||
2210 | drm_radeon_tcl_prim_t prim; | ||
2211 | |||
2212 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2213 | |||
2214 | DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", | ||
2215 | DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); | ||
2216 | |||
2217 | if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { | ||
2218 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
2219 | vertex->idx, dma->buf_count - 1); | ||
2220 | return -EINVAL; | ||
2221 | } | ||
2222 | if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { | ||
2223 | DRM_ERROR("buffer prim %d\n", vertex->prim); | ||
2224 | return -EINVAL; | ||
2225 | } | ||
2226 | |||
2227 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2228 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2229 | |||
2230 | buf = dma->buflist[vertex->idx]; | ||
2231 | |||
2232 | if (buf->file_priv != file_priv) { | ||
2233 | DRM_ERROR("process %d using buffer owned by %p\n", | ||
2234 | DRM_CURRENTPID, buf->file_priv); | ||
2235 | return -EINVAL; | ||
2236 | } | ||
2237 | if (buf->pending) { | ||
2238 | DRM_ERROR("sending pending buffer %d\n", vertex->idx); | ||
2239 | return -EINVAL; | ||
2240 | } | ||
2241 | |||
2242 | /* Build up a prim_t record: | ||
2243 | */ | ||
2244 | if (vertex->count) { | ||
2245 | buf->used = vertex->count; /* not used? */ | ||
2246 | |||
2247 | if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { | ||
2248 | if (radeon_emit_state(dev_priv, file_priv, | ||
2249 | &sarea_priv->context_state, | ||
2250 | sarea_priv->tex_state, | ||
2251 | sarea_priv->dirty)) { | ||
2252 | DRM_ERROR("radeon_emit_state failed\n"); | ||
2253 | return -EINVAL; | ||
2254 | } | ||
2255 | |||
2256 | sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | | ||
2257 | RADEON_UPLOAD_TEX1IMAGES | | ||
2258 | RADEON_UPLOAD_TEX2IMAGES | | ||
2259 | RADEON_REQUIRE_QUIESCENCE); | ||
2260 | } | ||
2261 | |||
2262 | prim.start = 0; | ||
2263 | prim.finish = vertex->count; /* unused */ | ||
2264 | prim.prim = vertex->prim; | ||
2265 | prim.numverts = vertex->count; | ||
2266 | prim.vc_format = dev_priv->sarea_priv->vc_format; | ||
2267 | |||
2268 | radeon_cp_dispatch_vertex(dev, buf, &prim); | ||
2269 | } | ||
2270 | |||
2271 | if (vertex->discard) { | ||
2272 | radeon_cp_discard_buffer(dev, buf); | ||
2273 | } | ||
2274 | |||
2275 | COMMIT_RING(); | ||
2276 | return 0; | ||
2277 | } | ||
2278 | |||
2279 | static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2280 | { | ||
2281 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2282 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
2283 | struct drm_device_dma *dma = dev->dma; | ||
2284 | struct drm_buf *buf; | ||
2285 | drm_radeon_indices_t *elts = data; | ||
2286 | drm_radeon_tcl_prim_t prim; | ||
2287 | int count; | ||
2288 | |||
2289 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2290 | |||
2291 | DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", | ||
2292 | DRM_CURRENTPID, elts->idx, elts->start, elts->end, | ||
2293 | elts->discard); | ||
2294 | |||
2295 | if (elts->idx < 0 || elts->idx >= dma->buf_count) { | ||
2296 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
2297 | elts->idx, dma->buf_count - 1); | ||
2298 | return -EINVAL; | ||
2299 | } | ||
2300 | if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { | ||
2301 | DRM_ERROR("buffer prim %d\n", elts->prim); | ||
2302 | return -EINVAL; | ||
2303 | } | ||
2304 | |||
2305 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2306 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2307 | |||
2308 | buf = dma->buflist[elts->idx]; | ||
2309 | |||
2310 | if (buf->file_priv != file_priv) { | ||
2311 | DRM_ERROR("process %d using buffer owned by %p\n", | ||
2312 | DRM_CURRENTPID, buf->file_priv); | ||
2313 | return -EINVAL; | ||
2314 | } | ||
2315 | if (buf->pending) { | ||
2316 | DRM_ERROR("sending pending buffer %d\n", elts->idx); | ||
2317 | return -EINVAL; | ||
2318 | } | ||
2319 | |||
2320 | count = (elts->end - elts->start) / sizeof(u16); | ||
2321 | elts->start -= RADEON_INDEX_PRIM_OFFSET; | ||
2322 | |||
2323 | if (elts->start & 0x7) { | ||
2324 | DRM_ERROR("misaligned buffer 0x%x\n", elts->start); | ||
2325 | return -EINVAL; | ||
2326 | } | ||
2327 | if (elts->start < buf->used) { | ||
2328 | DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); | ||
2329 | return -EINVAL; | ||
2330 | } | ||
2331 | |||
2332 | buf->used = elts->end; | ||
2333 | |||
2334 | if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { | ||
2335 | if (radeon_emit_state(dev_priv, file_priv, | ||
2336 | &sarea_priv->context_state, | ||
2337 | sarea_priv->tex_state, | ||
2338 | sarea_priv->dirty)) { | ||
2339 | DRM_ERROR("radeon_emit_state failed\n"); | ||
2340 | return -EINVAL; | ||
2341 | } | ||
2342 | |||
2343 | sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | | ||
2344 | RADEON_UPLOAD_TEX1IMAGES | | ||
2345 | RADEON_UPLOAD_TEX2IMAGES | | ||
2346 | RADEON_REQUIRE_QUIESCENCE); | ||
2347 | } | ||
2348 | |||
2349 | /* Build up a prim_t record: | ||
2350 | */ | ||
2351 | prim.start = elts->start; | ||
2352 | prim.finish = elts->end; | ||
2353 | prim.prim = elts->prim; | ||
2354 | prim.offset = 0; /* offset from start of dma buffers */ | ||
2355 | prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ | ||
2356 | prim.vc_format = dev_priv->sarea_priv->vc_format; | ||
2357 | |||
2358 | radeon_cp_dispatch_indices(dev, buf, &prim); | ||
2359 | if (elts->discard) { | ||
2360 | radeon_cp_discard_buffer(dev, buf); | ||
2361 | } | ||
2362 | |||
2363 | COMMIT_RING(); | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2367 | static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2368 | { | ||
2369 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2370 | drm_radeon_texture_t *tex = data; | ||
2371 | drm_radeon_tex_image_t image; | ||
2372 | int ret; | ||
2373 | |||
2374 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2375 | |||
2376 | if (tex->image == NULL) { | ||
2377 | DRM_ERROR("null texture image!\n"); | ||
2378 | return -EINVAL; | ||
2379 | } | ||
2380 | |||
2381 | if (DRM_COPY_FROM_USER(&image, | ||
2382 | (drm_radeon_tex_image_t __user *) tex->image, | ||
2383 | sizeof(image))) | ||
2384 | return -EFAULT; | ||
2385 | |||
2386 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2387 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2388 | |||
2389 | ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image); | ||
2390 | |||
2391 | return ret; | ||
2392 | } | ||
2393 | |||
2394 | static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2395 | { | ||
2396 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2397 | drm_radeon_stipple_t *stipple = data; | ||
2398 | u32 mask[32]; | ||
2399 | |||
2400 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2401 | |||
2402 | if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) | ||
2403 | return -EFAULT; | ||
2404 | |||
2405 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2406 | |||
2407 | radeon_cp_dispatch_stipple(dev, mask); | ||
2408 | |||
2409 | COMMIT_RING(); | ||
2410 | return 0; | ||
2411 | } | ||
2412 | |||
2413 | static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2414 | { | ||
2415 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2416 | struct drm_device_dma *dma = dev->dma; | ||
2417 | struct drm_buf *buf; | ||
2418 | drm_radeon_indirect_t *indirect = data; | ||
2419 | RING_LOCALS; | ||
2420 | |||
2421 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2422 | |||
2423 | DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", | ||
2424 | indirect->idx, indirect->start, indirect->end, | ||
2425 | indirect->discard); | ||
2426 | |||
2427 | if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { | ||
2428 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
2429 | indirect->idx, dma->buf_count - 1); | ||
2430 | return -EINVAL; | ||
2431 | } | ||
2432 | |||
2433 | buf = dma->buflist[indirect->idx]; | ||
2434 | |||
2435 | if (buf->file_priv != file_priv) { | ||
2436 | DRM_ERROR("process %d using buffer owned by %p\n", | ||
2437 | DRM_CURRENTPID, buf->file_priv); | ||
2438 | return -EINVAL; | ||
2439 | } | ||
2440 | if (buf->pending) { | ||
2441 | DRM_ERROR("sending pending buffer %d\n", indirect->idx); | ||
2442 | return -EINVAL; | ||
2443 | } | ||
2444 | |||
2445 | if (indirect->start < buf->used) { | ||
2446 | DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", | ||
2447 | indirect->start, buf->used); | ||
2448 | return -EINVAL; | ||
2449 | } | ||
2450 | |||
2451 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2452 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2453 | |||
2454 | buf->used = indirect->end; | ||
2455 | |||
2456 | /* Wait for the 3D stream to idle before the indirect buffer | ||
2457 | * containing 2D acceleration commands is processed. | ||
2458 | */ | ||
2459 | BEGIN_RING(2); | ||
2460 | |||
2461 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
2462 | |||
2463 | ADVANCE_RING(); | ||
2464 | |||
2465 | /* Dispatch the indirect buffer full of commands from the | ||
2466 | * X server. This is insecure and is thus only available to | ||
2467 | * privileged clients. | ||
2468 | */ | ||
2469 | radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); | ||
2470 | if (indirect->discard) { | ||
2471 | radeon_cp_discard_buffer(dev, buf); | ||
2472 | } | ||
2473 | |||
2474 | COMMIT_RING(); | ||
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2479 | { | ||
2480 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2481 | drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
2482 | struct drm_device_dma *dma = dev->dma; | ||
2483 | struct drm_buf *buf; | ||
2484 | drm_radeon_vertex2_t *vertex = data; | ||
2485 | int i; | ||
2486 | unsigned char laststate; | ||
2487 | |||
2488 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2489 | |||
2490 | DRM_DEBUG("pid=%d index=%d discard=%d\n", | ||
2491 | DRM_CURRENTPID, vertex->idx, vertex->discard); | ||
2492 | |||
2493 | if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { | ||
2494 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
2495 | vertex->idx, dma->buf_count - 1); | ||
2496 | return -EINVAL; | ||
2497 | } | ||
2498 | |||
2499 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2500 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2501 | |||
2502 | buf = dma->buflist[vertex->idx]; | ||
2503 | |||
2504 | if (buf->file_priv != file_priv) { | ||
2505 | DRM_ERROR("process %d using buffer owned by %p\n", | ||
2506 | DRM_CURRENTPID, buf->file_priv); | ||
2507 | return -EINVAL; | ||
2508 | } | ||
2509 | |||
2510 | if (buf->pending) { | ||
2511 | DRM_ERROR("sending pending buffer %d\n", vertex->idx); | ||
2512 | return -EINVAL; | ||
2513 | } | ||
2514 | |||
2515 | if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) | ||
2516 | return -EINVAL; | ||
2517 | |||
2518 | for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) { | ||
2519 | drm_radeon_prim_t prim; | ||
2520 | drm_radeon_tcl_prim_t tclprim; | ||
2521 | |||
2522 | if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim))) | ||
2523 | return -EFAULT; | ||
2524 | |||
2525 | if (prim.stateidx != laststate) { | ||
2526 | drm_radeon_state_t state; | ||
2527 | |||
2528 | if (DRM_COPY_FROM_USER(&state, | ||
2529 | &vertex->state[prim.stateidx], | ||
2530 | sizeof(state))) | ||
2531 | return -EFAULT; | ||
2532 | |||
2533 | if (radeon_emit_state2(dev_priv, file_priv, &state)) { | ||
2534 | DRM_ERROR("radeon_emit_state2 failed\n"); | ||
2535 | return -EINVAL; | ||
2536 | } | ||
2537 | |||
2538 | laststate = prim.stateidx; | ||
2539 | } | ||
2540 | |||
2541 | tclprim.start = prim.start; | ||
2542 | tclprim.finish = prim.finish; | ||
2543 | tclprim.prim = prim.prim; | ||
2544 | tclprim.vc_format = prim.vc_format; | ||
2545 | |||
2546 | if (prim.prim & RADEON_PRIM_WALK_IND) { | ||
2547 | tclprim.offset = prim.numverts * 64; | ||
2548 | tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ | ||
2549 | |||
2550 | radeon_cp_dispatch_indices(dev, buf, &tclprim); | ||
2551 | } else { | ||
2552 | tclprim.numverts = prim.numverts; | ||
2553 | tclprim.offset = 0; /* not used */ | ||
2554 | |||
2555 | radeon_cp_dispatch_vertex(dev, buf, &tclprim); | ||
2556 | } | ||
2557 | |||
2558 | if (sarea_priv->nbox == 1) | ||
2559 | sarea_priv->nbox = 0; | ||
2560 | } | ||
2561 | |||
2562 | if (vertex->discard) { | ||
2563 | radeon_cp_discard_buffer(dev, buf); | ||
2564 | } | ||
2565 | |||
2566 | COMMIT_RING(); | ||
2567 | return 0; | ||
2568 | } | ||
2569 | |||
2570 | static int radeon_emit_packets(drm_radeon_private_t * dev_priv, | ||
2571 | struct drm_file *file_priv, | ||
2572 | drm_radeon_cmd_header_t header, | ||
2573 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2574 | { | ||
2575 | int id = (int)header.packet.packet_id; | ||
2576 | int sz, reg; | ||
2577 | int *data = (int *)cmdbuf->buf; | ||
2578 | RING_LOCALS; | ||
2579 | |||
2580 | if (id >= RADEON_MAX_STATE_PACKETS) | ||
2581 | return -EINVAL; | ||
2582 | |||
2583 | sz = packet[id].len; | ||
2584 | reg = packet[id].start; | ||
2585 | |||
2586 | if (sz * sizeof(int) > cmdbuf->bufsz) { | ||
2587 | DRM_ERROR("Packet size provided larger than data provided\n"); | ||
2588 | return -EINVAL; | ||
2589 | } | ||
2590 | |||
2591 | if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) { | ||
2592 | DRM_ERROR("Packet verification failed\n"); | ||
2593 | return -EINVAL; | ||
2594 | } | ||
2595 | |||
2596 | BEGIN_RING(sz + 1); | ||
2597 | OUT_RING(CP_PACKET0(reg, (sz - 1))); | ||
2598 | OUT_RING_TABLE(data, sz); | ||
2599 | ADVANCE_RING(); | ||
2600 | |||
2601 | cmdbuf->buf += sz * sizeof(int); | ||
2602 | cmdbuf->bufsz -= sz * sizeof(int); | ||
2603 | return 0; | ||
2604 | } | ||
2605 | |||
2606 | static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv, | ||
2607 | drm_radeon_cmd_header_t header, | ||
2608 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2609 | { | ||
2610 | int sz = header.scalars.count; | ||
2611 | int start = header.scalars.offset; | ||
2612 | int stride = header.scalars.stride; | ||
2613 | RING_LOCALS; | ||
2614 | |||
2615 | BEGIN_RING(3 + sz); | ||
2616 | OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); | ||
2617 | OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); | ||
2618 | OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); | ||
2619 | OUT_RING_TABLE(cmdbuf->buf, sz); | ||
2620 | ADVANCE_RING(); | ||
2621 | cmdbuf->buf += sz * sizeof(int); | ||
2622 | cmdbuf->bufsz -= sz * sizeof(int); | ||
2623 | return 0; | ||
2624 | } | ||
2625 | |||
2626 | /* God this is ugly | ||
2627 | */ | ||
2628 | static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv, | ||
2629 | drm_radeon_cmd_header_t header, | ||
2630 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2631 | { | ||
2632 | int sz = header.scalars.count; | ||
2633 | int start = ((unsigned int)header.scalars.offset) + 0x100; | ||
2634 | int stride = header.scalars.stride; | ||
2635 | RING_LOCALS; | ||
2636 | |||
2637 | BEGIN_RING(3 + sz); | ||
2638 | OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); | ||
2639 | OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); | ||
2640 | OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); | ||
2641 | OUT_RING_TABLE(cmdbuf->buf, sz); | ||
2642 | ADVANCE_RING(); | ||
2643 | cmdbuf->buf += sz * sizeof(int); | ||
2644 | cmdbuf->bufsz -= sz * sizeof(int); | ||
2645 | return 0; | ||
2646 | } | ||
2647 | |||
2648 | static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, | ||
2649 | drm_radeon_cmd_header_t header, | ||
2650 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2651 | { | ||
2652 | int sz = header.vectors.count; | ||
2653 | int start = header.vectors.offset; | ||
2654 | int stride = header.vectors.stride; | ||
2655 | RING_LOCALS; | ||
2656 | |||
2657 | BEGIN_RING(5 + sz); | ||
2658 | OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); | ||
2659 | OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); | ||
2660 | OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); | ||
2661 | OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); | ||
2662 | OUT_RING_TABLE(cmdbuf->buf, sz); | ||
2663 | ADVANCE_RING(); | ||
2664 | |||
2665 | cmdbuf->buf += sz * sizeof(int); | ||
2666 | cmdbuf->bufsz -= sz * sizeof(int); | ||
2667 | return 0; | ||
2668 | } | ||
2669 | |||
2670 | static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, | ||
2671 | drm_radeon_cmd_header_t header, | ||
2672 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2673 | { | ||
2674 | int sz = header.veclinear.count * 4; | ||
2675 | int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); | ||
2676 | RING_LOCALS; | ||
2677 | |||
2678 | if (!sz) | ||
2679 | return 0; | ||
2680 | if (sz * 4 > cmdbuf->bufsz) | ||
2681 | return -EINVAL; | ||
2682 | |||
2683 | BEGIN_RING(5 + sz); | ||
2684 | OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); | ||
2685 | OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); | ||
2686 | OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); | ||
2687 | OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); | ||
2688 | OUT_RING_TABLE(cmdbuf->buf, sz); | ||
2689 | ADVANCE_RING(); | ||
2690 | |||
2691 | cmdbuf->buf += sz * sizeof(int); | ||
2692 | cmdbuf->bufsz -= sz * sizeof(int); | ||
2693 | return 0; | ||
2694 | } | ||
2695 | |||
2696 | static int radeon_emit_packet3(struct drm_device * dev, | ||
2697 | struct drm_file *file_priv, | ||
2698 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
2699 | { | ||
2700 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2701 | unsigned int cmdsz; | ||
2702 | int ret; | ||
2703 | RING_LOCALS; | ||
2704 | |||
2705 | DRM_DEBUG("\n"); | ||
2706 | |||
2707 | if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, | ||
2708 | cmdbuf, &cmdsz))) { | ||
2709 | DRM_ERROR("Packet verification failed\n"); | ||
2710 | return ret; | ||
2711 | } | ||
2712 | |||
2713 | BEGIN_RING(cmdsz); | ||
2714 | OUT_RING_TABLE(cmdbuf->buf, cmdsz); | ||
2715 | ADVANCE_RING(); | ||
2716 | |||
2717 | cmdbuf->buf += cmdsz * 4; | ||
2718 | cmdbuf->bufsz -= cmdsz * 4; | ||
2719 | return 0; | ||
2720 | } | ||
2721 | |||
2722 | static int radeon_emit_packet3_cliprect(struct drm_device *dev, | ||
2723 | struct drm_file *file_priv, | ||
2724 | drm_radeon_kcmd_buffer_t *cmdbuf, | ||
2725 | int orig_nbox) | ||
2726 | { | ||
2727 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2728 | struct drm_clip_rect box; | ||
2729 | unsigned int cmdsz; | ||
2730 | int ret; | ||
2731 | struct drm_clip_rect __user *boxes = cmdbuf->boxes; | ||
2732 | int i = 0; | ||
2733 | RING_LOCALS; | ||
2734 | |||
2735 | DRM_DEBUG("\n"); | ||
2736 | |||
2737 | if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, | ||
2738 | cmdbuf, &cmdsz))) { | ||
2739 | DRM_ERROR("Packet verification failed\n"); | ||
2740 | return ret; | ||
2741 | } | ||
2742 | |||
2743 | if (!orig_nbox) | ||
2744 | goto out; | ||
2745 | |||
2746 | do { | ||
2747 | if (i < cmdbuf->nbox) { | ||
2748 | if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) | ||
2749 | return -EFAULT; | ||
2750 | /* FIXME The second and subsequent times round | ||
2751 | * this loop, send a WAIT_UNTIL_3D_IDLE before | ||
2752 | * calling emit_clip_rect(). This fixes a | ||
2753 | * lockup on fast machines when sending | ||
2754 | * several cliprects with a cmdbuf, as when | ||
2755 | * waving a 2D window over a 3D | ||
2756 | * window. Something in the commands from user | ||
2757 | * space seems to hang the card when they're | ||
2758 | * sent several times in a row. That would be | ||
2759 | * the correct place to fix it but this works | ||
2760 | * around it until I can figure that out - Tim | ||
2761 | * Smith */ | ||
2762 | if (i) { | ||
2763 | BEGIN_RING(2); | ||
2764 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
2765 | ADVANCE_RING(); | ||
2766 | } | ||
2767 | radeon_emit_clip_rect(dev_priv, &box); | ||
2768 | } | ||
2769 | |||
2770 | BEGIN_RING(cmdsz); | ||
2771 | OUT_RING_TABLE(cmdbuf->buf, cmdsz); | ||
2772 | ADVANCE_RING(); | ||
2773 | |||
2774 | } while (++i < cmdbuf->nbox); | ||
2775 | if (cmdbuf->nbox == 1) | ||
2776 | cmdbuf->nbox = 0; | ||
2777 | |||
2778 | out: | ||
2779 | cmdbuf->buf += cmdsz * 4; | ||
2780 | cmdbuf->bufsz -= cmdsz * 4; | ||
2781 | return 0; | ||
2782 | } | ||
2783 | |||
2784 | static int radeon_emit_wait(struct drm_device * dev, int flags) | ||
2785 | { | ||
2786 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2787 | RING_LOCALS; | ||
2788 | |||
2789 | DRM_DEBUG("%x\n", flags); | ||
2790 | switch (flags) { | ||
2791 | case RADEON_WAIT_2D: | ||
2792 | BEGIN_RING(2); | ||
2793 | RADEON_WAIT_UNTIL_2D_IDLE(); | ||
2794 | ADVANCE_RING(); | ||
2795 | break; | ||
2796 | case RADEON_WAIT_3D: | ||
2797 | BEGIN_RING(2); | ||
2798 | RADEON_WAIT_UNTIL_3D_IDLE(); | ||
2799 | ADVANCE_RING(); | ||
2800 | break; | ||
2801 | case RADEON_WAIT_2D | RADEON_WAIT_3D: | ||
2802 | BEGIN_RING(2); | ||
2803 | RADEON_WAIT_UNTIL_IDLE(); | ||
2804 | ADVANCE_RING(); | ||
2805 | break; | ||
2806 | default: | ||
2807 | return -EINVAL; | ||
2808 | } | ||
2809 | |||
2810 | return 0; | ||
2811 | } | ||
2812 | |||
2813 | static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2814 | { | ||
2815 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2816 | struct drm_device_dma *dma = dev->dma; | ||
2817 | struct drm_buf *buf = NULL; | ||
2818 | int idx; | ||
2819 | drm_radeon_kcmd_buffer_t *cmdbuf = data; | ||
2820 | drm_radeon_cmd_header_t header; | ||
2821 | int orig_nbox, orig_bufsz; | ||
2822 | char *kbuf = NULL; | ||
2823 | |||
2824 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
2825 | |||
2826 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | ||
2827 | VB_AGE_TEST_WITH_RETURN(dev_priv); | ||
2828 | |||
2829 | if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) { | ||
2830 | return -EINVAL; | ||
2831 | } | ||
2832 | |||
2833 | /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid | ||
2834 | * races between checking values and using those values in other code, | ||
2835 | * and simply to avoid a lot of function calls to copy in data. | ||
2836 | */ | ||
2837 | orig_bufsz = cmdbuf->bufsz; | ||
2838 | if (orig_bufsz != 0) { | ||
2839 | kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER); | ||
2840 | if (kbuf == NULL) | ||
2841 | return -ENOMEM; | ||
2842 | if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf, | ||
2843 | cmdbuf->bufsz)) { | ||
2844 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); | ||
2845 | return -EFAULT; | ||
2846 | } | ||
2847 | cmdbuf->buf = kbuf; | ||
2848 | } | ||
2849 | |||
2850 | orig_nbox = cmdbuf->nbox; | ||
2851 | |||
2852 | if (dev_priv->microcode_version == UCODE_R300) { | ||
2853 | int temp; | ||
2854 | temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); | ||
2855 | |||
2856 | if (orig_bufsz != 0) | ||
2857 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); | ||
2858 | |||
2859 | return temp; | ||
2860 | } | ||
2861 | |||
2862 | /* microcode_version != r300 */ | ||
2863 | while (cmdbuf->bufsz >= sizeof(header)) { | ||
2864 | |||
2865 | header.i = *(int *)cmdbuf->buf; | ||
2866 | cmdbuf->buf += sizeof(header); | ||
2867 | cmdbuf->bufsz -= sizeof(header); | ||
2868 | |||
2869 | switch (header.header.cmd_type) { | ||
2870 | case RADEON_CMD_PACKET: | ||
2871 | DRM_DEBUG("RADEON_CMD_PACKET\n"); | ||
2872 | if (radeon_emit_packets | ||
2873 | (dev_priv, file_priv, header, cmdbuf)) { | ||
2874 | DRM_ERROR("radeon_emit_packets failed\n"); | ||
2875 | goto err; | ||
2876 | } | ||
2877 | break; | ||
2878 | |||
2879 | case RADEON_CMD_SCALARS: | ||
2880 | DRM_DEBUG("RADEON_CMD_SCALARS\n"); | ||
2881 | if (radeon_emit_scalars(dev_priv, header, cmdbuf)) { | ||
2882 | DRM_ERROR("radeon_emit_scalars failed\n"); | ||
2883 | goto err; | ||
2884 | } | ||
2885 | break; | ||
2886 | |||
2887 | case RADEON_CMD_VECTORS: | ||
2888 | DRM_DEBUG("RADEON_CMD_VECTORS\n"); | ||
2889 | if (radeon_emit_vectors(dev_priv, header, cmdbuf)) { | ||
2890 | DRM_ERROR("radeon_emit_vectors failed\n"); | ||
2891 | goto err; | ||
2892 | } | ||
2893 | break; | ||
2894 | |||
2895 | case RADEON_CMD_DMA_DISCARD: | ||
2896 | DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); | ||
2897 | idx = header.dma.buf_idx; | ||
2898 | if (idx < 0 || idx >= dma->buf_count) { | ||
2899 | DRM_ERROR("buffer index %d (of %d max)\n", | ||
2900 | idx, dma->buf_count - 1); | ||
2901 | goto err; | ||
2902 | } | ||
2903 | |||
2904 | buf = dma->buflist[idx]; | ||
2905 | if (buf->file_priv != file_priv || buf->pending) { | ||
2906 | DRM_ERROR("bad buffer %p %p %d\n", | ||
2907 | buf->file_priv, file_priv, | ||
2908 | buf->pending); | ||
2909 | goto err; | ||
2910 | } | ||
2911 | |||
2912 | radeon_cp_discard_buffer(dev, buf); | ||
2913 | break; | ||
2914 | |||
2915 | case RADEON_CMD_PACKET3: | ||
2916 | DRM_DEBUG("RADEON_CMD_PACKET3\n"); | ||
2917 | if (radeon_emit_packet3(dev, file_priv, cmdbuf)) { | ||
2918 | DRM_ERROR("radeon_emit_packet3 failed\n"); | ||
2919 | goto err; | ||
2920 | } | ||
2921 | break; | ||
2922 | |||
2923 | case RADEON_CMD_PACKET3_CLIP: | ||
2924 | DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); | ||
2925 | if (radeon_emit_packet3_cliprect | ||
2926 | (dev, file_priv, cmdbuf, orig_nbox)) { | ||
2927 | DRM_ERROR("radeon_emit_packet3_clip failed\n"); | ||
2928 | goto err; | ||
2929 | } | ||
2930 | break; | ||
2931 | |||
2932 | case RADEON_CMD_SCALARS2: | ||
2933 | DRM_DEBUG("RADEON_CMD_SCALARS2\n"); | ||
2934 | if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) { | ||
2935 | DRM_ERROR("radeon_emit_scalars2 failed\n"); | ||
2936 | goto err; | ||
2937 | } | ||
2938 | break; | ||
2939 | |||
2940 | case RADEON_CMD_WAIT: | ||
2941 | DRM_DEBUG("RADEON_CMD_WAIT\n"); | ||
2942 | if (radeon_emit_wait(dev, header.wait.flags)) { | ||
2943 | DRM_ERROR("radeon_emit_wait failed\n"); | ||
2944 | goto err; | ||
2945 | } | ||
2946 | break; | ||
2947 | case RADEON_CMD_VECLINEAR: | ||
2948 | DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); | ||
2949 | if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) { | ||
2950 | DRM_ERROR("radeon_emit_veclinear failed\n"); | ||
2951 | goto err; | ||
2952 | } | ||
2953 | break; | ||
2954 | |||
2955 | default: | ||
2956 | DRM_ERROR("bad cmd_type %d at %p\n", | ||
2957 | header.header.cmd_type, | ||
2958 | cmdbuf->buf - sizeof(header)); | ||
2959 | goto err; | ||
2960 | } | ||
2961 | } | ||
2962 | |||
2963 | if (orig_bufsz != 0) | ||
2964 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); | ||
2965 | |||
2966 | DRM_DEBUG("DONE\n"); | ||
2967 | COMMIT_RING(); | ||
2968 | return 0; | ||
2969 | |||
2970 | err: | ||
2971 | if (orig_bufsz != 0) | ||
2972 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); | ||
2973 | return -EINVAL; | ||
2974 | } | ||
2975 | |||
2976 | static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
2977 | { | ||
2978 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2979 | drm_radeon_getparam_t *param = data; | ||
2980 | int value; | ||
2981 | |||
2982 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | ||
2983 | |||
2984 | switch (param->param) { | ||
2985 | case RADEON_PARAM_GART_BUFFER_OFFSET: | ||
2986 | value = dev_priv->gart_buffers_offset; | ||
2987 | break; | ||
2988 | case RADEON_PARAM_LAST_FRAME: | ||
2989 | dev_priv->stats.last_frame_reads++; | ||
2990 | value = GET_SCRATCH(0); | ||
2991 | break; | ||
2992 | case RADEON_PARAM_LAST_DISPATCH: | ||
2993 | value = GET_SCRATCH(1); | ||
2994 | break; | ||
2995 | case RADEON_PARAM_LAST_CLEAR: | ||
2996 | dev_priv->stats.last_clear_reads++; | ||
2997 | value = GET_SCRATCH(2); | ||
2998 | break; | ||
2999 | case RADEON_PARAM_IRQ_NR: | ||
3000 | value = dev->irq; | ||
3001 | break; | ||
3002 | case RADEON_PARAM_GART_BASE: | ||
3003 | value = dev_priv->gart_vm_start; | ||
3004 | break; | ||
3005 | case RADEON_PARAM_REGISTER_HANDLE: | ||
3006 | value = dev_priv->mmio->offset; | ||
3007 | break; | ||
3008 | case RADEON_PARAM_STATUS_HANDLE: | ||
3009 | value = dev_priv->ring_rptr_offset; | ||
3010 | break; | ||
3011 | #if BITS_PER_LONG == 32 | ||
3012 | /* | ||
3013 | * This ioctl() doesn't work on 64-bit platforms because hw_lock is a | ||
3014 | * pointer which can't fit into an int-sized variable. According to | ||
3015 | * Michel Dänzer, the ioctl() is only used on embedded platforms, so | ||
3016 | * not supporting it shouldn't be a problem. If the same functionality | ||
3017 | * is needed on 64-bit platforms, a new ioctl() would have to be added, | ||
3018 | * so backwards-compatibility for the embedded platforms can be | ||
3019 | * maintained. --davidm 4-Feb-2004. | ||
3020 | */ | ||
3021 | case RADEON_PARAM_SAREA_HANDLE: | ||
3022 | /* The lock is the first dword in the sarea. */ | ||
3023 | value = (long)dev->lock.hw_lock; | ||
3024 | break; | ||
3025 | #endif | ||
3026 | case RADEON_PARAM_GART_TEX_HANDLE: | ||
3027 | value = dev_priv->gart_textures_offset; | ||
3028 | break; | ||
3029 | case RADEON_PARAM_SCRATCH_OFFSET: | ||
3030 | if (!dev_priv->writeback_works) | ||
3031 | return -EINVAL; | ||
3032 | value = RADEON_SCRATCH_REG_OFFSET; | ||
3033 | break; | ||
3034 | case RADEON_PARAM_CARD_TYPE: | ||
3035 | if (dev_priv->flags & RADEON_IS_PCIE) | ||
3036 | value = RADEON_CARD_PCIE; | ||
3037 | else if (dev_priv->flags & RADEON_IS_AGP) | ||
3038 | value = RADEON_CARD_AGP; | ||
3039 | else | ||
3040 | value = RADEON_CARD_PCI; | ||
3041 | break; | ||
3042 | case RADEON_PARAM_VBLANK_CRTC: | ||
3043 | value = radeon_vblank_crtc_get(dev); | ||
3044 | break; | ||
3045 | case RADEON_PARAM_FB_LOCATION: | ||
3046 | value = radeon_read_fb_location(dev_priv); | ||
3047 | break; | ||
3048 | case RADEON_PARAM_NUM_GB_PIPES: | ||
3049 | value = dev_priv->num_gb_pipes; | ||
3050 | break; | ||
3051 | default: | ||
3052 | DRM_DEBUG("Invalid parameter %d\n", param->param); | ||
3053 | return -EINVAL; | ||
3054 | } | ||
3055 | |||
3056 | if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { | ||
3057 | DRM_ERROR("copy_to_user\n"); | ||
3058 | return -EFAULT; | ||
3059 | } | ||
3060 | |||
3061 | return 0; | ||
3062 | } | ||
3063 | |||
3064 | static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
3065 | { | ||
3066 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
3067 | drm_radeon_setparam_t *sp = data; | ||
3068 | struct drm_radeon_driver_file_fields *radeon_priv; | ||
3069 | |||
3070 | switch (sp->param) { | ||
3071 | case RADEON_SETPARAM_FB_LOCATION: | ||
3072 | radeon_priv = file_priv->driver_priv; | ||
3073 | radeon_priv->radeon_fb_delta = dev_priv->fb_location - | ||
3074 | sp->value; | ||
3075 | break; | ||
3076 | case RADEON_SETPARAM_SWITCH_TILING: | ||
3077 | if (sp->value == 0) { | ||
3078 | DRM_DEBUG("color tiling disabled\n"); | ||
3079 | dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; | ||
3080 | dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; | ||
3081 | dev_priv->sarea_priv->tiling_enabled = 0; | ||
3082 | } else if (sp->value == 1) { | ||
3083 | DRM_DEBUG("color tiling enabled\n"); | ||
3084 | dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; | ||
3085 | dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; | ||
3086 | dev_priv->sarea_priv->tiling_enabled = 1; | ||
3087 | } | ||
3088 | break; | ||
3089 | case RADEON_SETPARAM_PCIGART_LOCATION: | ||
3090 | dev_priv->pcigart_offset = sp->value; | ||
3091 | dev_priv->pcigart_offset_set = 1; | ||
3092 | break; | ||
3093 | case RADEON_SETPARAM_NEW_MEMMAP: | ||
3094 | dev_priv->new_memmap = sp->value; | ||
3095 | break; | ||
3096 | case RADEON_SETPARAM_PCIGART_TABLE_SIZE: | ||
3097 | dev_priv->gart_info.table_size = sp->value; | ||
3098 | if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) | ||
3099 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; | ||
3100 | break; | ||
3101 | case RADEON_SETPARAM_VBLANK_CRTC: | ||
3102 | return radeon_vblank_crtc_set(dev, sp->value); | ||
3103 | break; | ||
3104 | default: | ||
3105 | DRM_DEBUG("Invalid parameter %d\n", sp->param); | ||
3106 | return -EINVAL; | ||
3107 | } | ||
3108 | |||
3109 | return 0; | ||
3110 | } | ||
3111 | |||
3112 | /* When a client dies: | ||
3113 | * - Check for and clean up flipped page state | ||
3114 | * - Free any alloced GART memory. | ||
3115 | * - Free any alloced radeon surfaces. | ||
3116 | * | ||
3117 | * DRM infrastructure takes care of reclaiming dma buffers. | ||
3118 | */ | ||
3119 | void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) | ||
3120 | { | ||
3121 | if (dev->dev_private) { | ||
3122 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
3123 | dev_priv->page_flipping = 0; | ||
3124 | radeon_mem_release(file_priv, dev_priv->gart_heap); | ||
3125 | radeon_mem_release(file_priv, dev_priv->fb_heap); | ||
3126 | radeon_surfaces_release(file_priv, dev_priv); | ||
3127 | } | ||
3128 | } | ||
3129 | |||
3130 | void radeon_driver_lastclose(struct drm_device *dev) | ||
3131 | { | ||
3132 | if (dev->dev_private) { | ||
3133 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
3134 | |||
3135 | if (dev_priv->sarea_priv && | ||
3136 | dev_priv->sarea_priv->pfCurrentPage != 0) | ||
3137 | radeon_cp_dispatch_flip(dev); | ||
3138 | } | ||
3139 | |||
3140 | radeon_do_release(dev); | ||
3141 | } | ||
3142 | |||
3143 | int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) | ||
3144 | { | ||
3145 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
3146 | struct drm_radeon_driver_file_fields *radeon_priv; | ||
3147 | |||
3148 | DRM_DEBUG("\n"); | ||
3149 | radeon_priv = | ||
3150 | (struct drm_radeon_driver_file_fields *) | ||
3151 | drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES); | ||
3152 | |||
3153 | if (!radeon_priv) | ||
3154 | return -ENOMEM; | ||
3155 | |||
3156 | file_priv->driver_priv = radeon_priv; | ||
3157 | |||
3158 | if (dev_priv) | ||
3159 | radeon_priv->radeon_fb_delta = dev_priv->fb_location; | ||
3160 | else | ||
3161 | radeon_priv->radeon_fb_delta = 0; | ||
3162 | return 0; | ||
3163 | } | ||
3164 | |||
3165 | void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) | ||
3166 | { | ||
3167 | struct drm_radeon_driver_file_fields *radeon_priv = | ||
3168 | file_priv->driver_priv; | ||
3169 | |||
3170 | drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES); | ||
3171 | } | ||
3172 | |||
3173 | struct drm_ioctl_desc radeon_ioctls[] = { | ||
3174 | DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3175 | DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3176 | DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3177 | DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3178 | DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), | ||
3179 | DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), | ||
3180 | DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH), | ||
3181 | DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), | ||
3182 | DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH), | ||
3183 | DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), | ||
3184 | DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), | ||
3185 | DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH), | ||
3186 | DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), | ||
3187 | DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), | ||
3188 | DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3189 | DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), | ||
3190 | DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), | ||
3191 | DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), | ||
3192 | DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH), | ||
3193 | DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), | ||
3194 | DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH), | ||
3195 | DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
3196 | DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), | ||
3197 | DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), | ||
3198 | DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), | ||
3199 | DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), | ||
3200 | DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH) | ||
3201 | }; | ||
3202 | |||
3203 | int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); | ||