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/*
39 * This module supports acceleration for 2097 and 2160.
40 */
41
42#ifdef HAVE_CONFIG_H
43#include "config.h"
44#endif
45
46#include "xf86.h"
47#include "xf86_OSproc.h"
48#include "compiler.h"
49
50/* Drivers that use XAA need this */
51#include "xf86fbman.h"
52
53#include "miline.h"
54
55#include "neo.h"
56#include "neo_reg.h"
57#include "neo_macros.h"
58
59#ifdef HAVE_XAA_H
60static void Neo2097Sync(ScrnInfoPtr pScrn);
61static void Neo2097SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
62					      int ydir, int rop,
63					      unsigned int planemask,
64					      int trans_color);
65static void Neo2097SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
66						int srcY, int dstX, int dstY,
67						int w, int h);
68static void Neo2097SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
69				  unsigned int planemask);
70static void Neo2097SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
71					   int w, int h);
72static void Neo2097SetupScanlineForCPUToScreenColorExpandFill(
73                                                      ScrnInfoPtr pScrn,
74						      int fg, int bg,
75						      int rop,
76						unsigned int planemask);
77static void Neo2097SubsequentScanlineCPUToScreenColorExpandFill(
78                                                        ScrnInfoPtr pScrn,
79							int x, int y,
80							int w, int h,
81							int skipleft);
82static void Neo2097SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
83#if 0
84static void Neo2097SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
85					      int patternx,
86					      int patterny,
87					      int fg, int bg,
88					      int rop, unsigned int planemask);
89static void Neo2097SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
90						int patternx,
91						int patterny,
92						int x, int y,
93						int w, int h);
94#endif
95static void Neo2097SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
96                                unsigned int planemask,
97                                int transparency_color, int bpp, int depth);
98static void Neo2097SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
99                                int x, int y, int w, int h, int skipleft);
100static void Neo2097SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int num);
101
102
103
104static unsigned int neo2097Rop[16] = {
105    0x000000,    /* 0x0000 - GXclear         */
106    0x080000,    /* 0x1000 - GXand           */
107    0x040000,    /* 0x0100 - GXandReverse    */
108    0x0c0000,    /* 0x1100 - GXcopy          */
109    0x020000,    /* 0x0010 - GXandInvert     */
110    0x0a0000,    /* 0x1010 - GXnoop          */
111    0x060000,    /* 0x0110 - GXxor           */
112    0x0e0000,    /* 0x1110 - GXor            */
113    0x010000,    /* 0x0001 - GXnor           */
114    0x090000,    /* 0x1001 - GXequiv         */
115    0x050000,    /* 0x0101 - GXinvert        */
116    0x0d0000,    /* 0x1101 - GXorReverse     */
117    0x030000,    /* 0x0011 - GXcopyInvert    */
118    0x0b0000,    /* 0x1011 - GXorInverted    */
119    0x070000,    /* 0x0111 - GXnand          */
120    0x0f0000     /* 0x1111 - GXset           */
121};
122#endif
123
124Bool
125Neo2097AccelInit(ScreenPtr pScreen)
126{
127#ifdef HAVE_XAA_H
128    XAAInfoRecPtr infoPtr;
129    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
130    NEOPtr nPtr = NEOPTR(pScrn);
131    NEOACLPtr nAcl = NEOACLPTR(pScrn);
132
133    nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
134    if(!infoPtr) return FALSE;
135
136    /*
137     * Set up the main acceleration flags.
138     */
139    infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
140    if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
141
142    infoPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES;
143
144    /* sync */
145    infoPtr->Sync = Neo2097Sync;
146
147    /* screen to screen copy */
148    infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
149    infoPtr->SetupForScreenToScreenCopy =
150	Neo2097SetupForScreenToScreenCopy;
151    infoPtr->SubsequentScreenToScreenCopy =
152	Neo2097SubsequentScreenToScreenCopy;
153
154    /* solid filled rectangles */
155    infoPtr->SolidFillFlags = NO_PLANEMASK;
156    infoPtr->SetupForSolidFill =
157	Neo2097SetupForSolidFillRect;
158    infoPtr->SubsequentSolidFillRect =
159	Neo2097SubsequentSolidFillRect;
160
161    if (!nPtr->strangeLockups) {
162	/* cpu to screen color expansion */
163	/*
164	 * We do CPUToScreenColorExpand (ab)using the Scanline functions:
165	 * the neo chipsets need byte padding however we can only do dword
166	 * padding. Fortunately the graphics engine doesn't choke if we
167	 * transfer up to 3 bytes more than it wants.
168	 */
169	infoPtr->ScanlineColorExpandBuffers =
170	    (unsigned char **)xnfalloc(sizeof(char*));
171	infoPtr->ScanlineColorExpandBuffers[0] = (unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
172	infoPtr->NumScanlineColorExpandBuffers = 1;
173	infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
174#ifdef NEO_DO_CLIPPING
175						LEFT_EDGE_CLIPPING |
176#endif
177						CPU_TRANSFER_PAD_DWORD |
178						BIT_ORDER_IN_BYTE_MSBFIRST );
179	infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
180	    Neo2097SetupScanlineForCPUToScreenColorExpandFill;
181	infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
182	    Neo2097SubsequentScanlineCPUToScreenColorExpandFill;
183	infoPtr->SubsequentColorExpandScanline =
184	    Neo2097SubsequentColorExpandScanline;
185    }
186
187#if 0
188    /* 8x8 pattern fills */
189    infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
190	| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
191	| BIT_ORDER_IN_BYTE_MSBFIRST;
192
193    infoPtr->SetupForMono8x8PatternFill =
194	Neo2097SetupForMono8x8PatternFill;
195    infoPtr->SubsequentMono8x8PatternFillRect =
196	Neo2097SubsequentMono8x8PatternFill;
197#endif
198
199    if (!nPtr->strangeLockups) {
200	/* image writes */
201	infoPtr->ScanlineImageWriteFlags =  ( CPU_TRANSFER_PAD_DWORD |
202					      SCANLINE_PAD_DWORD |
203					      NO_TRANSPARENCY |
204					      NO_PLANEMASK );
205
206	infoPtr->SetupForScanlineImageWrite =
207	    Neo2097SetupForScanlineImageWrite;
208	infoPtr->SubsequentScanlineImageWriteRect =
209	    Neo2097SubsequentScanlineImageWriteRect;
210	infoPtr->SubsequentImageWriteScanline =
211	    Neo2097SubsequentImageWriteScanline;
212	infoPtr->NumScanlineImageWriteBuffers = 1;
213	infoPtr->ScanlineImageWriteBuffers =
214	    infoPtr->ScanlineColorExpandBuffers;
215    }
216
217    /*
218     * Setup some global variables
219     */
220    nAcl->ColorShiftAmt = 0;
221
222    /* Initialize for 8bpp or 15/16bpp support accelerated */
223    switch (pScrn->bitsPerPixel) {
224    case 8:
225	nAcl->BltCntlFlags = NEO_BC1_DEPTH8;
226	nAcl->ColorShiftAmt = 8;
227	break;
228    case 15:
229    case 16:
230	nAcl->BltCntlFlags = NEO_BC1_DEPTH16;
231	nAcl->ColorShiftAmt = 0;
232	break;
233    case 24:
234    default:
235	return FALSE;
236    }
237
238    /* Initialize for widths */
239    switch (pScrn->displayWidth) {
240    case 640:
241	nAcl->BltCntlFlags |= NEO_BC1_X_640;
242	break;
243    case 800:
244	nAcl->BltCntlFlags |= NEO_BC1_X_800;
245	break;
246    case 1024:
247	nAcl->BltCntlFlags |= NEO_BC1_X_1024;
248	break;
249    default:
250	return FALSE;
251    }
252
253    return(XAAInit(pScreen, infoPtr));
254#else
255    return FALSE;
256#endif
257}
258
259#ifdef HAVE_XAA_H
260static void
261Neo2097Sync(ScrnInfoPtr pScrn)
262{
263    NEOPtr nPtr = NEOPTR(pScrn);
264
265    WAIT_ENGINE_IDLE();
266}
267
268static void
269Neo2097SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
270				  int rop,
271				  unsigned int planemask,
272				  int trans_color)
273{
274    NEOACLPtr nAcl = NEOACLPTR(pScrn);
275
276    nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags  |
277			     NEO_BC3_SKIP_MAPPING |
278			     NEO_BC3_DST_XY_ADDR  |
279			     NEO_BC3_SRC_XY_ADDR  | neo2097Rop[rop]);
280}
281
282static void
283Neo2097SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
284				    int srcX, int srcY,
285				    int dstX, int dstY,
286				    int w, int h)
287{
288    NEOPtr nPtr = NEOPTR(pScrn);
289    NEOACLPtr nAcl = NEOACLPTR(pScrn);
290
291    if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
292	/* start with upper left corner */
293	WAIT_ENGINE_IDLE();
294	OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
295	OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff));
296	OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff));
297	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
298    }
299    else {
300	/* start with lower right corner */
301	WAIT_ENGINE_IDLE();
302	OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC
303                                                       | NEO_BC0_DST_Y_DEC
304                                                       | NEO_BC0_SRC_Y_DEC));
305	OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff));
306	OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff));
307	OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
308    }
309}
310
311
312static void
313Neo2097SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
314			     unsigned int planemask)
315{
316    NEOPtr nPtr = NEOPTR(pScrn);
317    NEOACLPtr nAcl = NEOACLPTR(pScrn);
318
319    WAIT_ENGINE_IDLE();
320
321    /* set blt control */
322    OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
323                           NEO_BC0_SRC_IS_FG    |
324                           NEO_BC3_SKIP_MAPPING |
325                           NEO_BC3_DST_XY_ADDR  |
326                           NEO_BC3_SRC_XY_ADDR  | neo2097Rop[rop]);
327
328    /* set foreground color */
329    OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt));
330}
331
332
333static void
334Neo2097SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
335{
336    NEOPtr nPtr = NEOPTR(pScrn);
337
338    WAIT_ENGINE_IDLE();
339    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
340    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
341}
342
343static void
344Neo2097SetupScanlineForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
345						  int fg, int bg,
346						  int rop,
347						  unsigned int planemask)
348{
349    NEOPtr nPtr = NEOPTR(pScrn);
350    NEOACLPtr nAcl = NEOACLPTR(pScrn);
351
352    if (bg == -1) {
353	/* transparent setup */
354	WAIT_ENGINE_IDLE();
355#ifdef NEO_DO_CLIPPING
356	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
357			       NEO_BC0_SYS_TO_VID   |
358			       NEO_BC0_SRC_MONO     |
359			       NEO_BC0_SRC_TRANS    |
360			       NEO_BC3_SKIP_MAPPING |
361	                       NEO_BC3_CLIP_ON      |
362	                       NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
363#else
364	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
365			       NEO_BC0_SYS_TO_VID   |
366			       NEO_BC0_SRC_MONO     |
367			       NEO_BC0_SRC_TRANS    |
368			       NEO_BC3_SKIP_MAPPING |
369	                       NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
370#endif
371
372	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
373    }
374    else {
375	/* opaque setup */
376	WAIT_ENGINE_IDLE();
377#ifdef NEO_DO_CLIPPING
378	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
379			       NEO_BC0_SYS_TO_VID   |
380			       NEO_BC0_SRC_MONO     |
381			       NEO_BC3_SKIP_MAPPING |
382	                       NEO_BC3_CLIP_ON      |
383			       NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
384#else
385	OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags  |
386			       NEO_BC0_SYS_TO_VID   |
387			       NEO_BC0_SRC_MONO     |
388			       NEO_BC3_SKIP_MAPPING |
389			       NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
390#endif
391
392	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
393	OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt));
394    }
395}
396
397static void
398Neo2097SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
399					int x, int y,
400					int w, int h,
401					int skipleft)
402{
403    NEOPtr nPtr = NEOPTR(pScrn);
404    NEOACLPtr nAcl = NEOACLPTR(pScrn);
405
406#ifdef NEO_DO_CLIPPING
407    w = (w + 31) & ~31;
408#else
409    nAcl->CPUToScreenColorExpandFill_x = x;
410    nAcl->CPUToScreenColorExpandFill_y = y;
411    nAcl->CPUToScreenColorExpandFill_w = w;
412    nAcl->CPUToScreenColorExpandFill_h = h;
413#endif
414    WAIT_ENGINE_IDLE();
415#ifdef NEO_DO_CLIPPING
416    OUTREG(NEOREG_CLIPLT, (y << 16) | (x + skipleft));
417    OUTREG(NEOREG_CLIPRB, ((y + h) << 16) | (x + w));
418    WAIT_ENGINE_IDLE();
419#endif
420    OUTREG(NEOREG_SRCSTARTOFF, 0);
421    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
422#ifdef NEO_DO_CLIPPING
423    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
424#else
425    OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
426#endif
427}
428
429static void
430Neo2097SubsequentColorExpandScanline(ScrnInfoPtr pScrn,	int bufno)
431{
432#ifdef NEO_DO_CLIPPING
433    /* Should I be waiting for fifo slots to prevent retries ?
434       How do I do that on this engine ? */
435#else
436    NEOPtr nPtr = NEOPTR(pScrn);
437    NEOACLPtr nAcl = NEOACLPTR(pScrn);
438
439    if (!(--nAcl->CPUToScreenColorExpandFill_h))
440	return;
441
442    WAIT_ENGINE_IDLE();
443    OUTREG(NEOREG_SRCSTARTOFF, 0);
444    OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
445	   | (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
446    OUTREG(NEOREG_XYEXT, (1<<16)
447	   | (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
448#endif
449}
450
451#if 0
452static void
453Neo2097SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
454				     int patternx,
455				     int patterny,
456				     int fg, int bg,
457				     int rop, unsigned int planemask)
458{
459    NEOPtr nPtr = NEOPTR(pScrn);
460    NEOACLPtr nAcl = NEOACLPTR(pScrn);
461
462    if (bg == -1) {
463	/* transparent setup */
464	nAcl->tmpBltCntlFlags = ( nAcl->BltCntlFlags    |
465		                   NEO_BC0_SRC_MONO     |
466		                   NEO_BC0_FILL_PAT     |
467		                   NEO_BC0_SRC_TRANS    |
468		                   NEO_BC3_SKIP_MAPPING |
469		                   NEO_BC3_SRC_XY_ADDR  |
470		                   NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
471
472	WAIT_ENGINE_IDLE();
473	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
474	OUTREG(NEOREG_SRCSTARTOFF, (patterny << 16) | patternx);
475    }
476    else {
477	/* opaque setup */
478	nAcl->tmpBltCntlFlags = ( nAcl->BltCntlFlags    |
479		                   NEO_BC0_SRC_MONO     |
480		                   NEO_BC0_FILL_PAT     |
481		                   NEO_BC3_SKIP_MAPPING |
482		                   NEO_BC3_SRC_XY_ADDR  |
483		                   NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
484
485	WAIT_ENGINE_IDLE();
486	OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
487	OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt));
488	OUTREG(NEOREG_SRCSTARTOFF, (patterny << 16) | patternx);
489    }
490}
491
492
493static void
494Neo2097SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn,
495				    int patternx,
496				    int patterny,
497				    int x, int y,
498				    int w, int h)
499{
500    NEOPtr nPtr = NEOPTR(pScrn);
501    NEOACLPtr nAcl = NEOACLPTR(pScrn);
502
503    patterny &= 0x7;
504
505    WAIT_ENGINE_IDLE();
506    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags | (patterny << 20));
507/*   OUTREG(NEOREG_SRCBITOFF, patternx);  Bad Register */
508    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
509    OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
510}
511#endif
512
513static void
514Neo2097SetupForScanlineImageWrite(
515   ScrnInfoPtr pScrn,
516   int rop,
517   unsigned int planemask,
518   int transparency_color,
519   int bpp, int depth
520){
521    NEOACLPtr nAcl = NEOACLPTR(pScrn);
522
523    nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags   |
524			     NEO_BC0_SYS_TO_VID   |
525                             NEO_BC3_SKIP_MAPPING |
526                             NEO_BC3_DST_XY_ADDR  | neo2097Rop[rop]);
527}
528
529
530static void
531Neo2097SubsequentScanlineImageWriteRect(
532   ScrnInfoPtr pScrn,
533   int x, int y, int w, int h,
534   int skipleft
535){
536    NEOPtr nPtr = NEOPTR(pScrn);
537    NEOACLPtr nAcl = NEOACLPTR(pScrn);
538
539    WAIT_ENGINE_IDLE();
540    OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
541    OUTREG(NEOREG_SRCSTARTOFF, 0);
542    OUTREG(NEOREG_DSTSTARTOFF, (y << 16) | (x & 0xffff));
543    OUTREG(NEOREG_XYEXT, (h << 16) | w);
544}
545
546static void
547Neo2097SubsequentImageWriteScanline(
548    ScrnInfoPtr pScrn,
549    int bufno
550){
551    /* should I be checking for fifo slots here ? */
552}
553#endif
554