176888252Smrg/* 276888252Smrg * XAA acceleration for CL-GD546x -- The Laugna family 376888252Smrg * 476888252Smrg * lg_xaa.c 576888252Smrg * 676888252Smrg * (c) 1998 Corin Anderson. 776888252Smrg * corina@the4cs.com 876888252Smrg * Tukwila, WA 976888252Smrg * 1076888252Smrg * Much of this code is inspired by the XAA acceleration from XFree86 1176888252Smrg * 3.3.3, laguna_acl.c 1276888252Smrg */ 1376888252Smrg 1476888252Smrg#ifdef HAVE_CONFIG_H 1576888252Smrg#include "config.h" 1676888252Smrg#endif 1776888252Smrg 1876888252Smrg#include "xf86.h" 1976888252Smrg#include "xf86_OSproc.h" 2076888252Smrg#include "compiler.h" 2176888252Smrg 2276888252Smrg#include "xf86Pci.h" 2376888252Smrg 2476888252Smrg#include "vgaHW.h" 2576888252Smrg 2676888252Smrg#include "cir.h" 2776888252Smrg#define _LG_PRIVATE_ 2876888252Smrg#include "lg.h" 2963847c39Smrg 3063847c39Smrg#ifdef HAVE_XAA_H 3176888252Smrg#include "lg_xaa.h" 3276888252Smrg 3376888252Smrg/* Laguna raster operations, source is OP1 and destination is OP0. */ 3476888252Smrg/* The order in this array is important! */ 3576888252Smrgstatic int lgRop[16] = { 3676888252Smrg /* Lg Op X name */ 3776888252Smrg 3876888252Smrg 0x00, /* 0 GXclear */ 3976888252Smrg 0x88, /* S.D GXand */ 4076888252Smrg 0x44, /* S.~D GXandReverse */ 4176888252Smrg 0xCC, /* S GXcopy */ 4276888252Smrg 0x22, /* ~S.D GXandInverted */ 4376888252Smrg 0xAA, /* D GXnoop */ 4476888252Smrg 0x66, /* S~=D GXxor */ 4576888252Smrg 0xEE, /* S+D GXor */ 4676888252Smrg 0x77, /* ~S.~D GXnor */ 4776888252Smrg 0x99, /* S=D GXequiv */ 4876888252Smrg 0x55, /* ~D GXinvert */ 4976888252Smrg 0xDD, /* S+~D GXorReverse */ 5076888252Smrg 0x33, /* ~S GXcopyInverted */ 5176888252Smrg 0xBB, /* ~S+D GXorInverted */ 5276888252Smrg 0x11, /* ~S+~D GXnand */ 5376888252Smrg 0xFF /* 1 GXset */ 5476888252Smrg}; 5576888252Smrg 5676888252Smrg#if 0 5776888252Smrg/* Laguna raster operations, source is OP2 and destination is OP0. */ 5876888252Smrgstatic int lgPatRop[16] = { 5976888252Smrg /* Lg Op X name */ 6076888252Smrg 6176888252Smrg 0x00, /* 0 GXclear */ 6276888252Smrg 0xA0, /* S.D GXand */ 6376888252Smrg 0x50, /* S.~D GXandReverse */ 6476888252Smrg 0xF0, /* S GXcopy */ 6576888252Smrg 0x0A, /* ~S.D GXandInverted */ 6676888252Smrg 0xAA, /* D GXnoop */ 6776888252Smrg 0x5A, /* S~=D GXxor */ 6876888252Smrg 0xFA, /* S+D GXor */ 6976888252Smrg 0x05, /* ~S.~D GXnor */ 7076888252Smrg 0xA5, /* S=D GXequiv */ 7176888252Smrg 0x55, /* ~D GXinvert */ 7276888252Smrg 0xF5, /* S+~D GXorReverse */ 7376888252Smrg 0x0F, /* ~S GXcopyInverted */ 7476888252Smrg 0xAF, /* ~S+D GXorInverted */ 7576888252Smrg 0x5F, /* ~S+~D GXnand */ 7676888252Smrg 0xFF /* 1 GXset */ 7776888252Smrg}; 7876888252Smrg#endif 7976888252Smrg 8076888252Smrg 8176888252Smrgstatic void LgSetBitmask(CirPtr pCir, const CARD32 m); 8276888252Smrgstatic void LgWaitQAvail(CirPtr pCir, int n); 8376888252Smrgstatic CARD32 LgExpandColor(CARD32 color, int bpp); 8476888252Smrgstatic void LgSync(ScrnInfoPtr pScrn); 8576888252Smrgstatic void LgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 8676888252Smrg unsigned int planemask); 8776888252Smrg 8876888252Smrgstatic void LgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 8976888252Smrg int w, int h); 9076888252Smrgstatic void LgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 9176888252Smrg int rop, unsigned int planemask, 9276888252Smrg int transparency_color); 9376888252Smrgstatic void LgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 9476888252Smrg int x2, int y2, int w, int h); 9576888252Smrg 9676888252Smrg 9776888252Smrg/**************************************************** LgXAAInit *****/ 9876888252Smrg 9976888252SmrgBool 10076888252SmrgLgXAAInit(ScreenPtr pScreen) 10176888252Smrg{ 10263847c39Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 10376888252Smrg CirPtr pCir = CIRPTR(pScrn); 10476888252Smrg XAAInfoRecPtr XAAPtr; 10576888252Smrg 10676888252Smrg XAAPtr = XAACreateInfoRec(); 10776888252Smrg if (!XAAPtr) 10876888252Smrg return FALSE; 10976888252Smrg 11076888252Smrg /* 11176888252Smrg * Solid color fills. 11276888252Smrg */ 11376888252Smrg XAAPtr->SetupForSolidFill = LgSetupForSolidFill; 11476888252Smrg XAAPtr->SubsequentSolidFillRect = LgSubsequentSolidFillRect; 11576888252Smrg XAAPtr->SubsequentSolidFillTrap = NULL; 11676888252Smrg XAAPtr->SolidFillFlags = 0; 11776888252Smrg 11876888252Smrg /* 11976888252Smrg * Screen-to-screen copies. 12076888252Smrg */ 12176888252Smrg XAAPtr->SetupForScreenToScreenCopy = LgSetupForScreenToScreenCopy; 12276888252Smrg XAAPtr->SubsequentScreenToScreenCopy = LgSubsequentScreenToScreenCopy; 12376888252Smrg /* Maybe ONLY_LEFT_TO_RIGHT_BITBLT or ONLY_TWO_BITBLT_DIRECTIONS? */ 12476888252Smrg XAAPtr->ScreenToScreenCopyFlags = ONLY_LEFT_TO_RIGHT_BITBLT; 12576888252Smrg 12676888252Smrg /* 12776888252Smrg * Miscellany. 12876888252Smrg */ 12976888252Smrg XAAPtr->Sync = LgSync; 13076888252Smrg 13176888252Smrg pCir->AccelInfoRec = XAAPtr; 13276888252Smrg 13376888252Smrg if (!XAAInit(pScreen, XAAPtr)) 13476888252Smrg return FALSE; 13576888252Smrg 13676888252Smrg return TRUE; 13776888252Smrg} 13876888252Smrg 13976888252Smrg/******************************************** Lg XAA helper functions ***/ 14076888252Smrg 14176888252Smrg/* 14276888252Smrg * The bitmask is usually all 1's, so it's silly to spend a DWORD write 14376888252Smrg * to program the register with the same value each time. Bitmask is 14476888252Smrg * about the only register whose value is worth shadowing, so we special- 14576888252Smrg * case it. 14676888252Smrg */ 14776888252Smrgstatic void 14876888252SmrgLgSetBitmask(CirPtr pCir, const CARD32 m) 14976888252Smrg{ 15076888252Smrg const LgPtr pLg = LGPTR(pCir); 15176888252Smrg 15276888252Smrg if (m != pLg->oldBitmask) { 15376888252Smrg LgSETBITMASK(m); 15476888252Smrg pLg->oldBitmask = m; 15576888252Smrg } 15676888252Smrg} 15776888252Smrg 15876888252Smrg/* 15976888252Smrg * Return from the function only when there's room somewhere for the 16076888252Smrg * upcoming register writes. That means that either PCI retry is enabled 16176888252Smrg * (i.e., we let the PCI bus buffer the register writes), or we wait for 16276888252Smrg * room in the Laguna's command queue explicitly. 16376888252Smrg */ 16476888252Smrgstatic void 16576888252SmrgLgWaitQAvail(CirPtr pCir, int n) 16676888252Smrg{ 16776888252Smrg if (!0/*lgUsePCIRetry*/) { 16876888252Smrg CARD8 qfree; 16976888252Smrg 17076888252Smrg /* Wait until n entries are open in the command queue */ 17176888252Smrg do 17276888252Smrg qfree = *(volatile CARD8 *)(pCir->IOBase + QFREE); 17376888252Smrg while (qfree < n); 17476888252Smrg } 17576888252Smrg} 17676888252Smrg 17776888252Smrg 17876888252Smrg/* We might want to make this a macro at some point. */ 17976888252Smrgstatic CARD32 18076888252SmrgLgExpandColor(CARD32 color, int bpp) 18176888252Smrg{ 18276888252Smrg if (8 == bpp) 18376888252Smrg color = ((color&0xFF) << 8) | (color&0xFF); 18476888252Smrg 18576888252Smrg if (8 == bpp || 16 == bpp) 18676888252Smrg color = ((color&0xFFFF) << 16) | (color&0xFFFF); 18776888252Smrg 18876888252Smrg return color; 18976888252Smrg} 19076888252Smrg 19176888252Smrg 19276888252Smrg/*************************************************** Lg XAA functions ***/ 19376888252Smrg 19476888252Smrg 19576888252Smrgstatic void 19676888252SmrgLgSync(ScrnInfoPtr pScrn) 19776888252Smrg{ 19876888252Smrg const CirPtr pCir = CIRPTR(pScrn); 19976888252Smrg#if 0 20076888252Smrg LgPtr pLg = LGPTR(pScrn); 20176888252Smrg#endif 20276888252Smrg 20376888252Smrg while (!LgREADY()) 20476888252Smrg ; 20576888252Smrg} 20676888252Smrg 20776888252Smrgstatic void 20876888252SmrgLgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 20976888252Smrg unsigned int planemask) 21076888252Smrg{ 21176888252Smrg 21276888252Smrg const CirPtr pCir = CIRPTR(pScrn); 21376888252Smrg 21476888252Smrg color = LgExpandColor(color, pScrn->bitsPerPixel); 21576888252Smrg 21676888252Smrg LgWaitQAvail(pCir, 4); 21776888252Smrg 21876888252Smrg LgSETBACKGROUND(color); 21976888252Smrg LgSETROP(lgRop[rop]); 22076888252Smrg LgSETMODE(SCR2SCR | COLORFILL); 22176888252Smrg LgSetBitmask(pCir, planemask); 22276888252Smrg} 22376888252Smrg 22476888252Smrgstatic void 22576888252SmrgLgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 22676888252Smrg{ 22776888252Smrg const CirPtr pCir = CIRPTR(pScrn); 22876888252Smrg 22976888252Smrg /* Wait for room in the command queue. */ 23076888252Smrg LgWaitQAvail(pCir, 2); 23176888252Smrg 23276888252Smrg LgSETDSTXY(x, y); 23376888252Smrg LgSETEXTENTS(w, h); 23476888252Smrg} 23576888252Smrg 23676888252Smrgstatic void 23776888252SmrgLgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 23876888252Smrg int rop, unsigned int planemask, int transparency_color) 23976888252Smrg{ 24076888252Smrg int bltmode = 0; 24176888252Smrg const CirPtr pCir = CIRPTR(pScrn); 24276888252Smrg const LgPtr pLg = LGPTR(pCir); 24376888252Smrg 24476888252Smrg pLg->blitTransparent = (transparency_color != -1); 24576888252Smrg pLg->blitYDir = ydir; 24676888252Smrg 24776888252Smrg LgWaitQAvail(pCir, 4); 24876888252Smrg 24976888252Smrg /* We set the rop up here because the LgSETROP macro conveniently 25076888252Smrg (really -- it is convenient!) clears the transparency bits 2510814a2baSmrg in DRAWDEF. We'll set those bits appropriately later. */ 25276888252Smrg LgSETROP(lgRop[rop]); 25376888252Smrg 25476888252Smrg if (ydir < 0) 25576888252Smrg bltmode |= BLITUP; 25676888252Smrg if (pLg->blitTransparent) { 25776888252Smrg /* Gotta extend the transparency_color to the full 32-bit 25876888252Smrg size of the register. */ 25976888252Smrg transparency_color = LgExpandColor(transparency_color, 26076888252Smrg pScrn->bitsPerPixel); 26176888252Smrg 26276888252Smrg bltmode |= COLORTRANS; 26376888252Smrg LgSETBACKGROUND(transparency_color); 26476888252Smrg LgSETTRANSPARENCY(TRANSEQ); 26576888252Smrg } else { 26676888252Smrg LgSETTRANSPARENCY(TRANSNONE); 26776888252Smrg } 26876888252Smrg 26976888252Smrg LgSETMODE(SCR2SCR | COLORSRC | bltmode); 27076888252Smrg LgSetBitmask(pCir, planemask); 27176888252Smrg} 27276888252Smrg 27376888252Smrgstatic void 27476888252SmrgLgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 27576888252Smrg int x2, int y2, int w, int h) 27676888252Smrg{ 27776888252Smrg const CirPtr pCir = CIRPTR(pScrn); 27876888252Smrg const LgPtr pLg = LGPTR(pCir); 27976888252Smrg 28076888252Smrg /* 28176888252Smrg * We have set the flag indicating that xdir must be one, 28276888252Smrg * so we can assume that here. 28376888252Smrg */ 28476888252Smrg if (pLg->blitYDir == -1) { 28576888252Smrg y1 += h - 1; 28676888252Smrg y2 += h - 1; 28776888252Smrg } 28876888252Smrg 28976888252Smrg if (pLg->blitTransparent) { 29076888252Smrg /* We're doing a transparent blit. We'll need to point 29176888252Smrg OP2 to the color compare mask. */ 29276888252Smrg LgWaitQAvail(pCir, 4); 29376888252Smrg LgSETTRANSMASK(x1, y1); 29476888252Smrg } else { 29576888252Smrg LgWaitQAvail(pCir, 3); 29676888252Smrg } 29776888252Smrg LgSETSRCXY(x1, y1); 29876888252Smrg LgSETDSTXY(x2, y2); 29976888252Smrg LgSETEXTENTS(w, h); 30076888252Smrg} 30163847c39Smrg#endif 302