neo_2090.c revision 692f60a7
1/********************************************************************** 2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, distribute, and sell this software and 7its documentation for any purpose is hereby granted without fee, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Precision Insight not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. Precision Insight 13and its suppliers make no representations about the suitability of this 14software for any purpose. It is provided "as is" without express or 15implied warranty. 16 17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24**********************************************************************/ 25/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c,v 1.6 2002/04/04 14:05:44 eich Exp $ */ 26 27/* 28 * The original Precision Insight driver for 29 * XFree86 v.3.3 has been sponsored by Red Hat. 30 * 31 * Authors: 32 * Jens Owen (jens@tungstengraphics.com) 33 * Kevin E. Martin (kevin@precisioninsight.com) 34 * 35 * Port to Xfree86 v.4.0 36 * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 37 */ 38 39#ifdef HAVE_CONFIG_H 40#include "config.h" 41#endif 42 43#include "xf86.h" 44#include "xf86_OSproc.h" 45#include "compiler.h" 46#include "xf86PciInfo.h" 47 48/* Drivers that use XAA need this */ 49#include "xf86fbman.h" 50 51#include "miline.h" 52 53#include "neo.h" 54#include "neo_reg.h" 55#include "neo_macros.h" 56 57static unsigned int neo2090Rop[16] = { 58 0x000000, /* 0x0000 - GXclear */ 59 0x080000, /* 0x1000 - GXand */ 60 0x040000, /* 0x0100 - GXandReverse */ 61 0x0c0000, /* 0x1100 - GXcopy */ 62 0x020000, /* 0x0010 - GXandInvert */ 63 0x0a0000, /* 0x1010 - GXnoop */ 64 0x060000, /* 0x0110 - GXxor */ 65 0x0e0000, /* 0x1110 - GXor */ 66 0x010000, /* 0x0001 - GXnor */ 67 0x090000, /* 0x1001 - GXequiv */ 68 0x050000, /* 0x0101 - GXinvert */ 69 0x0d0000, /* 0x1101 - GXorReverse */ 70 0x030000, /* 0x0011 - GXcopyInvert */ 71 0x0b0000, /* 0x1011 - GXorInverted */ 72 0x070000, /* 0x0111 - GXnand */ 73 0x0f0000 /* 0x1111 - GXset */ 74}; 75 76static void Neo2090Sync(ScrnInfoPtr pScrn); 77static void Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 78 int ydir, int rop, 79 unsigned int planemask, 80 int trans_color); 81static void Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, 82 int srcY, int dstX, int dstY, 83 int w, int h); 84static void Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 85 unsigned int planemask); 86static void Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 87 int w, int h); 88static void Neo2093SetupForScanlineCPUToScreenColorExpandFill( 89 ScrnInfoPtr pScrn, 90 int fg, int bg, 91 int rop, 92 unsigned int planemask); 93static void Neo2093SubsequentScanlineCPUToScreenColorExpandFill( 94 ScrnInfoPtr pScrn, 95 int x, int y, 96 int w, int h, 97 int skipleft); 98static void Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); 99 100Bool 101Neo2090AccelInit(ScreenPtr pScreen) 102{ 103 XAAInfoRecPtr infoPtr; 104 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 105 NEOPtr nPtr = NEOPTR(pScrn); 106 NEOACLPtr nAcl = NEOACLPTR(pScrn); 107 108 nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec(); 109 if(!infoPtr) return FALSE; 110 111 /* 112 * Set up the main acceleration flags. 113 */ 114 infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; 115 if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE; 116#if 0 117 infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; 118#endif 119 /* sync */ 120 infoPtr->Sync = Neo2090Sync; 121 122 /* screen to screen copy */ 123 infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK); 124 infoPtr->SetupForScreenToScreenCopy = 125 Neo2090SetupForScreenToScreenCopy; 126 infoPtr->SubsequentScreenToScreenCopy = 127 Neo2090SubsequentScreenToScreenCopy; 128 129 /* solid filled rectangles */ 130 infoPtr->SolidFillFlags = NO_PLANEMASK; 131 infoPtr->SetupForSolidFill = 132 Neo2090SetupForSolidFillRect; 133 infoPtr->SubsequentSolidFillRect = 134 Neo2090SubsequentSolidFillRect; 135 136 if (nPtr->NeoChipset == PCI_CHIP_NM2093 && !nPtr->strangeLockups) { 137 /* 138 * We do CPUToScreenColorExpand (ab)using the Scanline functions: 139 * the neo chipsets need byte padding however we can only do dword 140 * padding. Fortunately the graphics engine doesn't choke if we 141 * transfer up to 3 bytes more than it wants. 142 */ 143 144 /* cpu to screen color expansion */ 145 infoPtr->ScanlineColorExpandBuffers = 146 (unsigned char **)xnfalloc(sizeof(char*)); 147 infoPtr->ScanlineColorExpandBuffers[0] = 148 (unsigned char *)(nPtr->NeoMMIOBase + 0x100000); 149 infoPtr->NumScanlineColorExpandBuffers = 1; 150 infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK | 151 SCANLINE_PAD_DWORD | 152 CPU_TRANSFER_PAD_DWORD | 153 BIT_ORDER_IN_BYTE_MSBFIRST ); 154 155 infoPtr->SetupForScanlineCPUToScreenColorExpandFill = 156 Neo2093SetupForScanlineCPUToScreenColorExpandFill; 157 infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = 158 Neo2093SubsequentScanlineCPUToScreenColorExpandFill; 159 infoPtr->SubsequentColorExpandScanline = 160 Neo2093SubsequentColorExpandScanline; 161 } 162 163 /* 164 * Setup some global variables 165 */ 166 nAcl->ColorShiftAmt = 0; 167 168 /* Initialize for 8bpp or 15/16bpp support accellerated */ 169 switch (pScrn->bitsPerPixel) { 170 case 8: 171 nAcl->BltCntlFlags = NEO_BC1_DEPTH8; 172 nAcl->ColorShiftAmt = 8; 173 break; 174 case 15: 175 case 16: 176 nAcl->BltCntlFlags = NEO_BC1_DEPTH16; 177 nAcl->ColorShiftAmt = 0; 178 break; 179 case 24: 180 default: 181 return FALSE; 182 } 183 184 /* Initialize for widths */ 185 switch (pScrn->displayWidth) { 186 case 640: 187 nAcl->BltCntlFlags |= NEO_BC1_X_640; 188 break; 189 case 800: 190 nAcl->BltCntlFlags |= NEO_BC1_X_800; 191 break; 192 case 1024: 193 nAcl->BltCntlFlags |= NEO_BC1_X_1024; 194 break; 195 default: 196 return FALSE; 197 } 198 199 nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN; 200 201 return(XAAInit(pScreen, infoPtr)); 202} 203 204static void 205Neo2090Sync(ScrnInfoPtr pScrn) 206{ 207 NEOPtr nPtr = NEOPTR(pScrn); 208 209 WAIT_ENGINE_IDLE(); 210} 211 212static void 213Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 214 int rop, 215 unsigned int planemask, 216 int trans_color) 217{ 218 NEOPtr nPtr = NEOPTR(pScrn); 219 NEOACLPtr nAcl = NEOACLPTR(pScrn); 220 221 nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags | 222 NEO_BC3_SKIP_MAPPING | 223 NEO_BC3_DST_XY_ADDR | 224 NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]); 225 226 /* set blt control */ 227 WAIT_FIFO(2); 228 OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 229} 230 231static void 232Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, 233 int srcX, int srcY, 234 int dstX, int dstY, 235 int w, int h) 236{ 237 NEOPtr nPtr = NEOPTR(pScrn); 238 NEOACLPtr nAcl = NEOACLPTR(pScrn); 239 240 if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) { 241 /* start with upper left corner */ 242 WAIT_FIFO(4); 243 OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 244 OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff)); 245 OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff)); 246 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 247 } 248 else { 249 /* start with lower right corner */ 250 WAIT_FIFO(4); 251 OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC 252 | NEO_BC0_DST_Y_DEC 253 | NEO_BC0_SRC_Y_DEC)); 254 OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff)); 255 OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff)); 256 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 257 } 258} 259 260 261static void 262Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 263 unsigned int planemask) 264{ 265 NEOPtr nPtr = NEOPTR(pScrn); 266 NEOACLPtr nAcl = NEOACLPTR(pScrn); 267 268 WAIT_FIFO(2); 269 270 /* set blt control */ 271 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 272 NEO_BC0_SRC_IS_FG | 273 NEO_BC3_SKIP_MAPPING | 274 NEO_BC3_DST_XY_ADDR | 275 NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]); 276 277 /* set foreground color */ 278 OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt)); 279} 280 281 282static void 283Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 284{ 285 NEOPtr nPtr = NEOPTR(pScrn); 286 287 WAIT_FIFO(2); 288 OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 289 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 290 291} 292 293static void 294Neo2093SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 295 int fg, int bg, 296 int rop, 297 unsigned int planemask) 298{ 299 NEOPtr nPtr = NEOPTR(pScrn); 300 NEOACLPtr nAcl = NEOACLPTR(pScrn); 301 302 if (bg == -1) { 303 /* transparent setup */ 304 WAIT_FIFO(2); 305 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 306 NEO_BC0_SYS_TO_VID | 307 NEO_BC0_SRC_MONO | 308 NEO_BC0_SRC_TRANS | 309 NEO_BC3_SKIP_MAPPING | 310 NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]); 311 312 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 313 } 314 else { 315 /* opaque setup */ 316 WAIT_FIFO(3); 317 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 318 NEO_BC0_SYS_TO_VID | 319 NEO_BC0_SRC_MONO | 320 NEO_BC3_SKIP_MAPPING | 321 NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]); 322 323 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 324 OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt)); 325 } 326} 327 328static void 329Neo2093SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 330 int x, int y, 331 int w, int h, 332 int skipleft) 333{ 334 NEOPtr nPtr = NEOPTR(pScrn); 335 NEOACLPtr nAcl = NEOACLPTR(pScrn); 336 337 nAcl->CPUToScreenColorExpandFill_x = x; 338 nAcl->CPUToScreenColorExpandFill_y = y; 339 nAcl->CPUToScreenColorExpandFill_w = w; 340 nAcl->CPUToScreenColorExpandFill_h = h; 341 nAcl->CPUToScreenColorExpandFill_skipleft = skipleft; 342 343 WAIT_FIFO(4); 344 OUTREG(NEOREG_SRCBITOFF, skipleft); 345 OUTREG(NEOREG_SRCSTARTOFF, 0); 346 OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 347 OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff)); 348} 349 350static void 351Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) 352{ 353 NEOPtr nPtr = NEOPTR(pScrn); 354 NEOACLPtr nAcl = NEOACLPTR(pScrn); 355 356 if (!(--nAcl->CPUToScreenColorExpandFill_h)) 357 return; 358 359 WAIT_FIFO(4); 360 OUTREG(NEOREG_SRCBITOFF, nAcl->CPUToScreenColorExpandFill_skipleft); 361 OUTREG(NEOREG_SRCSTARTOFF, 0); 362 OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16) 363 | (nAcl->CPUToScreenColorExpandFill_x & 0xffff)); 364 OUTREG(NEOREG_XYEXT, (1<<16) 365 | (nAcl->CPUToScreenColorExpandFill_w & 0xffff)); 366} 367 368 369 370