1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <dfb_types.h>
32
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36
37 #include <sys/mman.h>
38 #include <fcntl.h>
39 #include <sys/ioctl.h>
40
41 #include <fbdev/fb.h>
42
43 #include <directfb.h>
44
45 #include <direct/messages.h>
46
47 #include <core/coredefs.h>
48 #include <core/coretypes.h>
49
50 #include <core/screens.h>
51 #include <core/state.h>
52 #include <core/gfxcard.h>
53 #include <core/surface.h>
54
55 #include <gfx/convert.h>
56
57 #include <core/graphics_driver.h>
58
59
60 DFB_GRAPHICS_DRIVER( ati128 )
61
62
63 #include "regs.h"
64 #include "mmio.h"
65 #include "ati128_state.h"
66 #include "ati128.h"
67
68
69 /* driver capability flags */
70
71
72 #ifndef __powerpc__
73 #define ATI128_SUPPORTED_DRAWINGFLAGS \
74 (DSDRAW_BLEND)
75 #else
76 #define ATI128_SUPPORTED_DRAWINGFLAGS \
77 (DSDRAW_NOFX)
78 #endif
79
80 #define ATI128_SUPPORTED_DRAWINGFUNCTIONS \
81 (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE)
82
83 #define ATI128_SUPPORTED_BLITTINGFLAGS \
84 (DSBLIT_SRC_COLORKEY | DSBLIT_BLEND_ALPHACHANNEL)
85
86 #define ATI128_SUPPORTED_BLITTINGFUNCTIONS \
87 (DFXL_BLIT | DFXL_STRETCHBLIT)
88
89
90 /* macro for S12.0 and S14.0 format */
91 #define S12(val) (((u16)((s16)(val)))&0x3fff)
92 #define S14(val) (((u16)((s16)(val)))&0x3fff)
93
94 /** CARD FUNCTIONS **/
95 static bool ati128FillRectangle( void *drv, void *dev, DFBRectangle *rect );
96 static bool ati128FillBlendRectangle( void *drv, void *dev, DFBRectangle *rect );
97 static bool ati128DrawRectangle( void *drv, void *dev, DFBRectangle *rect );
98 static bool ati128DrawBlendRectangle( void *drv, void *dev, DFBRectangle *rect );
99
100 /* required implementations */
101
ati128EngineSync(void * drv,void * dev)102 static DFBResult ati128EngineSync( void *drv, void *dev )
103 {
104 ATI128DriverData *adrv = (ATI128DriverData*) drv;
105 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
106
107 ati128_waitidle( adrv, adev );
108
109 return DFB_OK;
110 }
111
ati128_check_blend(CardState * state)112 static bool ati128_check_blend( CardState *state )
113 {
114 if (state->dst_blend == DSBF_SRCALPHASAT)
115 return false;
116
117 return true;
118 }
119
ati128CheckState(void * drv,void * dev,CardState * state,DFBAccelerationMask accel)120 static void ati128CheckState( void *drv, void *dev,
121 CardState *state, DFBAccelerationMask accel )
122 {
123 switch (state->destination->config.format) {
124 case DSPF_RGB332:
125 case DSPF_ARGB1555:
126 case DSPF_RGB16:
127 case DSPF_RGB24:
128 case DSPF_RGB32:
129 case DSPF_ARGB:
130 break;
131 default:
132 return;
133 }
134
135 /* check for the special drawing function that does not support
136 the usually supported drawingflags */
137 if (accel == DFXL_DRAWLINE && state->drawingflags != DSDRAW_NOFX)
138 return;
139
140 /* if there are no other drawing flags than the supported */
141 if (!(accel & ~ATI128_SUPPORTED_DRAWINGFUNCTIONS) &&
142 !(state->drawingflags & ~ATI128_SUPPORTED_DRAWINGFLAGS)) {
143 if (state->drawingflags & DSDRAW_BLEND &&
144 !ati128_check_blend( state ))
145 return;
146
147 state->accel |= ATI128_SUPPORTED_DRAWINGFUNCTIONS;
148 }
149
150 /* if there are no other blitting flags than the supported
151 and the source has the minimum size */
152 if (!(accel & ~ATI128_SUPPORTED_BLITTINGFUNCTIONS) &&
153 !(state->blittingflags & ~ATI128_SUPPORTED_BLITTINGFLAGS) &&
154 state->source &&
155 state->source->config.size.w >= 8 &&
156 state->source->config.size.h >= 8 )
157 {
158 if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL &&
159 !ati128_check_blend( state ))
160 return;
161
162 switch (state->source->config.format) {
163 case DSPF_RGB332:
164 case DSPF_ARGB1555:
165 case DSPF_RGB16:
166 case DSPF_RGB24:
167 case DSPF_RGB32:
168 case DSPF_ARGB:
169 state->accel |= ATI128_SUPPORTED_BLITTINGFUNCTIONS;
170 default:
171 ;
172 }
173 }
174 }
175
176
ati128SetState(void * drv,void * dev,GraphicsDeviceFuncs * funcs,CardState * state,DFBAccelerationMask accel)177 static void ati128SetState( void *drv, void *dev,
178 GraphicsDeviceFuncs *funcs,
179 CardState *state, DFBAccelerationMask accel )
180 {
181 ATI128DriverData *adrv = (ATI128DriverData*) drv;
182 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
183
184 if (state->mod_hw & SMF_SOURCE)
185 adev->v_source = 0;
186
187 if (state->mod_hw & SMF_DESTINATION)
188 adev->v_destination = adev->v_color = 0;
189
190 if (state->mod_hw & SMF_COLOR)
191 adev->v_color = 0;
192
193 if (state->mod_hw & SMF_SRC_COLORKEY)
194 adev->v_src_colorkey = 0;
195
196 if (state->mod_hw & SMF_BLITTING_FLAGS)
197 adev->v_blittingflags = 0;
198
199 if (state->mod_hw & (SMF_SRC_BLEND | SMF_DST_BLEND))
200 adev->v_blending_function = 0;
201
202 ati128_set_destination( adrv, adev, state);
203
204 switch (accel) {
205 case DFXL_FILLRECTANGLE:
206 case DFXL_DRAWRECTANGLE:
207 if (state->drawingflags & DSDRAW_BLEND) {
208 ati128_set_blending_function( adrv, adev, state );
209 funcs->FillRectangle = ati128FillBlendRectangle;
210 funcs->DrawRectangle = ati128DrawBlendRectangle;
211 }
212 else {
213 funcs->FillRectangle = ati128FillRectangle;
214 funcs->DrawRectangle = ati128DrawRectangle;
215 }
216 case DFXL_DRAWLINE:
217 ati128_set_color( adrv, adev, state );
218 state->set |= DFXL_FILLRECTANGLE | DFXL_DRAWLINE | DFXL_DRAWRECTANGLE ;
219 break;
220
221 case DFXL_BLIT:
222 case DFXL_STRETCHBLIT:
223 ati128_set_source( adrv, adev, state );
224 if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
225 ati128_set_blending_function( adrv, adev, state );
226 if (state->blittingflags & DSBLIT_SRC_COLORKEY)
227 ati128_set_src_colorkey( adrv, adev, state );
228 ati128_set_blittingflags( adrv, adev, state );
229 state->set |= DFXL_BLIT | DFXL_STRETCHBLIT;
230 break;
231
232 default:
233 D_BUG( "unexpected drawing/blitting function" );
234 break;
235 }
236
237 if (state->mod_hw & SMF_CLIP)
238 ati128_set_clip( adrv, adev, state);
239
240 state->mod_hw = 0;
241 }
242
ati128FillRectangle(void * drv,void * dev,DFBRectangle * rect)243 static bool ati128FillRectangle( void *drv, void *dev, DFBRectangle *rect )
244 {
245 ATI128DriverData *adrv = (ATI128DriverData*) drv;
246 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
247 volatile u8 *mmio = adrv->mmio_base;
248
249 ati128_waitfifo( adrv, adev, 5 );
250 /* set the destination datatype */
251 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR );
252 /* set direction */
253 ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
254 /* set the drawing command */
255 ati128_out32( mmio, DP_MIX, ROP3_PATCOPY | DP_SRC_RECT );
256 /* set parameters */
257 ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x) );
258 /* this executes the drawing command */
259 ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w );
260
261 return true;
262 }
263
ati128FillBlendRectangle(void * drv,void * dev,DFBRectangle * rect)264 static bool ati128FillBlendRectangle( void *drv, void *dev, DFBRectangle *rect )
265 {
266 ATI128DriverData *adrv = (ATI128DriverData*) drv;
267 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
268 volatile u8 *mmio = adrv->mmio_base;
269
270 u32 fts = adev->ATI_fake_texture_src + (adev->fake_texture_number & 7)*4;
271 ati128_waitidle( adrv, adev );
272 *((u32*) dfb_gfxcard_memory_virtual(NULL,fts) ) = adev->fake_texture_color;
273 ati128_waitidle( adrv, adev );
274
275 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
276 ati128_out32( mmio, SCALE_PITCH, 1 );
277 /* enable scaling with filtering */
278 ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
279 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
280 ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
281 /* flush the texture cache */
282 ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON | TEX_CNTL_TEX_CACHE_FLUSH_ON);
283 /* set source offset */
284 ati128_out32( mmio, SCALE_OFFSET_0, fts ) ;
285 /* set height and width of the source */
286 ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (8 << 16) | 8);
287 /* set the scaling increment registers */
288 ati128_out32( mmio, SCALE_X_INC, 0 );
289 ati128_out32( mmio, SCALE_Y_INC, 0 );
290 /* reset accumulator regs */
291 ati128_out32( mmio, SCALE_HACC, 0x00000000 );
292 ati128_out32( mmio, SCALE_VACC, 0x00000000 );
293 /* set the destination coordinates */
294 ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y) );
295 /* set destination height and width and perform the blit */
296 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w );
297 /*reset scaling and texture control register */
298 ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
299 ati128_out32( mmio, TEX_CNTL, 0);
300 adev->fake_texture_number++;
301
302 return true;
303 }
304
ati128DrawRectangle(void * drv,void * dev,DFBRectangle * rect)305 static bool ati128DrawRectangle( void *drv, void *dev, DFBRectangle *rect )
306 {
307 ATI128DriverData *adrv = (ATI128DriverData*) drv;
308 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
309 volatile u8 *mmio = adrv->mmio_base;
310
311 ati128_waitfifo( adrv, adev, 3 );
312 /* set the destination datatype */
313 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR );
314 /* set direction */
315 ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
316 /* set the drawing command */
317 ati128_out32( mmio, DP_MIX, ROP3_PATCOPY | DP_SRC_RECT );
318
319 ati128_waitfifo( adrv, adev, 7 );
320 /* first line */
321 ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x));
322 ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | 1);
323 /* second line */
324 ati128_out32( mmio, DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
325 /* third line */
326 ati128_out32( mmio, DST_Y_X, (S14(rect->y+rect->h-1) << 16) | S12(rect->x));
327 ati128_out32( mmio, DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
328 /* fourth line */
329 ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x+rect->w-1));
330 ati128_out32( mmio, DST_HEIGHT_WIDTH, rect->h << 16 | 1);
331
332 return true;
333 }
334
ati128DrawBlendRectangle(void * drv,void * dev,DFBRectangle * rect)335 static bool ati128DrawBlendRectangle( void *drv, void *dev, DFBRectangle *rect )
336 {
337 ATI128DriverData *adrv = (ATI128DriverData*) drv;
338 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
339 volatile u8 *mmio = adrv->mmio_base;
340
341 u32 fts = adev->ATI_fake_texture_src + (adev->fake_texture_number & 7)*4;
342
343 ati128_waitidle( adrv, adev );
344 *((u32*) dfb_gfxcard_memory_virtual(NULL,fts) ) = adev->fake_texture_color;
345 ati128_waitidle( adrv, adev );
346
347 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
348 ati128_out32( mmio, SCALE_PITCH, 1 );
349
350 /* enable scaling with filtering */
351 ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
352 ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON | TEX_CNTL_TEX_CACHE_FLUSH_ON);
353 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
354 ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
355 /* set source offset */
356 ati128_out32( mmio, SCALE_OFFSET_0, adev->ATI_fake_texture_src );
357 /* set height and width of the source */
358 ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (8 << 16) | 8);
359 /* set the scaling increment registers */
360 ati128_out32( mmio, SCALE_X_INC, 0 );
361 ati128_out32( mmio, SCALE_Y_INC, 0 );
362 /* reset accumulator regs */
363 ati128_out32( mmio, SCALE_HACC, 0x00000000 );
364 ati128_out32( mmio, SCALE_VACC, 0x00000000 );
365 /* set the destination coordinates */
366
367 /*-----------------------*/
368 /* first line */
369 ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y) );
370 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (rect->h << 16) | 1);
371 /* second line */
372 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
373 /* third line */
374 ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y+rect->h-1));
375 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
376 /* fourth line */
377 ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x+rect->w-1) << 16) | S14(rect->y));
378 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, rect->h << 16 | 1);
379 /*-----------------------*/
380
381 /* reset scaling and texture control register */
382 ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
383 ati128_out32( mmio, TEX_CNTL, 0 );
384 adev->fake_texture_number++;
385
386 return true;
387 }
388
389
ati128DrawLine(void * drv,void * dev,DFBRegion * line)390 static bool ati128DrawLine( void *drv, void *dev, DFBRegion *line )
391 {
392 ATI128DriverData *adrv = (ATI128DriverData*) drv;
393 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
394 volatile u8 *mmio = adrv->mmio_base;
395
396 int dx, dy;
397 int small, large;
398 int x_dir, y_dir, y_major;
399 int err, inc, dec;
400
401 /* Determine x & y deltas and x & y direction bits. */
402 if (line->x1 < line->x2) {
403 dx = line->x2 - line->x1;
404 x_dir = 1 << 31;
405 }
406 else {
407 dx = line->x1 - line->x2;
408 x_dir = 0 << 31;
409 }
410
411 if (line->y1 < line->y2) {
412 dy = line->y2 - line->y1;
413 y_dir = 1 << 15;
414 }
415 else {
416 dy = line->y1 - line->y2;
417 y_dir = 0 << 15;
418 }
419
420 /* Determine x & y min and max values; also determine y major bit. */
421 if (dx < dy) {
422 small = dx;
423 large = dy;
424 y_major = 1 << 2;
425 }
426 else {
427 small = dy;
428 large = dx;
429 y_major = 0 << 2;
430 }
431
432 /* Calculate Bresenham parameters and draw line. */
433 err = -large;
434 inc = small * 2;
435 dec = large *(-2);
436
437 ati128_waitfifo( adrv, adev, 8 );
438 /* set the destination datatype */
439 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR | ROP3_SRCCOPY );
440 ati128_out32( mmio, DP_MIX, ROP3_PATCOPY );
441
442 /* set start coorinates */
443 ati128_out32( mmio, DST_Y_X, (S14(line->y1) << 16) | S12(line->x1));
444 /* allow setting of last pel bit and polygon
445 outline bit for line drawing */
446 ati128_out32( mmio, DP_CNTL_XDIR_YDIR_YMAJOR,
447 y_major | y_dir | x_dir );
448 /* set bresenham registers and start drawing */
449 ati128_out32( mmio, DST_BRES_ERR, err );
450 ati128_out32( mmio, DST_BRES_INC, inc );
451 ati128_out32( mmio, DST_BRES_DEC, dec );
452 ati128_out32( mmio, DST_BRES_LNTH, large + 1 );
453
454 return true;
455 }
456
ati128StretchBlit(void * drv,void * dev,DFBRectangle * sr,DFBRectangle * dr)457 static bool ati128StretchBlit( void *drv, void *dev, DFBRectangle *sr, DFBRectangle *dr )
458 {
459 ATI128DriverData *adrv = (ATI128DriverData*) drv;
460 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
461 volatile u8 *mmio = adrv->mmio_base;
462
463 u32 src = 0;
464
465 u32 scalex = (u32)(((double)sr->w/(double)dr->w) * 65536);
466 u32 scaley = (u32)(((double)sr->h/(double)dr->h) * 65536);
467
468 ati128_waitfifo( adrv, adev, 9 );
469
470 /* make sure that color compare register is restored to last state */
471
472 ati128_out32( mmio, CLR_CMP_CNTL, adev->ATI_color_compare );
473
474 switch (adev->source->config.format) {
475 case DSPF_RGB332:
476 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_8BPP_RGB332 );
477
478 ati128_out32( mmio, SCALE_PITCH,
479 adev->src->pitch >>3);
480
481 src = adev->src->offset +
482 sr->y *
483 adev->src->pitch + sr->x;
484
485 ati128_out32( mmio, TEX_CNTL, 0);
486
487 break;
488 case DSPF_ARGB1555: /* FIXME: alpha channel will be zero ;( */
489 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_15BPP );
490
491 ati128_out32( mmio, SCALE_PITCH,
492 adev->src->pitch >>4);
493
494 src = adev->src->offset +
495 sr->y *
496 adev->src->pitch + sr->x*2;
497
498 ati128_out32( mmio, TEX_CNTL, 0);
499
500 break;
501 case DSPF_RGB16:
502 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_16BPP );
503
504 ati128_out32( mmio, SCALE_PITCH,
505 adev->src->pitch >>4);
506
507 src = adev->src->offset +
508 sr->y *
509 adev->src->pitch + sr->x*2;
510
511 ati128_out32( mmio, TEX_CNTL, 0);
512
513 break;
514 case DSPF_RGB24:
515 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_24BPP );
516
517 ati128_out32( mmio, SCALE_PITCH,
518 adev->src->pitch >>3);
519
520 src = adev->src->offset +
521 sr->y *
522 adev->src->pitch + sr->x*3;
523
524 ati128_out32( mmio, TEX_CNTL, 0);
525
526 break;
527 case DSPF_RGB32:
528 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
529
530 ati128_out32( mmio, SCALE_PITCH,
531 adev->src->pitch >>5);
532
533 src = adev->src->offset +
534 sr->y *
535 adev->src->pitch + sr->x*4;
536
537 ati128_out32( mmio, TEX_CNTL, 0);
538
539 break;
540 case DSPF_ARGB:
541 ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
542
543 ati128_out32( mmio, SCALE_PITCH,
544 adev->src->pitch >>5);
545
546 src = adev->src->offset +
547 sr->y *
548 adev->src->pitch + sr->x*4;
549
550 if (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
551 ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON );
552 else
553 ati128_out32( mmio, TEX_CNTL, 0 );
554 break;
555 default:
556 D_BUG( "unexpected pixelformat!" );
557 return false;
558 }
559
560 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
561
562 /* set the blend function */
563 if (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
564 ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
565 else
566 ati128_out32( mmio, SCALE_3D_CNTL, SCALE_3D_CNTL_SCALE_3D_FN_SCALE );
567
568 /* set up source data and copy type */
569 ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
570 /* set source offset */
571 ati128_out32( mmio, SCALE_OFFSET_0, src);
572 /* set height and width of the source */
573 ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (sr->h << 16) | sr->w);
574
575 ati128_waitfifo( adrv, adev, 9 );
576 /* set the scaling increment registers */
577 ati128_out32( mmio, SCALE_X_INC, scalex );
578 ati128_out32( mmio, SCALE_Y_INC, scaley );
579 /* reset accumulator regs */
580 ati128_out32( mmio, SCALE_HACC, 0x00000000 );
581 ati128_out32( mmio, SCALE_VACC, 0x00000000 );
582 /* set the destination coordinates */
583 ati128_out32( mmio, SCALE_DST_X_Y, (S12(dr->x) << 16) | S14(dr->y) );
584 /* set destination height and width and perform the blit */
585 ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (dr->h << 16) | dr->w );
586 /*reset scaling and texture control register */
587 ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
588 ati128_out32( mmio, TEX_CNTL, 0x00000000 );
589
590 /* set CLR_CMP_CNTL to zero, to insure that drawing funcions work corrently */
591 if (adev->ATI_color_compare)
592 ati128_out32( mmio, CLR_CMP_CNTL, 0 );
593
594 return true;
595 }
596
ati128Blit(void * drv,void * dev,DFBRectangle * rect,int dx,int dy)597 static bool ati128Blit( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
598 {
599 ATI128DriverData *adrv = (ATI128DriverData*) drv;
600 ATI128DeviceData *adev = (ATI128DeviceData*) dev;
601 volatile u8 *mmio = adrv->mmio_base;
602
603 u32 dir_cmd = 0;
604
605 if ((adev->source->config.format != adev->destination->config.format) ||
606 (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL))
607 {
608 DFBRectangle sr = { rect->x, rect->y, rect->w, rect->h };
609 DFBRectangle dr = { dx, dy, rect->w, rect->h };
610 ati128StretchBlit( adrv, adev, &sr, &dr );
611 return true;
612 }
613
614 /* check which blitting direction should be used */
615 if (rect->x <= dx) {
616 dir_cmd |= DST_X_RIGHT_TO_LEFT;
617 rect->x += rect->w-1;
618 dx += rect->w-1;
619 }
620 else {
621 dir_cmd |= DST_X_LEFT_TO_RIGHT;
622 }
623 if (rect->y <= dy) {
624 dir_cmd |= DST_Y_BOTTOM_TO_TOP;
625 rect->y += rect->h-1;
626 dy += rect->h-1;
627 }
628 else {
629 dir_cmd |= DST_Y_TOP_TO_BOTTOM;
630 }
631
632 ati128_waitfifo( adrv, adev, 9 );
633
634 /* make sure that color compare register is restored to last state */
635 ati128_out32( mmio, CLR_CMP_CNTL, adev->ATI_color_compare );
636
637 /* set blitting direction */
638 ati128_out32( mmio, DP_CNTL, dir_cmd );
639
640 ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
641 ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
642
643 ati128_out32( mmio, SRC_Y_X, (rect->y << 16) | rect->x);
644 ati128_out32( mmio, DST_Y_X, (S14(dy) << 16) | S12(dx) );
645 ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w);
646
647 /* set CLR_CMP_CNTL to zero, to insure that drawing funcions work corrently */
648 if (adev->ATI_color_compare)
649 ati128_out32( mmio, CLR_CMP_CNTL, 0 );
650
651 if (dir_cmd != (DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT)) {
652 ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT |
653 DST_Y_TOP_TO_BOTTOM );
654 }
655
656 return true;
657 }
658
659 /* exported symbols */
660
661 static int
driver_probe(CoreGraphicsDevice * device)662 driver_probe( CoreGraphicsDevice *device )
663 {
664 switch (dfb_gfxcard_get_accelerator( device )) {
665 case FB_ACCEL_ATI_RAGE128: /* ATI Rage 128 */
666 return 1;
667 }
668
669 return 0;
670 }
671
672
673 static void
driver_get_info(CoreGraphicsDevice * device,GraphicsDriverInfo * info)674 driver_get_info( CoreGraphicsDevice *device,
675 GraphicsDriverInfo *info )
676 {
677 /* fill driver info structure */
678 snprintf( info->name,
679 DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH,
680 "ATI Rage 128 Driver" );
681
682 snprintf( info->vendor,
683 DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH,
684 "directfb.org" );
685
686 info->version.major = 0;
687 info->version.minor = 2;
688
689 info->driver_data_size = sizeof (ATI128DriverData);
690 info->device_data_size = sizeof (ATI128DeviceData);
691 }
692
693 static DFBResult
driver_init_driver(CoreGraphicsDevice * device,GraphicsDeviceFuncs * funcs,void * driver_data,void * device_data,CoreDFB * core)694 driver_init_driver( CoreGraphicsDevice *device,
695 GraphicsDeviceFuncs *funcs,
696 void *driver_data,
697 void *device_data,
698 CoreDFB *core )
699 {
700 ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
701
702 adrv->mmio_base = (volatile u8*) dfb_gfxcard_map_mmio( device, 0, -1 );
703 if (!adrv->mmio_base)
704 return DFB_IO;
705
706 funcs->CheckState = ati128CheckState;
707 funcs->SetState = ati128SetState;
708 funcs->EngineSync = ati128EngineSync;
709
710 funcs->FillRectangle = ati128FillRectangle;
711 funcs->DrawRectangle = ati128DrawRectangle;
712 funcs->DrawLine = ati128DrawLine;
713 funcs->Blit = ati128Blit;
714 funcs->StretchBlit = ati128StretchBlit;
715
716 /* overlay support */
717 dfb_layers_register( dfb_screens_at(DSCID_PRIMARY),
718 driver_data, &atiOverlayFuncs );
719
720 return DFB_OK;
721 }
722
723
724 static DFBResult
driver_init_device(CoreGraphicsDevice * device,GraphicsDeviceInfo * device_info,void * driver_data,void * device_data)725 driver_init_device( CoreGraphicsDevice *device,
726 GraphicsDeviceInfo *device_info,
727 void *driver_data,
728 void *device_data )
729 {
730 ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
731 ATI128DeviceData *adev = (ATI128DeviceData*) device_data;
732 volatile u8 *mmio = adrv->mmio_base;
733
734 /* fill device info */
735 snprintf( device_info->name,
736 DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "Rage 128" );
737
738 snprintf( device_info->vendor,
739 DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "ATI" );
740
741
742 device_info->caps.flags = CCF_CLIPPING;
743 device_info->caps.accel = ATI128_SUPPORTED_DRAWINGFUNCTIONS |
744 ATI128_SUPPORTED_BLITTINGFUNCTIONS;
745 device_info->caps.drawing = ATI128_SUPPORTED_DRAWINGFLAGS;
746 device_info->caps.blitting = ATI128_SUPPORTED_BLITTINGFLAGS;
747
748 device_info->limits.surface_byteoffset_alignment = 32 * 4;
749 device_info->limits.surface_pixelpitch_alignment = 32;
750
751
752 /* initialize card */
753 ati128_waitfifo( adrv, adev, 6 );
754
755 ati128_out32( mmio, DP_GUI_MASTER_CNTL,
756 GMC_SRC_PITCH_OFFSET_DEFAULT |
757 GMC_DST_PITCH_OFFSET_DEFAULT |
758 GMC_SRC_CLIP_DEFAULT |
759 GMC_DST_CLIP_DEFAULT |
760 GMC_BRUSH_SOLIDCOLOR |
761 GMC_SRC_DSTCOLOR |
762 GMC_BYTE_ORDER_MSB_TO_LSB |
763 GMC_DP_CONVERSION_TEMP_6500 |
764 ROP3_PATCOPY |
765 GMC_DP_SRC_RECT |
766 GMC_3D_FCN_EN_CLR |
767 GMC_DST_CLR_CMP_FCN_CLEAR |
768 GMC_AUX_CLIP_CLEAR |
769 GMC_WRITE_MASK_SET);
770
771 ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
772 ati128_out32( mmio, TEX_CNTL, 0x00000000 );
773
774 /* reserve 32bit pixel for fake texture at end of framebuffer */
775 adev->ATI_fake_texture_src = dfb_gfxcard_reserve_memory( device, 4*32 );
776
777 return DFB_OK;
778 }
779
780 static void
driver_close_device(CoreGraphicsDevice * device,void * driver_data,void * device_data)781 driver_close_device( CoreGraphicsDevice *device,
782 void *driver_data,
783 void *device_data )
784 {
785 ATI128DeviceData *adev = (ATI128DeviceData*) device_data;
786 ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
787 volatile u8 *mmio = adrv->mmio_base;
788
789 D_DEBUG( "DirectFB/ATI128: FIFO Performance Monitoring:\n" );
790 D_DEBUG( "DirectFB/ATI128: %9d ati128_waitfifo calls\n",
791 adev->waitfifo_calls );
792 D_DEBUG( "DirectFB/ATI128: %9d register writes (ati128_waitfifo sum)\n",
793 adev->waitfifo_sum );
794 D_DEBUG( "DirectFB/ATI128: %9d FIFO wait cycles (depends on CPU)\n",
795 adev->fifo_waitcycles );
796 D_DEBUG( "DirectFB/ATI128: %9d IDLE wait cycles (depends on CPU)\n",
797 adev->idle_waitcycles );
798 D_DEBUG( "DirectFB/ATI128: %9d FIFO space cache hits(depends on CPU)\n",
799 adev->fifo_cache_hits );
800 D_DEBUG( "DirectFB/ATI128: Conclusion:\n" );
801 D_DEBUG( "DirectFB/ATI128: Average register writes/ati128_waitfifo"
802 "call:%.2f\n",
803 adev->waitfifo_sum/(float)(adev->waitfifo_calls) );
804 D_DEBUG( "DirectFB/ATI128: Average wait cycles/ati128_waitfifo call:"
805 " %.2f\n",
806 adev->fifo_waitcycles/(float)(adev->waitfifo_calls) );
807 D_DEBUG( "DirectFB/ATI128: Average fifo space cache hits: %02d%%\n",
808 (int)(100 * adev->fifo_cache_hits/
809 (float)(adev->waitfifo_calls)) );
810
811 /* clean up, make sure that aty128fb does not hang in kernel space
812 afterwards */
813 ati128_waitfifo( adrv, adev, 3 );
814
815 ati128_out32( mmio, DP_GUI_MASTER_CNTL,
816 GMC_SRC_PITCH_OFFSET_DEFAULT |
817 GMC_DST_PITCH_OFFSET_DEFAULT |
818 GMC_SRC_CLIP_DEFAULT |
819 GMC_DST_CLIP_DEFAULT |
820 GMC_BRUSH_SOLIDCOLOR |
821 GMC_SRC_DSTCOLOR |
822 GMC_BYTE_ORDER_MSB_TO_LSB |
823 GMC_DP_CONVERSION_TEMP_6500 |
824 ROP3_PATCOPY |
825 GMC_DP_SRC_RECT |
826 GMC_3D_FCN_EN_CLR |
827 GMC_DST_CLR_CMP_FCN_CLEAR |
828 GMC_AUX_CLIP_CLEAR |
829 GMC_WRITE_MASK_SET);
830
831 ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
832 ati128_out32( mmio, TEX_CNTL, 0x00000000 );
833 }
834
835 static void
driver_close_driver(CoreGraphicsDevice * device,void * driver_data)836 driver_close_driver( CoreGraphicsDevice *device,
837 void *driver_data )
838 {
839 ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
840
841 dfb_gfxcard_unmap_mmio( device, adrv->mmio_base, -1 );
842 }
843