1/* 2 * XAA acceleration for CL-GD546x -- The Laugna family 3 * 4 * lg_xaa.c 5 * 6 * (c) 1998 Corin Anderson. 7 * corina@the4cs.com 8 * Tukwila, WA 9 * 10 * Much of this code is inspired by the XAA acceleration from XFree86 11 * 3.3.3, laguna_acl.c 12 */ 13 14#ifdef HAVE_CONFIG_H 15#include "config.h" 16#endif 17 18#include "xf86.h" 19#include "xf86_OSproc.h" 20#include "compiler.h" 21 22#include "xf86Pci.h" 23 24#include "vgaHW.h" 25 26#include "cir.h" 27#define _LG_PRIVATE_ 28#include "lg.h" 29 30#ifdef HAVE_XAA_H 31#include "lg_xaa.h" 32 33/* Laguna raster operations, source is OP1 and destination is OP0. */ 34/* The order in this array is important! */ 35static int lgRop[16] = { 36 /* Lg Op X name */ 37 38 0x00, /* 0 GXclear */ 39 0x88, /* S.D GXand */ 40 0x44, /* S.~D GXandReverse */ 41 0xCC, /* S GXcopy */ 42 0x22, /* ~S.D GXandInverted */ 43 0xAA, /* D GXnoop */ 44 0x66, /* S~=D GXxor */ 45 0xEE, /* S+D GXor */ 46 0x77, /* ~S.~D GXnor */ 47 0x99, /* S=D GXequiv */ 48 0x55, /* ~D GXinvert */ 49 0xDD, /* S+~D GXorReverse */ 50 0x33, /* ~S GXcopyInverted */ 51 0xBB, /* ~S+D GXorInverted */ 52 0x11, /* ~S+~D GXnand */ 53 0xFF /* 1 GXset */ 54}; 55 56#if 0 57/* Laguna raster operations, source is OP2 and destination is OP0. */ 58static int lgPatRop[16] = { 59 /* Lg Op X name */ 60 61 0x00, /* 0 GXclear */ 62 0xA0, /* S.D GXand */ 63 0x50, /* S.~D GXandReverse */ 64 0xF0, /* S GXcopy */ 65 0x0A, /* ~S.D GXandInverted */ 66 0xAA, /* D GXnoop */ 67 0x5A, /* S~=D GXxor */ 68 0xFA, /* S+D GXor */ 69 0x05, /* ~S.~D GXnor */ 70 0xA5, /* S=D GXequiv */ 71 0x55, /* ~D GXinvert */ 72 0xF5, /* S+~D GXorReverse */ 73 0x0F, /* ~S GXcopyInverted */ 74 0xAF, /* ~S+D GXorInverted */ 75 0x5F, /* ~S+~D GXnand */ 76 0xFF /* 1 GXset */ 77}; 78#endif 79 80 81static void LgSetBitmask(CirPtr pCir, const CARD32 m); 82static void LgWaitQAvail(CirPtr pCir, int n); 83static CARD32 LgExpandColor(CARD32 color, int bpp); 84static void LgSync(ScrnInfoPtr pScrn); 85static void LgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 86 unsigned int planemask); 87 88static void LgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 89 int w, int h); 90static void LgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 91 int rop, unsigned int planemask, 92 int transparency_color); 93static void LgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 94 int x2, int y2, int w, int h); 95 96 97/**************************************************** LgXAAInit *****/ 98 99Bool 100LgXAAInit(ScreenPtr pScreen) 101{ 102 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 103 CirPtr pCir = CIRPTR(pScrn); 104 XAAInfoRecPtr XAAPtr; 105 106 XAAPtr = XAACreateInfoRec(); 107 if (!XAAPtr) 108 return FALSE; 109 110 /* 111 * Solid color fills. 112 */ 113 XAAPtr->SetupForSolidFill = LgSetupForSolidFill; 114 XAAPtr->SubsequentSolidFillRect = LgSubsequentSolidFillRect; 115 XAAPtr->SubsequentSolidFillTrap = NULL; 116 XAAPtr->SolidFillFlags = 0; 117 118 /* 119 * Screen-to-screen copies. 120 */ 121 XAAPtr->SetupForScreenToScreenCopy = LgSetupForScreenToScreenCopy; 122 XAAPtr->SubsequentScreenToScreenCopy = LgSubsequentScreenToScreenCopy; 123 /* Maybe ONLY_LEFT_TO_RIGHT_BITBLT or ONLY_TWO_BITBLT_DIRECTIONS? */ 124 XAAPtr->ScreenToScreenCopyFlags = ONLY_LEFT_TO_RIGHT_BITBLT; 125 126 /* 127 * Miscellany. 128 */ 129 XAAPtr->Sync = LgSync; 130 131 pCir->AccelInfoRec = XAAPtr; 132 133 if (!XAAInit(pScreen, XAAPtr)) 134 return FALSE; 135 136 return TRUE; 137} 138 139/******************************************** Lg XAA helper functions ***/ 140 141/* 142 * The bitmask is usually all 1's, so it's silly to spend a DWORD write 143 * to program the register with the same value each time. Bitmask is 144 * about the only register whose value is worth shadowing, so we special- 145 * case it. 146 */ 147static void 148LgSetBitmask(CirPtr pCir, const CARD32 m) 149{ 150 const LgPtr pLg = LGPTR(pCir); 151 152 if (m != pLg->oldBitmask) { 153 LgSETBITMASK(m); 154 pLg->oldBitmask = m; 155 } 156} 157 158/* 159 * Return from the function only when there's room somewhere for the 160 * upcoming register writes. That means that either PCI retry is enabled 161 * (i.e., we let the PCI bus buffer the register writes), or we wait for 162 * room in the Laguna's command queue explicitly. 163 */ 164static void 165LgWaitQAvail(CirPtr pCir, int n) 166{ 167 if (!0/*lgUsePCIRetry*/) { 168 CARD8 qfree; 169 170 /* Wait until n entries are open in the command queue */ 171 do 172 qfree = *(volatile CARD8 *)(pCir->IOBase + QFREE); 173 while (qfree < n); 174 } 175} 176 177 178/* We might want to make this a macro at some point. */ 179static CARD32 180LgExpandColor(CARD32 color, int bpp) 181{ 182 if (8 == bpp) 183 color = ((color&0xFF) << 8) | (color&0xFF); 184 185 if (8 == bpp || 16 == bpp) 186 color = ((color&0xFFFF) << 16) | (color&0xFFFF); 187 188 return color; 189} 190 191 192/*************************************************** Lg XAA functions ***/ 193 194 195static void 196LgSync(ScrnInfoPtr pScrn) 197{ 198 const CirPtr pCir = CIRPTR(pScrn); 199#if 0 200 LgPtr pLg = LGPTR(pScrn); 201#endif 202 203 while (!LgREADY()) 204 ; 205} 206 207static void 208LgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 209 unsigned int planemask) 210{ 211 212 const CirPtr pCir = CIRPTR(pScrn); 213 214 color = LgExpandColor(color, pScrn->bitsPerPixel); 215 216 LgWaitQAvail(pCir, 4); 217 218 LgSETBACKGROUND(color); 219 LgSETROP(lgRop[rop]); 220 LgSETMODE(SCR2SCR | COLORFILL); 221 LgSetBitmask(pCir, planemask); 222} 223 224static void 225LgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 226{ 227 const CirPtr pCir = CIRPTR(pScrn); 228 229 /* Wait for room in the command queue. */ 230 LgWaitQAvail(pCir, 2); 231 232 LgSETDSTXY(x, y); 233 LgSETEXTENTS(w, h); 234} 235 236static void 237LgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 238 int rop, unsigned int planemask, int transparency_color) 239{ 240 int bltmode = 0; 241 const CirPtr pCir = CIRPTR(pScrn); 242 const LgPtr pLg = LGPTR(pCir); 243 244 pLg->blitTransparent = (transparency_color != -1); 245 pLg->blitYDir = ydir; 246 247 LgWaitQAvail(pCir, 4); 248 249 /* We set the rop up here because the LgSETROP macro conveniently 250 (really -- it is convenient!) clears the transparency bits 251 in DRAWDEF. We'll set those bits appropriately later. */ 252 LgSETROP(lgRop[rop]); 253 254 if (ydir < 0) 255 bltmode |= BLITUP; 256 if (pLg->blitTransparent) { 257 /* Gotta extend the transparency_color to the full 32-bit 258 size of the register. */ 259 transparency_color = LgExpandColor(transparency_color, 260 pScrn->bitsPerPixel); 261 262 bltmode |= COLORTRANS; 263 LgSETBACKGROUND(transparency_color); 264 LgSETTRANSPARENCY(TRANSEQ); 265 } else { 266 LgSETTRANSPARENCY(TRANSNONE); 267 } 268 269 LgSETMODE(SCR2SCR | COLORSRC | bltmode); 270 LgSetBitmask(pCir, planemask); 271} 272 273static void 274LgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 275 int x2, int y2, int w, int h) 276{ 277 const CirPtr pCir = CIRPTR(pScrn); 278 const LgPtr pLg = LGPTR(pCir); 279 280 /* 281 * We have set the flag indicating that xdir must be one, 282 * so we can assume that here. 283 */ 284 if (pLg->blitYDir == -1) { 285 y1 += h - 1; 286 y2 += h - 1; 287 } 288 289 if (pLg->blitTransparent) { 290 /* We're doing a transparent blit. We'll need to point 291 OP2 to the color compare mask. */ 292 LgWaitQAvail(pCir, 4); 293 LgSETTRANSMASK(x1, y1); 294 } else { 295 LgWaitQAvail(pCir, 3); 296 } 297 LgSETSRCXY(x1, y1); 298 LgSETDSTXY(x2, y2); 299 LgSETEXTENTS(w, h); 300} 301#endif 302