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