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