summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/ati128/ati128.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/ati128/ati128.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/ati128/ati128.c842
1 files changed, 842 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/ati128/ati128.c b/Source/DirectFB/gfxdrivers/ati128/ati128.c
new file mode 100755
index 0000000..4ae34c6
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/ati128/ati128.c
@@ -0,0 +1,842 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <dfb_types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <fbdev/fb.h>
+
+#include <directfb.h>
+
+#include <direct/messages.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/screens.h>
+#include <core/state.h>
+#include <core/gfxcard.h>
+#include <core/surface.h>
+
+#include <gfx/convert.h>
+
+#include <core/graphics_driver.h>
+
+
+DFB_GRAPHICS_DRIVER( ati128 )
+
+
+#include "regs.h"
+#include "mmio.h"
+#include "ati128_state.h"
+#include "ati128.h"
+
+
+/* driver capability flags */
+
+
+#ifndef __powerpc__
+#define ATI128_SUPPORTED_DRAWINGFLAGS \
+ (DSDRAW_BLEND)
+#else
+#define ATI128_SUPPORTED_DRAWINGFLAGS \
+ (DSDRAW_NOFX)
+#endif
+
+#define ATI128_SUPPORTED_DRAWINGFUNCTIONS \
+ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE)
+
+#define ATI128_SUPPORTED_BLITTINGFLAGS \
+ (DSBLIT_SRC_COLORKEY | DSBLIT_BLEND_ALPHACHANNEL)
+
+#define ATI128_SUPPORTED_BLITTINGFUNCTIONS \
+ (DFXL_BLIT | DFXL_STRETCHBLIT)
+
+
+/* macro for S12.0 and S14.0 format */
+#define S12(val) (((u16)((s16)(val)))&0x3fff)
+#define S14(val) (((u16)((s16)(val)))&0x3fff)
+
+/** CARD FUNCTIONS **/
+static bool ati128FillRectangle( void *drv, void *dev, DFBRectangle *rect );
+static bool ati128FillBlendRectangle( void *drv, void *dev, DFBRectangle *rect );
+static bool ati128DrawRectangle( void *drv, void *dev, DFBRectangle *rect );
+static bool ati128DrawBlendRectangle( void *drv, void *dev, DFBRectangle *rect );
+
+/* required implementations */
+
+static DFBResult ati128EngineSync( void *drv, void *dev )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+
+ ati128_waitidle( adrv, adev );
+
+ return DFB_OK;
+}
+
+static bool ati128_check_blend( CardState *state )
+{
+ if (state->dst_blend == DSBF_SRCALPHASAT)
+ return false;
+
+ return true;
+}
+
+static void ati128CheckState( void *drv, void *dev,
+ CardState *state, DFBAccelerationMask accel )
+{
+ switch (state->destination->config.format) {
+ case DSPF_RGB332:
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_RGB24:
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ break;
+ default:
+ return;
+ }
+
+ /* check for the special drawing function that does not support
+ the usually supported drawingflags */
+ if (accel == DFXL_DRAWLINE && state->drawingflags != DSDRAW_NOFX)
+ return;
+
+ /* if there are no other drawing flags than the supported */
+ if (!(accel & ~ATI128_SUPPORTED_DRAWINGFUNCTIONS) &&
+ !(state->drawingflags & ~ATI128_SUPPORTED_DRAWINGFLAGS)) {
+ if (state->drawingflags & DSDRAW_BLEND &&
+ !ati128_check_blend( state ))
+ return;
+
+ state->accel |= ATI128_SUPPORTED_DRAWINGFUNCTIONS;
+ }
+
+ /* if there are no other blitting flags than the supported
+ and the source has the minimum size */
+ if (!(accel & ~ATI128_SUPPORTED_BLITTINGFUNCTIONS) &&
+ !(state->blittingflags & ~ATI128_SUPPORTED_BLITTINGFLAGS) &&
+ state->source &&
+ state->source->config.size.w >= 8 &&
+ state->source->config.size.h >= 8 )
+ {
+ if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL &&
+ !ati128_check_blend( state ))
+ return;
+
+ switch (state->source->config.format) {
+ case DSPF_RGB332:
+ case DSPF_ARGB1555:
+ case DSPF_RGB16:
+ case DSPF_RGB24:
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ state->accel |= ATI128_SUPPORTED_BLITTINGFUNCTIONS;
+ default:
+ ;
+ }
+ }
+}
+
+
+static void ati128SetState( void *drv, void *dev,
+ GraphicsDeviceFuncs *funcs,
+ CardState *state, DFBAccelerationMask accel )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+
+ if (state->mod_hw & SMF_SOURCE)
+ adev->v_source = 0;
+
+ if (state->mod_hw & SMF_DESTINATION)
+ adev->v_destination = adev->v_color = 0;
+
+ if (state->mod_hw & SMF_COLOR)
+ adev->v_color = 0;
+
+ if (state->mod_hw & SMF_SRC_COLORKEY)
+ adev->v_src_colorkey = 0;
+
+ if (state->mod_hw & SMF_BLITTING_FLAGS)
+ adev->v_blittingflags = 0;
+
+ if (state->mod_hw & (SMF_SRC_BLEND | SMF_DST_BLEND))
+ adev->v_blending_function = 0;
+
+ ati128_set_destination( adrv, adev, state);
+
+ switch (accel) {
+ case DFXL_FILLRECTANGLE:
+ case DFXL_DRAWRECTANGLE:
+ if (state->drawingflags & DSDRAW_BLEND) {
+ ati128_set_blending_function( adrv, adev, state );
+ funcs->FillRectangle = ati128FillBlendRectangle;
+ funcs->DrawRectangle = ati128DrawBlendRectangle;
+ }
+ else {
+ funcs->FillRectangle = ati128FillRectangle;
+ funcs->DrawRectangle = ati128DrawRectangle;
+ }
+ case DFXL_DRAWLINE:
+ ati128_set_color( adrv, adev, state );
+ state->set |= DFXL_FILLRECTANGLE | DFXL_DRAWLINE | DFXL_DRAWRECTANGLE ;
+ break;
+
+ case DFXL_BLIT:
+ case DFXL_STRETCHBLIT:
+ ati128_set_source( adrv, adev, state );
+ if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
+ ati128_set_blending_function( adrv, adev, state );
+ if (state->blittingflags & DSBLIT_SRC_COLORKEY)
+ ati128_set_src_colorkey( adrv, adev, state );
+ ati128_set_blittingflags( adrv, adev, state );
+ state->set |= DFXL_BLIT | DFXL_STRETCHBLIT;
+ break;
+
+ default:
+ D_BUG( "unexpected drawing/blitting function" );
+ break;
+ }
+
+ if (state->mod_hw & SMF_CLIP)
+ ati128_set_clip( adrv, adev, state);
+
+ state->mod_hw = 0;
+}
+
+static bool ati128FillRectangle( void *drv, void *dev, DFBRectangle *rect )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ ati128_waitfifo( adrv, adev, 5 );
+ /* set the destination datatype */
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR );
+ /* set direction */
+ ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ /* set the drawing command */
+ ati128_out32( mmio, DP_MIX, ROP3_PATCOPY | DP_SRC_RECT );
+ /* set parameters */
+ ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x) );
+ /* this executes the drawing command */
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w );
+
+ return true;
+}
+
+static bool ati128FillBlendRectangle( void *drv, void *dev, DFBRectangle *rect )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ u32 fts = adev->ATI_fake_texture_src + (adev->fake_texture_number & 7)*4;
+ ati128_waitidle( adrv, adev );
+ *((u32*) dfb_gfxcard_memory_virtual(NULL,fts) ) = adev->fake_texture_color;
+ ati128_waitidle( adrv, adev );
+
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
+ ati128_out32( mmio, SCALE_PITCH, 1 );
+ /* enable scaling with filtering */
+ ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
+ ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
+ /* flush the texture cache */
+ ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON | TEX_CNTL_TEX_CACHE_FLUSH_ON);
+ /* set source offset */
+ ati128_out32( mmio, SCALE_OFFSET_0, fts ) ;
+ /* set height and width of the source */
+ ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (8 << 16) | 8);
+ /* set the scaling increment registers */
+ ati128_out32( mmio, SCALE_X_INC, 0 );
+ ati128_out32( mmio, SCALE_Y_INC, 0 );
+ /* reset accumulator regs */
+ ati128_out32( mmio, SCALE_HACC, 0x00000000 );
+ ati128_out32( mmio, SCALE_VACC, 0x00000000 );
+ /* set the destination coordinates */
+ ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y) );
+ /* set destination height and width and perform the blit */
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w );
+ /*reset scaling and texture control register */
+ ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
+ ati128_out32( mmio, TEX_CNTL, 0);
+ adev->fake_texture_number++;
+
+ return true;
+}
+
+static bool ati128DrawRectangle( void *drv, void *dev, DFBRectangle *rect )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ ati128_waitfifo( adrv, adev, 3 );
+ /* set the destination datatype */
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR );
+ /* set direction */
+ ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ /* set the drawing command */
+ ati128_out32( mmio, DP_MIX, ROP3_PATCOPY | DP_SRC_RECT );
+
+ ati128_waitfifo( adrv, adev, 7 );
+ /* first line */
+ ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x));
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | 1);
+ /* second line */
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
+ /* third line */
+ ati128_out32( mmio, DST_Y_X, (S14(rect->y+rect->h-1) << 16) | S12(rect->x));
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
+ /* fourth line */
+ ati128_out32( mmio, DST_Y_X, (S14(rect->y) << 16) | S12(rect->x+rect->w-1));
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, rect->h << 16 | 1);
+
+ return true;
+}
+
+static bool ati128DrawBlendRectangle( void *drv, void *dev, DFBRectangle *rect )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ u32 fts = adev->ATI_fake_texture_src + (adev->fake_texture_number & 7)*4;
+
+ ati128_waitidle( adrv, adev );
+ *((u32*) dfb_gfxcard_memory_virtual(NULL,fts) ) = adev->fake_texture_color;
+ ati128_waitidle( adrv, adev );
+
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
+ ati128_out32( mmio, SCALE_PITCH, 1 );
+
+ /* enable scaling with filtering */
+ ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
+ ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON | TEX_CNTL_TEX_CACHE_FLUSH_ON);
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
+ ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
+ /* set source offset */
+ ati128_out32( mmio, SCALE_OFFSET_0, adev->ATI_fake_texture_src );
+ /* set height and width of the source */
+ ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (8 << 16) | 8);
+ /* set the scaling increment registers */
+ ati128_out32( mmio, SCALE_X_INC, 0 );
+ ati128_out32( mmio, SCALE_Y_INC, 0 );
+ /* reset accumulator regs */
+ ati128_out32( mmio, SCALE_HACC, 0x00000000 );
+ ati128_out32( mmio, SCALE_VACC, 0x00000000 );
+ /* set the destination coordinates */
+
+ /*-----------------------*/
+ /* first line */
+ ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y) );
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (rect->h << 16) | 1);
+ /* second line */
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
+ /* third line */
+ ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x) << 16) | S14(rect->y+rect->h-1));
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (1 << 16) | rect->w );
+ /* fourth line */
+ ati128_out32( mmio, SCALE_DST_X_Y, (S12(rect->x+rect->w-1) << 16) | S14(rect->y));
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, rect->h << 16 | 1);
+ /*-----------------------*/
+
+ /* reset scaling and texture control register */
+ ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
+ ati128_out32( mmio, TEX_CNTL, 0 );
+ adev->fake_texture_number++;
+
+ return true;
+}
+
+
+static bool ati128DrawLine( void *drv, void *dev, DFBRegion *line )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ int dx, dy;
+ int small, large;
+ int x_dir, y_dir, y_major;
+ int err, inc, dec;
+
+ /* Determine x & y deltas and x & y direction bits. */
+ if (line->x1 < line->x2) {
+ dx = line->x2 - line->x1;
+ x_dir = 1 << 31;
+ }
+ else {
+ dx = line->x1 - line->x2;
+ x_dir = 0 << 31;
+ }
+
+ if (line->y1 < line->y2) {
+ dy = line->y2 - line->y1;
+ y_dir = 1 << 15;
+ }
+ else {
+ dy = line->y1 - line->y2;
+ y_dir = 0 << 15;
+ }
+
+ /* Determine x & y min and max values; also determine y major bit. */
+ if (dx < dy) {
+ small = dx;
+ large = dy;
+ y_major = 1 << 2;
+ }
+ else {
+ small = dy;
+ large = dx;
+ y_major = 0 << 2;
+ }
+
+ /* Calculate Bresenham parameters and draw line. */
+ err = -large;
+ inc = small * 2;
+ dec = large *(-2);
+
+ ati128_waitfifo( adrv, adev, 8 );
+ /* set the destination datatype */
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | BRUSH_SOLIDCOLOR | ROP3_SRCCOPY );
+ ati128_out32( mmio, DP_MIX, ROP3_PATCOPY );
+
+ /* set start coorinates */
+ ati128_out32( mmio, DST_Y_X, (S14(line->y1) << 16) | S12(line->x1));
+ /* allow setting of last pel bit and polygon
+ outline bit for line drawing */
+ ati128_out32( mmio, DP_CNTL_XDIR_YDIR_YMAJOR,
+ y_major | y_dir | x_dir );
+ /* set bresenham registers and start drawing */
+ ati128_out32( mmio, DST_BRES_ERR, err );
+ ati128_out32( mmio, DST_BRES_INC, inc );
+ ati128_out32( mmio, DST_BRES_DEC, dec );
+ ati128_out32( mmio, DST_BRES_LNTH, large + 1 );
+
+ return true;
+}
+
+static bool ati128StretchBlit( void *drv, void *dev, DFBRectangle *sr, DFBRectangle *dr )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ u32 src = 0;
+
+ u32 scalex = (u32)(((double)sr->w/(double)dr->w) * 65536);
+ u32 scaley = (u32)(((double)sr->h/(double)dr->h) * 65536);
+
+ ati128_waitfifo( adrv, adev, 9 );
+
+ /* make sure that color compare register is restored to last state */
+
+ ati128_out32( mmio, CLR_CMP_CNTL, adev->ATI_color_compare );
+
+ switch (adev->source->config.format) {
+ case DSPF_RGB332:
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_8BPP_RGB332 );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>3);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x;
+
+ ati128_out32( mmio, TEX_CNTL, 0);
+
+ break;
+ case DSPF_ARGB1555: /* FIXME: alpha channel will be zero ;( */
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_15BPP );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>4);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x*2;
+
+ ati128_out32( mmio, TEX_CNTL, 0);
+
+ break;
+ case DSPF_RGB16:
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_16BPP );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>4);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x*2;
+
+ ati128_out32( mmio, TEX_CNTL, 0);
+
+ break;
+ case DSPF_RGB24:
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_24BPP );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>3);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x*3;
+
+ ati128_out32( mmio, TEX_CNTL, 0);
+
+ break;
+ case DSPF_RGB32:
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>5);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x*4;
+
+ ati128_out32( mmio, TEX_CNTL, 0);
+
+ break;
+ case DSPF_ARGB:
+ ati128_out32( mmio, SCALE_3D_DATATYPE, DST_32BPP );
+
+ ati128_out32( mmio, SCALE_PITCH,
+ adev->src->pitch >>5);
+
+ src = adev->src->offset +
+ sr->y *
+ adev->src->pitch + sr->x*4;
+
+ if (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
+ ati128_out32( mmio, TEX_CNTL, TEX_CNTL_ALPHA_EN_ON );
+ else
+ ati128_out32( mmio, TEX_CNTL, 0 );
+ break;
+ default:
+ D_BUG( "unexpected pixelformat!" );
+ return false;
+ }
+
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
+
+ /* set the blend function */
+ if (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL)
+ ati128_out32( mmio, SCALE_3D_CNTL, adev->ATI_blend_function );
+ else
+ ati128_out32( mmio, SCALE_3D_CNTL, SCALE_3D_CNTL_SCALE_3D_FN_SCALE );
+
+ /* set up source data and copy type */
+ ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
+ /* set source offset */
+ ati128_out32( mmio, SCALE_OFFSET_0, src);
+ /* set height and width of the source */
+ ati128_out32( mmio, SCALE_SRC_HEIGHT_WIDTH, (sr->h << 16) | sr->w);
+
+ ati128_waitfifo( adrv, adev, 9 );
+ /* set the scaling increment registers */
+ ati128_out32( mmio, SCALE_X_INC, scalex );
+ ati128_out32( mmio, SCALE_Y_INC, scaley );
+ /* reset accumulator regs */
+ ati128_out32( mmio, SCALE_HACC, 0x00000000 );
+ ati128_out32( mmio, SCALE_VACC, 0x00000000 );
+ /* set the destination coordinates */
+ ati128_out32( mmio, SCALE_DST_X_Y, (S12(dr->x) << 16) | S14(dr->y) );
+ /* set destination height and width and perform the blit */
+ ati128_out32( mmio, SCALE_DST_HEIGHT_WIDTH, (dr->h << 16) | dr->w );
+ /*reset scaling and texture control register */
+ ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
+ ati128_out32( mmio, TEX_CNTL, 0x00000000 );
+
+ /* set CLR_CMP_CNTL to zero, to insure that drawing funcions work corrently */
+ if (adev->ATI_color_compare)
+ ati128_out32( mmio, CLR_CMP_CNTL, 0 );
+
+ return true;
+}
+
+static bool ati128Blit( void *drv, void *dev, DFBRectangle *rect, int dx, int dy )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) drv;
+ ATI128DeviceData *adev = (ATI128DeviceData*) dev;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ u32 dir_cmd = 0;
+
+ if ((adev->source->config.format != adev->destination->config.format) ||
+ (adev->blittingflags & DSBLIT_BLEND_ALPHACHANNEL))
+ {
+ DFBRectangle sr = { rect->x, rect->y, rect->w, rect->h };
+ DFBRectangle dr = { dx, dy, rect->w, rect->h };
+ ati128StretchBlit( adrv, adev, &sr, &dr );
+ return true;
+ }
+
+ /* check which blitting direction should be used */
+ if (rect->x <= dx) {
+ dir_cmd |= DST_X_RIGHT_TO_LEFT;
+ rect->x += rect->w-1;
+ dx += rect->w-1;
+ }
+ else {
+ dir_cmd |= DST_X_LEFT_TO_RIGHT;
+ }
+ if (rect->y <= dy) {
+ dir_cmd |= DST_Y_BOTTOM_TO_TOP;
+ rect->y += rect->h-1;
+ dy += rect->h-1;
+ }
+ else {
+ dir_cmd |= DST_Y_TOP_TO_BOTTOM;
+ }
+
+ ati128_waitfifo( adrv, adev, 9 );
+
+ /* make sure that color compare register is restored to last state */
+ ati128_out32( mmio, CLR_CMP_CNTL, adev->ATI_color_compare );
+
+ /* set blitting direction */
+ ati128_out32( mmio, DP_CNTL, dir_cmd );
+
+ ati128_out32( mmio, DP_DATATYPE, adev->ATI_dst_bpp | SRC_DSTCOLOR );
+ ati128_out32( mmio, DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT );
+
+ ati128_out32( mmio, SRC_Y_X, (rect->y << 16) | rect->x);
+ ati128_out32( mmio, DST_Y_X, (S14(dy) << 16) | S12(dx) );
+ ati128_out32( mmio, DST_HEIGHT_WIDTH, (rect->h << 16) | rect->w);
+
+ /* set CLR_CMP_CNTL to zero, to insure that drawing funcions work corrently */
+ if (adev->ATI_color_compare)
+ ati128_out32( mmio, CLR_CMP_CNTL, 0 );
+
+ if (dir_cmd != (DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT)) {
+ ati128_out32( mmio, DP_CNTL, DST_X_LEFT_TO_RIGHT |
+ DST_Y_TOP_TO_BOTTOM );
+ }
+
+ return true;
+}
+
+/* exported symbols */
+
+static int
+driver_probe( CoreGraphicsDevice *device )
+{
+ switch (dfb_gfxcard_get_accelerator( device )) {
+ case FB_ACCEL_ATI_RAGE128: /* ATI Rage 128 */
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static void
+driver_get_info( CoreGraphicsDevice *device,
+ GraphicsDriverInfo *info )
+{
+ /* fill driver info structure */
+ snprintf( info->name,
+ DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH,
+ "ATI Rage 128 Driver" );
+
+ snprintf( info->vendor,
+ DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH,
+ "directfb.org" );
+
+ info->version.major = 0;
+ info->version.minor = 2;
+
+ info->driver_data_size = sizeof (ATI128DriverData);
+ info->device_data_size = sizeof (ATI128DeviceData);
+}
+
+static DFBResult
+driver_init_driver( CoreGraphicsDevice *device,
+ GraphicsDeviceFuncs *funcs,
+ void *driver_data,
+ void *device_data,
+ CoreDFB *core )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
+
+ adrv->mmio_base = (volatile u8*) dfb_gfxcard_map_mmio( device, 0, -1 );
+ if (!adrv->mmio_base)
+ return DFB_IO;
+
+ funcs->CheckState = ati128CheckState;
+ funcs->SetState = ati128SetState;
+ funcs->EngineSync = ati128EngineSync;
+
+ funcs->FillRectangle = ati128FillRectangle;
+ funcs->DrawRectangle = ati128DrawRectangle;
+ funcs->DrawLine = ati128DrawLine;
+ funcs->Blit = ati128Blit;
+ funcs->StretchBlit = ati128StretchBlit;
+
+ /* overlay support */
+ dfb_layers_register( dfb_screens_at(DSCID_PRIMARY),
+ driver_data, &atiOverlayFuncs );
+
+ return DFB_OK;
+}
+
+
+static DFBResult
+driver_init_device( CoreGraphicsDevice *device,
+ GraphicsDeviceInfo *device_info,
+ void *driver_data,
+ void *device_data )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
+ ATI128DeviceData *adev = (ATI128DeviceData*) device_data;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ /* fill device info */
+ snprintf( device_info->name,
+ DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "Rage 128" );
+
+ snprintf( device_info->vendor,
+ DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "ATI" );
+
+
+ device_info->caps.flags = CCF_CLIPPING;
+ device_info->caps.accel = ATI128_SUPPORTED_DRAWINGFUNCTIONS |
+ ATI128_SUPPORTED_BLITTINGFUNCTIONS;
+ device_info->caps.drawing = ATI128_SUPPORTED_DRAWINGFLAGS;
+ device_info->caps.blitting = ATI128_SUPPORTED_BLITTINGFLAGS;
+
+ device_info->limits.surface_byteoffset_alignment = 32 * 4;
+ device_info->limits.surface_pixelpitch_alignment = 32;
+
+
+ /* initialize card */
+ ati128_waitfifo( adrv, adev, 6 );
+
+ ati128_out32( mmio, DP_GUI_MASTER_CNTL,
+ GMC_SRC_PITCH_OFFSET_DEFAULT |
+ GMC_DST_PITCH_OFFSET_DEFAULT |
+ GMC_SRC_CLIP_DEFAULT |
+ GMC_DST_CLIP_DEFAULT |
+ GMC_BRUSH_SOLIDCOLOR |
+ GMC_SRC_DSTCOLOR |
+ GMC_BYTE_ORDER_MSB_TO_LSB |
+ GMC_DP_CONVERSION_TEMP_6500 |
+ ROP3_PATCOPY |
+ GMC_DP_SRC_RECT |
+ GMC_3D_FCN_EN_CLR |
+ GMC_DST_CLR_CMP_FCN_CLEAR |
+ GMC_AUX_CLIP_CLEAR |
+ GMC_WRITE_MASK_SET);
+
+ ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
+ ati128_out32( mmio, TEX_CNTL, 0x00000000 );
+
+ /* reserve 32bit pixel for fake texture at end of framebuffer */
+ adev->ATI_fake_texture_src = dfb_gfxcard_reserve_memory( device, 4*32 );
+
+ return DFB_OK;
+}
+
+static void
+driver_close_device( CoreGraphicsDevice *device,
+ void *driver_data,
+ void *device_data )
+{
+ ATI128DeviceData *adev = (ATI128DeviceData*) device_data;
+ ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
+ volatile u8 *mmio = adrv->mmio_base;
+
+ D_DEBUG( "DirectFB/ATI128: FIFO Performance Monitoring:\n" );
+ D_DEBUG( "DirectFB/ATI128: %9d ati128_waitfifo calls\n",
+ adev->waitfifo_calls );
+ D_DEBUG( "DirectFB/ATI128: %9d register writes (ati128_waitfifo sum)\n",
+ adev->waitfifo_sum );
+ D_DEBUG( "DirectFB/ATI128: %9d FIFO wait cycles (depends on CPU)\n",
+ adev->fifo_waitcycles );
+ D_DEBUG( "DirectFB/ATI128: %9d IDLE wait cycles (depends on CPU)\n",
+ adev->idle_waitcycles );
+ D_DEBUG( "DirectFB/ATI128: %9d FIFO space cache hits(depends on CPU)\n",
+ adev->fifo_cache_hits );
+ D_DEBUG( "DirectFB/ATI128: Conclusion:\n" );
+ D_DEBUG( "DirectFB/ATI128: Average register writes/ati128_waitfifo"
+ "call:%.2f\n",
+ adev->waitfifo_sum/(float)(adev->waitfifo_calls) );
+ D_DEBUG( "DirectFB/ATI128: Average wait cycles/ati128_waitfifo call:"
+ " %.2f\n",
+ adev->fifo_waitcycles/(float)(adev->waitfifo_calls) );
+ D_DEBUG( "DirectFB/ATI128: Average fifo space cache hits: %02d%%\n",
+ (int)(100 * adev->fifo_cache_hits/
+ (float)(adev->waitfifo_calls)) );
+
+ /* clean up, make sure that aty128fb does not hang in kernel space
+ afterwards */
+ ati128_waitfifo( adrv, adev, 3 );
+
+ ati128_out32( mmio, DP_GUI_MASTER_CNTL,
+ GMC_SRC_PITCH_OFFSET_DEFAULT |
+ GMC_DST_PITCH_OFFSET_DEFAULT |
+ GMC_SRC_CLIP_DEFAULT |
+ GMC_DST_CLIP_DEFAULT |
+ GMC_BRUSH_SOLIDCOLOR |
+ GMC_SRC_DSTCOLOR |
+ GMC_BYTE_ORDER_MSB_TO_LSB |
+ GMC_DP_CONVERSION_TEMP_6500 |
+ ROP3_PATCOPY |
+ GMC_DP_SRC_RECT |
+ GMC_3D_FCN_EN_CLR |
+ GMC_DST_CLR_CMP_FCN_CLEAR |
+ GMC_AUX_CLIP_CLEAR |
+ GMC_WRITE_MASK_SET);
+
+ ati128_out32( mmio, SCALE_3D_CNTL, 0x00000000 );
+ ati128_out32( mmio, TEX_CNTL, 0x00000000 );
+}
+
+static void
+driver_close_driver( CoreGraphicsDevice *device,
+ void *driver_data )
+{
+ ATI128DriverData *adrv = (ATI128DriverData*) driver_data;
+
+ dfb_gfxcard_unmap_mmio( device, adrv->mmio_base, -1 );
+}