1/*
2 * Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org>
3 * Copyright 2005 Adam Jackson <ajax@nwnk.net>
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the names of the authors not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  The authors make no representations
12 * about the suitability of this software for any purpose.  It is provided
13 * "as is" without express or implied warranty.
14 *
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24/* Solid and Copy support derived from the i128 XAA code */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "exa.h"
31#include "miline.h"
32#include "servermd.h"
33#include "picture.h"
34
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "xf86Pci.h"
38
39#include "i128.h"
40#include "i128reg.h"
41
42#define PI128_FROM_PIXMAP(x) \
43    I128Ptr pI128 = I128PTR(xf86ScreenToScrn(x->drawable.pScreen))
44#define PI128_FROM_SCREEN(x) \
45    I128Ptr pI128 = I128PTR(xf86ScreenToScrn(x))
46#define PI128_FROM_PICTURE(x) \
47    I128Ptr pI128 = I128PTR(xf86ScreenToScrn(x->pDrawable->pScreen))
48
49/* we might be able to do something smarter than this */
50#define ENG_PIPELINE_READY() \
51    while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY)
52#define ENG_DONE() \
53    while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV))
54
55#if 1
56#define I128_EXA_DEBUG(x)
57#else
58#define I128_EXA_DEBUG(x) ErrorF x
59#endif
60
61/* technically we should set the caches to bogus things during init... */
62#define CACHE_DEBUG 0
63
64#define CACHED_UPDATE(val, reg) \
65    do if (pI128->val != val) { \
66        if (CACHE_DEBUG) { I128_EXA_DEBUG(("Updated cache for " #reg "\n")); } \
67        pI128->mem.rbase_a[reg] = pI128->val = val; \
68    } while (0)
69
70static void
71i128SetBufCtrl(I128Ptr pI128, int dest_bpp)
72{
73    unsigned int buf_ctrl;
74
75    switch (dest_bpp) {
76        case 8:  buf_ctrl = BC_PSIZ_8B;  break;
77        case 16: buf_ctrl = BC_PSIZ_16B; break;
78        case 24:
79        case 32: buf_ctrl = BC_PSIZ_32B; break;
80        default: buf_ctrl = 0;           break; /* error */
81    }
82    if (pI128->Chipset == PCI_CHIP_I128_T2R) {
83        if (pI128->MemoryType == I128_MEMORY_SGRAM)
84            buf_ctrl |= BC_MDM_PLN;
85        else
86            buf_ctrl |= BC_BLK_ENA;
87    }
88
89    CACHED_UPDATE(buf_ctrl, BUF_CTRL);
90}
91
92static const CARD32 i128alu[16] =
93{
94    CR_CLEAR << 8,
95    CR_AND << 8,
96    CR_AND_REV << 8,
97    CR_COPY << 8,
98    CR_AND_INV << 8,
99    CR_NOOP << 8,
100    CR_XOR << 8,
101    CR_OR << 8,
102    CR_NOR << 8,
103    CR_EQUIV << 8,
104    CR_INVERT << 8,
105    CR_OR_REV << 8,
106    CR_COPY_INV << 8,
107    CR_OR_INV << 8,
108    CR_NAND << 8,
109    CR_SET << 8
110};
111
112/*                                8bpp   16bpp  32bpp unused */
113static const int min_size[]   = { 0x62,  0x32,  0x1A, 0x00 };
114static const int max_size[]   = { 0x80,  0x40,  0x20, 0x00 };
115static const int split_size[] = { 0x20,  0x10,  0x08, 0x00 };
116
117/*
118 * this is the workhorse for our solid and copy routines.  this works because
119 * when CS_SOLID is set, the color comes from the FORE register regardless of
120 * the source pixmap coords.
121 */
122
123static void
124i128ExaBlit(PixmapPtr dst, int x1, int y1, int x2, int y2, int w, int h)
125{
126    int wh;
127    PI128_FROM_PIXMAP(dst);
128
129    I128_EXA_DEBUG(("Blit: %d %d %d %d %d %d\n", x1, y1, x2, y2, w, h));
130    ENG_PIPELINE_READY();
131
132    /*
133     * this deserves explanation.  XY3_DIR == 0 means left to right, top to
134     * bottom.  setting bit zero (DIR_LR_BT) switches to bottom to top, and
135     * setting bit one (DIR_RL_TB) switches to right to left. XXX rewrite me.
136     */
137    if (pI128->blitdir & DIR_RL_TB) { /* right-to-left */
138        x1 += w; x1--;
139        x2 += w; x2--;
140    }
141    if (pI128->blitdir & DIR_LR_BT) { /* bottom-to-top */
142        y1 += h; y1--;
143        y2 += h; y2--;
144    }
145
146    if (pI128->Chipset == PCI_CHIP_I128) {
147        int bppi;
148
149        /* The I128-1 has a nasty bitblit bug
150         * that occurs when dest is exactly 8 pages wide
151         */
152
153        bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24;
154
155        if ((w >= min_size[bppi]) && (w <= max_size[bppi])) {
156            bppi = split_size[bppi];
157#if 1
158            /* split method */
159
160            wh = (bppi << 16) | h;
161            CACHED_UPDATE(wh, XY2_WH);
162            pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1;    MB;
163            pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2;    MB;
164
165            ENG_PIPELINE_READY();
166
167            w -= bppi;
168
169            if (pI128->blitdir & DIR_RL_TB) {
170                /* right to left blit */
171                x1 -= bppi;
172                x2 -= bppi;
173            } else {
174                /* left to right blit */
175                x1 += bppi;
176                x2 += bppi;
177            }
178#else
179            /* clip method */
180            pI128->mem.rbase_a[CLPTL] = (x2 << 16) | y2;
181            pI128->mem.rbase_a[CLPBR] = ((x2 + w) << 16) | (y2 + h);
182            w += bppi;
183#endif
184        }
185    }
186
187    /* this is overkill, but you can never have too much overkill */
188    wh = (w << 16) | h;
189    CACHED_UPDATE(wh, XY2_WH);
190
191    pI128->mem.rbase_a[XY0_SRC] = (x1 << 16) | y1;    MB;
192    pI128->mem.rbase_a[XY1_DST] = (x2 << 16) | y2;    MB;
193}
194
195static void
196i128WaitMarker(ScreenPtr pScreen, int Marker)
197{
198    PI128_FROM_SCREEN(pScreen);
199    ENG_DONE();
200}
201
202static void
203i128SetPlanemask(I128Ptr pI128, Pixel p)
204{
205    Pixel planemask;
206    I128_EXA_DEBUG(("SetPlanemask: %d\n", (int)p));
207    if (p == -1)
208        planemask = -1;
209    else switch (pI128->bitsPerPixel) {
210        case 8:
211            planemask = p * 0x01010101; break;
212        case 16:
213            planemask = p * 0x00010001; break;
214        default:
215            planemask = p; break;
216    }
217
218    CACHED_UPDATE(planemask, MASK);
219}
220
221/* this should be superfluous... */
222static void
223i128SetClip(I128Ptr pI128)
224{
225#if 0
226    pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000;
227    pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047;
228#endif
229}
230
231static void
232i128SetBlitDirection(I128Ptr pI128, int dx, int dy)
233{
234    int blitdir;
235
236    I128_EXA_DEBUG(("SetBlitDirection: %d %d\n", dx, dy));
237
238    if (dx < 0) {
239        if (dy < 0) blitdir = DIR_RL_BT;
240        else blitdir = DIR_RL_TB;
241    } else {
242        if (dy < 0) blitdir = DIR_LR_BT;
243        else blitdir = DIR_LR_TB;
244    }
245
246    CACHED_UPDATE(blitdir, XY3_DIR);
247}
248
249static void
250i128SetRop(I128Ptr pI128, int alu, int solid)
251{
252    int cmd;
253
254    I128_EXA_DEBUG(("SetRop: %d %d\n", alu, solid));
255
256    cmd = i128alu[alu] | CO_BITBLT | (solid ? (CS_SOLID << 16) : 0);
257
258    CACHED_UPDATE(cmd, CMD);
259}
260
261static void
262i128SetSourcePixmap(I128Ptr pI128, PixmapPtr src)
263{
264    unsigned int sorg = exaGetPixmapOffset(src);
265    unsigned int sptch = exaGetPixmapPitch(src);
266
267    I128_EXA_DEBUG(("SetSourcePixmap: %x, %d\n", sorg, sptch));
268
269    CACHED_UPDATE(sorg, DE_SORG);
270    CACHED_UPDATE(sptch, DE_SPTCH);
271}
272
273static void
274i128SetDestPixmap(I128Ptr pI128, PixmapPtr dst)
275{
276    unsigned int dorg = exaGetPixmapOffset(dst);
277    unsigned int dptch = exaGetPixmapPitch(dst);
278
279    I128_EXA_DEBUG(("SetDestPixmap: %x, %d\n", dorg, dptch));
280
281    CACHED_UPDATE(dorg, DE_DORG);
282    CACHED_UPDATE(dptch, DE_DPTCH);
283}
284
285static void
286i128SetTexture(I128Ptr pI128, PixmapPtr tex)
287{
288    unsigned int torg = exaGetPixmapOffset(tex);
289    unsigned int tptch = exaGetPixmapPitch(tex);
290
291    I128_EXA_DEBUG(("SetTexture: %x, %d\n", torg, tptch));
292
293    CACHED_UPDATE(torg, LOD0_ORG);
294    CACHED_UPDATE(tptch, DE_TPTCH);
295}
296
297static const int func_tab[13][2] = {
298        /* source function,         destination function */
299        { ABLEND_SRC_ZERO,          ABLEND_DST_ZERO        }, /* clear */
300        { ABLEND_SRC_ONE,           ABLEND_DST_ZERO        }, /* src */
301        { ABLEND_SRC_ZERO,          ABLEND_DST_ONE         }, /* dst */
302        { ABLEND_SRC_ONE,           ABLEND_DST_OMSRC_ALPHA }, /* over */
303        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_ONE         }, /* overreverse */
304        { ABLEND_SRC_DST_ALPHA,     ABLEND_DST_ZERO        }, /* in */
305        { ABLEND_SRC_ZERO,          ABLEND_DST_SRC_ALPHA   }, /* inreverse */
306        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_ZERO        }, /* out */
307        { ABLEND_SRC_ZERO,          ABLEND_DST_OMSRC_ALPHA }, /* outreverse */
308        { ABLEND_SRC_DST_ALPHA,     ABLEND_DST_OMSRC_ALPHA }, /* atop */
309        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_SRC_ALPHA   }, /* atopreverse */
310        { ABLEND_SRC_OMDST_ALPHA,   ABLEND_DST_OMSRC_ALPHA }, /* xor */
311        { ABLEND_SRC_ONE,           ABLEND_DST_ONE         }  /* add */
312};
313
314static void
315i128SetAlphaForOp(I128Ptr pI128, int op, int enable)
316{
317    int acntrl = 0;
318
319    if (enable) {
320        acntrl |= ACTL_BE;  /* blend enable */
321        acntrl |= func_tab[op][0];  /* source factor */
322        acntrl |= func_tab[op][1];  /* dest_factor */
323        acntrl |= 0; /* ACTL_AMD; / * modulate alpha */
324    } else {
325        acntrl = 0;
326    }
327
328    I128_EXA_DEBUG(("SetAlphaForOp: %d, %d\n", op, enable));
329
330    CACHED_UPDATE(acntrl, ACNTRL);
331}
332
333/* we don't need a finalizer, yet */
334static void
335i128Done(PixmapPtr p) {
336    I128_EXA_DEBUG(("Done\n\n"));
337    return;
338}
339
340/* Solid */
341
342static Bool
343i128PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
344{
345    PI128_FROM_PIXMAP(pPixmap);
346
347    ENG_PIPELINE_READY();
348
349    i128SetPlanemask(pI128, planemask);
350
351    if (alu != GXclear && alu != GXset)
352        pI128->mem.rbase_a[FORE] = fg;
353
354    i128SetClip(pI128);
355    i128SetBlitDirection(pI128, 1, 1); /* probably unnecessary/ignored */
356
357    i128SetAlphaForOp(pI128, 0, 0);
358    i128SetRop(pI128, alu, 1);
359
360    /* no need to set the source, the chip ignores it */
361    i128SetDestPixmap(pI128, pPixmap);
362
363    return TRUE;
364}
365
366static void
367i128Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
368{
369    i128ExaBlit(pPixmap, 0, 0, x1, y1, x2 - x1, y2 - y1);
370}
371
372/* Copy */
373
374static Bool
375i128PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy,
376                int alu, Pixel planemask)
377{
378    PI128_FROM_PIXMAP(pSrcPixmap);
379
380    ENG_PIPELINE_READY();
381
382    i128SetPlanemask(pI128, planemask);
383    i128SetClip(pI128);
384    i128SetBlitDirection(pI128, dx, dy);
385
386    i128SetAlphaForOp(pI128, 0, 0);
387    i128SetRop(pI128, alu, 0);
388
389    i128SetSourcePixmap(pI128, pSrcPixmap);
390    i128SetDestPixmap(pI128, pDstPixmap);
391
392    return TRUE;
393}
394
395static void
396i128Copy(PixmapPtr pDstPixmap, int x1, int y1, int x2, int y2, int w, int h)
397{
398    i128ExaBlit(pDstPixmap, x1, y1, x2, y2, w, h);
399}
400
401/* Composite */
402
403static const struct source_format source_formats[] = {
404    /* 32bpp */
405    { PICT_a8r8g8b8,    0x14,   0,  0 },
406    { PICT_x8r8g8b8,    0x14,   0,  1 },
407#if 0
408    { PICT_a8b8g8r8,    0x14,   0,  0 },
409    { PICT_x8b8g8r8,    0x14,   0,  1 },
410    /* no direct 24bpp formats */
411    /* 16bpp */
412    { PICT_r5g6b5,      0x12,   0,  0 },
413    { PICT_b5g6r5,      0x12,   0,  0 },
414    { PICT_a1r5g5b5,    0x11,   0,  0 },
415    { PICT_x1r5g5b5,    0x11,   0,  1 },
416    { PICT_a1b5g5r5,    0x11,   0,  0 },
417    { PICT_x1b5g5r5,    0x11,   0,  1 },
418    { PICT_a4r4g4b4,    0x10,   0,  0 },
419    { PICT_x4r4g4b4,    0x10,   0,  1 },
420    { PICT_a4b4g4r4,    0x10,   0,  0 },
421    { PICT_x4b4g4r4,    0x10,   0,  1 },
422    /* 8bpp */
423    { PICT_a8,          0x21,   0,  0 },
424    { PICT_r3g3b2,      0x0D,   0,  0 },
425    { PICT_b2g3r3,      0x0D,   0,  0 },
426    { PICT_a2r2g2b2,    0x30,   0,  0 },
427    { PICT_a2b2g2r2,    0x30,   0,  0 },
428    /* 4bpp */
429    { PICT_a4,          0x20,   0,  0 },
430#endif
431    /* terminator */
432    { 0,                0,      0,  0 }
433};
434
435static struct source_format *
436i128MapSourceFormat(int fmt)
437{
438    struct source_format *f;
439    for (f = (struct source_format *)source_formats; f->render_format; f++)
440        if (f->render_format == fmt)
441            return f;
442    return NULL;
443}
444
445struct dest_format {
446    int render_format;
447    int i128_format;
448};
449
450#if 0
451static const struct dest_format dest_formats[] = {
452    { 0, 0 }
453};
454
455static struct dest_format *
456i128MapDestFormat(int fmt)
457{
458    return NULL;
459}
460#endif
461
462/* Composite is probably t2r and t2r4 only */
463static Bool
464i128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
465                   PicturePtr pDstPicture)
466{
467    PI128_FROM_PICTURE(pDstPicture);
468
469    if (op >= PictOpSaturate) return FALSE;
470
471    /*
472     * no direct alpha mask support.  we only have one TMU, so while we
473     * can emulate it, we should emulate it in the generic EXA layer.
474     */
475    if (pMaskPicture) return FALSE;
476
477    /* when transforms added, be sure to check for linear/nearest */
478    if (pSrcPicture->transform && pSrcPicture->filter != PictFilterNearest)
479        return FALSE;
480
481    /* no support for external alpha */
482    if (pSrcPicture->alphaMap || pDstPicture->alphaMap) return FALSE;
483
484    /* driver currently doesn't support repeating */
485    if (pSrcPicture->repeat) return FALSE;
486
487    pI128->source = i128MapSourceFormat(pSrcPicture->format);
488    if (!pI128->source)
489        return FALSE;
490#if 0
491    if (!i128MapDestFormat(pDstPicture->format)) return FALSE;
492#endif
493
494    return TRUE;
495}
496
497static Bool
498i128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
499                     PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
500                     PixmapPtr pDst)
501{
502    unsigned int cmd;
503    unsigned int tex_ctl = 0;
504    unsigned int threedctl = 0;
505    PI128_FROM_PIXMAP(pDst);
506
507    /* 2D setup */
508    i128SetBufCtrl(pI128, pDst->drawable.bitsPerPixel);
509    i128SetPlanemask(pI128, -1);
510    i128SetSourcePixmap(pI128, pSrc);
511    i128SetDestPixmap(pI128, pDst);
512
513    /* TEX_INV command here? */
514
515    cmd = CO_TRIAN3D;
516    CACHED_UPDATE(cmd, CMD);
517
518    /* 3D setup */
519    i128SetTexture(pI128, pSrc);
520
521    i128SetAlphaForOp(pI128, op, 1);
522
523    /* it looks pointless to cache these, but we'll need it for DRI */
524
525    tex_ctl |= TEX_TM;  /* enable texture mapping */
526    tex_ctl |= TEX_NMG | TEX_NMN;   /* nearest interpolation */
527    tex_ctl |= 0; /* TEX_RM;  / * modulate RGB */
528    CACHED_UPDATE(tex_ctl, TEX_CTL);
529
530    threedctl |= 0; /* COMP_TRUE << TCTL_ZOP_SHIFT;   / * always pass Z check */
531    threedctl |= TCTL_ABS;  /* enable alpha blend */
532    threedctl |= TCTL_TBS;  /* enable texture blend */
533    threedctl |= TCTL_RT;   /* draw textured rectangle */
534    CACHED_UPDATE(threedctl, THREEDCTL);
535
536    return TRUE;
537}
538
539static void
540i128Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
541              int dstX, int dstY, int width, int height)
542{
543    PI128_FROM_PIXMAP(pDst);
544
545    /*
546     * vertex setup.  vertex layout must be:
547     * V0    V1
548     * V2   (V3 is implicit)
549     */
550
551    pI128->mem.rbase_af[V0_X] = 0.0;
552    pI128->mem.rbase_af[V0_Y] = 0.0;
553    pI128->mem.rbase_af[V0_W] = 1.0;
554    pI128->mem.rbase_af[V0_U] = 0.0;
555    pI128->mem.rbase_af[V0_V] = 0.0;
556    pI128->mem.rbase_af[V1_X] = 300.0;
557    pI128->mem.rbase_af[V1_Y] = 0.0;
558    pI128->mem.rbase_af[V1_W] = 1.0;
559    pI128->mem.rbase_af[V1_U] = 1.0;
560    pI128->mem.rbase_af[V1_V] = 0.0;
561    pI128->mem.rbase_af[V2_X] = 0.0;
562    pI128->mem.rbase_af[V2_Y] = 300.0;
563    pI128->mem.rbase_af[V2_W] = 1.0;
564    pI128->mem.rbase_af[V2_U] = 0.0;
565    pI128->mem.rbase_af[V2_V] = 1.0;
566
567    /* and fire */
568    pI128->mem.rbase_a[TRIGGER3D] = 1; MB;
569
570#if 0
571    static int i = 0;
572    /* test for raster */
573    if (!(i = (i + 1) % 32)) {
574        ErrorF("Composite test: %d %d %d %d %d %d\n", srcX, srcY, dstX, dstY,
575                width, height);
576    }
577    i128SetRop(pI128, GXxor, 0);
578    i128ExaBlit(pDst, srcX, srcY, dstX, dstY, width, height);
579#endif
580}
581
582#if 0
583/*
584 * upload and download will require a DRM.  AGP DMA only works on T2R4, and
585 * then only for upload.  we could probably use memory windows on other chips,
586 * but those have goofy alignment restrictions and need to be disabled when
587 * not in use.
588 */
589static Bool
590i128DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
591                       int dst_pitch)
592{
593}
594
595static Bool
596i128UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
597                   int src_pitch)
598{
599}
600#endif
601
602Bool
603I128ExaInit(ScreenPtr pScreen)
604{
605    ExaDriverPtr pExa;
606    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
607    I128Ptr pI128 = I128PTR(pScrn);
608
609    if (!(pExa = exaDriverAlloc())) {
610        pI128->NoAccel = TRUE;
611        return FALSE;
612    }
613    pI128->ExaDriver = pExa;
614
615    pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT;
616    pExa->memoryBase = pI128->MemoryPtr;
617    pExa->memorySize = pI128->MemorySize * 1024;
618    pExa->offScreenBase = (pScrn->virtualX * pScrn->virtualY) *
619                               (pScrn->bitsPerPixel / 8) + 4096;
620    /* these two are probably right */
621    pExa->pixmapOffsetAlign = 16;
622    pExa->pixmapPitchAlign = 16;
623    /* these two are guesses */
624    pExa->maxX = 2048;
625    pExa->maxY = 2048;
626
627    pExa->WaitMarker = i128WaitMarker;
628
629    pExa->PrepareSolid = i128PrepareSolid;
630    pExa->Solid = i128Solid;
631    pExa->DoneSolid = i128Done;
632
633    pExa->PrepareCopy = i128PrepareCopy;
634    pExa->Copy = i128Copy;
635    pExa->DoneCopy = i128Done;
636
637    if (0 && (pI128->Chipset == PCI_CHIP_I128_T2R ||
638        pI128->Chipset == PCI_CHIP_I128_T2R4))
639    {
640#if 0
641        pExa->DownloadFromScreen = i128DownloadFromScreen;
642        pExa->UploadToScreen = i128UploadToScreen;
643#endif
644        pExa->CheckComposite = i128CheckComposite;
645        pExa->PrepareComposite = i128PrepareComposite;
646        pExa->Composite = i128Composite;
647        pExa->DoneComposite = i128Done;
648    }
649
650    /*
651     * XXX much of this is duplicated from the XAA code, but I expect the XAA
652     * support to disappear eventually.
653     */
654    pI128->buf_ctrl = 0; /* force write */
655    i128SetBufCtrl(pI128, pI128->bitsPerPixel);
656
657    /* all of this needs to be properly documented */
658    {
659        pI128->mem.rbase_a[DE_PGE] = 0x00;
660        pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset;
661        pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset;
662        pI128->mem.rbase_a[DE_MSRC] = 0x00;
663        pI128->mem.rbase_a[DE_WKEY] = 0x00;
664        pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH];
665        pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH];
666        if (pI128->Chipset == PCI_CHIP_I128_T2R4)
667            pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH];
668        pI128->mem.rbase_a[RMSK] = 0x00000000;
669        pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE;
670        pI128->mem.rbase_a[LPAT] = 0xffffffff;  /* for lines */
671        pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */
672        pI128->mem.rbase_a[CLPTL] = 0x00000000;
673        pI128->mem.rbase_a[CLPBR] = (4095 << 16) | 2047 ;
674        pI128->mem.rbase_a[ACNTRL] = 0x00000000;
675        pI128->mem.rbase_a[INTM] = 0x03;
676    }
677
678    /* need this as a float * for vertex setup */
679    pI128->mem.rbase_af = (float *)pI128->mem.rbase_a;
680
681    if (pI128->Debug) {
682        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128ExaInit done\n");
683        I128DumpActiveRegisters(pScrn);
684    }
685
686    return(exaDriverInit(pScreen, pExa));
687}
688