r128_state.c revision 139749
195584Sanholt/* r128_state.c -- State support for r128 -*- linux-c -*-
2139749Simp * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com */
3139749Simp/*-
495584Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
595584Sanholt * All Rights Reserved.
695584Sanholt *
795584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a
895584Sanholt * copy of this software and associated documentation files (the "Software"),
995584Sanholt * to deal in the Software without restriction, including without limitation
1095584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1195584Sanholt * and/or sell copies of the Software, and to permit persons to whom the
1295584Sanholt * Software is furnished to do so, subject to the following conditions:
1395584Sanholt *
1495584Sanholt * The above copyright notice and this permission notice (including the next
1595584Sanholt * paragraph) shall be included in all copies or substantial portions of the
1695584Sanholt * Software.
1795584Sanholt *
1895584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1995584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2095584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2195584Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2295584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2395584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2495584Sanholt * DEALINGS IN THE SOFTWARE.
2595584Sanholt *
2695584Sanholt * Authors:
2795584Sanholt *    Gareth Hughes <gareth@valinux.com>
2895584Sanholt *
2995584Sanholt * $FreeBSD: head/sys/dev/drm/r128_state.c 139749 2005-01-06 01:43:34Z imp $
3095584Sanholt */
3195584Sanholt
3295584Sanholt#include "dev/drm/r128.h"
3395584Sanholt#include "dev/drm/drmP.h"
34112015Sanholt#include "dev/drm/drm.h"
3595746Sanholt#include "dev/drm/r128_drm.h"
3695584Sanholt#include "dev/drm/r128_drv.h"
3795584Sanholt
3895584Sanholt
3995584Sanholt/* ================================================================
4095584Sanholt * CCE hardware state programming functions
4195584Sanholt */
4295584Sanholt
4395584Sanholtstatic void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
4495584Sanholt				  drm_clip_rect_t *boxes, int count )
4595584Sanholt{
4695584Sanholt	u32 aux_sc_cntl = 0x00000000;
4795584Sanholt	RING_LOCALS;
48112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
4995584Sanholt
50121447Sanholt	BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
5195584Sanholt
5295584Sanholt	if ( count >= 1 ) {
5395584Sanholt		OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
5495584Sanholt		OUT_RING( boxes[0].x1 );
5595584Sanholt		OUT_RING( boxes[0].x2 - 1 );
5695584Sanholt		OUT_RING( boxes[0].y1 );
5795584Sanholt		OUT_RING( boxes[0].y2 - 1 );
5895584Sanholt
5995584Sanholt		aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
6095584Sanholt	}
6195584Sanholt	if ( count >= 2 ) {
6295584Sanholt		OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
6395584Sanholt		OUT_RING( boxes[1].x1 );
6495584Sanholt		OUT_RING( boxes[1].x2 - 1 );
6595584Sanholt		OUT_RING( boxes[1].y1 );
6695584Sanholt		OUT_RING( boxes[1].y2 - 1 );
6795584Sanholt
6895584Sanholt		aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
6995584Sanholt	}
7095584Sanholt	if ( count >= 3 ) {
7195584Sanholt		OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
7295584Sanholt		OUT_RING( boxes[2].x1 );
7395584Sanholt		OUT_RING( boxes[2].x2 - 1 );
7495584Sanholt		OUT_RING( boxes[2].y1 );
7595584Sanholt		OUT_RING( boxes[2].y2 - 1 );
7695584Sanholt
7795584Sanholt		aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
7895584Sanholt	}
7995584Sanholt
8095584Sanholt	OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
8195584Sanholt	OUT_RING( aux_sc_cntl );
8295584Sanholt
8395584Sanholt	ADVANCE_RING();
8495584Sanholt}
8595584Sanholt
8695584Sanholtstatic __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
8795584Sanholt{
8895584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
8995584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
9095584Sanholt	RING_LOCALS;
91112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
9295584Sanholt
9395584Sanholt	BEGIN_RING( 2 );
9495584Sanholt
9595584Sanholt	OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
9695584Sanholt	OUT_RING( ctx->scale_3d_cntl );
9795584Sanholt
9895584Sanholt	ADVANCE_RING();
9995584Sanholt}
10095584Sanholt
10195584Sanholtstatic __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
10295584Sanholt{
10395584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
10495584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
10595584Sanholt	RING_LOCALS;
106112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
10795584Sanholt
10895584Sanholt	BEGIN_RING( 13 );
10995584Sanholt
11095584Sanholt	OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
11195584Sanholt	OUT_RING( ctx->dst_pitch_offset_c );
11295584Sanholt	OUT_RING( ctx->dp_gui_master_cntl_c );
11395584Sanholt	OUT_RING( ctx->sc_top_left_c );
11495584Sanholt	OUT_RING( ctx->sc_bottom_right_c );
11595584Sanholt	OUT_RING( ctx->z_offset_c );
11695584Sanholt	OUT_RING( ctx->z_pitch_c );
11795584Sanholt	OUT_RING( ctx->z_sten_cntl_c );
11895584Sanholt	OUT_RING( ctx->tex_cntl_c );
11995584Sanholt	OUT_RING( ctx->misc_3d_state_cntl_reg );
12095584Sanholt	OUT_RING( ctx->texture_clr_cmp_clr_c );
12195584Sanholt	OUT_RING( ctx->texture_clr_cmp_msk_c );
12295584Sanholt	OUT_RING( ctx->fog_color_c );
12395584Sanholt
12495584Sanholt	ADVANCE_RING();
12595584Sanholt}
12695584Sanholt
12795584Sanholtstatic __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
12895584Sanholt{
12995584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
13095584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
13195584Sanholt	RING_LOCALS;
132112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
13395584Sanholt
13495584Sanholt	BEGIN_RING( 3 );
13595584Sanholt
13695584Sanholt	OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
13795584Sanholt	OUT_RING( ctx->setup_cntl );
13895584Sanholt	OUT_RING( ctx->pm4_vc_fpu_setup );
13995584Sanholt
14095584Sanholt	ADVANCE_RING();
14195584Sanholt}
14295584Sanholt
14395584Sanholtstatic __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
14495584Sanholt{
14595584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
14695584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
14795584Sanholt	RING_LOCALS;
148112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
14995584Sanholt
15095584Sanholt	BEGIN_RING( 5 );
15195584Sanholt
15295584Sanholt	OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
15395584Sanholt	OUT_RING( ctx->dp_write_mask );
15495584Sanholt
15595584Sanholt	OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
15695584Sanholt	OUT_RING( ctx->sten_ref_mask_c );
15795584Sanholt	OUT_RING( ctx->plane_3d_mask_c );
15895584Sanholt
15995584Sanholt	ADVANCE_RING();
16095584Sanholt}
16195584Sanholt
16295584Sanholtstatic __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
16395584Sanholt{
16495584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
16595584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
16695584Sanholt	RING_LOCALS;
167112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
16895584Sanholt
16995584Sanholt	BEGIN_RING( 2 );
17095584Sanholt
17195584Sanholt	OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
17295584Sanholt	OUT_RING( ctx->window_xy_offset );
17395584Sanholt
17495584Sanholt	ADVANCE_RING();
17595584Sanholt}
17695584Sanholt
17795584Sanholtstatic __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
17895584Sanholt{
17995584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
18095584Sanholt	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
18195584Sanholt	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
18295584Sanholt	int i;
18395584Sanholt	RING_LOCALS;
184112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
18595584Sanholt
18695584Sanholt	BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
18795584Sanholt
18895584Sanholt	OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
18995584Sanholt			       2 + R128_MAX_TEXTURE_LEVELS ) );
19095584Sanholt	OUT_RING( tex->tex_cntl );
19195584Sanholt	OUT_RING( tex->tex_combine_cntl );
19295584Sanholt	OUT_RING( ctx->tex_size_pitch_c );
19395584Sanholt	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
19495584Sanholt		OUT_RING( tex->tex_offset[i] );
19595584Sanholt	}
19695584Sanholt
19795584Sanholt	OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
19895584Sanholt	OUT_RING( ctx->constant_color_c );
19995584Sanholt	OUT_RING( tex->tex_border_color );
20095584Sanholt
20195584Sanholt	ADVANCE_RING();
20295584Sanholt}
20395584Sanholt
20495584Sanholtstatic __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
20595584Sanholt{
20695584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
20795584Sanholt	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
20895584Sanholt	int i;
20995584Sanholt	RING_LOCALS;
210112015Sanholt	DRM_DEBUG( "    %s\n", __FUNCTION__ );
21195584Sanholt
21295584Sanholt	BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
21395584Sanholt
21495584Sanholt	OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
21595584Sanholt			       1 + R128_MAX_TEXTURE_LEVELS ) );
21695584Sanholt	OUT_RING( tex->tex_cntl );
21795584Sanholt	OUT_RING( tex->tex_combine_cntl );
21895584Sanholt	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
21995584Sanholt		OUT_RING( tex->tex_offset[i] );
22095584Sanholt	}
22195584Sanholt
22295584Sanholt	OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
22395584Sanholt	OUT_RING( tex->tex_border_color );
22495584Sanholt
22595584Sanholt	ADVANCE_RING();
22695584Sanholt}
22795584Sanholt
22895584Sanholtstatic __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
22995584Sanholt{
23095584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
23195584Sanholt	unsigned int dirty = sarea_priv->dirty;
23295584Sanholt
233112015Sanholt	DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
23495584Sanholt
23595584Sanholt	if ( dirty & R128_UPLOAD_CORE ) {
23695584Sanholt		r128_emit_core( dev_priv );
23795584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_CORE;
23895584Sanholt	}
23995584Sanholt
24095584Sanholt	if ( dirty & R128_UPLOAD_CONTEXT ) {
24195584Sanholt		r128_emit_context( dev_priv );
24295584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
24395584Sanholt	}
24495584Sanholt
24595584Sanholt	if ( dirty & R128_UPLOAD_SETUP ) {
24695584Sanholt		r128_emit_setup( dev_priv );
24795584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
24895584Sanholt	}
24995584Sanholt
25095584Sanholt	if ( dirty & R128_UPLOAD_MASKS ) {
25195584Sanholt		r128_emit_masks( dev_priv );
25295584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
25395584Sanholt	}
25495584Sanholt
25595584Sanholt	if ( dirty & R128_UPLOAD_WINDOW ) {
25695584Sanholt		r128_emit_window( dev_priv );
25795584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
25895584Sanholt	}
25995584Sanholt
26095584Sanholt	if ( dirty & R128_UPLOAD_TEX0 ) {
26195584Sanholt		r128_emit_tex0( dev_priv );
26295584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
26395584Sanholt	}
26495584Sanholt
26595584Sanholt	if ( dirty & R128_UPLOAD_TEX1 ) {
26695584Sanholt		r128_emit_tex1( dev_priv );
26795584Sanholt		sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
26895584Sanholt	}
26995584Sanholt
27095584Sanholt	/* Turn off the texture cache flushing */
27195584Sanholt	sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
27295584Sanholt
27395584Sanholt	sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
27495584Sanholt}
27595584Sanholt
27695584Sanholt
27795584Sanholt#if R128_PERFORMANCE_BOXES
27895584Sanholt/* ================================================================
27995584Sanholt * Performance monitoring functions
28095584Sanholt */
28195584Sanholt
28295584Sanholtstatic void r128_clear_box( drm_r128_private_t *dev_priv,
28395584Sanholt			    int x, int y, int w, int h,
28495584Sanholt			    int r, int g, int b )
28595584Sanholt{
28695584Sanholt	u32 pitch, offset;
28795584Sanholt	u32 fb_bpp, color;
28895584Sanholt	RING_LOCALS;
28995584Sanholt
29095584Sanholt	switch ( dev_priv->fb_bpp ) {
29195584Sanholt	case 16:
29295584Sanholt		fb_bpp = R128_GMC_DST_16BPP;
29395584Sanholt		color = (((r & 0xf8) << 8) |
29495584Sanholt			 ((g & 0xfc) << 3) |
29595584Sanholt			 ((b & 0xf8) >> 3));
29695584Sanholt		break;
29795584Sanholt	case 24:
29895584Sanholt		fb_bpp = R128_GMC_DST_24BPP;
29995584Sanholt		color = ((r << 16) | (g << 8) | b);
30095584Sanholt		break;
30195584Sanholt	case 32:
30295584Sanholt		fb_bpp = R128_GMC_DST_32BPP;
30395584Sanholt		color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
30495584Sanholt		break;
30595584Sanholt	default:
30695584Sanholt		return;
30795584Sanholt	}
30895584Sanholt
30995584Sanholt	offset = dev_priv->back_offset;
31095584Sanholt	pitch = dev_priv->back_pitch >> 3;
31195584Sanholt
31295584Sanholt	BEGIN_RING( 6 );
31395584Sanholt
31495584Sanholt	OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
31595584Sanholt	OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
31695584Sanholt		  R128_GMC_BRUSH_SOLID_COLOR |
31795584Sanholt		  fb_bpp |
31895584Sanholt		  R128_GMC_SRC_DATATYPE_COLOR |
31995584Sanholt		  R128_ROP3_P |
32095584Sanholt		  R128_GMC_CLR_CMP_CNTL_DIS |
32195584Sanholt		  R128_GMC_AUX_CLIP_DIS );
32295584Sanholt
32395584Sanholt	OUT_RING( (pitch << 21) | (offset >> 5) );
32495584Sanholt	OUT_RING( color );
32595584Sanholt
32695584Sanholt	OUT_RING( (x << 16) | y );
32795584Sanholt	OUT_RING( (w << 16) | h );
32895584Sanholt
32995584Sanholt	ADVANCE_RING();
33095584Sanholt}
33195584Sanholt
33295584Sanholtstatic void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
33395584Sanholt{
33495584Sanholt	if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
33595584Sanholt		r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
33695584Sanholt	} else {
33795584Sanholt		atomic_set( &dev_priv->idle_count, 0 );
33895584Sanholt	}
33995584Sanholt}
34095584Sanholt
34195584Sanholt#endif
34295584Sanholt
34395584Sanholt
34495584Sanholt/* ================================================================
34595584Sanholt * CCE command dispatch functions
34695584Sanholt */
34795584Sanholt
34895584Sanholtstatic void r128_print_dirty( const char *msg, unsigned int flags )
34995584Sanholt{
35095584Sanholt	DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
35195584Sanholt		  msg,
35295584Sanholt		  flags,
35395584Sanholt		  (flags & R128_UPLOAD_CORE)        ? "core, " : "",
35495584Sanholt		  (flags & R128_UPLOAD_CONTEXT)     ? "context, " : "",
35595584Sanholt		  (flags & R128_UPLOAD_SETUP)       ? "setup, " : "",
35695584Sanholt		  (flags & R128_UPLOAD_TEX0)        ? "tex0, " : "",
35795584Sanholt		  (flags & R128_UPLOAD_TEX1)        ? "tex1, " : "",
35895584Sanholt		  (flags & R128_UPLOAD_MASKS)       ? "masks, " : "",
35995584Sanholt		  (flags & R128_UPLOAD_WINDOW)      ? "window, " : "",
36095584Sanholt		  (flags & R128_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
36195584Sanholt		  (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
36295584Sanholt}
36395584Sanholt
36495584Sanholtstatic void r128_cce_dispatch_clear( drm_device_t *dev,
36595584Sanholt				     drm_r128_clear_t *clear )
36695584Sanholt{
36795584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
36895584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
36995584Sanholt	int nbox = sarea_priv->nbox;
37095584Sanholt	drm_clip_rect_t *pbox = sarea_priv->boxes;
37195584Sanholt	unsigned int flags = clear->flags;
37295584Sanholt	int i;
37395584Sanholt	RING_LOCALS;
374112015Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
37595584Sanholt
37695584Sanholt	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
37795584Sanholt		unsigned int tmp = flags;
37895584Sanholt
37995584Sanholt		flags &= ~(R128_FRONT | R128_BACK);
38095584Sanholt		if ( tmp & R128_FRONT ) flags |= R128_BACK;
38195584Sanholt		if ( tmp & R128_BACK )  flags |= R128_FRONT;
38295584Sanholt	}
38395584Sanholt
38495584Sanholt	for ( i = 0 ; i < nbox ; i++ ) {
38595584Sanholt		int x = pbox[i].x1;
38695584Sanholt		int y = pbox[i].y1;
38795584Sanholt		int w = pbox[i].x2 - x;
38895584Sanholt		int h = pbox[i].y2 - y;
38995584Sanholt
39095584Sanholt		DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
39195584Sanholt			   pbox[i].x1, pbox[i].y1, pbox[i].x2,
39295584Sanholt			   pbox[i].y2, flags );
39395584Sanholt
39495584Sanholt		if ( flags & (R128_FRONT | R128_BACK) ) {
39595584Sanholt			BEGIN_RING( 2 );
39695584Sanholt
39795584Sanholt			OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
39895584Sanholt			OUT_RING( clear->color_mask );
39995584Sanholt
40095584Sanholt			ADVANCE_RING();
40195584Sanholt		}
40295584Sanholt
40395584Sanholt		if ( flags & R128_FRONT ) {
40495584Sanholt			BEGIN_RING( 6 );
40595584Sanholt
40695584Sanholt			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
40795584Sanholt			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
40895584Sanholt				  R128_GMC_BRUSH_SOLID_COLOR |
40995584Sanholt				  (dev_priv->color_fmt << 8) |
41095584Sanholt				  R128_GMC_SRC_DATATYPE_COLOR |
41195584Sanholt				  R128_ROP3_P |
41295584Sanholt				  R128_GMC_CLR_CMP_CNTL_DIS |
41395584Sanholt				  R128_GMC_AUX_CLIP_DIS );
41495584Sanholt
41595584Sanholt			OUT_RING( dev_priv->front_pitch_offset_c );
41695584Sanholt			OUT_RING( clear->clear_color );
41795584Sanholt
41895584Sanholt			OUT_RING( (x << 16) | y );
41995584Sanholt			OUT_RING( (w << 16) | h );
42095584Sanholt
42195584Sanholt			ADVANCE_RING();
42295584Sanholt		}
42395584Sanholt
42495584Sanholt		if ( flags & R128_BACK ) {
42595584Sanholt			BEGIN_RING( 6 );
42695584Sanholt
42795584Sanholt			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
42895584Sanholt			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
42995584Sanholt				  R128_GMC_BRUSH_SOLID_COLOR |
43095584Sanholt				  (dev_priv->color_fmt << 8) |
43195584Sanholt				  R128_GMC_SRC_DATATYPE_COLOR |
43295584Sanholt				  R128_ROP3_P |
43395584Sanholt				  R128_GMC_CLR_CMP_CNTL_DIS |
43495584Sanholt				  R128_GMC_AUX_CLIP_DIS );
43595584Sanholt
43695584Sanholt			OUT_RING( dev_priv->back_pitch_offset_c );
43795584Sanholt			OUT_RING( clear->clear_color );
43895584Sanholt
43995584Sanholt			OUT_RING( (x << 16) | y );
44095584Sanholt			OUT_RING( (w << 16) | h );
44195584Sanholt
44295584Sanholt			ADVANCE_RING();
44395584Sanholt		}
44495584Sanholt
44595584Sanholt		if ( flags & R128_DEPTH ) {
44695584Sanholt			BEGIN_RING( 6 );
44795584Sanholt
44895584Sanholt			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
44995584Sanholt			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
45095584Sanholt				  R128_GMC_BRUSH_SOLID_COLOR |
45195584Sanholt				  (dev_priv->depth_fmt << 8) |
45295584Sanholt				  R128_GMC_SRC_DATATYPE_COLOR |
45395584Sanholt				  R128_ROP3_P |
45495584Sanholt				  R128_GMC_CLR_CMP_CNTL_DIS |
45595584Sanholt				  R128_GMC_AUX_CLIP_DIS |
45695584Sanholt				  R128_GMC_WR_MSK_DIS );
45795584Sanholt
45895584Sanholt			OUT_RING( dev_priv->depth_pitch_offset_c );
45995584Sanholt			OUT_RING( clear->clear_depth );
46095584Sanholt
46195584Sanholt			OUT_RING( (x << 16) | y );
46295584Sanholt			OUT_RING( (w << 16) | h );
46395584Sanholt
46495584Sanholt			ADVANCE_RING();
46595584Sanholt		}
46695584Sanholt	}
46795584Sanholt}
46895584Sanholt
46995584Sanholtstatic void r128_cce_dispatch_swap( drm_device_t *dev )
47095584Sanholt{
47195584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
47295584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
47395584Sanholt	int nbox = sarea_priv->nbox;
47495584Sanholt	drm_clip_rect_t *pbox = sarea_priv->boxes;
47595584Sanholt	int i;
47695584Sanholt	RING_LOCALS;
477112015Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
47895584Sanholt
47995584Sanholt#if R128_PERFORMANCE_BOXES
48095584Sanholt	/* Do some trivial performance monitoring...
48195584Sanholt	 */
48295584Sanholt	r128_cce_performance_boxes( dev_priv );
48395584Sanholt#endif
48495584Sanholt
48595584Sanholt	for ( i = 0 ; i < nbox ; i++ ) {
48695584Sanholt		int x = pbox[i].x1;
48795584Sanholt		int y = pbox[i].y1;
48895584Sanholt		int w = pbox[i].x2 - x;
48995584Sanholt		int h = pbox[i].y2 - y;
49095584Sanholt
49195584Sanholt		BEGIN_RING( 7 );
49295584Sanholt
49395584Sanholt		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
49495584Sanholt		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
49595584Sanholt			  R128_GMC_DST_PITCH_OFFSET_CNTL |
49695584Sanholt			  R128_GMC_BRUSH_NONE |
49795584Sanholt			  (dev_priv->color_fmt << 8) |
49895584Sanholt			  R128_GMC_SRC_DATATYPE_COLOR |
49995584Sanholt			  R128_ROP3_S |
50095584Sanholt			  R128_DP_SRC_SOURCE_MEMORY |
50195584Sanholt			  R128_GMC_CLR_CMP_CNTL_DIS |
50295584Sanholt			  R128_GMC_AUX_CLIP_DIS |
50395584Sanholt			  R128_GMC_WR_MSK_DIS );
50495584Sanholt
505119098Sanholt		/* Make this work even if front & back are flipped:
506119098Sanholt		 */
507119098Sanholt		if (dev_priv->current_page == 0) {
508119098Sanholt			OUT_RING( dev_priv->back_pitch_offset_c );
509119098Sanholt			OUT_RING( dev_priv->front_pitch_offset_c );
510119098Sanholt		}
511119098Sanholt		else {
512119098Sanholt			OUT_RING( dev_priv->front_pitch_offset_c );
513119098Sanholt			OUT_RING( dev_priv->back_pitch_offset_c );
514119098Sanholt		}
51595584Sanholt
51695584Sanholt		OUT_RING( (x << 16) | y );
51795584Sanholt		OUT_RING( (x << 16) | y );
51895584Sanholt		OUT_RING( (w << 16) | h );
51995584Sanholt
52095584Sanholt		ADVANCE_RING();
52195584Sanholt	}
52295584Sanholt
52395584Sanholt	/* Increment the frame counter.  The client-side 3D driver must
52495584Sanholt	 * throttle the framerate by waiting for this value before
52595584Sanholt	 * performing the swapbuffer ioctl.
52695584Sanholt	 */
52795584Sanholt	dev_priv->sarea_priv->last_frame++;
52895584Sanholt
52995584Sanholt	BEGIN_RING( 2 );
53095584Sanholt
53195584Sanholt	OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
53295584Sanholt	OUT_RING( dev_priv->sarea_priv->last_frame );
53395584Sanholt
53495584Sanholt	ADVANCE_RING();
53595584Sanholt}
53695584Sanholt
53795584Sanholtstatic void r128_cce_dispatch_flip( drm_device_t *dev )
53895584Sanholt{
53995584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
54095584Sanholt	RING_LOCALS;
541119098Sanholt	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
542119098Sanholt		__FUNCTION__,
543119098Sanholt		dev_priv->current_page,
544119098Sanholt		dev_priv->sarea_priv->pfCurrentPage);
54595584Sanholt
54695584Sanholt#if R128_PERFORMANCE_BOXES
54795584Sanholt	/* Do some trivial performance monitoring...
54895584Sanholt	 */
54995584Sanholt	r128_cce_performance_boxes( dev_priv );
55095584Sanholt#endif
55195584Sanholt
55295584Sanholt	BEGIN_RING( 4 );
55395584Sanholt
55495584Sanholt	R128_WAIT_UNTIL_PAGE_FLIPPED();
55595584Sanholt	OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
55695584Sanholt
55795584Sanholt	if ( dev_priv->current_page == 0 ) {
55895584Sanholt		OUT_RING( dev_priv->back_offset );
55995584Sanholt	} else {
56095584Sanholt		OUT_RING( dev_priv->front_offset );
56195584Sanholt	}
56295584Sanholt
56395584Sanholt	ADVANCE_RING();
56495584Sanholt
56595584Sanholt	/* Increment the frame counter.  The client-side 3D driver must
56695584Sanholt	 * throttle the framerate by waiting for this value before
56795584Sanholt	 * performing the swapbuffer ioctl.
56895584Sanholt	 */
56995584Sanholt	dev_priv->sarea_priv->last_frame++;
570119098Sanholt	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
571119098Sanholt					      1 - dev_priv->current_page;
57295584Sanholt
57395584Sanholt	BEGIN_RING( 2 );
57495584Sanholt
57595584Sanholt	OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
57695584Sanholt	OUT_RING( dev_priv->sarea_priv->last_frame );
57795584Sanholt
57895584Sanholt	ADVANCE_RING();
57995584Sanholt}
58095584Sanholt
58195584Sanholtstatic void r128_cce_dispatch_vertex( drm_device_t *dev,
58295584Sanholt				      drm_buf_t *buf )
58395584Sanholt{
58495584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
58595584Sanholt	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
58695584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
58795584Sanholt	int format = sarea_priv->vc_format;
58895584Sanholt	int offset = buf->bus_address;
58995584Sanholt	int size = buf->used;
59095584Sanholt	int prim = buf_priv->prim;
59195584Sanholt	int i = 0;
59295584Sanholt	RING_LOCALS;
593112015Sanholt	DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
59495584Sanholt
59595584Sanholt	if ( 0 )
59695584Sanholt		r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
59795584Sanholt
59895584Sanholt	if ( buf->used ) {
59995584Sanholt		buf_priv->dispatched = 1;
60095584Sanholt
60195584Sanholt		if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
60295584Sanholt			r128_emit_state( dev_priv );
60395584Sanholt		}
60495584Sanholt
60595584Sanholt		do {
60695584Sanholt			/* Emit the next set of up to three cliprects */
60795584Sanholt			if ( i < sarea_priv->nbox ) {
60895584Sanholt				r128_emit_clip_rects( dev_priv,
60995584Sanholt						      &sarea_priv->boxes[i],
61095584Sanholt						      sarea_priv->nbox - i );
61195584Sanholt			}
61295584Sanholt
61395584Sanholt			/* Emit the vertex buffer rendering commands */
61495584Sanholt			BEGIN_RING( 5 );
61595584Sanholt
61695584Sanholt			OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
61795584Sanholt			OUT_RING( offset );
61895584Sanholt			OUT_RING( size );
61995584Sanholt			OUT_RING( format );
62095584Sanholt			OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
62195584Sanholt				  (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
62295584Sanholt
62395584Sanholt			ADVANCE_RING();
62495584Sanholt
62595584Sanholt			i += 3;
62695584Sanholt		} while ( i < sarea_priv->nbox );
62795584Sanholt	}
62895584Sanholt
62995584Sanholt	if ( buf_priv->discard ) {
63095584Sanholt		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
63195584Sanholt
63295584Sanholt		/* Emit the vertex buffer age */
63395584Sanholt		BEGIN_RING( 2 );
63495584Sanholt
63595584Sanholt		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
63695584Sanholt		OUT_RING( buf_priv->age );
63795584Sanholt
63895584Sanholt		ADVANCE_RING();
63995584Sanholt
64095584Sanholt		buf->pending = 1;
64195584Sanholt		buf->used = 0;
64295584Sanholt		/* FIXME: Check dispatched field */
64395584Sanholt		buf_priv->dispatched = 0;
64495584Sanholt	}
64595584Sanholt
64695584Sanholt	dev_priv->sarea_priv->last_dispatch++;
64795584Sanholt
64895584Sanholt	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
64995584Sanholt	sarea_priv->nbox = 0;
65095584Sanholt}
65195584Sanholt
65295584Sanholtstatic void r128_cce_dispatch_indirect( drm_device_t *dev,
65395584Sanholt					drm_buf_t *buf,
65495584Sanholt					int start, int end )
65595584Sanholt{
65695584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
65795584Sanholt	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
65895584Sanholt	RING_LOCALS;
65995584Sanholt	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
66095584Sanholt		   buf->idx, start, end );
66195584Sanholt
66295584Sanholt	if ( start != end ) {
66395584Sanholt		int offset = buf->bus_address + start;
66495584Sanholt		int dwords = (end - start + 3) / sizeof(u32);
66595584Sanholt
66695584Sanholt		/* Indirect buffer data must be an even number of
66795584Sanholt		 * dwords, so if we've been given an odd number we must
66895584Sanholt		 * pad the data with a Type-2 CCE packet.
66995584Sanholt		 */
67095584Sanholt		if ( dwords & 1 ) {
67195584Sanholt			u32 *data = (u32 *)
67295584Sanholt				((char *)dev_priv->buffers->handle
67395584Sanholt				 + buf->offset + start);
67495584Sanholt			data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
67595584Sanholt		}
67695584Sanholt
67795584Sanholt		buf_priv->dispatched = 1;
67895584Sanholt
67995584Sanholt		/* Fire off the indirect buffer */
68095584Sanholt		BEGIN_RING( 3 );
68195584Sanholt
68295584Sanholt		OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
68395584Sanholt		OUT_RING( offset );
68495584Sanholt		OUT_RING( dwords );
68595584Sanholt
68695584Sanholt		ADVANCE_RING();
68795584Sanholt	}
68895584Sanholt
68995584Sanholt	if ( buf_priv->discard ) {
69095584Sanholt		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
69195584Sanholt
69295584Sanholt		/* Emit the indirect buffer age */
69395584Sanholt		BEGIN_RING( 2 );
69495584Sanholt
69595584Sanholt		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
69695584Sanholt		OUT_RING( buf_priv->age );
69795584Sanholt
69895584Sanholt		ADVANCE_RING();
69995584Sanholt
70095584Sanholt		buf->pending = 1;
70195584Sanholt		buf->used = 0;
70295584Sanholt		/* FIXME: Check dispatched field */
70395584Sanholt		buf_priv->dispatched = 0;
70495584Sanholt	}
70595584Sanholt
70695584Sanholt	dev_priv->sarea_priv->last_dispatch++;
70795584Sanholt}
70895584Sanholt
70995584Sanholtstatic void r128_cce_dispatch_indices( drm_device_t *dev,
71095584Sanholt				       drm_buf_t *buf,
71195584Sanholt				       int start, int end,
71295584Sanholt				       int count )
71395584Sanholt{
71495584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
71595584Sanholt	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
71695584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
71795584Sanholt	int format = sarea_priv->vc_format;
71895584Sanholt	int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
71995584Sanholt	int prim = buf_priv->prim;
72095584Sanholt	u32 *data;
72195584Sanholt	int dwords;
72295584Sanholt	int i = 0;
72395584Sanholt	RING_LOCALS;
72495584Sanholt	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
72595584Sanholt
72695584Sanholt	if ( 0 )
72795584Sanholt		r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
72895584Sanholt
72995584Sanholt	if ( start != end ) {
73095584Sanholt		buf_priv->dispatched = 1;
73195584Sanholt
73295584Sanholt		if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
73395584Sanholt			r128_emit_state( dev_priv );
73495584Sanholt		}
73595584Sanholt
73695584Sanholt		dwords = (end - start + 3) / sizeof(u32);
73795584Sanholt
73895584Sanholt		data = (u32 *)((char *)dev_priv->buffers->handle
73995584Sanholt			       + buf->offset + start);
74095584Sanholt
74195584Sanholt		data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
74295584Sanholt						    dwords-2 ) );
74395584Sanholt
74495584Sanholt		data[1] = cpu_to_le32( offset );
74595584Sanholt		data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
74695584Sanholt		data[3] = cpu_to_le32( format );
74795584Sanholt		data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
74895584Sanholt					(count << 16)) );
74995584Sanholt
75095584Sanholt		if ( count & 0x1 ) {
75195584Sanholt#ifdef __LITTLE_ENDIAN
75295584Sanholt			data[dwords-1] &= 0x0000ffff;
75395584Sanholt#else
75495584Sanholt			data[dwords-1] &= 0xffff0000;
75595584Sanholt#endif
75695584Sanholt		}
75795584Sanholt
75895584Sanholt		do {
75995584Sanholt			/* Emit the next set of up to three cliprects */
76095584Sanholt			if ( i < sarea_priv->nbox ) {
76195584Sanholt				r128_emit_clip_rects( dev_priv,
76295584Sanholt						      &sarea_priv->boxes[i],
76395584Sanholt						      sarea_priv->nbox - i );
76495584Sanholt			}
76595584Sanholt
76695584Sanholt			r128_cce_dispatch_indirect( dev, buf, start, end );
76795584Sanholt
76895584Sanholt			i += 3;
76995584Sanholt		} while ( i < sarea_priv->nbox );
77095584Sanholt	}
77195584Sanholt
77295584Sanholt	if ( buf_priv->discard ) {
77395584Sanholt		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
77495584Sanholt
77595584Sanholt		/* Emit the vertex buffer age */
77695584Sanholt		BEGIN_RING( 2 );
77795584Sanholt
77895584Sanholt		OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
77995584Sanholt		OUT_RING( buf_priv->age );
78095584Sanholt
78195584Sanholt		ADVANCE_RING();
78295584Sanholt
78395584Sanholt		buf->pending = 1;
78495584Sanholt		/* FIXME: Check dispatched field */
78595584Sanholt		buf_priv->dispatched = 0;
78695584Sanholt	}
78795584Sanholt
78895584Sanholt	dev_priv->sarea_priv->last_dispatch++;
78995584Sanholt
79095584Sanholt	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
79195584Sanholt	sarea_priv->nbox = 0;
79295584Sanholt}
79395584Sanholt
794113995Sanholtstatic int r128_cce_dispatch_blit( DRMFILE filp,
795113995Sanholt				   drm_device_t *dev,
796112015Sanholt				   drm_r128_blit_t *blit )
79795584Sanholt{
79895584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
79995584Sanholt	drm_device_dma_t *dma = dev->dma;
80095584Sanholt	drm_buf_t *buf;
80195584Sanholt	drm_r128_buf_priv_t *buf_priv;
80295584Sanholt	u32 *data;
80395584Sanholt	int dword_shift, dwords;
80495584Sanholt	RING_LOCALS;
805112015Sanholt	DRM_DEBUG( "\n" );
80695584Sanholt
80795584Sanholt	/* The compiler won't optimize away a division by a variable,
80895584Sanholt	 * even if the only legal values are powers of two.  Thus, we'll
80995584Sanholt	 * use a shift instead.
81095584Sanholt	 */
81195584Sanholt	switch ( blit->format ) {
81295584Sanholt	case R128_DATATYPE_ARGB8888:
81395584Sanholt		dword_shift = 0;
81495584Sanholt		break;
81595584Sanholt	case R128_DATATYPE_ARGB1555:
81695584Sanholt	case R128_DATATYPE_RGB565:
81795584Sanholt	case R128_DATATYPE_ARGB4444:
818119098Sanholt	case R128_DATATYPE_YVYU422:
819119098Sanholt	case R128_DATATYPE_VYUY422:
82095584Sanholt		dword_shift = 1;
82195584Sanholt		break;
82295584Sanholt	case R128_DATATYPE_CI8:
82395584Sanholt	case R128_DATATYPE_RGB8:
82495584Sanholt		dword_shift = 2;
82595584Sanholt		break;
82695584Sanholt	default:
82795584Sanholt		DRM_ERROR( "invalid blit format %d\n", blit->format );
828112015Sanholt		return DRM_ERR(EINVAL);
82995584Sanholt	}
83095584Sanholt
83195584Sanholt	/* Flush the pixel cache, and mark the contents as Read Invalid.
83295584Sanholt	 * This ensures no pixel data gets mixed up with the texture
83395584Sanholt	 * data from the host data blit, otherwise part of the texture
83495584Sanholt	 * image may be corrupted.
83595584Sanholt	 */
83695584Sanholt	BEGIN_RING( 2 );
83795584Sanholt
83895584Sanholt	OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
83995584Sanholt	OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
84095584Sanholt
84195584Sanholt	ADVANCE_RING();
84295584Sanholt
84395584Sanholt	/* Dispatch the indirect buffer.
84495584Sanholt	 */
84595584Sanholt	buf = dma->buflist[blit->idx];
84695584Sanholt	buf_priv = buf->dev_private;
84795584Sanholt
848113995Sanholt	if ( buf->filp != filp ) {
849113995Sanholt		DRM_ERROR( "process %d using buffer owned by %p\n",
850113995Sanholt			   DRM_CURRENTPID, buf->filp );
851112015Sanholt		return DRM_ERR(EINVAL);
85295584Sanholt	}
85395584Sanholt	if ( buf->pending ) {
85495584Sanholt		DRM_ERROR( "sending pending buffer %d\n", blit->idx );
855112015Sanholt		return DRM_ERR(EINVAL);
85695584Sanholt	}
85795584Sanholt
85895584Sanholt	buf_priv->discard = 1;
85995584Sanholt
86095584Sanholt	dwords = (blit->width * blit->height) >> dword_shift;
86195584Sanholt
86295584Sanholt	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
86395584Sanholt
86495584Sanholt	data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
86595584Sanholt	data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
86695584Sanholt				R128_GMC_BRUSH_NONE |
86795584Sanholt				(blit->format << 8) |
86895584Sanholt				R128_GMC_SRC_DATATYPE_COLOR |
86995584Sanholt				R128_ROP3_S |
87095584Sanholt				R128_DP_SRC_SOURCE_HOST_DATA |
87195584Sanholt				R128_GMC_CLR_CMP_CNTL_DIS |
87295584Sanholt				R128_GMC_AUX_CLIP_DIS |
87395584Sanholt				R128_GMC_WR_MSK_DIS) );
87495584Sanholt
87595584Sanholt	data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
87695584Sanholt	data[3] = cpu_to_le32( 0xffffffff );
87795584Sanholt	data[4] = cpu_to_le32( 0xffffffff );
87895584Sanholt	data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
87995584Sanholt	data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
88095584Sanholt	data[7] = cpu_to_le32( dwords );
88195584Sanholt
88295584Sanholt	buf->used = (dwords + 8) * sizeof(u32);
88395584Sanholt
88495584Sanholt	r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
88595584Sanholt
88695584Sanholt	/* Flush the pixel cache after the blit completes.  This ensures
88795584Sanholt	 * the texture data is written out to memory before rendering
88895584Sanholt	 * continues.
88995584Sanholt	 */
89095584Sanholt	BEGIN_RING( 2 );
89195584Sanholt
89295584Sanholt	OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
89395584Sanholt	OUT_RING( R128_PC_FLUSH_GUI );
89495584Sanholt
89595584Sanholt	ADVANCE_RING();
89695584Sanholt
89795584Sanholt	return 0;
89895584Sanholt}
89995584Sanholt
90095584Sanholt
90195584Sanholt/* ================================================================
90295584Sanholt * Tiled depth buffer management
90395584Sanholt *
90495584Sanholt * FIXME: These should all set the destination write mask for when we
90595584Sanholt * have hardware stencil support.
90695584Sanholt */
90795584Sanholt
90895584Sanholtstatic int r128_cce_dispatch_write_span( drm_device_t *dev,
90995584Sanholt					 drm_r128_depth_t *depth )
91095584Sanholt{
91195584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
91295584Sanholt	int count, x, y;
91395584Sanholt	u32 *buffer;
91495584Sanholt	u8 *mask;
915112015Sanholt	int i, buffer_size, mask_size;
91695584Sanholt	RING_LOCALS;
917112015Sanholt	DRM_DEBUG( "\n" );
91895584Sanholt
91995584Sanholt	count = depth->n;
920130331Sanholt	if (count > 4096 || count <= 0)
921126137Srwatson		return DRM_ERR(EMSGSIZE);
922130331Sanholt
923112015Sanholt	if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
924112015Sanholt		return DRM_ERR(EFAULT);
92595584Sanholt	}
926112015Sanholt	if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
927112015Sanholt		return DRM_ERR(EFAULT);
92895584Sanholt	}
92995584Sanholt
930112015Sanholt	buffer_size = depth->n * sizeof(u32);
931112015Sanholt	buffer = DRM_MALLOC( buffer_size );
93295584Sanholt	if ( buffer == NULL )
933112015Sanholt		return DRM_ERR(ENOMEM);
934112015Sanholt	if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
935112015Sanholt		DRM_FREE( buffer, buffer_size);
936112015Sanholt		return DRM_ERR(EFAULT);
93795584Sanholt	}
93895584Sanholt
939112015Sanholt	mask_size = depth->n * sizeof(u8);
94095584Sanholt	if ( depth->mask ) {
941112015Sanholt		mask = DRM_MALLOC( mask_size );
94295584Sanholt		if ( mask == NULL ) {
943112015Sanholt			DRM_FREE( buffer, buffer_size );
944112015Sanholt			return DRM_ERR(ENOMEM);
94595584Sanholt		}
946112015Sanholt		if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
947112015Sanholt			DRM_FREE( buffer, buffer_size );
948112015Sanholt			DRM_FREE( mask, mask_size );
949112015Sanholt			return DRM_ERR(EFAULT);
95095584Sanholt		}
95195584Sanholt
95295584Sanholt		for ( i = 0 ; i < count ; i++, x++ ) {
95395584Sanholt			if ( mask[i] ) {
95495584Sanholt				BEGIN_RING( 6 );
95595584Sanholt
95695584Sanholt				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
95795584Sanholt				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
95895584Sanholt					  R128_GMC_BRUSH_SOLID_COLOR |
95995584Sanholt					  (dev_priv->depth_fmt << 8) |
96095584Sanholt					  R128_GMC_SRC_DATATYPE_COLOR |
96195584Sanholt					  R128_ROP3_P |
96295584Sanholt					  R128_GMC_CLR_CMP_CNTL_DIS |
96395584Sanholt					  R128_GMC_WR_MSK_DIS );
96495584Sanholt
96595584Sanholt				OUT_RING( dev_priv->depth_pitch_offset_c );
96695584Sanholt				OUT_RING( buffer[i] );
96795584Sanholt
96895584Sanholt				OUT_RING( (x << 16) | y );
96995584Sanholt				OUT_RING( (1 << 16) | 1 );
97095584Sanholt
97195584Sanholt				ADVANCE_RING();
97295584Sanholt			}
97395584Sanholt		}
97495584Sanholt
975112015Sanholt		DRM_FREE( mask, mask_size );
97695584Sanholt	} else {
97795584Sanholt		for ( i = 0 ; i < count ; i++, x++ ) {
97895584Sanholt			BEGIN_RING( 6 );
97995584Sanholt
98095584Sanholt			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
98195584Sanholt			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
98295584Sanholt				  R128_GMC_BRUSH_SOLID_COLOR |
98395584Sanholt				  (dev_priv->depth_fmt << 8) |
98495584Sanholt				  R128_GMC_SRC_DATATYPE_COLOR |
98595584Sanholt				  R128_ROP3_P |
98695584Sanholt				  R128_GMC_CLR_CMP_CNTL_DIS |
98795584Sanholt				  R128_GMC_WR_MSK_DIS );
98895584Sanholt
98995584Sanholt			OUT_RING( dev_priv->depth_pitch_offset_c );
99095584Sanholt			OUT_RING( buffer[i] );
99195584Sanholt
99295584Sanholt			OUT_RING( (x << 16) | y );
99395584Sanholt			OUT_RING( (1 << 16) | 1 );
99495584Sanholt
99595584Sanholt			ADVANCE_RING();
99695584Sanholt		}
99795584Sanholt	}
99895584Sanholt
999112015Sanholt	DRM_FREE( buffer, buffer_size );
100095584Sanholt
100195584Sanholt	return 0;
100295584Sanholt}
100395584Sanholt
100495584Sanholtstatic int r128_cce_dispatch_write_pixels( drm_device_t *dev,
100595584Sanholt					   drm_r128_depth_t *depth )
100695584Sanholt{
100795584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
100895584Sanholt	int count, *x, *y;
100995584Sanholt	u32 *buffer;
101095584Sanholt	u8 *mask;
1011112015Sanholt	int i, xbuf_size, ybuf_size, buffer_size, mask_size;
101295584Sanholt	RING_LOCALS;
1013112015Sanholt	DRM_DEBUG( "\n" );
101495584Sanholt
101595584Sanholt	count = depth->n;
1016130331Sanholt	if (count > 4096 || count <= 0)
1017126137Srwatson		return DRM_ERR(EMSGSIZE);
101895584Sanholt
1019112015Sanholt	xbuf_size = count * sizeof(*x);
1020112015Sanholt	ybuf_size = count * sizeof(*y);
1021126137Srwatson
1022112015Sanholt	x = DRM_MALLOC( xbuf_size );
102395584Sanholt	if ( x == NULL ) {
1024112015Sanholt		return DRM_ERR(ENOMEM);
102595584Sanholt	}
1026112015Sanholt	y = DRM_MALLOC( ybuf_size );
102795584Sanholt	if ( y == NULL ) {
1028112015Sanholt		DRM_FREE( x, xbuf_size );
1029112015Sanholt		return DRM_ERR(ENOMEM);
103095584Sanholt	}
1031112015Sanholt	if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1032112015Sanholt		DRM_FREE( x, xbuf_size );
1033112015Sanholt		DRM_FREE( y, ybuf_size );
1034112015Sanholt		return DRM_ERR(EFAULT);
103595584Sanholt	}
1036112015Sanholt	if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
1037112015Sanholt		DRM_FREE( x, xbuf_size );
1038112015Sanholt		DRM_FREE( y, ybuf_size );
1039112015Sanholt		return DRM_ERR(EFAULT);
104095584Sanholt	}
104195584Sanholt
1042112015Sanholt	buffer_size = depth->n * sizeof(u32);
1043112015Sanholt	buffer = DRM_MALLOC( buffer_size );
104495584Sanholt	if ( buffer == NULL ) {
1045112015Sanholt		DRM_FREE( x, xbuf_size );
1046112015Sanholt		DRM_FREE( y, ybuf_size );
1047112015Sanholt		return DRM_ERR(ENOMEM);
104895584Sanholt	}
1049112015Sanholt	if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
1050112015Sanholt		DRM_FREE( x, xbuf_size );
1051112015Sanholt		DRM_FREE( y, ybuf_size );
1052112015Sanholt		DRM_FREE( buffer, buffer_size );
1053112015Sanholt		return DRM_ERR(EFAULT);
105495584Sanholt	}
105595584Sanholt
105695584Sanholt	if ( depth->mask ) {
1057112015Sanholt		mask_size = depth->n * sizeof(u8);
1058112015Sanholt		mask = DRM_MALLOC( mask_size );
105995584Sanholt		if ( mask == NULL ) {
1060112015Sanholt			DRM_FREE( x, xbuf_size );
1061112015Sanholt			DRM_FREE( y, ybuf_size );
1062112015Sanholt			DRM_FREE( buffer, buffer_size );
1063112015Sanholt			return DRM_ERR(ENOMEM);
106495584Sanholt		}
1065112015Sanholt		if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
1066112015Sanholt			DRM_FREE( x, xbuf_size );
1067112015Sanholt			DRM_FREE( y, ybuf_size );
1068112015Sanholt			DRM_FREE( buffer, buffer_size );
1069112015Sanholt			DRM_FREE( mask, mask_size );
1070112015Sanholt			return DRM_ERR(EFAULT);
107195584Sanholt		}
107295584Sanholt
107395584Sanholt		for ( i = 0 ; i < count ; i++ ) {
107495584Sanholt			if ( mask[i] ) {
107595584Sanholt				BEGIN_RING( 6 );
107695584Sanholt
107795584Sanholt				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
107895584Sanholt				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
107995584Sanholt					  R128_GMC_BRUSH_SOLID_COLOR |
108095584Sanholt					  (dev_priv->depth_fmt << 8) |
108195584Sanholt					  R128_GMC_SRC_DATATYPE_COLOR |
108295584Sanholt					  R128_ROP3_P |
108395584Sanholt					  R128_GMC_CLR_CMP_CNTL_DIS |
108495584Sanholt					  R128_GMC_WR_MSK_DIS );
108595584Sanholt
108695584Sanholt				OUT_RING( dev_priv->depth_pitch_offset_c );
108795584Sanholt				OUT_RING( buffer[i] );
108895584Sanholt
108995584Sanholt				OUT_RING( (x[i] << 16) | y[i] );
109095584Sanholt				OUT_RING( (1 << 16) | 1 );
109195584Sanholt
109295584Sanholt				ADVANCE_RING();
109395584Sanholt			}
109495584Sanholt		}
109595584Sanholt
1096112015Sanholt		DRM_FREE( mask, mask_size );
109795584Sanholt	} else {
109895584Sanholt		for ( i = 0 ; i < count ; i++ ) {
109995584Sanholt			BEGIN_RING( 6 );
110095584Sanholt
110195584Sanholt			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
110295584Sanholt			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
110395584Sanholt				  R128_GMC_BRUSH_SOLID_COLOR |
110495584Sanholt				  (dev_priv->depth_fmt << 8) |
110595584Sanholt				  R128_GMC_SRC_DATATYPE_COLOR |
110695584Sanholt				  R128_ROP3_P |
110795584Sanholt				  R128_GMC_CLR_CMP_CNTL_DIS |
110895584Sanholt				  R128_GMC_WR_MSK_DIS );
110995584Sanholt
111095584Sanholt			OUT_RING( dev_priv->depth_pitch_offset_c );
111195584Sanholt			OUT_RING( buffer[i] );
111295584Sanholt
111395584Sanholt			OUT_RING( (x[i] << 16) | y[i] );
111495584Sanholt			OUT_RING( (1 << 16) | 1 );
111595584Sanholt
111695584Sanholt			ADVANCE_RING();
111795584Sanholt		}
111895584Sanholt	}
111995584Sanholt
1120112015Sanholt	DRM_FREE( x, xbuf_size );
1121112015Sanholt	DRM_FREE( y, ybuf_size );
1122112015Sanholt	DRM_FREE( buffer, buffer_size );
112395584Sanholt
112495584Sanholt	return 0;
112595584Sanholt}
112695584Sanholt
112795584Sanholtstatic int r128_cce_dispatch_read_span( drm_device_t *dev,
112895584Sanholt					drm_r128_depth_t *depth )
112995584Sanholt{
113095584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
113195584Sanholt	int count, x, y;
113295584Sanholt	RING_LOCALS;
1133112015Sanholt	DRM_DEBUG( "\n" );
113495584Sanholt
113595584Sanholt	count = depth->n;
1136130331Sanholt	if (count > 4096 || count <= 0)
1137130331Sanholt		return DRM_ERR(EMSGSIZE);
1138126137Srwatson
1139112015Sanholt	if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
1140112015Sanholt		return DRM_ERR(EFAULT);
114195584Sanholt	}
1142112015Sanholt	if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
1143112015Sanholt		return DRM_ERR(EFAULT);
114495584Sanholt	}
114595584Sanholt
114695584Sanholt	BEGIN_RING( 7 );
114795584Sanholt
114895584Sanholt	OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
114995584Sanholt	OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
115095584Sanholt		  R128_GMC_DST_PITCH_OFFSET_CNTL |
115195584Sanholt		  R128_GMC_BRUSH_NONE |
115295584Sanholt		  (dev_priv->depth_fmt << 8) |
115395584Sanholt		  R128_GMC_SRC_DATATYPE_COLOR |
115495584Sanholt		  R128_ROP3_S |
115595584Sanholt		  R128_DP_SRC_SOURCE_MEMORY |
115695584Sanholt		  R128_GMC_CLR_CMP_CNTL_DIS |
115795584Sanholt		  R128_GMC_WR_MSK_DIS );
115895584Sanholt
115995584Sanholt	OUT_RING( dev_priv->depth_pitch_offset_c );
116095584Sanholt	OUT_RING( dev_priv->span_pitch_offset_c );
116195584Sanholt
116295584Sanholt	OUT_RING( (x << 16) | y );
116395584Sanholt	OUT_RING( (0 << 16) | 0 );
116495584Sanholt	OUT_RING( (count << 16) | 1 );
116595584Sanholt
116695584Sanholt	ADVANCE_RING();
116795584Sanholt
116895584Sanholt	return 0;
116995584Sanholt}
117095584Sanholt
117195584Sanholtstatic int r128_cce_dispatch_read_pixels( drm_device_t *dev,
117295584Sanholt					  drm_r128_depth_t *depth )
117395584Sanholt{
117495584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
117595584Sanholt	int count, *x, *y;
1176112015Sanholt	int i, xbuf_size, ybuf_size;
117795584Sanholt	RING_LOCALS;
1178112015Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
117995584Sanholt
118095584Sanholt	count = depth->n;
1181130331Sanholt	if (count > 4096 || count <= 0)
1182130331Sanholt		return DRM_ERR(EMSGSIZE);
1183130331Sanholt
118495584Sanholt	if ( count > dev_priv->depth_pitch ) {
118595584Sanholt		count = dev_priv->depth_pitch;
118695584Sanholt	}
118795584Sanholt
1188112015Sanholt	xbuf_size = count * sizeof(*x);
1189112015Sanholt	ybuf_size = count * sizeof(*y);
1190112015Sanholt	x = DRM_MALLOC( xbuf_size );
119195584Sanholt	if ( x == NULL ) {
1192112015Sanholt		return DRM_ERR(ENOMEM);
119395584Sanholt	}
1194112015Sanholt	y = DRM_MALLOC( ybuf_size );
119595584Sanholt	if ( y == NULL ) {
1196112015Sanholt		DRM_FREE( x, xbuf_size );
1197112015Sanholt		return DRM_ERR(ENOMEM);
119895584Sanholt	}
1199112015Sanholt	if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1200112015Sanholt		DRM_FREE( x, xbuf_size );
1201112015Sanholt		DRM_FREE( y, ybuf_size );
1202112015Sanholt		return DRM_ERR(EFAULT);
120395584Sanholt	}
1204112015Sanholt	if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
1205112015Sanholt		DRM_FREE( x, xbuf_size );
1206112015Sanholt		DRM_FREE( y, ybuf_size );
1207112015Sanholt		return DRM_ERR(EFAULT);
120895584Sanholt	}
120995584Sanholt
121095584Sanholt	for ( i = 0 ; i < count ; i++ ) {
121195584Sanholt		BEGIN_RING( 7 );
121295584Sanholt
121395584Sanholt		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
121495584Sanholt		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
121595584Sanholt			  R128_GMC_DST_PITCH_OFFSET_CNTL |
121695584Sanholt			  R128_GMC_BRUSH_NONE |
121795584Sanholt			  (dev_priv->depth_fmt << 8) |
121895584Sanholt			  R128_GMC_SRC_DATATYPE_COLOR |
121995584Sanholt			  R128_ROP3_S |
122095584Sanholt			  R128_DP_SRC_SOURCE_MEMORY |
122195584Sanholt			  R128_GMC_CLR_CMP_CNTL_DIS |
122295584Sanholt			  R128_GMC_WR_MSK_DIS );
122395584Sanholt
122495584Sanholt		OUT_RING( dev_priv->depth_pitch_offset_c );
122595584Sanholt		OUT_RING( dev_priv->span_pitch_offset_c );
122695584Sanholt
122795584Sanholt		OUT_RING( (x[i] << 16) | y[i] );
122895584Sanholt		OUT_RING( (i << 16) | 0 );
122995584Sanholt		OUT_RING( (1 << 16) | 1 );
123095584Sanholt
123195584Sanholt		ADVANCE_RING();
123295584Sanholt	}
123395584Sanholt
1234112015Sanholt	DRM_FREE( x, xbuf_size );
1235112015Sanholt	DRM_FREE( y, ybuf_size );
123695584Sanholt
123795584Sanholt	return 0;
123895584Sanholt}
123995584Sanholt
124095584Sanholt
124195584Sanholt/* ================================================================
124295584Sanholt * Polygon stipple
124395584Sanholt */
124495584Sanholt
124595584Sanholtstatic void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
124695584Sanholt{
124795584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
124895584Sanholt	int i;
124995584Sanholt	RING_LOCALS;
1250112015Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
125195584Sanholt
125295584Sanholt	BEGIN_RING( 33 );
125395584Sanholt
125495584Sanholt	OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
125595584Sanholt	for ( i = 0 ; i < 32 ; i++ ) {
125695584Sanholt		OUT_RING( stipple[i] );
125795584Sanholt	}
125895584Sanholt
125995584Sanholt	ADVANCE_RING();
126095584Sanholt}
126195584Sanholt
126295584Sanholt
126395584Sanholt/* ================================================================
126495584Sanholt * IOCTL functions
126595584Sanholt */
126695584Sanholt
1267112015Sanholtint r128_cce_clear( DRM_IOCTL_ARGS )
126895584Sanholt{
1269112015Sanholt	DRM_DEVICE;
127095584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
127195584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
127295584Sanholt	drm_r128_clear_t clear;
1273112015Sanholt	DRM_DEBUG( "\n" );
127495584Sanholt
1275113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
127695584Sanholt
1277112015Sanholt	DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data,
127895584Sanholt			     sizeof(clear) );
127995584Sanholt
128095584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
128195584Sanholt
128295584Sanholt	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
128395584Sanholt		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
128495584Sanholt
128595584Sanholt	r128_cce_dispatch_clear( dev, &clear );
1286121447Sanholt	COMMIT_RING();
128795584Sanholt
128895584Sanholt	/* Make sure we restore the 3D state next time.
128995584Sanholt	 */
129095584Sanholt	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
129195584Sanholt
129295584Sanholt	return 0;
129395584Sanholt}
129495584Sanholt
1295119098Sanholtstatic int r128_do_init_pageflip( drm_device_t *dev )
1296119098Sanholt{
1297119098Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
1298119098Sanholt	DRM_DEBUG( "\n" );
1299119098Sanholt
1300119098Sanholt	dev_priv->crtc_offset =      R128_READ( R128_CRTC_OFFSET );
1301119098Sanholt	dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
1302119098Sanholt
1303119098Sanholt	R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
1304119098Sanholt	R128_WRITE( R128_CRTC_OFFSET_CNTL,
1305119098Sanholt		    dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
1306119098Sanholt
1307119098Sanholt	dev_priv->page_flipping = 1;
1308119098Sanholt	dev_priv->current_page = 0;
1309119098Sanholt	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1310119098Sanholt
1311119098Sanholt	return 0;
1312119098Sanholt}
1313119098Sanholt
1314119098Sanholtint r128_do_cleanup_pageflip( drm_device_t *dev )
1315119098Sanholt{
1316119098Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
1317119098Sanholt	DRM_DEBUG( "\n" );
1318119098Sanholt
1319119098Sanholt	R128_WRITE( R128_CRTC_OFFSET,      dev_priv->crtc_offset );
1320119098Sanholt	R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
1321119098Sanholt
1322121447Sanholt	if (dev_priv->current_page != 0) {
1323119098Sanholt		r128_cce_dispatch_flip( dev );
1324121447Sanholt		COMMIT_RING();
1325121447Sanholt	}
1326119098Sanholt
1327119098Sanholt	dev_priv->page_flipping = 0;
1328119098Sanholt	return 0;
1329119098Sanholt}
1330119098Sanholt
1331119098Sanholt/* Swapping and flipping are different operations, need different ioctls.
1332119098Sanholt * They can & should be intermixed to support multiple 3d windows.
1333119098Sanholt */
1334119098Sanholt
1335119098Sanholtint r128_cce_flip( DRM_IOCTL_ARGS )
1336119098Sanholt{
1337119098Sanholt	DRM_DEVICE;
1338119098Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
1339119098Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
1340119098Sanholt
1341119098Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
1342119098Sanholt
1343119098Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
1344119098Sanholt
1345119098Sanholt	if (!dev_priv->page_flipping)
1346119098Sanholt		r128_do_init_pageflip( dev );
1347119098Sanholt
1348119098Sanholt	r128_cce_dispatch_flip( dev );
1349119098Sanholt
1350121447Sanholt	COMMIT_RING();
1351119098Sanholt	return 0;
1352119098Sanholt}
1353119098Sanholt
1354112015Sanholtint r128_cce_swap( DRM_IOCTL_ARGS )
135595584Sanholt{
1356112015Sanholt	DRM_DEVICE;
135795584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
135895584Sanholt	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1359112015Sanholt	DRM_DEBUG( "%s\n", __FUNCTION__ );
136095584Sanholt
1361113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
136295584Sanholt
136395584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
136495584Sanholt
136595584Sanholt	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
136695584Sanholt		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
136795584Sanholt
1368119098Sanholt	r128_cce_dispatch_swap( dev );
1369119098Sanholt	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1370119098Sanholt					R128_UPLOAD_MASKS);
137195584Sanholt
1372121447Sanholt	COMMIT_RING();
137395584Sanholt	return 0;
137495584Sanholt}
137595584Sanholt
1376112015Sanholtint r128_cce_vertex( DRM_IOCTL_ARGS )
137795584Sanholt{
1378112015Sanholt	DRM_DEVICE;
137995584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
138095584Sanholt	drm_device_dma_t *dma = dev->dma;
138195584Sanholt	drm_buf_t *buf;
138295584Sanholt	drm_r128_buf_priv_t *buf_priv;
138395584Sanholt	drm_r128_vertex_t vertex;
138495584Sanholt
1385113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
138695584Sanholt
138795584Sanholt	if ( !dev_priv ) {
1388112015Sanholt		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1389112015Sanholt		return DRM_ERR(EINVAL);
139095584Sanholt	}
139195584Sanholt
1392112015Sanholt	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t *) data,
139395584Sanholt			     sizeof(vertex) );
139495584Sanholt
1395112015Sanholt	DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1396112015Sanholt		   DRM_CURRENTPID,
139795584Sanholt		   vertex.idx, vertex.count, vertex.discard );
139895584Sanholt
139995584Sanholt	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
140095584Sanholt		DRM_ERROR( "buffer index %d (of %d max)\n",
140195584Sanholt			   vertex.idx, dma->buf_count - 1 );
1402112015Sanholt		return DRM_ERR(EINVAL);
140395584Sanholt	}
140495584Sanholt	if ( vertex.prim < 0 ||
140595584Sanholt	     vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
140695584Sanholt		DRM_ERROR( "buffer prim %d\n", vertex.prim );
1407112015Sanholt		return DRM_ERR(EINVAL);
140895584Sanholt	}
140995584Sanholt
141095584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
141195584Sanholt	VB_AGE_TEST_WITH_RETURN( dev_priv );
141295584Sanholt
141395584Sanholt	buf = dma->buflist[vertex.idx];
141495584Sanholt	buf_priv = buf->dev_private;
141595584Sanholt
1416113995Sanholt	if ( buf->filp != filp ) {
1417113995Sanholt		DRM_ERROR( "process %d using buffer owned by %p\n",
1418113995Sanholt			   DRM_CURRENTPID, buf->filp );
1419112015Sanholt		return DRM_ERR(EINVAL);
142095584Sanholt	}
142195584Sanholt	if ( buf->pending ) {
142295584Sanholt		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1423112015Sanholt		return DRM_ERR(EINVAL);
142495584Sanholt	}
142595584Sanholt
142695584Sanholt	buf->used = vertex.count;
142795584Sanholt	buf_priv->prim = vertex.prim;
142895584Sanholt	buf_priv->discard = vertex.discard;
142995584Sanholt
143095584Sanholt	r128_cce_dispatch_vertex( dev, buf );
143195584Sanholt
1432121447Sanholt	COMMIT_RING();
143395584Sanholt	return 0;
143495584Sanholt}
143595584Sanholt
1436112015Sanholtint r128_cce_indices( DRM_IOCTL_ARGS )
143795584Sanholt{
1438112015Sanholt	DRM_DEVICE;
143995584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
144095584Sanholt	drm_device_dma_t *dma = dev->dma;
144195584Sanholt	drm_buf_t *buf;
144295584Sanholt	drm_r128_buf_priv_t *buf_priv;
144395584Sanholt	drm_r128_indices_t elts;
144495584Sanholt	int count;
144595584Sanholt
1446113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
144795584Sanholt
144895584Sanholt	if ( !dev_priv ) {
1449112015Sanholt		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1450112015Sanholt		return DRM_ERR(EINVAL);
145195584Sanholt	}
145295584Sanholt
1453112015Sanholt	DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t *) data,
145495584Sanholt			     sizeof(elts) );
145595584Sanholt
1456112015Sanholt	DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
145795584Sanholt		   elts.idx, elts.start, elts.end, elts.discard );
145895584Sanholt
145995584Sanholt	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
146095584Sanholt		DRM_ERROR( "buffer index %d (of %d max)\n",
146195584Sanholt			   elts.idx, dma->buf_count - 1 );
1462112015Sanholt		return DRM_ERR(EINVAL);
146395584Sanholt	}
146495584Sanholt	if ( elts.prim < 0 ||
146595584Sanholt	     elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
146695584Sanholt		DRM_ERROR( "buffer prim %d\n", elts.prim );
1467112015Sanholt		return DRM_ERR(EINVAL);
146895584Sanholt	}
146995584Sanholt
147095584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
147195584Sanholt	VB_AGE_TEST_WITH_RETURN( dev_priv );
147295584Sanholt
147395584Sanholt	buf = dma->buflist[elts.idx];
147495584Sanholt	buf_priv = buf->dev_private;
147595584Sanholt
1476113995Sanholt	if ( buf->filp != filp ) {
1477113995Sanholt		DRM_ERROR( "process %d using buffer owned by %p\n",
1478113995Sanholt			   DRM_CURRENTPID, buf->filp );
1479112015Sanholt		return DRM_ERR(EINVAL);
148095584Sanholt	}
148195584Sanholt	if ( buf->pending ) {
148295584Sanholt		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1483112015Sanholt		return DRM_ERR(EINVAL);
148495584Sanholt	}
148595584Sanholt
148695584Sanholt	count = (elts.end - elts.start) / sizeof(u16);
148795584Sanholt	elts.start -= R128_INDEX_PRIM_OFFSET;
148895584Sanholt
148995584Sanholt	if ( elts.start & 0x7 ) {
149095584Sanholt		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1491112015Sanholt		return DRM_ERR(EINVAL);
149295584Sanholt	}
149395584Sanholt	if ( elts.start < buf->used ) {
149495584Sanholt		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1495112015Sanholt		return DRM_ERR(EINVAL);
149695584Sanholt	}
149795584Sanholt
149895584Sanholt	buf->used = elts.end;
149995584Sanholt	buf_priv->prim = elts.prim;
150095584Sanholt	buf_priv->discard = elts.discard;
150195584Sanholt
150295584Sanholt	r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
150395584Sanholt
1504121447Sanholt	COMMIT_RING();
150595584Sanholt	return 0;
150695584Sanholt}
150795584Sanholt
1508112015Sanholtint r128_cce_blit( DRM_IOCTL_ARGS )
150995584Sanholt{
1510112015Sanholt	DRM_DEVICE;
151195584Sanholt	drm_device_dma_t *dma = dev->dma;
151295584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
151395584Sanholt	drm_r128_blit_t blit;
1514121447Sanholt	int ret;
151595584Sanholt
1516113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
151795584Sanholt
1518112015Sanholt	DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data,
151995584Sanholt			     sizeof(blit) );
152095584Sanholt
1521112015Sanholt	DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
152295584Sanholt
152395584Sanholt	if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
152495584Sanholt		DRM_ERROR( "buffer index %d (of %d max)\n",
152595584Sanholt			   blit.idx, dma->buf_count - 1 );
1526112015Sanholt		return DRM_ERR(EINVAL);
152795584Sanholt	}
152895584Sanholt
152995584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
153095584Sanholt	VB_AGE_TEST_WITH_RETURN( dev_priv );
153195584Sanholt
1532121447Sanholt	ret = r128_cce_dispatch_blit( filp, dev, &blit );
1533121447Sanholt
1534121447Sanholt	COMMIT_RING();
1535121447Sanholt	return ret;
153695584Sanholt}
153795584Sanholt
1538112015Sanholtint r128_cce_depth( DRM_IOCTL_ARGS )
153995584Sanholt{
1540112015Sanholt	DRM_DEVICE;
154195584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
154295584Sanholt	drm_r128_depth_t depth;
1543121447Sanholt	int ret;
154495584Sanholt
1545113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
154695584Sanholt
1547112015Sanholt	DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data,
154895584Sanholt			     sizeof(depth) );
154995584Sanholt
155095584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
155195584Sanholt
1552121447Sanholt	ret = DRM_ERR(EINVAL);
155395584Sanholt	switch ( depth.func ) {
155495584Sanholt	case R128_WRITE_SPAN:
1555121447Sanholt		ret = r128_cce_dispatch_write_span( dev, &depth );
155695584Sanholt	case R128_WRITE_PIXELS:
1557121447Sanholt		ret = r128_cce_dispatch_write_pixels( dev, &depth );
155895584Sanholt	case R128_READ_SPAN:
1559121447Sanholt		ret = r128_cce_dispatch_read_span( dev, &depth );
156095584Sanholt	case R128_READ_PIXELS:
1561121447Sanholt		ret = r128_cce_dispatch_read_pixels( dev, &depth );
156295584Sanholt	}
156395584Sanholt
1564121447Sanholt	COMMIT_RING();
1565121447Sanholt	return ret;
156695584Sanholt}
156795584Sanholt
1568112015Sanholtint r128_cce_stipple( DRM_IOCTL_ARGS )
156995584Sanholt{
1570112015Sanholt	DRM_DEVICE;
157195584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
157295584Sanholt	drm_r128_stipple_t stipple;
157395584Sanholt	u32 mask[32];
157495584Sanholt
1575113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
157695584Sanholt
1577112015Sanholt	DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data,
157895584Sanholt			     sizeof(stipple) );
157995584Sanholt
1580112015Sanholt	if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
158195584Sanholt			     32 * sizeof(u32) ) )
1582112015Sanholt		return DRM_ERR( EFAULT );
158395584Sanholt
158495584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
158595584Sanholt
158695584Sanholt	r128_cce_dispatch_stipple( dev, mask );
158795584Sanholt
1588121447Sanholt	COMMIT_RING();
158995584Sanholt	return 0;
159095584Sanholt}
159195584Sanholt
1592112015Sanholtint r128_cce_indirect( DRM_IOCTL_ARGS )
159395584Sanholt{
1594112015Sanholt	DRM_DEVICE;
159595584Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
159695584Sanholt	drm_device_dma_t *dma = dev->dma;
159795584Sanholt	drm_buf_t *buf;
159895584Sanholt	drm_r128_buf_priv_t *buf_priv;
159995584Sanholt	drm_r128_indirect_t indirect;
160095584Sanholt#if 0
160195584Sanholt	RING_LOCALS;
160295584Sanholt#endif
160395584Sanholt
1604113995Sanholt	LOCK_TEST_WITH_RETURN( dev, filp );
160595584Sanholt
160695584Sanholt	if ( !dev_priv ) {
1607112015Sanholt		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1608112015Sanholt		return DRM_ERR(EINVAL);
160995584Sanholt	}
161095584Sanholt
1611112015Sanholt	DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t *) data,
161295584Sanholt			     sizeof(indirect) );
161395584Sanholt
161495584Sanholt	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
161595584Sanholt		   indirect.idx, indirect.start,
161695584Sanholt		   indirect.end, indirect.discard );
161795584Sanholt
161895584Sanholt	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
161995584Sanholt		DRM_ERROR( "buffer index %d (of %d max)\n",
162095584Sanholt			   indirect.idx, dma->buf_count - 1 );
1621112015Sanholt		return DRM_ERR(EINVAL);
162295584Sanholt	}
162395584Sanholt
162495584Sanholt	buf = dma->buflist[indirect.idx];
162595584Sanholt	buf_priv = buf->dev_private;
162695584Sanholt
1627113995Sanholt	if ( buf->filp != filp ) {
1628113995Sanholt		DRM_ERROR( "process %d using buffer owned by %p\n",
1629113995Sanholt			   DRM_CURRENTPID, buf->filp );
1630112015Sanholt		return DRM_ERR(EINVAL);
163195584Sanholt	}
163295584Sanholt	if ( buf->pending ) {
163395584Sanholt		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1634112015Sanholt		return DRM_ERR(EINVAL);
163595584Sanholt	}
163695584Sanholt
163795584Sanholt	if ( indirect.start < buf->used ) {
163895584Sanholt		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
163995584Sanholt			   indirect.start, buf->used );
1640112015Sanholt		return DRM_ERR(EINVAL);
164195584Sanholt	}
164295584Sanholt
164395584Sanholt	RING_SPACE_TEST_WITH_RETURN( dev_priv );
164495584Sanholt	VB_AGE_TEST_WITH_RETURN( dev_priv );
164595584Sanholt
164695584Sanholt	buf->used = indirect.end;
164795584Sanholt	buf_priv->discard = indirect.discard;
164895584Sanholt
164995584Sanholt#if 0
165095584Sanholt	/* Wait for the 3D stream to idle before the indirect buffer
165195584Sanholt	 * containing 2D acceleration commands is processed.
165295584Sanholt	 */
165395584Sanholt	BEGIN_RING( 2 );
165495584Sanholt	RADEON_WAIT_UNTIL_3D_IDLE();
165595584Sanholt	ADVANCE_RING();
165695584Sanholt#endif
165795584Sanholt
165895584Sanholt	/* Dispatch the indirect buffer full of commands from the
165995584Sanholt	 * X server.  This is insecure and is thus only available to
166095584Sanholt	 * privileged clients.
166195584Sanholt	 */
166295584Sanholt	r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
166395584Sanholt
1664121447Sanholt	COMMIT_RING();
166595584Sanholt	return 0;
166695584Sanholt}
1667112015Sanholt
1668112015Sanholtint r128_getparam( DRM_IOCTL_ARGS )
1669112015Sanholt{
1670112015Sanholt	DRM_DEVICE;
1671112015Sanholt	drm_r128_private_t *dev_priv = dev->dev_private;
1672112015Sanholt	drm_r128_getparam_t param;
1673112015Sanholt	int value;
1674112015Sanholt
1675112015Sanholt	if ( !dev_priv ) {
1676112015Sanholt		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1677112015Sanholt		return DRM_ERR(EINVAL);
1678112015Sanholt	}
1679112015Sanholt
1680112015Sanholt	DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data,
1681112015Sanholt			     sizeof(param) );
1682112015Sanholt
1683112015Sanholt	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
1684112015Sanholt
1685112015Sanholt	switch( param.param ) {
1686112015Sanholt	case R128_PARAM_IRQ_NR:
1687112015Sanholt		value = dev->irq;
1688112015Sanholt		break;
1689112015Sanholt	default:
1690112015Sanholt		return DRM_ERR(EINVAL);
1691112015Sanholt	}
1692112015Sanholt
1693112015Sanholt	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
1694112015Sanholt		DRM_ERROR( "copy_to_user\n" );
1695112015Sanholt		return DRM_ERR(EFAULT);
1696112015Sanholt	}
1697112015Sanholt
1698112015Sanholt	return 0;
1699112015Sanholt}
1700