1/*
2 * Copyright 2006 by Alan Hourihane, North Wales, UK.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  The authors make no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *
24 * Trident XP4/XP5 accelerated options.
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "exa.h"
32#include "picture.h"
33
34#include "xf86.h"
35#include "xf86_OSproc.h"
36#include "xf86Pci.h"
37#include "xaarop.h"
38
39#include "trident.h"
40#include "trident_regs.h"
41
42static int ropcode;
43
44static int CopyROP[16] =
45{
46    ROP_0,              /* GXclear */
47    ROP_DSa,            /* GXand */
48    ROP_SDna,           /* GXandReverse */
49    ROP_S,              /* GXcopy */
50    ROP_DSna,           /* GXandInverted */
51    ROP_D,              /* GXnoop */
52    ROP_DSx,            /* GXxor */
53    ROP_DSo,            /* GXor */
54    ROP_DSon,           /* GXnor */
55    ROP_DSxn,           /* GXequiv */
56    ROP_Dn,             /* GXinvert*/
57    ROP_SDno,           /* GXorReverse */
58    ROP_Sn,             /* GXcopyInverted */
59    ROP_DSno,           /* GXorInverted */
60    ROP_DSan,           /* GXnand */
61    ROP_1               /* GXset */
62};
63
64static int PatternROP[16]=
65{
66    ROP_0,
67    ROP_DPa,
68    ROP_PDna,
69    ROP_P,
70    ROP_DPna,
71    ROP_D,
72    ROP_DPx,
73    ROP_DPo,
74    ROP_DPon,
75    ROP_PDxn,
76    ROP_Dn,
77    ROP_PDno,
78    ROP_Pn,
79    ROP_DPno,
80    ROP_DPan,
81    ROP_1
82};
83
84static int
85GetCopyROP(int i)
86{
87    return CopyROP[i];
88}
89
90static int
91GetPatternROP(int i)
92{
93    return PatternROP[i];
94}
95
96static void
97XP4WaitMarker(ScreenPtr pScreen, int Marker)
98{
99    /* Don't need a wait marker as we need to sync on all operations */
100}
101
102static void
103XP4Done(PixmapPtr p)
104{
105    ScrnInfoPtr pScrn = xf86ScreenToScrn(p->drawable.pScreen);
106    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
107    int count = 0, timeout = 0;
108    int busy;
109
110    for (;;) {
111        BLTBUSY(busy);
112        if (busy != GE_BUSY) {
113            return;
114        }
115
116        count++;
117        if (count == 10000000) {
118            ErrorF("XP: BitBLT engine time-out.\n");
119            count = 9990000;
120            timeout++;
121            if (timeout == 4) {
122                /* Reset BitBLT Engine */
123                TGUI_STATUS(0x00);
124                return;
125            }
126        }
127    }
128}
129
130static Bool
131XP4PrepareSolid(PixmapPtr pPixmap,
132                int alu, Pixel planemask, Pixel fg)
133{
134    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
135    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
136    unsigned int dorg = exaGetPixmapOffset(pPixmap);
137    unsigned int dptch = exaGetPixmapPitch(pPixmap);
138
139    if (planemask != -1)
140        return FALSE;
141
142    ropcode = alu;
143
144    MMIO_OUT32(pTrident->IOBase, 0x2150, (dptch << 18) | (dorg >> 4));
145
146    REPLICATE(fg);
147    MMIO_OUT32(pTrident->IOBase, 0x2158, fg);
148    MMIO_OUT32(pTrident->IOBase, 0x2128, 1 << 14);
149
150    return TRUE;
151}
152
153static void
154XP4Solid(PixmapPtr pPixmap,
155            int x1, int y1,
156            int x2, int y2)
157{
158    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
159    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
160    int bpp;
161
162    switch (pPixmap->drawable.bitsPerPixel) {
163    case 8:
164        bpp = 0x40;
165        break;
166    case 16:
167        bpp = 0x41;
168        break;
169    case 32:
170        bpp = 0x42;
171        break;
172    }
173
174    MMIO_OUT32(pTrident->IOBase, 0x2138, (x1 << 16) | y1);
175    MMIO_OUT32(pTrident->IOBase, 0x2140, ((x2 - x1) << 16) |
176                                            (y2 - y1));
177    MMIO_OUT32(pTrident->IOBase, 0x2124,
178                                    (GetPatternROP(ropcode) << 24) |
179                                    (bpp << 8) |
180                                    2);
181}
182
183static Bool
184XP4PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
185                int dx, int dy,
186                int alu, Pixel planemask)
187{
188    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
189    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
190    unsigned int sorg = exaGetPixmapOffset(pSrcPixmap);
191    unsigned int dorg = exaGetPixmapOffset(pDstPixmap);
192    unsigned int sptch = exaGetPixmapPitch(pSrcPixmap);
193    unsigned int dptch = exaGetPixmapPitch(pDstPixmap);
194
195    if (planemask != -1)
196        return FALSE;
197
198    pTrident->BltScanDirection = 0;
199    if (dx < 0)
200        pTrident->BltScanDirection |= XNEG;
201    if (dy < 0)
202        pTrident->BltScanDirection |= YNEG;
203
204    ropcode = alu;
205
206    MMIO_OUT32(pTrident->IOBase, 0x2154, (sptch << 18) | (sorg >> 4));
207    MMIO_OUT32(pTrident->IOBase, 0x2150, (dptch << 18) | (dorg >> 4));
208
209    return TRUE;
210}
211
212static void
213XP4Copy(PixmapPtr pDstPixmap,
214        int x1, int y1,
215        int x2, int y2,
216        int w, int h)
217{
218    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
219    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
220    int bpp;
221
222    switch (pDstPixmap->drawable.bitsPerPixel) {
223    case 8:
224        bpp = 0x40;
225        break;
226    case 16:
227        bpp = 0x41;
228        break;
229    case 32:
230        bpp = 0x42;
231        break;
232    }
233
234    if (pTrident->BltScanDirection & YNEG) {
235        y1 = y1 + h - 1;
236        y2 = y2 + h - 1;
237    }
238    if (pTrident->BltScanDirection & XNEG) {
239        x1 = x1 + w - 1;
240        x2 = x2 + w - 1;
241    }
242    MMIO_OUT32(pTrident->IOBase, 0x2128, pTrident->BltScanDirection |
243                                            SCR2SCR);
244    MMIO_OUT32(pTrident->IOBase, 0x2138, (x2 << 16) | y2);
245    MMIO_OUT32(pTrident->IOBase, 0x213C, (x1 << 16) | y1);
246    MMIO_OUT32(pTrident->IOBase, 0x2140, (w << 16) | h);
247    MMIO_OUT32(pTrident->IOBase, 0x2124, (GetCopyROP(ropcode) << 24) |
248                                            (bpp << 8) |
249                                            1);
250}
251
252Bool
253XP4ExaInit(ScreenPtr pScreen)
254{
255    ExaDriverPtr pExa;
256    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
257    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
258
259    if (pTrident->NoAccel)
260        return FALSE;
261
262    if (!(pExa = pTrident->EXADriverPtr = exaDriverAlloc())) {
263        pTrident->NoAccel = TRUE;
264        return FALSE;
265    }
266
267    pExa->exa_major = 2;
268    pExa->exa_minor = 0;
269
270    pExa->flags = EXA_OFFSCREEN_PIXMAPS;
271    pExa->memoryBase = pTrident->FbBase;
272    pExa->memorySize = pTrident->FbMapSize;
273    pExa->offScreenBase = pScrn->displayWidth * pScrn->virtualY *
274                            ((pScrn->bitsPerPixel + 7) / 8);
275
276    pExa->pixmapOffsetAlign = 16;
277    pExa->pixmapPitchAlign = 16;
278
279    pExa->maxX = 4095;
280    pExa->maxY = 4095;
281
282    pExa->WaitMarker = XP4WaitMarker;
283
284    pExa->PrepareSolid = XP4PrepareSolid;
285    pExa->Solid = XP4Solid;
286    pExa->DoneSolid = XP4Done;
287
288    pExa->PrepareCopy = XP4PrepareCopy;
289    pExa->Copy = XP4Copy;
290    pExa->DoneCopy = XP4Done;
291
292    return (exaDriverInit(pScreen, pExa));
293}
294