1/********************************************************************
2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas.
3
4                        All Rights Reserved
5
6Permission to use, copy, modify, distribute, and sell this software and
7its documentation for any purpose is hereby granted without fee,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of Precision Insight not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.  Precision Insight
13and its suppliers make no representations about the suitability of this
14software for any purpose.  It is provided "as is" without express or
15implied warranty.
16
17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24**********************************************************************/
25/*
26 * The original Precision Insight driver for
27 * XFree86 v.3.3 has been sponsored by Red Hat.
28 *
29 * Authors:
30 *   Jens Owen (jens@tungstengraphics.com)
31 *   Kevin E. Martin (kevin@precisioninsight.com)
32 *
33 * Port to Xfree86 v.4.0
34 *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include "xf86.h"
42#include "xf86_OSproc.h"
43#include "compiler.h"
44
45/* Drivers that use XAA need this */
46#include "xf86fbman.h"
47
48#include "miline.h"
49
50#include "neo.h"
51#include "neo_reg.h"
52#include "neo_macros.h"
53
54#ifdef HAVE_XAA_H
55static void Neo2200Sync(ScrnInfoPtr pScrn);
56static void Neo2200SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
57					      int ydir, int rop,
58					      unsigned int planemask,
59					      int trans_color);
60#ifdef NOT_BROKEN
61static void Neo2200SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
62						int srcY, int dstX, int dstY,
63						int w, int h);
64#else
65static void Neo2200SubsequentScreenToScreenCopyBroken(ScrnInfoPtr pScrn, int srcX,
66						int srcY, int dstX, int dstY,
67						int w, int h);
68#endif
69static void Neo2200SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
70				  unsigned int planemask);
71static void Neo2200SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
72					   int w, int h);
73static void Neo2200SetupForScanlineCPUToScreenColorExpandFill(
74                                                      ScrnInfoPtr pScrn,
75						      int fg, int bg,
76						      int rop,
77						unsigned int planemask);
78static void Neo2200SubsequentScanlineCPUToScreenColorExpandFill(
79                                                        ScrnInfoPtr pScrn,
80							int x, int y,
81							int w, int h,
82							int skipleft);
83static void Neo2200SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
84#if 0
85static void Neo2200SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
86					       int patternx,
87					       int patterny,
88					       int bg,
89					       int fg,
90					       int rop,
91					       unsigned int planemask);
92static void Neo2200SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
93						 int patternx,
94						 int patterny,
95						 int x, int y,
96						 int w, int h);
97#endif
98
99
100static unsigned int neo2200Rop[16] = {
101    0x000000,    /* 0x0000 - GXclear         */
102    0x080000,    /* 0x1000 - GXand           */
103    0x040000,    /* 0x0100 - GXandReverse    */
104    0x0c0000,    /* 0x1100 - GXcopy          */
105    0x020000,    /* 0x0010 - GXandInvert     */
106    0x0a0000,    /* 0x1010 - GXnoop          */
107    0x060000,    /* 0x0110 - GXxor           */
108    0x0e0000,    /* 0x1110 - GXor            */
109    0x010000,    /* 0x0001 - GXnor           */
110    0x090000,    /* 0x1001 - GXequiv         */
111    0x050000,    /* 0x0101 - GXinvert        */
112    0x0d0000,    /* 0x1101 - GXorReverse     */
113    0x030000,    /* 0x0011 - GXcopyInvert    */
114    0x0b0000,    /* 0x1011 - GXorInverted    */
115    0x070000,    /* 0x0111 - GXnand          */
116    0x0f0000     /* 0x1111 - GXset           */
117};
118
119#endif
120Bool
121Neo2200AccelInit(ScreenPtr pScreen)
122{
123#ifdef HAVE_XAA_H
124    XAAInfoRecPtr infoPtr;
125    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
126    NEOPtr nPtr = NEOPTR(pScrn);
127    NEOACLPtr nAcl = NEOACLPTR(pScrn);
128
129    nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
130    if(!infoPtr) return FALSE;
131
132    /*
133     * Set up the main acceleration flags.
134     */
135    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
136    if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
137#if 0
138    infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES;
139#endif
140    /* sync */
141    infoPtr->Sync = Neo2200Sync;
142
143    /* screen to screen copy */
144    infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
145    infoPtr->SetupForScreenToScreenCopy =
146	Neo2200SetupForScreenToScreenCopy;
147    infoPtr->SubsequentScreenToScreenCopy
148#ifdef NOT_BROKEN
149	= Neo2200SubsequentScreenToScreenCopy;
150#else
151	= Neo2200SubsequentScreenToScreenCopyBroken;
152#endif
153
154    /* solid filled rectangles */
155    infoPtr->SolidFillFlags = NO_PLANEMASK;
156    infoPtr->SetupForSolidFill =
157	Neo2200SetupForSolidFillRect;
158    infoPtr->SubsequentSolidFillRect =
159	Neo2200SubsequentSolidFillRect;
160
161    /* cpu to screen color expansion */
162    /*
163     * We do CPUToScreenColorExpand (ab)using the Scanline functions:
164     * the neo chipsets need byte padding however we can only do dword
165     * padding. Fortunately the graphics engine doesn't choke if we
166     * transfer up to 3 bytes more than it wants.
167     */
168
169    if (!nPtr->strangeLockups) {
170
171	infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
172#ifdef NEO_DO_CLIPPING
173						LEFT_EDGE_CLIPPING |
174#endif
175						SCANLINE_PAD_DWORD |
176						CPU_TRANSFER_PAD_DWORD |
177						BIT_ORDER_IN_BYTE_MSBFIRST );
178	infoPtr->ScanlineColorExpandBuffers =
179	    (unsigned char **)xnfalloc(sizeof(char*));
180	infoPtr->ScanlineColorExpandBuffers[0] =
181	    (unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
182	infoPtr->NumScanlineColorExpandBuffers = 1;
183	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
184	    Neo2200SetupForScanlineCPUToScreenColorExpandFill;
185	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
186	    Neo2200SubsequentScanlineCPUToScreenColorExpandFill;
187	infoPtr->SubsequentColorExpandScanline =
188	    Neo2200SubsequentColorExpandScanline;
189    }
190
191#if 0
192    /* 8x8 pattern fills */
193    infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
194	| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
195	|BIT_ORDER_IN_BYTE_MSBFIRST;
196
197    infoPtr->SetupForMono8x8PatternFill =
198	Neo2200SetupForMono8x8PatternFill;
199    infoPtr->SubsequentMono8x8PatternFillRect =
200	Neo2200SubsequentMono8x8PatternFill;
201#endif
202
203    /*
204     * Setup some global variables
205     */
206
207    /* Initialize for 8bpp or 15/16bpp support accelerated */
208    switch (pScrn->bitsPerPixel) {
209    case 8:
210	nAcl->BltModeFlags = NEO_MODE1_DEPTH8;
211        nAcl->PixelWidth = 1;
212	break;
213    case 15:
214    case 16:
215	nAcl->BltModeFlags = NEO_MODE1_DEPTH16;
216        nAcl->PixelWidth = 2;
217	break;
218    case 24:
219	if (nPtr->noAccelSet || nPtr->NeoChipset == NM2230
220	    || nPtr->NeoChipset == NM2360
221	    || nPtr->NeoChipset == NM2380) {
222	    nAcl->BltModeFlags = NEO_MODE1_DEPTH24;
223            nAcl->PixelWidth = 3;
224	} else
225	    return FALSE;
226	break;
227    default:
228	return FALSE;
229    }
230    nAcl->Pitch = pScrn->displayWidth * nAcl->PixelWidth;
231
232    /* Initialize for widths */
233    switch (pScrn->displayWidth) {
234    case 320:
235	nAcl->BltModeFlags |= NEO_MODE1_X_320;
236	break;
237    case 640:
238	nAcl->BltModeFlags |= NEO_MODE1_X_640;
239	break;
240    case 800:
241	nAcl->BltModeFlags |= NEO_MODE1_X_800;
242	break;
243    case 1024:
244	nAcl->BltModeFlags |= NEO_MODE1_X_1024;
245	break;
246    case 1152:
247	nAcl->BltModeFlags |= NEO_MODE1_X_1152;
248	break;
249    case 1280:
250	nAcl->BltModeFlags |= NEO_MODE1_X_1280;
251	break;
252    case 1600:
253	nAcl->BltModeFlags |= NEO_MODE1_X_1600;
254	break;
255    default:
256	return FALSE;
257    }
258
259    return(XAAInit(pScreen, infoPtr));
260#else
261    return FALSE;
262#endif
263}
264
265#ifdef HAVE_XAA_H
266static void
267Neo2200Sync(ScrnInfoPtr pScrn)
268{
269    NEOPtr nPtr = NEOPTR(pScrn);
270
271    WAIT_ENGINE_IDLE();
272}
273
274static void
275Neo2200SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
276				  int rop,
277				  unsigned int planemask,
278				  int trans_color)
279{
280    NEOPtr nPtr = NEOPTR(pScrn);
281    NEOACLPtr nAcl = NEOACLPTR(pScrn);
282
283    nAcl->tmpBltCntlFlags = (NEO_BC3_SKIP_MAPPING | neo2200Rop[rop]);
284    /* set blt control */
285    WAIT_ENGINE_IDLE();
286    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
287    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
288    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
289    OUTREG(NEOREG_PITCH, (nAcl->Pitch<<16)
290	   | (nAcl->Pitch & 0xffff));
291}
292
293#ifdef NOT_BROKEN
294static void
295Neo2200SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
296				    int srcX, int srcY,
297				    int dstX, int dstY,
298				    int w, int h)
299{
300    NEOPtr nPtr = NEOPTR(pScrn);
301    NEOACLPtr nAcl = NEOACLPTR(pScrn);
302
303    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
304	/* start with upper left corner */
305	WAIT_ENGINE_IDLE();
306#if 0
307	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
308#endif
309	OUTREG(NEOREG_SRCSTARTOFF,
310            (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
311	OUTREG(NEOREG_DSTSTARTOFF,
312            (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
313	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
314    }
315    else {
316	/* start with lower right corner */
317	WAIT_ENGINE_IDLE();
318#if 0
319	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
320				| NEO_BC0_X_DEC
321				| NEO_BC0_DST_Y_DEC
322				| NEO_BC0_SRC_Y_DEC));
323#endif
324	OUTREG(NEOREG_SRCSTARTOFF,
325            ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
326						 * nAcl->PixelWidth));
327	OUTREG(NEOREG_DSTSTARTOFF,
328            ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
329						 * nAcl->PixelWidth));
330	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
331    }
332}
333
334#else /* NOT_BROKEN */
335
336static void
337Neo2200SubsequentScreenToScreenCopyBroken(ScrnInfoPtr pScrn,
338					  int srcX, int srcY,
339					  int dstX, int dstY,
340					  int w, int h)
341{
342    NEOPtr nPtr = NEOPTR(pScrn);
343    NEOACLPtr nAcl = NEOACLPTR(pScrn);
344
345    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
346	if ((((dstX < 64) && ((srcX + w + 64) >= pScrn->displayWidth)) ||
347	    ((dstX == 0) && (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
348
349#define COPY_64 \
350	    OUTREG(NEOREG_SRCSTARTOFF,\
351		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));\
352	    OUTREG(NEOREG_DSTSTARTOFF,\
353		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));\
354	    OUTREG(NEOREG_XYEXT, (h<<16) | (64));
355#define COPY_W \
356	    OUTREG(NEOREG_SRCSTARTOFF,\
357		   (srcY * nAcl->Pitch) + (srcX1 * nAcl->PixelWidth));\
358	    OUTREG(NEOREG_DSTSTARTOFF,\
359		   (dstY * nAcl->Pitch) + (dstX1 * nAcl->PixelWidth));\
360	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
361
362	    int srcX1 = srcX + 64;
363	    int dstX1 = dstX + 64;
364	    w -= 64;
365	    /* start with upper left corner */
366	    WAIT_ENGINE_IDLE();
367	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
368	    if (srcX < dstX) {
369		COPY_W;
370	        WAIT_ENGINE_IDLE();
371	        COPY_64;
372	    } else {
373		COPY_64;
374	        WAIT_ENGINE_IDLE();
375		COPY_W;
376	    }
377#undef COPY_W
378#undef COPY_64
379	} else {
380	    /* start with upper left corner */
381	    WAIT_ENGINE_IDLE();
382	    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
383	    OUTREG(NEOREG_SRCSTARTOFF,
384		   (srcY * nAcl->Pitch) + (srcX * nAcl->PixelWidth));
385	    OUTREG(NEOREG_DSTSTARTOFF,
386		   (dstY * nAcl->Pitch) + (dstX * nAcl->PixelWidth));
387	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
388	}
389    } else {
390	if (((((dstX + w) > (pScrn->displayWidth - 64)) && (srcX == 0))
391	    || (((dstX + w + 64) >= pScrn->displayWidth)
392		&& (w > (pScrn->displayWidth - 64)))) && (w > 64)) {
393#define COPY_64 \
394	    OUTREG(NEOREG_SRCSTARTOFF, \
395		   ((srcY+h-1) * nAcl->Pitch) + ((srcX1+64-1)  \
396						 * nAcl->PixelWidth)); \
397	    OUTREG(NEOREG_DSTSTARTOFF, \
398		   ((dstY+h-1) * nAcl->Pitch) + ((dstX1+64-1) \
399						 * nAcl->PixelWidth)); \
400	    OUTREG(NEOREG_XYEXT, (h<<16) | (64 & 0xffff));
401#define COPY_W \
402	    OUTREG(NEOREG_SRCSTARTOFF, \
403		   ((srcY+h-1) * nAcl->Pitch) + ((srcX + w -1)  \
404						 * nAcl->PixelWidth)); \
405	    OUTREG(NEOREG_DSTSTARTOFF, \
406		   ((dstY+h-1) * nAcl->Pitch) + ((dstX + w -1) \
407						 * nAcl->PixelWidth)); \
408	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
409
410	    int srcX1, dstX1;
411
412	    w -= 64;
413	    srcX1 = srcX + w;
414	    dstX1 = dstX + w;
415	    /* start with lower right corner */
416	    WAIT_ENGINE_IDLE();
417	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
418				    | NEO_BC0_X_DEC
419				    | NEO_BC0_DST_Y_DEC
420				    | NEO_BC0_SRC_Y_DEC));
421	    if (srcX < dstX) {
422	      COPY_64;
423	      WAIT_ENGINE_IDLE();
424	      COPY_W;
425	    } else {
426	      COPY_W;
427	      WAIT_ENGINE_IDLE();
428	      COPY_64;
429	    }
430#undef COPY_W
431#undef COPY_64
432	} else {
433	    /* start with lower right corner */
434	    WAIT_ENGINE_IDLE();
435	    OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags
436				    | NEO_BC0_X_DEC
437				    | NEO_BC0_DST_Y_DEC
438				    | NEO_BC0_SRC_Y_DEC));
439	    OUTREG(NEOREG_SRCSTARTOFF,
440		   ((srcY+h-1) * nAcl->Pitch) + ((srcX+w-1)
441						 * nAcl->PixelWidth));
442	    OUTREG(NEOREG_DSTSTARTOFF,
443		   ((dstY+h-1) * nAcl->Pitch) + ((dstX+w-1)
444						 * nAcl->PixelWidth));
445	    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
446	}
447    }
448}
449
450#endif /* NOT_BROKEN */
451
452static void
453Neo2200SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
454			     unsigned int planemask)
455{
456    NEOPtr nPtr = NEOPTR(pScrn);
457    NEOACLPtr nAcl = NEOACLPTR(pScrn);
458
459    WAIT_ENGINE_IDLE();
460
461    /* set blt control */
462    /*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
463    OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
464    OUTREG(NEOREG_BLTCNTL, NEO_BC0_SRC_IS_FG    |
465                           NEO_BC3_SKIP_MAPPING |
466                           NEO_BC3_DST_XY_ADDR  |
467                           NEO_BC3_SRC_XY_ADDR  | neo2200Rop[rop]);
468
469    /* set foreground color */
470    OUTREG(NEOREG_FGCOLOR, color);
471}
472
473
474static void
475Neo2200SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
476{
477    NEOPtr nPtr = NEOPTR(pScrn);
478
479    WAIT_ENGINE_IDLE();
480    OUTREG(NEOREG_DSTSTARTOFF, (y <<16) | (x & 0xffff));
481    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
482}
483
484static void
485Neo2200SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
486 				      int fg, int bg,
487				      int rop,
488				      unsigned int planemask)
489{
490    NEOPtr nPtr = NEOPTR(pScrn);
491    NEOACLPtr nAcl = NEOACLPTR(pScrn);
492
493    if (bg == -1) {
494	/* transparent setup */
495	nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
496					 NEO_BC0_SRC_MONO     |
497					 NEO_BC0_SRC_TRANS    |
498					 NEO_BC3_SKIP_MAPPING |
499					 NEO_BC3_DST_XY_ADDR  |
500#ifdef NEO_DO_CLIPPING
501				         NEO_BC3_CLIP_ON      |
502#endif
503				         neo2200Rop[rop]);
504
505	WAIT_ENGINE_IDLE();
506	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
507	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
508	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
509	OUTREG(NEOREG_FGCOLOR, fg);
510    }
511    else {
512	/* opaque setup */
513        nAcl->tmpBltCntlFlags = ( NEO_BC0_SYS_TO_VID   |
514					 NEO_BC0_SRC_MONO     |
515					 NEO_BC3_SKIP_MAPPING |
516					 NEO_BC3_DST_XY_ADDR  |
517#ifdef NEO_DO_CLIPPING
518 				         NEO_BC3_CLIP_ON      |
519#endif
520					 neo2200Rop[rop]);
521
522	WAIT_ENGINE_IDLE();
523	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
524	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
525	OUTREG(NEOREG_FGCOLOR, fg);
526	OUTREG(NEOREG_BGCOLOR, bg);
527    }
528}
529
530
531static void
532Neo2200SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
533					int x, int y,
534					int w, int h,
535					int skipleft)
536{
537    NEOPtr nPtr = NEOPTR(pScrn);
538    NEOACLPtr nAcl = NEOACLPTR(pScrn);
539
540#ifdef NEO_DO_CLIPPING
541        w = (w + 31) & ~31;
542#else
543    nAcl->CPUToScreenColorExpandFill_x = x;
544    nAcl->CPUToScreenColorExpandFill_y = y;
545    nAcl->CPUToScreenColorExpandFill_w = w;
546    nAcl->CPUToScreenColorExpandFill_h = h;
547    nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
548#endif
549    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
550	   | ((skipleft << 2) & 0x1C));
551#ifdef NEO_DO_CLIPPING
552    OUTREG(NEOREG_CLIPLT, (y << 16) | (x + skipleft));
553    OUTREG(NEOREG_CLIPRB, ((y + h) << 16) | (x + w));
554#endif
555    OUTREG(NEOREG_SRCSTARTOFF, 0);
556    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
557#ifdef NEO_DO_CLIPPING
558    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
559#else
560    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
561#endif
562}
563
564static void
565Neo2200SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
566{
567    NEOPtr nPtr = NEOPTR(pScrn);
568    NEOACLPtr nAcl = NEOACLPTR(pScrn);
569
570#ifdef NEO_DO_CLIPPING
571    /* Should I be waiting for fifo slots to prevent retries ?
572       How do I do that on this engine ? */
573#else
574    if (!(--nAcl->CPUToScreenColorExpandFill_h))
575	return;
576
577    WAIT_ENGINE_IDLE();
578    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags
579	   | ((nAcl->CPUToScreenColorExpandFill_skipleft << 2) & 0x1C));
580    OUTREG(NEOREG_SRCSTARTOFF, 0);
581    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
582	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
583    OUTREG(NEOREG_XYEXT, (1<<16)
584	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
585#endif
586}
587
588#if 0
589static void
590Neo2200SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
591				     int patternx,
592				     int patterny,
593				     int fg, int bg,
594				     int rop, unsigned int planemask)
595{
596    NEOPtr nPtr = NEOPTR(pScrn);
597    NEOACLPtr nAcl = NEOACLPTR(pScrn);
598
599    if (bg == -1) {
600	/* transparent setup */
601	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
602					 NEO_BC0_FILL_PAT     |
603					 NEO_BC0_SRC_TRANS    |
604					 NEO_BC3_SKIP_MAPPING |
605					 NEO_BC3_DST_XY_ADDR  |
606					 neo2200Rop[rop]);
607
608	WAIT_ENGINE_IDLE();
609	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
610	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
611	OUTREG(NEOREG_FGCOLOR, fg);
612	OUTREG(NEOREG_SRCSTARTOFF,
613	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
614	     + patternx) >> 3);
615    }
616    else {
617	/* opaque setup */
618	nAcl->tmpBltCntlFlags = ( NEO_BC0_SRC_MONO     |
619					 NEO_BC0_FILL_PAT     |
620					 NEO_BC3_SKIP_MAPPING |
621					 NEO_BC3_DST_XY_ADDR  |
622					 neo2200Rop[rop]);
623
624	WAIT_ENGINE_IDLE();
625	/*OUTREG16(NEOREG_BLTMODE, nAcl->BltModeFlags);*/
626	OUTREG(NEOREG_BLTSTAT, nAcl->BltModeFlags << 16);
627	OUTREG(NEOREG_FGCOLOR, fg);
628	OUTREG(NEOREG_BGCOLOR, bg);
629	OUTREG(NEOREG_SRCSTARTOFF,
630	    (patterny * pScrn->displayWidth * pScrn->bitsPerPixel
631	     + patternx) >> 3);
632    }
633}
634
635
636static void
637Neo2200SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
638				    int patternx,
639				    int patterny,
640				    int x, int y,
641				    int w, int h)
642{
643    NEOPtr nPtr = NEOPTR(pScrn);
644    NEOACLPtr nAcl = NEOACLPTR(pScrn);
645
646    patterny &= 0x7;
647
648    WAIT_ENGINE_IDLE();
649    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags |
650	   (patterny << 20)       |
651	   ((patternx << 10) & 0x1C00));
652    OUTREG(NEOREG_SRCBITOFF, patternx);
653    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
654    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
655}
656#endif
657#endif
658