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