neo_2090.c revision 692f60a7
1692f60a7Smrg/********************************************************************** 2692f60a7SmrgCopyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3692f60a7Smrg 4692f60a7Smrg All Rights Reserved 5692f60a7Smrg 6692f60a7SmrgPermission to use, copy, modify, distribute, and sell this software and 7692f60a7Smrgits documentation for any purpose is hereby granted without fee, 8692f60a7Smrgprovided that the above copyright notice appear in all copies and that 9692f60a7Smrgboth that copyright notice and this permission notice appear in 10692f60a7Smrgsupporting documentation, and that the name of Precision Insight not be 11692f60a7Smrgused in advertising or publicity pertaining to distribution of the 12692f60a7Smrgsoftware without specific, written prior permission. Precision Insight 13692f60a7Smrgand its suppliers make no representations about the suitability of this 14692f60a7Smrgsoftware for any purpose. It is provided "as is" without express or 15692f60a7Smrgimplied warranty. 16692f60a7Smrg 17692f60a7SmrgPRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18692f60a7SmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19692f60a7SmrgEVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20692f60a7SmrgSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21692f60a7SmrgRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22692f60a7SmrgCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23692f60a7SmrgCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24692f60a7Smrg**********************************************************************/ 25692f60a7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c,v 1.6 2002/04/04 14:05:44 eich Exp $ */ 26692f60a7Smrg 27692f60a7Smrg/* 28692f60a7Smrg * The original Precision Insight driver for 29692f60a7Smrg * XFree86 v.3.3 has been sponsored by Red Hat. 30692f60a7Smrg * 31692f60a7Smrg * Authors: 32692f60a7Smrg * Jens Owen (jens@tungstengraphics.com) 33692f60a7Smrg * Kevin E. Martin (kevin@precisioninsight.com) 34692f60a7Smrg * 35692f60a7Smrg * Port to Xfree86 v.4.0 36692f60a7Smrg * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 37692f60a7Smrg */ 38692f60a7Smrg 39692f60a7Smrg#ifdef HAVE_CONFIG_H 40692f60a7Smrg#include "config.h" 41692f60a7Smrg#endif 42692f60a7Smrg 43692f60a7Smrg#include "xf86.h" 44692f60a7Smrg#include "xf86_OSproc.h" 45692f60a7Smrg#include "compiler.h" 46692f60a7Smrg#include "xf86PciInfo.h" 47692f60a7Smrg 48692f60a7Smrg/* Drivers that use XAA need this */ 49692f60a7Smrg#include "xf86fbman.h" 50692f60a7Smrg 51692f60a7Smrg#include "miline.h" 52692f60a7Smrg 53692f60a7Smrg#include "neo.h" 54692f60a7Smrg#include "neo_reg.h" 55692f60a7Smrg#include "neo_macros.h" 56692f60a7Smrg 57692f60a7Smrgstatic unsigned int neo2090Rop[16] = { 58692f60a7Smrg 0x000000, /* 0x0000 - GXclear */ 59692f60a7Smrg 0x080000, /* 0x1000 - GXand */ 60692f60a7Smrg 0x040000, /* 0x0100 - GXandReverse */ 61692f60a7Smrg 0x0c0000, /* 0x1100 - GXcopy */ 62692f60a7Smrg 0x020000, /* 0x0010 - GXandInvert */ 63692f60a7Smrg 0x0a0000, /* 0x1010 - GXnoop */ 64692f60a7Smrg 0x060000, /* 0x0110 - GXxor */ 65692f60a7Smrg 0x0e0000, /* 0x1110 - GXor */ 66692f60a7Smrg 0x010000, /* 0x0001 - GXnor */ 67692f60a7Smrg 0x090000, /* 0x1001 - GXequiv */ 68692f60a7Smrg 0x050000, /* 0x0101 - GXinvert */ 69692f60a7Smrg 0x0d0000, /* 0x1101 - GXorReverse */ 70692f60a7Smrg 0x030000, /* 0x0011 - GXcopyInvert */ 71692f60a7Smrg 0x0b0000, /* 0x1011 - GXorInverted */ 72692f60a7Smrg 0x070000, /* 0x0111 - GXnand */ 73692f60a7Smrg 0x0f0000 /* 0x1111 - GXset */ 74692f60a7Smrg}; 75692f60a7Smrg 76692f60a7Smrgstatic void Neo2090Sync(ScrnInfoPtr pScrn); 77692f60a7Smrgstatic void Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 78692f60a7Smrg int ydir, int rop, 79692f60a7Smrg unsigned int planemask, 80692f60a7Smrg int trans_color); 81692f60a7Smrgstatic void Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, 82692f60a7Smrg int srcY, int dstX, int dstY, 83692f60a7Smrg int w, int h); 84692f60a7Smrgstatic void Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 85692f60a7Smrg unsigned int planemask); 86692f60a7Smrgstatic void Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 87692f60a7Smrg int w, int h); 88692f60a7Smrgstatic void Neo2093SetupForScanlineCPUToScreenColorExpandFill( 89692f60a7Smrg ScrnInfoPtr pScrn, 90692f60a7Smrg int fg, int bg, 91692f60a7Smrg int rop, 92692f60a7Smrg unsigned int planemask); 93692f60a7Smrgstatic void Neo2093SubsequentScanlineCPUToScreenColorExpandFill( 94692f60a7Smrg ScrnInfoPtr pScrn, 95692f60a7Smrg int x, int y, 96692f60a7Smrg int w, int h, 97692f60a7Smrg int skipleft); 98692f60a7Smrgstatic void Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); 99692f60a7Smrg 100692f60a7SmrgBool 101692f60a7SmrgNeo2090AccelInit(ScreenPtr pScreen) 102692f60a7Smrg{ 103692f60a7Smrg XAAInfoRecPtr infoPtr; 104692f60a7Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 105692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 106692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 107692f60a7Smrg 108692f60a7Smrg nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec(); 109692f60a7Smrg if(!infoPtr) return FALSE; 110692f60a7Smrg 111692f60a7Smrg /* 112692f60a7Smrg * Set up the main acceleration flags. 113692f60a7Smrg */ 114692f60a7Smrg infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; 115692f60a7Smrg if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE; 116692f60a7Smrg#if 0 117692f60a7Smrg infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; 118692f60a7Smrg#endif 119692f60a7Smrg /* sync */ 120692f60a7Smrg infoPtr->Sync = Neo2090Sync; 121692f60a7Smrg 122692f60a7Smrg /* screen to screen copy */ 123692f60a7Smrg infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK); 124692f60a7Smrg infoPtr->SetupForScreenToScreenCopy = 125692f60a7Smrg Neo2090SetupForScreenToScreenCopy; 126692f60a7Smrg infoPtr->SubsequentScreenToScreenCopy = 127692f60a7Smrg Neo2090SubsequentScreenToScreenCopy; 128692f60a7Smrg 129692f60a7Smrg /* solid filled rectangles */ 130692f60a7Smrg infoPtr->SolidFillFlags = NO_PLANEMASK; 131692f60a7Smrg infoPtr->SetupForSolidFill = 132692f60a7Smrg Neo2090SetupForSolidFillRect; 133692f60a7Smrg infoPtr->SubsequentSolidFillRect = 134692f60a7Smrg Neo2090SubsequentSolidFillRect; 135692f60a7Smrg 136692f60a7Smrg if (nPtr->NeoChipset == PCI_CHIP_NM2093 && !nPtr->strangeLockups) { 137692f60a7Smrg /* 138692f60a7Smrg * We do CPUToScreenColorExpand (ab)using the Scanline functions: 139692f60a7Smrg * the neo chipsets need byte padding however we can only do dword 140692f60a7Smrg * padding. Fortunately the graphics engine doesn't choke if we 141692f60a7Smrg * transfer up to 3 bytes more than it wants. 142692f60a7Smrg */ 143692f60a7Smrg 144692f60a7Smrg /* cpu to screen color expansion */ 145692f60a7Smrg infoPtr->ScanlineColorExpandBuffers = 146692f60a7Smrg (unsigned char **)xnfalloc(sizeof(char*)); 147692f60a7Smrg infoPtr->ScanlineColorExpandBuffers[0] = 148692f60a7Smrg (unsigned char *)(nPtr->NeoMMIOBase + 0x100000); 149692f60a7Smrg infoPtr->NumScanlineColorExpandBuffers = 1; 150692f60a7Smrg infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK | 151692f60a7Smrg SCANLINE_PAD_DWORD | 152692f60a7Smrg CPU_TRANSFER_PAD_DWORD | 153692f60a7Smrg BIT_ORDER_IN_BYTE_MSBFIRST ); 154692f60a7Smrg 155692f60a7Smrg infoPtr->SetupForScanlineCPUToScreenColorExpandFill = 156692f60a7Smrg Neo2093SetupForScanlineCPUToScreenColorExpandFill; 157692f60a7Smrg infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = 158692f60a7Smrg Neo2093SubsequentScanlineCPUToScreenColorExpandFill; 159692f60a7Smrg infoPtr->SubsequentColorExpandScanline = 160692f60a7Smrg Neo2093SubsequentColorExpandScanline; 161692f60a7Smrg } 162692f60a7Smrg 163692f60a7Smrg /* 164692f60a7Smrg * Setup some global variables 165692f60a7Smrg */ 166692f60a7Smrg nAcl->ColorShiftAmt = 0; 167692f60a7Smrg 168692f60a7Smrg /* Initialize for 8bpp or 15/16bpp support accellerated */ 169692f60a7Smrg switch (pScrn->bitsPerPixel) { 170692f60a7Smrg case 8: 171692f60a7Smrg nAcl->BltCntlFlags = NEO_BC1_DEPTH8; 172692f60a7Smrg nAcl->ColorShiftAmt = 8; 173692f60a7Smrg break; 174692f60a7Smrg case 15: 175692f60a7Smrg case 16: 176692f60a7Smrg nAcl->BltCntlFlags = NEO_BC1_DEPTH16; 177692f60a7Smrg nAcl->ColorShiftAmt = 0; 178692f60a7Smrg break; 179692f60a7Smrg case 24: 180692f60a7Smrg default: 181692f60a7Smrg return FALSE; 182692f60a7Smrg } 183692f60a7Smrg 184692f60a7Smrg /* Initialize for widths */ 185692f60a7Smrg switch (pScrn->displayWidth) { 186692f60a7Smrg case 640: 187692f60a7Smrg nAcl->BltCntlFlags |= NEO_BC1_X_640; 188692f60a7Smrg break; 189692f60a7Smrg case 800: 190692f60a7Smrg nAcl->BltCntlFlags |= NEO_BC1_X_800; 191692f60a7Smrg break; 192692f60a7Smrg case 1024: 193692f60a7Smrg nAcl->BltCntlFlags |= NEO_BC1_X_1024; 194692f60a7Smrg break; 195692f60a7Smrg default: 196692f60a7Smrg return FALSE; 197692f60a7Smrg } 198692f60a7Smrg 199692f60a7Smrg nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN; 200692f60a7Smrg 201692f60a7Smrg return(XAAInit(pScreen, infoPtr)); 202692f60a7Smrg} 203692f60a7Smrg 204692f60a7Smrgstatic void 205692f60a7SmrgNeo2090Sync(ScrnInfoPtr pScrn) 206692f60a7Smrg{ 207692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 208692f60a7Smrg 209692f60a7Smrg WAIT_ENGINE_IDLE(); 210692f60a7Smrg} 211692f60a7Smrg 212692f60a7Smrgstatic void 213692f60a7SmrgNeo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 214692f60a7Smrg int rop, 215692f60a7Smrg unsigned int planemask, 216692f60a7Smrg int trans_color) 217692f60a7Smrg{ 218692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 219692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 220692f60a7Smrg 221692f60a7Smrg nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags | 222692f60a7Smrg NEO_BC3_SKIP_MAPPING | 223692f60a7Smrg NEO_BC3_DST_XY_ADDR | 224692f60a7Smrg NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]); 225692f60a7Smrg 226692f60a7Smrg /* set blt control */ 227692f60a7Smrg WAIT_FIFO(2); 228692f60a7Smrg OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 229692f60a7Smrg} 230692f60a7Smrg 231692f60a7Smrgstatic void 232692f60a7SmrgNeo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, 233692f60a7Smrg int srcX, int srcY, 234692f60a7Smrg int dstX, int dstY, 235692f60a7Smrg int w, int h) 236692f60a7Smrg{ 237692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 238692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 239692f60a7Smrg 240692f60a7Smrg if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) { 241692f60a7Smrg /* start with upper left corner */ 242692f60a7Smrg WAIT_FIFO(4); 243692f60a7Smrg OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 244692f60a7Smrg OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff)); 245692f60a7Smrg OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff)); 246692f60a7Smrg OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 247692f60a7Smrg } 248692f60a7Smrg else { 249692f60a7Smrg /* start with lower right corner */ 250692f60a7Smrg WAIT_FIFO(4); 251692f60a7Smrg OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC 252692f60a7Smrg | NEO_BC0_DST_Y_DEC 253692f60a7Smrg | NEO_BC0_SRC_Y_DEC)); 254692f60a7Smrg OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff)); 255692f60a7Smrg OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff)); 256692f60a7Smrg OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 257692f60a7Smrg } 258692f60a7Smrg} 259692f60a7Smrg 260692f60a7Smrg 261692f60a7Smrgstatic void 262692f60a7SmrgNeo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 263692f60a7Smrg unsigned int planemask) 264692f60a7Smrg{ 265692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 266692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 267692f60a7Smrg 268692f60a7Smrg WAIT_FIFO(2); 269692f60a7Smrg 270692f60a7Smrg /* set blt control */ 271692f60a7Smrg OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 272692f60a7Smrg NEO_BC0_SRC_IS_FG | 273692f60a7Smrg NEO_BC3_SKIP_MAPPING | 274692f60a7Smrg NEO_BC3_DST_XY_ADDR | 275692f60a7Smrg NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]); 276692f60a7Smrg 277692f60a7Smrg /* set foreground color */ 278692f60a7Smrg OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt)); 279692f60a7Smrg} 280692f60a7Smrg 281692f60a7Smrg 282692f60a7Smrgstatic void 283692f60a7SmrgNeo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 284692f60a7Smrg{ 285692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 286692f60a7Smrg 287692f60a7Smrg WAIT_FIFO(2); 288692f60a7Smrg OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 289692f60a7Smrg OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 290692f60a7Smrg 291692f60a7Smrg} 292692f60a7Smrg 293692f60a7Smrgstatic void 294692f60a7SmrgNeo2093SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 295692f60a7Smrg int fg, int bg, 296692f60a7Smrg int rop, 297692f60a7Smrg unsigned int planemask) 298692f60a7Smrg{ 299692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 300692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 301692f60a7Smrg 302692f60a7Smrg if (bg == -1) { 303692f60a7Smrg /* transparent setup */ 304692f60a7Smrg WAIT_FIFO(2); 305692f60a7Smrg OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 306692f60a7Smrg NEO_BC0_SYS_TO_VID | 307692f60a7Smrg NEO_BC0_SRC_MONO | 308692f60a7Smrg NEO_BC0_SRC_TRANS | 309692f60a7Smrg NEO_BC3_SKIP_MAPPING | 310692f60a7Smrg NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]); 311692f60a7Smrg 312692f60a7Smrg OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 313692f60a7Smrg } 314692f60a7Smrg else { 315692f60a7Smrg /* opaque setup */ 316692f60a7Smrg WAIT_FIFO(3); 317692f60a7Smrg OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 318692f60a7Smrg NEO_BC0_SYS_TO_VID | 319692f60a7Smrg NEO_BC0_SRC_MONO | 320692f60a7Smrg NEO_BC3_SKIP_MAPPING | 321692f60a7Smrg NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]); 322692f60a7Smrg 323692f60a7Smrg OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 324692f60a7Smrg OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt)); 325692f60a7Smrg } 326692f60a7Smrg} 327692f60a7Smrg 328692f60a7Smrgstatic void 329692f60a7SmrgNeo2093SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 330692f60a7Smrg int x, int y, 331692f60a7Smrg int w, int h, 332692f60a7Smrg int skipleft) 333692f60a7Smrg{ 334692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 335692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 336692f60a7Smrg 337692f60a7Smrg nAcl->CPUToScreenColorExpandFill_x = x; 338692f60a7Smrg nAcl->CPUToScreenColorExpandFill_y = y; 339692f60a7Smrg nAcl->CPUToScreenColorExpandFill_w = w; 340692f60a7Smrg nAcl->CPUToScreenColorExpandFill_h = h; 341692f60a7Smrg nAcl->CPUToScreenColorExpandFill_skipleft = skipleft; 342692f60a7Smrg 343692f60a7Smrg WAIT_FIFO(4); 344692f60a7Smrg OUTREG(NEOREG_SRCBITOFF, skipleft); 345692f60a7Smrg OUTREG(NEOREG_SRCSTARTOFF, 0); 346692f60a7Smrg OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 347692f60a7Smrg OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff)); 348692f60a7Smrg} 349692f60a7Smrg 350692f60a7Smrgstatic void 351692f60a7SmrgNeo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) 352692f60a7Smrg{ 353692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 354692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 355692f60a7Smrg 356692f60a7Smrg if (!(--nAcl->CPUToScreenColorExpandFill_h)) 357692f60a7Smrg return; 358692f60a7Smrg 359692f60a7Smrg WAIT_FIFO(4); 360692f60a7Smrg OUTREG(NEOREG_SRCBITOFF, nAcl->CPUToScreenColorExpandFill_skipleft); 361692f60a7Smrg OUTREG(NEOREG_SRCSTARTOFF, 0); 362692f60a7Smrg OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16) 363692f60a7Smrg | (nAcl->CPUToScreenColorExpandFill_x & 0xffff)); 364692f60a7Smrg OUTREG(NEOREG_XYEXT, (1<<16) 365692f60a7Smrg | (nAcl->CPUToScreenColorExpandFill_w & 0xffff)); 366692f60a7Smrg} 367692f60a7Smrg 368692f60a7Smrg 369692f60a7Smrg 370