neo_2200.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_2200.c,v 1.19tsi Exp $ */
26692f60a7Smrg/*
27692f60a7Smrg * The original Precision Insight driver for
28692f60a7Smrg * XFree86 v.3.3 has been sponsored by Red Hat.
29692f60a7Smrg *
30692f60a7Smrg * Authors:
31692f60a7Smrg *   Jens Owen (jens@tungstengraphics.com)
32692f60a7Smrg *   Kevin E. Martin (kevin@precisioninsight.com)
33692f60a7Smrg *
34692f60a7Smrg * Port to Xfree86 v.4.0
35692f60a7Smrg *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
36692f60a7Smrg */
37692f60a7Smrg
38692f60a7Smrg#ifdef HAVE_CONFIG_H
39692f60a7Smrg#include "config.h"
40692f60a7Smrg#endif
41692f60a7Smrg
42692f60a7Smrg#include "xf86.h"
43692f60a7Smrg#include "xf86_OSproc.h"
44692f60a7Smrg#include "compiler.h"
45692f60a7Smrg
46692f60a7Smrg/* Drivers that use XAA need this */
47692f60a7Smrg#include "xf86fbman.h"
48692f60a7Smrg
49692f60a7Smrg#include "miline.h"
50692f60a7Smrg
51692f60a7Smrg#include "neo.h"
52692f60a7Smrg#include "neo_reg.h"
53692f60a7Smrg#include "neo_macros.h"
54692f60a7Smrg
55692f60a7Smrgstatic void Neo2200Sync(ScrnInfoPtr pScrn);
56692f60a7Smrgstatic void Neo2200SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
57692f60a7Smrg					      int ydir, int rop,
58692f60a7Smrg					      unsigned int planemask,
59692f60a7Smrg					      int trans_color);
60692f60a7Smrg#ifdef NOT_BROKEN
61692f60a7Smrgstatic void Neo2200SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
62692f60a7Smrg						int srcY, int dstX, int dstY,
63692f60a7Smrg						int w, int h);
64692f60a7Smrg#else
65692f60a7Smrgstatic void Neo2200SubsequentScreenToScreenCopyBroken(ScrnInfoPtr pScrn, int srcX,
66692f60a7Smrg						int srcY, int dstX, int dstY,
67692f60a7Smrg						int w, int h);
68692f60a7Smrg#endif
69692f60a7Smrgstatic void Neo2200SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
70692f60a7Smrg				  unsigned int planemask);
71692f60a7Smrgstatic void Neo2200SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
72692f60a7Smrg					   int w, int h);
73692f60a7Smrgstatic void Neo2200SetupForScanlineCPUToScreenColorExpandFill(
74692f60a7Smrg                                                      ScrnInfoPtr pScrn,
75692f60a7Smrg						      int fg, int bg,
76692f60a7Smrg						      int rop,
77692f60a7Smrg						unsigned int planemask);
78692f60a7Smrgstatic void Neo2200SubsequentScanlineCPUToScreenColorExpandFill(
79692f60a7Smrg                                                        ScrnInfoPtr pScrn,
80692f60a7Smrg							int x, int y,
81692f60a7Smrg							int w, int h,
82692f60a7Smrg							int skipleft);
83692f60a7Smrgstatic void Neo2200SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
84692f60a7Smrg#if 0
85692f60a7Smrgstatic void Neo2200SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
86692f60a7Smrg					       int patternx,
87692f60a7Smrg					       int patterny,
88692f60a7Smrg					       int bg,
89692f60a7Smrg					       int fg,
90692f60a7Smrg					       int rop,
91692f60a7Smrg					       unsigned int planemask);
92692f60a7Smrgstatic void Neo2200SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
93692f60a7Smrg						 int patternx,
94692f60a7Smrg						 int patterny,
95692f60a7Smrg						 int x, int y,
96692f60a7Smrg						 int w, int h);
97692f60a7Smrg#endif
98692f60a7Smrg
99692f60a7Smrg
100692f60a7Smrgstatic unsigned int neo2200Rop[16] = {
101692f60a7Smrg    0x000000,    /* 0x0000 - GXclear         */
102692f60a7Smrg    0x080000,    /* 0x1000 - GXand           */
103692f60a7Smrg    0x040000,    /* 0x0100 - GXandReverse    */
104692f60a7Smrg    0x0c0000,    /* 0x1100 - GXcopy          */
105692f60a7Smrg    0x020000,    /* 0x0010 - GXandInvert     */
106692f60a7Smrg    0x0a0000,    /* 0x1010 - GXnoop          */
107692f60a7Smrg    0x060000,    /* 0x0110 - GXxor           */
108692f60a7Smrg    0x0e0000,    /* 0x1110 - GXor            */
109692f60a7Smrg    0x010000,    /* 0x0001 - GXnor           */
110692f60a7Smrg    0x090000,    /* 0x1001 - GXequiv         */
111692f60a7Smrg    0x050000,    /* 0x0101 - GXinvert        */
112692f60a7Smrg    0x0d0000,    /* 0x1101 - GXorReverse     */
113692f60a7Smrg    0x030000,    /* 0x0011 - GXcopyInvert    */
114692f60a7Smrg    0x0b0000,    /* 0x1011 - GXorInverted    */
115692f60a7Smrg    0x070000,    /* 0x0111 - GXnand          */
116692f60a7Smrg    0x0f0000     /* 0x1111 - GXset           */
117692f60a7Smrg};
118692f60a7Smrg
119692f60a7SmrgBool
120692f60a7SmrgNeo2200AccelInit(ScreenPtr pScreen)
121692f60a7Smrg{
122692f60a7Smrg    XAAInfoRecPtr infoPtr;
123692f60a7Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
124692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
125692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
126692f60a7Smrg
127692f60a7Smrg    nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
128692f60a7Smrg    if(!infoPtr) return FALSE;
129692f60a7Smrg
130692f60a7Smrg    /*
131692f60a7Smrg     * Set up the main acceleration flags.
132692f60a7Smrg     */
133692f60a7Smrg    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
134692f60a7Smrg    if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
135692f60a7Smrg#if 0
136692f60a7Smrg    infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES;
137692f60a7Smrg#endif
138692f60a7Smrg    /* sync */
139692f60a7Smrg    infoPtr->Sync = Neo2200Sync;
140692f60a7Smrg
141692f60a7Smrg    /* screen to screen copy */
142692f60a7Smrg    infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
143692f60a7Smrg    infoPtr->SetupForScreenToScreenCopy =
144692f60a7Smrg	Neo2200SetupForScreenToScreenCopy;
145692f60a7Smrg    infoPtr->SubsequentScreenToScreenCopy
146692f60a7Smrg#ifdef NOT_BROKEN
147692f60a7Smrg	= Neo2200SubsequentScreenToScreenCopy;
148692f60a7Smrg#else
149692f60a7Smrg	= Neo2200SubsequentScreenToScreenCopyBroken;
150692f60a7Smrg#endif
151692f60a7Smrg
152692f60a7Smrg    /* solid filled rectangles */
153692f60a7Smrg    infoPtr->SolidFillFlags = NO_PLANEMASK;
154692f60a7Smrg    infoPtr->SetupForSolidFill =
155692f60a7Smrg	Neo2200SetupForSolidFillRect;
156692f60a7Smrg    infoPtr->SubsequentSolidFillRect =
157692f60a7Smrg	Neo2200SubsequentSolidFillRect;
158692f60a7Smrg
159692f60a7Smrg    /* cpu to screen color expansion */
160692f60a7Smrg    /*
161692f60a7Smrg     * We do CPUToScreenColorExpand (ab)using the Scanline functions:
162692f60a7Smrg     * the neo chipsets need byte padding however we can only do dword
163692f60a7Smrg     * padding. Fortunately the graphics engine doesn't choke if we
164692f60a7Smrg     * transfer up to 3 bytes more than it wants.
165692f60a7Smrg     */
166692f60a7Smrg
167692f60a7Smrg    if (!nPtr->strangeLockups) {
168692f60a7Smrg
169692f60a7Smrg	infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
170692f60a7Smrg#ifdef NEO_DO_CLIPPING
171692f60a7Smrg						LEFT_EDGE_CLIPPING |
172692f60a7Smrg#endif
173692f60a7Smrg						SCANLINE_PAD_DWORD |
174692f60a7Smrg						CPU_TRANSFER_PAD_DWORD |
175692f60a7Smrg						BIT_ORDER_IN_BYTE_MSBFIRST );
176692f60a7Smrg	infoPtr->ScanlineColorExpandBuffers =
177692f60a7Smrg	    (unsigned char **)xnfalloc(sizeof(char*));
178692f60a7Smrg	infoPtr->ScanlineColorExpandBuffers[0] =
179692f60a7Smrg	    (unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
180692f60a7Smrg	infoPtr->NumScanlineColorExpandBuffers = 1;
181692f60a7Smrg	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
182692f60a7Smrg	    Neo2200SetupForScanlineCPUToScreenColorExpandFill;
183692f60a7Smrg	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
184692f60a7Smrg	    Neo2200SubsequentScanlineCPUToScreenColorExpandFill;
185692f60a7Smrg	infoPtr->SubsequentColorExpandScanline =
186692f60a7Smrg	    Neo2200SubsequentColorExpandScanline;
187692f60a7Smrg    }
188692f60a7Smrg
189692f60a7Smrg#if 0
190692f60a7Smrg    /* 8x8 pattern fills */
191692f60a7Smrg    infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
192692f60a7Smrg	| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
193692f60a7Smrg	|BIT_ORDER_IN_BYTE_MSBFIRST;
194692f60a7Smrg
195692f60a7Smrg    infoPtr->SetupForMono8x8PatternFill =
196692f60a7Smrg	Neo2200SetupForMono8x8PatternFill;
197692f60a7Smrg    infoPtr->SubsequentMono8x8PatternFillRect =
198692f60a7Smrg	Neo2200SubsequentMono8x8PatternFill;
199692f60a7Smrg#endif
200692f60a7Smrg
201692f60a7Smrg    /*
202692f60a7Smrg     * Setup some global variables
203692f60a7Smrg     */
204692f60a7Smrg
205692f60a7Smrg    /* Initialize for 8bpp or 15/16bpp support accelerated */
206692f60a7Smrg    switch (pScrn->bitsPerPixel) {
207692f60a7Smrg    case 8:
208692f60a7Smrg	nAcl->BltModeFlags = NEO_MODE1_DEPTH8;
209692f60a7Smrg        nAcl->PixelWidth = 1;
210692f60a7Smrg	break;
211692f60a7Smrg    case 15:
212692f60a7Smrg    case 16:
213692f60a7Smrg	nAcl->BltModeFlags = NEO_MODE1_DEPTH16;
214692f60a7Smrg        nAcl->PixelWidth = 2;
215692f60a7Smrg	break;
216692f60a7Smrg    case 24:
217692f60a7Smrg	if (nPtr->noAccelSet || nPtr->NeoChipset == NM2230
218692f60a7Smrg	    || nPtr->NeoChipset == NM2360
219692f60a7Smrg	    || nPtr->NeoChipset == NM2380) {
220692f60a7Smrg	    nAcl->BltModeFlags = NEO_MODE1_DEPTH24;
221692f60a7Smrg            nAcl->PixelWidth = 3;
222692f60a7Smrg	} else
223692f60a7Smrg	    return FALSE;
224692f60a7Smrg	break;
225692f60a7Smrg    default:
226692f60a7Smrg	return FALSE;
227692f60a7Smrg    }
228692f60a7Smrg    nAcl->Pitch = pScrn->displayWidth * nAcl->PixelWidth;
229692f60a7Smrg
230692f60a7Smrg    /* Initialize for widths */
231692f60a7Smrg    switch (pScrn->displayWidth) {
232692f60a7Smrg    case 320:
233692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_320;
234692f60a7Smrg	break;
235692f60a7Smrg    case 640:
236692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_640;
237692f60a7Smrg	break;
238692f60a7Smrg    case 800:
239692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_800;
240692f60a7Smrg	break;
241692f60a7Smrg    case 1024:
242692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1024;
243692f60a7Smrg	break;
244692f60a7Smrg    case 1152:
245692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1152;
246692f60a7Smrg	break;
247692f60a7Smrg    case 1280:
248692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1280;
249692f60a7Smrg	break;
250692f60a7Smrg    case 1600:
251692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1600;
252692f60a7Smrg	break;
253692f60a7Smrg    default:
254692f60a7Smrg	return FALSE;
255692f60a7Smrg    }
256692f60a7Smrg
257692f60a7Smrg    return (xaaSetupWrapper(pScreen, infoPtr, pScrn->depth, &nPtr->accelSync));
258692f60a7Smrg}
259692f60a7Smrg
260692f60a7Smrgstatic void
261692f60a7SmrgNeo2200Sync(ScrnInfoPtr pScrn)
262692f60a7Smrg{
263692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
264692f60a7Smrg
265692f60a7Smrg    WAIT_ENGINE_IDLE();
266692f60a7Smrg}
267692f60a7Smrg
268692f60a7Smrgstatic void
269692f60a7SmrgNeo2200SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
270692f60a7Smrg				  int rop,
271692f60a7Smrg				  unsigned int planemask,
272692f60a7Smrg				  int trans_color)
273692f60a7Smrg{
274692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
275692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
276692f60a7Smrg
277692f60a7Smrg    nAcl->tmpBltCntlFlags = (NEO_BC3_SKIP_MAPPING | neo2200Rop[rop]);
278692f60a7Smrg    /* set blt control */
279692f60a7Smrg    WAIT_ENGINE_IDLE();
280692f60a7Smrg    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
281692f60a7Smrg    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
282692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
283692f60a7Smrg    OUTREG(NEOREG_PITCH, (nAcl->Pitch<<16)
284692f60a7Smrg	   | (nAcl->Pitch & 0xffff));
285692f60a7Smrg}
286692f60a7Smrg
287692f60a7Smrg#ifdef NOT_BROKEN
288692f60a7Smrgstatic void
289692f60a7SmrgNeo2200SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
290692f60a7Smrg				    int srcX, int srcY,
291692f60a7Smrg				    int dstX, int dstY,
292692f60a7Smrg				    int w, int h)
293692f60a7Smrg{
294692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
295692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
296692f60a7Smrg
297692f60a7Smrg    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
298692f60a7Smrg	/* start with upper left corner */
299692f60a7Smrg	WAIT_ENGINE_IDLE();
300692f60a7Smrg#if 0
301692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
302692f60a7Smrg#endif
303692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
304692f60a7Smrg            (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
305692f60a7Smrg	OUTREG(NEOREG_DSTSTARTOFF,
306692f60a7Smrg            (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
307692f60a7Smrg	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
308692f60a7Smrg    }
309692f60a7Smrg    else {
310692f60a7Smrg	/* start with lower right corner */
311692f60a7Smrg	WAIT_ENGINE_IDLE();
312692f60a7Smrg#if 0
313692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
314692f60a7Smrg				| NEO_BC0_X_DEC
315692f60a7Smrg				| NEO_BC0_DST_Y_DEC
316692f60a7Smrg				| NEO_BC0_SRC_Y_DEC));
317692f60a7Smrg#endif
318692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
319692f60a7Smrg            ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
320692f60a7Smrg						 * nAcl->PixelWidth));
321692f60a7Smrg	OUTREG(NEOREG_DSTSTARTOFF,
322692f60a7Smrg            ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
323692f60a7Smrg						 * nAcl->PixelWidth));
324692f60a7Smrg	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
325692f60a7Smrg    }
326692f60a7Smrg}
327692f60a7Smrg
328692f60a7Smrg#else /* NOT_BROKEN */
329692f60a7Smrg
330692f60a7Smrgstatic void
331692f60a7SmrgNeo2200SubsequentScreenToScreenCopyBroken(ScrnInfoPtr pScrn,
332692f60a7Smrg					  int srcX, int srcY,
333692f60a7Smrg					  int dstX, int dstY,
334692f60a7Smrg					  int w, int h)
335692f60a7Smrg{
336692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
337692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
338692f60a7Smrg
339692f60a7Smrg    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
340692f60a7Smrg	if ((((dstX < 64) && ((srcX + w + 64) >= pScrn->displayWidth)) ||
341692f60a7Smrg	    ((dstX == 0) && (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
342692f60a7Smrg
343692f60a7Smrg#define COPY_64 \
344692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,\
345692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));\
346692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,\
347692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));\
348692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (64));
349692f60a7Smrg#define COPY_W \
350692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,\
351692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX1 * nAcl->PixelWidth));\
352692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,\
353692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX1 * nAcl->PixelWidth));\
354692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
355692f60a7Smrg
356692f60a7Smrg	    int srcX1 = srcX + 64;
357692f60a7Smrg	    int dstX1 = dstX + 64;
358692f60a7Smrg	    w -= 64;
359692f60a7Smrg	    /* start with upper left corner */
360692f60a7Smrg	    WAIT_ENGINE_IDLE();
361692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
362692f60a7Smrg	    if (srcX < dstX) {
363692f60a7Smrg		COPY_W;
364692f60a7Smrg	        WAIT_ENGINE_IDLE();
365692f60a7Smrg	        COPY_64;
366692f60a7Smrg	    } else {
367692f60a7Smrg		COPY_64;
368692f60a7Smrg	        WAIT_ENGINE_IDLE();
369692f60a7Smrg		COPY_W;
370692f60a7Smrg	    }
371692f60a7Smrg#undef COPY_W
372692f60a7Smrg#undef COPY_64
373692f60a7Smrg	} else {
374692f60a7Smrg	    /* start with upper left corner */
375692f60a7Smrg	    WAIT_ENGINE_IDLE();
376692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
377692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,
378692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
379692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,
380692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
381692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
382692f60a7Smrg	}
383692f60a7Smrg    } else {
384692f60a7Smrg	if (((((dstX + w) > (pScrn->displayWidth - 64)) && (srcX == 0))
385692f60a7Smrg	    || (((dstX + w + 64) >= pScrn->displayWidth)
386692f60a7Smrg		&& (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
387692f60a7Smrg#define COPY_64 \
388692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF, \
389692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX1+64-1)  \
390692f60a7Smrg						 * nAcl->PixelWidth)); \
391692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF, \
392692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX1+64-1) \
393692f60a7Smrg						 * nAcl->PixelWidth)); \
394692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (64 & 0xffff));
395692f60a7Smrg#define COPY_W \
396692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF, \
397692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX + w -1)  \
398692f60a7Smrg						 * nAcl->PixelWidth)); \
399692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF, \
400692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX + w -1) \
401692f60a7Smrg						 * nAcl->PixelWidth)); \
402692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
403692f60a7Smrg
404692f60a7Smrg	    int srcX1, dstX1;
405692f60a7Smrg
406692f60a7Smrg	    w -= 64;
407692f60a7Smrg	    srcX1 = srcX + w;
408692f60a7Smrg	    dstX1 = dstX + w;
409692f60a7Smrg	    /* start with lower right corner */
410692f60a7Smrg	    WAIT_ENGINE_IDLE();
411692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
412692f60a7Smrg				    | NEO_BC0_X_DEC
413692f60a7Smrg				    | NEO_BC0_DST_Y_DEC
414692f60a7Smrg				    | NEO_BC0_SRC_Y_DEC));
415692f60a7Smrg	    if (srcX < dstX) {
416692f60a7Smrg	      COPY_64;
417692f60a7Smrg	      WAIT_ENGINE_IDLE();
418692f60a7Smrg	      COPY_W;
419692f60a7Smrg	    } else {
420692f60a7Smrg	      COPY_W;
421692f60a7Smrg	      WAIT_ENGINE_IDLE();
422692f60a7Smrg	      COPY_64;
423692f60a7Smrg	    }
424692f60a7Smrg#undef COPY_W
425692f60a7Smrg#undef COPY_64
426692f60a7Smrg	} else {
427692f60a7Smrg	    /* start with lower right corner */
428692f60a7Smrg	    WAIT_ENGINE_IDLE();
429692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
430692f60a7Smrg				    | NEO_BC0_X_DEC
431692f60a7Smrg				    | NEO_BC0_DST_Y_DEC
432692f60a7Smrg				    | NEO_BC0_SRC_Y_DEC));
433692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,
434692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
435692f60a7Smrg						 * nAcl->PixelWidth));
436692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,
437692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
438692f60a7Smrg						 * nAcl->PixelWidth));
439692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
440692f60a7Smrg	}
441692f60a7Smrg    }
442692f60a7Smrg}
443692f60a7Smrg
444692f60a7Smrg#endif /* NOT_BROKEN */
445692f60a7Smrg
446692f60a7Smrgstatic void
447692f60a7SmrgNeo2200SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
448692f60a7Smrg			     unsigned int planemask)
449692f60a7Smrg{
450692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
451692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
452692f60a7Smrg
453692f60a7Smrg    WAIT_ENGINE_IDLE();
454692f60a7Smrg
455692f60a7Smrg    /* set blt control */
456692f60a7Smrg    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
457692f60a7Smrg    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
458692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, NEO_BC0_SRC_IS_FG    |
459692f60a7Smrg                           NEO_BC3_SKIP_MAPPING |
460692f60a7Smrg                           NEO_BC3_DST_XY_ADDR  |
461692f60a7Smrg                           NEO_BC3_SRC_XY_ADDR  | neo2200Rop[rop]);
462692f60a7Smrg
463692f60a7Smrg    /* set foreground color */
464692f60a7Smrg    OUTREG(NEOREG_FGCOLOR, color);
465692f60a7Smrg}
466692f60a7Smrg
467692f60a7Smrg
468692f60a7Smrgstatic void
469692f60a7SmrgNeo2200SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
470692f60a7Smrg{
471692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
472692f60a7Smrg
473692f60a7Smrg    WAIT_ENGINE_IDLE();
474692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y <<16) | (x & 0xffff));
475692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
476692f60a7Smrg}
477692f60a7Smrg
478692f60a7Smrgstatic void
479692f60a7SmrgNeo2200SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
480692f60a7Smrg 				      int fg, int bg,
481692f60a7Smrg				      int rop,
482692f60a7Smrg				      unsigned int planemask)
483692f60a7Smrg{
484692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
485692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
486692f60a7Smrg
487692f60a7Smrg    if (bg == -1) {
488692f60a7Smrg	/* transparent setup */
489692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
490692f60a7Smrg					 NEO_BC0_SRC_MONO     |
491692f60a7Smrg					 NEO_BC0_SRC_TRANS    |
492692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
493692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
494692f60a7Smrg#ifdef NEO_DO_CLIPPING
495692f60a7Smrg				         NEO_BC3_CLIP_ON      |
496692f60a7Smrg#endif
497692f60a7Smrg				         neo2200Rop[rop]);
498692f60a7Smrg
499692f60a7Smrg	WAIT_ENGINE_IDLE();
500692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
501692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
502692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
503692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
504692f60a7Smrg    }
505692f60a7Smrg    else {
506692f60a7Smrg	/* opaque setup */
507692f60a7Smrg        nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
508692f60a7Smrg					 NEO_BC0_SRC_MONO     |
509692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
510692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
511692f60a7Smrg#ifdef NEO_DO_CLIPPING
512692f60a7Smrg 				         NEO_BC3_CLIP_ON      |
513692f60a7Smrg#endif
514692f60a7Smrg					 neo2200Rop[rop]);
515692f60a7Smrg
516692f60a7Smrg	WAIT_ENGINE_IDLE();
517692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
518692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
519692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
520692f60a7Smrg	OUTREG(NEOREG_BGCOLOR, bg);
521692f60a7Smrg    }
522692f60a7Smrg}
523692f60a7Smrg
524692f60a7Smrg
525692f60a7Smrgstatic void
526692f60a7SmrgNeo2200SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
527692f60a7Smrg					int x, int y,
528692f60a7Smrg					int w, int h,
529692f60a7Smrg					int skipleft)
530692f60a7Smrg{
531692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
532692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
533692f60a7Smrg
534692f60a7Smrg#ifdef NEO_DO_CLIPPING
535692f60a7Smrg        w = (w + 31) & ~31;
536692f60a7Smrg#else
537692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_x = x;
538692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_y = y;
539692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_w = w;
540692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_h = h;
541692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
542692f60a7Smrg#endif
543692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
544692f60a7Smrg	   | ((skipleft << 2) & 0x1C));
545692f60a7Smrg#ifdef NEO_DO_CLIPPING
546692f60a7Smrg    OUTREG(NEOREG_CLIPLT, (y << 16) | (x + skipleft));
547692f60a7Smrg    OUTREG(NEOREG_CLIPRB, ((y + h) << 16) | (x + w));
548692f60a7Smrg#endif
549692f60a7Smrg    OUTREG(NEOREG_SRCSTARTOFF, 0);
550692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
551692f60a7Smrg#ifdef NEO_DO_CLIPPING
552692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
553692f60a7Smrg#else
554692f60a7Smrg    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
555692f60a7Smrg#endif
556692f60a7Smrg}
557692f60a7Smrg
558692f60a7Smrgstatic void
559692f60a7SmrgNeo2200SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
560692f60a7Smrg{
561692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
562692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
563692f60a7Smrg
564692f60a7Smrg#ifdef NEO_DO_CLIPPING
565692f60a7Smrg    /* Should I be waiting for fifo slots to prevent retries ?
566692f60a7Smrg       How do I do that on this engine ? */
567692f60a7Smrg#else
568692f60a7Smrg    if (!(--nAcl->CPUToScreenColorExpandFill_h))
569692f60a7Smrg	return;
570692f60a7Smrg
571692f60a7Smrg    WAIT_ENGINE_IDLE();
572692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
573692f60a7Smrg	   | ((nAcl->CPUToScreenColorExpandFill_skipleft << 2) & 0x1C));
574692f60a7Smrg    OUTREG(NEOREG_SRCSTARTOFF, 0);
575692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
576692f60a7Smrg	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
577692f60a7Smrg    OUTREG(NEOREG_XYEXT, (1<<16)
578692f60a7Smrg	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
579692f60a7Smrg#endif
580692f60a7Smrg}
581692f60a7Smrg
582692f60a7Smrg#if 0
583692f60a7Smrgstatic void
584692f60a7SmrgNeo2200SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
585692f60a7Smrg				     int patternx,
586692f60a7Smrg				     int patterny,
587692f60a7Smrg				     int fg, int bg,
588692f60a7Smrg				     int rop, unsigned int planemask)
589692f60a7Smrg{
590692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
591692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
592692f60a7Smrg
593692f60a7Smrg    if (bg == -1) {
594692f60a7Smrg	/* transparent setup */
595692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
596692f60a7Smrg					 NEO_BC0_FILL_PAT     |
597692f60a7Smrg					 NEO_BC0_SRC_TRANS    |
598692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
599692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
600692f60a7Smrg					 neo2200Rop[rop]);
601692f60a7Smrg
602692f60a7Smrg	WAIT_ENGINE_IDLE();
603692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
604692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
605692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
606692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
607692f60a7Smrg	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
608692f60a7Smrg	     + patternx) >> 3);
609692f60a7Smrg    }
610692f60a7Smrg    else {
611692f60a7Smrg	/* opaque setup */
612692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
613692f60a7Smrg					 NEO_BC0_FILL_PAT     |
614692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
615692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
616692f60a7Smrg					 neo2200Rop[rop]);
617692f60a7Smrg
618692f60a7Smrg	WAIT_ENGINE_IDLE();
619692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
620692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
621692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
622692f60a7Smrg	OUTREG(NEOREG_BGCOLOR, bg);
623692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
624692f60a7Smrg	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
625692f60a7Smrg	     + patternx) >> 3);
626692f60a7Smrg    }
627692f60a7Smrg}
628692f60a7Smrg
629692f60a7Smrg
630692f60a7Smrgstatic void
631692f60a7SmrgNeo2200SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
632692f60a7Smrg				    int patternx,
633692f60a7Smrg				    int patterny,
634692f60a7Smrg				    int x, int y,
635692f60a7Smrg				    int w, int h)
636692f60a7Smrg{
637692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
638692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
639692f60a7Smrg
640692f60a7Smrg    patterny &= 0x7;
641692f60a7Smrg
642692f60a7Smrg    WAIT_ENGINE_IDLE();
643692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags |
644692f60a7Smrg	   (patterny << 20)       |
645692f60a7Smrg	   ((patternx << 10) & 0x1C00));
646692f60a7Smrg    OUTREG(NEOREG_SRCBITOFF, patternx);
647692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
648692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
649692f60a7Smrg}
650692f60a7Smrg#endif
651