1 /* r128_state.c -- State support for r128 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
27 * Gareth Hughes <gareth@valinux.com>
36 /* ================================================================
37 * CCE hardware state programming functions
40 static void r128_emit_clip_rects( drm_r128_private_t
*dev_priv
,
41 drm_clip_rect_t
*boxes
, int count
)
43 u32 aux_sc_cntl
= 0x00000000;
45 DRM_DEBUG( " %s\n", __FUNCTION__
);
47 BEGIN_RING( (count
< 3? count
: 3) * 5 + 2 );
50 OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT
, 3 ) );
51 OUT_RING( boxes
[0].x1
);
52 OUT_RING( boxes
[0].x2
- 1 );
53 OUT_RING( boxes
[0].y1
);
54 OUT_RING( boxes
[0].y2
- 1 );
56 aux_sc_cntl
|= (R128_AUX1_SC_EN
| R128_AUX1_SC_MODE_OR
);
59 OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT
, 3 ) );
60 OUT_RING( boxes
[1].x1
);
61 OUT_RING( boxes
[1].x2
- 1 );
62 OUT_RING( boxes
[1].y1
);
63 OUT_RING( boxes
[1].y2
- 1 );
65 aux_sc_cntl
|= (R128_AUX2_SC_EN
| R128_AUX2_SC_MODE_OR
);
68 OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT
, 3 ) );
69 OUT_RING( boxes
[2].x1
);
70 OUT_RING( boxes
[2].x2
- 1 );
71 OUT_RING( boxes
[2].y1
);
72 OUT_RING( boxes
[2].y2
- 1 );
74 aux_sc_cntl
|= (R128_AUX3_SC_EN
| R128_AUX3_SC_MODE_OR
);
77 OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL
, 0 ) );
78 OUT_RING( aux_sc_cntl
);
83 static __inline__
void r128_emit_core( drm_r128_private_t
*dev_priv
)
85 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
86 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
88 DRM_DEBUG( " %s\n", __FUNCTION__
);
92 OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL
, 0 ) );
93 OUT_RING( ctx
->scale_3d_cntl
);
98 static __inline__
void r128_emit_context( drm_r128_private_t
*dev_priv
)
100 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
101 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
103 DRM_DEBUG( " %s\n", __FUNCTION__
);
107 OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C
, 11 ) );
108 OUT_RING( ctx
->dst_pitch_offset_c
);
109 OUT_RING( ctx
->dp_gui_master_cntl_c
);
110 OUT_RING( ctx
->sc_top_left_c
);
111 OUT_RING( ctx
->sc_bottom_right_c
);
112 OUT_RING( ctx
->z_offset_c
);
113 OUT_RING( ctx
->z_pitch_c
);
114 OUT_RING( ctx
->z_sten_cntl_c
);
115 OUT_RING( ctx
->tex_cntl_c
);
116 OUT_RING( ctx
->misc_3d_state_cntl_reg
);
117 OUT_RING( ctx
->texture_clr_cmp_clr_c
);
118 OUT_RING( ctx
->texture_clr_cmp_msk_c
);
119 OUT_RING( ctx
->fog_color_c
);
124 static __inline__
void r128_emit_setup( drm_r128_private_t
*dev_priv
)
126 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
127 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
129 DRM_DEBUG( " %s\n", __FUNCTION__
);
133 OUT_RING( CCE_PACKET1( R128_SETUP_CNTL
, R128_PM4_VC_FPU_SETUP
) );
134 OUT_RING( ctx
->setup_cntl
);
135 OUT_RING( ctx
->pm4_vc_fpu_setup
);
140 static __inline__
void r128_emit_masks( drm_r128_private_t
*dev_priv
)
142 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
143 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
145 DRM_DEBUG( " %s\n", __FUNCTION__
);
149 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK
, 0 ) );
150 OUT_RING( ctx
->dp_write_mask
);
152 OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C
, 1 ) );
153 OUT_RING( ctx
->sten_ref_mask_c
);
154 OUT_RING( ctx
->plane_3d_mask_c
);
159 static __inline__
void r128_emit_window( drm_r128_private_t
*dev_priv
)
161 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
162 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
164 DRM_DEBUG( " %s\n", __FUNCTION__
);
168 OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET
, 0 ) );
169 OUT_RING( ctx
->window_xy_offset
);
174 static __inline__
void r128_emit_tex0( drm_r128_private_t
*dev_priv
)
176 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
177 drm_r128_context_regs_t
*ctx
= &sarea_priv
->context_state
;
178 drm_r128_texture_regs_t
*tex
= &sarea_priv
->tex_state
[0];
181 DRM_DEBUG( " %s\n", __FUNCTION__
);
183 BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS
);
185 OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C
,
186 2 + R128_MAX_TEXTURE_LEVELS
) );
187 OUT_RING( tex
->tex_cntl
);
188 OUT_RING( tex
->tex_combine_cntl
);
189 OUT_RING( ctx
->tex_size_pitch_c
);
190 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
191 OUT_RING( tex
->tex_offset
[i
] );
194 OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C
, 1 ) );
195 OUT_RING( ctx
->constant_color_c
);
196 OUT_RING( tex
->tex_border_color
);
201 static __inline__
void r128_emit_tex1( drm_r128_private_t
*dev_priv
)
203 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
204 drm_r128_texture_regs_t
*tex
= &sarea_priv
->tex_state
[1];
207 DRM_DEBUG( " %s\n", __FUNCTION__
);
209 BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS
);
211 OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C
,
212 1 + R128_MAX_TEXTURE_LEVELS
) );
213 OUT_RING( tex
->tex_cntl
);
214 OUT_RING( tex
->tex_combine_cntl
);
215 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
216 OUT_RING( tex
->tex_offset
[i
] );
219 OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C
, 0 ) );
220 OUT_RING( tex
->tex_border_color
);
225 static __inline__
void r128_emit_state( drm_r128_private_t
*dev_priv
)
227 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
228 unsigned int dirty
= sarea_priv
->dirty
;
230 DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__
, dirty
);
232 if ( dirty
& R128_UPLOAD_CORE
) {
233 r128_emit_core( dev_priv
);
234 sarea_priv
->dirty
&= ~R128_UPLOAD_CORE
;
237 if ( dirty
& R128_UPLOAD_CONTEXT
) {
238 r128_emit_context( dev_priv
);
239 sarea_priv
->dirty
&= ~R128_UPLOAD_CONTEXT
;
242 if ( dirty
& R128_UPLOAD_SETUP
) {
243 r128_emit_setup( dev_priv
);
244 sarea_priv
->dirty
&= ~R128_UPLOAD_SETUP
;
247 if ( dirty
& R128_UPLOAD_MASKS
) {
248 r128_emit_masks( dev_priv
);
249 sarea_priv
->dirty
&= ~R128_UPLOAD_MASKS
;
252 if ( dirty
& R128_UPLOAD_WINDOW
) {
253 r128_emit_window( dev_priv
);
254 sarea_priv
->dirty
&= ~R128_UPLOAD_WINDOW
;
257 if ( dirty
& R128_UPLOAD_TEX0
) {
258 r128_emit_tex0( dev_priv
);
259 sarea_priv
->dirty
&= ~R128_UPLOAD_TEX0
;
262 if ( dirty
& R128_UPLOAD_TEX1
) {
263 r128_emit_tex1( dev_priv
);
264 sarea_priv
->dirty
&= ~R128_UPLOAD_TEX1
;
267 /* Turn off the texture cache flushing */
268 sarea_priv
->context_state
.tex_cntl_c
&= ~R128_TEX_CACHE_FLUSH
;
270 sarea_priv
->dirty
&= ~R128_REQUIRE_QUIESCENCE
;
274 #if R128_PERFORMANCE_BOXES
275 /* ================================================================
276 * Performance monitoring functions
279 static void r128_clear_box( drm_r128_private_t
*dev_priv
,
280 int x
, int y
, int w
, int h
,
281 int r
, int g
, int b
)
287 switch ( dev_priv
->fb_bpp
) {
289 fb_bpp
= R128_GMC_DST_16BPP
;
290 color
= (((r
& 0xf8) << 8) |
295 fb_bpp
= R128_GMC_DST_24BPP
;
296 color
= ((r
<< 16) | (g
<< 8) | b
);
299 fb_bpp
= R128_GMC_DST_32BPP
;
300 color
= (((0xff) << 24) | (r
<< 16) | (g
<< 8) | b
);
306 offset
= dev_priv
->back_offset
;
307 pitch
= dev_priv
->back_pitch
>> 3;
311 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
312 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
313 R128_GMC_BRUSH_SOLID_COLOR
|
315 R128_GMC_SRC_DATATYPE_COLOR
|
317 R128_GMC_CLR_CMP_CNTL_DIS
|
318 R128_GMC_AUX_CLIP_DIS
);
320 OUT_RING( (pitch
<< 21) | (offset
>> 5) );
323 OUT_RING( (x
<< 16) | y
);
324 OUT_RING( (w
<< 16) | h
);
329 static void r128_cce_performance_boxes( drm_r128_private_t
*dev_priv
)
331 if ( atomic_read( &dev_priv
->idle_count
) == 0 ) {
332 r128_clear_box( dev_priv
, 64, 4, 8, 8, 0, 255, 0 );
334 atomic_set( &dev_priv
->idle_count
, 0 );
341 /* ================================================================
342 * CCE command dispatch functions
345 static void r128_print_dirty( const char *msg
, unsigned int flags
)
347 DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
350 (flags
& R128_UPLOAD_CORE
) ? "core, " : "",
351 (flags
& R128_UPLOAD_CONTEXT
) ? "context, " : "",
352 (flags
& R128_UPLOAD_SETUP
) ? "setup, " : "",
353 (flags
& R128_UPLOAD_TEX0
) ? "tex0, " : "",
354 (flags
& R128_UPLOAD_TEX1
) ? "tex1, " : "",
355 (flags
& R128_UPLOAD_MASKS
) ? "masks, " : "",
356 (flags
& R128_UPLOAD_WINDOW
) ? "window, " : "",
357 (flags
& R128_UPLOAD_CLIPRECTS
) ? "cliprects, " : "",
358 (flags
& R128_REQUIRE_QUIESCENCE
) ? "quiescence, " : "" );
361 static void r128_cce_dispatch_clear( drm_device_t
*dev
,
362 drm_r128_clear_t
*clear
)
364 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
365 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
366 int nbox
= sarea_priv
->nbox
;
367 drm_clip_rect_t
*pbox
= sarea_priv
->boxes
;
368 unsigned int flags
= clear
->flags
;
371 DRM_DEBUG( "%s\n", __FUNCTION__
);
373 if ( dev_priv
->page_flipping
&& dev_priv
->current_page
== 1 ) {
374 unsigned int tmp
= flags
;
376 flags
&= ~(R128_FRONT
| R128_BACK
);
377 if ( tmp
& R128_FRONT
) flags
|= R128_BACK
;
378 if ( tmp
& R128_BACK
) flags
|= R128_FRONT
;
381 for ( i
= 0 ; i
< nbox
; i
++ ) {
384 int w
= pbox
[i
].x2
- x
;
385 int h
= pbox
[i
].y2
- y
;
387 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
388 pbox
[i
].x1
, pbox
[i
].y1
, pbox
[i
].x2
,
391 if ( flags
& (R128_FRONT
| R128_BACK
) ) {
394 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK
, 0 ) );
395 OUT_RING( clear
->color_mask
);
400 if ( flags
& R128_FRONT
) {
403 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
404 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
405 R128_GMC_BRUSH_SOLID_COLOR
|
406 (dev_priv
->color_fmt
<< 8) |
407 R128_GMC_SRC_DATATYPE_COLOR
|
409 R128_GMC_CLR_CMP_CNTL_DIS
|
410 R128_GMC_AUX_CLIP_DIS
);
412 OUT_RING( dev_priv
->front_pitch_offset_c
);
413 OUT_RING( clear
->clear_color
);
415 OUT_RING( (x
<< 16) | y
);
416 OUT_RING( (w
<< 16) | h
);
421 if ( flags
& R128_BACK
) {
424 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
425 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
426 R128_GMC_BRUSH_SOLID_COLOR
|
427 (dev_priv
->color_fmt
<< 8) |
428 R128_GMC_SRC_DATATYPE_COLOR
|
430 R128_GMC_CLR_CMP_CNTL_DIS
|
431 R128_GMC_AUX_CLIP_DIS
);
433 OUT_RING( dev_priv
->back_pitch_offset_c
);
434 OUT_RING( clear
->clear_color
);
436 OUT_RING( (x
<< 16) | y
);
437 OUT_RING( (w
<< 16) | h
);
442 if ( flags
& R128_DEPTH
) {
445 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
446 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
447 R128_GMC_BRUSH_SOLID_COLOR
|
448 (dev_priv
->depth_fmt
<< 8) |
449 R128_GMC_SRC_DATATYPE_COLOR
|
451 R128_GMC_CLR_CMP_CNTL_DIS
|
452 R128_GMC_AUX_CLIP_DIS
|
453 R128_GMC_WR_MSK_DIS
);
455 OUT_RING( dev_priv
->depth_pitch_offset_c
);
456 OUT_RING( clear
->clear_depth
);
458 OUT_RING( (x
<< 16) | y
);
459 OUT_RING( (w
<< 16) | h
);
466 static void r128_cce_dispatch_swap( drm_device_t
*dev
)
468 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
469 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
470 int nbox
= sarea_priv
->nbox
;
471 drm_clip_rect_t
*pbox
= sarea_priv
->boxes
;
474 DRM_DEBUG( "%s\n", __FUNCTION__
);
476 #if R128_PERFORMANCE_BOXES
477 /* Do some trivial performance monitoring...
479 r128_cce_performance_boxes( dev_priv
);
482 for ( i
= 0 ; i
< nbox
; i
++ ) {
485 int w
= pbox
[i
].x2
- x
;
486 int h
= pbox
[i
].y2
- y
;
490 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI
, 5 ) );
491 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
|
492 R128_GMC_DST_PITCH_OFFSET_CNTL
|
493 R128_GMC_BRUSH_NONE
|
494 (dev_priv
->color_fmt
<< 8) |
495 R128_GMC_SRC_DATATYPE_COLOR
|
497 R128_DP_SRC_SOURCE_MEMORY
|
498 R128_GMC_CLR_CMP_CNTL_DIS
|
499 R128_GMC_AUX_CLIP_DIS
|
500 R128_GMC_WR_MSK_DIS
);
502 /* Make this work even if front & back are flipped:
504 if (dev_priv
->current_page
== 0) {
505 OUT_RING( dev_priv
->back_pitch_offset_c
);
506 OUT_RING( dev_priv
->front_pitch_offset_c
);
509 OUT_RING( dev_priv
->front_pitch_offset_c
);
510 OUT_RING( dev_priv
->back_pitch_offset_c
);
513 OUT_RING( (x
<< 16) | y
);
514 OUT_RING( (x
<< 16) | y
);
515 OUT_RING( (w
<< 16) | h
);
520 /* Increment the frame counter. The client-side 3D driver must
521 * throttle the framerate by waiting for this value before
522 * performing the swapbuffer ioctl.
524 dev_priv
->sarea_priv
->last_frame
++;
528 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG
, 0 ) );
529 OUT_RING( dev_priv
->sarea_priv
->last_frame
);
534 static void r128_cce_dispatch_flip( drm_device_t
*dev
)
536 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
538 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
540 dev_priv
->current_page
,
541 dev_priv
->sarea_priv
->pfCurrentPage
);
543 #if R128_PERFORMANCE_BOXES
544 /* Do some trivial performance monitoring...
546 r128_cce_performance_boxes( dev_priv
);
551 R128_WAIT_UNTIL_PAGE_FLIPPED();
552 OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET
, 0 ) );
554 if ( dev_priv
->current_page
== 0 ) {
555 OUT_RING( dev_priv
->back_offset
);
557 OUT_RING( dev_priv
->front_offset
);
562 /* Increment the frame counter. The client-side 3D driver must
563 * throttle the framerate by waiting for this value before
564 * performing the swapbuffer ioctl.
566 dev_priv
->sarea_priv
->last_frame
++;
567 dev_priv
->sarea_priv
->pfCurrentPage
= dev_priv
->current_page
=
568 1 - dev_priv
->current_page
;
572 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG
, 0 ) );
573 OUT_RING( dev_priv
->sarea_priv
->last_frame
);
578 static void r128_cce_dispatch_vertex( drm_device_t
*dev
,
581 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
582 drm_r128_buf_priv_t
*buf_priv
= buf
->dev_private
;
583 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
584 int format
= sarea_priv
->vc_format
;
585 int offset
= buf
->bus_address
;
586 int size
= buf
->used
;
587 int prim
= buf_priv
->prim
;
590 DRM_DEBUG( "buf=%d nbox=%d\n", buf
->idx
, sarea_priv
->nbox
);
593 r128_print_dirty( "dispatch_vertex", sarea_priv
->dirty
);
596 buf_priv
->dispatched
= 1;
598 if ( sarea_priv
->dirty
& ~R128_UPLOAD_CLIPRECTS
) {
599 r128_emit_state( dev_priv
);
603 /* Emit the next set of up to three cliprects */
604 if ( i
< sarea_priv
->nbox
) {
605 r128_emit_clip_rects( dev_priv
,
606 &sarea_priv
->boxes
[i
],
607 sarea_priv
->nbox
- i
);
610 /* Emit the vertex buffer rendering commands */
613 OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM
, 3 ) );
617 OUT_RING( prim
| R128_CCE_VC_CNTL_PRIM_WALK_LIST
|
618 (size
<< R128_CCE_VC_CNTL_NUM_SHIFT
) );
623 } while ( i
< sarea_priv
->nbox
);
626 if ( buf_priv
->discard
) {
627 buf_priv
->age
= dev_priv
->sarea_priv
->last_dispatch
;
629 /* Emit the vertex buffer age */
632 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG
, 0 ) );
633 OUT_RING( buf_priv
->age
);
639 /* FIXME: Check dispatched field */
640 buf_priv
->dispatched
= 0;
643 dev_priv
->sarea_priv
->last_dispatch
++;
645 sarea_priv
->dirty
&= ~R128_UPLOAD_CLIPRECTS
;
646 sarea_priv
->nbox
= 0;
649 static void r128_cce_dispatch_indirect( drm_device_t
*dev
,
653 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
654 drm_r128_buf_priv_t
*buf_priv
= buf
->dev_private
;
656 DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
657 buf
->idx
, start
, end
);
659 if ( start
!= end
) {
660 int offset
= buf
->bus_address
+ start
;
661 int dwords
= (end
- start
+ 3) / sizeof(u32
);
663 /* Indirect buffer data must be an even number of
664 * dwords, so if we've been given an odd number we must
665 * pad the data with a Type-2 CCE packet.
669 ((char *)dev
->agp_buffer_map
->handle
670 + buf
->offset
+ start
);
671 data
[dwords
++] = cpu_to_le32( R128_CCE_PACKET2
);
674 buf_priv
->dispatched
= 1;
676 /* Fire off the indirect buffer */
679 OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF
, 1 ) );
686 if ( buf_priv
->discard
) {
687 buf_priv
->age
= dev_priv
->sarea_priv
->last_dispatch
;
689 /* Emit the indirect buffer age */
692 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG
, 0 ) );
693 OUT_RING( buf_priv
->age
);
699 /* FIXME: Check dispatched field */
700 buf_priv
->dispatched
= 0;
703 dev_priv
->sarea_priv
->last_dispatch
++;
706 static void r128_cce_dispatch_indices( drm_device_t
*dev
,
711 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
712 drm_r128_buf_priv_t
*buf_priv
= buf
->dev_private
;
713 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
714 int format
= sarea_priv
->vc_format
;
715 int offset
= dev
->agp_buffer_map
->offset
- dev_priv
->cce_buffers_offset
;
716 int prim
= buf_priv
->prim
;
721 DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start
, end
, count
);
724 r128_print_dirty( "dispatch_indices", sarea_priv
->dirty
);
726 if ( start
!= end
) {
727 buf_priv
->dispatched
= 1;
729 if ( sarea_priv
->dirty
& ~R128_UPLOAD_CLIPRECTS
) {
730 r128_emit_state( dev_priv
);
733 dwords
= (end
- start
+ 3) / sizeof(u32
);
735 data
= (u32
*)((char *)dev
->agp_buffer_map
->handle
736 + buf
->offset
+ start
);
738 data
[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM
,
741 data
[1] = cpu_to_le32( offset
);
742 data
[2] = cpu_to_le32( R128_MAX_VB_VERTS
);
743 data
[3] = cpu_to_le32( format
);
744 data
[4] = cpu_to_le32( (prim
| R128_CCE_VC_CNTL_PRIM_WALK_IND
|
748 #ifdef __LITTLE_ENDIAN
749 data
[dwords
-1] &= 0x0000ffff;
751 data
[dwords
-1] &= 0xffff0000;
756 /* Emit the next set of up to three cliprects */
757 if ( i
< sarea_priv
->nbox
) {
758 r128_emit_clip_rects( dev_priv
,
759 &sarea_priv
->boxes
[i
],
760 sarea_priv
->nbox
- i
);
763 r128_cce_dispatch_indirect( dev
, buf
, start
, end
);
766 } while ( i
< sarea_priv
->nbox
);
769 if ( buf_priv
->discard
) {
770 buf_priv
->age
= dev_priv
->sarea_priv
->last_dispatch
;
772 /* Emit the vertex buffer age */
775 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG
, 0 ) );
776 OUT_RING( buf_priv
->age
);
781 /* FIXME: Check dispatched field */
782 buf_priv
->dispatched
= 0;
785 dev_priv
->sarea_priv
->last_dispatch
++;
787 sarea_priv
->dirty
&= ~R128_UPLOAD_CLIPRECTS
;
788 sarea_priv
->nbox
= 0;
791 static int r128_cce_dispatch_blit( DRMFILE filp
,
793 drm_r128_blit_t
*blit
)
795 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
796 drm_device_dma_t
*dma
= dev
->dma
;
798 drm_r128_buf_priv_t
*buf_priv
;
800 int dword_shift
, dwords
;
804 /* The compiler won't optimize away a division by a variable,
805 * even if the only legal values are powers of two. Thus, we'll
806 * use a shift instead.
808 switch ( blit
->format
) {
809 case R128_DATATYPE_ARGB8888
:
812 case R128_DATATYPE_ARGB1555
:
813 case R128_DATATYPE_RGB565
:
814 case R128_DATATYPE_ARGB4444
:
815 case R128_DATATYPE_YVYU422
:
816 case R128_DATATYPE_VYUY422
:
819 case R128_DATATYPE_CI8
:
820 case R128_DATATYPE_RGB8
:
824 DRM_ERROR( "invalid blit format %d\n", blit
->format
);
825 return DRM_ERR(EINVAL
);
828 /* Flush the pixel cache, and mark the contents as Read Invalid.
829 * This ensures no pixel data gets mixed up with the texture
830 * data from the host data blit, otherwise part of the texture
831 * image may be corrupted.
835 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT
, 0 ) );
836 OUT_RING( R128_PC_RI_GUI
| R128_PC_FLUSH_GUI
);
840 /* Dispatch the indirect buffer.
842 buf
= dma
->buflist
[blit
->idx
];
843 buf_priv
= buf
->dev_private
;
845 if ( buf
->filp
!= filp
) {
846 DRM_ERROR( "process %d using buffer owned by %p\n",
847 DRM_CURRENTPID
, buf
->filp
);
848 return DRM_ERR(EINVAL
);
850 if ( buf
->pending
) {
851 DRM_ERROR( "sending pending buffer %d\n", blit
->idx
);
852 return DRM_ERR(EINVAL
);
855 buf_priv
->discard
= 1;
857 dwords
= (blit
->width
* blit
->height
) >> dword_shift
;
859 data
= (u32
*)((char *)dev
->agp_buffer_map
->handle
+ buf
->offset
);
861 data
[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT
, dwords
+ 6 ) );
862 data
[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL
|
863 R128_GMC_BRUSH_NONE
|
864 (blit
->format
<< 8) |
865 R128_GMC_SRC_DATATYPE_COLOR
|
867 R128_DP_SRC_SOURCE_HOST_DATA
|
868 R128_GMC_CLR_CMP_CNTL_DIS
|
869 R128_GMC_AUX_CLIP_DIS
|
870 R128_GMC_WR_MSK_DIS
) );
872 data
[2] = cpu_to_le32( (blit
->pitch
<< 21) | (blit
->offset
>> 5) );
873 data
[3] = cpu_to_le32( 0xffffffff );
874 data
[4] = cpu_to_le32( 0xffffffff );
875 data
[5] = cpu_to_le32( (blit
->y
<< 16) | blit
->x
);
876 data
[6] = cpu_to_le32( (blit
->height
<< 16) | blit
->width
);
877 data
[7] = cpu_to_le32( dwords
);
879 buf
->used
= (dwords
+ 8) * sizeof(u32
);
881 r128_cce_dispatch_indirect( dev
, buf
, 0, buf
->used
);
883 /* Flush the pixel cache after the blit completes. This ensures
884 * the texture data is written out to memory before rendering
889 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT
, 0 ) );
890 OUT_RING( R128_PC_FLUSH_GUI
);
898 /* ================================================================
899 * Tiled depth buffer management
901 * FIXME: These should all set the destination write mask for when we
902 * have hardware stencil support.
905 static int r128_cce_dispatch_write_span( drm_device_t
*dev
,
906 drm_r128_depth_t
*depth
)
908 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
912 int i
, buffer_size
, mask_size
;
917 if (count
> 4096 || count
<= 0)
918 return DRM_ERR(EMSGSIZE
);
920 if ( DRM_COPY_FROM_USER( &x
, depth
->x
, sizeof(x
) ) ) {
921 return DRM_ERR(EFAULT
);
923 if ( DRM_COPY_FROM_USER( &y
, depth
->y
, sizeof(y
) ) ) {
924 return DRM_ERR(EFAULT
);
927 buffer_size
= depth
->n
* sizeof(u32
);
928 buffer
= drm_alloc( buffer_size
, DRM_MEM_BUFS
);
929 if ( buffer
== NULL
)
930 return DRM_ERR(ENOMEM
);
931 if ( DRM_COPY_FROM_USER( buffer
, depth
->buffer
, buffer_size
) ) {
932 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
933 return DRM_ERR(EFAULT
);
936 mask_size
= depth
->n
* sizeof(u8
);
938 mask
= drm_alloc( mask_size
, DRM_MEM_BUFS
);
939 if ( mask
== NULL
) {
940 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
941 return DRM_ERR(ENOMEM
);
943 if ( DRM_COPY_FROM_USER( mask
, depth
->mask
, mask_size
) ) {
944 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
945 drm_free( mask
, mask_size
, DRM_MEM_BUFS
);
946 return DRM_ERR(EFAULT
);
949 for ( i
= 0 ; i
< count
; i
++, x
++ ) {
953 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
954 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
955 R128_GMC_BRUSH_SOLID_COLOR
|
956 (dev_priv
->depth_fmt
<< 8) |
957 R128_GMC_SRC_DATATYPE_COLOR
|
959 R128_GMC_CLR_CMP_CNTL_DIS
|
960 R128_GMC_WR_MSK_DIS
);
962 OUT_RING( dev_priv
->depth_pitch_offset_c
);
963 OUT_RING( buffer
[i
] );
965 OUT_RING( (x
<< 16) | y
);
966 OUT_RING( (1 << 16) | 1 );
972 drm_free( mask
, mask_size
, DRM_MEM_BUFS
);
974 for ( i
= 0 ; i
< count
; i
++, x
++ ) {
977 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
978 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
979 R128_GMC_BRUSH_SOLID_COLOR
|
980 (dev_priv
->depth_fmt
<< 8) |
981 R128_GMC_SRC_DATATYPE_COLOR
|
983 R128_GMC_CLR_CMP_CNTL_DIS
|
984 R128_GMC_WR_MSK_DIS
);
986 OUT_RING( dev_priv
->depth_pitch_offset_c
);
987 OUT_RING( buffer
[i
] );
989 OUT_RING( (x
<< 16) | y
);
990 OUT_RING( (1 << 16) | 1 );
996 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
1001 static int r128_cce_dispatch_write_pixels( drm_device_t
*dev
,
1002 drm_r128_depth_t
*depth
)
1004 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1008 int i
, xbuf_size
, ybuf_size
, buffer_size
, mask_size
;
1013 if (count
> 4096 || count
<= 0)
1014 return DRM_ERR(EMSGSIZE
);
1016 xbuf_size
= count
* sizeof(*x
);
1017 ybuf_size
= count
* sizeof(*y
);
1018 x
= drm_alloc( xbuf_size
, DRM_MEM_BUFS
);
1020 return DRM_ERR(ENOMEM
);
1022 y
= drm_alloc( ybuf_size
, DRM_MEM_BUFS
);
1024 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1025 return DRM_ERR(ENOMEM
);
1027 if ( DRM_COPY_FROM_USER( x
, depth
->x
, xbuf_size
) ) {
1028 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1029 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1030 return DRM_ERR(EFAULT
);
1032 if ( DRM_COPY_FROM_USER( y
, depth
->y
, xbuf_size
) ) {
1033 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1034 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1035 return DRM_ERR(EFAULT
);
1038 buffer_size
= depth
->n
* sizeof(u32
);
1039 buffer
= drm_alloc( buffer_size
, DRM_MEM_BUFS
);
1040 if ( buffer
== NULL
) {
1041 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1042 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1043 return DRM_ERR(ENOMEM
);
1045 if ( DRM_COPY_FROM_USER( buffer
, depth
->buffer
, buffer_size
) ) {
1046 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1047 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1048 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
1049 return DRM_ERR(EFAULT
);
1052 if ( depth
->mask
) {
1053 mask_size
= depth
->n
* sizeof(u8
);
1054 mask
= drm_alloc( mask_size
, DRM_MEM_BUFS
);
1055 if ( mask
== NULL
) {
1056 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1057 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1058 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
1059 return DRM_ERR(ENOMEM
);
1061 if ( DRM_COPY_FROM_USER( mask
, depth
->mask
, mask_size
) ) {
1062 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1063 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1064 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
1065 drm_free( mask
, mask_size
, DRM_MEM_BUFS
);
1066 return DRM_ERR(EFAULT
);
1069 for ( i
= 0 ; i
< count
; i
++ ) {
1073 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
1074 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
1075 R128_GMC_BRUSH_SOLID_COLOR
|
1076 (dev_priv
->depth_fmt
<< 8) |
1077 R128_GMC_SRC_DATATYPE_COLOR
|
1079 R128_GMC_CLR_CMP_CNTL_DIS
|
1080 R128_GMC_WR_MSK_DIS
);
1082 OUT_RING( dev_priv
->depth_pitch_offset_c
);
1083 OUT_RING( buffer
[i
] );
1085 OUT_RING( (x
[i
] << 16) | y
[i
] );
1086 OUT_RING( (1 << 16) | 1 );
1092 drm_free( mask
, mask_size
, DRM_MEM_BUFS
);
1094 for ( i
= 0 ; i
< count
; i
++ ) {
1097 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI
, 4 ) );
1098 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
|
1099 R128_GMC_BRUSH_SOLID_COLOR
|
1100 (dev_priv
->depth_fmt
<< 8) |
1101 R128_GMC_SRC_DATATYPE_COLOR
|
1103 R128_GMC_CLR_CMP_CNTL_DIS
|
1104 R128_GMC_WR_MSK_DIS
);
1106 OUT_RING( dev_priv
->depth_pitch_offset_c
);
1107 OUT_RING( buffer
[i
] );
1109 OUT_RING( (x
[i
] << 16) | y
[i
] );
1110 OUT_RING( (1 << 16) | 1 );
1116 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1117 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1118 drm_free( buffer
, buffer_size
, DRM_MEM_BUFS
);
1123 static int r128_cce_dispatch_read_span( drm_device_t
*dev
,
1124 drm_r128_depth_t
*depth
)
1126 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1132 if (count
> 4096 || count
<= 0)
1133 return DRM_ERR(EMSGSIZE
);
1135 if ( DRM_COPY_FROM_USER( &x
, depth
->x
, sizeof(x
) ) ) {
1136 return DRM_ERR(EFAULT
);
1138 if ( DRM_COPY_FROM_USER( &y
, depth
->y
, sizeof(y
) ) ) {
1139 return DRM_ERR(EFAULT
);
1144 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI
, 5 ) );
1145 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
|
1146 R128_GMC_DST_PITCH_OFFSET_CNTL
|
1147 R128_GMC_BRUSH_NONE
|
1148 (dev_priv
->depth_fmt
<< 8) |
1149 R128_GMC_SRC_DATATYPE_COLOR
|
1151 R128_DP_SRC_SOURCE_MEMORY
|
1152 R128_GMC_CLR_CMP_CNTL_DIS
|
1153 R128_GMC_WR_MSK_DIS
);
1155 OUT_RING( dev_priv
->depth_pitch_offset_c
);
1156 OUT_RING( dev_priv
->span_pitch_offset_c
);
1158 OUT_RING( (x
<< 16) | y
);
1159 OUT_RING( (0 << 16) | 0 );
1160 OUT_RING( (count
<< 16) | 1 );
1167 static int r128_cce_dispatch_read_pixels( drm_device_t
*dev
,
1168 drm_r128_depth_t
*depth
)
1170 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1172 int i
, xbuf_size
, ybuf_size
;
1174 DRM_DEBUG( "%s\n", __FUNCTION__
);
1177 if (count
> 4096 || count
<= 0)
1178 return DRM_ERR(EMSGSIZE
);
1180 if ( count
> dev_priv
->depth_pitch
) {
1181 count
= dev_priv
->depth_pitch
;
1184 xbuf_size
= count
* sizeof(*x
);
1185 ybuf_size
= count
* sizeof(*y
);
1186 x
= drm_alloc( xbuf_size
, DRM_MEM_BUFS
);
1188 return DRM_ERR(ENOMEM
);
1190 y
= drm_alloc( ybuf_size
, DRM_MEM_BUFS
);
1192 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1193 return DRM_ERR(ENOMEM
);
1195 if ( DRM_COPY_FROM_USER( x
, depth
->x
, xbuf_size
) ) {
1196 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1197 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1198 return DRM_ERR(EFAULT
);
1200 if ( DRM_COPY_FROM_USER( y
, depth
->y
, ybuf_size
) ) {
1201 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1202 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1203 return DRM_ERR(EFAULT
);
1206 for ( i
= 0 ; i
< count
; i
++ ) {
1209 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI
, 5 ) );
1210 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
|
1211 R128_GMC_DST_PITCH_OFFSET_CNTL
|
1212 R128_GMC_BRUSH_NONE
|
1213 (dev_priv
->depth_fmt
<< 8) |
1214 R128_GMC_SRC_DATATYPE_COLOR
|
1216 R128_DP_SRC_SOURCE_MEMORY
|
1217 R128_GMC_CLR_CMP_CNTL_DIS
|
1218 R128_GMC_WR_MSK_DIS
);
1220 OUT_RING( dev_priv
->depth_pitch_offset_c
);
1221 OUT_RING( dev_priv
->span_pitch_offset_c
);
1223 OUT_RING( (x
[i
] << 16) | y
[i
] );
1224 OUT_RING( (i
<< 16) | 0 );
1225 OUT_RING( (1 << 16) | 1 );
1230 drm_free( x
, xbuf_size
, DRM_MEM_BUFS
);
1231 drm_free( y
, ybuf_size
, DRM_MEM_BUFS
);
1237 /* ================================================================
1241 static void r128_cce_dispatch_stipple( drm_device_t
*dev
, u32
*stipple
)
1243 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1246 DRM_DEBUG( "%s\n", __FUNCTION__
);
1250 OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0
, 31 ) );
1251 for ( i
= 0 ; i
< 32 ; i
++ ) {
1252 OUT_RING( stipple
[i
] );
1259 /* ================================================================
1263 static int r128_cce_clear( DRM_IOCTL_ARGS
)
1266 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1267 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
1268 drm_r128_clear_t clear
;
1271 LOCK_TEST_WITH_RETURN( dev
, filp
);
1273 DRM_COPY_FROM_USER_IOCTL( clear
, (drm_r128_clear_t __user
*) data
,
1276 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1278 if ( sarea_priv
->nbox
> R128_NR_SAREA_CLIPRECTS
)
1279 sarea_priv
->nbox
= R128_NR_SAREA_CLIPRECTS
;
1281 r128_cce_dispatch_clear( dev
, &clear
);
1284 /* Make sure we restore the 3D state next time.
1286 dev_priv
->sarea_priv
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_MASKS
;
1291 static int r128_do_init_pageflip( drm_device_t
*dev
)
1293 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1296 dev_priv
->crtc_offset
= R128_READ( R128_CRTC_OFFSET
);
1297 dev_priv
->crtc_offset_cntl
= R128_READ( R128_CRTC_OFFSET_CNTL
);
1299 R128_WRITE( R128_CRTC_OFFSET
, dev_priv
->front_offset
);
1300 R128_WRITE( R128_CRTC_OFFSET_CNTL
,
1301 dev_priv
->crtc_offset_cntl
| R128_CRTC_OFFSET_FLIP_CNTL
);
1303 dev_priv
->page_flipping
= 1;
1304 dev_priv
->current_page
= 0;
1305 dev_priv
->sarea_priv
->pfCurrentPage
= dev_priv
->current_page
;
1310 int r128_do_cleanup_pageflip( drm_device_t
*dev
)
1312 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1315 R128_WRITE( R128_CRTC_OFFSET
, dev_priv
->crtc_offset
);
1316 R128_WRITE( R128_CRTC_OFFSET_CNTL
, dev_priv
->crtc_offset_cntl
);
1318 if (dev_priv
->current_page
!= 0) {
1319 r128_cce_dispatch_flip( dev
);
1323 dev_priv
->page_flipping
= 0;
1327 /* Swapping and flipping are different operations, need different ioctls.
1328 * They can & should be intermixed to support multiple 3d windows.
1331 static int r128_cce_flip( DRM_IOCTL_ARGS
)
1334 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1335 DRM_DEBUG( "%s\n", __FUNCTION__
);
1337 LOCK_TEST_WITH_RETURN( dev
, filp
);
1339 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1341 if (!dev_priv
->page_flipping
)
1342 r128_do_init_pageflip( dev
);
1344 r128_cce_dispatch_flip( dev
);
1350 static int r128_cce_swap( DRM_IOCTL_ARGS
)
1353 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1354 drm_r128_sarea_t
*sarea_priv
= dev_priv
->sarea_priv
;
1355 DRM_DEBUG( "%s\n", __FUNCTION__
);
1357 LOCK_TEST_WITH_RETURN( dev
, filp
);
1359 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1361 if ( sarea_priv
->nbox
> R128_NR_SAREA_CLIPRECTS
)
1362 sarea_priv
->nbox
= R128_NR_SAREA_CLIPRECTS
;
1364 r128_cce_dispatch_swap( dev
);
1365 dev_priv
->sarea_priv
->dirty
|= (R128_UPLOAD_CONTEXT
|
1372 static int r128_cce_vertex( DRM_IOCTL_ARGS
)
1375 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1376 drm_device_dma_t
*dma
= dev
->dma
;
1378 drm_r128_buf_priv_t
*buf_priv
;
1379 drm_r128_vertex_t vertex
;
1381 LOCK_TEST_WITH_RETURN( dev
, filp
);
1384 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__
);
1385 return DRM_ERR(EINVAL
);
1388 DRM_COPY_FROM_USER_IOCTL( vertex
, (drm_r128_vertex_t __user
*) data
,
1391 DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1393 vertex
.idx
, vertex
.count
, vertex
.discard
);
1395 if ( vertex
.idx
< 0 || vertex
.idx
>= dma
->buf_count
) {
1396 DRM_ERROR( "buffer index %d (of %d max)\n",
1397 vertex
.idx
, dma
->buf_count
- 1 );
1398 return DRM_ERR(EINVAL
);
1400 if ( vertex
.prim
< 0 ||
1401 vertex
.prim
> R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2
) {
1402 DRM_ERROR( "buffer prim %d\n", vertex
.prim
);
1403 return DRM_ERR(EINVAL
);
1406 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1407 VB_AGE_TEST_WITH_RETURN( dev_priv
);
1409 buf
= dma
->buflist
[vertex
.idx
];
1410 buf_priv
= buf
->dev_private
;
1412 if ( buf
->filp
!= filp
) {
1413 DRM_ERROR( "process %d using buffer owned by %p\n",
1414 DRM_CURRENTPID
, buf
->filp
);
1415 return DRM_ERR(EINVAL
);
1417 if ( buf
->pending
) {
1418 DRM_ERROR( "sending pending buffer %d\n", vertex
.idx
);
1419 return DRM_ERR(EINVAL
);
1422 buf
->used
= vertex
.count
;
1423 buf_priv
->prim
= vertex
.prim
;
1424 buf_priv
->discard
= vertex
.discard
;
1426 r128_cce_dispatch_vertex( dev
, buf
);
1432 static int r128_cce_indices( DRM_IOCTL_ARGS
)
1435 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1436 drm_device_dma_t
*dma
= dev
->dma
;
1438 drm_r128_buf_priv_t
*buf_priv
;
1439 drm_r128_indices_t elts
;
1442 LOCK_TEST_WITH_RETURN( dev
, filp
);
1445 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__
);
1446 return DRM_ERR(EINVAL
);
1449 DRM_COPY_FROM_USER_IOCTL( elts
, (drm_r128_indices_t __user
*) data
,
1452 DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID
,
1453 elts
.idx
, elts
.start
, elts
.end
, elts
.discard
);
1455 if ( elts
.idx
< 0 || elts
.idx
>= dma
->buf_count
) {
1456 DRM_ERROR( "buffer index %d (of %d max)\n",
1457 elts
.idx
, dma
->buf_count
- 1 );
1458 return DRM_ERR(EINVAL
);
1460 if ( elts
.prim
< 0 ||
1461 elts
.prim
> R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2
) {
1462 DRM_ERROR( "buffer prim %d\n", elts
.prim
);
1463 return DRM_ERR(EINVAL
);
1466 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1467 VB_AGE_TEST_WITH_RETURN( dev_priv
);
1469 buf
= dma
->buflist
[elts
.idx
];
1470 buf_priv
= buf
->dev_private
;
1472 if ( buf
->filp
!= filp
) {
1473 DRM_ERROR( "process %d using buffer owned by %p\n",
1474 DRM_CURRENTPID
, buf
->filp
);
1475 return DRM_ERR(EINVAL
);
1477 if ( buf
->pending
) {
1478 DRM_ERROR( "sending pending buffer %d\n", elts
.idx
);
1479 return DRM_ERR(EINVAL
);
1482 count
= (elts
.end
- elts
.start
) / sizeof(u16
);
1483 elts
.start
-= R128_INDEX_PRIM_OFFSET
;
1485 if ( elts
.start
& 0x7 ) {
1486 DRM_ERROR( "misaligned buffer 0x%x\n", elts
.start
);
1487 return DRM_ERR(EINVAL
);
1489 if ( elts
.start
< buf
->used
) {
1490 DRM_ERROR( "no header 0x%x - 0x%x\n", elts
.start
, buf
->used
);
1491 return DRM_ERR(EINVAL
);
1494 buf
->used
= elts
.end
;
1495 buf_priv
->prim
= elts
.prim
;
1496 buf_priv
->discard
= elts
.discard
;
1498 r128_cce_dispatch_indices( dev
, buf
, elts
.start
, elts
.end
, count
);
1504 static int r128_cce_blit( DRM_IOCTL_ARGS
)
1507 drm_device_dma_t
*dma
= dev
->dma
;
1508 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1509 drm_r128_blit_t blit
;
1512 LOCK_TEST_WITH_RETURN( dev
, filp
);
1514 DRM_COPY_FROM_USER_IOCTL( blit
, (drm_r128_blit_t __user
*) data
,
1517 DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID
, blit
.idx
);
1519 if ( blit
.idx
< 0 || blit
.idx
>= dma
->buf_count
) {
1520 DRM_ERROR( "buffer index %d (of %d max)\n",
1521 blit
.idx
, dma
->buf_count
- 1 );
1522 return DRM_ERR(EINVAL
);
1525 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1526 VB_AGE_TEST_WITH_RETURN( dev_priv
);
1528 ret
= r128_cce_dispatch_blit( filp
, dev
, &blit
);
1534 static int r128_cce_depth( DRM_IOCTL_ARGS
)
1537 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1538 drm_r128_depth_t depth
;
1541 LOCK_TEST_WITH_RETURN( dev
, filp
);
1543 DRM_COPY_FROM_USER_IOCTL( depth
, (drm_r128_depth_t __user
*) data
,
1546 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1548 ret
= DRM_ERR(EINVAL
);
1549 switch ( depth
.func
) {
1550 case R128_WRITE_SPAN
:
1551 ret
= r128_cce_dispatch_write_span( dev
, &depth
);
1553 case R128_WRITE_PIXELS
:
1554 ret
= r128_cce_dispatch_write_pixels( dev
, &depth
);
1556 case R128_READ_SPAN
:
1557 ret
= r128_cce_dispatch_read_span( dev
, &depth
);
1559 case R128_READ_PIXELS
:
1560 ret
= r128_cce_dispatch_read_pixels( dev
, &depth
);
1568 static int r128_cce_stipple( DRM_IOCTL_ARGS
)
1571 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1572 drm_r128_stipple_t stipple
;
1575 LOCK_TEST_WITH_RETURN( dev
, filp
);
1577 DRM_COPY_FROM_USER_IOCTL( stipple
, (drm_r128_stipple_t __user
*) data
,
1580 if ( DRM_COPY_FROM_USER( &mask
, stipple
.mask
,
1581 32 * sizeof(u32
) ) )
1582 return DRM_ERR( EFAULT
);
1584 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1586 r128_cce_dispatch_stipple( dev
, mask
);
1592 static int r128_cce_indirect( DRM_IOCTL_ARGS
)
1595 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1596 drm_device_dma_t
*dma
= dev
->dma
;
1598 drm_r128_buf_priv_t
*buf_priv
;
1599 drm_r128_indirect_t indirect
;
1604 LOCK_TEST_WITH_RETURN( dev
, filp
);
1607 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__
);
1608 return DRM_ERR(EINVAL
);
1611 DRM_COPY_FROM_USER_IOCTL( indirect
, (drm_r128_indirect_t __user
*) data
,
1614 DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1615 indirect
.idx
, indirect
.start
,
1616 indirect
.end
, indirect
.discard
);
1618 if ( indirect
.idx
< 0 || indirect
.idx
>= dma
->buf_count
) {
1619 DRM_ERROR( "buffer index %d (of %d max)\n",
1620 indirect
.idx
, dma
->buf_count
- 1 );
1621 return DRM_ERR(EINVAL
);
1624 buf
= dma
->buflist
[indirect
.idx
];
1625 buf_priv
= buf
->dev_private
;
1627 if ( buf
->filp
!= filp
) {
1628 DRM_ERROR( "process %d using buffer owned by %p\n",
1629 DRM_CURRENTPID
, buf
->filp
);
1630 return DRM_ERR(EINVAL
);
1632 if ( buf
->pending
) {
1633 DRM_ERROR( "sending pending buffer %d\n", indirect
.idx
);
1634 return DRM_ERR(EINVAL
);
1637 if ( indirect
.start
< buf
->used
) {
1638 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1639 indirect
.start
, buf
->used
);
1640 return DRM_ERR(EINVAL
);
1643 RING_SPACE_TEST_WITH_RETURN( dev_priv
);
1644 VB_AGE_TEST_WITH_RETURN( dev_priv
);
1646 buf
->used
= indirect
.end
;
1647 buf_priv
->discard
= indirect
.discard
;
1650 /* Wait for the 3D stream to idle before the indirect buffer
1651 * containing 2D acceleration commands is processed.
1654 RADEON_WAIT_UNTIL_3D_IDLE();
1658 /* Dispatch the indirect buffer full of commands from the
1659 * X server. This is insecure and is thus only available to
1660 * privileged clients.
1662 r128_cce_dispatch_indirect( dev
, buf
, indirect
.start
, indirect
.end
);
1668 static int r128_getparam( DRM_IOCTL_ARGS
)
1671 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1672 drm_r128_getparam_t param
;
1676 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__
);
1677 return DRM_ERR(EINVAL
);
1680 DRM_COPY_FROM_USER_IOCTL( param
, (drm_r128_getparam_t __user
*)data
,
1683 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID
);
1685 switch( param
.param
) {
1686 case R128_PARAM_IRQ_NR
:
1690 return DRM_ERR(EINVAL
);
1693 if ( DRM_COPY_TO_USER( param
.value
, &value
, sizeof(int) ) ) {
1694 DRM_ERROR( "copy_to_user\n" );
1695 return DRM_ERR(EFAULT
);
1701 void r128_driver_prerelease(drm_device_t
*dev
, DRMFILE filp
)
1703 if ( dev
->dev_private
) {
1704 drm_r128_private_t
*dev_priv
= dev
->dev_private
;
1705 if ( dev_priv
->page_flipping
) {
1706 r128_do_cleanup_pageflip( dev
);
1711 void r128_driver_pretakedown(drm_device_t
*dev
)
1713 r128_do_cleanup_cce( dev
);
1716 drm_ioctl_desc_t r128_ioctls
[] = {
1717 [DRM_IOCTL_NR(DRM_R128_INIT
)] = { r128_cce_init
, 1, 1 },
1718 [DRM_IOCTL_NR(DRM_R128_CCE_START
)] = { r128_cce_start
, 1, 1 },
1719 [DRM_IOCTL_NR(DRM_R128_CCE_STOP
)] = { r128_cce_stop
, 1, 1 },
1720 [DRM_IOCTL_NR(DRM_R128_CCE_RESET
)] = { r128_cce_reset
, 1, 1 },
1721 [DRM_IOCTL_NR(DRM_R128_CCE_IDLE
)] = { r128_cce_idle
, 1, 0 },
1722 [DRM_IOCTL_NR(DRM_R128_RESET
)] = { r128_engine_reset
, 1, 0 },
1723 [DRM_IOCTL_NR(DRM_R128_FULLSCREEN
)] = { r128_fullscreen
, 1, 0 },
1724 [DRM_IOCTL_NR(DRM_R128_SWAP
)] = { r128_cce_swap
, 1, 0 },
1725 [DRM_IOCTL_NR(DRM_R128_FLIP
)] = { r128_cce_flip
, 1, 0 },
1726 [DRM_IOCTL_NR(DRM_R128_CLEAR
)] = { r128_cce_clear
, 1, 0 },
1727 [DRM_IOCTL_NR(DRM_R128_VERTEX
)] = { r128_cce_vertex
, 1, 0 },
1728 [DRM_IOCTL_NR(DRM_R128_INDICES
)] = { r128_cce_indices
, 1, 0 },
1729 [DRM_IOCTL_NR(DRM_R128_BLIT
)] = { r128_cce_blit
, 1, 0 },
1730 [DRM_IOCTL_NR(DRM_R128_DEPTH
)] = { r128_cce_depth
, 1, 0 },
1731 [DRM_IOCTL_NR(DRM_R128_STIPPLE
)] = { r128_cce_stipple
, 1, 0 },
1732 [DRM_IOCTL_NR(DRM_R128_INDIRECT
)] = { r128_cce_indirect
, 1, 1 },
1733 [DRM_IOCTL_NR(DRM_R128_GETPARAM
)] = { r128_getparam
, 1, 0 },
1736 int r128_max_ioctl
= DRM_ARRAY_SIZE(r128_ioctls
);