gx_driver.c revision 3406bd8e
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
393406bd8eSmrg#include "xorg-server.h"
40f29dbc25Smrg#include "xf86.h"
41f29dbc25Smrg#include "xf86_OSproc.h"
42f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
43f29dbc25Smrg#include "xf86Resources.h"
44f29dbc25Smrg#endif
45f29dbc25Smrg#include "xf86cmap.h"
46f29dbc25Smrg#include "compiler.h"
47f29dbc25Smrg#include "mipointer.h"
48f29dbc25Smrg#include "shadow.h"
49f29dbc25Smrg#include <X11/extensions/randr.h>
50f29dbc25Smrg#include "fb.h"
51f29dbc25Smrg#include "miscstruct.h"
52f29dbc25Smrg#include "micmap.h"
53f29dbc25Smrg#include "vbe.h"
54f29dbc25Smrg#include "fb.h"
55f29dbc25Smrg#include "randrstr.h"
56f29dbc25Smrg
57f29dbc25Smrg#include "geode.h"
58f29dbc25Smrg#include "gfx_defs.h"
59f29dbc25Smrg#include "gfx_regs.h"
60f29dbc25Smrg#include "panel.h"
61f29dbc25Smrg
62f29dbc25Smrg/* Bring in VGA functions */
63f29dbc25Smrg#include "gx_vga.c"
64f29dbc25Smrg
65f29dbc25Smrg#define GX_MIN_PITCH 1024
66f29dbc25Smrg#define GX_MAX_PITCH 8192
67f29dbc25Smrg#define GX_MAX_WIDTH  1600
68f29dbc25Smrg#define GX_MIN_HEIGHT  400
69f29dbc25Smrg#define GX_MAX_HEIGHT 1200
70f29dbc25Smrg#define GX_CB_PITCH   544
71f29dbc25Smrg#define GX_CB_SIZE    544
72f29dbc25Smrg
73f29dbc25Smrg#define GX_CPU_REG_SIZE 0x4000
74f29dbc25Smrg#define GX_GP_REG_SIZE  0x4000
75f29dbc25Smrg#define GX_VID_REG_SIZE 0x4000
76f29dbc25Smrg
77f29dbc25Smrg#define DEFAULT_IMG_LINE_BUFS 20
78f29dbc25Smrg#define DEFAULT_CLR_LINE_BUFS 20
79f29dbc25Smrg
80f29dbc25Smrgextern OptionInfoRec GX_GeodeOptions[];
81f29dbc25Smrg
82f29dbc25Smrgunsigned char *XpressROMPtr;
83f29dbc25Smrg
84f29dbc25Smrgstatic inline void
85f29dbc25Smrggx_enable_dac_power(void)
86f29dbc25Smrg{
87f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
8804007ebaSmrg                    gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH);
89f29dbc25Smrg}
90f29dbc25Smrg
91f29dbc25Smrgstatic inline void
92f29dbc25Smrggx_disable_dac_power(void)
93f29dbc25Smrg{
94f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
9504007ebaSmrg                    RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN |
9604007ebaSmrg                    (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH));
97f29dbc25Smrg}
98f29dbc25Smrg
99f29dbc25Smrgstatic void
100f29dbc25SmrgGXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
101f29dbc25Smrg{
102f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
103f29dbc25Smrg
104f29dbc25Smrg    if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) {
10504007ebaSmrg        pGeode->exaBfrOffset = *offset;
10604007ebaSmrg        *offset += pGeode->exaBfrOffset;
10704007ebaSmrg        *avail -= pGeode->exaBfrOffset;
108f29dbc25Smrg    }
109f29dbc25Smrg}
110f29dbc25Smrg
111f29dbc25Smrgstatic void
112f29dbc25SmrgGXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
113f29dbc25Smrg{
114f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
115f29dbc25Smrg    unsigned int size, i, pitch;
116f29dbc25Smrg
117f29dbc25Smrg    /* XXX - FIXME - What if we are out of room?  Then what? */
118f29dbc25Smrg    /* For now, we NULL them all out.                        */
119f29dbc25Smrg
120f29dbc25Smrg    if (pGeode->NoOfImgBuffers > 0) {
12104007ebaSmrg        size = pGeode->displayPitch * pGeode->NoOfImgBuffers;
12204007ebaSmrg        if (size <= *avail) {
12304007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++) {
12404007ebaSmrg                pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset;
12504007ebaSmrg                *offset += pGeode->displayPitch;
12604007ebaSmrg                *avail -= pGeode->displayPitch;
12704007ebaSmrg            }
12804007ebaSmrg        }
12904007ebaSmrg        else {
13004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
13104007ebaSmrg                       "Not enough memory for image write buffers.\n");
13204007ebaSmrg
13304007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
13404007ebaSmrg                pGeode->AccelImageWriteBuffers[i] = NULL;
13504007ebaSmrg        }
136f29dbc25Smrg    }
137f29dbc25Smrg
138f29dbc25Smrg    if (pGeode->NoOfColorExpandLines > 0) {
13904007ebaSmrg        pitch = ((pGeode->displayPitch + 31) >> 5) << 2;
14004007ebaSmrg        size = pitch * pGeode->NoOfColorExpandLines;
14104007ebaSmrg
14204007ebaSmrg        if (size <= *avail) {
14304007ebaSmrg            for (i = 0; i < pGeode->NoOfColorExpandLines; i++) {
14404007ebaSmrg                pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset;
14504007ebaSmrg                *offset += pitch;
14604007ebaSmrg                *avail -= pitch;
14704007ebaSmrg            }
14804007ebaSmrg        }
14904007ebaSmrg        else {
15004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
15104007ebaSmrg                       "Not enough memory for color expansion buffers.\n");
15204007ebaSmrg
15304007ebaSmrg            for (i = 0; i < pGeode->NoOfImgBuffers; i++)
15404007ebaSmrg                pGeode->AccelColorExpandBuffers[i] = NULL;
15504007ebaSmrg        }
156f29dbc25Smrg    }
157f29dbc25Smrg}
158f29dbc25Smrg
159f29dbc25Smrgstatic Bool
160f29dbc25SmrgGXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate)
161f29dbc25Smrg{
162f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
163f29dbc25Smrg
164f29dbc25Smrg    unsigned int fboffset, fbavail;
165f29dbc25Smrg    unsigned int size;
166f29dbc25Smrg    unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8;
167f29dbc25Smrg    BOOL ret = TRUE;
168f29dbc25Smrg
169f29dbc25Smrg    if (pGeode->tryCompression)
17004007ebaSmrg        pGeode->displayPitch =
17104007ebaSmrg            GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
172f29dbc25Smrg    else
17304007ebaSmrg        pGeode->displayPitch =
17404007ebaSmrg            ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
175f29dbc25Smrg
176f29dbc25Smrg    pGeode->Pitch = pGeode->displayPitch;
177f29dbc25Smrg    pGeode->displayWidth = pGeode->displayPitch / bytpp;
178f29dbc25Smrg    pScrni->displayWidth = pGeode->displayWidth;
179f29dbc25Smrg
180f29dbc25Smrg    fbavail = pGeode->FBAvail - 0x4000;
181f29dbc25Smrg
182f29dbc25Smrg    pGeode->displayOffset = fboffset = 0;
183f29dbc25Smrg    pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch;
184f29dbc25Smrg
185f29dbc25Smrg    fbavail -= pGeode->displaySize;
186f29dbc25Smrg    fboffset += pGeode->displaySize;
187f29dbc25Smrg
188f29dbc25Smrg    if (pGeode->tryCompression) {
18904007ebaSmrg        size = pScrni->virtualY * GX_CB_PITCH;
190f29dbc25Smrg
19104007ebaSmrg        if (size <= fbavail) {
19204007ebaSmrg            pGeode->CBData.compression_offset = fboffset;
193f29dbc25Smrg
19404007ebaSmrg            fboffset += size;
19504007ebaSmrg            fbavail -= size;
196f29dbc25Smrg
19704007ebaSmrg            pGeode->Compression = TRUE;
19804007ebaSmrg        }
19904007ebaSmrg        else {
20004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
20104007ebaSmrg                       "Not enough memory for compression\n");
20204007ebaSmrg            pGeode->Compression = FALSE;
20304007ebaSmrg        }
204f29dbc25Smrg    }
205f29dbc25Smrg
206f29dbc25Smrg    if (pGeode->tryHWCursor) {
207f29dbc25Smrg
20804007ebaSmrg        if (fbavail >= 1024) {
20904007ebaSmrg            pGeode->CursorStartOffset = fboffset;
21004007ebaSmrg            fboffset += 1024;
21104007ebaSmrg            fbavail -= 1024;
21204007ebaSmrg            pGeode->HWCursor = TRUE;
21304007ebaSmrg        }
21404007ebaSmrg        else {
21504007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
21604007ebaSmrg                       "Not enough memory for the hardware cursor\n");
21704007ebaSmrg            pGeode->HWCursor = FALSE;
21804007ebaSmrg        }
219f29dbc25Smrg    }
220f29dbc25Smrg
221f29dbc25Smrg    if (!pGeode->NoAccel) {
22204007ebaSmrg        if (pGeode->useEXA)
22304007ebaSmrg            GXInitEXAMemory(pScrni, &fboffset, &fbavail);
22404007ebaSmrg        else
22504007ebaSmrg            GXInitXAAMemory(pScrni, &fboffset, &fbavail);
226f29dbc25Smrg    }
227f29dbc25Smrg
228f29dbc25Smrg    pGeode->shadowSize = 0;
229f29dbc25Smrg
230f29dbc25Smrg    if (rotate != RR_Rotate_0) {
23104007ebaSmrg        if (rotate & (RR_Rotate_90 | RR_Rotate_270))
23204007ebaSmrg            size = pGeode->displayPitch * pScrni->virtualX;
23304007ebaSmrg        else
23404007ebaSmrg            size = pGeode->displayPitch * pScrni->virtualY;
23504007ebaSmrg
23604007ebaSmrg        if (size <= fbavail) {
23704007ebaSmrg            pGeode->shadowOffset = fboffset;
23804007ebaSmrg            pGeode->shadowSize = size;
23904007ebaSmrg
24004007ebaSmrg            fboffset += size;
24104007ebaSmrg            fbavail -= size;
24204007ebaSmrg        }
24304007ebaSmrg        else {
24404007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
24504007ebaSmrg                       "Not enough memory for the shadow framebuffer\n");
24604007ebaSmrg            ret = FALSE;
24704007ebaSmrg        }
248f29dbc25Smrg    }
249f29dbc25Smrg
250f29dbc25Smrg    /* XAA always exists - we can't remove it on demand like we can with EXA.
251f29dbc25Smrg     * So we assume the worse, and only give XAA enough offspace room to
252f29dbc25Smrg     * account for any eventuality that RandR might throw at us. */
253f29dbc25Smrg
254f29dbc25Smrg    if (!pGeode->NoAccel) {
255f29dbc25Smrg
25604007ebaSmrg        if (pGeode->useEXA && pGeode->pExa) {
25704007ebaSmrg            ExaDriverPtr pExa = pGeode->pExa;
258f29dbc25Smrg
25904007ebaSmrg            pExa->offScreenBase = fboffset;
26004007ebaSmrg            pExa->memorySize = fboffset + fbavail;
26104007ebaSmrg        }
262f29dbc25Smrg
26304007ebaSmrg        if (!pGeode->useEXA) {
264f29dbc25Smrg
26504007ebaSmrg#if XF86XAA
26604007ebaSmrg            if (!xf86FBManagerRunning(pScrn)) {
267f29dbc25Smrg
26804007ebaSmrg                unsigned int offset = fboffset;
26904007ebaSmrg                unsigned int avail = fbavail;
27004007ebaSmrg                RegionRec OffscreenRegion;
27104007ebaSmrg                BoxRec AvailBox;
272f29dbc25Smrg
27304007ebaSmrg                /* Assume the shadow FB exists even if it doesnt */
274f29dbc25Smrg
27504007ebaSmrg                if (pGeode->shadowSize == 0) {
27604007ebaSmrg                    size = (pScrn->width * bytpp) * pScrni->virtualX;
27704007ebaSmrg                    offset += size;
27804007ebaSmrg                    avail -= size;
27904007ebaSmrg                }
280f29dbc25Smrg
28104007ebaSmrg                AvailBox.x1 = 0;
28204007ebaSmrg                AvailBox.y1 =
28304007ebaSmrg                    (offset + pGeode->displayPitch - 1) / pGeode->displayPitch;
284f29dbc25Smrg
28504007ebaSmrg                AvailBox.x2 = pGeode->displayWidth;
28604007ebaSmrg                AvailBox.y2 = (offset + avail) / pGeode->displayPitch;
287f29dbc25Smrg
28804007ebaSmrg                if (AvailBox.y1 < AvailBox.y2) {
28904007ebaSmrg                    REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2);
290f29dbc25Smrg
29104007ebaSmrg                    if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion))
29204007ebaSmrg                        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
29304007ebaSmrg                                   "Memory manager initialization failed.\n");
294f29dbc25Smrg
29504007ebaSmrg                    REGION_UNINIT(pScrn, &OffscreenRegion);
29604007ebaSmrg                }
29704007ebaSmrg                else
29804007ebaSmrg                    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
29904007ebaSmrg                               "Cache disabled - no offscreen memory available.\n");
30004007ebaSmrg            }
30104007ebaSmrg            else
30204007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_INFO,
30304007ebaSmrg                           "XAA offscreen memory has already been allocated.\n");
30404007ebaSmrg#endif
30504007ebaSmrg        }
306f29dbc25Smrg    }
307f29dbc25Smrg    return ret;
308f29dbc25Smrg}
309f29dbc25Smrg
310f29dbc25Smrgstatic Bool
311f29dbc25SmrgGXSaveScreen(ScreenPtr pScrn, int mode)
312f29dbc25Smrg{
31304007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
314f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
315f29dbc25Smrg
316f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
31704007ebaSmrg        return vgaHWSaveScreen(pScrn, mode);
318f29dbc25Smrg
319f29dbc25Smrg    return TRUE;
320f29dbc25Smrg}
321f29dbc25Smrg
322f29dbc25Smrg/* Common function - used by the LX too */
323f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
324f29dbc25Smrgstatic inline void *
325f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
32604007ebaSmrg            struct pci_device *dev, int bar, int size)
327f29dbc25Smrg{
328f29dbc25Smrg    void *ptr;
329f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
330f29dbc25Smrg
331f29dbc25Smrg    int err = pci_device_map_range(dev,
33204007ebaSmrg                                   dev->regions[bar].base_addr,
33304007ebaSmrg                                   map_size,
33404007ebaSmrg                                   PCI_DEV_MAP_FLAG_WRITABLE |
33504007ebaSmrg                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
3367f419768Smrg                                   &ptr);
337f29dbc25Smrg
338f29dbc25Smrg    if (err)
33904007ebaSmrg        return NULL;
340f29dbc25Smrg    return ptr;
341f29dbc25Smrg}
3427f419768Smrg
3437f419768Smrgstatic inline int
3447f419768Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
3457f419768Smrg{
3467f419768Smrg    return pci_device_unmap_range(dev, ptr, size);
3477f419768Smrg}
348f29dbc25Smrg#endif
349f29dbc25Smrg
350f29dbc25Smrgextern unsigned long gfx_gx2_scratch_base;
351f29dbc25Smrg
352f29dbc25Smrgstatic Bool
353f29dbc25SmrgGXMapMem(ScrnInfoPtr pScrni)
354f29dbc25Smrg{
355f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
356f29dbc25Smrg    int index = pScrni->scrnIndex;
357f29dbc25Smrg
358f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
359f29dbc25Smrg
360f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
36104007ebaSmrg    gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
36204007ebaSmrg                                                      pci->memBase[2],
36304007ebaSmrg                                                      pci->size[2]);
364f29dbc25Smrg
36504007ebaSmrg    gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
36604007ebaSmrg                                                     pci->memBase[1],
36704007ebaSmrg                                                     pci->size[1]);
368f29dbc25Smrg
36904007ebaSmrg    gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO,
37004007ebaSmrg                                                      pci->memBase[3],
37104007ebaSmrg                                                      pci->size[3]);
372f29dbc25Smrg
37304007ebaSmrg    gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER,
37404007ebaSmrg                                                     pci->memBase[0],
37504007ebaSmrg                                                     pGeode->FBAvail);
376f29dbc25Smrg#else
377f29dbc25Smrg    gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0);
378f29dbc25Smrg    gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0);
379f29dbc25Smrg    gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0);
380f29dbc25Smrg    gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail);
381f29dbc25Smrg#endif
382f29dbc25Smrg
383f29dbc25Smrg    gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000;
384f29dbc25Smrg
3857f419768Smrg#ifndef XSERVER_LIBPCIACCESS
386f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
3877f419768Smrg#else
3887f419768Smrg    {
3897f419768Smrg        int fd = open("/dev/mem", O_RDWR);
3907f419768Smrg        if (fd < 0) {
3917f419768Smrg            xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n");
3927f419768Smrg            return FALSE;
3937f419768Smrg        }
3947f419768Smrg        XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000);
3957f419768Smrg        close(fd);
3967f419768Smrg    }
3977f419768Smrg#endif
398f29dbc25Smrg    pGeode->FBBase = gfx_virt_fbptr;
399f29dbc25Smrg
400f29dbc25Smrg    if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) ||
40104007ebaSmrg        (!gfx_virt_vidptr) || (!gfx_virt_fbptr))
40204007ebaSmrg        return FALSE;
403f29dbc25Smrg
404f29dbc25Smrg    if (!pGeode->NoAccel && pGeode->useEXA)
40504007ebaSmrg        pGeode->pExa->memoryBase = pGeode->FBBase;
406f29dbc25Smrg
407f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n",
40804007ebaSmrg               pGeode->FBAvail, pGeode->FBBase);
409f29dbc25Smrg
410f29dbc25Smrg    return TRUE;
411f29dbc25Smrg}
412f29dbc25Smrg
413f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
414f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
415f29dbc25Smrg*/
416f29dbc25Smrg
417f29dbc25Smrgstatic Bool
4187f419768SmrgGXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt)
419f29dbc25Smrg{
4207f419768Smrg#ifndef XSERVER_LIBPCIACCESS
421f29dbc25Smrg    unsigned char *ptr;
422f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
423f29dbc25Smrg    int ret;
424f29dbc25Smrg
425f29dbc25Smrg    ptr =
42604007ebaSmrg        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
42704007ebaSmrg                      strlen(vgasig));
428f29dbc25Smrg
429f29dbc25Smrg    if (ptr == NULL)
43004007ebaSmrg        return FALSE;
431f29dbc25Smrg
432f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
433f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
434f29dbc25Smrg
435f29dbc25Smrg    return ret ? FALSE : TRUE;
4367f419768Smrg#else
4377f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index);
4387f419768Smrg
4397f419768Smrg    return pci_device_is_boot_vga(pci);
4407f419768Smrg#endif
441f29dbc25Smrg}
442f29dbc25Smrg
443f29dbc25Smrgstatic Bool
444f29dbc25SmrgGXPreInit(ScrnInfoPtr pScrni, int flags)
445f29dbc25Smrg{
446f29dbc25Smrg    GeodePtr pGeode;
447f29dbc25Smrg    ClockRangePtr GeodeClockRange;
448f29dbc25Smrg    OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0];
449f29dbc25Smrg    int ret;
450f29dbc25Smrg    QQ_WORD msrValue;
451f29dbc25Smrg    EntityInfoPtr pEnt;
452f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
453f29dbc25Smrg    int modecnt;
4543406bd8eSmrg    const char *s, *panelgeo;
455f29dbc25Smrg    Bool useVGA;
456f29dbc25Smrg
457f29dbc25Smrg    if (pScrni->numEntities != 1)
45804007ebaSmrg        return FALSE;
459f29dbc25Smrg
460f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
461f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
462f29dbc25Smrg    if (pEnt->resources)
46304007ebaSmrg        return FALSE;
464f29dbc25Smrg#endif
465f29dbc25Smrg
46604007ebaSmrg    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
467f29dbc25Smrg
468f29dbc25Smrg    if (pGeode == NULL)
46904007ebaSmrg        return FALSE;
470f29dbc25Smrg
4717f419768Smrg    useVGA = GXCheckVGA(pScrni, pEnt);
472f29dbc25Smrg
473f29dbc25Smrg    if (flags & PROBE_DETECT) {
47404007ebaSmrg        GeodeProbeDDC(pScrni, pEnt->index);
47504007ebaSmrg        return TRUE;
476f29dbc25Smrg    }
477f29dbc25Smrg
478f29dbc25Smrg    /* Probe for VGA */
479f29dbc25Smrg    pGeode->useVGA = useVGA;
480f29dbc25Smrg    pGeode->pEnt = pEnt;
481f29dbc25Smrg
482f29dbc25Smrg    if (pGeode->useVGA) {
48304007ebaSmrg        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
48404007ebaSmrg            pGeode->useVGA = FALSE;
48504007ebaSmrg        else
48604007ebaSmrg            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
487f29dbc25Smrg
488f29dbc25Smrg#if INT10_SUPPORT
48904007ebaSmrg        pGeode->vesa = calloc(1, sizeof(VESARec));
490f29dbc25Smrg#endif
491f29dbc25Smrg    }
492f29dbc25Smrg
493f29dbc25Smrg    gfx_msr_init();
494f29dbc25Smrg
495f29dbc25Smrg    ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue);
496f29dbc25Smrg
497f29dbc25Smrg    if (!ret) {
49804007ebaSmrg        pGeode->Output =
49904007ebaSmrg            ((msrValue.low & RCDF_CONFIG_FMT_MASK) ==
50004007ebaSmrg             RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT;
501f29dbc25Smrg    }
502f29dbc25Smrg
503f29dbc25Smrg    /* Fill in the monitor information */
504f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
505f29dbc25Smrg
506f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
50704007ebaSmrg        return FALSE;
508f29dbc25Smrg
509f29dbc25Smrg    switch (pScrni->depth) {
510f29dbc25Smrg    case 8:
51104007ebaSmrg        pScrni->rgbBits = 8;
512f29dbc25Smrg    case 16:
513f29dbc25Smrg    case 24:
514f29dbc25Smrg    case 32:
51504007ebaSmrg        break;
516f29dbc25Smrg    default:
51704007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
51804007ebaSmrg                   "The driver does not support %d as a depth.\n",
51904007ebaSmrg                   pScrni->depth);
52004007ebaSmrg        return FALSE;
521f29dbc25Smrg    }
522f29dbc25Smrg
523f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
524f29dbc25Smrg
525f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
52604007ebaSmrg        return FALSE;
527f29dbc25Smrg
528f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
52904007ebaSmrg        return FALSE;
530f29dbc25Smrg
531f29dbc25Smrg    /*
532f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
533f29dbc25Smrg     * here.
534f29dbc25Smrg     */
535f29dbc25Smrg    {
53604007ebaSmrg        Gamma zeros = { 0.0, 0.0, 0.0 };
537f29dbc25Smrg
53804007ebaSmrg        if (!xf86SetGamma(pScrni, zeros)) {
53904007ebaSmrg            return FALSE;
54004007ebaSmrg        }
541f29dbc25Smrg    }
542f29dbc25Smrg
543f29dbc25Smrg    pScrni->progClock = TRUE;
544f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
545f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
546f29dbc25Smrg
547f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
548f29dbc25Smrg
549f29dbc25Smrg    pGeode->FBVGAActive = FALSE;
550f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
551f29dbc25Smrg    pGeode->tryCompression = TRUE;
552f29dbc25Smrg
553f29dbc25Smrg    pGeode->NoAccel = FALSE;
554f29dbc25Smrg    pGeode->useEXA = FALSE;
555f29dbc25Smrg
556f29dbc25Smrg    pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE;
557f29dbc25Smrg
558f29dbc25Smrg    pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS;
559f29dbc25Smrg    pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS;
560f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
561f29dbc25Smrg
56204007ebaSmrg    xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
563f29dbc25Smrg
564f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE,
56504007ebaSmrg                              (int *) &(pGeode->FBAvail)))
56604007ebaSmrg        pGeode->FBAvail = 0;
567f29dbc25Smrg
568f29dbc25Smrg    /* For compatability - allow SWCursor too */
569f29dbc25Smrg
570f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE))
57104007ebaSmrg        pGeode->tryHWCursor = FALSE;
572f29dbc25Smrg
573f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE))
57404007ebaSmrg        pGeode->tryCompression = FALSE;
575f29dbc25Smrg
576f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE))
57704007ebaSmrg        pGeode->NoAccel = TRUE;
578f29dbc25Smrg
579f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
580f29dbc25Smrg
581f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) {
582f29dbc25Smrg
58304007ebaSmrg        if (!xf86NameCmp(s, "LEFT"))
58404007ebaSmrg            pGeode->rotation = RR_Rotate_90;
58504007ebaSmrg        else if (!xf86NameCmp(s, "INVERT"))
58604007ebaSmrg            pGeode->rotation = RR_Rotate_180;
58704007ebaSmrg        else if (!xf86NameCmp(s, "CCW"))
58804007ebaSmrg            pGeode->rotation = RR_Rotate_270;
58904007ebaSmrg        else
59004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
591f29dbc25Smrg    }
592f29dbc25Smrg
593f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS,
59404007ebaSmrg                         &(pGeode->NoOfImgBuffers));
595f29dbc25Smrg
596f29dbc25Smrg    if (pGeode->NoOfImgBuffers <= 0)
59704007ebaSmrg        pGeode->NoOfImgBuffers = 0;
598f29dbc25Smrg
599f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
60004007ebaSmrg                         &(pGeode->NoOfColorExpandLines));
601f29dbc25Smrg
602f29dbc25Smrg    if (pGeode->NoOfColorExpandLines <= 0)
60304007ebaSmrg        pGeode->NoOfColorExpandLines = 0;
604f29dbc25Smrg
605f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
60604007ebaSmrg                         (int *) &(pGeode->exaBfrSz));
607f29dbc25Smrg
608f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
60904007ebaSmrg        pGeode->exaBfrSz = 0;
610f29dbc25Smrg
611f29dbc25Smrg    if (pGeode->Panel == TRUE) {
61204007ebaSmrg        if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE))
61304007ebaSmrg            pGeode->Panel = FALSE;
614f29dbc25Smrg    }
615f29dbc25Smrg
616f29dbc25Smrg    panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY);
617f29dbc25Smrg
618f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) {
6197f419768Smrg#if defined(XF86XAA) && defined(XF86EXA)
62004007ebaSmrg        if (!xf86NameCmp(s, "XAA"))
62104007ebaSmrg            pGeode->useEXA = FALSE;
62204007ebaSmrg        else if (xf86NameCmp(s, "EXA"))
62304007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
62404007ebaSmrg                       "Unknown accleration method %s.  Defaulting to XAA.\n",
62504007ebaSmrg                       s);
6267f419768Smrg#elif defined(XF86EXA)
6277f419768Smrg        pGeode->useEXA = TRUE;
6287f419768Smrg#else
6297f419768Smrg        pGeode->useEXA = FALSE;
6307f419768Smrg#endif
631f29dbc25Smrg    }
632f29dbc25Smrg
633f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
63404007ebaSmrg               "Using %s acceleration architecture\n",
63504007ebaSmrg               pGeode->useEXA ? "EXA" : "XAA");
636f29dbc25Smrg
637f29dbc25Smrg    /* Set up the panel */
638f29dbc25Smrg
639f29dbc25Smrg    if (pGeode->Panel) {
64004007ebaSmrg        if (panelgeo != NULL) {
64104007ebaSmrg            if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY))
64204007ebaSmrg                pGeode->Panel = FALSE;
64304007ebaSmrg        }
644f29dbc25Smrg#ifdef PNL_SUP
64504007ebaSmrg        else {
64604007ebaSmrg            int b, f;
647f29dbc25Smrg
64804007ebaSmrg            /* The bitdepth and refresh isn't used anywhere else in the driver */
649f29dbc25Smrg
65004007ebaSmrg            if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS()))
65104007ebaSmrg                Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b,
65204007ebaSmrg                                         &f);
65304007ebaSmrg        }
654f29dbc25Smrg#endif
655f29dbc25Smrg    }
656f29dbc25Smrg
657f29dbc25Smrg    /* Set up the VGA */
658f29dbc25Smrg
659f29dbc25Smrg    if (pGeode->useVGA) {
660f29dbc25Smrg#if INT10_SUPPORT
66104007ebaSmrg        VESARec *pVesa;
662f29dbc25Smrg
66304007ebaSmrg        if (!xf86LoadSubModule(pScrni, "int10"))
66404007ebaSmrg            return FALSE;
665f29dbc25Smrg
66604007ebaSmrg        pVesa = pGeode->vesa;
667f29dbc25Smrg
66804007ebaSmrg        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
66904007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
67004007ebaSmrg                       "Unable to initialize 1NT10 support\n");
67104007ebaSmrg            pGeode->useVGA = FALSE;
67204007ebaSmrg        }
673f29dbc25Smrg#endif
674f29dbc25Smrg    }
675f29dbc25Smrg
676f29dbc25Smrg    /* First try to get the framebuffer size from the framebuffer,
677f29dbc25Smrg     * and if that fails, revert all  the way back to the legacy
678f29dbc25Smrg     * method
679f29dbc25Smrg     */
680f29dbc25Smrg
681f29dbc25Smrg    if (pGeode->FBAvail == 0) {
68204007ebaSmrg        if (GeodeGetSizeFromFB(&pGeode->FBAvail))
68304007ebaSmrg            pGeode->FBAvail = gfx_get_frame_buffer_size();
684f29dbc25Smrg    }
685f29dbc25Smrg
686f29dbc25Smrg    if (pScrni->memPhysBase == 0)
68704007ebaSmrg        pScrni->memPhysBase = gfx_get_frame_buffer_base();
688f29dbc25Smrg
689f29dbc25Smrg    pScrni->fbOffset = 0;
690f29dbc25Smrg
691f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
69204007ebaSmrg        pScrni->videoRam = pGeode->FBAvail / 1024;
693f29dbc25Smrg    else
69404007ebaSmrg        pScrni->videoRam = pGeode->pEnt->device->videoRam;
695f29dbc25Smrg
69604007ebaSmrg    GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange));
697f29dbc25Smrg    GeodeClockRange->next = NULL;
698f29dbc25Smrg    GeodeClockRange->minClock = 25175;
699f29dbc25Smrg    GeodeClockRange->maxClock = 229500;
700f29dbc25Smrg    GeodeClockRange->clockIndex = -1;
701f29dbc25Smrg    GeodeClockRange->interlaceAllowed = TRUE;
702f29dbc25Smrg    GeodeClockRange->doubleScanAllowed = FALSE;
703f29dbc25Smrg
704f29dbc25Smrg    pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index);
705f29dbc25Smrg
706f29dbc25Smrg    /* I'm still not 100% sure this uses the right values */
707f29dbc25Smrg
708f29dbc25Smrg    modecnt = xf86ValidateModes(pScrni,
70904007ebaSmrg                                pScrni->monitor->Modes,
71004007ebaSmrg                                pScrni->display->modes,
71104007ebaSmrg                                GeodeClockRange,
71204007ebaSmrg                                NULL, GX_MIN_PITCH, GX_MAX_PITCH,
71304007ebaSmrg                                32, GX_MIN_HEIGHT, GX_MAX_HEIGHT,
71404007ebaSmrg                                pScrni->display->virtualX,
71504007ebaSmrg                                pScrni->display->virtualY, pGeode->FBAvail,
71604007ebaSmrg                                LOOKUP_BEST_REFRESH);
717f29dbc25Smrg
718f29dbc25Smrg    if (modecnt <= 0) {
71904007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
72004007ebaSmrg        return FALSE;
721f29dbc25Smrg    }
722f29dbc25Smrg
723f29dbc25Smrg    xf86PruneDriverModes(pScrni);
724f29dbc25Smrg
725f29dbc25Smrg    if (pScrni->modes == NULL) {
72604007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
72704007ebaSmrg        return FALSE;
728f29dbc25Smrg    }
729f29dbc25Smrg
730f29dbc25Smrg    xf86SetCrtcForModes(pScrni, 0);
731f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
732f29dbc25Smrg
733f29dbc25Smrg    xf86PrintModes(pScrni);
734f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
735f29dbc25Smrg
736f29dbc25Smrg    /* Load the modules we'll need */
737f29dbc25Smrg
738f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
73904007ebaSmrg        return FALSE;
740f29dbc25Smrg    }
741f29dbc25Smrg
742f29dbc25Smrg    if (pGeode->NoAccel == FALSE) {
74304007ebaSmrg        const char *module = (pGeode->useEXA) ? "exa" : "xaa";
744f29dbc25Smrg
74504007ebaSmrg        if (!xf86LoadSubModule(pScrni, module)) {
74604007ebaSmrg            return FALSE;
74704007ebaSmrg        }
748f29dbc25Smrg    }
749f29dbc25Smrg
750f29dbc25Smrg    if (pGeode->tryHWCursor == TRUE) {
75104007ebaSmrg        if (!xf86LoadSubModule(pScrni, "ramdac")) {
75204007ebaSmrg            return FALSE;
75304007ebaSmrg        }
754f29dbc25Smrg    }
755f29dbc25Smrg
756f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
757f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
75804007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
75904007ebaSmrg                   "Couldn't register the resources.\n");
76004007ebaSmrg        return FALSE;
761f29dbc25Smrg    }
762f29dbc25Smrg#endif
763f29dbc25Smrg    return TRUE;
764f29dbc25Smrg}
765f29dbc25Smrg
766f29dbc25Smrgstatic void
767f29dbc25SmrgGXRestore(ScrnInfoPtr pScrni)
768f29dbc25Smrg{
769f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
770f29dbc25Smrg
771f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
77204007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
773f29dbc25Smrg
77404007ebaSmrg        vgaHWProtect(pScrni, TRUE);
77504007ebaSmrg        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
77604007ebaSmrg        vgaHWProtect(pScrni, FALSE);
777f29dbc25Smrg    }
778f29dbc25Smrg}
779f29dbc25Smrg
780f29dbc25Smrgstatic Bool
781f29dbc25SmrgGXUnmapMem(ScrnInfoPtr pScrni)
782f29dbc25Smrg{
783f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
784f29dbc25Smrg
785f29dbc25Smrg    /* unmap all the memory map's */
7867f419768Smrg#ifndef XSERVER_LIBPCIACCESS
787f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE);
788f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE);
789f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE);
790f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail);
7917f419768Smrg#else
7927f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
7937f419768Smrg
7947f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_regptr, GX_CPU_REG_SIZE);
7957f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_gpptr, GX_GP_REG_SIZE);
7967f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_vidptr, GX_VID_REG_SIZE);
7977f419768Smrg    unmap_pci_mem(pScrni, pci, gfx_virt_fbptr, pGeode->FBAvail);
7987f419768Smrg
7997f419768Smrg    munmap(XpressROMPtr, 0x10000);
8007f419768Smrg#endif
801f29dbc25Smrg    return TRUE;
802f29dbc25Smrg}
803f29dbc25Smrg
804f29dbc25Smrgstatic void
805f29dbc25SmrgGXSetDvLineSize(unsigned int pitch)
806f29dbc25Smrg{
807f29dbc25Smrg    unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024;
808f29dbc25Smrg
809f29dbc25Smrg    if (pitch > 1024) {
81004007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_2048;
811f29dbc25Smrg    }
812f29dbc25Smrg    if (pitch > 2048) {
81304007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_4096;
814f29dbc25Smrg    }
815f29dbc25Smrg    if (pitch > 4096) {
81604007ebaSmrg        dv_size = MDC_DV_LINE_SIZE_8192;
817f29dbc25Smrg    }
818f29dbc25Smrg
819f29dbc25Smrg    /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
820f29dbc25Smrg
821f29dbc25Smrg    temp = READ_REG32(MDC_DV_CTL);
822f29dbc25Smrg    WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size);
823f29dbc25Smrg}
824f29dbc25Smrg
825f29dbc25Smrg/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */
826f29dbc25Smrg
827f29dbc25Smrgstatic void
82804007ebaSmrgGXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
829f29dbc25Smrg{
83004007ebaSmrg    SCRN_INFO_PTR(arg);
831f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
832f29dbc25Smrg    unsigned long offset;
833f29dbc25Smrg
834f29dbc25Smrg    offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3);
835f29dbc25Smrg
836f29dbc25Smrg    gfx_set_display_offset(offset);
837f29dbc25Smrg}
838f29dbc25Smrg
839f29dbc25Smrgstatic Bool
840f29dbc25SmrgGXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode)
841f29dbc25Smrg{
842f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
843f29dbc25Smrg    int flags = 0;
844f29dbc25Smrg    int custom = 0;
845f29dbc25Smrg
846f29dbc25Smrg    pScrni->vtSema = TRUE;
847f29dbc25Smrg
848f29dbc25Smrg    gx_disable_dac_power();
849f29dbc25Smrg
850f29dbc25Smrg    if (pMode->Flags & V_NHSYNC)
85104007ebaSmrg        flags |= 1;
852f29dbc25Smrg    if (pMode->Flags & V_NVSYNC)
85304007ebaSmrg        flags |= 2;
854f29dbc25Smrg
855f29dbc25Smrg    /* Check to see if we should use custom or built-in timings */
856f29dbc25Smrg
857f29dbc25Smrg    if (pGeode->Panel)
85804007ebaSmrg        custom = (pMode->type & M_T_USERDEF);
859f29dbc25Smrg    else
86004007ebaSmrg        custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
861f29dbc25Smrg
862f29dbc25Smrg    /* If we're not doing a custom mode, then just set the fixed timings,
863f29dbc25Smrg     * otherwise, do the whole shooting match */
864f29dbc25Smrg
865f29dbc25Smrg    if (!custom) {
86604007ebaSmrg        GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY,
86704007ebaSmrg                              pMode->CrtcHDisplay, pMode->CrtcVDisplay,
86804007ebaSmrg                              pScrni->bitsPerPixel));
86904007ebaSmrg    }
87004007ebaSmrg    else {
87104007ebaSmrg        if (pGeode->Panel)
87204007ebaSmrg            GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY,
87304007ebaSmrg                                  pMode->CrtcHDisplay, pMode->CrtcVDisplay,
87404007ebaSmrg                                  pScrni->bitsPerPixel));
87504007ebaSmrg
87604007ebaSmrg        GFX(set_display_timings(pScrni->bitsPerPixel, flags,
87704007ebaSmrg                                pMode->CrtcHDisplay, pMode->CrtcHBlankStart,
87804007ebaSmrg                                pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd,
87904007ebaSmrg                                pMode->CrtcHBlankEnd, pMode->CrtcHTotal,
88004007ebaSmrg                                pMode->CrtcVDisplay, pMode->CrtcVBlankStart,
88104007ebaSmrg                                pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd,
88204007ebaSmrg                                pMode->CrtcVBlankEnd, pMode->CrtcVTotal,
88304007ebaSmrg                                (int) ((pMode->SynthClock / 1000.0) *
88404007ebaSmrg                                       0x10000)));
885f29dbc25Smrg    }
886f29dbc25Smrg
887f29dbc25Smrg    GFX(set_crt_enable(CRT_ENABLE));
888f29dbc25Smrg    GFX(set_display_pitch(pGeode->displayPitch));
889f29dbc25Smrg    GFX(set_display_offset(0L));
890f29dbc25Smrg    GFX(wait_vertical_blank());
891f29dbc25Smrg
892f29dbc25Smrg    if (pGeode->Compression) {
89304007ebaSmrg        GXSetDvLineSize(pGeode->Pitch);
894f29dbc25Smrg
89504007ebaSmrg        gfx_set_compression_offset(pGeode->CBData.compression_offset);
89604007ebaSmrg        gfx_set_compression_pitch(GX_CB_PITCH);
89704007ebaSmrg        gfx_set_compression_size(GX_CB_SIZE);
898f29dbc25Smrg
89904007ebaSmrg        gfx_set_compression_enable(1);
900f29dbc25Smrg    }
901f29dbc25Smrg
902f29dbc25Smrg    if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) {
90304007ebaSmrg        GXLoadCursorImage(pScrni, NULL);
90404007ebaSmrg        GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0));
90504007ebaSmrg        GXShowCursor(pScrni);
90604007ebaSmrg    }
90704007ebaSmrg    else {
90804007ebaSmrg        GFX(set_cursor_enable(0));
90904007ebaSmrg        pGeode->HWCursor = FALSE;
910f29dbc25Smrg    }
911f29dbc25Smrg
91204007ebaSmrg    GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0));
913f29dbc25Smrg    gx_enable_dac_power();
914f29dbc25Smrg
915f29dbc25Smrg    return TRUE;
916f29dbc25Smrg}
917f29dbc25Smrg
918f29dbc25Smrgstatic Bool
91904007ebaSmrgGXSwitchMode(SWITCH_MODE_ARGS_DECL)
920f29dbc25Smrg{
92104007ebaSmrg    SCRN_INFO_PTR(arg);
922f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
923f29dbc25Smrg    int ret = TRUE;
924f29dbc25Smrg    int rotate;
925f29dbc25Smrg
926f29dbc25Smrg    /* Syn the engine and shutdown the DAC momentarily */
927f29dbc25Smrg
928f29dbc25Smrg    gfx_wait_until_idle();
929f29dbc25Smrg
930f29dbc25Smrg    /* Set up the memory for the new mode */
931f29dbc25Smrg    rotate = GXGetRotation(pScrni->pScreen);
932f29dbc25Smrg    ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate);
933f29dbc25Smrg
934f29dbc25Smrg    if (ret) {
93504007ebaSmrg        if (pGeode->curMode != pMode)
93604007ebaSmrg            ret = GXSetVideoMode(pScrni, pMode);
937f29dbc25Smrg    }
938f29dbc25Smrg
939f29dbc25Smrg    if (ret)
94004007ebaSmrg        ret = GXRotate(pScrni, pMode);
941f29dbc25Smrg
942f29dbc25Smrg    /* Go back the way it was */
943f29dbc25Smrg
944f29dbc25Smrg    if (ret == FALSE) {
94504007ebaSmrg        if (!GXSetVideoMode(pScrni, pGeode->curMode))
94604007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
94704007ebaSmrg                       "Could not restore the previous mode\n");
94804007ebaSmrg    }
94904007ebaSmrg    else
95004007ebaSmrg        pGeode->curMode = pMode;
951f29dbc25Smrg
952f29dbc25Smrg    return ret;
953f29dbc25Smrg}
954f29dbc25Smrg
955f29dbc25Smrgstatic void
956f29dbc25SmrgGXLeaveGraphics(ScrnInfoPtr pScrni)
957f29dbc25Smrg{
958f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
959f29dbc25Smrg
960f29dbc25Smrg    gfx_wait_until_idle();
961f29dbc25Smrg
962f29dbc25Smrg    /* Restore VG registers */
963f29dbc25Smrg    gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp,
96404007ebaSmrg                            pGeode->FBgfxdisplaytiming.wPolarity,
96504007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHActive,
96604007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHBlankStart,
96704007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHSyncStart,
96804007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHSyncEnd,
96904007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHBlankEnd,
97004007ebaSmrg                            pGeode->FBgfxdisplaytiming.wHTotal,
97104007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVActive,
97204007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVBlankStart,
97304007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVSyncStart,
97404007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVSyncEnd,
97504007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVBlankEnd,
97604007ebaSmrg                            pGeode->FBgfxdisplaytiming.wVTotal,
97704007ebaSmrg                            pGeode->FBgfxdisplaytiming.dwDotClock);
978f29dbc25Smrg
979f29dbc25Smrg    gfx_set_compression_enable(0);
980f29dbc25Smrg
981f29dbc25Smrg    /* Restore the previous Compression state */
982f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
98304007ebaSmrg        gfx_set_compression_offset(pGeode->FBCompressionOffset);
98404007ebaSmrg        gfx_set_compression_pitch(pGeode->FBCompressionPitch);
98504007ebaSmrg        gfx_set_compression_size(pGeode->FBCompressionSize);
98604007ebaSmrg        gfx_set_compression_enable(1);
987f29dbc25Smrg    }
988f29dbc25Smrg
989f29dbc25Smrg    gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch);
990f29dbc25Smrg
991f29dbc25Smrg    gfx_set_display_offset(pGeode->FBDisplayOffset);
992f29dbc25Smrg
993f29dbc25Smrg    /* Restore Cursor */
994f29dbc25Smrg    gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0);
995f29dbc25Smrg
996f29dbc25Smrg    if (pGeode->useVGA) {
99704007ebaSmrg        pGeode->vesa->pInt->num = 0x10;
99804007ebaSmrg        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
99904007ebaSmrg        pGeode->vesa->pInt->bx = 0;
100004007ebaSmrg        xf86ExecX86int10(pGeode->vesa->pInt);
100104007ebaSmrg        gfx_delay_milliseconds(3);
1002f29dbc25Smrg    }
1003f29dbc25Smrg
1004f29dbc25Smrg    GXRestore(pScrni);
1005f29dbc25Smrg
1006f29dbc25Smrg    gx_enable_dac_power();
1007f29dbc25Smrg}
1008f29dbc25Smrg
1009f29dbc25Smrgstatic Bool
101004007ebaSmrgGXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
1011f29dbc25Smrg{
101204007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1013f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1014f29dbc25Smrg
1015f29dbc25Smrg    if (pScrni->vtSema)
101604007ebaSmrg        GXLeaveGraphics(pScrni);
1017f29dbc25Smrg
101804007ebaSmrg#ifdef XF86XAA
1019f29dbc25Smrg    if (pGeode->AccelInfoRec)
102004007ebaSmrg        XAADestroyInfoRec(pGeode->AccelInfoRec);
102104007ebaSmrg#endif
1022f29dbc25Smrg
1023f29dbc25Smrg    if (pGeode->AccelImageWriteBuffers) {
102404007ebaSmrg        free(pGeode->AccelImageWriteBuffers[0]);
102504007ebaSmrg        free(pGeode->AccelImageWriteBuffers);
102604007ebaSmrg        pGeode->AccelImageWriteBuffers = NULL;
1027f29dbc25Smrg    }
1028f29dbc25Smrg
1029f29dbc25Smrg    if (pGeode->AccelColorExpandBuffers) {
103004007ebaSmrg        free(pGeode->AccelColorExpandBuffers);
103104007ebaSmrg        pGeode->AccelColorExpandBuffers = NULL;
1032f29dbc25Smrg    }
1033f29dbc25Smrg
1034f29dbc25Smrg    if (pGeode->pExa) {
103504007ebaSmrg        exaDriverFini(pScrn);
103604007ebaSmrg        free(pGeode->pExa);
103704007ebaSmrg        pGeode->pExa = NULL;
1038f29dbc25Smrg    }
1039f29dbc25Smrg
1040f29dbc25Smrg    pScrni->vtSema = FALSE;
1041f29dbc25Smrg
1042f29dbc25Smrg    GXUnmapMem(pScrni);
1043f29dbc25Smrg
1044f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
1045f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
1046f29dbc25Smrg
1047f29dbc25Smrg    if (pScrn->CloseScreen)
104804007ebaSmrg        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
1049f29dbc25Smrg
1050f29dbc25Smrg    return TRUE;
1051f29dbc25Smrg}
1052f29dbc25Smrg
1053f29dbc25Smrgstatic Bool
1054f29dbc25SmrgGXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
1055f29dbc25Smrg{
1056f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1057f29dbc25Smrg
1058f29dbc25Smrg    if (!GXMapMem(pScrni))
105904007ebaSmrg        return FALSE;
1060f29dbc25Smrg
1061f29dbc25Smrg    if (pGeode->useVGA)
106204007ebaSmrg        pGeode->FBVGAActive = gu2_get_vga_active();
1063f29dbc25Smrg
1064f29dbc25Smrg    gfx_wait_until_idle();
1065f29dbc25Smrg
1066f29dbc25Smrg    /* Save off the current state (should this be somewhere else)? */
1067f29dbc25Smrg
1068f29dbc25Smrg    pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency();
1069f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch();
1070f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp();
1071f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal();
1072f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive();
1073f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start();
1074f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end();
1075f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start();
1076f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end();
1077f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal();
1078f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive();
1079f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start();
1080f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end();
1081f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start();
1082f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end();
1083f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities();
1084f29dbc25Smrg
1085f29dbc25Smrg    pGeode->FBDisplayOffset = gfx_get_display_offset();
1086f29dbc25Smrg
1087f29dbc25Smrg    if (pGeode->useVGA) {
108804007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1089f29dbc25Smrg
109004007ebaSmrg        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
1091f29dbc25Smrg    }
1092f29dbc25Smrg
1093f29dbc25Smrg    pGeode->FBCompressionEnable = gfx_get_compression_enable();
1094f29dbc25Smrg    pGeode->FBCompressionOffset = gfx_get_compression_offset();
1095f29dbc25Smrg    pGeode->FBCompressionPitch = gfx_get_compression_pitch();
1096f29dbc25Smrg    pGeode->FBCompressionSize = gfx_get_compression_size();
1097f29dbc25Smrg
1098f29dbc25Smrg#ifdef PNL_SUP
1099f29dbc25Smrg    Pnl_SavePanelState();
1100f29dbc25Smrg#endif
1101f29dbc25Smrg
1102f29dbc25Smrg    /* Turn off the VGA */
1103f29dbc25Smrg
1104f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
110504007ebaSmrg        unsigned short sequencer;
110604007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1107f29dbc25Smrg
110804007ebaSmrg        /* Map VGA aperture */
110904007ebaSmrg        if (!vgaHWMapMem(pScrni))
111004007ebaSmrg            return FALSE;
1111f29dbc25Smrg
111204007ebaSmrg        /* Unlock VGA registers */
111304007ebaSmrg        vgaHWUnlock(pvgaHW);
1114f29dbc25Smrg
111504007ebaSmrg        /* Save the current state and setup the current mode */
111604007ebaSmrg        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
1117f29dbc25Smrg
111804007ebaSmrg        /* DISABLE VGA SEQUENCER */
111904007ebaSmrg        /* This allows the VGA state machine to terminate. We must delay */
112004007ebaSmrg        /* such that there are no pending MBUS requests.  */
1121f29dbc25Smrg
112204007ebaSmrg        gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
112304007ebaSmrg        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
112404007ebaSmrg        sequencer |= MDC_CLK_MODE_SCREEN_OFF;
112504007ebaSmrg        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1126f29dbc25Smrg
112704007ebaSmrg        gfx_delay_milliseconds(1);
1128f29dbc25Smrg
112904007ebaSmrg        /* BLANK THE VGA DISPLAY */
113004007ebaSmrg        gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET);
113104007ebaSmrg        sequencer = gfx_inb(MDC_SEQUENCER_DATA);
113204007ebaSmrg        sequencer &= ~MDC_RESET_VGA_DISP_ENABLE;
113304007ebaSmrg        gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1134f29dbc25Smrg
113504007ebaSmrg        gfx_delay_milliseconds(1);
1136f29dbc25Smrg    }
1137f29dbc25Smrg
1138f29dbc25Smrg    /* Set up the memory */
1139f29dbc25Smrg    /* XXX - FIXME - when we alow inital rotation, it should be here */
1140f29dbc25Smrg    GXAllocateMemory(pScrn, pScrni, pGeode->rotation);
1141f29dbc25Smrg
1142f29dbc25Smrg    /* Clear the framebuffer */
1143f29dbc25Smrg    memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize);
1144f29dbc25Smrg
1145f29dbc25Smrg    /* Set up the video mode */
1146f29dbc25Smrg    GXSetVideoMode(pScrni, pScrni->currentMode);
1147f29dbc25Smrg    pGeode->curMode = pScrni->currentMode;
1148f29dbc25Smrg
1149f29dbc25Smrg    return TRUE;
1150f29dbc25Smrg}
1151f29dbc25Smrg
1152f29dbc25Smrgstatic void
1153f29dbc25SmrgGXLoadPalette(ScrnInfoPtr pScrni,
115404007ebaSmrg              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
1155f29dbc25Smrg{
1156f29dbc25Smrg    int i, index, color;
1157f29dbc25Smrg
1158f29dbc25Smrg    for (i = 0; i < numColors; i++) {
115904007ebaSmrg        index = indizes[i] & 0xFF;
116004007ebaSmrg        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
116104007ebaSmrg            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
116204007ebaSmrg            ((unsigned long) (colors[index].blue & 0xFF));
1163f29dbc25Smrg
116404007ebaSmrg        GFX(set_display_palette_entry(index, color));
1165f29dbc25Smrg    }
1166f29dbc25Smrg}
1167f29dbc25Smrg
1168f29dbc25Smrg#ifdef DPMSExtension
1169f29dbc25Smrgstatic void
1170f29dbc25SmrgGXPanelPower(int enable)
1171f29dbc25Smrg{
1172f29dbc25Smrg    unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT);
1173f29dbc25Smrg
1174f29dbc25Smrg    if (enable != 0)
117504007ebaSmrg        power |= RCDF_PM_PANEL_POWER_ON;
1176f29dbc25Smrg    else
117704007ebaSmrg        power &= ~RCDF_PM_PANEL_POWER_ON;
1178f29dbc25Smrg
1179f29dbc25Smrg    WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
1180f29dbc25Smrg}
1181f29dbc25Smrg
1182f29dbc25Smrgstatic void
1183f29dbc25SmrgGXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags)
1184f29dbc25Smrg{
1185f29dbc25Smrg    GeodeRec *pGeode;
1186f29dbc25Smrg
1187f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
1188f29dbc25Smrg
1189f29dbc25Smrg    if (!pScrni->vtSema)
119004007ebaSmrg        return;
1191f29dbc25Smrg
1192f29dbc25Smrg    switch (mode) {
1193f29dbc25Smrg    case DPMSModeOn:
119404007ebaSmrg        /* Screen: On; HSync: On; VSync: On */
119504007ebaSmrg        GFX(set_crt_enable(CRT_ENABLE));
1196f29dbc25Smrg#if defined(PNL_SUP)
119704007ebaSmrg        if (pGeode->Panel) {
119804007ebaSmrg            Pnl_PowerUp();
119904007ebaSmrg            GXPanelPower(1);
120004007ebaSmrg        }
1201f29dbc25Smrg#endif
120204007ebaSmrg        break;
1203f29dbc25Smrg
1204f29dbc25Smrg    case DPMSModeStandby:
120504007ebaSmrg        /* Screen: Off; HSync: Off; VSync: On */
120604007ebaSmrg        GFX(set_crt_enable(CRT_STANDBY));
1207f29dbc25Smrg#if defined(PNL_SUP)
120804007ebaSmrg        if (pGeode->Panel) {
120904007ebaSmrg            Pnl_PowerDown();
121004007ebaSmrg            GXPanelPower(0);
121104007ebaSmrg        }
1212f29dbc25Smrg#endif
121304007ebaSmrg        break;
1214f29dbc25Smrg
1215f29dbc25Smrg    case DPMSModeSuspend:
121604007ebaSmrg        /* Screen: Off; HSync: On; VSync: Off */
121704007ebaSmrg        GFX(set_crt_enable(CRT_SUSPEND));
1218f29dbc25Smrg#if defined(PNL_SUP)
121904007ebaSmrg        if (pGeode->Panel) {
122004007ebaSmrg            Pnl_PowerDown();
122104007ebaSmrg            GXPanelPower(0);
122204007ebaSmrg        }
1223f29dbc25Smrg#endif
122404007ebaSmrg        break;
1225f29dbc25Smrg
1226f29dbc25Smrg    case DPMSModeOff:
122704007ebaSmrg        /* Screen: Off; HSync: Off; VSync: Off */
122804007ebaSmrg        GFX(set_crt_enable(CRT_DISABLE));
1229f29dbc25Smrg#if defined(PNL_SUP)
123004007ebaSmrg        if (pGeode->Panel) {
123104007ebaSmrg            Pnl_PowerDown();
123204007ebaSmrg            GXPanelPower(0);
123304007ebaSmrg        }
1234f29dbc25Smrg#endif
123504007ebaSmrg        break;
1236f29dbc25Smrg    }
1237f29dbc25Smrg}
1238f29dbc25Smrg#endif
1239f29dbc25Smrg
1240f29dbc25Smrgstatic Bool
1241f29dbc25SmrgGXCreateScreenResources(ScreenPtr pScreen)
1242f29dbc25Smrg{
124304007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen);
1244f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1245f29dbc25Smrg
1246f29dbc25Smrg    pScreen->CreateScreenResources = pGeode->CreateScreenResources;
1247f29dbc25Smrg    if (!(*pScreen->CreateScreenResources) (pScreen))
124804007ebaSmrg        return FALSE;
1249f29dbc25Smrg
1250f29dbc25Smrg    if (xf86LoaderCheckSymbol("GXRandRSetConfig")
125104007ebaSmrg        && pGeode->rotation != RR_Rotate_0) {
125204007ebaSmrg        Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate,
125304007ebaSmrg                                     RRScreenSizePtr pSize) = NULL;
1254f29dbc25Smrg
125504007ebaSmrg        RRScreenSize p;
125604007ebaSmrg        Rotation requestedRotation = pGeode->rotation;
1257f29dbc25Smrg
125804007ebaSmrg        pGeode->rotation = RR_Rotate_0;
1259f29dbc25Smrg
126004007ebaSmrg        /* Just setup enough for an initial rotate */
1261f29dbc25Smrg
126204007ebaSmrg        p.width = pScreen->width;
126304007ebaSmrg        p.height = pScreen->height;
126404007ebaSmrg        p.mmWidth = pScreen->mmWidth;
126504007ebaSmrg        p.mmHeight = pScreen->mmHeight;
1266f29dbc25Smrg
126704007ebaSmrg        GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig");
126804007ebaSmrg        if (GXRandRSetConfig) {
126904007ebaSmrg            pGeode->starting = TRUE;
127004007ebaSmrg            (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p);
127104007ebaSmrg            pGeode->starting = FALSE;
127204007ebaSmrg        }
1273f29dbc25Smrg    }
1274f29dbc25Smrg
1275f29dbc25Smrg    return TRUE;
1276f29dbc25Smrg}
1277f29dbc25Smrg
1278f29dbc25Smrgstatic Bool
127904007ebaSmrgGXScreenInit(SCREEN_INIT_ARGS_DECL)
1280f29dbc25Smrg{
128104007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
1282f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1283f29dbc25Smrg    XF86ModReqInfo shadowReq;
1284f29dbc25Smrg    int maj, min, ret, rotate;
1285f29dbc25Smrg
1286f29dbc25Smrg    pGeode->starting = TRUE;
1287f29dbc25Smrg
1288f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
1289f29dbc25Smrg
1290f29dbc25Smrg    if (pGeode->useVGA) {
1291f29dbc25Smrg
129204007ebaSmrg        if (!vgaHWMapMem(pScrni))
129304007ebaSmrg            return FALSE;
1294f29dbc25Smrg
129504007ebaSmrg        vgaHWGetIOBase(VGAHWPTR(pScrni));
1296f29dbc25Smrg    }
1297f29dbc25Smrg
1298f29dbc25Smrg    if (!pGeode->NoAccel) {
1299f29dbc25Smrg
130004007ebaSmrg        if (pGeode->useEXA) {
130104007ebaSmrg
130204007ebaSmrg            if (!(pGeode->pExa = exaDriverAlloc())) {
130304007ebaSmrg                xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
130404007ebaSmrg                           "Couldn't allocate the EXA structure.\n");
130504007ebaSmrg                pGeode->NoAccel = TRUE;
130604007ebaSmrg            }
130704007ebaSmrg            else {
130804007ebaSmrg                ExaDriverPtr pExa = pGeode->pExa;
130904007ebaSmrg
131004007ebaSmrg                /* THis is set in GXAllocMem */
131104007ebaSmrg                pExa->memoryBase = 0;
131204007ebaSmrg
131304007ebaSmrg                /* This is set in GXAllocateMemory */
131404007ebaSmrg                pExa->memorySize = 0;
131504007ebaSmrg
131604007ebaSmrg                pExa->pixmapOffsetAlign = 32;
131704007ebaSmrg                pExa->pixmapPitchAlign = 32;
131804007ebaSmrg                pExa->flags = EXA_OFFSCREEN_PIXMAPS;
131904007ebaSmrg                pExa->maxX = GX_MAX_WIDTH - 1;
132004007ebaSmrg                pExa->maxY = GX_MAX_HEIGHT - 1;
132104007ebaSmrg            }
132204007ebaSmrg        }
132304007ebaSmrg        else {
132404007ebaSmrg            pGeode->AccelImageWriteBuffers =
132504007ebaSmrg                calloc(pGeode->NoOfImgBuffers,
132604007ebaSmrg                       sizeof(pGeode->AccelImageWriteBuffers[0]));
132704007ebaSmrg            pGeode->AccelColorExpandBuffers =
132804007ebaSmrg                calloc(pGeode->NoOfColorExpandLines,
132904007ebaSmrg                       sizeof(pGeode->AccelColorExpandBuffers[0]));
133004007ebaSmrg        }
1331f29dbc25Smrg    }
1332f29dbc25Smrg
1333f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
1334f29dbc25Smrg
1335f29dbc25Smrg    if (!GXEnterGraphics(pScrn, pScrni))
133604007ebaSmrg        return FALSE;
1337f29dbc25Smrg
1338f29dbc25Smrg    miClearVisualTypes();
1339f29dbc25Smrg
1340f29dbc25Smrg    /* XXX Again - take down anything? */
1341f29dbc25Smrg
1342f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
134304007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
134404007ebaSmrg                              TrueColorMask, pScrni->rgbBits,
134504007ebaSmrg                              pScrni->defaultVisual)) {
134604007ebaSmrg            return FALSE;
134704007ebaSmrg        }
134804007ebaSmrg    }
134904007ebaSmrg    else {
135004007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
135104007ebaSmrg                              miGetDefaultVisualMask(pScrni->depth),
135204007ebaSmrg                              pScrni->rgbBits, pScrni->defaultVisual)) {
135304007ebaSmrg            return FALSE;
135404007ebaSmrg        }
1355f29dbc25Smrg    }
1356f29dbc25Smrg
1357f29dbc25Smrg    miSetPixmapDepths();
1358f29dbc25Smrg
1359f29dbc25Smrg    /* Point at the visible area to start */
1360f29dbc25Smrg
1361f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset,
136204007ebaSmrg                       pScrni->virtualX, pScrni->virtualY,
136304007ebaSmrg                       pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth,
136404007ebaSmrg                       pScrni->bitsPerPixel);
1365f29dbc25Smrg
1366f29dbc25Smrg    if (!ret)
136704007ebaSmrg        return FALSE;
1368f29dbc25Smrg
1369f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
1370f29dbc25Smrg
1371f29dbc25Smrg    /* Set up the color ordering */
1372f29dbc25Smrg
1373f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
137404007ebaSmrg        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
137504007ebaSmrg
137604007ebaSmrg        while (--visual >= pScrn->visuals) {
137704007ebaSmrg            if ((visual->class | DynamicClass) == DirectColor) {
137804007ebaSmrg                visual->offsetRed = pScrni->offset.red;
137904007ebaSmrg                visual->offsetGreen = pScrni->offset.green;
138004007ebaSmrg                visual->offsetBlue = pScrni->offset.blue;
138104007ebaSmrg                visual->redMask = pScrni->mask.red;
138204007ebaSmrg                visual->greenMask = pScrni->mask.green;
138304007ebaSmrg                visual->blueMask = pScrni->mask.blue;
138404007ebaSmrg            }
138504007ebaSmrg        }
1386f29dbc25Smrg    }
1387f29dbc25Smrg
1388f29dbc25Smrg    /* Must follow the color ordering */
1389f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
1390f29dbc25Smrg
1391f29dbc25Smrg    if (!pGeode->NoAccel)
139204007ebaSmrg        GXAccelInit(pScrn);
1393f29dbc25Smrg
1394f29dbc25Smrg    xf86SetBackingStore(pScrn);
1395f29dbc25Smrg
1396f29dbc25Smrg    /* Set up the soft cursor */
1397f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
1398f29dbc25Smrg
1399f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
1400f29dbc25Smrg
1401f29dbc25Smrg    if (pGeode->tryHWCursor) {
140204007ebaSmrg        if (!GXHWCursorInit(pScrn))
140304007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
140404007ebaSmrg                       "Hardware cursor initialization failed.\n");
1405f29dbc25Smrg    }
1406f29dbc25Smrg
1407f29dbc25Smrg    /* Set up the color map */
1408f29dbc25Smrg
1409f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
141004007ebaSmrg        return FALSE;
1411f29dbc25Smrg
1412f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
141304007ebaSmrg        /* Must follow initialization of the default colormap */
1414f29dbc25Smrg
141504007ebaSmrg        if (!xf86HandleColormaps(pScrn, 256, 8,
141604007ebaSmrg                                 GXLoadPalette, NULL,
141704007ebaSmrg                                 CMAP_PALETTED_TRUECOLOR |
141804007ebaSmrg                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
141904007ebaSmrg            return FALSE;
142004007ebaSmrg        }
1421f29dbc25Smrg    }
1422f29dbc25Smrg#ifdef DPMSExtension
1423f29dbc25Smrg    xf86DPMSInit(pScrn, GXDPMSSet, 0);
1424f29dbc25Smrg#endif
1425f29dbc25Smrg
1426f29dbc25Smrg    GXInitVideo(pScrn);
1427f29dbc25Smrg
1428f29dbc25Smrg    /* Set up RandR */
1429f29dbc25Smrg
143004007ebaSmrg    xf86DisableRandR();         /* We provide our own RandR goodness */
1431f29dbc25Smrg
1432f29dbc25Smrg    /* Try to set up the shadow FB for rotation */
1433f29dbc25Smrg
1434f29dbc25Smrg    memset(&shadowReq, 0, sizeof(shadowReq));
1435f29dbc25Smrg    shadowReq.majorversion = 1;
1436f29dbc25Smrg    shadowReq.minorversion = 1;
1437f29dbc25Smrg
1438f29dbc25Smrg    if (LoadSubModule(pScrni->module, "shadow",
143904007ebaSmrg                      NULL, NULL, NULL, &shadowReq, &maj, &min)) {
1440f29dbc25Smrg
144104007ebaSmrg        rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
144204007ebaSmrg        shadowSetup(pScrn);
144304007ebaSmrg    }
144404007ebaSmrg    else {
144504007ebaSmrg        LoaderErrorMsg(NULL, "shadow", maj, min);
144604007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
144704007ebaSmrg                   "Error loading shadow - rotation not available.\n");
1448f29dbc25Smrg
144904007ebaSmrg        if (pGeode->rotation != RR_Rotate_0)
145004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
145104007ebaSmrg                       "Reverting back to normal rotation.\n");
1452f29dbc25Smrg
145304007ebaSmrg        rotate = pGeode->rotation = RR_Rotate_0;
1454f29dbc25Smrg    }
1455f29dbc25Smrg
1456f29dbc25Smrg    GXRandRInit(pScrn, rotate);
1457f29dbc25Smrg
1458f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
1459f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
1460f29dbc25Smrg
1461f29dbc25Smrg    pGeode->CreateScreenResources = pScrn->CreateScreenResources;
1462f29dbc25Smrg    pScrn->CreateScreenResources = GXCreateScreenResources;
1463f29dbc25Smrg
1464f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
1465f29dbc25Smrg    pScrn->CloseScreen = GXCloseScreen;
1466f29dbc25Smrg    pScrn->SaveScreen = GXSaveScreen;
1467f29dbc25Smrg
1468f29dbc25Smrg    if (serverGeneration == 1)
146904007ebaSmrg        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1470f29dbc25Smrg
1471f29dbc25Smrg    pGeode->starting = FALSE;
1472f29dbc25Smrg
1473f29dbc25Smrg    return TRUE;
1474f29dbc25Smrg}
1475f29dbc25Smrg
1476f29dbc25Smrgstatic int
147704007ebaSmrgGXValidMode(VALID_MODE_ARGS_DECL)
1478f29dbc25Smrg{
147904007ebaSmrg    SCRN_INFO_PTR(arg);
1480f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1481f29dbc25Smrg    int p;
1482f29dbc25Smrg    int custom = 0;
1483f29dbc25Smrg
1484f29dbc25Smrg    if (pGeode->Panel)
148504007ebaSmrg        custom = (pMode->type & M_T_USERDEF);
1486f29dbc25Smrg    else
148704007ebaSmrg        custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
1488f29dbc25Smrg
1489f29dbc25Smrg    /* Use the durango lookup for !custom modes */
1490f29dbc25Smrg
1491f29dbc25Smrg    if (!custom && pGeode->Panel) {
1492f29dbc25Smrg        if (pMode->CrtcHDisplay > pGeode->PanelX ||
1493f29dbc25Smrg            pMode->CrtcVDisplay > pGeode->PanelY ||
1494f29dbc25Smrg            gfx_is_panel_mode_supported(pGeode->PanelX,
1495f29dbc25Smrg                                        pGeode->PanelY,
1496f29dbc25Smrg                                        pMode->CrtcHDisplay,
1497f29dbc25Smrg                                        pMode->CrtcVDisplay,
1498f29dbc25Smrg                                        pScrni->bitsPerPixel) < 0) {
1499f29dbc25Smrg
1500f29dbc25Smrg            return MODE_BAD;
1501f29dbc25Smrg        }
1502f29dbc25Smrg    }
1503f29dbc25Smrg
1504f29dbc25Smrg    if (gfx_is_display_mode_supported(pMode->CrtcHDisplay,
1505f29dbc25Smrg                                      pMode->CrtcVDisplay,
1506f29dbc25Smrg                                      pScrni->bitsPerPixel,
1507f29dbc25Smrg                                      GeodeGetRefreshRate(pMode)) < 0) {
1508f29dbc25Smrg        return MODE_BAD;
1509f29dbc25Smrg    }
1510f29dbc25Smrg
1511f29dbc25Smrg    if (pMode->Flags & V_INTERLACE)
151204007ebaSmrg        return MODE_NO_INTERLACE;
1513f29dbc25Smrg
1514f29dbc25Smrg    if (pGeode->tryCompression)
151504007ebaSmrg        p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel);
1516f29dbc25Smrg    else
151704007ebaSmrg        p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
1518f29dbc25Smrg
1519f29dbc25Smrg    if (p * pMode->CrtcVDisplay > pGeode->FBAvail)
152004007ebaSmrg        return MODE_MEM;
1521f29dbc25Smrg
1522f29dbc25Smrg    return MODE_OK;
1523f29dbc25Smrg}
1524f29dbc25Smrg
1525f29dbc25Smrg/* XXX - Way more to do here */
1526f29dbc25Smrg
1527f29dbc25Smrgstatic Bool
152804007ebaSmrgGXEnterVT(VT_FUNC_ARGS_DECL)
1529f29dbc25Smrg{
153004007ebaSmrg    SCRN_INFO_PTR(arg);
153104007ebaSmrg    return GXEnterGraphics(NULL, pScrni);
1532f29dbc25Smrg}
1533f29dbc25Smrg
1534f29dbc25Smrgstatic void
153504007ebaSmrgGXLeaveVT(VT_FUNC_ARGS_DECL)
1536f29dbc25Smrg{
153704007ebaSmrg    SCRN_INFO_PTR(arg);
1538f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1539f29dbc25Smrg
1540f29dbc25Smrg    pGeode->PrevDisplayOffset = gfx_get_display_offset();
154104007ebaSmrg    GXLeaveGraphics(pScrni);
1542f29dbc25Smrg}
1543f29dbc25Smrg
1544f29dbc25Smrgvoid
1545f29dbc25SmrgGXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1546f29dbc25Smrg{
1547f29dbc25Smrg    pScrn->PreInit = GXPreInit;
1548f29dbc25Smrg    pScrn->ScreenInit = GXScreenInit;
1549f29dbc25Smrg    pScrn->SwitchMode = GXSwitchMode;
1550f29dbc25Smrg    pScrn->AdjustFrame = GXAdjustFrame;
1551f29dbc25Smrg    pScrn->EnterVT = GXEnterVT;
1552f29dbc25Smrg    pScrn->LeaveVT = GXLeaveVT;
1553f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1554f29dbc25Smrg    pScrn->ValidMode = GXValidMode;
1555f29dbc25Smrg}
1556f29dbc25Smrg
1557f29dbc25Smrg/* ====== Common functions ======
1558f29dbc25Smrg * These are all the common functions that we use for both GX and LX - They live here
1559f29dbc25Smrg * because most of them came along for the GX first, and then were adapted to the LX.
1560f29dbc25Smrg *  We could move these to a common function, but there is no hurry
1561f29dbc25Smrg * ============================== */
1562f29dbc25Smrg
1563f29dbc25Smrgvoid
156404007ebaSmrgGeodePointerMoved(POINTER_MOVED_ARGS_DECL)
1565f29dbc25Smrg{
156604007ebaSmrg    SCRN_INFO_PTR(arg);
1567f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1568f29dbc25Smrg
1569f29dbc25Smrg    int newX = x, newY = y;
1570f29dbc25Smrg
1571f29dbc25Smrg    switch (pGeode->rotation) {
1572f29dbc25Smrg    case RR_Rotate_0:
157304007ebaSmrg        break;
1574f29dbc25Smrg    case RR_Rotate_90:
157504007ebaSmrg        newX = y;
157604007ebaSmrg        newY = pScrni->pScreen->width - x - 1;
157704007ebaSmrg        break;
1578f29dbc25Smrg    case RR_Rotate_180:
157904007ebaSmrg        newX = pScrni->pScreen->width - x - 1;
158004007ebaSmrg        newY = pScrni->pScreen->height - y - 1;
158104007ebaSmrg        break;
1582f29dbc25Smrg    case RR_Rotate_270:
158304007ebaSmrg        newX = pScrni->pScreen->height - y - 1;
158404007ebaSmrg        newY = x;
158504007ebaSmrg        break;
1586f29dbc25Smrg    }
1587f29dbc25Smrg
158804007ebaSmrg    (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY));
1589f29dbc25Smrg}
1590f29dbc25Smrg
1591f29dbc25Smrgint
1592f29dbc25SmrgGeodeGetFPGeometry(const char *str, int *width, int *height)
1593f29dbc25Smrg{
1594f29dbc25Smrg
1595f29dbc25Smrg    int ret = sscanf(str, "%dx%d", width, height);
1596f29dbc25Smrg
1597f29dbc25Smrg    return (ret == 2) ? 0 : 1;
1598f29dbc25Smrg}
1599f29dbc25Smrg
1600f29dbc25Smrgstatic void
1601f29dbc25SmrgGeodeFreeRec(ScrnInfoPtr pScrni)
1602f29dbc25Smrg{
1603f29dbc25Smrg    if (pScrni->driverPrivate != NULL) {
160404007ebaSmrg        free(pScrni->driverPrivate);
160504007ebaSmrg        pScrni->driverPrivate = NULL;
1606f29dbc25Smrg    }
1607f29dbc25Smrg}
1608f29dbc25Smrg
1609f29dbc25Smrgvoid
161004007ebaSmrgGeodeFreeScreen(FREE_SCREEN_ARGS_DECL)
1611f29dbc25Smrg{
161204007ebaSmrg    SCRN_INFO_PTR(arg);
161304007ebaSmrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1614f29dbc25Smrg
1615f29dbc25Smrg    if (pGeode == NULL)
161604007ebaSmrg        return;
1617f29dbc25Smrg
1618f29dbc25Smrg    if (pGeode->useVGA) {
161904007ebaSmrg        if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
162004007ebaSmrg            vgaHWFreeHWRec(pScrni);
1621f29dbc25Smrg    }
1622f29dbc25Smrg
162304007ebaSmrg    GeodeFreeRec(pScrni);
1624f29dbc25Smrg}
1625f29dbc25Smrg
1626f29dbc25Smrgint
1627f29dbc25SmrgGeodeCalculatePitchBytes(unsigned int width, unsigned int bpp)
1628f29dbc25Smrg{
1629f29dbc25Smrg
1630f29dbc25Smrg    int delta = width * (bpp >> 3);
1631f29dbc25Smrg
1632f29dbc25Smrg    /* Less then 640 has doubling enabled */
1633f29dbc25Smrg
1634f29dbc25Smrg    if (width < 640)
163504007ebaSmrg        delta <<= 1;
1636f29dbc25Smrg
1637f29dbc25Smrg    /* Calculate the pitch (compression rquires a power of 2) */
1638f29dbc25Smrg
1639f29dbc25Smrg    if (delta > 4096)
164004007ebaSmrg        delta = 8192;
1641f29dbc25Smrg    else if (delta > 2048)
164204007ebaSmrg        delta = 4096;
1643f29dbc25Smrg    else if (delta > 1024)
164404007ebaSmrg        delta = 2048;
1645f29dbc25Smrg    else
164604007ebaSmrg        delta = 1024;
1647f29dbc25Smrg
1648f29dbc25Smrg    return delta;
1649f29dbc25Smrg}
1650