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/*
27 * The original Precision Insight driver for
28 * XFree86 v.3.3 has been sponsored by Red Hat.
29 *
30 * Authors:
31 *   Jens Owen (jens@tungstengraphics.com)
32 *   Kevin E. Martin (kevin@precisioninsight.com)
33 *
34 * Port to Xfree86 v.4.0
35 *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include "xf86.h"
43#include "xf86_OSproc.h"
44#include "compiler.h"
45
46/* Drivers that use XAA need this */
47#include "xf86fbman.h"
48
49#include "miline.h"
50
51#include "neo.h"
52#include "neo_reg.h"
53#include "neo_macros.h"
54
55#ifdef HAVE_XAA_H
56static unsigned int neo2090Rop[16] = {
57    0x000000,    /* 0x0000 - GXclear         */
58    0x080000,    /* 0x1000 - GXand           */
59    0x040000,    /* 0x0100 - GXandReverse    */
60    0x0c0000,    /* 0x1100 - GXcopy          */
61    0x020000,    /* 0x0010 - GXandInvert     */
62    0x0a0000,    /* 0x1010 - GXnoop          */
63    0x060000,    /* 0x0110 - GXxor           */
64    0x0e0000,    /* 0x1110 - GXor            */
65    0x010000,    /* 0x0001 - GXnor           */
66    0x090000,    /* 0x1001 - GXequiv         */
67    0x050000,    /* 0x0101 - GXinvert        */
68    0x0d0000,    /* 0x1101 - GXorReverse     */
69    0x030000,    /* 0x0011 - GXcopyInvert    */
70    0x0b0000,    /* 0x1011 - GXorInverted    */
71    0x070000,    /* 0x0111 - GXnand          */
72    0x0f0000     /* 0x1111 - GXset           */
73};
74
75static void Neo2090Sync(ScrnInfoPtr pScrn);
76static void Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
77					      int ydir, int rop,
78					      unsigned int planemask,
79					      int trans_color);
80static void Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
81						int srcY, int dstX, int dstY,
82						int w, int h);
83static void Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
84				  unsigned int planemask);
85static void Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
86					   int w, int h);
87static void Neo2093SetupForScanlineCPUToScreenColorExpandFill(
88                                                      ScrnInfoPtr pScrn,
89						      int fg, int bg,
90						      int rop,
91						unsigned int planemask);
92static void Neo2093SubsequentScanlineCPUToScreenColorExpandFill(
93                                                      ScrnInfoPtr pScrn,
94							int x, int y,
95							int w, int h,
96							int skipleft);
97static void Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
98#endif
99Bool
100Neo2090AccelInit(ScreenPtr pScreen)
101{
102#ifdef HAVE_XAA_H
103    XAAInfoRecPtr infoPtr;
104    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
105    NEOPtr nPtr = NEOPTR(pScrn);
106    NEOACLPtr nAcl = NEOACLPTR(pScrn);
107
108    nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
109    if(!infoPtr) return FALSE;
110
111    /*
112     * Set up the main acceleration flags.
113     */
114    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
115    if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
116#if 0
117    infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES;
118#endif
119    /* sync */
120    infoPtr->Sync = Neo2090Sync;
121
122    /* screen to screen copy */
123    infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
124    infoPtr->SetupForScreenToScreenCopy =
125	Neo2090SetupForScreenToScreenCopy;
126    infoPtr->SubsequentScreenToScreenCopy =
127	Neo2090SubsequentScreenToScreenCopy;
128
129    /* solid filled rectangles */
130    infoPtr->SolidFillFlags = NO_PLANEMASK;
131    infoPtr->SetupForSolidFill =
132	Neo2090SetupForSolidFillRect;
133    infoPtr->SubsequentSolidFillRect =
134	Neo2090SubsequentSolidFillRect;
135
136    if (nPtr->NeoChipset == PCI_CHIP_NM2093 && !nPtr->strangeLockups) {
137	/*
138	 * We do CPUToScreenColorExpand (ab)using the Scanline functions:
139	 * the neo chipsets need byte padding however we can only do dword
140	 * padding. Fortunately the graphics engine doesn't choke if we
141	 * transfer up to 3 bytes more than it wants.
142	 */
143
144	/* cpu to screen color expansion */
145	infoPtr->ScanlineColorExpandBuffers =
146	    (unsigned char **)xnfalloc(sizeof(char*));
147	infoPtr->ScanlineColorExpandBuffers[0] =
148	    (unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
149	infoPtr->NumScanlineColorExpandBuffers = 1;
150	infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
151						     SCANLINE_PAD_DWORD |
152						     CPU_TRANSFER_PAD_DWORD |
153						BIT_ORDER_IN_BYTE_MSBFIRST );
154
155	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
156	    Neo2093SetupForScanlineCPUToScreenColorExpandFill;
157	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
158	    Neo2093SubsequentScanlineCPUToScreenColorExpandFill;
159	infoPtr->SubsequentColorExpandScanline =
160	    Neo2093SubsequentColorExpandScanline;
161    }
162
163    /*
164     * Setup some global variables
165     */
166    nAcl->ColorShiftAmt = 0;
167
168    /* Initialize for 8bpp or 15/16bpp support accelerated */
169    switch (pScrn->bitsPerPixel) {
170    case 8:
171	nAcl->BltCntlFlags = NEO_BC1_DEPTH8;
172	nAcl->ColorShiftAmt = 8;
173	break;
174    case 15:
175    case 16:
176	nAcl->BltCntlFlags = NEO_BC1_DEPTH16;
177	nAcl->ColorShiftAmt = 0;
178	break;
179    case 24:
180    default:
181	return FALSE;
182    }
183
184    /* Initialize for widths */
185    switch (pScrn->displayWidth) {
186    case 640:
187	nAcl->BltCntlFlags |= NEO_BC1_X_640;
188	break;
189    case 800:
190	nAcl->BltCntlFlags |= NEO_BC1_X_800;
191	break;
192    case 1024:
193	nAcl->BltCntlFlags |= NEO_BC1_X_1024;
194	break;
195    default:
196	return FALSE;
197    }
198
199    nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN;
200
201    return(XAAInit(pScreen, infoPtr));
202#else
203    return FALSE;
204#endif
205}
206
207#ifdef HAVE_XAA_H
208static void
209Neo2090Sync(ScrnInfoPtr pScrn)
210{
211    NEOPtr nPtr = NEOPTR(pScrn);
212
213    WAIT_ENGINE_IDLE();
214}
215
216static void
217Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
218				  int rop,
219				  unsigned int planemask,
220				  int trans_color)
221{
222    NEOPtr nPtr = NEOPTR(pScrn);
223    NEOACLPtr nAcl = NEOACLPTR(pScrn);
224
225    nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags  |
226		              NEO_BC3_SKIP_MAPPING |
227		              NEO_BC3_DST_XY_ADDR  |
228		              NEO_BC3_SRC_XY_ADDR  | neo2090Rop[rop]);
229
230    /* set blt control */
231    WAIT_FIFO(2);
232    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
233}
234
235static void
236Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
237				    int srcX, int srcY,
238				    int dstX, int dstY,
239				    int w, int h)
240{
241    NEOPtr nPtr = NEOPTR(pScrn);
242    NEOACLPtr nAcl = NEOACLPTR(pScrn);
243
244    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
245	/* start with upper left corner */
246	WAIT_FIFO(4);
247	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
248	OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff));
249	OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff));
250	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
251    }
252    else {
253	/* start with lower right corner */
254	WAIT_FIFO(4);
255	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC
256                                                       | NEO_BC0_DST_Y_DEC
257                                                       | NEO_BC0_SRC_Y_DEC));
258	OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff));
259	OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff));
260	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
261    }
262}
263
264
265static void
266Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
267			     unsigned int planemask)
268{
269    NEOPtr nPtr = NEOPTR(pScrn);
270    NEOACLPtr nAcl = NEOACLPTR(pScrn);
271
272    WAIT_FIFO(2);
273
274    /* set blt control */
275    OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
276                           NEO_BC0_SRC_IS_FG    |
277                           NEO_BC3_SKIP_MAPPING |
278                           NEO_BC3_DST_XY_ADDR  |
279                           NEO_BC3_SRC_XY_ADDR  | neo2090Rop[rop]);
280
281    /* set foreground color */
282    OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt));
283}
284
285
286static void
287Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
288{
289    NEOPtr nPtr = NEOPTR(pScrn);
290
291    WAIT_FIFO(2);
292    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
293    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
294
295}
296
297static void
298Neo2093SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
299				      int fg, int bg,
300				      int rop,
301				      unsigned int planemask)
302{
303    NEOPtr nPtr = NEOPTR(pScrn);
304    NEOACLPtr nAcl = NEOACLPTR(pScrn);
305
306    if (bg == -1) {
307	/* transparent setup */
308	WAIT_FIFO(2);
309	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
310			       NEO_BC0_SYS_TO_VID   |
311			       NEO_BC0_SRC_MONO     |
312			       NEO_BC0_SRC_TRANS    |
313			       NEO_BC3_SKIP_MAPPING |
314			       NEO_BC3_DST_XY_ADDR  | neo2090Rop[rop]);
315
316	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
317    }
318    else {
319	/* opaque setup */
320	WAIT_FIFO(3);
321	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
322			       NEO_BC0_SYS_TO_VID   |
323			       NEO_BC0_SRC_MONO     |
324			       NEO_BC3_SKIP_MAPPING |
325			       NEO_BC3_DST_XY_ADDR  | neo2090Rop[rop]);
326
327	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
328	OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt));
329    }
330}
331
332static void
333Neo2093SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
334					int x, int y,
335					int w, int h,
336					int skipleft)
337{
338    NEOPtr nPtr = NEOPTR(pScrn);
339    NEOACLPtr nAcl = NEOACLPTR(pScrn);
340
341    nAcl->CPUToScreenColorExpandFill_x = x;
342    nAcl->CPUToScreenColorExpandFill_y = y;
343    nAcl->CPUToScreenColorExpandFill_w = w;
344    nAcl->CPUToScreenColorExpandFill_h = h;
345    nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
346
347    WAIT_FIFO(4);
348    OUTREG(NEOREG_SRCBITOFF, skipleft);
349    OUTREG(NEOREG_SRCSTARTOFF, 0);
350    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
351    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
352}
353
354static void
355Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
356{
357    NEOPtr nPtr = NEOPTR(pScrn);
358    NEOACLPtr nAcl = NEOACLPTR(pScrn);
359
360    if (!(--nAcl->CPUToScreenColorExpandFill_h))
361	return;
362
363    WAIT_FIFO(4);
364    OUTREG(NEOREG_SRCBITOFF, nAcl->CPUToScreenColorExpandFill_skipleft);
365    OUTREG(NEOREG_SRCSTARTOFF, 0);
366    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
367	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
368    OUTREG(NEOREG_XYEXT, (1<<16)
369	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
370}
371#endif
372