1f29dbc25Smrg/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Portioned modeled from xf86-video-intel/src/i830_driver.c
4f29dbc25Smrg * Copyright 2001 VA Linux Systems Inc., Fremont, California.
5f29dbc25Smrg * Copyright \ufffd 2002 by David Dawes
6f29dbc25Smrg
7f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
8f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
9f29dbc25Smrg * deal in the Software without restriction, including without limitation the
10f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
12f29dbc25Smrg * furnished to do so, subject to the following conditions:
13f29dbc25Smrg *
14f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
15f29dbc25Smrg * all copies or substantial portions of the Software.
16f29dbc25Smrg *
17f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23f29dbc25Smrg * IN THE SOFTWARE.
24f29dbc25Smrg *
25f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
26f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
27f29dbc25Smrg * software without specific prior written permission.
28f29dbc25Smrg */
29f29dbc25Smrg
30f29dbc25Smrg#ifdef HAVE_CONFIG_H
31f29dbc25Smrg#include "config.h"
32f29dbc25Smrg#endif
33f29dbc25Smrg
34f29dbc25Smrg#include <stdio.h>
357f419768Smrg#include <fcntl.h>
367f419768Smrg#include <unistd.h>
377f419768Smrg#include <sys/mman.h>
38f29dbc25Smrg
3900be8644Schristos#include "xorg-server.h"
4000be8644Schristos
41f29dbc25Smrg#include "xf86.h"
42f29dbc25Smrg#include "xf86_OSproc.h"
43f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
44f29dbc25Smrg#include "xf86Resources.h"
45f29dbc25Smrg#endif
46f29dbc25Smrg#include "xf86cmap.h"
47f29dbc25Smrg#include "compiler.h"
48f29dbc25Smrg#include "mipointer.h"
49f29dbc25Smrg#include "shadow.h"
50f29dbc25Smrg#include <X11/extensions/randr.h>
51f29dbc25Smrg#include "fb.h"
52f29dbc25Smrg#include "miscstruct.h"
53f29dbc25Smrg#include "micmap.h"
54f29dbc25Smrg#include "vbe.h"
55f29dbc25Smrg#include "fb.h"
56f29dbc25Smrg#include "randrstr.h"
57f29dbc25Smrg
58f29dbc25Smrg#include "geode.h"
59f29dbc25Smrg#include "gfx_defs.h"
60f29dbc25Smrg#include "gfx_regs.h"
61f29dbc25Smrg#include "panel.h"
62f29dbc25Smrg
63f29dbc25Smrg/* Bring in VGA functions */
64f29dbc25Smrg#include "gx_vga.c"
65f29dbc25Smrg
66f29dbc25Smrg#define GX_MIN_PITCH 1024
67f29dbc25Smrg#define GX_MAX_PITCH 8192
68f29dbc25Smrg#define GX_MAX_WIDTH  1600
69f29dbc25Smrg#define GX_MIN_HEIGHT  400
70f29dbc25Smrg#define GX_MAX_HEIGHT 1200
71f29dbc25Smrg#define GX_CB_PITCH   544
72f29dbc25Smrg#define GX_CB_SIZE    544
73f29dbc25Smrg
74f29dbc25Smrg#define GX_CPU_REG_SIZE 0x4000
75f29dbc25Smrg#define GX_GP_REG_SIZE  0x4000
76f29dbc25Smrg#define GX_VID_REG_SIZE 0x4000
77f29dbc25Smrg
78f29dbc25Smrg#define DEFAULT_IMG_LINE_BUFS 20
79f29dbc25Smrg#define DEFAULT_CLR_LINE_BUFS 20
80f29dbc25Smrg
81f29dbc25Smrgextern OptionInfoRec GX_GeodeOptions[];
82f29dbc25Smrg
83c744f008Smrgextern unsigned char *XpressROMPtr;
84f29dbc25Smrg
85f29dbc25Smrgstatic inline void
86f29dbc25Smrggx_enable_dac_power(void)
87f29dbc25Smrg{
88f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
8904007ebaSmrg                    gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH);
90f29dbc25Smrg}
91f29dbc25Smrg
92f29dbc25Smrgstatic inline void
93f29dbc25Smrggx_disable_dac_power(void)
94f29dbc25Smrg{
95f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
9604007ebaSmrg                    RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN |
9704007ebaSmrg                    (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH));
98f29dbc25Smrg}
99f29dbc25Smrg
100f29dbc25Smrgstatic void
101f29dbc25SmrgGXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
102f29dbc25Smrg{
103f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
104f29dbc25Smrg
105f29dbc25Smrg    if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) {
10604007ebaSmrg        pGeode->exaBfrOffset = *offset;
10704007ebaSmrg        *offset += pGeode->exaBfrOffset;
10804007ebaSmrg        *avail -= pGeode->exaBfrOffset;
109f29dbc25Smrg    }
110f29dbc25Smrg}
111f29dbc25Smrg
112f29dbc25Smrgstatic void
113f29dbc25SmrgGXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
114f29dbc25Smrg{
115f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
116f29dbc25Smrg    unsigned int size, i, pitch;
117f29dbc25Smrg
118f29dbc25Smrg    /* XXX - FIXME - What if we are out of room?  Then what? */
119f29dbc25Smrg    /* For now, we NULL them all out.                        */
120f29dbc25Smrg
121f29dbc25Smrg    if (pGeode->NoOfImgBuffers > 0) {
12204007ebaSmrg        size = pGeode->displayPitch * pGeode->NoOfImgBuffers;
12304007ebaSmrg        if (size <= *avail) {
12404007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++) {
12504007ebaSmrg                pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset;
12604007ebaSmrg                *offset += pGeode->displayPitch;
12704007ebaSmrg                *avail -= pGeode->displayPitch;
12804007ebaSmrg            }
12904007ebaSmrg        }
13004007ebaSmrg        else {
13104007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
13204007ebaSmrg                       "Not enough memory for image write buffers.\n");
13304007ebaSmrg
13404007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
13504007ebaSmrg                pGeode->AccelImageWriteBuffers[i] = NULL;
13604007ebaSmrg        }
137f29dbc25Smrg    }
138f29dbc25Smrg
139f29dbc25Smrg    if (pGeode->NoOfColorExpandLines > 0) {
14004007ebaSmrg        pitch = ((pGeode->displayPitch + 31) >> 5) << 2;
14104007ebaSmrg        size = pitch * pGeode->NoOfColorExpandLines;
14204007ebaSmrg
14304007ebaSmrg        if (size <= *avail) {
14404007ebaSmrg            for (i = 0; i < pGeode->NoOfColorExpandLines; i++) {
14504007ebaSmrg                pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset;
14604007ebaSmrg                *offset += pitch;
14704007ebaSmrg                *avail -= pitch;
14804007ebaSmrg            }
14904007ebaSmrg        }
15004007ebaSmrg        else {
15104007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
15204007ebaSmrg                       "Not enough memory for color expansion buffers.\n");
15304007ebaSmrg
15404007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
15504007ebaSmrg                pGeode->AccelColorExpandBuffers[i] = NULL;
15604007ebaSmrg        }
157f29dbc25Smrg    }
158f29dbc25Smrg}
159f29dbc25Smrg
160f29dbc25Smrgstatic Bool
161f29dbc25SmrgGXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate)
162f29dbc25Smrg{
163f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
164f29dbc25Smrg
165f29dbc25Smrg    unsigned int fboffset, fbavail;
166f29dbc25Smrg    unsigned int size;
167f29dbc25Smrg    unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8;
168f29dbc25Smrg    BOOL ret = TRUE;
169f29dbc25Smrg
170f29dbc25Smrg    if (pGeode->tryCompression)
17104007ebaSmrg        pGeode->displayPitch =
17204007ebaSmrg            GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
173f29dbc25Smrg    else
17404007ebaSmrg        pGeode->displayPitch =
17504007ebaSmrg            ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
176f29dbc25Smrg
177f29dbc25Smrg    pGeode->Pitch = pGeode->displayPitch;
178f29dbc25Smrg    pGeode->displayWidth = pGeode->displayPitch / bytpp;
179f29dbc25Smrg    pScrni->displayWidth = pGeode->displayWidth;
180f29dbc25Smrg
181f29dbc25Smrg    fbavail = pGeode->FBAvail - 0x4000;
182f29dbc25Smrg
183f29dbc25Smrg    pGeode->displayOffset = fboffset = 0;
184f29dbc25Smrg    pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch;
185f29dbc25Smrg
186f29dbc25Smrg    fbavail -= pGeode->displaySize;
187f29dbc25Smrg    fboffset += pGeode->displaySize;
188f29dbc25Smrg
189f29dbc25Smrg    if (pGeode->tryCompression) {
19004007ebaSmrg        size = pScrni->virtualY * GX_CB_PITCH;
191f29dbc25Smrg
19204007ebaSmrg        if (size <= fbavail) {
19304007ebaSmrg            pGeode->CBData.compression_offset = fboffset;
194f29dbc25Smrg
19504007ebaSmrg            fboffset += size;
19604007ebaSmrg            fbavail -= size;
197f29dbc25Smrg
19804007ebaSmrg            pGeode->Compression = TRUE;
19904007ebaSmrg        }
20004007ebaSmrg        else {
20104007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
20204007ebaSmrg                       "Not enough memory for compression\n");
20304007ebaSmrg            pGeode->Compression = FALSE;
20404007ebaSmrg        }
205f29dbc25Smrg    }
206f29dbc25Smrg
207f29dbc25Smrg    if (pGeode->tryHWCursor) {
208f29dbc25Smrg
20904007ebaSmrg        if (fbavail >= 1024) {
21004007ebaSmrg            pGeode->CursorStartOffset = fboffset;
21104007ebaSmrg            fboffset += 1024;
21204007ebaSmrg            fbavail -= 1024;
21304007ebaSmrg            pGeode->HWCursor = TRUE;
21404007ebaSmrg        }
21504007ebaSmrg        else {
21604007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
21704007ebaSmrg                       "Not enough memory for the hardware cursor\n");
21804007ebaSmrg            pGeode->HWCursor = FALSE;
21904007ebaSmrg        }
220f29dbc25Smrg    }
221f29dbc25Smrg
222f29dbc25Smrg    if (!pGeode->NoAccel) {
22304007ebaSmrg        if (pGeode->useEXA)
22404007ebaSmrg            GXInitEXAMemory(pScrni, &fboffset, &fbavail);
22504007ebaSmrg        else
22604007ebaSmrg            GXInitXAAMemory(pScrni, &fboffset, &fbavail);
227f29dbc25Smrg    }
228f29dbc25Smrg
229f29dbc25Smrg    pGeode->shadowSize = 0;
230f29dbc25Smrg
231f29dbc25Smrg    if (rotate != RR_Rotate_0) {
23204007ebaSmrg        if (rotate & (RR_Rotate_90 | RR_Rotate_270))
23304007ebaSmrg            size = pGeode->displayPitch * pScrni->virtualX;
23404007ebaSmrg        else
23504007ebaSmrg            size = pGeode->displayPitch * pScrni->virtualY;
23604007ebaSmrg
23704007ebaSmrg        if (size <= fbavail) {
23804007ebaSmrg            pGeode->shadowOffset = fboffset;
23904007ebaSmrg            pGeode->shadowSize = size;
24004007ebaSmrg
24104007ebaSmrg            fboffset += size;
24204007ebaSmrg            fbavail -= size;
24304007ebaSmrg        }
24404007ebaSmrg        else {
24504007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
24604007ebaSmrg                       "Not enough memory for the shadow framebuffer\n");
24704007ebaSmrg            ret = FALSE;
24804007ebaSmrg        }
249f29dbc25Smrg    }
250f29dbc25Smrg
251f29dbc25Smrg    /* XAA always exists - we can't remove it on demand like we can with EXA.
252f29dbc25Smrg     * So we assume the worse, and only give XAA enough offspace room to
253f29dbc25Smrg     * account for any eventuality that RandR might throw at us. */
254f29dbc25Smrg
255f29dbc25Smrg    if (!pGeode->NoAccel) {
256f29dbc25Smrg
25704007ebaSmrg        if (pGeode->useEXA && pGeode->pExa) {
25804007ebaSmrg            ExaDriverPtr pExa = pGeode->pExa;
259f29dbc25Smrg
26004007ebaSmrg            pExa->offScreenBase = fboffset;
26104007ebaSmrg            pExa->memorySize = fboffset + fbavail;
26204007ebaSmrg        }
263f29dbc25Smrg
26404007ebaSmrg        if (!pGeode->useEXA) {
265f29dbc25Smrg
26604007ebaSmrg#if XF86XAA
26704007ebaSmrg            if (!xf86FBManagerRunning(pScrn)) {
268f29dbc25Smrg
26904007ebaSmrg                unsigned int offset = fboffset;
27004007ebaSmrg                unsigned int avail = fbavail;
27104007ebaSmrg                RegionRec OffscreenRegion;
27204007ebaSmrg                BoxRec AvailBox;
273f29dbc25Smrg
274c744f008Smrg                /* Assume the shadow FB exists even if it doesn't */
275f29dbc25Smrg
27604007ebaSmrg                if (pGeode->shadowSize == 0) {
27704007ebaSmrg                    size = (pScrn->width * bytpp) * pScrni->virtualX;
27804007ebaSmrg                    offset += size;
27904007ebaSmrg                    avail -= size;
28004007ebaSmrg                }
281f29dbc25Smrg
28204007ebaSmrg                AvailBox.x1 = 0;
28304007ebaSmrg                AvailBox.y1 =
28404007ebaSmrg                    (offset + pGeode->displayPitch - 1) / pGeode->displayPitch;
285f29dbc25Smrg
28604007ebaSmrg                AvailBox.x2 = pGeode->displayWidth;
28704007ebaSmrg                AvailBox.y2 = (offset + avail) / pGeode->displayPitch;
288f29dbc25Smrg
28904007ebaSmrg                if (AvailBox.y1 < AvailBox.y2) {
29004007ebaSmrg                    REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2);
291f29dbc25Smrg
29204007ebaSmrg                    if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion))
29304007ebaSmrg                        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
29404007ebaSmrg                                   "Memory manager initialization failed.\n");
295f29dbc25Smrg
29604007ebaSmrg                    REGION_UNINIT(pScrn, &OffscreenRegion);
29704007ebaSmrg                }
29804007ebaSmrg                else
29904007ebaSmrg                    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
30004007ebaSmrg                               "Cache disabled - no offscreen memory available.\n");
30104007ebaSmrg            }
30204007ebaSmrg            else
30304007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_INFO,
30404007ebaSmrg                           "XAA offscreen memory has already been allocated.\n");
30504007ebaSmrg#endif
30604007ebaSmrg        }
307f29dbc25Smrg    }
308f29dbc25Smrg    return ret;
309f29dbc25Smrg}
310f29dbc25Smrg
311f29dbc25Smrgstatic Bool
312f29dbc25SmrgGXSaveScreen(ScreenPtr pScrn, int mode)
313f29dbc25Smrg{
31404007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
315f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
316f29dbc25Smrg
317f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
31804007ebaSmrg        return vgaHWSaveScreen(pScrn, mode);
319f29dbc25Smrg
320f29dbc25Smrg    return TRUE;
321f29dbc25Smrg}
322f29dbc25Smrg
323f29dbc25Smrg/* Common function - used by the LX too */
324f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
325f29dbc25Smrgstatic inline void *
326f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
32704007ebaSmrg            struct pci_device *dev, int bar, int size)
328f29dbc25Smrg{
329f29dbc25Smrg    void *ptr;
330f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
331f29dbc25Smrg
332f29dbc25Smrg    int err = pci_device_map_range(dev,
33304007ebaSmrg                                   dev->regions[bar].base_addr,
33404007ebaSmrg                                   map_size,
33504007ebaSmrg                                   PCI_DEV_MAP_FLAG_WRITABLE |
33604007ebaSmrg                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
3377f419768Smrg                                   &ptr);
338f29dbc25Smrg
339f29dbc25Smrg    if (err)
34004007ebaSmrg        return NULL;
341f29dbc25Smrg    return ptr;
342f29dbc25Smrg}
3437f419768Smrg
3447f419768Smrgstatic inline int
3457f419768Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
3467f419768Smrg{
3477f419768Smrg    return pci_device_unmap_range(dev, ptr, size);
3487f419768Smrg}
349f29dbc25Smrg#endif
350f29dbc25Smrg
351f29dbc25Smrgextern unsigned long gfx_gx2_scratch_base;
352f29dbc25Smrg
353f29dbc25Smrgstatic Bool
354f29dbc25SmrgGXMapMem(ScrnInfoPtr pScrni)
355f29dbc25Smrg{
356f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
357f29dbc25Smrg    int index = pScrni->scrnIndex;
358f29dbc25Smrg
359f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
360f29dbc25Smrg
361f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
36204007ebaSmrg    gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
36304007ebaSmrg                                                      pci->memBase[2],
36404007ebaSmrg                                                      pci->size[2]);
365f29dbc25Smrg
36604007ebaSmrg    gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
36704007ebaSmrg                                                     pci->memBase[1],
36804007ebaSmrg                                                     pci->size[1]);
369f29dbc25Smrg
37004007ebaSmrg    gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
37104007ebaSmrg                                                      pci->memBase[3],
37204007ebaSmrg                                                      pci->size[3]);
373f29dbc25Smrg
37404007ebaSmrg    gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER,
37504007ebaSmrg                                                     pci->memBase[0],
37604007ebaSmrg                                                     pGeode->FBAvail);
377f29dbc25Smrg#else
378f29dbc25Smrg    gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0);
379f29dbc25Smrg    gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0);
380f29dbc25Smrg    gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0);
381f29dbc25Smrg    gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail);
382f29dbc25Smrg#endif
383f29dbc25Smrg
384f29dbc25Smrg    gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000;
385f29dbc25Smrg
3867f419768Smrg#ifndef XSERVER_LIBPCIACCESS
387f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
3887f419768Smrg#else
3897f419768Smrg    {
3907f419768Smrg        int fd = open("/dev/mem", O_RDWR);
3917f419768Smrg        if (fd < 0) {
3927f419768Smrg            xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n");
3937f419768Smrg            return FALSE;
3947f419768Smrg        }
3957f419768Smrg        XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000);
3967f419768Smrg        close(fd);
3977f419768Smrg    }
3987f419768Smrg#endif
399f29dbc25Smrg    pGeode->FBBase = gfx_virt_fbptr;
400f29dbc25Smrg
401f29dbc25Smrg    if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) ||
40204007ebaSmrg        (!gfx_virt_vidptr) || (!gfx_virt_fbptr))
40304007ebaSmrg        return FALSE;
404f29dbc25Smrg
405f29dbc25Smrg    if (!pGeode->NoAccel && pGeode->useEXA)
40604007ebaSmrg        pGeode->pExa->memoryBase = pGeode->FBBase;
407f29dbc25Smrg
408f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n",
40904007ebaSmrg               pGeode->FBAvail, pGeode->FBBase);
410f29dbc25Smrg
411f29dbc25Smrg    return TRUE;
412f29dbc25Smrg}
413f29dbc25Smrg
414f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
415f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
416f29dbc25Smrg*/
417f29dbc25Smrg
418f29dbc25Smrgstatic Bool
4197f419768SmrgGXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt)
420f29dbc25Smrg{
4217f419768Smrg#ifndef XSERVER_LIBPCIACCESS
422f29dbc25Smrg    unsigned char *ptr;
423f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
424f29dbc25Smrg    int ret;
425f29dbc25Smrg
426f29dbc25Smrg    ptr =
42704007ebaSmrg        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
42804007ebaSmrg                      strlen(vgasig));
429f29dbc25Smrg
430f29dbc25Smrg    if (ptr == NULL)
43104007ebaSmrg        return FALSE;
432f29dbc25Smrg
433f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
434f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
435f29dbc25Smrg
436f29dbc25Smrg    return ret ? FALSE : TRUE;
4377f419768Smrg#else
4387f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index);
4397f419768Smrg
4407f419768Smrg    return pci_device_is_boot_vga(pci);
4417f419768Smrg#endif
442f29dbc25Smrg}
443f29dbc25Smrg
444f29dbc25Smrgstatic Bool
445f29dbc25SmrgGXPreInit(ScrnInfoPtr pScrni, int flags)
446f29dbc25Smrg{
447f29dbc25Smrg    GeodePtr pGeode;
448f29dbc25Smrg    ClockRangePtr GeodeClockRange;
449f29dbc25Smrg    OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0];
450f29dbc25Smrg    int ret;
451f29dbc25Smrg    QQ_WORD msrValue;
452f29dbc25Smrg    EntityInfoPtr pEnt;
453f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
454f29dbc25Smrg    int modecnt;
4553406bd8eSmrg    const char *s, *panelgeo;
456f29dbc25Smrg    Bool useVGA;
457f29dbc25Smrg
458f29dbc25Smrg    if (pScrni->numEntities != 1)
45904007ebaSmrg        return FALSE;
460f29dbc25Smrg
461f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
462f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
463f29dbc25Smrg    if (pEnt->resources)
46404007ebaSmrg        return FALSE;
465f29dbc25Smrg#endif
466f29dbc25Smrg
46704007ebaSmrg    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
468f29dbc25Smrg
469f29dbc25Smrg    if (pGeode == NULL)
47004007ebaSmrg        return FALSE;
471f29dbc25Smrg
4727f419768Smrg    useVGA = GXCheckVGA(pScrni, pEnt);
473f29dbc25Smrg
474f29dbc25Smrg    if (flags & PROBE_DETECT) {
47504007ebaSmrg        GeodeProbeDDC(pScrni, pEnt->index);
47604007ebaSmrg        return TRUE;
477f29dbc25Smrg    }
478f29dbc25Smrg
479f29dbc25Smrg    /* Probe for VGA */
480f29dbc25Smrg    pGeode->useVGA = useVGA;
481f29dbc25Smrg    pGeode->pEnt = pEnt;
482f29dbc25Smrg
483f29dbc25Smrg    if (pGeode->useVGA) {
48404007ebaSmrg        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
48504007ebaSmrg            pGeode->useVGA = FALSE;
48604007ebaSmrg        else
48704007ebaSmrg            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
488f29dbc25Smrg
489f29dbc25Smrg#if INT10_SUPPORT
49004007ebaSmrg        pGeode->vesa = calloc(1, sizeof(VESARec));
491f29dbc25Smrg#endif
492f29dbc25Smrg    }
493f29dbc25Smrg
494f29dbc25Smrg    gfx_msr_init();
495f29dbc25Smrg
496f29dbc25Smrg    ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue);
497f29dbc25Smrg
498f29dbc25Smrg    if (!ret) {
49904007ebaSmrg        pGeode->Output =
50004007ebaSmrg            ((msrValue.low & RCDF_CONFIG_FMT_MASK) ==
50104007ebaSmrg             RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT;
502f29dbc25Smrg    }
503f29dbc25Smrg
504f29dbc25Smrg    /* Fill in the monitor information */
505f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
506f29dbc25Smrg
507f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
50804007ebaSmrg        return FALSE;
509f29dbc25Smrg
510f29dbc25Smrg    switch (pScrni->depth) {
511f29dbc25Smrg    case 8:
51204007ebaSmrg        pScrni->rgbBits = 8;
513f29dbc25Smrg    case 16:
514f29dbc25Smrg    case 24:
515f29dbc25Smrg    case 32:
51604007ebaSmrg        break;
517f29dbc25Smrg    default:
51804007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
51904007ebaSmrg                   "The driver does not support %d as a depth.\n",
52004007ebaSmrg                   pScrni->depth);
52104007ebaSmrg        return FALSE;
522f29dbc25Smrg    }
523f29dbc25Smrg
524f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
525f29dbc25Smrg
526f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
52704007ebaSmrg        return FALSE;
528f29dbc25Smrg
529f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
53004007ebaSmrg        return FALSE;
531f29dbc25Smrg
532f29dbc25Smrg    /*
533f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
534f29dbc25Smrg     * here.
535f29dbc25Smrg     */
536f29dbc25Smrg    {
53704007ebaSmrg        Gamma zeros = { 0.0, 0.0, 0.0 };
538f29dbc25Smrg
53904007ebaSmrg        if (!xf86SetGamma(pScrni, zeros)) {
54004007ebaSmrg            return FALSE;
54104007ebaSmrg        }
542f29dbc25Smrg    }
543f29dbc25Smrg
544f29dbc25Smrg    pScrni->progClock = TRUE;
545f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
546f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
547f29dbc25Smrg
548f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
549f29dbc25Smrg
550f29dbc25Smrg    pGeode->FBVGAActive = FALSE;
551f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
552f29dbc25Smrg    pGeode->tryCompression = TRUE;
553f29dbc25Smrg
554f29dbc25Smrg    pGeode->NoAccel = FALSE;
555f29dbc25Smrg    pGeode->useEXA = FALSE;
556f29dbc25Smrg
557f29dbc25Smrg    pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE;
558f29dbc25Smrg
559f29dbc25Smrg    pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS;
560f29dbc25Smrg    pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS;
561f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
562f29dbc25Smrg
56304007ebaSmrg    xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
564f29dbc25Smrg
565f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE,
56604007ebaSmrg                              (int *) &(pGeode->FBAvail)))
56704007ebaSmrg        pGeode->FBAvail = 0;
568f29dbc25Smrg
569c744f008Smrg    /* For compatibility - allow SWCursor too */
570f29dbc25Smrg
571f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE))
57204007ebaSmrg        pGeode->tryHWCursor = FALSE;
573f29dbc25Smrg
574f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE))
57504007ebaSmrg        pGeode->tryCompression = FALSE;
576f29dbc25Smrg
577f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE))
57804007ebaSmrg        pGeode->NoAccel = TRUE;
579f29dbc25Smrg
580f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
581f29dbc25Smrg
582f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) {
583f29dbc25Smrg
58404007ebaSmrg        if (!xf86NameCmp(s, "LEFT"))
58504007ebaSmrg            pGeode->rotation = RR_Rotate_90;
58604007ebaSmrg        else if (!xf86NameCmp(s, "INVERT"))
58704007ebaSmrg            pGeode->rotation = RR_Rotate_180;
58804007ebaSmrg        else if (!xf86NameCmp(s, "CCW"))
58904007ebaSmrg            pGeode->rotation = RR_Rotate_270;
59004007ebaSmrg        else
59104007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
592f29dbc25Smrg    }
593f29dbc25Smrg
594f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS,
59504007ebaSmrg                         &(pGeode->NoOfImgBuffers));
596f29dbc25Smrg
597f29dbc25Smrg    if (pGeode->NoOfImgBuffers <= 0)
59804007ebaSmrg        pGeode->NoOfImgBuffers = 0;
599f29dbc25Smrg
600f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
60104007ebaSmrg                         &(pGeode->NoOfColorExpandLines));
602f29dbc25Smrg
603f29dbc25Smrg    if (pGeode->NoOfColorExpandLines <= 0)
60404007ebaSmrg        pGeode->NoOfColorExpandLines = 0;
605f29dbc25Smrg
606f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
60704007ebaSmrg                         (int *) &(pGeode->exaBfrSz));
608f29dbc25Smrg
609f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
61004007ebaSmrg        pGeode->exaBfrSz = 0;
611f29dbc25Smrg
612f29dbc25Smrg    if (pGeode->Panel == TRUE) {
61304007ebaSmrg        if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE))
61404007ebaSmrg            pGeode->Panel = FALSE;
615f29dbc25Smrg    }
616f29dbc25Smrg
617f29dbc25Smrg    panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY);
618f29dbc25Smrg
619f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) {
6207f419768Smrg#if defined(XF86XAA) && defined(XF86EXA)
62104007ebaSmrg        if (!xf86NameCmp(s, "XAA"))
62204007ebaSmrg            pGeode->useEXA = FALSE;
62304007ebaSmrg        else if (xf86NameCmp(s, "EXA"))
62404007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
625c744f008Smrg                       "Unknown acceleration method %s.  Defaulting to XAA.\n",
62604007ebaSmrg                       s);
6277f419768Smrg#elif defined(XF86EXA)
6287f419768Smrg        pGeode->useEXA = TRUE;
6297f419768Smrg#else
6307f419768Smrg        pGeode->useEXA = FALSE;
6317f419768Smrg#endif
632f29dbc25Smrg    }
633f29dbc25Smrg
634f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
63504007ebaSmrg               "Using %s acceleration architecture\n",
63604007ebaSmrg               pGeode->useEXA ? "EXA" : "XAA");
637f29dbc25Smrg
638f29dbc25Smrg    /* Set up the panel */
639f29dbc25Smrg
640f29dbc25Smrg    if (pGeode->Panel) {
64104007ebaSmrg        if (panelgeo != NULL) {
64204007ebaSmrg            if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY))
64304007ebaSmrg                pGeode->Panel = FALSE;
64404007ebaSmrg        }
645f29dbc25Smrg#ifdef PNL_SUP
64604007ebaSmrg        else {
64704007ebaSmrg            int b, f;
648f29dbc25Smrg
64904007ebaSmrg            /* The bitdepth and refresh isn't used anywhere else in the driver */
650f29dbc25Smrg
65104007ebaSmrg            if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS()))
65204007ebaSmrg                Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b,
65304007ebaSmrg                                         &f);
65404007ebaSmrg        }
655f29dbc25Smrg#endif
656f29dbc25Smrg    }
657f29dbc25Smrg
658f29dbc25Smrg    /* Set up the VGA */
659f29dbc25Smrg
660f29dbc25Smrg    if (pGeode->useVGA) {
661f29dbc25Smrg#if INT10_SUPPORT
66204007ebaSmrg        VESARec *pVesa;
663f29dbc25Smrg
66404007ebaSmrg        if (!xf86LoadSubModule(pScrni, "int10"))
66504007ebaSmrg            return FALSE;
666f29dbc25Smrg
66704007ebaSmrg        pVesa = pGeode->vesa;
668f29dbc25Smrg
66904007ebaSmrg        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
67004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
67104007ebaSmrg                       "Unable to initialize 1NT10 support\n");
67204007ebaSmrg            pGeode->useVGA = FALSE;
67304007ebaSmrg        }
674f29dbc25Smrg#endif
675f29dbc25Smrg    }
676f29dbc25Smrg
677f29dbc25Smrg    /* First try to get the framebuffer size from the framebuffer,
678f29dbc25Smrg     * and if that fails, revert all  the way back to the legacy
679f29dbc25Smrg     * method
680f29dbc25Smrg     */
681f29dbc25Smrg
682f29dbc25Smrg    if (pGeode->FBAvail == 0) {
68304007ebaSmrg        if (GeodeGetSizeFromFB(&pGeode->FBAvail))
68404007ebaSmrg            pGeode->FBAvail = gfx_get_frame_buffer_size();
685f29dbc25Smrg    }
686f29dbc25Smrg
687f29dbc25Smrg    if (pScrni->memPhysBase == 0)
68804007ebaSmrg        pScrni->memPhysBase = gfx_get_frame_buffer_base();
689f29dbc25Smrg
690f29dbc25Smrg    pScrni->fbOffset = 0;
691f29dbc25Smrg
692f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
69304007ebaSmrg        pScrni->videoRam = pGeode->FBAvail / 1024;
694f29dbc25Smrg    else
69504007ebaSmrg        pScrni->videoRam = pGeode->pEnt->device->videoRam;
696f29dbc25Smrg
69704007ebaSmrg    GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange));
698f29dbc25Smrg    GeodeClockRange->next = NULL;
699f29dbc25Smrg    GeodeClockRange->minClock = 25175;
700f29dbc25Smrg    GeodeClockRange->maxClock = 229500;
701f29dbc25Smrg    GeodeClockRange->clockIndex = -1;
702f29dbc25Smrg    GeodeClockRange->interlaceAllowed = TRUE;
703f29dbc25Smrg    GeodeClockRange->doubleScanAllowed = FALSE;
704f29dbc25Smrg
705f29dbc25Smrg    pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index);
706f29dbc25Smrg
707f29dbc25Smrg    /* I'm still not 100% sure this uses the right values */
708f29dbc25Smrg
709f29dbc25Smrg    modecnt = xf86ValidateModes(pScrni,
71004007ebaSmrg                                pScrni->monitor->Modes,
71104007ebaSmrg                                pScrni->display->modes,
71204007ebaSmrg                                GeodeClockRange,
71304007ebaSmrg                                NULL, GX_MIN_PITCH, GX_MAX_PITCH,
71404007ebaSmrg                                32, GX_MIN_HEIGHT, GX_MAX_HEIGHT,
71504007ebaSmrg                                pScrni->display->virtualX,
71604007ebaSmrg                                pScrni->display->virtualY, pGeode->FBAvail,
71704007ebaSmrg                                LOOKUP_BEST_REFRESH);
718f29dbc25Smrg
719f29dbc25Smrg    if (modecnt <= 0) {
72004007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
72104007ebaSmrg        return FALSE;
722f29dbc25Smrg    }
723f29dbc25Smrg
724f29dbc25Smrg    xf86PruneDriverModes(pScrni);
725f29dbc25Smrg
726f29dbc25Smrg    if (pScrni->modes == NULL) {
72704007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
72804007ebaSmrg        return FALSE;
729f29dbc25Smrg    }
730f29dbc25Smrg
731f29dbc25Smrg    xf86SetCrtcForModes(pScrni, 0);
732f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
733f29dbc25Smrg
734f29dbc25Smrg    xf86PrintModes(pScrni);
735f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
736f29dbc25Smrg
737f29dbc25Smrg    /* Load the modules we'll need */
738f29dbc25Smrg
739f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
74004007ebaSmrg        return FALSE;
741f29dbc25Smrg    }
742f29dbc25Smrg
743f29dbc25Smrg    if (pGeode->NoAccel == FALSE) {
74404007ebaSmrg        const char *module = (pGeode->useEXA) ? "exa" : "xaa";
745f29dbc25Smrg
74604007ebaSmrg        if (!xf86LoadSubModule(pScrni, module)) {
74704007ebaSmrg            return FALSE;
74804007ebaSmrg        }
749f29dbc25Smrg    }
750f29dbc25Smrg
751f29dbc25Smrg    if (pGeode->tryHWCursor == TRUE) {
75204007ebaSmrg        if (!xf86LoadSubModule(pScrni, "ramdac")) {
75304007ebaSmrg            return FALSE;
75404007ebaSmrg        }
755f29dbc25Smrg    }
756f29dbc25Smrg
757f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
758f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
75904007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
76004007ebaSmrg                   "Couldn't register the resources.\n");
76104007ebaSmrg        return FALSE;
762f29dbc25Smrg    }
763f29dbc25Smrg#endif
764f29dbc25Smrg    return TRUE;
765f29dbc25Smrg}
766f29dbc25Smrg
767f29dbc25Smrgstatic void
768f29dbc25SmrgGXRestore(ScrnInfoPtr pScrni)
769f29dbc25Smrg{
770f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
771f29dbc25Smrg
772f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
77304007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
774f29dbc25Smrg
77504007ebaSmrg        vgaHWProtect(pScrni, TRUE);
77604007ebaSmrg        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
77704007ebaSmrg        vgaHWProtect(pScrni, FALSE);
778f29dbc25Smrg    }
779f29dbc25Smrg}
780f29dbc25Smrg
781f29dbc25Smrgstatic Bool
782f29dbc25SmrgGXUnmapMem(ScrnInfoPtr pScrni)
783f29dbc25Smrg{
784f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
785f29dbc25Smrg
786f29dbc25Smrg    /* unmap all the memory map's */
7877f419768Smrg#ifndef XSERVER_LIBPCIACCESS
788f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE);
789f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE);
790f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE);
791f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail);
7927f419768Smrg#else
7937f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
7947f419768Smrg
7957f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_regptr, GX_CPU_REG_SIZE);
7967f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_gpptr, GX_GP_REG_SIZE);
7977f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_vidptr, GX_VID_REG_SIZE);
7987f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_fbptr, pGeode->FBAvail);
7997f419768Smrg
8007f419768Smrg    munmap(XpressROMPtr, 0x10000);
8017f419768Smrg#endif
802f29dbc25Smrg    return TRUE;
803f29dbc25Smrg}
804f29dbc25Smrg
805f29dbc25Smrgstatic void
806f29dbc25SmrgGXSetDvLineSize(unsigned int pitch)
807f29dbc25Smrg{
808f29dbc25Smrg    unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024;
809f29dbc25Smrg
810f29dbc25Smrg    if (pitch > 1024) {
81104007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_2048;
812f29dbc25Smrg    }
813f29dbc25Smrg    if (pitch > 2048) {
81404007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_4096;
815f29dbc25Smrg    }
816f29dbc25Smrg    if (pitch > 4096) {
81704007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_8192;
818f29dbc25Smrg    }
819f29dbc25Smrg
820f29dbc25Smrg    /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
821f29dbc25Smrg
822f29dbc25Smrg    temp = READ_REG32(MDC_DV_CTL);
823f29dbc25Smrg    WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size);
824f29dbc25Smrg}
825f29dbc25Smrg
826f29dbc25Smrg/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */
827f29dbc25Smrg
828f29dbc25Smrgstatic void
82904007ebaSmrgGXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
830f29dbc25Smrg{
83104007ebaSmrg    SCRN_INFO_PTR(arg);
832f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
833f29dbc25Smrg    unsigned long offset;
834f29dbc25Smrg
835f29dbc25Smrg    offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3);
836f29dbc25Smrg
837f29dbc25Smrg    gfx_set_display_offset(offset);
838f29dbc25Smrg}
839f29dbc25Smrg
840f29dbc25Smrgstatic Bool
841f29dbc25SmrgGXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode)
842f29dbc25Smrg{
843f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
844f29dbc25Smrg    int flags = 0;
845f29dbc25Smrg    int custom = 0;
846f29dbc25Smrg
847f29dbc25Smrg    pScrni->vtSema = TRUE;
848f29dbc25Smrg
849f29dbc25Smrg    gx_disable_dac_power();
850f29dbc25Smrg
851f29dbc25Smrg    if (pMode->Flags & V_NHSYNC)
85204007ebaSmrg        flags |= 1;
853f29dbc25Smrg    if (pMode->Flags & V_NVSYNC)
85404007ebaSmrg        flags |= 2;
855f29dbc25Smrg
856f29dbc25Smrg    /* Check to see if we should use custom or built-in timings */
857f29dbc25Smrg
858f29dbc25Smrg    if (pGeode->Panel)
85904007ebaSmrg        custom = (pMode->type & M_T_USERDEF);
860f29dbc25Smrg    else
86104007ebaSmrg        custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
862f29dbc25Smrg
863f29dbc25Smrg    /* If we're not doing a custom mode, then just set the fixed timings,
864f29dbc25Smrg     * otherwise, do the whole shooting match */
865f29dbc25Smrg
866f29dbc25Smrg    if (!custom) {
86704007ebaSmrg        GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY,
86804007ebaSmrg                              pMode->CrtcHDisplay, pMode->CrtcVDisplay,
86904007ebaSmrg                              pScrni->bitsPerPixel));
87004007ebaSmrg    }
87104007ebaSmrg    else {
87204007ebaSmrg        if (pGeode->Panel)
87304007ebaSmrg            GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY,
87404007ebaSmrg                                  pMode->CrtcHDisplay, pMode->CrtcVDisplay,
87504007ebaSmrg                                  pScrni->bitsPerPixel));
87604007ebaSmrg
87704007ebaSmrg        GFX(set_display_timings(pScrni->bitsPerPixel, flags,
87804007ebaSmrg                                pMode->CrtcHDisplay, pMode->CrtcHBlankStart,
87904007ebaSmrg                                pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd,
88004007ebaSmrg                                pMode->CrtcHBlankEnd, pMode->CrtcHTotal,
88104007ebaSmrg                                pMode->CrtcVDisplay, pMode->CrtcVBlankStart,
88204007ebaSmrg                                pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd,
88304007ebaSmrg                                pMode->CrtcVBlankEnd, pMode->CrtcVTotal,
88404007ebaSmrg                                (int) ((pMode->SynthClock / 1000.0) *
88504007ebaSmrg                                       0x10000)));
886f29dbc25Smrg    }
887f29dbc25Smrg
888f29dbc25Smrg    GFX(set_crt_enable(CRT_ENABLE));
889f29dbc25Smrg    GFX(set_display_pitch(pGeode->displayPitch));
890f29dbc25Smrg    GFX(set_display_offset(0L));
891f29dbc25Smrg    GFX(wait_vertical_blank());
892f29dbc25Smrg
893f29dbc25Smrg    if (pGeode->Compression) {
89404007ebaSmrg        GXSetDvLineSize(pGeode->Pitch);
895f29dbc25Smrg
89604007ebaSmrg        gfx_set_compression_offset(pGeode->CBData.compression_offset);
89704007ebaSmrg        gfx_set_compression_pitch(GX_CB_PITCH);
89804007ebaSmrg        gfx_set_compression_size(GX_CB_SIZE);
899f29dbc25Smrg
90004007ebaSmrg        gfx_set_compression_enable(1);
901f29dbc25Smrg    }
902f29dbc25Smrg
903f29dbc25Smrg    if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) {
90404007ebaSmrg        GXLoadCursorImage(pScrni, NULL);
90504007ebaSmrg        GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0));
90604007ebaSmrg        GXShowCursor(pScrni);
90704007ebaSmrg    }
90804007ebaSmrg    else {
90904007ebaSmrg        GFX(set_cursor_enable(0));
91004007ebaSmrg        pGeode->HWCursor = FALSE;
911f29dbc25Smrg    }
912f29dbc25Smrg
91304007ebaSmrg    GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0));
914f29dbc25Smrg    gx_enable_dac_power();
915f29dbc25Smrg
916f29dbc25Smrg    return TRUE;
917f29dbc25Smrg}
918f29dbc25Smrg
919f29dbc25Smrgstatic Bool
92004007ebaSmrgGXSwitchMode(SWITCH_MODE_ARGS_DECL)
921f29dbc25Smrg{
92204007ebaSmrg    SCRN_INFO_PTR(arg);
923f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
924f29dbc25Smrg    int ret = TRUE;
925f29dbc25Smrg    int rotate;
926f29dbc25Smrg
927f29dbc25Smrg    /* Syn the engine and shutdown the DAC momentarily */
928f29dbc25Smrg
929f29dbc25Smrg    gfx_wait_until_idle();
930f29dbc25Smrg
931f29dbc25Smrg    /* Set up the memory for the new mode */
932f29dbc25Smrg    rotate = GXGetRotation(pScrni->pScreen);
933f29dbc25Smrg    ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate);
934f29dbc25Smrg
935f29dbc25Smrg    if (ret) {
93604007ebaSmrg        if (pGeode->curMode != pMode)
93704007ebaSmrg            ret = GXSetVideoMode(pScrni, pMode);
938f29dbc25Smrg    }
939f29dbc25Smrg
940f29dbc25Smrg    if (ret)
94104007ebaSmrg        ret = GXRotate(pScrni, pMode);
942f29dbc25Smrg
943f29dbc25Smrg    /* Go back the way it was */
944f29dbc25Smrg
945f29dbc25Smrg    if (ret == FALSE) {
94604007ebaSmrg        if (!GXSetVideoMode(pScrni, pGeode->curMode))
94704007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
94804007ebaSmrg                       "Could not restore the previous mode\n");
94904007ebaSmrg    }
95004007ebaSmrg    else
95104007ebaSmrg        pGeode->curMode = pMode;
952f29dbc25Smrg
953f29dbc25Smrg    return ret;
954f29dbc25Smrg}
955f29dbc25Smrg
956f29dbc25Smrgstatic void
957f29dbc25SmrgGXLeaveGraphics(ScrnInfoPtr pScrni)
958f29dbc25Smrg{
959f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
960f29dbc25Smrg
961f29dbc25Smrg    gfx_wait_until_idle();
962f29dbc25Smrg
963f29dbc25Smrg    /* Restore VG registers */
964f29dbc25Smrg    gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp,
96504007ebaSmrg                            pGeode->FBgfxdisplaytiming.wPolarity,
96604007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHActive,
96704007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHBlankStart,
96804007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHSyncStart,
96904007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHSyncEnd,
97004007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHBlankEnd,
97104007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHTotal,
97204007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVActive,
97304007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVBlankStart,
97404007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVSyncStart,
97504007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVSyncEnd,
97604007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVBlankEnd,
97704007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVTotal,
97804007ebaSmrg                            pGeode->FBgfxdisplaytiming.dwDotClock);
979f29dbc25Smrg
980f29dbc25Smrg    gfx_set_compression_enable(0);
981f29dbc25Smrg
982f29dbc25Smrg    /* Restore the previous Compression state */
983f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
98404007ebaSmrg        gfx_set_compression_offset(pGeode->FBCompressionOffset);
98504007ebaSmrg        gfx_set_compression_pitch(pGeode->FBCompressionPitch);
98604007ebaSmrg        gfx_set_compression_size(pGeode->FBCompressionSize);
98704007ebaSmrg        gfx_set_compression_enable(1);
988f29dbc25Smrg    }
989f29dbc25Smrg
990f29dbc25Smrg    gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch);
991f29dbc25Smrg
992f29dbc25Smrg    gfx_set_display_offset(pGeode->FBDisplayOffset);
993f29dbc25Smrg
994f29dbc25Smrg    /* Restore Cursor */
995f29dbc25Smrg    gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0);
996f29dbc25Smrg
997f29dbc25Smrg    if (pGeode->useVGA) {
99804007ebaSmrg        pGeode->vesa->pInt->num = 0x10;
99904007ebaSmrg        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
100004007ebaSmrg        pGeode->vesa->pInt->bx = 0;
100104007ebaSmrg        xf86ExecX86int10(pGeode->vesa->pInt);
100204007ebaSmrg        gfx_delay_milliseconds(3);
1003f29dbc25Smrg    }
1004f29dbc25Smrg
1005f29dbc25Smrg    GXRestore(pScrni);
1006f29dbc25Smrg
1007f29dbc25Smrg    gx_enable_dac_power();
1008f29dbc25Smrg}
1009f29dbc25Smrg
1010f29dbc25Smrgstatic Bool
101104007ebaSmrgGXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
1012f29dbc25Smrg{
101304007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1014f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1015f29dbc25Smrg
1016f29dbc25Smrg    if (pScrni->vtSema)
101704007ebaSmrg        GXLeaveGraphics(pScrni);
1018f29dbc25Smrg
101904007ebaSmrg#ifdef XF86XAA
1020f29dbc25Smrg    if (pGeode->AccelInfoRec)
102104007ebaSmrg        XAADestroyInfoRec(pGeode->AccelInfoRec);
102204007ebaSmrg#endif
1023f29dbc25Smrg
1024f29dbc25Smrg    if (pGeode->AccelImageWriteBuffers) {
102504007ebaSmrg        free(pGeode->AccelImageWriteBuffers[0]);
102604007ebaSmrg        free(pGeode->AccelImageWriteBuffers);
102704007ebaSmrg        pGeode->AccelImageWriteBuffers = NULL;
1028f29dbc25Smrg    }
1029f29dbc25Smrg
1030f29dbc25Smrg    if (pGeode->AccelColorExpandBuffers) {
103104007ebaSmrg        free(pGeode->AccelColorExpandBuffers);
103204007ebaSmrg        pGeode->AccelColorExpandBuffers = NULL;
1033f29dbc25Smrg    }
1034f29dbc25Smrg
1035f29dbc25Smrg    if (pGeode->pExa) {
103604007ebaSmrg        exaDriverFini(pScrn);
103704007ebaSmrg        free(pGeode->pExa);
103804007ebaSmrg        pGeode->pExa = NULL;
1039f29dbc25Smrg    }
1040f29dbc25Smrg
1041f29dbc25Smrg    pScrni->vtSema = FALSE;
1042f29dbc25Smrg
1043f29dbc25Smrg    GXUnmapMem(pScrni);
1044f29dbc25Smrg
1045f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
1046f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
1047f29dbc25Smrg
1048f29dbc25Smrg    if (pScrn->CloseScreen)
104904007ebaSmrg        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
1050f29dbc25Smrg
1051f29dbc25Smrg    return TRUE;
1052f29dbc25Smrg}
1053f29dbc25Smrg
1054f29dbc25Smrgstatic Bool
1055f29dbc25SmrgGXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
1056f29dbc25Smrg{
1057f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1058f29dbc25Smrg
1059f29dbc25Smrg    if (!GXMapMem(pScrni))
106004007ebaSmrg        return FALSE;
1061f29dbc25Smrg
1062f29dbc25Smrg    if (pGeode->useVGA)
106304007ebaSmrg        pGeode->FBVGAActive = gu2_get_vga_active();
1064f29dbc25Smrg
1065f29dbc25Smrg    gfx_wait_until_idle();
1066f29dbc25Smrg
1067f29dbc25Smrg    /* Save off the current state (should this be somewhere else)? */
1068f29dbc25Smrg
1069f29dbc25Smrg    pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency();
1070f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch();
1071f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp();
1072f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal();
1073f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive();
1074f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start();
1075f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end();
1076f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start();
1077f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end();
1078f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal();
1079f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive();
1080f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start();
1081f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end();
1082f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start();
1083f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end();
1084f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities();
1085f29dbc25Smrg
1086f29dbc25Smrg    pGeode->FBDisplayOffset = gfx_get_display_offset();
1087f29dbc25Smrg
1088f29dbc25Smrg    if (pGeode->useVGA) {
108904007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1090f29dbc25Smrg
109104007ebaSmrg        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
1092f29dbc25Smrg    }
1093f29dbc25Smrg
1094f29dbc25Smrg    pGeode->FBCompressionEnable = gfx_get_compression_enable();
1095f29dbc25Smrg    pGeode->FBCompressionOffset = gfx_get_compression_offset();
1096f29dbc25Smrg    pGeode->FBCompressionPitch = gfx_get_compression_pitch();
1097f29dbc25Smrg    pGeode->FBCompressionSize = gfx_get_compression_size();
1098f29dbc25Smrg
1099f29dbc25Smrg#ifdef PNL_SUP
1100f29dbc25Smrg    Pnl_SavePanelState();
1101f29dbc25Smrg#endif
1102f29dbc25Smrg
1103f29dbc25Smrg    /* Turn off the VGA */
1104f29dbc25Smrg
1105f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
110604007ebaSmrg        unsigned short sequencer;
110704007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1108f29dbc25Smrg
110904007ebaSmrg        /* Map VGA aperture */
111004007ebaSmrg        if (!vgaHWMapMem(pScrni))
111104007ebaSmrg            return FALSE;
1112f29dbc25Smrg
111304007ebaSmrg        /* Unlock VGA registers */
111404007ebaSmrg        vgaHWUnlock(pvgaHW);
1115f29dbc25Smrg
111604007ebaSmrg        /* Save the current state and setup the current mode */
111704007ebaSmrg        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
1118f29dbc25Smrg
111904007ebaSmrg        /* DISABLE VGA SEQUENCER */
112004007ebaSmrg        /* This allows the VGA state machine to terminate. We must delay */
112104007ebaSmrg        /* such that there are no pending MBUS requests.  */
1122f29dbc25Smrg
112304007ebaSmrg        gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
112404007ebaSmrg        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
112504007ebaSmrg        sequencer |= MDC_CLK_MODE_SCREEN_OFF;
112604007ebaSmrg        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1127f29dbc25Smrg
112804007ebaSmrg        gfx_delay_milliseconds(1);
1129f29dbc25Smrg
113004007ebaSmrg        /* BLANK THE VGA DISPLAY */
113104007ebaSmrg        gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET);
113204007ebaSmrg        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
113304007ebaSmrg        sequencer &= ~MDC_RESET_VGA_DISP_ENABLE;
113404007ebaSmrg        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1135f29dbc25Smrg
113604007ebaSmrg        gfx_delay_milliseconds(1);
1137f29dbc25Smrg    }
1138f29dbc25Smrg
1139f29dbc25Smrg    /* Set up the memory */
1140c744f008Smrg    /* XXX - FIXME - when we allow initial rotation, it should be here */
1141f29dbc25Smrg    GXAllocateMemory(pScrn, pScrni, pGeode->rotation);
1142f29dbc25Smrg
1143f29dbc25Smrg    /* Clear the framebuffer */
1144f29dbc25Smrg    memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize);
1145f29dbc25Smrg
1146f29dbc25Smrg    /* Set up the video mode */
1147f29dbc25Smrg    GXSetVideoMode(pScrni, pScrni->currentMode);
1148f29dbc25Smrg    pGeode->curMode = pScrni->currentMode;
1149f29dbc25Smrg
1150f29dbc25Smrg    return TRUE;
1151f29dbc25Smrg}
1152f29dbc25Smrg
1153f29dbc25Smrgstatic void
1154f29dbc25SmrgGXLoadPalette(ScrnInfoPtr pScrni,
115504007ebaSmrg              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
1156f29dbc25Smrg{
1157f29dbc25Smrg    int i, index, color;
1158f29dbc25Smrg
1159f29dbc25Smrg    for (i = 0; i < numColors; i++) {
116004007ebaSmrg        index = indizes[i] & 0xFF;
116104007ebaSmrg        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
116204007ebaSmrg            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
116304007ebaSmrg            ((unsigned long) (colors[index].blue & 0xFF));
1164f29dbc25Smrg
116504007ebaSmrg        GFX(set_display_palette_entry(index, color));
1166f29dbc25Smrg    }
1167f29dbc25Smrg}
1168f29dbc25Smrg
1169f29dbc25Smrg#ifdef DPMSExtension
1170f29dbc25Smrgstatic void
1171f29dbc25SmrgGXPanelPower(int enable)
1172f29dbc25Smrg{
1173f29dbc25Smrg    unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT);
1174f29dbc25Smrg
1175f29dbc25Smrg    if (enable != 0)
117604007ebaSmrg        power |= RCDF_PM_PANEL_POWER_ON;
1177f29dbc25Smrg    else
117804007ebaSmrg        power &= ~RCDF_PM_PANEL_POWER_ON;
1179f29dbc25Smrg
1180f29dbc25Smrg    WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
1181f29dbc25Smrg}
1182f29dbc25Smrg
1183f29dbc25Smrgstatic void
1184f29dbc25SmrgGXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags)
1185f29dbc25Smrg{
1186f29dbc25Smrg    GeodeRec *pGeode;
1187f29dbc25Smrg
1188f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
1189f29dbc25Smrg
1190f29dbc25Smrg    if (!pScrni->vtSema)
119104007ebaSmrg        return;
1192f29dbc25Smrg
1193f29dbc25Smrg    switch (mode) {
1194f29dbc25Smrg    case DPMSModeOn:
119504007ebaSmrg        /* Screen: On; HSync: On; VSync: On */
119604007ebaSmrg        GFX(set_crt_enable(CRT_ENABLE));
1197f29dbc25Smrg#if defined(PNL_SUP)
119804007ebaSmrg        if (pGeode->Panel) {
119904007ebaSmrg            Pnl_PowerUp();
120004007ebaSmrg            GXPanelPower(1);
120104007ebaSmrg        }
1202f29dbc25Smrg#endif
120304007ebaSmrg        break;
1204f29dbc25Smrg
1205f29dbc25Smrg    case DPMSModeStandby:
120604007ebaSmrg        /* Screen: Off; HSync: Off; VSync: On */
120704007ebaSmrg        GFX(set_crt_enable(CRT_STANDBY));
1208f29dbc25Smrg#if defined(PNL_SUP)
120904007ebaSmrg        if (pGeode->Panel) {
121004007ebaSmrg            Pnl_PowerDown();
121104007ebaSmrg            GXPanelPower(0);
121204007ebaSmrg        }
1213f29dbc25Smrg#endif
121404007ebaSmrg        break;
1215f29dbc25Smrg
1216f29dbc25Smrg    case DPMSModeSuspend:
121704007ebaSmrg        /* Screen: Off; HSync: On; VSync: Off */
121804007ebaSmrg        GFX(set_crt_enable(CRT_SUSPEND));
1219f29dbc25Smrg#if defined(PNL_SUP)
122004007ebaSmrg        if (pGeode->Panel) {
122104007ebaSmrg            Pnl_PowerDown();
122204007ebaSmrg            GXPanelPower(0);
122304007ebaSmrg        }
1224f29dbc25Smrg#endif
122504007ebaSmrg        break;
1226f29dbc25Smrg
1227f29dbc25Smrg    case DPMSModeOff:
122804007ebaSmrg        /* Screen: Off; HSync: Off; VSync: Off */
122904007ebaSmrg        GFX(set_crt_enable(CRT_DISABLE));
1230f29dbc25Smrg#if defined(PNL_SUP)
123104007ebaSmrg        if (pGeode->Panel) {
123204007ebaSmrg            Pnl_PowerDown();
123304007ebaSmrg            GXPanelPower(0);
123404007ebaSmrg        }
1235f29dbc25Smrg#endif
123604007ebaSmrg        break;
1237f29dbc25Smrg    }
1238f29dbc25Smrg}
1239f29dbc25Smrg#endif
1240f29dbc25Smrg
1241f29dbc25Smrgstatic Bool
1242f29dbc25SmrgGXCreateScreenResources(ScreenPtr pScreen)
1243f29dbc25Smrg{
124404007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
1245f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1246f29dbc25Smrg
1247f29dbc25Smrg    pScreen->CreateScreenResources = pGeode->CreateScreenResources;
1248f29dbc25Smrg    if (!(*pScreen->CreateScreenResources) (pScreen))
124904007ebaSmrg        return FALSE;
1250f29dbc25Smrg
1251f29dbc25Smrg    if (xf86LoaderCheckSymbol("GXRandRSetConfig")
125204007ebaSmrg        && pGeode->rotation != RR_Rotate_0) {
125304007ebaSmrg        Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate,
125404007ebaSmrg                                     RRScreenSizePtr pSize) = NULL;
1255f29dbc25Smrg
125604007ebaSmrg        RRScreenSize p;
125704007ebaSmrg        Rotation requestedRotation = pGeode->rotation;
1258f29dbc25Smrg
125904007ebaSmrg        pGeode->rotation = RR_Rotate_0;
1260f29dbc25Smrg
126104007ebaSmrg        /* Just setup enough for an initial rotate */
1262f29dbc25Smrg
126304007ebaSmrg        p.width = pScreen->width;
126404007ebaSmrg        p.height = pScreen->height;
126504007ebaSmrg        p.mmWidth = pScreen->mmWidth;
126604007ebaSmrg        p.mmHeight = pScreen->mmHeight;
1267f29dbc25Smrg
126804007ebaSmrg        GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig");
126904007ebaSmrg        if (GXRandRSetConfig) {
127004007ebaSmrg            pGeode->starting = TRUE;
127104007ebaSmrg            (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p);
127204007ebaSmrg            pGeode->starting = FALSE;
127304007ebaSmrg        }
1274f29dbc25Smrg    }
1275f29dbc25Smrg
1276f29dbc25Smrg    return TRUE;
1277f29dbc25Smrg}
1278f29dbc25Smrg
1279f29dbc25Smrgstatic Bool
128004007ebaSmrgGXScreenInit(SCREEN_INIT_ARGS_DECL)
1281f29dbc25Smrg{
128204007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1283f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1284f29dbc25Smrg    XF86ModReqInfo shadowReq;
1285f29dbc25Smrg    int maj, min, ret, rotate;
1286f29dbc25Smrg
1287f29dbc25Smrg    pGeode->starting = TRUE;
1288f29dbc25Smrg
1289f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
1290f29dbc25Smrg
1291f29dbc25Smrg    if (pGeode->useVGA) {
1292f29dbc25Smrg
129304007ebaSmrg        if (!vgaHWMapMem(pScrni))
129404007ebaSmrg            return FALSE;
1295f29dbc25Smrg
129604007ebaSmrg        vgaHWGetIOBase(VGAHWPTR(pScrni));
1297f29dbc25Smrg    }
1298f29dbc25Smrg
1299f29dbc25Smrg    if (!pGeode->NoAccel) {
1300f29dbc25Smrg
130104007ebaSmrg        if (pGeode->useEXA) {
130204007ebaSmrg
130304007ebaSmrg            if (!(pGeode->pExa = exaDriverAlloc())) {
130404007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
130504007ebaSmrg                           "Couldn't allocate the EXA structure.\n");
130604007ebaSmrg                pGeode->NoAccel = TRUE;
130704007ebaSmrg            }
130804007ebaSmrg            else {
130904007ebaSmrg                ExaDriverPtr pExa = pGeode->pExa;
131004007ebaSmrg
131104007ebaSmrg                /* THis is set in GXAllocMem */
131204007ebaSmrg                pExa->memoryBase = 0;
131304007ebaSmrg
131404007ebaSmrg                /* This is set in GXAllocateMemory */
131504007ebaSmrg                pExa->memorySize = 0;
131604007ebaSmrg
131704007ebaSmrg                pExa->pixmapOffsetAlign = 32;
131804007ebaSmrg                pExa->pixmapPitchAlign = 32;
131904007ebaSmrg                pExa->flags = EXA_OFFSCREEN_PIXMAPS;
132004007ebaSmrg                pExa->maxX = GX_MAX_WIDTH - 1;
132104007ebaSmrg                pExa->maxY = GX_MAX_HEIGHT - 1;
132204007ebaSmrg            }
132304007ebaSmrg        }
132404007ebaSmrg        else {
132504007ebaSmrg            pGeode->AccelImageWriteBuffers =
132604007ebaSmrg                calloc(pGeode->NoOfImgBuffers,
132704007ebaSmrg                       sizeof(pGeode->AccelImageWriteBuffers[0]));
132804007ebaSmrg            pGeode->AccelColorExpandBuffers =
132904007ebaSmrg                calloc(pGeode->NoOfColorExpandLines,
133004007ebaSmrg                       sizeof(pGeode->AccelColorExpandBuffers[0]));
133104007ebaSmrg        }
1332f29dbc25Smrg    }
1333f29dbc25Smrg
1334f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
1335f29dbc25Smrg
1336f29dbc25Smrg    if (!GXEnterGraphics(pScrn, pScrni))
133704007ebaSmrg        return FALSE;
1338f29dbc25Smrg
1339f29dbc25Smrg    miClearVisualTypes();
1340f29dbc25Smrg
1341f29dbc25Smrg    /* XXX Again - take down anything? */
1342f29dbc25Smrg
1343f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
134404007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
134504007ebaSmrg                              TrueColorMask, pScrni->rgbBits,
134604007ebaSmrg                              pScrni->defaultVisual)) {
134704007ebaSmrg            return FALSE;
134804007ebaSmrg        }
134904007ebaSmrg    }
135004007ebaSmrg    else {
135104007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
135204007ebaSmrg                              miGetDefaultVisualMask(pScrni->depth),
135304007ebaSmrg                              pScrni->rgbBits, pScrni->defaultVisual)) {
135404007ebaSmrg            return FALSE;
135504007ebaSmrg        }
1356f29dbc25Smrg    }
1357f29dbc25Smrg
1358f29dbc25Smrg    miSetPixmapDepths();
1359f29dbc25Smrg
1360f29dbc25Smrg    /* Point at the visible area to start */
1361f29dbc25Smrg
1362f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset,
136304007ebaSmrg                       pScrni->virtualX, pScrni->virtualY,
136404007ebaSmrg                       pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth,
136504007ebaSmrg                       pScrni->bitsPerPixel);
1366f29dbc25Smrg
1367f29dbc25Smrg    if (!ret)
136804007ebaSmrg        return FALSE;
1369f29dbc25Smrg
1370f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
1371f29dbc25Smrg
1372f29dbc25Smrg    /* Set up the color ordering */
1373f29dbc25Smrg
1374f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
137504007ebaSmrg        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
137604007ebaSmrg
137704007ebaSmrg        while (--visual >= pScrn->visuals) {
137804007ebaSmrg            if ((visual->class | DynamicClass) == DirectColor) {
137904007ebaSmrg                visual->offsetRed = pScrni->offset.red;
138004007ebaSmrg                visual->offsetGreen = pScrni->offset.green;
138104007ebaSmrg                visual->offsetBlue = pScrni->offset.blue;
138204007ebaSmrg                visual->redMask = pScrni->mask.red;
138304007ebaSmrg                visual->greenMask = pScrni->mask.green;
138404007ebaSmrg                visual->blueMask = pScrni->mask.blue;
138504007ebaSmrg            }
138604007ebaSmrg        }
1387f29dbc25Smrg    }
1388f29dbc25Smrg
1389f29dbc25Smrg    /* Must follow the color ordering */
1390f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
1391f29dbc25Smrg
1392f29dbc25Smrg    if (!pGeode->NoAccel)
139304007ebaSmrg        GXAccelInit(pScrn);
1394f29dbc25Smrg
1395f29dbc25Smrg    xf86SetBackingStore(pScrn);
1396f29dbc25Smrg
1397f29dbc25Smrg    /* Set up the soft cursor */
1398f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
1399f29dbc25Smrg
1400f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
1401f29dbc25Smrg
1402f29dbc25Smrg    if (pGeode->tryHWCursor) {
140304007ebaSmrg        if (!GXHWCursorInit(pScrn))
140404007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
140504007ebaSmrg                       "Hardware cursor initialization failed.\n");
1406f29dbc25Smrg    }
1407f29dbc25Smrg
1408f29dbc25Smrg    /* Set up the color map */
1409f29dbc25Smrg
1410f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
141104007ebaSmrg        return FALSE;
1412f29dbc25Smrg
1413f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
141404007ebaSmrg        /* Must follow initialization of the default colormap */
1415f29dbc25Smrg
141604007ebaSmrg        if (!xf86HandleColormaps(pScrn, 256, 8,
141704007ebaSmrg                                 GXLoadPalette, NULL,
141804007ebaSmrg                                 CMAP_PALETTED_TRUECOLOR |
141904007ebaSmrg                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
142004007ebaSmrg            return FALSE;
142104007ebaSmrg        }
1422f29dbc25Smrg    }
1423f29dbc25Smrg#ifdef DPMSExtension
1424f29dbc25Smrg    xf86DPMSInit(pScrn, GXDPMSSet, 0);
1425f29dbc25Smrg#endif
1426f29dbc25Smrg
1427f29dbc25Smrg    GXInitVideo(pScrn);
1428f29dbc25Smrg
1429f29dbc25Smrg    /* Set up RandR */
1430f29dbc25Smrg
14315748e6ecSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24
143204007ebaSmrg    xf86DisableRandR();         /* We provide our own RandR goodness */
143346edf8f1Smrg#endif
1434f29dbc25Smrg
1435f29dbc25Smrg    /* Try to set up the shadow FB for rotation */
1436f29dbc25Smrg
1437f29dbc25Smrg    memset(&shadowReq, 0, sizeof(shadowReq));
1438f29dbc25Smrg    shadowReq.majorversion = 1;
1439f29dbc25Smrg    shadowReq.minorversion = 1;
1440f29dbc25Smrg
1441f29dbc25Smrg    if (LoadSubModule(pScrni->module, "shadow",
144204007ebaSmrg                      NULL, NULL, NULL, &shadowReq, &maj, &min)) {
1443f29dbc25Smrg
144404007ebaSmrg        rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
144504007ebaSmrg        shadowSetup(pScrn);
144604007ebaSmrg    }
144704007ebaSmrg    else {
144804007ebaSmrg        LoaderErrorMsg(NULL, "shadow", maj, min);
144904007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
145004007ebaSmrg                   "Error loading shadow - rotation not available.\n");
1451f29dbc25Smrg
145204007ebaSmrg        if (pGeode->rotation != RR_Rotate_0)
145304007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
145404007ebaSmrg                       "Reverting back to normal rotation.\n");
1455f29dbc25Smrg
145604007ebaSmrg        rotate = pGeode->rotation = RR_Rotate_0;
1457f29dbc25Smrg    }
1458f29dbc25Smrg
1459f29dbc25Smrg    GXRandRInit(pScrn, rotate);
1460f29dbc25Smrg
1461f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
1462f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
1463f29dbc25Smrg
1464f29dbc25Smrg    pGeode->CreateScreenResources = pScrn->CreateScreenResources;
1465f29dbc25Smrg    pScrn->CreateScreenResources = GXCreateScreenResources;
1466f29dbc25Smrg
1467f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
1468f29dbc25Smrg    pScrn->CloseScreen = GXCloseScreen;
1469f29dbc25Smrg    pScrn->SaveScreen = GXSaveScreen;
1470f29dbc25Smrg
1471f29dbc25Smrg    if (serverGeneration == 1)
147204007ebaSmrg        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1473f29dbc25Smrg
1474f29dbc25Smrg    pGeode->starting = FALSE;
1475f29dbc25Smrg
1476f29dbc25Smrg    return TRUE;
1477f29dbc25Smrg}
1478f29dbc25Smrg
1479f29dbc25Smrgstatic int
148004007ebaSmrgGXValidMode(VALID_MODE_ARGS_DECL)
1481f29dbc25Smrg{
148204007ebaSmrg    SCRN_INFO_PTR(arg);
1483f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1484f29dbc25Smrg    int p;
1485f29dbc25Smrg    int custom = 0;
1486f29dbc25Smrg
1487f29dbc25Smrg    if (pGeode->Panel)
148804007ebaSmrg        custom = (pMode->type & M_T_USERDEF);
1489f29dbc25Smrg    else
149004007ebaSmrg        custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
1491f29dbc25Smrg
1492f29dbc25Smrg    /* Use the durango lookup for !custom modes */
1493f29dbc25Smrg
1494f29dbc25Smrg    if (!custom && pGeode->Panel) {
1495f29dbc25Smrg        if (pMode->CrtcHDisplay > pGeode->PanelX ||
1496f29dbc25Smrg            pMode->CrtcVDisplay > pGeode->PanelY ||
1497f29dbc25Smrg            gfx_is_panel_mode_supported(pGeode->PanelX,
1498f29dbc25Smrg                                        pGeode->PanelY,
1499f29dbc25Smrg                                        pMode->CrtcHDisplay,
1500f29dbc25Smrg                                        pMode->CrtcVDisplay,
1501f29dbc25Smrg                                        pScrni->bitsPerPixel) < 0) {
1502f29dbc25Smrg
1503f29dbc25Smrg            return MODE_BAD;
1504f29dbc25Smrg        }
1505f29dbc25Smrg    }
1506f29dbc25Smrg
1507f29dbc25Smrg    if (gfx_is_display_mode_supported(pMode->CrtcHDisplay,
1508f29dbc25Smrg                                      pMode->CrtcVDisplay,
1509f29dbc25Smrg                                      pScrni->bitsPerPixel,
1510f29dbc25Smrg                                      GeodeGetRefreshRate(pMode)) < 0) {
1511f29dbc25Smrg        return MODE_BAD;
1512f29dbc25Smrg    }
1513f29dbc25Smrg
1514f29dbc25Smrg    if (pMode->Flags & V_INTERLACE)
151504007ebaSmrg        return MODE_NO_INTERLACE;
1516f29dbc25Smrg
1517f29dbc25Smrg    if (pGeode->tryCompression)
151804007ebaSmrg        p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel);
1519f29dbc25Smrg    else
152004007ebaSmrg        p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
1521f29dbc25Smrg
1522f29dbc25Smrg    if (p * pMode->CrtcVDisplay > pGeode->FBAvail)
152304007ebaSmrg        return MODE_MEM;
1524f29dbc25Smrg
1525f29dbc25Smrg    return MODE_OK;
1526f29dbc25Smrg}
1527f29dbc25Smrg
1528f29dbc25Smrg/* XXX - Way more to do here */
1529f29dbc25Smrg
1530f29dbc25Smrgstatic Bool
153104007ebaSmrgGXEnterVT(VT_FUNC_ARGS_DECL)
1532f29dbc25Smrg{
153304007ebaSmrg    SCRN_INFO_PTR(arg);
153404007ebaSmrg    return GXEnterGraphics(NULL, pScrni);
1535f29dbc25Smrg}
1536f29dbc25Smrg
1537f29dbc25Smrgstatic void
153804007ebaSmrgGXLeaveVT(VT_FUNC_ARGS_DECL)
1539f29dbc25Smrg{
154004007ebaSmrg    SCRN_INFO_PTR(arg);
1541f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1542f29dbc25Smrg
1543f29dbc25Smrg    pGeode->PrevDisplayOffset = gfx_get_display_offset();
154404007ebaSmrg    GXLeaveGraphics(pScrni);
1545f29dbc25Smrg}
1546f29dbc25Smrg
1547f29dbc25Smrgvoid
1548f29dbc25SmrgGXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1549f29dbc25Smrg{
1550f29dbc25Smrg    pScrn->PreInit = GXPreInit;
1551f29dbc25Smrg    pScrn->ScreenInit = GXScreenInit;
1552f29dbc25Smrg    pScrn->SwitchMode = GXSwitchMode;
1553f29dbc25Smrg    pScrn->AdjustFrame = GXAdjustFrame;
1554f29dbc25Smrg    pScrn->EnterVT = GXEnterVT;
1555f29dbc25Smrg    pScrn->LeaveVT = GXLeaveVT;
1556f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1557f29dbc25Smrg    pScrn->ValidMode = GXValidMode;
1558f29dbc25Smrg}
1559f29dbc25Smrg
1560f29dbc25Smrg/* ====== Common functions ======
1561f29dbc25Smrg * These are all the common functions that we use for both GX and LX - They live here
1562f29dbc25Smrg * because most of them came along for the GX first, and then were adapted to the LX.
1563f29dbc25Smrg *  We could move these to a common function, but there is no hurry
1564f29dbc25Smrg * ============================== */
1565f29dbc25Smrg
1566f29dbc25Smrgvoid
156704007ebaSmrgGeodePointerMoved(POINTER_MOVED_ARGS_DECL)
1568f29dbc25Smrg{
156904007ebaSmrg    SCRN_INFO_PTR(arg);
1570f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1571f29dbc25Smrg
1572f29dbc25Smrg    int newX = x, newY = y;
1573f29dbc25Smrg
1574f29dbc25Smrg    switch (pGeode->rotation) {
1575f29dbc25Smrg    case RR_Rotate_0:
157604007ebaSmrg        break;
1577f29dbc25Smrg    case RR_Rotate_90:
157804007ebaSmrg        newX = y;
157904007ebaSmrg        newY = pScrni->pScreen->width - x - 1;
158004007ebaSmrg        break;
1581f29dbc25Smrg    case RR_Rotate_180:
158204007ebaSmrg        newX = pScrni->pScreen->width - x - 1;
158304007ebaSmrg        newY = pScrni->pScreen->height - y - 1;
158404007ebaSmrg        break;
1585f29dbc25Smrg    case RR_Rotate_270:
158604007ebaSmrg        newX = pScrni->pScreen->height - y - 1;
158704007ebaSmrg        newY = x;
158804007ebaSmrg        break;
1589f29dbc25Smrg    }
1590f29dbc25Smrg
159104007ebaSmrg    (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY));
1592f29dbc25Smrg}
1593f29dbc25Smrg
1594f29dbc25Smrgint
1595f29dbc25SmrgGeodeGetFPGeometry(const char *str, int *width, int *height)
1596f29dbc25Smrg{
1597f29dbc25Smrg
1598f29dbc25Smrg    int ret = sscanf(str, "%dx%d", width, height);
1599f29dbc25Smrg
1600f29dbc25Smrg    return (ret == 2) ? 0 : 1;
1601f29dbc25Smrg}
1602f29dbc25Smrg
1603f29dbc25Smrgstatic void
1604f29dbc25SmrgGeodeFreeRec(ScrnInfoPtr pScrni)
1605f29dbc25Smrg{
1606f29dbc25Smrg    if (pScrni->driverPrivate != NULL) {
160704007ebaSmrg        free(pScrni->driverPrivate);
160804007ebaSmrg        pScrni->driverPrivate = NULL;
1609f29dbc25Smrg    }
1610f29dbc25Smrg}
1611f29dbc25Smrg
1612f29dbc25Smrgvoid
161304007ebaSmrgGeodeFreeScreen(FREE_SCREEN_ARGS_DECL)
1614f29dbc25Smrg{
161504007ebaSmrg    SCRN_INFO_PTR(arg);
161604007ebaSmrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1617f29dbc25Smrg
1618f29dbc25Smrg    if (pGeode == NULL)
161904007ebaSmrg        return;
1620f29dbc25Smrg
1621f29dbc25Smrg    if (pGeode->useVGA) {
162204007ebaSmrg        if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
162304007ebaSmrg            vgaHWFreeHWRec(pScrni);
1624f29dbc25Smrg    }
1625f29dbc25Smrg
162604007ebaSmrg    GeodeFreeRec(pScrni);
1627f29dbc25Smrg}
1628f29dbc25Smrg
1629f29dbc25Smrgint
1630f29dbc25SmrgGeodeCalculatePitchBytes(unsigned int width, unsigned int bpp)
1631f29dbc25Smrg{
1632f29dbc25Smrg
1633f29dbc25Smrg    int delta = width * (bpp >> 3);
1634f29dbc25Smrg
1635f29dbc25Smrg    /* Less then 640 has doubling enabled */
1636f29dbc25Smrg
1637f29dbc25Smrg    if (width < 640)
163804007ebaSmrg        delta <<= 1;
1639f29dbc25Smrg
1640c744f008Smrg    /* Calculate the pitch (compression requires a power of 2) */
1641f29dbc25Smrg
1642f29dbc25Smrg    if (delta > 4096)
164304007ebaSmrg        delta = 8192;
1644f29dbc25Smrg    else if (delta > 2048)
164504007ebaSmrg        delta = 4096;
1646f29dbc25Smrg    else if (delta > 1024)
164704007ebaSmrg        delta = 2048;
1648f29dbc25Smrg    else
164904007ebaSmrg        delta = 1024;
1650f29dbc25Smrg
1651f29dbc25Smrg    return delta;
1652f29dbc25Smrg}
1653