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