xref: /trueos/sys/dev/drm/r128_state.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /* r128_state.c -- State support for r128 -*- linux-c -*-
2  * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
3  */
4 /*-
5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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  *    Gareth Hughes <gareth@valinux.com>
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include "dev/drm/drmP.h"
35 #include "dev/drm/drm.h"
36 #include "dev/drm/r128_drm.h"
37 #include "dev/drm/r128_drv.h"
38 
39 /* ================================================================
40  * CCE hardware state programming functions
41  */
42 
r128_emit_clip_rects(drm_r128_private_t * dev_priv,struct drm_clip_rect * boxes,int count)43 static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
44 				 struct drm_clip_rect * boxes, int count)
45 {
46 	u32 aux_sc_cntl = 0x00000000;
47 	RING_LOCALS;
48 	DRM_DEBUG("\n");
49 
50 	BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
51 
52 	if (count >= 1) {
53 		OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
54 		OUT_RING(boxes[0].x1);
55 		OUT_RING(boxes[0].x2 - 1);
56 		OUT_RING(boxes[0].y1);
57 		OUT_RING(boxes[0].y2 - 1);
58 
59 		aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
60 	}
61 	if (count >= 2) {
62 		OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
63 		OUT_RING(boxes[1].x1);
64 		OUT_RING(boxes[1].x2 - 1);
65 		OUT_RING(boxes[1].y1);
66 		OUT_RING(boxes[1].y2 - 1);
67 
68 		aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
69 	}
70 	if (count >= 3) {
71 		OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
72 		OUT_RING(boxes[2].x1);
73 		OUT_RING(boxes[2].x2 - 1);
74 		OUT_RING(boxes[2].y1);
75 		OUT_RING(boxes[2].y2 - 1);
76 
77 		aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
78 	}
79 
80 	OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
81 	OUT_RING(aux_sc_cntl);
82 
83 	ADVANCE_RING();
84 }
85 
r128_emit_core(drm_r128_private_t * dev_priv)86 static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
87 {
88 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
89 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
90 	RING_LOCALS;
91 	DRM_DEBUG("\n");
92 
93 	BEGIN_RING(2);
94 
95 	OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
96 	OUT_RING(ctx->scale_3d_cntl);
97 
98 	ADVANCE_RING();
99 }
100 
r128_emit_context(drm_r128_private_t * dev_priv)101 static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
102 {
103 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
104 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
105 	RING_LOCALS;
106 	DRM_DEBUG("\n");
107 
108 	BEGIN_RING(13);
109 
110 	OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
111 	OUT_RING(ctx->dst_pitch_offset_c);
112 	OUT_RING(ctx->dp_gui_master_cntl_c);
113 	OUT_RING(ctx->sc_top_left_c);
114 	OUT_RING(ctx->sc_bottom_right_c);
115 	OUT_RING(ctx->z_offset_c);
116 	OUT_RING(ctx->z_pitch_c);
117 	OUT_RING(ctx->z_sten_cntl_c);
118 	OUT_RING(ctx->tex_cntl_c);
119 	OUT_RING(ctx->misc_3d_state_cntl_reg);
120 	OUT_RING(ctx->texture_clr_cmp_clr_c);
121 	OUT_RING(ctx->texture_clr_cmp_msk_c);
122 	OUT_RING(ctx->fog_color_c);
123 
124 	ADVANCE_RING();
125 }
126 
r128_emit_setup(drm_r128_private_t * dev_priv)127 static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
128 {
129 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
130 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
131 	RING_LOCALS;
132 	DRM_DEBUG("\n");
133 
134 	BEGIN_RING(3);
135 
136 	OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
137 	OUT_RING(ctx->setup_cntl);
138 	OUT_RING(ctx->pm4_vc_fpu_setup);
139 
140 	ADVANCE_RING();
141 }
142 
r128_emit_masks(drm_r128_private_t * dev_priv)143 static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
144 {
145 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
146 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
147 	RING_LOCALS;
148 	DRM_DEBUG("\n");
149 
150 	BEGIN_RING(5);
151 
152 	OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
153 	OUT_RING(ctx->dp_write_mask);
154 
155 	OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
156 	OUT_RING(ctx->sten_ref_mask_c);
157 	OUT_RING(ctx->plane_3d_mask_c);
158 
159 	ADVANCE_RING();
160 }
161 
r128_emit_window(drm_r128_private_t * dev_priv)162 static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
163 {
164 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
165 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
166 	RING_LOCALS;
167 	DRM_DEBUG("\n");
168 
169 	BEGIN_RING(2);
170 
171 	OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
172 	OUT_RING(ctx->window_xy_offset);
173 
174 	ADVANCE_RING();
175 }
176 
r128_emit_tex0(drm_r128_private_t * dev_priv)177 static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
178 {
179 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
180 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
181 	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
182 	int i;
183 	RING_LOCALS;
184 	DRM_DEBUG("\n");
185 
186 	BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
187 
188 	OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
189 			     2 + R128_MAX_TEXTURE_LEVELS));
190 	OUT_RING(tex->tex_cntl);
191 	OUT_RING(tex->tex_combine_cntl);
192 	OUT_RING(ctx->tex_size_pitch_c);
193 	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
194 		OUT_RING(tex->tex_offset[i]);
195 	}
196 
197 	OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
198 	OUT_RING(ctx->constant_color_c);
199 	OUT_RING(tex->tex_border_color);
200 
201 	ADVANCE_RING();
202 }
203 
r128_emit_tex1(drm_r128_private_t * dev_priv)204 static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
205 {
206 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
207 	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
208 	int i;
209 	RING_LOCALS;
210 	DRM_DEBUG("\n");
211 
212 	BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
213 
214 	OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
215 	OUT_RING(tex->tex_cntl);
216 	OUT_RING(tex->tex_combine_cntl);
217 	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
218 		OUT_RING(tex->tex_offset[i]);
219 	}
220 
221 	OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
222 	OUT_RING(tex->tex_border_color);
223 
224 	ADVANCE_RING();
225 }
226 
r128_emit_state(drm_r128_private_t * dev_priv)227 static void r128_emit_state(drm_r128_private_t * dev_priv)
228 {
229 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
230 	unsigned int dirty = sarea_priv->dirty;
231 
232 	DRM_DEBUG("dirty=0x%08x\n", dirty);
233 
234 	if (dirty & R128_UPLOAD_CORE) {
235 		r128_emit_core(dev_priv);
236 		sarea_priv->dirty &= ~R128_UPLOAD_CORE;
237 	}
238 
239 	if (dirty & R128_UPLOAD_CONTEXT) {
240 		r128_emit_context(dev_priv);
241 		sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
242 	}
243 
244 	if (dirty & R128_UPLOAD_SETUP) {
245 		r128_emit_setup(dev_priv);
246 		sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
247 	}
248 
249 	if (dirty & R128_UPLOAD_MASKS) {
250 		r128_emit_masks(dev_priv);
251 		sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
252 	}
253 
254 	if (dirty & R128_UPLOAD_WINDOW) {
255 		r128_emit_window(dev_priv);
256 		sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
257 	}
258 
259 	if (dirty & R128_UPLOAD_TEX0) {
260 		r128_emit_tex0(dev_priv);
261 		sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
262 	}
263 
264 	if (dirty & R128_UPLOAD_TEX1) {
265 		r128_emit_tex1(dev_priv);
266 		sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
267 	}
268 
269 	/* Turn off the texture cache flushing */
270 	sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
271 
272 	sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
273 }
274 
275 #if R128_PERFORMANCE_BOXES
276 /* ================================================================
277  * Performance monitoring functions
278  */
279 
r128_clear_box(drm_r128_private_t * dev_priv,int x,int y,int w,int h,int r,int g,int b)280 static void r128_clear_box(drm_r128_private_t * dev_priv,
281 			   int x, int y, int w, int h, int r, int g, int b)
282 {
283 	u32 pitch, offset;
284 	u32 fb_bpp, color;
285 	RING_LOCALS;
286 
287 	switch (dev_priv->fb_bpp) {
288 	case 16:
289 		fb_bpp = R128_GMC_DST_16BPP;
290 		color = (((r & 0xf8) << 8) |
291 			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
292 		break;
293 	case 24:
294 		fb_bpp = R128_GMC_DST_24BPP;
295 		color = ((r << 16) | (g << 8) | b);
296 		break;
297 	case 32:
298 		fb_bpp = R128_GMC_DST_32BPP;
299 		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
300 		break;
301 	default:
302 		return;
303 	}
304 
305 	offset = dev_priv->back_offset;
306 	pitch = dev_priv->back_pitch >> 3;
307 
308 	BEGIN_RING(6);
309 
310 	OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
311 	OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
312 		 R128_GMC_BRUSH_SOLID_COLOR |
313 		 fb_bpp |
314 		 R128_GMC_SRC_DATATYPE_COLOR |
315 		 R128_ROP3_P |
316 		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
317 
318 	OUT_RING((pitch << 21) | (offset >> 5));
319 	OUT_RING(color);
320 
321 	OUT_RING((x << 16) | y);
322 	OUT_RING((w << 16) | h);
323 
324 	ADVANCE_RING();
325 }
326 
r128_cce_performance_boxes(drm_r128_private_t * dev_priv)327 static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
328 {
329 	if (atomic_read(&dev_priv->idle_count) == 0) {
330 		r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
331 	} else {
332 		atomic_set(&dev_priv->idle_count, 0);
333 	}
334 }
335 
336 #endif
337 
338 /* ================================================================
339  * CCE command dispatch functions
340  */
341 
r128_print_dirty(const char * msg,unsigned int flags)342 static void r128_print_dirty(const char *msg, unsigned int flags)
343 {
344 	DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
345 		 msg,
346 		 flags,
347 		 (flags & R128_UPLOAD_CORE) ? "core, " : "",
348 		 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
349 		 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
350 		 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
351 		 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
352 		 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
353 		 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
354 		 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
355 		 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
356 }
357 
r128_cce_dispatch_clear(struct drm_device * dev,drm_r128_clear_t * clear)358 static void r128_cce_dispatch_clear(struct drm_device * dev,
359 				    drm_r128_clear_t * clear)
360 {
361 	drm_r128_private_t *dev_priv = dev->dev_private;
362 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
363 	int nbox = sarea_priv->nbox;
364 	struct drm_clip_rect *pbox = sarea_priv->boxes;
365 	unsigned int flags = clear->flags;
366 	int i;
367 	RING_LOCALS;
368 	DRM_DEBUG("\n");
369 
370 	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
371 		unsigned int tmp = flags;
372 
373 		flags &= ~(R128_FRONT | R128_BACK);
374 		if (tmp & R128_FRONT)
375 			flags |= R128_BACK;
376 		if (tmp & R128_BACK)
377 			flags |= R128_FRONT;
378 	}
379 
380 	for (i = 0; i < nbox; i++) {
381 		int x = pbox[i].x1;
382 		int y = pbox[i].y1;
383 		int w = pbox[i].x2 - x;
384 		int h = pbox[i].y2 - y;
385 
386 		DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
387 			  pbox[i].x1, pbox[i].y1, pbox[i].x2,
388 			  pbox[i].y2, flags);
389 
390 		if (flags & (R128_FRONT | R128_BACK)) {
391 			BEGIN_RING(2);
392 
393 			OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
394 			OUT_RING(clear->color_mask);
395 
396 			ADVANCE_RING();
397 		}
398 
399 		if (flags & R128_FRONT) {
400 			BEGIN_RING(6);
401 
402 			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
403 			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
404 				 R128_GMC_BRUSH_SOLID_COLOR |
405 				 (dev_priv->color_fmt << 8) |
406 				 R128_GMC_SRC_DATATYPE_COLOR |
407 				 R128_ROP3_P |
408 				 R128_GMC_CLR_CMP_CNTL_DIS |
409 				 R128_GMC_AUX_CLIP_DIS);
410 
411 			OUT_RING(dev_priv->front_pitch_offset_c);
412 			OUT_RING(clear->clear_color);
413 
414 			OUT_RING((x << 16) | y);
415 			OUT_RING((w << 16) | h);
416 
417 			ADVANCE_RING();
418 		}
419 
420 		if (flags & R128_BACK) {
421 			BEGIN_RING(6);
422 
423 			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
424 			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
425 				 R128_GMC_BRUSH_SOLID_COLOR |
426 				 (dev_priv->color_fmt << 8) |
427 				 R128_GMC_SRC_DATATYPE_COLOR |
428 				 R128_ROP3_P |
429 				 R128_GMC_CLR_CMP_CNTL_DIS |
430 				 R128_GMC_AUX_CLIP_DIS);
431 
432 			OUT_RING(dev_priv->back_pitch_offset_c);
433 			OUT_RING(clear->clear_color);
434 
435 			OUT_RING((x << 16) | y);
436 			OUT_RING((w << 16) | h);
437 
438 			ADVANCE_RING();
439 		}
440 
441 		if (flags & R128_DEPTH) {
442 			BEGIN_RING(6);
443 
444 			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
445 			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
446 				 R128_GMC_BRUSH_SOLID_COLOR |
447 				 (dev_priv->depth_fmt << 8) |
448 				 R128_GMC_SRC_DATATYPE_COLOR |
449 				 R128_ROP3_P |
450 				 R128_GMC_CLR_CMP_CNTL_DIS |
451 				 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
452 
453 			OUT_RING(dev_priv->depth_pitch_offset_c);
454 			OUT_RING(clear->clear_depth);
455 
456 			OUT_RING((x << 16) | y);
457 			OUT_RING((w << 16) | h);
458 
459 			ADVANCE_RING();
460 		}
461 	}
462 }
463 
r128_cce_dispatch_swap(struct drm_device * dev)464 static void r128_cce_dispatch_swap(struct drm_device * dev)
465 {
466 	drm_r128_private_t *dev_priv = dev->dev_private;
467 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
468 	int nbox = sarea_priv->nbox;
469 	struct drm_clip_rect *pbox = sarea_priv->boxes;
470 	int i;
471 	RING_LOCALS;
472 	DRM_DEBUG("\n");
473 
474 #if R128_PERFORMANCE_BOXES
475 	/* Do some trivial performance monitoring...
476 	 */
477 	r128_cce_performance_boxes(dev_priv);
478 #endif
479 
480 	for (i = 0; i < nbox; i++) {
481 		int x = pbox[i].x1;
482 		int y = pbox[i].y1;
483 		int w = pbox[i].x2 - x;
484 		int h = pbox[i].y2 - y;
485 
486 		BEGIN_RING(7);
487 
488 		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
489 		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
490 			 R128_GMC_DST_PITCH_OFFSET_CNTL |
491 			 R128_GMC_BRUSH_NONE |
492 			 (dev_priv->color_fmt << 8) |
493 			 R128_GMC_SRC_DATATYPE_COLOR |
494 			 R128_ROP3_S |
495 			 R128_DP_SRC_SOURCE_MEMORY |
496 			 R128_GMC_CLR_CMP_CNTL_DIS |
497 			 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
498 
499 		/* Make this work even if front & back are flipped:
500 		 */
501 		if (dev_priv->current_page == 0) {
502 			OUT_RING(dev_priv->back_pitch_offset_c);
503 			OUT_RING(dev_priv->front_pitch_offset_c);
504 		} else {
505 			OUT_RING(dev_priv->front_pitch_offset_c);
506 			OUT_RING(dev_priv->back_pitch_offset_c);
507 		}
508 
509 		OUT_RING((x << 16) | y);
510 		OUT_RING((x << 16) | y);
511 		OUT_RING((w << 16) | h);
512 
513 		ADVANCE_RING();
514 	}
515 
516 	/* Increment the frame counter.  The client-side 3D driver must
517 	 * throttle the framerate by waiting for this value before
518 	 * performing the swapbuffer ioctl.
519 	 */
520 	dev_priv->sarea_priv->last_frame++;
521 
522 	BEGIN_RING(2);
523 
524 	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
525 	OUT_RING(dev_priv->sarea_priv->last_frame);
526 
527 	ADVANCE_RING();
528 }
529 
r128_cce_dispatch_flip(struct drm_device * dev)530 static void r128_cce_dispatch_flip(struct drm_device * dev)
531 {
532 	drm_r128_private_t *dev_priv = dev->dev_private;
533 	RING_LOCALS;
534 	DRM_DEBUG("page=%d pfCurrentPage=%d\n",
535 		  dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
536 
537 #if R128_PERFORMANCE_BOXES
538 	/* Do some trivial performance monitoring...
539 	 */
540 	r128_cce_performance_boxes(dev_priv);
541 #endif
542 
543 	BEGIN_RING(4);
544 
545 	R128_WAIT_UNTIL_PAGE_FLIPPED();
546 	OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
547 
548 	if (dev_priv->current_page == 0) {
549 		OUT_RING(dev_priv->back_offset);
550 	} else {
551 		OUT_RING(dev_priv->front_offset);
552 	}
553 
554 	ADVANCE_RING();
555 
556 	/* Increment the frame counter.  The client-side 3D driver must
557 	 * throttle the framerate by waiting for this value before
558 	 * performing the swapbuffer ioctl.
559 	 */
560 	dev_priv->sarea_priv->last_frame++;
561 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
562 	    1 - dev_priv->current_page;
563 
564 	BEGIN_RING(2);
565 
566 	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
567 	OUT_RING(dev_priv->sarea_priv->last_frame);
568 
569 	ADVANCE_RING();
570 }
571 
r128_cce_dispatch_vertex(struct drm_device * dev,struct drm_buf * buf)572 static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
573 {
574 	drm_r128_private_t *dev_priv = dev->dev_private;
575 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
576 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
577 	int format = sarea_priv->vc_format;
578 	int offset = buf->bus_address;
579 	int size = buf->used;
580 	int prim = buf_priv->prim;
581 	int i = 0;
582 	RING_LOCALS;
583 	DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
584 
585 	if (0)
586 		r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
587 
588 	if (buf->used) {
589 		buf_priv->dispatched = 1;
590 
591 		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
592 			r128_emit_state(dev_priv);
593 		}
594 
595 		do {
596 			/* Emit the next set of up to three cliprects */
597 			if (i < sarea_priv->nbox) {
598 				r128_emit_clip_rects(dev_priv,
599 						     &sarea_priv->boxes[i],
600 						     sarea_priv->nbox - i);
601 			}
602 
603 			/* Emit the vertex buffer rendering commands */
604 			BEGIN_RING(5);
605 
606 			OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
607 			OUT_RING(offset);
608 			OUT_RING(size);
609 			OUT_RING(format);
610 			OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
611 				 (size << R128_CCE_VC_CNTL_NUM_SHIFT));
612 
613 			ADVANCE_RING();
614 
615 			i += 3;
616 		} while (i < sarea_priv->nbox);
617 	}
618 
619 	if (buf_priv->discard) {
620 		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
621 
622 		/* Emit the vertex buffer age */
623 		BEGIN_RING(2);
624 
625 		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
626 		OUT_RING(buf_priv->age);
627 
628 		ADVANCE_RING();
629 
630 		buf->pending = 1;
631 		buf->used = 0;
632 		/* FIXME: Check dispatched field */
633 		buf_priv->dispatched = 0;
634 	}
635 
636 	dev_priv->sarea_priv->last_dispatch++;
637 
638 	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
639 	sarea_priv->nbox = 0;
640 }
641 
r128_cce_dispatch_indirect(struct drm_device * dev,struct drm_buf * buf,int start,int end)642 static void r128_cce_dispatch_indirect(struct drm_device * dev,
643 				       struct drm_buf * buf, int start, int end)
644 {
645 	drm_r128_private_t *dev_priv = dev->dev_private;
646 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
647 	RING_LOCALS;
648 	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
649 
650 	if (start != end) {
651 		int offset = buf->bus_address + start;
652 		int dwords = (end - start + 3) / sizeof(u32);
653 
654 		/* Indirect buffer data must be an even number of
655 		 * dwords, so if we've been given an odd number we must
656 		 * pad the data with a Type-2 CCE packet.
657 		 */
658 		if (dwords & 1) {
659 			u32 *data = (u32 *)
660 			    ((char *)dev->agp_buffer_map->virtual
661 			     + buf->offset + start);
662 			data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
663 		}
664 
665 		buf_priv->dispatched = 1;
666 
667 		/* Fire off the indirect buffer */
668 		BEGIN_RING(3);
669 
670 		OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
671 		OUT_RING(offset);
672 		OUT_RING(dwords);
673 
674 		ADVANCE_RING();
675 	}
676 
677 	if (buf_priv->discard) {
678 		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
679 
680 		/* Emit the indirect buffer age */
681 		BEGIN_RING(2);
682 
683 		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
684 		OUT_RING(buf_priv->age);
685 
686 		ADVANCE_RING();
687 
688 		buf->pending = 1;
689 		buf->used = 0;
690 		/* FIXME: Check dispatched field */
691 		buf_priv->dispatched = 0;
692 	}
693 
694 	dev_priv->sarea_priv->last_dispatch++;
695 }
696 
r128_cce_dispatch_indices(struct drm_device * dev,struct drm_buf * buf,int start,int end,int count)697 static void r128_cce_dispatch_indices(struct drm_device * dev,
698 				      struct drm_buf * buf,
699 				      int start, int end, int count)
700 {
701 	drm_r128_private_t *dev_priv = dev->dev_private;
702 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
703 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
704 	int format = sarea_priv->vc_format;
705 	int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
706 	int prim = buf_priv->prim;
707 	u32 *data;
708 	int dwords;
709 	int i = 0;
710 	RING_LOCALS;
711 	DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
712 
713 	if (0)
714 		r128_print_dirty("dispatch_indices", sarea_priv->dirty);
715 
716 	if (start != end) {
717 		buf_priv->dispatched = 1;
718 
719 		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
720 			r128_emit_state(dev_priv);
721 		}
722 
723 		dwords = (end - start + 3) / sizeof(u32);
724 
725 		data = (u32 *) ((char *)dev->agp_buffer_map->virtual
726 				+ buf->offset + start);
727 
728 		data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
729 						  dwords - 2));
730 
731 		data[1] = cpu_to_le32(offset);
732 		data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
733 		data[3] = cpu_to_le32(format);
734 		data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
735 				       (count << 16)));
736 
737 		if (count & 0x1) {
738 #ifdef __LITTLE_ENDIAN
739 			data[dwords - 1] &= 0x0000ffff;
740 #else
741 			data[dwords - 1] &= 0xffff0000;
742 #endif
743 		}
744 
745 		do {
746 			/* Emit the next set of up to three cliprects */
747 			if (i < sarea_priv->nbox) {
748 				r128_emit_clip_rects(dev_priv,
749 						     &sarea_priv->boxes[i],
750 						     sarea_priv->nbox - i);
751 			}
752 
753 			r128_cce_dispatch_indirect(dev, buf, start, end);
754 
755 			i += 3;
756 		} while (i < sarea_priv->nbox);
757 	}
758 
759 	if (buf_priv->discard) {
760 		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
761 
762 		/* Emit the vertex buffer age */
763 		BEGIN_RING(2);
764 
765 		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
766 		OUT_RING(buf_priv->age);
767 
768 		ADVANCE_RING();
769 
770 		buf->pending = 1;
771 		/* FIXME: Check dispatched field */
772 		buf_priv->dispatched = 0;
773 	}
774 
775 	dev_priv->sarea_priv->last_dispatch++;
776 
777 	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
778 	sarea_priv->nbox = 0;
779 }
780 
r128_cce_dispatch_blit(struct drm_device * dev,struct drm_file * file_priv,drm_r128_blit_t * blit)781 static int r128_cce_dispatch_blit(struct drm_device * dev,
782 				  struct drm_file *file_priv,
783 				  drm_r128_blit_t * blit)
784 {
785 	drm_r128_private_t *dev_priv = dev->dev_private;
786 	struct drm_device_dma *dma = dev->dma;
787 	struct drm_buf *buf;
788 	drm_r128_buf_priv_t *buf_priv;
789 	u32 *data;
790 	int dword_shift, dwords;
791 	RING_LOCALS;
792 	DRM_DEBUG("\n");
793 
794 	/* The compiler won't optimize away a division by a variable,
795 	 * even if the only legal values are powers of two.  Thus, we'll
796 	 * use a shift instead.
797 	 */
798 	switch (blit->format) {
799 	case R128_DATATYPE_ARGB8888:
800 		dword_shift = 0;
801 		break;
802 	case R128_DATATYPE_ARGB1555:
803 	case R128_DATATYPE_RGB565:
804 	case R128_DATATYPE_ARGB4444:
805 	case R128_DATATYPE_YVYU422:
806 	case R128_DATATYPE_VYUY422:
807 		dword_shift = 1;
808 		break;
809 	case R128_DATATYPE_CI8:
810 	case R128_DATATYPE_RGB8:
811 		dword_shift = 2;
812 		break;
813 	default:
814 		DRM_ERROR("invalid blit format %d\n", blit->format);
815 		return -EINVAL;
816 	}
817 
818 	/* Flush the pixel cache, and mark the contents as Read Invalid.
819 	 * This ensures no pixel data gets mixed up with the texture
820 	 * data from the host data blit, otherwise part of the texture
821 	 * image may be corrupted.
822 	 */
823 	BEGIN_RING(2);
824 
825 	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
826 	OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
827 
828 	ADVANCE_RING();
829 
830 	/* Dispatch the indirect buffer.
831 	 */
832 	buf = dma->buflist[blit->idx];
833 	buf_priv = buf->dev_private;
834 
835 	if (buf->file_priv != file_priv) {
836 		DRM_ERROR("process %d using buffer owned by %p\n",
837 			  DRM_CURRENTPID, buf->file_priv);
838 		return -EINVAL;
839 	}
840 	if (buf->pending) {
841 		DRM_ERROR("sending pending buffer %d\n", blit->idx);
842 		return -EINVAL;
843 	}
844 
845 	buf_priv->discard = 1;
846 
847 	dwords = (blit->width * blit->height) >> dword_shift;
848 
849 	data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
850 
851 	data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
852 	data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
853 			       R128_GMC_BRUSH_NONE |
854 			       (blit->format << 8) |
855 			       R128_GMC_SRC_DATATYPE_COLOR |
856 			       R128_ROP3_S |
857 			       R128_DP_SRC_SOURCE_HOST_DATA |
858 			       R128_GMC_CLR_CMP_CNTL_DIS |
859 			       R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
860 
861 	data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
862 	data[3] = cpu_to_le32(0xffffffff);
863 	data[4] = cpu_to_le32(0xffffffff);
864 	data[5] = cpu_to_le32((blit->y << 16) | blit->x);
865 	data[6] = cpu_to_le32((blit->height << 16) | blit->width);
866 	data[7] = cpu_to_le32(dwords);
867 
868 	buf->used = (dwords + 8) * sizeof(u32);
869 
870 	r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
871 
872 	/* Flush the pixel cache after the blit completes.  This ensures
873 	 * the texture data is written out to memory before rendering
874 	 * continues.
875 	 */
876 	BEGIN_RING(2);
877 
878 	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
879 	OUT_RING(R128_PC_FLUSH_GUI);
880 
881 	ADVANCE_RING();
882 
883 	return 0;
884 }
885 
886 /* ================================================================
887  * Tiled depth buffer management
888  *
889  * FIXME: These should all set the destination write mask for when we
890  * have hardware stencil support.
891  */
892 
r128_cce_dispatch_write_span(struct drm_device * dev,drm_r128_depth_t * depth)893 static int r128_cce_dispatch_write_span(struct drm_device * dev,
894 					drm_r128_depth_t * depth)
895 {
896 	drm_r128_private_t *dev_priv = dev->dev_private;
897 	int count, x, y;
898 	u32 *buffer;
899 	u8 *mask;
900 	int i, buffer_size, mask_size;
901 	RING_LOCALS;
902 	DRM_DEBUG("\n");
903 
904 	count = depth->n;
905 	if (count > 4096 || count <= 0)
906 		return -EMSGSIZE;
907 
908 	if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
909 		return -EFAULT;
910 	}
911 	if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
912 		return -EFAULT;
913 	}
914 
915 	buffer_size = depth->n * sizeof(u32);
916 	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
917 	if (buffer == NULL)
918 		return -ENOMEM;
919 	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
920 		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
921 		return -EFAULT;
922 	}
923 
924 	mask_size = depth->n * sizeof(u8);
925 	if (depth->mask) {
926 		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
927 		if (mask == NULL) {
928 			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
929 			return -ENOMEM;
930 		}
931 		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
932 			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
933 			drm_free(mask, mask_size, DRM_MEM_BUFS);
934 			return -EFAULT;
935 		}
936 
937 		for (i = 0; i < count; i++, x++) {
938 			if (mask[i]) {
939 				BEGIN_RING(6);
940 
941 				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
942 				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
943 					 R128_GMC_BRUSH_SOLID_COLOR |
944 					 (dev_priv->depth_fmt << 8) |
945 					 R128_GMC_SRC_DATATYPE_COLOR |
946 					 R128_ROP3_P |
947 					 R128_GMC_CLR_CMP_CNTL_DIS |
948 					 R128_GMC_WR_MSK_DIS);
949 
950 				OUT_RING(dev_priv->depth_pitch_offset_c);
951 				OUT_RING(buffer[i]);
952 
953 				OUT_RING((x << 16) | y);
954 				OUT_RING((1 << 16) | 1);
955 
956 				ADVANCE_RING();
957 			}
958 		}
959 
960 		drm_free(mask, mask_size, DRM_MEM_BUFS);
961 	} else {
962 		for (i = 0; i < count; i++, x++) {
963 			BEGIN_RING(6);
964 
965 			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
966 			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
967 				 R128_GMC_BRUSH_SOLID_COLOR |
968 				 (dev_priv->depth_fmt << 8) |
969 				 R128_GMC_SRC_DATATYPE_COLOR |
970 				 R128_ROP3_P |
971 				 R128_GMC_CLR_CMP_CNTL_DIS |
972 				 R128_GMC_WR_MSK_DIS);
973 
974 			OUT_RING(dev_priv->depth_pitch_offset_c);
975 			OUT_RING(buffer[i]);
976 
977 			OUT_RING((x << 16) | y);
978 			OUT_RING((1 << 16) | 1);
979 
980 			ADVANCE_RING();
981 		}
982 	}
983 
984 	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
985 
986 	return 0;
987 }
988 
r128_cce_dispatch_write_pixels(struct drm_device * dev,drm_r128_depth_t * depth)989 static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
990 					  drm_r128_depth_t * depth)
991 {
992 	drm_r128_private_t *dev_priv = dev->dev_private;
993 	int count, *x, *y;
994 	u32 *buffer;
995 	u8 *mask;
996 	int i, xbuf_size, ybuf_size, buffer_size, mask_size;
997 	RING_LOCALS;
998 	DRM_DEBUG("\n");
999 
1000 	count = depth->n;
1001 	if (count > 4096 || count <= 0)
1002 		return -EMSGSIZE;
1003 
1004 	xbuf_size = count * sizeof(*x);
1005 	ybuf_size = count * sizeof(*y);
1006 	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
1007 	if (x == NULL) {
1008 		return -ENOMEM;
1009 	}
1010 	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
1011 	if (y == NULL) {
1012 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1013 		return -ENOMEM;
1014 	}
1015 	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
1016 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1017 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1018 		return -EFAULT;
1019 	}
1020 	if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
1021 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1022 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1023 		return -EFAULT;
1024 	}
1025 
1026 	buffer_size = depth->n * sizeof(u32);
1027 	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
1028 	if (buffer == NULL) {
1029 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1030 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1031 		return -ENOMEM;
1032 	}
1033 	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
1034 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1035 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1036 		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1037 		return -EFAULT;
1038 	}
1039 
1040 	if (depth->mask) {
1041 		mask_size = depth->n * sizeof(u8);
1042 		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
1043 		if (mask == NULL) {
1044 			drm_free(x, xbuf_size, DRM_MEM_BUFS);
1045 			drm_free(y, ybuf_size, DRM_MEM_BUFS);
1046 			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1047 			return -ENOMEM;
1048 		}
1049 		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
1050 			drm_free(x, xbuf_size, DRM_MEM_BUFS);
1051 			drm_free(y, ybuf_size, DRM_MEM_BUFS);
1052 			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1053 			drm_free(mask, mask_size, DRM_MEM_BUFS);
1054 			return -EFAULT;
1055 		}
1056 
1057 		for (i = 0; i < count; i++) {
1058 			if (mask[i]) {
1059 				BEGIN_RING(6);
1060 
1061 				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1062 				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1063 					 R128_GMC_BRUSH_SOLID_COLOR |
1064 					 (dev_priv->depth_fmt << 8) |
1065 					 R128_GMC_SRC_DATATYPE_COLOR |
1066 					 R128_ROP3_P |
1067 					 R128_GMC_CLR_CMP_CNTL_DIS |
1068 					 R128_GMC_WR_MSK_DIS);
1069 
1070 				OUT_RING(dev_priv->depth_pitch_offset_c);
1071 				OUT_RING(buffer[i]);
1072 
1073 				OUT_RING((x[i] << 16) | y[i]);
1074 				OUT_RING((1 << 16) | 1);
1075 
1076 				ADVANCE_RING();
1077 			}
1078 		}
1079 
1080 		drm_free(mask, mask_size, DRM_MEM_BUFS);
1081 	} else {
1082 		for (i = 0; i < count; i++) {
1083 			BEGIN_RING(6);
1084 
1085 			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
1086 			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
1087 				 R128_GMC_BRUSH_SOLID_COLOR |
1088 				 (dev_priv->depth_fmt << 8) |
1089 				 R128_GMC_SRC_DATATYPE_COLOR |
1090 				 R128_ROP3_P |
1091 				 R128_GMC_CLR_CMP_CNTL_DIS |
1092 				 R128_GMC_WR_MSK_DIS);
1093 
1094 			OUT_RING(dev_priv->depth_pitch_offset_c);
1095 			OUT_RING(buffer[i]);
1096 
1097 			OUT_RING((x[i] << 16) | y[i]);
1098 			OUT_RING((1 << 16) | 1);
1099 
1100 			ADVANCE_RING();
1101 		}
1102 	}
1103 
1104 	drm_free(x, xbuf_size, DRM_MEM_BUFS);
1105 	drm_free(y, ybuf_size, DRM_MEM_BUFS);
1106 	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
1107 
1108 	return 0;
1109 }
1110 
r128_cce_dispatch_read_span(struct drm_device * dev,drm_r128_depth_t * depth)1111 static int r128_cce_dispatch_read_span(struct drm_device * dev,
1112 				       drm_r128_depth_t * depth)
1113 {
1114 	drm_r128_private_t *dev_priv = dev->dev_private;
1115 	int count, x, y;
1116 	RING_LOCALS;
1117 	DRM_DEBUG("\n");
1118 
1119 	count = depth->n;
1120 	if (count > 4096 || count <= 0)
1121 		return -EMSGSIZE;
1122 
1123 	if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
1124 		return -EFAULT;
1125 	}
1126 	if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
1127 		return -EFAULT;
1128 	}
1129 
1130 	BEGIN_RING(7);
1131 
1132 	OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1133 	OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1134 		 R128_GMC_DST_PITCH_OFFSET_CNTL |
1135 		 R128_GMC_BRUSH_NONE |
1136 		 (dev_priv->depth_fmt << 8) |
1137 		 R128_GMC_SRC_DATATYPE_COLOR |
1138 		 R128_ROP3_S |
1139 		 R128_DP_SRC_SOURCE_MEMORY |
1140 		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1141 
1142 	OUT_RING(dev_priv->depth_pitch_offset_c);
1143 	OUT_RING(dev_priv->span_pitch_offset_c);
1144 
1145 	OUT_RING((x << 16) | y);
1146 	OUT_RING((0 << 16) | 0);
1147 	OUT_RING((count << 16) | 1);
1148 
1149 	ADVANCE_RING();
1150 
1151 	return 0;
1152 }
1153 
r128_cce_dispatch_read_pixels(struct drm_device * dev,drm_r128_depth_t * depth)1154 static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
1155 					 drm_r128_depth_t * depth)
1156 {
1157 	drm_r128_private_t *dev_priv = dev->dev_private;
1158 	int count, *x, *y;
1159 	int i, xbuf_size, ybuf_size;
1160 	RING_LOCALS;
1161 	DRM_DEBUG("\n");
1162 
1163 	count = depth->n;
1164 	if (count > 4096 || count <= 0)
1165 		return -EMSGSIZE;
1166 
1167 	if (count > dev_priv->depth_pitch) {
1168 		count = dev_priv->depth_pitch;
1169 	}
1170 
1171 	xbuf_size = count * sizeof(*x);
1172 	ybuf_size = count * sizeof(*y);
1173 	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
1174 	if (x == NULL) {
1175 		return -ENOMEM;
1176 	}
1177 	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
1178 	if (y == NULL) {
1179 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1180 		return -ENOMEM;
1181 	}
1182 	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
1183 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1184 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1185 		return -EFAULT;
1186 	}
1187 	if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
1188 		drm_free(x, xbuf_size, DRM_MEM_BUFS);
1189 		drm_free(y, ybuf_size, DRM_MEM_BUFS);
1190 		return -EFAULT;
1191 	}
1192 
1193 	for (i = 0; i < count; i++) {
1194 		BEGIN_RING(7);
1195 
1196 		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
1197 		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
1198 			 R128_GMC_DST_PITCH_OFFSET_CNTL |
1199 			 R128_GMC_BRUSH_NONE |
1200 			 (dev_priv->depth_fmt << 8) |
1201 			 R128_GMC_SRC_DATATYPE_COLOR |
1202 			 R128_ROP3_S |
1203 			 R128_DP_SRC_SOURCE_MEMORY |
1204 			 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
1205 
1206 		OUT_RING(dev_priv->depth_pitch_offset_c);
1207 		OUT_RING(dev_priv->span_pitch_offset_c);
1208 
1209 		OUT_RING((x[i] << 16) | y[i]);
1210 		OUT_RING((i << 16) | 0);
1211 		OUT_RING((1 << 16) | 1);
1212 
1213 		ADVANCE_RING();
1214 	}
1215 
1216 	drm_free(x, xbuf_size, DRM_MEM_BUFS);
1217 	drm_free(y, ybuf_size, DRM_MEM_BUFS);
1218 
1219 	return 0;
1220 }
1221 
1222 /* ================================================================
1223  * Polygon stipple
1224  */
1225 
r128_cce_dispatch_stipple(struct drm_device * dev,u32 * stipple)1226 static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
1227 {
1228 	drm_r128_private_t *dev_priv = dev->dev_private;
1229 	int i;
1230 	RING_LOCALS;
1231 	DRM_DEBUG("\n");
1232 
1233 	BEGIN_RING(33);
1234 
1235 	OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
1236 	for (i = 0; i < 32; i++) {
1237 		OUT_RING(stipple[i]);
1238 	}
1239 
1240 	ADVANCE_RING();
1241 }
1242 
1243 /* ================================================================
1244  * IOCTL functions
1245  */
1246 
r128_cce_clear(struct drm_device * dev,void * data,struct drm_file * file_priv)1247 static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
1248 {
1249 	drm_r128_private_t *dev_priv = dev->dev_private;
1250 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1251 	drm_r128_clear_t *clear = data;
1252 	DRM_DEBUG("\n");
1253 
1254 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1255 
1256 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1257 
1258 	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1259 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1260 
1261 	r128_cce_dispatch_clear(dev, clear);
1262 	COMMIT_RING();
1263 
1264 	/* Make sure we restore the 3D state next time.
1265 	 */
1266 	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1267 
1268 	return 0;
1269 }
1270 
r128_do_init_pageflip(struct drm_device * dev)1271 static int r128_do_init_pageflip(struct drm_device * dev)
1272 {
1273 	drm_r128_private_t *dev_priv = dev->dev_private;
1274 	DRM_DEBUG("\n");
1275 
1276 	dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
1277 	dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
1278 
1279 	R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
1280 	R128_WRITE(R128_CRTC_OFFSET_CNTL,
1281 		   dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
1282 
1283 	dev_priv->page_flipping = 1;
1284 	dev_priv->current_page = 0;
1285 	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1286 
1287 	return 0;
1288 }
1289 
r128_do_cleanup_pageflip(struct drm_device * dev)1290 static int r128_do_cleanup_pageflip(struct drm_device * dev)
1291 {
1292 	drm_r128_private_t *dev_priv = dev->dev_private;
1293 	DRM_DEBUG("\n");
1294 
1295 	R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
1296 	R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
1297 
1298 	if (dev_priv->current_page != 0) {
1299 		r128_cce_dispatch_flip(dev);
1300 		COMMIT_RING();
1301 	}
1302 
1303 	dev_priv->page_flipping = 0;
1304 	return 0;
1305 }
1306 
1307 /* Swapping and flipping are different operations, need different ioctls.
1308  * They can & should be intermixed to support multiple 3d windows.
1309  */
1310 
r128_cce_flip(struct drm_device * dev,void * data,struct drm_file * file_priv)1311 static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
1312 {
1313 	drm_r128_private_t *dev_priv = dev->dev_private;
1314 	DRM_DEBUG("\n");
1315 
1316 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1317 
1318 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1319 
1320 	if (!dev_priv->page_flipping)
1321 		r128_do_init_pageflip(dev);
1322 
1323 	r128_cce_dispatch_flip(dev);
1324 
1325 	COMMIT_RING();
1326 	return 0;
1327 }
1328 
r128_cce_swap(struct drm_device * dev,void * data,struct drm_file * file_priv)1329 static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
1330 {
1331 	drm_r128_private_t *dev_priv = dev->dev_private;
1332 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1333 	DRM_DEBUG("\n");
1334 
1335 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1336 
1337 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1338 
1339 	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1340 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1341 
1342 	r128_cce_dispatch_swap(dev);
1343 	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1344 					R128_UPLOAD_MASKS);
1345 
1346 	COMMIT_RING();
1347 	return 0;
1348 }
1349 
r128_cce_vertex(struct drm_device * dev,void * data,struct drm_file * file_priv)1350 static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
1351 {
1352 	drm_r128_private_t *dev_priv = dev->dev_private;
1353 	struct drm_device_dma *dma = dev->dma;
1354 	struct drm_buf *buf;
1355 	drm_r128_buf_priv_t *buf_priv;
1356 	drm_r128_vertex_t *vertex = data;
1357 
1358 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1359 
1360 	if (!dev_priv) {
1361 		DRM_ERROR("called with no initialization\n");
1362 		return -EINVAL;
1363 	}
1364 
1365 	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
1366 		  DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
1367 
1368 	if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
1369 		DRM_ERROR("buffer index %d (of %d max)\n",
1370 			  vertex->idx, dma->buf_count - 1);
1371 		return -EINVAL;
1372 	}
1373 	if (vertex->prim < 0 ||
1374 	    vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1375 		DRM_ERROR("buffer prim %d\n", vertex->prim);
1376 		return -EINVAL;
1377 	}
1378 
1379 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1380 	VB_AGE_TEST_WITH_RETURN(dev_priv);
1381 
1382 	buf = dma->buflist[vertex->idx];
1383 	buf_priv = buf->dev_private;
1384 
1385 	if (buf->file_priv != file_priv) {
1386 		DRM_ERROR("process %d using buffer owned by %p\n",
1387 			  DRM_CURRENTPID, buf->file_priv);
1388 		return -EINVAL;
1389 	}
1390 	if (buf->pending) {
1391 		DRM_ERROR("sending pending buffer %d\n", vertex->idx);
1392 		return -EINVAL;
1393 	}
1394 
1395 	buf->used = vertex->count;
1396 	buf_priv->prim = vertex->prim;
1397 	buf_priv->discard = vertex->discard;
1398 
1399 	r128_cce_dispatch_vertex(dev, buf);
1400 
1401 	COMMIT_RING();
1402 	return 0;
1403 }
1404 
r128_cce_indices(struct drm_device * dev,void * data,struct drm_file * file_priv)1405 static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
1406 {
1407 	drm_r128_private_t *dev_priv = dev->dev_private;
1408 	struct drm_device_dma *dma = dev->dma;
1409 	struct drm_buf *buf;
1410 	drm_r128_buf_priv_t *buf_priv;
1411 	drm_r128_indices_t *elts = data;
1412 	int count;
1413 
1414 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1415 
1416 	if (!dev_priv) {
1417 		DRM_ERROR("called with no initialization\n");
1418 		return -EINVAL;
1419 	}
1420 
1421 	DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1422 		  elts->idx, elts->start, elts->end, elts->discard);
1423 
1424 	if (elts->idx < 0 || elts->idx >= dma->buf_count) {
1425 		DRM_ERROR("buffer index %d (of %d max)\n",
1426 			  elts->idx, dma->buf_count - 1);
1427 		return -EINVAL;
1428 	}
1429 	if (elts->prim < 0 ||
1430 	    elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
1431 		DRM_ERROR("buffer prim %d\n", elts->prim);
1432 		return -EINVAL;
1433 	}
1434 
1435 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1436 	VB_AGE_TEST_WITH_RETURN(dev_priv);
1437 
1438 	buf = dma->buflist[elts->idx];
1439 	buf_priv = buf->dev_private;
1440 
1441 	if (buf->file_priv != file_priv) {
1442 		DRM_ERROR("process %d using buffer owned by %p\n",
1443 			  DRM_CURRENTPID, buf->file_priv);
1444 		return -EINVAL;
1445 	}
1446 	if (buf->pending) {
1447 		DRM_ERROR("sending pending buffer %d\n", elts->idx);
1448 		return -EINVAL;
1449 	}
1450 
1451 	count = (elts->end - elts->start) / sizeof(u16);
1452 	elts->start -= R128_INDEX_PRIM_OFFSET;
1453 
1454 	if (elts->start & 0x7) {
1455 		DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
1456 		return -EINVAL;
1457 	}
1458 	if (elts->start < buf->used) {
1459 		DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
1460 		return -EINVAL;
1461 	}
1462 
1463 	buf->used = elts->end;
1464 	buf_priv->prim = elts->prim;
1465 	buf_priv->discard = elts->discard;
1466 
1467 	r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
1468 
1469 	COMMIT_RING();
1470 	return 0;
1471 }
1472 
r128_cce_blit(struct drm_device * dev,void * data,struct drm_file * file_priv)1473 static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
1474 {
1475 	struct drm_device_dma *dma = dev->dma;
1476 	drm_r128_private_t *dev_priv = dev->dev_private;
1477 	drm_r128_blit_t *blit = data;
1478 	int ret;
1479 
1480 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1481 
1482 	DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
1483 
1484 	if (blit->idx < 0 || blit->idx >= dma->buf_count) {
1485 		DRM_ERROR("buffer index %d (of %d max)\n",
1486 			  blit->idx, dma->buf_count - 1);
1487 		return -EINVAL;
1488 	}
1489 
1490 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1491 	VB_AGE_TEST_WITH_RETURN(dev_priv);
1492 
1493 	ret = r128_cce_dispatch_blit(dev, file_priv, blit);
1494 
1495 	COMMIT_RING();
1496 	return ret;
1497 }
1498 
r128_cce_depth(struct drm_device * dev,void * data,struct drm_file * file_priv)1499 static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
1500 {
1501 	drm_r128_private_t *dev_priv = dev->dev_private;
1502 	drm_r128_depth_t *depth = data;
1503 	int ret;
1504 
1505 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1506 
1507 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1508 
1509 	ret = -EINVAL;
1510 	switch (depth->func) {
1511 	case R128_WRITE_SPAN:
1512 		ret = r128_cce_dispatch_write_span(dev, depth);
1513 		break;
1514 	case R128_WRITE_PIXELS:
1515 		ret = r128_cce_dispatch_write_pixels(dev, depth);
1516 		break;
1517 	case R128_READ_SPAN:
1518 		ret = r128_cce_dispatch_read_span(dev, depth);
1519 		break;
1520 	case R128_READ_PIXELS:
1521 		ret = r128_cce_dispatch_read_pixels(dev, depth);
1522 		break;
1523 	}
1524 
1525 	COMMIT_RING();
1526 	return ret;
1527 }
1528 
r128_cce_stipple(struct drm_device * dev,void * data,struct drm_file * file_priv)1529 static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
1530 {
1531 	drm_r128_private_t *dev_priv = dev->dev_private;
1532 	drm_r128_stipple_t *stipple = data;
1533 	u32 mask[32];
1534 
1535 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1536 
1537 	if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
1538 		return -EFAULT;
1539 
1540 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1541 
1542 	r128_cce_dispatch_stipple(dev, mask);
1543 
1544 	COMMIT_RING();
1545 	return 0;
1546 }
1547 
r128_cce_indirect(struct drm_device * dev,void * data,struct drm_file * file_priv)1548 static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
1549 {
1550 	drm_r128_private_t *dev_priv = dev->dev_private;
1551 	struct drm_device_dma *dma = dev->dma;
1552 	struct drm_buf *buf;
1553 	drm_r128_buf_priv_t *buf_priv;
1554 	drm_r128_indirect_t *indirect = data;
1555 #if 0
1556 	RING_LOCALS;
1557 #endif
1558 
1559 	LOCK_TEST_WITH_RETURN(dev, file_priv);
1560 
1561 	if (!dev_priv) {
1562 		DRM_ERROR("called with no initialization\n");
1563 		return -EINVAL;
1564 	}
1565 
1566 	DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
1567 		  indirect->idx, indirect->start, indirect->end,
1568 		  indirect->discard);
1569 
1570 	if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
1571 		DRM_ERROR("buffer index %d (of %d max)\n",
1572 			  indirect->idx, dma->buf_count - 1);
1573 		return -EINVAL;
1574 	}
1575 
1576 	buf = dma->buflist[indirect->idx];
1577 	buf_priv = buf->dev_private;
1578 
1579 	if (buf->file_priv != file_priv) {
1580 		DRM_ERROR("process %d using buffer owned by %p\n",
1581 			  DRM_CURRENTPID, buf->file_priv);
1582 		return -EINVAL;
1583 	}
1584 	if (buf->pending) {
1585 		DRM_ERROR("sending pending buffer %d\n", indirect->idx);
1586 		return -EINVAL;
1587 	}
1588 
1589 	if (indirect->start < buf->used) {
1590 		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
1591 			  indirect->start, buf->used);
1592 		return -EINVAL;
1593 	}
1594 
1595 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
1596 	VB_AGE_TEST_WITH_RETURN(dev_priv);
1597 
1598 	buf->used = indirect->end;
1599 	buf_priv->discard = indirect->discard;
1600 
1601 #if 0
1602 	/* Wait for the 3D stream to idle before the indirect buffer
1603 	 * containing 2D acceleration commands is processed.
1604 	 */
1605 	BEGIN_RING(2);
1606 	RADEON_WAIT_UNTIL_3D_IDLE();
1607 	ADVANCE_RING();
1608 #endif
1609 
1610 	/* Dispatch the indirect buffer full of commands from the
1611 	 * X server.  This is insecure and is thus only available to
1612 	 * privileged clients.
1613 	 */
1614 	r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
1615 
1616 	COMMIT_RING();
1617 	return 0;
1618 }
1619 
r128_getparam(struct drm_device * dev,void * data,struct drm_file * file_priv)1620 static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
1621 {
1622 	drm_r128_private_t *dev_priv = dev->dev_private;
1623 	drm_r128_getparam_t *param = data;
1624 	int value;
1625 
1626 	if (!dev_priv) {
1627 		DRM_ERROR("called with no initialization\n");
1628 		return -EINVAL;
1629 	}
1630 
1631 	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1632 
1633 	switch (param->param) {
1634 	case R128_PARAM_IRQ_NR:
1635 		value = dev->irq;
1636 		break;
1637 	default:
1638 		return -EINVAL;
1639 	}
1640 
1641 	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
1642 		DRM_ERROR("copy_to_user\n");
1643 		return -EFAULT;
1644 	}
1645 
1646 	return 0;
1647 }
1648 
r128_driver_preclose(struct drm_device * dev,struct drm_file * file_priv)1649 void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
1650 {
1651 	if (dev->dev_private) {
1652 		drm_r128_private_t *dev_priv = dev->dev_private;
1653 		if (dev_priv->page_flipping) {
1654 			r128_do_cleanup_pageflip(dev);
1655 		}
1656 	}
1657 }
1658 
r128_driver_lastclose(struct drm_device * dev)1659 void r128_driver_lastclose(struct drm_device * dev)
1660 {
1661 	r128_do_cleanup_cce(dev);
1662 }
1663 
1664 struct drm_ioctl_desc r128_ioctls[] = {
1665 	DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1666 	DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1667 	DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1668 	DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1669 	DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
1670 	DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
1671 	DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
1672 	DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
1673 	DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
1674 	DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
1675 	DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
1676 	DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
1677 	DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
1678 	DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
1679 	DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
1680 	DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
1681 	DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
1682 };
1683 
1684 int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
1685