neo_2090.c revision 692f60a7
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/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c,v 1.6 2002/04/04 14:05:44 eich Exp $ */
26
27/*
28 * The original Precision Insight driver for
29 * XFree86 v.3.3 has been sponsored by Red Hat.
30 *
31 * Authors:
32 *   Jens Owen (jens@tungstengraphics.com)
33 *   Kevin E. Martin (kevin@precisioninsight.com)
34 *
35 * Port to Xfree86 v.4.0
36 *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
37 */
38
39#ifdef HAVE_CONFIG_H
40#include "config.h"
41#endif
42
43#include "xf86.h"
44#include "xf86_OSproc.h"
45#include "compiler.h"
46#include "xf86PciInfo.h"
47
48/* Drivers that use XAA need this */
49#include "xf86fbman.h"
50
51#include "miline.h"
52
53#include "neo.h"
54#include "neo_reg.h"
55#include "neo_macros.h"
56
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
100Bool
101Neo2090AccelInit(ScreenPtr pScreen)
102{
103    XAAInfoRecPtr infoPtr;
104    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
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 accellerated */
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}
203
204static void
205Neo2090Sync(ScrnInfoPtr pScrn)
206{
207    NEOPtr nPtr = NEOPTR(pScrn);
208
209    WAIT_ENGINE_IDLE();
210}
211
212static void
213Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
214				  int rop,
215				  unsigned int planemask,
216				  int trans_color)
217{
218    NEOPtr nPtr = NEOPTR(pScrn);
219    NEOACLPtr nAcl = NEOACLPTR(pScrn);
220
221    nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags  |
222		              NEO_BC3_SKIP_MAPPING |
223		              NEO_BC3_DST_XY_ADDR  |
224		              NEO_BC3_SRC_XY_ADDR  | neo2090Rop[rop]);
225
226    /* set blt control */
227    WAIT_FIFO(2);
228    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
229}
230
231static void
232Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
233				    int srcX, int srcY,
234				    int dstX, int dstY,
235				    int w, int h)
236{
237    NEOPtr nPtr = NEOPTR(pScrn);
238    NEOACLPtr nAcl = NEOACLPTR(pScrn);
239
240    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
241	/* start with upper left corner */
242	WAIT_FIFO(4);
243	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
244	OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff));
245	OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff));
246	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
247    }
248    else {
249	/* start with lower right corner */
250	WAIT_FIFO(4);
251	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC
252                                                       | NEO_BC0_DST_Y_DEC
253                                                       | NEO_BC0_SRC_Y_DEC));
254	OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff));
255	OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff));
256	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
257    }
258}
259
260
261static void
262Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
263			     unsigned int planemask)
264{
265    NEOPtr nPtr = NEOPTR(pScrn);
266    NEOACLPtr nAcl = NEOACLPTR(pScrn);
267
268    WAIT_FIFO(2);
269
270    /* set blt control */
271    OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
272                           NEO_BC0_SRC_IS_FG    |
273                           NEO_BC3_SKIP_MAPPING |
274                           NEO_BC3_DST_XY_ADDR  |
275                           NEO_BC3_SRC_XY_ADDR  | neo2090Rop[rop]);
276
277    /* set foreground color */
278    OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt));
279}
280
281
282static void
283Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
284{
285    NEOPtr nPtr = NEOPTR(pScrn);
286
287    WAIT_FIFO(2);
288    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
289    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
290
291}
292
293static void
294Neo2093SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
295				      int fg, int bg,
296				      int rop,
297				      unsigned int planemask)
298{
299    NEOPtr nPtr = NEOPTR(pScrn);
300    NEOACLPtr nAcl = NEOACLPTR(pScrn);
301
302    if (bg == -1) {
303	/* transparent setup */
304	WAIT_FIFO(2);
305	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
306			       NEO_BC0_SYS_TO_VID   |
307			       NEO_BC0_SRC_MONO     |
308			       NEO_BC0_SRC_TRANS    |
309			       NEO_BC3_SKIP_MAPPING |
310			       NEO_BC3_DST_XY_ADDR  | neo2090Rop[rop]);
311
312	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
313    }
314    else {
315	/* opaque setup */
316	WAIT_FIFO(3);
317	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
318			       NEO_BC0_SYS_TO_VID   |
319			       NEO_BC0_SRC_MONO     |
320			       NEO_BC3_SKIP_MAPPING |
321			       NEO_BC3_DST_XY_ADDR  | neo2090Rop[rop]);
322
323	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
324	OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt));
325    }
326}
327
328static void
329Neo2093SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
330					int x, int y,
331					int w, int h,
332					int skipleft)
333{
334    NEOPtr nPtr = NEOPTR(pScrn);
335    NEOACLPtr nAcl = NEOACLPTR(pScrn);
336
337    nAcl->CPUToScreenColorExpandFill_x = x;
338    nAcl->CPUToScreenColorExpandFill_y = y;
339    nAcl->CPUToScreenColorExpandFill_w = w;
340    nAcl->CPUToScreenColorExpandFill_h = h;
341    nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
342
343    WAIT_FIFO(4);
344    OUTREG(NEOREG_SRCBITOFF, skipleft);
345    OUTREG(NEOREG_SRCSTARTOFF, 0);
346    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
347    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
348}
349
350static void
351Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
352{
353    NEOPtr nPtr = NEOPTR(pScrn);
354    NEOACLPtr nAcl = NEOACLPTR(pScrn);
355
356    if (!(--nAcl->CPUToScreenColorExpandFill_h))
357	return;
358
359    WAIT_FIFO(4);
360    OUTREG(NEOREG_SRCBITOFF, nAcl->CPUToScreenColorExpandFill_skipleft);
361    OUTREG(NEOREG_SRCSTARTOFF, 0);
362    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
363	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
364    OUTREG(NEOREG_XYEXT, (1<<16)
365	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
366}
367
368
369
370