OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [r128_state.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.