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