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
543f6d0e1dSmrg#ifdef HAVE_XAA_H
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
1193f6d0e1dSmrg#endif
120692f60a7SmrgBool
121692f60a7SmrgNeo2200AccelInit(ScreenPtr pScreen)
122692f60a7Smrg{
1233f6d0e1dSmrg#ifdef HAVE_XAA_H
124692f60a7Smrg    XAAInfoRecPtr infoPtr;
1253f6d0e1dSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
126692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
127692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
128692f60a7Smrg
129692f60a7Smrg    nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
130692f60a7Smrg    if(!infoPtr) return FALSE;
131692f60a7Smrg
132692f60a7Smrg    /*
133692f60a7Smrg     * Set up the main acceleration flags.
134692f60a7Smrg     */
135692f60a7Smrg    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
136692f60a7Smrg    if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
137692f60a7Smrg#if 0
138692f60a7Smrg    infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES;
139692f60a7Smrg#endif
140692f60a7Smrg    /* sync */
141692f60a7Smrg    infoPtr->Sync = Neo2200Sync;
142692f60a7Smrg
143692f60a7Smrg    /* screen to screen copy */
144692f60a7Smrg    infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
145692f60a7Smrg    infoPtr->SetupForScreenToScreenCopy =
146692f60a7Smrg	Neo2200SetupForScreenToScreenCopy;
147692f60a7Smrg    infoPtr->SubsequentScreenToScreenCopy
148692f60a7Smrg#ifdef NOT_BROKEN
149692f60a7Smrg	= Neo2200SubsequentScreenToScreenCopy;
150692f60a7Smrg#else
151692f60a7Smrg	= Neo2200SubsequentScreenToScreenCopyBroken;
152692f60a7Smrg#endif
153692f60a7Smrg
154692f60a7Smrg    /* solid filled rectangles */
155692f60a7Smrg    infoPtr->SolidFillFlags = NO_PLANEMASK;
156692f60a7Smrg    infoPtr->SetupForSolidFill =
157692f60a7Smrg	Neo2200SetupForSolidFillRect;
158692f60a7Smrg    infoPtr->SubsequentSolidFillRect =
159692f60a7Smrg	Neo2200SubsequentSolidFillRect;
160692f60a7Smrg
161692f60a7Smrg    /* cpu to screen color expansion */
162692f60a7Smrg    /*
163692f60a7Smrg     * We do CPUToScreenColorExpand (ab)using the Scanline functions:
164692f60a7Smrg     * the neo chipsets need byte padding however we can only do dword
165692f60a7Smrg     * padding. Fortunately the graphics engine doesn't choke if we
166692f60a7Smrg     * transfer up to 3 bytes more than it wants.
167692f60a7Smrg     */
168692f60a7Smrg
169692f60a7Smrg    if (!nPtr->strangeLockups) {
170692f60a7Smrg
171692f60a7Smrg	infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
172692f60a7Smrg#ifdef NEO_DO_CLIPPING
173692f60a7Smrg						LEFT_EDGE_CLIPPING |
174692f60a7Smrg#endif
175692f60a7Smrg						SCANLINE_PAD_DWORD |
176692f60a7Smrg						CPU_TRANSFER_PAD_DWORD |
177692f60a7Smrg						BIT_ORDER_IN_BYTE_MSBFIRST );
178692f60a7Smrg	infoPtr->ScanlineColorExpandBuffers =
179692f60a7Smrg	    (unsigned char **)xnfalloc(sizeof(char*));
180692f60a7Smrg	infoPtr->ScanlineColorExpandBuffers[0] =
181692f60a7Smrg	    (unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
182692f60a7Smrg	infoPtr->NumScanlineColorExpandBuffers = 1;
183692f60a7Smrg	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
184692f60a7Smrg	    Neo2200SetupForScanlineCPUToScreenColorExpandFill;
185692f60a7Smrg	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
186692f60a7Smrg	    Neo2200SubsequentScanlineCPUToScreenColorExpandFill;
187692f60a7Smrg	infoPtr->SubsequentColorExpandScanline =
188692f60a7Smrg	    Neo2200SubsequentColorExpandScanline;
189692f60a7Smrg    }
190692f60a7Smrg
191692f60a7Smrg#if 0
192692f60a7Smrg    /* 8x8 pattern fills */
193692f60a7Smrg    infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
194692f60a7Smrg	| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
195692f60a7Smrg	|BIT_ORDER_IN_BYTE_MSBFIRST;
196692f60a7Smrg
197692f60a7Smrg    infoPtr->SetupForMono8x8PatternFill =
198692f60a7Smrg	Neo2200SetupForMono8x8PatternFill;
199692f60a7Smrg    infoPtr->SubsequentMono8x8PatternFillRect =
200692f60a7Smrg	Neo2200SubsequentMono8x8PatternFill;
201692f60a7Smrg#endif
202692f60a7Smrg
203692f60a7Smrg    /*
204692f60a7Smrg     * Setup some global variables
205692f60a7Smrg     */
206692f60a7Smrg
207692f60a7Smrg    /* Initialize for 8bpp or 15/16bpp support accelerated */
208692f60a7Smrg    switch (pScrn->bitsPerPixel) {
209692f60a7Smrg    case 8:
210692f60a7Smrg	nAcl->BltModeFlags = NEO_MODE1_DEPTH8;
211692f60a7Smrg        nAcl->PixelWidth = 1;
212692f60a7Smrg	break;
213692f60a7Smrg    case 15:
214692f60a7Smrg    case 16:
215692f60a7Smrg	nAcl->BltModeFlags = NEO_MODE1_DEPTH16;
216692f60a7Smrg        nAcl->PixelWidth = 2;
217692f60a7Smrg	break;
218692f60a7Smrg    case 24:
219692f60a7Smrg	if (nPtr->noAccelSet || nPtr->NeoChipset == NM2230
220692f60a7Smrg	    || nPtr->NeoChipset == NM2360
221692f60a7Smrg	    || nPtr->NeoChipset == NM2380) {
222692f60a7Smrg	    nAcl->BltModeFlags = NEO_MODE1_DEPTH24;
223692f60a7Smrg            nAcl->PixelWidth = 3;
224692f60a7Smrg	} else
225692f60a7Smrg	    return FALSE;
226692f60a7Smrg	break;
227692f60a7Smrg    default:
228692f60a7Smrg	return FALSE;
229692f60a7Smrg    }
230692f60a7Smrg    nAcl->Pitch = pScrn->displayWidth * nAcl->PixelWidth;
231692f60a7Smrg
232692f60a7Smrg    /* Initialize for widths */
233692f60a7Smrg    switch (pScrn->displayWidth) {
234692f60a7Smrg    case 320:
235692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_320;
236692f60a7Smrg	break;
237692f60a7Smrg    case 640:
238692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_640;
239692f60a7Smrg	break;
240692f60a7Smrg    case 800:
241692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_800;
242692f60a7Smrg	break;
243692f60a7Smrg    case 1024:
244692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1024;
245692f60a7Smrg	break;
246692f60a7Smrg    case 1152:
247692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1152;
248692f60a7Smrg	break;
249692f60a7Smrg    case 1280:
250692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1280;
251692f60a7Smrg	break;
252692f60a7Smrg    case 1600:
253692f60a7Smrg	nAcl->BltModeFlags |= NEO_MODE1_X_1600;
254692f60a7Smrg	break;
255692f60a7Smrg    default:
256692f60a7Smrg	return FALSE;
257692f60a7Smrg    }
258692f60a7Smrg
259c3c9db83Smrg    return(XAAInit(pScreen, infoPtr));
2603f6d0e1dSmrg#else
2613f6d0e1dSmrg    return FALSE;
2623f6d0e1dSmrg#endif
263692f60a7Smrg}
264692f60a7Smrg
2653f6d0e1dSmrg#ifdef HAVE_XAA_H
266692f60a7Smrgstatic void
267692f60a7SmrgNeo2200Sync(ScrnInfoPtr pScrn)
268692f60a7Smrg{
269692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
270692f60a7Smrg
271692f60a7Smrg    WAIT_ENGINE_IDLE();
272692f60a7Smrg}
273692f60a7Smrg
274692f60a7Smrgstatic void
275692f60a7SmrgNeo2200SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
276692f60a7Smrg				  int rop,
277692f60a7Smrg				  unsigned int planemask,
278692f60a7Smrg				  int trans_color)
279692f60a7Smrg{
280692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
281692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
282692f60a7Smrg
283692f60a7Smrg    nAcl->tmpBltCntlFlags = (NEO_BC3_SKIP_MAPPING | neo2200Rop[rop]);
284692f60a7Smrg    /* set blt control */
285692f60a7Smrg    WAIT_ENGINE_IDLE();
286692f60a7Smrg    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
287692f60a7Smrg    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
288692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
289692f60a7Smrg    OUTREG(NEOREG_PITCH, (nAcl->Pitch<<16)
290692f60a7Smrg	   | (nAcl->Pitch & 0xffff));
291692f60a7Smrg}
292692f60a7Smrg
293692f60a7Smrg#ifdef NOT_BROKEN
294692f60a7Smrgstatic void
295692f60a7SmrgNeo2200SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
296692f60a7Smrg				    int srcX, int srcY,
297692f60a7Smrg				    int dstX, int dstY,
298692f60a7Smrg				    int w, int h)
299692f60a7Smrg{
300692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
301692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
302692f60a7Smrg
303692f60a7Smrg    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
304692f60a7Smrg	/* start with upper left corner */
305692f60a7Smrg	WAIT_ENGINE_IDLE();
306692f60a7Smrg#if 0
307692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
308692f60a7Smrg#endif
309692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
310692f60a7Smrg            (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
311692f60a7Smrg	OUTREG(NEOREG_DSTSTARTOFF,
312692f60a7Smrg            (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
313692f60a7Smrg	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
314692f60a7Smrg    }
315692f60a7Smrg    else {
316692f60a7Smrg	/* start with lower right corner */
317692f60a7Smrg	WAIT_ENGINE_IDLE();
318692f60a7Smrg#if 0
319692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
320692f60a7Smrg				| NEO_BC0_X_DEC
321692f60a7Smrg				| NEO_BC0_DST_Y_DEC
322692f60a7Smrg				| NEO_BC0_SRC_Y_DEC));
323692f60a7Smrg#endif
324692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
325692f60a7Smrg            ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
326692f60a7Smrg						 * nAcl->PixelWidth));
327692f60a7Smrg	OUTREG(NEOREG_DSTSTARTOFF,
328692f60a7Smrg            ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
329692f60a7Smrg						 * nAcl->PixelWidth));
330692f60a7Smrg	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
331692f60a7Smrg    }
332692f60a7Smrg}
333692f60a7Smrg
334692f60a7Smrg#else /* NOT_BROKEN */
335692f60a7Smrg
336692f60a7Smrgstatic void
337692f60a7SmrgNeo2200SubsequentScreenToScreenCopyBroken(ScrnInfoPtr pScrn,
338692f60a7Smrg					  int srcX, int srcY,
339692f60a7Smrg					  int dstX, int dstY,
340692f60a7Smrg					  int w, int h)
341692f60a7Smrg{
342692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
343692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
344692f60a7Smrg
345692f60a7Smrg    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
346692f60a7Smrg	if ((((dstX < 64) && ((srcX + w + 64) >= pScrn->displayWidth)) ||
347692f60a7Smrg	    ((dstX == 0) && (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
348692f60a7Smrg
349692f60a7Smrg#define COPY_64 \
350692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,\
351692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));\
352692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,\
353692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));\
354692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (64));
355692f60a7Smrg#define COPY_W \
356692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,\
357692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX1 * nAcl->PixelWidth));\
358692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,\
359692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX1 * nAcl->PixelWidth));\
360692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
361692f60a7Smrg
362692f60a7Smrg	    int srcX1 = srcX + 64;
363692f60a7Smrg	    int dstX1 = dstX + 64;
364692f60a7Smrg	    w -= 64;
365692f60a7Smrg	    /* start with upper left corner */
366692f60a7Smrg	    WAIT_ENGINE_IDLE();
367692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
368692f60a7Smrg	    if (srcX < dstX) {
369692f60a7Smrg		COPY_W;
370692f60a7Smrg	        WAIT_ENGINE_IDLE();
371692f60a7Smrg	        COPY_64;
372692f60a7Smrg	    } else {
373692f60a7Smrg		COPY_64;
374692f60a7Smrg	        WAIT_ENGINE_IDLE();
375692f60a7Smrg		COPY_W;
376692f60a7Smrg	    }
377692f60a7Smrg#undef COPY_W
378692f60a7Smrg#undef COPY_64
379692f60a7Smrg	} else {
380692f60a7Smrg	    /* start with upper left corner */
381692f60a7Smrg	    WAIT_ENGINE_IDLE();
382692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
383692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,
384692f60a7Smrg		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
385692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,
386692f60a7Smrg		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
387692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
388692f60a7Smrg	}
389692f60a7Smrg    } else {
390692f60a7Smrg	if (((((dstX + w) > (pScrn->displayWidth - 64)) && (srcX == 0))
391692f60a7Smrg	    || (((dstX + w + 64) >= pScrn->displayWidth)
392692f60a7Smrg		&& (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
393692f60a7Smrg#define COPY_64 \
394692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF, \
395692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX1+64-1)  \
396692f60a7Smrg						 * nAcl->PixelWidth)); \
397692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF, \
398692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX1+64-1) \
399692f60a7Smrg						 * nAcl->PixelWidth)); \
400692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (64 & 0xffff));
401692f60a7Smrg#define COPY_W \
402692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF, \
403692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX + w -1)  \
404692f60a7Smrg						 * nAcl->PixelWidth)); \
405692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF, \
406692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX + w -1) \
407692f60a7Smrg						 * nAcl->PixelWidth)); \
408692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
409692f60a7Smrg
410692f60a7Smrg	    int srcX1, dstX1;
411692f60a7Smrg
412692f60a7Smrg	    w -= 64;
413692f60a7Smrg	    srcX1 = srcX + w;
414692f60a7Smrg	    dstX1 = dstX + w;
415692f60a7Smrg	    /* start with lower right corner */
416692f60a7Smrg	    WAIT_ENGINE_IDLE();
417692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
418692f60a7Smrg				    | NEO_BC0_X_DEC
419692f60a7Smrg				    | NEO_BC0_DST_Y_DEC
420692f60a7Smrg				    | NEO_BC0_SRC_Y_DEC));
421692f60a7Smrg	    if (srcX < dstX) {
422692f60a7Smrg	      COPY_64;
423692f60a7Smrg	      WAIT_ENGINE_IDLE();
424692f60a7Smrg	      COPY_W;
425692f60a7Smrg	    } else {
426692f60a7Smrg	      COPY_W;
427692f60a7Smrg	      WAIT_ENGINE_IDLE();
428692f60a7Smrg	      COPY_64;
429692f60a7Smrg	    }
430692f60a7Smrg#undef COPY_W
431692f60a7Smrg#undef COPY_64
432692f60a7Smrg	} else {
433692f60a7Smrg	    /* start with lower right corner */
434692f60a7Smrg	    WAIT_ENGINE_IDLE();
435692f60a7Smrg	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
436692f60a7Smrg				    | NEO_BC0_X_DEC
437692f60a7Smrg				    | NEO_BC0_DST_Y_DEC
438692f60a7Smrg				    | NEO_BC0_SRC_Y_DEC));
439692f60a7Smrg	    OUTREG(NEOREG_SRCSTARTOFF,
440692f60a7Smrg		   ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
441692f60a7Smrg						 * nAcl->PixelWidth));
442692f60a7Smrg	    OUTREG(NEOREG_DSTSTARTOFF,
443692f60a7Smrg		   ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
444692f60a7Smrg						 * nAcl->PixelWidth));
445692f60a7Smrg	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
446692f60a7Smrg	}
447692f60a7Smrg    }
448692f60a7Smrg}
449692f60a7Smrg
450692f60a7Smrg#endif /* NOT_BROKEN */
451692f60a7Smrg
452692f60a7Smrgstatic void
453692f60a7SmrgNeo2200SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
454692f60a7Smrg			     unsigned int planemask)
455692f60a7Smrg{
456692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
457692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
458692f60a7Smrg
459692f60a7Smrg    WAIT_ENGINE_IDLE();
460692f60a7Smrg
461692f60a7Smrg    /* set blt control */
462692f60a7Smrg    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
463692f60a7Smrg    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
464692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, NEO_BC0_SRC_IS_FG    |
465692f60a7Smrg                           NEO_BC3_SKIP_MAPPING |
466692f60a7Smrg                           NEO_BC3_DST_XY_ADDR  |
467692f60a7Smrg                           NEO_BC3_SRC_XY_ADDR  | neo2200Rop[rop]);
468692f60a7Smrg
469692f60a7Smrg    /* set foreground color */
470692f60a7Smrg    OUTREG(NEOREG_FGCOLOR, color);
471692f60a7Smrg}
472692f60a7Smrg
473692f60a7Smrg
474692f60a7Smrgstatic void
475692f60a7SmrgNeo2200SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
476692f60a7Smrg{
477692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
478692f60a7Smrg
479692f60a7Smrg    WAIT_ENGINE_IDLE();
480692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y <<16) | (x & 0xffff));
481692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
482692f60a7Smrg}
483692f60a7Smrg
484692f60a7Smrgstatic void
485692f60a7SmrgNeo2200SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
486692f60a7Smrg 				      int fg, int bg,
487692f60a7Smrg				      int rop,
488692f60a7Smrg				      unsigned int planemask)
489692f60a7Smrg{
490692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
491692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
492692f60a7Smrg
493692f60a7Smrg    if (bg == -1) {
494692f60a7Smrg	/* transparent setup */
495692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
496692f60a7Smrg					 NEO_BC0_SRC_MONO     |
497692f60a7Smrg					 NEO_BC0_SRC_TRANS    |
498692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
499692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
500692f60a7Smrg#ifdef NEO_DO_CLIPPING
501692f60a7Smrg				         NEO_BC3_CLIP_ON      |
502692f60a7Smrg#endif
503692f60a7Smrg				         neo2200Rop[rop]);
504692f60a7Smrg
505692f60a7Smrg	WAIT_ENGINE_IDLE();
506692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
507692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
508692f60a7Smrg	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
509692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
510692f60a7Smrg    }
511692f60a7Smrg    else {
512692f60a7Smrg	/* opaque setup */
513692f60a7Smrg        nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
514692f60a7Smrg					 NEO_BC0_SRC_MONO     |
515692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
516692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
517692f60a7Smrg#ifdef NEO_DO_CLIPPING
518692f60a7Smrg 				         NEO_BC3_CLIP_ON      |
519692f60a7Smrg#endif
520692f60a7Smrg					 neo2200Rop[rop]);
521692f60a7Smrg
522692f60a7Smrg	WAIT_ENGINE_IDLE();
523692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
524692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
525692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
526692f60a7Smrg	OUTREG(NEOREG_BGCOLOR, bg);
527692f60a7Smrg    }
528692f60a7Smrg}
529692f60a7Smrg
530692f60a7Smrg
531692f60a7Smrgstatic void
532692f60a7SmrgNeo2200SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
533692f60a7Smrg					int x, int y,
534692f60a7Smrg					int w, int h,
535692f60a7Smrg					int skipleft)
536692f60a7Smrg{
537692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
538692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
539692f60a7Smrg
540692f60a7Smrg#ifdef NEO_DO_CLIPPING
541692f60a7Smrg        w = (w + 31) & ~31;
542692f60a7Smrg#else
543692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_x = x;
544692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_y = y;
545692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_w = w;
546692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_h = h;
547692f60a7Smrg    nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
548692f60a7Smrg#endif
549692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
550692f60a7Smrg	   | ((skipleft << 2) & 0x1C));
551692f60a7Smrg#ifdef NEO_DO_CLIPPING
552692f60a7Smrg    OUTREG(NEOREG_CLIPLT, (y << 16) | (x + skipleft));
553692f60a7Smrg    OUTREG(NEOREG_CLIPRB, ((y + h) << 16) | (x + w));
554692f60a7Smrg#endif
555692f60a7Smrg    OUTREG(NEOREG_SRCSTARTOFF, 0);
556692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
557692f60a7Smrg#ifdef NEO_DO_CLIPPING
558692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
559692f60a7Smrg#else
560692f60a7Smrg    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
561692f60a7Smrg#endif
562692f60a7Smrg}
563692f60a7Smrg
564692f60a7Smrgstatic void
565692f60a7SmrgNeo2200SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
566692f60a7Smrg{
567692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
568692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
569692f60a7Smrg
570692f60a7Smrg#ifdef NEO_DO_CLIPPING
571692f60a7Smrg    /* Should I be waiting for fifo slots to prevent retries ?
572692f60a7Smrg       How do I do that on this engine ? */
573692f60a7Smrg#else
574692f60a7Smrg    if (!(--nAcl->CPUToScreenColorExpandFill_h))
575692f60a7Smrg	return;
576692f60a7Smrg
577692f60a7Smrg    WAIT_ENGINE_IDLE();
578692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
579692f60a7Smrg	   | ((nAcl->CPUToScreenColorExpandFill_skipleft << 2) & 0x1C));
580692f60a7Smrg    OUTREG(NEOREG_SRCSTARTOFF, 0);
581692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
582692f60a7Smrg	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
583692f60a7Smrg    OUTREG(NEOREG_XYEXT, (1<<16)
584692f60a7Smrg	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
585692f60a7Smrg#endif
586692f60a7Smrg}
587692f60a7Smrg
588692f60a7Smrg#if 0
589692f60a7Smrgstatic void
590692f60a7SmrgNeo2200SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
591692f60a7Smrg				     int patternx,
592692f60a7Smrg				     int patterny,
593692f60a7Smrg				     int fg, int bg,
594692f60a7Smrg				     int rop, unsigned int planemask)
595692f60a7Smrg{
596692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
597692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
598692f60a7Smrg
599692f60a7Smrg    if (bg == -1) {
600692f60a7Smrg	/* transparent setup */
601692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
602692f60a7Smrg					 NEO_BC0_FILL_PAT     |
603692f60a7Smrg					 NEO_BC0_SRC_TRANS    |
604692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
605692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
606692f60a7Smrg					 neo2200Rop[rop]);
607692f60a7Smrg
608692f60a7Smrg	WAIT_ENGINE_IDLE();
609692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
610692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
611692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
612692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
613692f60a7Smrg	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
614692f60a7Smrg	     + patternx) >> 3);
615692f60a7Smrg    }
616692f60a7Smrg    else {
617692f60a7Smrg	/* opaque setup */
618692f60a7Smrg	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
619692f60a7Smrg					 NEO_BC0_FILL_PAT     |
620692f60a7Smrg					 NEO_BC3_SKIP_MAPPING |
621692f60a7Smrg					 NEO_BC3_DST_XY_ADDR  |
622692f60a7Smrg					 neo2200Rop[rop]);
623692f60a7Smrg
624692f60a7Smrg	WAIT_ENGINE_IDLE();
625692f60a7Smrg	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
626692f60a7Smrg	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
627692f60a7Smrg	OUTREG(NEOREG_FGCOLOR, fg);
628692f60a7Smrg	OUTREG(NEOREG_BGCOLOR, bg);
629692f60a7Smrg	OUTREG(NEOREG_SRCSTARTOFF,
630692f60a7Smrg	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
631692f60a7Smrg	     + patternx) >> 3);
632692f60a7Smrg    }
633692f60a7Smrg}
634692f60a7Smrg
635692f60a7Smrg
636692f60a7Smrgstatic void
637692f60a7SmrgNeo2200SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
638692f60a7Smrg				    int patternx,
639692f60a7Smrg				    int patterny,
640692f60a7Smrg				    int x, int y,
641692f60a7Smrg				    int w, int h)
642692f60a7Smrg{
643692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
644692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
645692f60a7Smrg
646692f60a7Smrg    patterny &= 0x7;
647692f60a7Smrg
648692f60a7Smrg    WAIT_ENGINE_IDLE();
649692f60a7Smrg    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags |
650692f60a7Smrg	   (patterny << 20)       |
651692f60a7Smrg	   ((patternx << 10) & 0x1C00));
652692f60a7Smrg    OUTREG(NEOREG_SRCBITOFF, patternx);
653692f60a7Smrg    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
654692f60a7Smrg    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
655692f60a7Smrg}
656692f60a7Smrg#endif
6573f6d0e1dSmrg#endif
658