From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/ati128/ati128.c | 842 +++++++++++++++++++++++++++++ 1 file changed, 842 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/ati128/ati128.c (limited to 'Source/DirectFB/gfxdrivers/ati128/ati128.c') 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +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 ); +} -- cgit