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