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