gx_driver.c revision 04007eba
1/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc.
2 *
3 * Portioned modeled from xf86-video-intel/src/i830_driver.c
4 * Copyright 2001 VA Linux Systems Inc., Fremont, California.
5 * Copyright \ufffd 2002 by David Dawes
6
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to
9 * deal in the Software without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 *
25 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
26 * contributors may be used to endorse or promote products derived from this
27 * software without specific prior written permission.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <stdio.h>
35
36#include "xf86.h"
37#include "xf86_OSproc.h"
38#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
39#include "xf86Resources.h"
40#endif
41#include "xf86cmap.h"
42#include "compiler.h"
43#include "mipointer.h"
44#include "shadow.h"
45#include <X11/extensions/randr.h>
46#include "fb.h"
47#include "miscstruct.h"
48#include "micmap.h"
49#include "vbe.h"
50#include "fb.h"
51#include "randrstr.h"
52
53#include "geode.h"
54#include "gfx_defs.h"
55#include "gfx_regs.h"
56#include "panel.h"
57
58/* Bring in VGA functions */
59#include "gx_vga.c"
60
61#define GX_MIN_PITCH 1024
62#define GX_MAX_PITCH 8192
63#define GX_MAX_WIDTH  1600
64#define GX_MIN_HEIGHT  400
65#define GX_MAX_HEIGHT 1200
66#define GX_CB_PITCH   544
67#define GX_CB_SIZE    544
68
69#define GX_CPU_REG_SIZE 0x4000
70#define GX_GP_REG_SIZE  0x4000
71#define GX_VID_REG_SIZE 0x4000
72
73#define DEFAULT_IMG_LINE_BUFS 20
74#define DEFAULT_CLR_LINE_BUFS 20
75
76extern OptionInfoRec GX_GeodeOptions[];
77
78unsigned char *XpressROMPtr;
79
80static inline void
81gx_enable_dac_power(void)
82{
83    gfx_write_vid32(RCDF_VID_MISC,
84                    gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH);
85}
86
87static inline void
88gx_disable_dac_power(void)
89{
90    gfx_write_vid32(RCDF_VID_MISC,
91                    RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN |
92                    (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH));
93}
94
95static void
96GXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
97{
98    GeodePtr pGeode = GEODEPTR(pScrni);
99
100    if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) {
101        pGeode->exaBfrOffset = *offset;
102        *offset += pGeode->exaBfrOffset;
103        *avail -= pGeode->exaBfrOffset;
104    }
105}
106
107static void
108GXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
109{
110    GeodePtr pGeode = GEODEPTR(pScrni);
111    unsigned int size, i, pitch;
112
113    /* XXX - FIXME - What if we are out of room?  Then what? */
114    /* For now, we NULL them all out.                        */
115
116    if (pGeode->NoOfImgBuffers > 0) {
117        size = pGeode->displayPitch * pGeode->NoOfImgBuffers;
118        if (size <= *avail) {
119            for (i = 0; i < pGeode->NoOfImgBuffers; i++) {
120                pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset;
121                *offset += pGeode->displayPitch;
122                *avail -= pGeode->displayPitch;
123            }
124        }
125        else {
126            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
127                       "Not enough memory for image write buffers.\n");
128
129            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
130                pGeode->AccelImageWriteBuffers[i] = NULL;
131        }
132    }
133
134    if (pGeode->NoOfColorExpandLines > 0) {
135        pitch = ((pGeode->displayPitch + 31) >> 5) << 2;
136        size = pitch * pGeode->NoOfColorExpandLines;
137
138        if (size <= *avail) {
139            for (i = 0; i < pGeode->NoOfColorExpandLines; i++) {
140                pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset;
141                *offset += pitch;
142                *avail -= pitch;
143            }
144        }
145        else {
146            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
147                       "Not enough memory for color expansion buffers.\n");
148
149            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
150                pGeode->AccelColorExpandBuffers[i] = NULL;
151        }
152    }
153}
154
155static Bool
156GXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate)
157{
158    GeodePtr pGeode = GEODEPTR(pScrni);
159
160    unsigned int fboffset, fbavail;
161    unsigned int size;
162    unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8;
163    BOOL ret = TRUE;
164
165    if (pGeode->tryCompression)
166        pGeode->displayPitch =
167            GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
168    else
169        pGeode->displayPitch =
170            ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
171
172    pGeode->Pitch = pGeode->displayPitch;
173    pGeode->displayWidth = pGeode->displayPitch / bytpp;
174    pScrni->displayWidth = pGeode->displayWidth;
175
176    fbavail = pGeode->FBAvail - 0x4000;
177
178    pGeode->displayOffset = fboffset = 0;
179    pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch;
180
181    fbavail -= pGeode->displaySize;
182    fboffset += pGeode->displaySize;
183
184    if (pGeode->tryCompression) {
185        size = pScrni->virtualY * GX_CB_PITCH;
186
187        if (size <= fbavail) {
188            pGeode->CBData.compression_offset = fboffset;
189
190            fboffset += size;
191            fbavail -= size;
192
193            pGeode->Compression = TRUE;
194        }
195        else {
196            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
197                       "Not enough memory for compression\n");
198            pGeode->Compression = FALSE;
199        }
200    }
201
202    if (pGeode->tryHWCursor) {
203
204        if (fbavail >= 1024) {
205            pGeode->CursorStartOffset = fboffset;
206            fboffset += 1024;
207            fbavail -= 1024;
208            pGeode->HWCursor = TRUE;
209        }
210        else {
211            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
212                       "Not enough memory for the hardware cursor\n");
213            pGeode->HWCursor = FALSE;
214        }
215    }
216
217    if (!pGeode->NoAccel) {
218        if (pGeode->useEXA)
219            GXInitEXAMemory(pScrni, &fboffset, &fbavail);
220        else
221            GXInitXAAMemory(pScrni, &fboffset, &fbavail);
222    }
223
224    pGeode->shadowSize = 0;
225
226    if (rotate != RR_Rotate_0) {
227        if (rotate & (RR_Rotate_90 | RR_Rotate_270))
228            size = pGeode->displayPitch * pScrni->virtualX;
229        else
230            size = pGeode->displayPitch * pScrni->virtualY;
231
232        if (size <= fbavail) {
233            pGeode->shadowOffset = fboffset;
234            pGeode->shadowSize = size;
235
236            fboffset += size;
237            fbavail -= size;
238        }
239        else {
240            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
241                       "Not enough memory for the shadow framebuffer\n");
242            ret = FALSE;
243        }
244    }
245
246    /* XAA always exists - we can't remove it on demand like we can with EXA.
247     * So we assume the worse, and only give XAA enough offspace room to
248     * account for any eventuality that RandR might throw at us. */
249
250    if (!pGeode->NoAccel) {
251
252        if (pGeode->useEXA && pGeode->pExa) {
253            ExaDriverPtr pExa = pGeode->pExa;
254
255            pExa->offScreenBase = fboffset;
256            pExa->memorySize = fboffset + fbavail;
257        }
258
259        if (!pGeode->useEXA) {
260
261#if XF86XAA
262            if (!xf86FBManagerRunning(pScrn)) {
263
264                unsigned int offset = fboffset;
265                unsigned int avail = fbavail;
266                RegionRec OffscreenRegion;
267                BoxRec AvailBox;
268
269                /* Assume the shadow FB exists even if it doesnt */
270
271                if (pGeode->shadowSize == 0) {
272                    size = (pScrn->width * bytpp) * pScrni->virtualX;
273                    offset += size;
274                    avail -= size;
275                }
276
277                AvailBox.x1 = 0;
278                AvailBox.y1 =
279                    (offset + pGeode->displayPitch - 1) / pGeode->displayPitch;
280
281                AvailBox.x2 = pGeode->displayWidth;
282                AvailBox.y2 = (offset + avail) / pGeode->displayPitch;
283
284                if (AvailBox.y1 < AvailBox.y2) {
285                    REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2);
286
287                    if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion))
288                        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
289                                   "Memory manager initialization failed.\n");
290
291                    REGION_UNINIT(pScrn, &OffscreenRegion);
292                }
293                else
294                    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
295                               "Cache disabled - no offscreen memory available.\n");
296            }
297            else
298                xf86DrvMsg(pScrni->scrnIndex, X_INFO,
299                           "XAA offscreen memory has already been allocated.\n");
300#endif
301        }
302    }
303    return ret;
304}
305
306static Bool
307GXSaveScreen(ScreenPtr pScrn, int mode)
308{
309    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
310    GeodePtr pGeode = GEODEPTR(pScrni);
311
312    if (pGeode->useVGA && !pScrni->vtSema)
313        return vgaHWSaveScreen(pScrn, mode);
314
315    return TRUE;
316}
317
318/* Common function - used by the LX too */
319#ifdef XSERVER_LIBPCIACCESS
320static inline void *
321map_pci_mem(ScrnInfoPtr pScrni, int vram,
322            struct pci_device *dev, int bar, int size)
323{
324    void *ptr;
325    void **result = (void **) &ptr;
326    int map_size = size ? size : dev->regions[bar].size;
327
328    int err = pci_device_map_range(dev,
329                                   dev->regions[bar].base_addr,
330                                   map_size,
331                                   PCI_DEV_MAP_FLAG_WRITABLE |
332                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
333                                   result);
334
335    if (err)
336        return NULL;
337    return ptr;
338}
339#endif
340
341extern unsigned long gfx_gx2_scratch_base;
342
343static Bool
344GXMapMem(ScrnInfoPtr pScrni)
345{
346    GeodeRec *pGeode = GEODEPTR(pScrni);
347    int index = pScrni->scrnIndex;
348
349    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
350
351#ifndef XSERVER_LIBPCIACCESS
352    gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
353                                                      pci->memBase[2],
354                                                      pci->size[2]);
355
356    gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
357                                                     pci->memBase[1],
358                                                     pci->size[1]);
359
360    gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
361                                                      pci->memBase[3],
362                                                      pci->size[3]);
363
364    gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER,
365                                                     pci->memBase[0],
366                                                     pGeode->FBAvail);
367#else
368    gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0);
369    gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0);
370    gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0);
371    gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail);
372#endif
373
374    gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000;
375
376    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
377
378    pGeode->FBBase = gfx_virt_fbptr;
379
380    if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) ||
381        (!gfx_virt_vidptr) || (!gfx_virt_fbptr))
382        return FALSE;
383
384    if (!pGeode->NoAccel && pGeode->useEXA)
385        pGeode->pExa->memoryBase = pGeode->FBBase;
386
387    xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n",
388               pGeode->FBAvail, pGeode->FBBase);
389
390    return TRUE;
391}
392
393/* Check to see if VGA exists - we map the space and look for a
394   signature - if it doesn't match exactly, then we assume no VGA.
395*/
396
397static Bool
398GXCheckVGA(ScrnInfoPtr pScrni)
399{
400
401    unsigned char *ptr;
402    const char *vgasig = "IBM VGA Compatible";
403    int ret;
404
405    ptr =
406        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
407                      strlen(vgasig));
408
409    if (ptr == NULL)
410        return FALSE;
411
412    ret = memcmp(ptr, vgasig, strlen(vgasig));
413    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
414
415    return ret ? FALSE : TRUE;
416}
417
418static Bool
419GXPreInit(ScrnInfoPtr pScrni, int flags)
420{
421    GeodePtr pGeode;
422    ClockRangePtr GeodeClockRange;
423    OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0];
424    int ret;
425    QQ_WORD msrValue;
426    EntityInfoPtr pEnt;
427    rgb defaultWeight = { 0, 0, 0 };
428    int modecnt;
429    char *s, *panelgeo;
430    Bool useVGA;
431
432    if (pScrni->numEntities != 1)
433        return FALSE;
434
435    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
436#ifndef XSERVER_LIBPCIACCESS
437    if (pEnt->resources)
438        return FALSE;
439#endif
440
441    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
442
443    if (pGeode == NULL)
444        return FALSE;
445
446    useVGA = GXCheckVGA(pScrni);
447
448    if (flags & PROBE_DETECT) {
449        GeodeProbeDDC(pScrni, pEnt->index);
450        return TRUE;
451    }
452
453    /* Probe for VGA */
454    pGeode->useVGA = useVGA;
455    pGeode->pEnt = pEnt;
456
457    if (pGeode->useVGA) {
458        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
459            pGeode->useVGA = FALSE;
460        else
461            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
462
463#if INT10_SUPPORT
464        pGeode->vesa = calloc(1, sizeof(VESARec));
465#endif
466    }
467
468    gfx_msr_init();
469
470    ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue);
471
472    if (!ret) {
473        pGeode->Output =
474            ((msrValue.low & RCDF_CONFIG_FMT_MASK) ==
475             RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT;
476    }
477
478    /* Fill in the monitor information */
479    pScrni->monitor = pScrni->confScreen->monitor;
480
481    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
482        return FALSE;
483
484    switch (pScrni->depth) {
485    case 8:
486        pScrni->rgbBits = 8;
487    case 16:
488    case 24:
489    case 32:
490        break;
491    default:
492        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
493                   "The driver does not support %d as a depth.\n",
494                   pScrni->depth);
495        return FALSE;
496    }
497
498    xf86PrintDepthBpp(pScrni);
499
500    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
501        return FALSE;
502
503    if (!xf86SetDefaultVisual(pScrni, -1))
504        return FALSE;
505
506    /*
507     * If the driver can do gamma correction, it should call xf86SetGamma()
508     * here.
509     */
510    {
511        Gamma zeros = { 0.0, 0.0, 0.0 };
512
513        if (!xf86SetGamma(pScrni, zeros)) {
514            return FALSE;
515        }
516    }
517
518    pScrni->progClock = TRUE;
519    xf86CollectOptions(pScrni, NULL);
520    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
521
522    /* Set up our various options that may get reversed as we go on */
523
524    pGeode->FBVGAActive = FALSE;
525    pGeode->tryHWCursor = TRUE;
526    pGeode->tryCompression = TRUE;
527
528    pGeode->NoAccel = FALSE;
529    pGeode->useEXA = FALSE;
530
531    pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE;
532
533    pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS;
534    pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS;
535    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
536
537    xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
538
539    if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE,
540                              (int *) &(pGeode->FBAvail)))
541        pGeode->FBAvail = 0;
542
543    /* For compatability - allow SWCursor too */
544
545    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE))
546        pGeode->tryHWCursor = FALSE;
547
548    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE))
549        pGeode->tryCompression = FALSE;
550
551    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE))
552        pGeode->NoAccel = TRUE;
553
554    pGeode->rotation = RR_Rotate_0;
555
556    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) {
557
558        if (!xf86NameCmp(s, "LEFT"))
559            pGeode->rotation = RR_Rotate_90;
560        else if (!xf86NameCmp(s, "INVERT"))
561            pGeode->rotation = RR_Rotate_180;
562        else if (!xf86NameCmp(s, "CCW"))
563            pGeode->rotation = RR_Rotate_270;
564        else
565            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
566    }
567
568    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS,
569                         &(pGeode->NoOfImgBuffers));
570
571    if (pGeode->NoOfImgBuffers <= 0)
572        pGeode->NoOfImgBuffers = 0;
573
574    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
575                         &(pGeode->NoOfColorExpandLines));
576
577    if (pGeode->NoOfColorExpandLines <= 0)
578        pGeode->NoOfColorExpandLines = 0;
579
580    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
581                         (int *) &(pGeode->exaBfrSz));
582
583    if (pGeode->exaBfrSz <= 0)
584        pGeode->exaBfrSz = 0;
585
586    if (pGeode->Panel == TRUE) {
587        if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE))
588            pGeode->Panel = FALSE;
589    }
590
591    panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY);
592
593    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) {
594        if (!xf86NameCmp(s, "XAA"))
595            pGeode->useEXA = FALSE;
596        else if (xf86NameCmp(s, "EXA"))
597            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
598                       "Unknown accleration method %s.  Defaulting to XAA.\n",
599                       s);
600    }
601
602    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
603               "Using %s acceleration architecture\n",
604               pGeode->useEXA ? "EXA" : "XAA");
605
606    /* Set up the panel */
607
608    if (pGeode->Panel) {
609        if (panelgeo != NULL) {
610            if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY))
611                pGeode->Panel = FALSE;
612        }
613#ifdef PNL_SUP
614        else {
615            int b, f;
616
617            /* The bitdepth and refresh isn't used anywhere else in the driver */
618
619            if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS()))
620                Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b,
621                                         &f);
622        }
623#endif
624    }
625
626    /* Set up the VGA */
627
628    if (pGeode->useVGA) {
629#if INT10_SUPPORT
630        VESARec *pVesa;
631
632        if (!xf86LoadSubModule(pScrni, "int10"))
633            return FALSE;
634
635        pVesa = pGeode->vesa;
636
637        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
638            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
639                       "Unable to initialize 1NT10 support\n");
640            pGeode->useVGA = FALSE;
641        }
642#endif
643    }
644
645    /* First try to get the framebuffer size from the framebuffer,
646     * and if that fails, revert all  the way back to the legacy
647     * method
648     */
649
650    if (pGeode->FBAvail == 0) {
651        if (GeodeGetSizeFromFB(&pGeode->FBAvail))
652            pGeode->FBAvail = gfx_get_frame_buffer_size();
653    }
654
655    if (pScrni->memPhysBase == 0)
656        pScrni->memPhysBase = gfx_get_frame_buffer_base();
657
658    pScrni->fbOffset = 0;
659
660    if (pGeode->pEnt->device->videoRam == 0)
661        pScrni->videoRam = pGeode->FBAvail / 1024;
662    else
663        pScrni->videoRam = pGeode->pEnt->device->videoRam;
664
665    GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange));
666    GeodeClockRange->next = NULL;
667    GeodeClockRange->minClock = 25175;
668    GeodeClockRange->maxClock = 229500;
669    GeodeClockRange->clockIndex = -1;
670    GeodeClockRange->interlaceAllowed = TRUE;
671    GeodeClockRange->doubleScanAllowed = FALSE;
672
673    pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index);
674
675    /* I'm still not 100% sure this uses the right values */
676
677    modecnt = xf86ValidateModes(pScrni,
678                                pScrni->monitor->Modes,
679                                pScrni->display->modes,
680                                GeodeClockRange,
681                                NULL, GX_MIN_PITCH, GX_MAX_PITCH,
682                                32, GX_MIN_HEIGHT, GX_MAX_HEIGHT,
683                                pScrni->display->virtualX,
684                                pScrni->display->virtualY, pGeode->FBAvail,
685                                LOOKUP_BEST_REFRESH);
686
687    if (modecnt <= 0) {
688        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
689        return FALSE;
690    }
691
692    xf86PruneDriverModes(pScrni);
693
694    if (pScrni->modes == NULL) {
695        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
696        return FALSE;
697    }
698
699    xf86SetCrtcForModes(pScrni, 0);
700    pScrni->currentMode = pScrni->modes;
701
702    xf86PrintModes(pScrni);
703    xf86SetDpi(pScrni, 0, 0);
704
705    /* Load the modules we'll need */
706
707    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
708        return FALSE;
709    }
710
711    if (pGeode->NoAccel == FALSE) {
712        const char *module = (pGeode->useEXA) ? "exa" : "xaa";
713
714        if (!xf86LoadSubModule(pScrni, module)) {
715            return FALSE;
716        }
717    }
718
719    if (pGeode->tryHWCursor == TRUE) {
720        if (!xf86LoadSubModule(pScrni, "ramdac")) {
721            return FALSE;
722        }
723    }
724
725#ifndef XSERVER_LIBPCIACCESS
726    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
727        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
728                   "Couldn't register the resources.\n");
729        return FALSE;
730    }
731#endif
732    return TRUE;
733}
734
735static void
736GXRestore(ScrnInfoPtr pScrni)
737{
738    GeodeRec *pGeode = GEODEPTR(pScrni);
739
740    if (pGeode->useVGA && pGeode->FBVGAActive) {
741        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
742
743        vgaHWProtect(pScrni, TRUE);
744        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
745        vgaHWProtect(pScrni, FALSE);
746    }
747}
748
749static Bool
750GXUnmapMem(ScrnInfoPtr pScrni)
751{
752    GeodeRec *pGeode = GEODEPTR(pScrni);
753
754    /* unmap all the memory map's */
755
756    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE);
757    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE);
758    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE);
759    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail);
760    return TRUE;
761}
762
763static void
764GXSetDvLineSize(unsigned int pitch)
765{
766    unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024;
767
768    if (pitch > 1024) {
769        dv_size = MDC_DV_LINE_SIZE_2048;
770    }
771    if (pitch > 2048) {
772        dv_size = MDC_DV_LINE_SIZE_4096;
773    }
774    if (pitch > 4096) {
775        dv_size = MDC_DV_LINE_SIZE_8192;
776    }
777
778    /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
779
780    temp = READ_REG32(MDC_DV_CTL);
781    WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size);
782}
783
784/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */
785
786static void
787GXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
788{
789    SCRN_INFO_PTR(arg);
790    GeodeRec *pGeode = GEODEPTR(pScrni);
791    unsigned long offset;
792
793    offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3);
794
795    gfx_set_display_offset(offset);
796}
797
798static Bool
799GXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode)
800{
801    GeodeRec *pGeode = GEODEPTR(pScrni);
802    int flags = 0;
803    int custom = 0;
804
805    pScrni->vtSema = TRUE;
806
807    gx_disable_dac_power();
808
809    if (pMode->Flags & V_NHSYNC)
810        flags |= 1;
811    if (pMode->Flags & V_NVSYNC)
812        flags |= 2;
813
814    /* Check to see if we should use custom or built-in timings */
815
816    if (pGeode->Panel)
817        custom = (pMode->type & M_T_USERDEF);
818    else
819        custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
820
821    /* If we're not doing a custom mode, then just set the fixed timings,
822     * otherwise, do the whole shooting match */
823
824    if (!custom) {
825        GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY,
826                              pMode->CrtcHDisplay, pMode->CrtcVDisplay,
827                              pScrni->bitsPerPixel));
828    }
829    else {
830        if (pGeode->Panel)
831            GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY,
832                                  pMode->CrtcHDisplay, pMode->CrtcVDisplay,
833                                  pScrni->bitsPerPixel));
834
835        GFX(set_display_timings(pScrni->bitsPerPixel, flags,
836                                pMode->CrtcHDisplay, pMode->CrtcHBlankStart,
837                                pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd,
838                                pMode->CrtcHBlankEnd, pMode->CrtcHTotal,
839                                pMode->CrtcVDisplay, pMode->CrtcVBlankStart,
840                                pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd,
841                                pMode->CrtcVBlankEnd, pMode->CrtcVTotal,
842                                (int) ((pMode->SynthClock / 1000.0) *
843                                       0x10000)));
844    }
845
846    GFX(set_crt_enable(CRT_ENABLE));
847    GFX(set_display_pitch(pGeode->displayPitch));
848    GFX(set_display_offset(0L));
849    GFX(wait_vertical_blank());
850
851    if (pGeode->Compression) {
852        GXSetDvLineSize(pGeode->Pitch);
853
854        gfx_set_compression_offset(pGeode->CBData.compression_offset);
855        gfx_set_compression_pitch(GX_CB_PITCH);
856        gfx_set_compression_size(GX_CB_SIZE);
857
858        gfx_set_compression_enable(1);
859    }
860
861    if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) {
862        GXLoadCursorImage(pScrni, NULL);
863        GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0));
864        GXShowCursor(pScrni);
865    }
866    else {
867        GFX(set_cursor_enable(0));
868        pGeode->HWCursor = FALSE;
869    }
870
871    GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0));
872    gx_enable_dac_power();
873
874    return TRUE;
875}
876
877static Bool
878GXSwitchMode(SWITCH_MODE_ARGS_DECL)
879{
880    SCRN_INFO_PTR(arg);
881    GeodeRec *pGeode = GEODEPTR(pScrni);
882    int ret = TRUE;
883    int rotate;
884
885    /* Syn the engine and shutdown the DAC momentarily */
886
887    gfx_wait_until_idle();
888
889    /* Set up the memory for the new mode */
890    rotate = GXGetRotation(pScrni->pScreen);
891    ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate);
892
893    if (ret) {
894        if (pGeode->curMode != pMode)
895            ret = GXSetVideoMode(pScrni, pMode);
896    }
897
898    if (ret)
899        ret = GXRotate(pScrni, pMode);
900
901    /* Go back the way it was */
902
903    if (ret == FALSE) {
904        if (!GXSetVideoMode(pScrni, pGeode->curMode))
905            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
906                       "Could not restore the previous mode\n");
907    }
908    else
909        pGeode->curMode = pMode;
910
911    return ret;
912}
913
914static void
915GXLeaveGraphics(ScrnInfoPtr pScrni)
916{
917    GeodeRec *pGeode = GEODEPTR(pScrni);
918
919    gfx_wait_until_idle();
920
921    /* Restore VG registers */
922    gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp,
923                            pGeode->FBgfxdisplaytiming.wPolarity,
924                            pGeode->FBgfxdisplaytiming.wHActive,
925                            pGeode->FBgfxdisplaytiming.wHBlankStart,
926                            pGeode->FBgfxdisplaytiming.wHSyncStart,
927                            pGeode->FBgfxdisplaytiming.wHSyncEnd,
928                            pGeode->FBgfxdisplaytiming.wHBlankEnd,
929                            pGeode->FBgfxdisplaytiming.wHTotal,
930                            pGeode->FBgfxdisplaytiming.wVActive,
931                            pGeode->FBgfxdisplaytiming.wVBlankStart,
932                            pGeode->FBgfxdisplaytiming.wVSyncStart,
933                            pGeode->FBgfxdisplaytiming.wVSyncEnd,
934                            pGeode->FBgfxdisplaytiming.wVBlankEnd,
935                            pGeode->FBgfxdisplaytiming.wVTotal,
936                            pGeode->FBgfxdisplaytiming.dwDotClock);
937
938    gfx_set_compression_enable(0);
939
940    /* Restore the previous Compression state */
941    if (pGeode->FBCompressionEnable) {
942        gfx_set_compression_offset(pGeode->FBCompressionOffset);
943        gfx_set_compression_pitch(pGeode->FBCompressionPitch);
944        gfx_set_compression_size(pGeode->FBCompressionSize);
945        gfx_set_compression_enable(1);
946    }
947
948    gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch);
949
950    gfx_set_display_offset(pGeode->FBDisplayOffset);
951
952    /* Restore Cursor */
953    gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0);
954
955    if (pGeode->useVGA) {
956        pGeode->vesa->pInt->num = 0x10;
957        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
958        pGeode->vesa->pInt->bx = 0;
959        xf86ExecX86int10(pGeode->vesa->pInt);
960        gfx_delay_milliseconds(3);
961    }
962
963    GXRestore(pScrni);
964
965    gx_enable_dac_power();
966}
967
968static Bool
969GXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
970{
971    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
972    GeodeRec *pGeode = GEODEPTR(pScrni);
973
974    if (pScrni->vtSema)
975        GXLeaveGraphics(pScrni);
976
977#ifdef XF86XAA
978    if (pGeode->AccelInfoRec)
979        XAADestroyInfoRec(pGeode->AccelInfoRec);
980#endif
981
982    if (pGeode->AccelImageWriteBuffers) {
983        free(pGeode->AccelImageWriteBuffers[0]);
984        free(pGeode->AccelImageWriteBuffers);
985        pGeode->AccelImageWriteBuffers = NULL;
986    }
987
988    if (pGeode->AccelColorExpandBuffers) {
989        free(pGeode->AccelColorExpandBuffers);
990        pGeode->AccelColorExpandBuffers = NULL;
991    }
992
993    if (pGeode->pExa) {
994        exaDriverFini(pScrn);
995        free(pGeode->pExa);
996        pGeode->pExa = NULL;
997    }
998
999    pScrni->vtSema = FALSE;
1000
1001    GXUnmapMem(pScrni);
1002
1003    pScrni->PointerMoved = pGeode->PointerMoved;
1004    pScrn->CloseScreen = pGeode->CloseScreen;
1005
1006    if (pScrn->CloseScreen)
1007        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
1008
1009    return TRUE;
1010}
1011
1012static Bool
1013GXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
1014{
1015    GeodeRec *pGeode = GEODEPTR(pScrni);
1016
1017    if (!GXMapMem(pScrni))
1018        return FALSE;
1019
1020    if (pGeode->useVGA)
1021        pGeode->FBVGAActive = gu2_get_vga_active();
1022
1023    gfx_wait_until_idle();
1024
1025    /* Save off the current state (should this be somewhere else)? */
1026
1027    pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency();
1028    pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch();
1029    pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp();
1030    pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal();
1031    pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive();
1032    pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start();
1033    pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end();
1034    pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start();
1035    pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end();
1036    pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal();
1037    pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive();
1038    pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start();
1039    pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end();
1040    pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start();
1041    pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end();
1042    pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities();
1043
1044    pGeode->FBDisplayOffset = gfx_get_display_offset();
1045
1046    if (pGeode->useVGA) {
1047        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1048
1049        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
1050    }
1051
1052    pGeode->FBCompressionEnable = gfx_get_compression_enable();
1053    pGeode->FBCompressionOffset = gfx_get_compression_offset();
1054    pGeode->FBCompressionPitch = gfx_get_compression_pitch();
1055    pGeode->FBCompressionSize = gfx_get_compression_size();
1056
1057#ifdef PNL_SUP
1058    Pnl_SavePanelState();
1059#endif
1060
1061    /* Turn off the VGA */
1062
1063    if (pGeode->useVGA && pGeode->FBVGAActive) {
1064        unsigned short sequencer;
1065        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1066
1067        /* Map VGA aperture */
1068        if (!vgaHWMapMem(pScrni))
1069            return FALSE;
1070
1071        /* Unlock VGA registers */
1072        vgaHWUnlock(pvgaHW);
1073
1074        /* Save the current state and setup the current mode */
1075        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
1076
1077        /* DISABLE VGA SEQUENCER */
1078        /* This allows the VGA state machine to terminate. We must delay */
1079        /* such that there are no pending MBUS requests.  */
1080
1081        gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
1082        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
1083        sequencer |= MDC_CLK_MODE_SCREEN_OFF;
1084        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1085
1086        gfx_delay_milliseconds(1);
1087
1088        /* BLANK THE VGA DISPLAY */
1089        gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET);
1090        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
1091        sequencer &= ~MDC_RESET_VGA_DISP_ENABLE;
1092        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1093
1094        gfx_delay_milliseconds(1);
1095    }
1096
1097    /* Set up the memory */
1098    /* XXX - FIXME - when we alow inital rotation, it should be here */
1099    GXAllocateMemory(pScrn, pScrni, pGeode->rotation);
1100
1101    /* Clear the framebuffer */
1102    memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize);
1103
1104    /* Set up the video mode */
1105    GXSetVideoMode(pScrni, pScrni->currentMode);
1106    pGeode->curMode = pScrni->currentMode;
1107
1108    return TRUE;
1109}
1110
1111static void
1112GXLoadPalette(ScrnInfoPtr pScrni,
1113              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
1114{
1115    int i, index, color;
1116
1117    for (i = 0; i < numColors; i++) {
1118        index = indizes[i] & 0xFF;
1119        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
1120            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
1121            ((unsigned long) (colors[index].blue & 0xFF));
1122
1123        GFX(set_display_palette_entry(index, color));
1124    }
1125}
1126
1127#ifdef DPMSExtension
1128static void
1129GXPanelPower(int enable)
1130{
1131    unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT);
1132
1133    if (enable != 0)
1134        power |= RCDF_PM_PANEL_POWER_ON;
1135    else
1136        power &= ~RCDF_PM_PANEL_POWER_ON;
1137
1138    WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
1139}
1140
1141static void
1142GXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags)
1143{
1144    GeodeRec *pGeode;
1145
1146    pGeode = GEODEPTR(pScrni);
1147
1148    if (!pScrni->vtSema)
1149        return;
1150
1151    switch (mode) {
1152    case DPMSModeOn:
1153        /* Screen: On; HSync: On; VSync: On */
1154        GFX(set_crt_enable(CRT_ENABLE));
1155#if defined(PNL_SUP)
1156        if (pGeode->Panel) {
1157            Pnl_PowerUp();
1158            GXPanelPower(1);
1159        }
1160#endif
1161        break;
1162
1163    case DPMSModeStandby:
1164        /* Screen: Off; HSync: Off; VSync: On */
1165        GFX(set_crt_enable(CRT_STANDBY));
1166#if defined(PNL_SUP)
1167        if (pGeode->Panel) {
1168            Pnl_PowerDown();
1169            GXPanelPower(0);
1170        }
1171#endif
1172        break;
1173
1174    case DPMSModeSuspend:
1175        /* Screen: Off; HSync: On; VSync: Off */
1176        GFX(set_crt_enable(CRT_SUSPEND));
1177#if defined(PNL_SUP)
1178        if (pGeode->Panel) {
1179            Pnl_PowerDown();
1180            GXPanelPower(0);
1181        }
1182#endif
1183        break;
1184
1185    case DPMSModeOff:
1186        /* Screen: Off; HSync: Off; VSync: Off */
1187        GFX(set_crt_enable(CRT_DISABLE));
1188#if defined(PNL_SUP)
1189        if (pGeode->Panel) {
1190            Pnl_PowerDown();
1191            GXPanelPower(0);
1192        }
1193#endif
1194        break;
1195    }
1196}
1197#endif
1198
1199static Bool
1200GXCreateScreenResources(ScreenPtr pScreen)
1201{
1202    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
1203    GeodeRec *pGeode = GEODEPTR(pScrni);
1204
1205    pScreen->CreateScreenResources = pGeode->CreateScreenResources;
1206    if (!(*pScreen->CreateScreenResources) (pScreen))
1207        return FALSE;
1208
1209    if (xf86LoaderCheckSymbol("GXRandRSetConfig")
1210        && pGeode->rotation != RR_Rotate_0) {
1211        Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate,
1212                                     RRScreenSizePtr pSize) = NULL;
1213
1214        RRScreenSize p;
1215        Rotation requestedRotation = pGeode->rotation;
1216
1217        pGeode->rotation = RR_Rotate_0;
1218
1219        /* Just setup enough for an initial rotate */
1220
1221        p.width = pScreen->width;
1222        p.height = pScreen->height;
1223        p.mmWidth = pScreen->mmWidth;
1224        p.mmHeight = pScreen->mmHeight;
1225
1226        GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig");
1227        if (GXRandRSetConfig) {
1228            pGeode->starting = TRUE;
1229            (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p);
1230            pGeode->starting = FALSE;
1231        }
1232    }
1233
1234    return TRUE;
1235}
1236
1237static Bool
1238GXScreenInit(SCREEN_INIT_ARGS_DECL)
1239{
1240    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1241    GeodeRec *pGeode = GEODEPTR(pScrni);
1242    XF86ModReqInfo shadowReq;
1243    int maj, min, ret, rotate;
1244
1245    pGeode->starting = TRUE;
1246
1247    /* If we are using VGA then go ahead and map the memory */
1248
1249    if (pGeode->useVGA) {
1250
1251        if (!vgaHWMapMem(pScrni))
1252            return FALSE;
1253
1254        vgaHWGetIOBase(VGAHWPTR(pScrni));
1255    }
1256
1257    if (!pGeode->NoAccel) {
1258
1259        if (pGeode->useEXA) {
1260
1261            if (!(pGeode->pExa = exaDriverAlloc())) {
1262                xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1263                           "Couldn't allocate the EXA structure.\n");
1264                pGeode->NoAccel = TRUE;
1265            }
1266            else {
1267                ExaDriverPtr pExa = pGeode->pExa;
1268
1269                /* THis is set in GXAllocMem */
1270                pExa->memoryBase = 0;
1271
1272                /* This is set in GXAllocateMemory */
1273                pExa->memorySize = 0;
1274
1275                pExa->pixmapOffsetAlign = 32;
1276                pExa->pixmapPitchAlign = 32;
1277                pExa->flags = EXA_OFFSCREEN_PIXMAPS;
1278                pExa->maxX = GX_MAX_WIDTH - 1;
1279                pExa->maxY = GX_MAX_HEIGHT - 1;
1280            }
1281        }
1282        else {
1283            pGeode->AccelImageWriteBuffers =
1284                calloc(pGeode->NoOfImgBuffers,
1285                       sizeof(pGeode->AccelImageWriteBuffers[0]));
1286            pGeode->AccelColorExpandBuffers =
1287                calloc(pGeode->NoOfColorExpandLines,
1288                       sizeof(pGeode->AccelColorExpandBuffers[0]));
1289        }
1290    }
1291
1292    /* XXX FIXME - Take down any of the structures on failure? */
1293
1294    if (!GXEnterGraphics(pScrn, pScrni))
1295        return FALSE;
1296
1297    miClearVisualTypes();
1298
1299    /* XXX Again - take down anything? */
1300
1301    if (pScrni->bitsPerPixel > 8) {
1302        if (!miSetVisualTypes(pScrni->depth,
1303                              TrueColorMask, pScrni->rgbBits,
1304                              pScrni->defaultVisual)) {
1305            return FALSE;
1306        }
1307    }
1308    else {
1309        if (!miSetVisualTypes(pScrni->depth,
1310                              miGetDefaultVisualMask(pScrni->depth),
1311                              pScrni->rgbBits, pScrni->defaultVisual)) {
1312            return FALSE;
1313        }
1314    }
1315
1316    miSetPixmapDepths();
1317
1318    /* Point at the visible area to start */
1319
1320    ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset,
1321                       pScrni->virtualX, pScrni->virtualY,
1322                       pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth,
1323                       pScrni->bitsPerPixel);
1324
1325    if (!ret)
1326        return FALSE;
1327
1328    xf86SetBlackWhitePixels(pScrn);
1329
1330    /* Set up the color ordering */
1331
1332    if (pScrni->bitsPerPixel > 8) {
1333        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
1334
1335        while (--visual >= pScrn->visuals) {
1336            if ((visual->class | DynamicClass) == DirectColor) {
1337                visual->offsetRed = pScrni->offset.red;
1338                visual->offsetGreen = pScrni->offset.green;
1339                visual->offsetBlue = pScrni->offset.blue;
1340                visual->redMask = pScrni->mask.red;
1341                visual->greenMask = pScrni->mask.green;
1342                visual->blueMask = pScrni->mask.blue;
1343            }
1344        }
1345    }
1346
1347    /* Must follow the color ordering */
1348    fbPictureInit(pScrn, 0, 0);
1349
1350    if (!pGeode->NoAccel)
1351        GXAccelInit(pScrn);
1352
1353    xf86SetBackingStore(pScrn);
1354
1355    /* Set up the soft cursor */
1356    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
1357
1358    /* Set up the HW cursor - must follow the soft cursor init */
1359
1360    if (pGeode->tryHWCursor) {
1361        if (!GXHWCursorInit(pScrn))
1362            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1363                       "Hardware cursor initialization failed.\n");
1364    }
1365
1366    /* Set up the color map */
1367
1368    if (!miCreateDefColormap(pScrn))
1369        return FALSE;
1370
1371    if (pScrni->bitsPerPixel == 8) {
1372        /* Must follow initialization of the default colormap */
1373
1374        if (!xf86HandleColormaps(pScrn, 256, 8,
1375                                 GXLoadPalette, NULL,
1376                                 CMAP_PALETTED_TRUECOLOR |
1377                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
1378            return FALSE;
1379        }
1380    }
1381#ifdef DPMSExtension
1382    xf86DPMSInit(pScrn, GXDPMSSet, 0);
1383#endif
1384
1385    GXInitVideo(pScrn);
1386
1387    /* Set up RandR */
1388
1389    xf86DisableRandR();         /* We provide our own RandR goodness */
1390
1391    /* Try to set up the shadow FB for rotation */
1392
1393    memset(&shadowReq, 0, sizeof(shadowReq));
1394    shadowReq.majorversion = 1;
1395    shadowReq.minorversion = 1;
1396
1397    if (LoadSubModule(pScrni->module, "shadow",
1398                      NULL, NULL, NULL, &shadowReq, &maj, &min)) {
1399
1400        rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
1401        shadowSetup(pScrn);
1402    }
1403    else {
1404        LoaderErrorMsg(NULL, "shadow", maj, min);
1405        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1406                   "Error loading shadow - rotation not available.\n");
1407
1408        if (pGeode->rotation != RR_Rotate_0)
1409            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1410                       "Reverting back to normal rotation.\n");
1411
1412        rotate = pGeode->rotation = RR_Rotate_0;
1413    }
1414
1415    GXRandRInit(pScrn, rotate);
1416
1417    pGeode->PointerMoved = pScrni->PointerMoved;
1418    pScrni->PointerMoved = GeodePointerMoved;
1419
1420    pGeode->CreateScreenResources = pScrn->CreateScreenResources;
1421    pScrn->CreateScreenResources = GXCreateScreenResources;
1422
1423    pGeode->CloseScreen = pScrn->CloseScreen;
1424    pScrn->CloseScreen = GXCloseScreen;
1425    pScrn->SaveScreen = GXSaveScreen;
1426
1427    if (serverGeneration == 1)
1428        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1429
1430    pGeode->starting = FALSE;
1431
1432    return TRUE;
1433}
1434
1435static int
1436GXValidMode(VALID_MODE_ARGS_DECL)
1437{
1438    SCRN_INFO_PTR(arg);
1439    GeodeRec *pGeode = GEODEPTR(pScrni);
1440    int p;
1441    int custom = 0;
1442
1443    if (pGeode->Panel)
1444        custom = (pMode->type & M_T_USERDEF);
1445    else
1446        custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
1447
1448    /* Use the durango lookup for !custom modes */
1449
1450    if (!custom && pGeode->Panel) {
1451        if (pMode->CrtcHDisplay > pGeode->PanelX ||
1452            pMode->CrtcVDisplay > pGeode->PanelY ||
1453            gfx_is_panel_mode_supported(pGeode->PanelX,
1454                                        pGeode->PanelY,
1455                                        pMode->CrtcHDisplay,
1456                                        pMode->CrtcVDisplay,
1457                                        pScrni->bitsPerPixel) < 0) {
1458
1459            return MODE_BAD;
1460        }
1461    }
1462
1463    if (gfx_is_display_mode_supported(pMode->CrtcHDisplay,
1464                                      pMode->CrtcVDisplay,
1465                                      pScrni->bitsPerPixel,
1466                                      GeodeGetRefreshRate(pMode)) < 0) {
1467        return MODE_BAD;
1468    }
1469
1470    if (pMode->Flags & V_INTERLACE)
1471        return MODE_NO_INTERLACE;
1472
1473    if (pGeode->tryCompression)
1474        p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel);
1475    else
1476        p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
1477
1478    if (p * pMode->CrtcVDisplay > pGeode->FBAvail)
1479        return MODE_MEM;
1480
1481    return MODE_OK;
1482}
1483
1484/* XXX - Way more to do here */
1485
1486static Bool
1487GXEnterVT(VT_FUNC_ARGS_DECL)
1488{
1489    SCRN_INFO_PTR(arg);
1490    return GXEnterGraphics(NULL, pScrni);
1491}
1492
1493static void
1494GXLeaveVT(VT_FUNC_ARGS_DECL)
1495{
1496    SCRN_INFO_PTR(arg);
1497    GeodeRec *pGeode = GEODEPTR(pScrni);
1498
1499    pGeode->PrevDisplayOffset = gfx_get_display_offset();
1500    GXLeaveGraphics(pScrni);
1501}
1502
1503void
1504GXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1505{
1506    pScrn->PreInit = GXPreInit;
1507    pScrn->ScreenInit = GXScreenInit;
1508    pScrn->SwitchMode = GXSwitchMode;
1509    pScrn->AdjustFrame = GXAdjustFrame;
1510    pScrn->EnterVT = GXEnterVT;
1511    pScrn->LeaveVT = GXLeaveVT;
1512    pScrn->FreeScreen = GeodeFreeScreen;
1513    pScrn->ValidMode = GXValidMode;
1514}
1515
1516/* ====== Common functions ======
1517 * These are all the common functions that we use for both GX and LX - They live here
1518 * because most of them came along for the GX first, and then were adapted to the LX.
1519 *  We could move these to a common function, but there is no hurry
1520 * ============================== */
1521
1522void
1523GeodePointerMoved(POINTER_MOVED_ARGS_DECL)
1524{
1525    SCRN_INFO_PTR(arg);
1526    GeodeRec *pGeode = GEODEPTR(pScrni);
1527
1528    int newX = x, newY = y;
1529
1530    switch (pGeode->rotation) {
1531    case RR_Rotate_0:
1532        break;
1533    case RR_Rotate_90:
1534        newX = y;
1535        newY = pScrni->pScreen->width - x - 1;
1536        break;
1537    case RR_Rotate_180:
1538        newX = pScrni->pScreen->width - x - 1;
1539        newY = pScrni->pScreen->height - y - 1;
1540        break;
1541    case RR_Rotate_270:
1542        newX = pScrni->pScreen->height - y - 1;
1543        newY = x;
1544        break;
1545    }
1546
1547    (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY));
1548}
1549
1550int
1551GeodeGetFPGeometry(const char *str, int *width, int *height)
1552{
1553
1554    int ret = sscanf(str, "%dx%d", width, height);
1555
1556    return (ret == 2) ? 0 : 1;
1557}
1558
1559static void
1560GeodeFreeRec(ScrnInfoPtr pScrni)
1561{
1562    if (pScrni->driverPrivate != NULL) {
1563        free(pScrni->driverPrivate);
1564        pScrni->driverPrivate = NULL;
1565    }
1566}
1567
1568void
1569GeodeFreeScreen(FREE_SCREEN_ARGS_DECL)
1570{
1571    SCRN_INFO_PTR(arg);
1572    GeodeRec *pGeode = GEODEPTR(pScrni);
1573
1574    if (pGeode == NULL)
1575        return;
1576
1577    if (pGeode->useVGA) {
1578        if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1579            vgaHWFreeHWRec(pScrni);
1580    }
1581
1582    GeodeFreeRec(pScrni);
1583}
1584
1585int
1586GeodeCalculatePitchBytes(unsigned int width, unsigned int bpp)
1587{
1588
1589    int delta = width * (bpp >> 3);
1590
1591    /* Less then 640 has doubling enabled */
1592
1593    if (width < 640)
1594        delta <<= 1;
1595
1596    /* Calculate the pitch (compression rquires a power of 2) */
1597
1598    if (delta > 4096)
1599        delta = 8192;
1600    else if (delta > 2048)
1601        delta = 4096;
1602    else if (delta > 1024)
1603        delta = 2048;
1604    else
1605        delta = 1024;
1606
1607    return delta;
1608}
1609