lx_driver.c revision 3406bd8e
1f29dbc25Smrg/* Copyright (c) 2003-2008 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>
35f29dbc25Smrg#include <string.h>
367f419768Smrg#include <fcntl.h>
377f419768Smrg#include <unistd.h>
387f419768Smrg#include <sys/mman.h>
39f29dbc25Smrg
403406bd8eSmrg#include "xorg-server.h"
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 "xf86i2c.h"
47f29dbc25Smrg#include "xf86Crtc.h"
48f29dbc25Smrg#include "xf86cmap.h"
49f29dbc25Smrg#include "compiler.h"
50f29dbc25Smrg#include "mipointer.h"
51f29dbc25Smrg#include "fb.h"
52f29dbc25Smrg#include "miscstruct.h"
53f29dbc25Smrg#include "micmap.h"
54f29dbc25Smrg#include "vbe.h"
55f29dbc25Smrg#include "fb.h"
56f29dbc25Smrg#include "cim_defs.h"
57f29dbc25Smrg#include "cim_regs.h"
58f29dbc25Smrg#include "geode.h"
59f29dbc25Smrg
60f29dbc25Smrg/* Bring in VGA functions */
61f29dbc25Smrg#include "lx_vga.c"
62f29dbc25Smrg
63f29dbc25Smrg#define LX_MAX_WIDTH  1940
64f29dbc25Smrg#define LX_MAX_HEIGHT 1600
65f29dbc25Smrg
66f29dbc25Smrg/* Size of the register blocks */
67f29dbc25Smrg
68f29dbc25Smrg#define LX_GP_REG_SIZE  0x4000
69f29dbc25Smrg#define LX_VG_REG_SIZE  0x4000
70f29dbc25Smrg#define LX_VID_REG_SIZE 0x4000
71f29dbc25Smrg#define LX_VIP_REG_SIZE 0x4000
72f29dbc25Smrg
73f29dbc25Smrg/* Size of the Cimarron command buffer */
74f29dbc25Smrg#define CIM_CMD_BFR_SZ 0x200000
75f29dbc25Smrg
76f29dbc25Smrgextern OptionInfoRec LX_GeodeOptions[];
77f29dbc25Smrg
78f29dbc25Smrgunsigned char *XpressROMPtr;
79f29dbc25Smrg
80f29dbc25Smrgstatic Bool
81f29dbc25SmrgLXSaveScreen(ScreenPtr pScrn, int mode)
82f29dbc25Smrg{
8304007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
84f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
85f29dbc25Smrg
86f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
8704007ebaSmrg        return vgaHWSaveScreen(pScrn, mode);
88f29dbc25Smrg
89f29dbc25Smrg    return TRUE;
90f29dbc25Smrg}
91f29dbc25Smrg
92f29dbc25Smrg/* This is an overly complex MSR read mechanism */
93f29dbc25Smrg
94f29dbc25Smrg/* From Cimarron - the VSAII read/write methods - we use these as fallback */
95f29dbc25Smrg
96f29dbc25Smrg#define LX_MSR_READ(adr,lo,hi)              \
97f29dbc25Smrg     __asm__ __volatile__(                      \
98f29dbc25Smrg        " mov $0x0AC1C, %%edx\n"                \
99f29dbc25Smrg        " mov $0xFC530007, %%eax\n"             \
100f29dbc25Smrg        " out %%eax,%%dx\n"                     \
101f29dbc25Smrg        " add $2,%%dl\n"                        \
102f29dbc25Smrg        " in %%dx, %%ax"                        \
103f29dbc25Smrg        : "=a" (lo), "=d" (hi)                  \
104f29dbc25Smrg        : "c" (adr))
105f29dbc25Smrg
106f29dbc25Smrg#define LX_MSR_WRITE(adr,low,high) \
107f29dbc25Smrg  { int d0, d1, d2, d3, d4;        \
108f29dbc25Smrg  __asm__ __volatile__(            \
109f29dbc25Smrg    " push %%ebx\n"                \
110f29dbc25Smrg    " mov $0x0AC1C, %%edx\n"       \
111f29dbc25Smrg    " mov $0xFC530007, %%eax\n"    \
112f29dbc25Smrg    " out %%eax,%%dx\n"            \
113f29dbc25Smrg    " add $2,%%dl\n"               \
114f29dbc25Smrg    " mov %6, %%ebx\n"             \
115f29dbc25Smrg    " mov %7, %0\n"                \
116f29dbc25Smrg    " mov %5, %3\n"                \
117f29dbc25Smrg    " xor %2, %2\n"                \
118f29dbc25Smrg    " xor %1, %1\n"                \
119f29dbc25Smrg    " out %%ax, %%dx\n"            \
120f29dbc25Smrg    " pop %%ebx\n"                 \
121f29dbc25Smrg    : "=a"(d0),"=&D"(d1),"=&S"(d2), \
122f29dbc25Smrg      "=c"(d3),"=d"(d4)  \
123f29dbc25Smrg    : "1"(adr),"2"(high),"3"(low)); \
124f29dbc25Smrg  }
125f29dbc25Smrg
126f29dbc25Smrgstatic void
127f29dbc25SmrgLXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi)
128f29dbc25Smrg{
129f29dbc25Smrg    if (GeodeReadMSR(addr, lo, hi) == -1) {
13004007ebaSmrg        unsigned int l, h;
131f29dbc25Smrg
13204007ebaSmrg        LX_MSR_READ(addr, l, h);
13304007ebaSmrg        *lo = l;
13404007ebaSmrg        *hi = h;
135f29dbc25Smrg    }
136f29dbc25Smrg}
137f29dbc25Smrg
138f29dbc25Smrgstatic void
139f29dbc25SmrgLXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi)
140f29dbc25Smrg{
141f29dbc25Smrg    if (GeodeWriteMSR(addr, lo, hi) == -1)
14204007ebaSmrg        LX_MSR_WRITE(addr, lo, hi);
143f29dbc25Smrg}
144f29dbc25Smrg
145f29dbc25Smrgstatic unsigned int
146f29dbc25SmrgLXCalcPitch(ScrnInfoPtr pScrni)
147f29dbc25Smrg{
148f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
149f29dbc25Smrg
150f29dbc25Smrg    if (pGeode->tryCompression)
15104007ebaSmrg        return GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
152f29dbc25Smrg    else
15304007ebaSmrg        return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
154f29dbc25Smrg}
155f29dbc25Smrg
156f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
157f29dbc25Smrgstatic inline void *
158f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
15904007ebaSmrg            struct pci_device *dev, int bar, int size)
160f29dbc25Smrg{
161f29dbc25Smrg    void *ptr;
162f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
163f29dbc25Smrg
164f29dbc25Smrg    int err = pci_device_map_range(dev,
16504007ebaSmrg                                   dev->regions[bar].base_addr,
16604007ebaSmrg                                   map_size,
16704007ebaSmrg                                   PCI_DEV_MAP_FLAG_WRITABLE |
16804007ebaSmrg                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
1697f419768Smrg                                   &ptr);
170f29dbc25Smrg
171f29dbc25Smrg    if (err)
17204007ebaSmrg        return NULL;
173f29dbc25Smrg    return ptr;
174f29dbc25Smrg}
175f29dbc25Smrg
176f29dbc25Smrgstatic inline int
177f29dbc25Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
178f29dbc25Smrg{
179f29dbc25Smrg    return pci_device_unmap_range(dev, ptr, size);
180f29dbc25Smrg}
181f29dbc25Smrg
182f29dbc25Smrg#endif
183f29dbc25Smrg
184f29dbc25Smrgstatic Bool
185f29dbc25SmrgLXMapMem(ScrnInfoPtr pScrni)
186f29dbc25Smrg{
187f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
188f29dbc25Smrg    int index = pScrni->scrnIndex;
189f29dbc25Smrg    unsigned long cmd_bfr_phys;
190f29dbc25Smrg
191f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
192f29dbc25Smrg
193f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
194f29dbc25Smrg    PCITAG tag;
195f29dbc25Smrg
196f29dbc25Smrg    tag = pciTag(pci->bus, pci->device, pci->func);
197f29dbc25Smrg
19804007ebaSmrg    cim_gp_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
19904007ebaSmrg                                                 tag, pci->memBase[1],
20004007ebaSmrg                                                 LX_GP_REG_SIZE);
201f29dbc25Smrg
20204007ebaSmrg    cim_vg_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
20304007ebaSmrg                                                 tag, pci->memBase[2],
20404007ebaSmrg                                                 LX_VG_REG_SIZE);
205f29dbc25Smrg
20604007ebaSmrg    cim_vid_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
20704007ebaSmrg                                                  tag, pci->memBase[3],
20804007ebaSmrg                                                  LX_VID_REG_SIZE);
209f29dbc25Smrg
21004007ebaSmrg    cim_vip_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
21104007ebaSmrg                                                  tag, pci->memBase[4],
21204007ebaSmrg                                                  LX_VIP_REG_SIZE);
213f29dbc25Smrg
21404007ebaSmrg    cim_fb_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_FRAMEBUFFER,
21504007ebaSmrg                                                 tag, pci->memBase[0],
21604007ebaSmrg                                                 pGeode->FBAvail +
21704007ebaSmrg                                                 CIM_CMD_BFR_SZ);
218f29dbc25Smrg#else
219f29dbc25Smrg    cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE);
220f29dbc25Smrg    cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE);
221f29dbc25Smrg    cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE);
222f29dbc25Smrg    cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE);
223f29dbc25Smrg    cim_fb_ptr =
22404007ebaSmrg        map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ);
225f29dbc25Smrg#endif
226f29dbc25Smrg
227f29dbc25Smrg    if (pScrni->memPhysBase == 0)
22804007ebaSmrg        pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM);
229f29dbc25Smrg
230f29dbc25Smrg    cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset;
231f29dbc25Smrg    cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset;
232f29dbc25Smrg
233f29dbc25Smrg    if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr ||
23404007ebaSmrg        !cim_vip_ptr)
23504007ebaSmrg        return FALSE;
236f29dbc25Smrg
237f29dbc25Smrg    gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM),
23804007ebaSmrg                             pGeode->FBAvail);
239f29dbc25Smrg    gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize);
240f29dbc25Smrg
2417f419768Smrg#ifndef XSERVER_LIBPCIACCESS
242f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
2437f419768Smrg#else
2447f419768Smrg    {
2457f419768Smrg        int fd = open("/dev/mem", O_RDWR);
2467f419768Smrg        if (fd < 0) {
2477f419768Smrg            xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n");
2487f419768Smrg            return FALSE;
2497f419768Smrg        }
2507f419768Smrg        XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000);
2517f419768Smrg        close(fd);
2527f419768Smrg    }
2537f419768Smrg#endif
254f29dbc25Smrg
255f29dbc25Smrg    pGeode->FBBase = cim_fb_ptr;
256f29dbc25Smrg
257f29dbc25Smrg    if (!pGeode->NoAccel)
25804007ebaSmrg        pGeode->pExa->memoryBase = pGeode->FBBase;
259f29dbc25Smrg
260f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n",
26104007ebaSmrg               pGeode->FBAvail, pGeode->FBBase);
262f29dbc25Smrg
263f29dbc25Smrg    return TRUE;
264f29dbc25Smrg}
265f29dbc25Smrg
266f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
267f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
268f29dbc25Smrg*/
269f29dbc25Smrg
270f29dbc25Smrgstatic Bool
2717f419768SmrgLXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt)
272f29dbc25Smrg{
2737f419768Smrg#ifndef XSERVER_LIBPCIACCESS
274f29dbc25Smrg    unsigned char *ptr;
275f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
276f29dbc25Smrg    int ret;
277f29dbc25Smrg
278f29dbc25Smrg    ptr =
27904007ebaSmrg        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
28004007ebaSmrg                      strlen(vgasig));
281f29dbc25Smrg
282f29dbc25Smrg    if (ptr == NULL)
28304007ebaSmrg        return FALSE;
284f29dbc25Smrg
285f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
286f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
287f29dbc25Smrg
288f29dbc25Smrg    return ret ? FALSE : TRUE;
2897f419768Smrg#else
2907f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index);
2917f419768Smrg
2927f419768Smrg    return pci_device_is_boot_vga(pci);
2937f419768Smrg#endif
294f29dbc25Smrg}
295f29dbc25Smrg
296f29dbc25Smrgstatic Bool
297f29dbc25SmrgLXCrtcResize(ScrnInfoPtr pScrni, int width, int height)
298f29dbc25Smrg{
299f29dbc25Smrg    return TRUE;
300f29dbc25Smrg}
301f29dbc25Smrg
302f29dbc25Smrgstatic const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = {
303f29dbc25Smrg    LXCrtcResize,
304f29dbc25Smrg};
305f29dbc25Smrg
306f29dbc25Smrgstatic Bool
307f29dbc25SmrgLXPreInit(ScrnInfoPtr pScrni, int flags)
308f29dbc25Smrg{
309f29dbc25Smrg    GeodePtr pGeode;
310f29dbc25Smrg    EntityInfoPtr pEnt;
311f29dbc25Smrg    OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0];
312f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
3133406bd8eSmrg    const char *s;
314f29dbc25Smrg
315f29dbc25Smrg    if (pScrni->numEntities != 1)
31604007ebaSmrg        return FALSE;
317f29dbc25Smrg
318f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
319f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
320f29dbc25Smrg    if (pEnt->resources)
32104007ebaSmrg        return FALSE;
322f29dbc25Smrg#endif
323f29dbc25Smrg    if (flags & PROBE_DETECT) {
32404007ebaSmrg        GeodeProbeDDC(pScrni, pEnt->index);
32504007ebaSmrg        return TRUE;
326f29dbc25Smrg    }
327f29dbc25Smrg
32804007ebaSmrg    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
329f29dbc25Smrg
330f29dbc25Smrg    if (pGeode == NULL)
33104007ebaSmrg        return FALSE;
332f29dbc25Smrg
3337f419768Smrg    pGeode->useVGA = LXCheckVGA(pScrni, pEnt);
334f29dbc25Smrg    pGeode->VGAActive = FALSE;
335f29dbc25Smrg    pGeode->pEnt = pEnt;
336f29dbc25Smrg
337f29dbc25Smrg    if (pGeode->useVGA) {
33804007ebaSmrg        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
33904007ebaSmrg            pGeode->useVGA = FALSE;
34004007ebaSmrg        else
34104007ebaSmrg            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
342f29dbc25Smrg
34304007ebaSmrg        pGeode->vesa = calloc(1, sizeof(VESARec));
344f29dbc25Smrg    }
345f29dbc25Smrg
346f29dbc25Smrg    cim_rdmsr = LXReadMSR;
347f29dbc25Smrg    cim_wrmsr = LXWriteMSR;
348f29dbc25Smrg
349f29dbc25Smrg    /* Set up the Cimarron MSR tables */
350f29dbc25Smrg    msr_init_table();
351f29dbc25Smrg
352f29dbc25Smrg    /* By default, we support panel and CRT - the config file should
353f29dbc25Smrg     * disable the ones we don't want
354f29dbc25Smrg     */
355f29dbc25Smrg
356f29dbc25Smrg    pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT;
357f29dbc25Smrg
358f29dbc25Smrg    /* Fill in the monitor information */
359f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
360f29dbc25Smrg
361f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
36204007ebaSmrg        return FALSE;
363f29dbc25Smrg
364f29dbc25Smrg    switch (pScrni->depth) {
365f29dbc25Smrg    case 8:
36604007ebaSmrg        pScrni->rgbBits = 8;
367f29dbc25Smrg    case 16:
368f29dbc25Smrg    case 24:
369f29dbc25Smrg    case 32:
37004007ebaSmrg        break;
371f29dbc25Smrg    default:
37204007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
37304007ebaSmrg                   "The driver does not support %d as a depth.\n",
37404007ebaSmrg                   pScrni->depth);
37504007ebaSmrg        return FALSE;
376f29dbc25Smrg    }
377f29dbc25Smrg
378f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
379f29dbc25Smrg
380f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
38104007ebaSmrg        return FALSE;
382f29dbc25Smrg
383f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
38404007ebaSmrg        return FALSE;
385f29dbc25Smrg
386f29dbc25Smrg    /*
387f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
388f29dbc25Smrg     * here.
389f29dbc25Smrg     */
390f29dbc25Smrg    {
39104007ebaSmrg        Gamma zeros = { 0.0, 0.0, 0.0 };
392f29dbc25Smrg
39304007ebaSmrg        if (!xf86SetGamma(pScrni, zeros)) {
39404007ebaSmrg            return FALSE;
39504007ebaSmrg        }
396f29dbc25Smrg    }
397f29dbc25Smrg
398f29dbc25Smrg    pScrni->progClock = TRUE;
399f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
400f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
401f29dbc25Smrg
402f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
403f29dbc25Smrg
404f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
405f29dbc25Smrg    pGeode->tryCompression = TRUE;
406f29dbc25Smrg
407f29dbc25Smrg    /* Protect against old versions of EXA */
408f29dbc25Smrg
409f29dbc25Smrg#if (EXA_VERSION_MAJOR < 2)
410f29dbc25Smrg    pGeode->NoAccel = TRUE;
411f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41204007ebaSmrg               "*** This driver was compiled with EXA version %d\n");
413f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41404007ebaSmrg               "*** we need version 2 or greater\n");
415f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41604007ebaSmrg               "*** All accelerations are being turned off.\n");
417f29dbc25Smrg#else
418f29dbc25Smrg    pGeode->NoAccel = FALSE;
419f29dbc25Smrg#endif
420f29dbc25Smrg
421f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
422f29dbc25Smrg
42304007ebaSmrg    xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
424f29dbc25Smrg
425f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE,
42604007ebaSmrg                              (int *) &(pGeode->FBAvail)))
42704007ebaSmrg        pGeode->FBAvail = 0;
428f29dbc25Smrg
429f29dbc25Smrg    /* For compatability - allow SWCursor too */
430f29dbc25Smrg
431f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE))
43204007ebaSmrg        pGeode->tryHWCursor = FALSE;
433f29dbc25Smrg
434f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE))
43504007ebaSmrg        pGeode->tryCompression = FALSE;
436f29dbc25Smrg
437f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE))
43804007ebaSmrg        pGeode->NoAccel = TRUE;
439f29dbc25Smrg
440f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
441f29dbc25Smrg
442f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) {
443f29dbc25Smrg
44404007ebaSmrg        if (!xf86NameCmp(s, "LEFT"))
44504007ebaSmrg            pGeode->rotation = RR_Rotate_90;
44604007ebaSmrg        else if (!xf86NameCmp(s, "INVERT"))
44704007ebaSmrg            pGeode->rotation = RR_Rotate_180;
44804007ebaSmrg        else if (!xf86NameCmp(s, "CCW"))
44904007ebaSmrg            pGeode->rotation = RR_Rotate_270;
45004007ebaSmrg        else
45104007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
452f29dbc25Smrg    }
453f29dbc25Smrg
454f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ,
45504007ebaSmrg                         (int *) &(pGeode->exaBfrSz));
456f29dbc25Smrg
457f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
45804007ebaSmrg        pGeode->exaBfrSz = 0;
459f29dbc25Smrg
460f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL) {
46104007ebaSmrg        if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE))
46204007ebaSmrg            pGeode->Output &= ~OUTPUT_PANEL;
463f29dbc25Smrg    }
464f29dbc25Smrg
465f29dbc25Smrg    /* Panel detection code -
466f29dbc25Smrg     * 1.  See if an OLPC DCON is attached - we can make some assumptions
467f29dbc25Smrg     * about the panel if so.
468f29dbc25Smrg     * 2.  Use panel mode specified in the config
469f29dbc25Smrg     * 3.  "Autodetect" the panel through VSA
470f29dbc25Smrg     */
471f29dbc25Smrg
472f29dbc25Smrg    if (dcon_init(pScrni)) {
47304007ebaSmrg        pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON;
47404007ebaSmrg    }
47504007ebaSmrg    else if (pGeode->Output & OUTPUT_PANEL) {
47604007ebaSmrg        char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE);
477f29dbc25Smrg
47804007ebaSmrg        if (pmode != NULL)
47904007ebaSmrg            pGeode->panelMode = LXGetManualPanelMode(pmode);
480f29dbc25Smrg
48104007ebaSmrg        if (pGeode->panelMode == NULL)
48204007ebaSmrg            pGeode->panelMode = LXGetLegacyPanelMode(pScrni);
483f29dbc25Smrg
48404007ebaSmrg        if (pGeode->panelMode == NULL)
48504007ebaSmrg            pGeode->Output &= ~OUTPUT_PANEL;
486f29dbc25Smrg    }
487f29dbc25Smrg
488f29dbc25Smrg    /* Default to turn scaling on for panels */
489f29dbc25Smrg
490f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL)
49104007ebaSmrg        pGeode->Scale = TRUE;
492f29dbc25Smrg
493f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n");
494f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n",
49504007ebaSmrg               pGeode->Output & OUTPUT_CRT ? "YES" : "NO");
496f29dbc25Smrg
497f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n",
49804007ebaSmrg               pGeode->Output & OUTPUT_PANEL ? "YES" : "NO");
499f29dbc25Smrg
500f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n",
50104007ebaSmrg               pGeode->Output & OUTPUT_DCON ? "YES" : "NO");
502f29dbc25Smrg
503f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n",
50404007ebaSmrg               pGeode->useVGA ? "YES" : "NO");
505f29dbc25Smrg
506f29dbc25Smrg    /* Set up VGA */
507f29dbc25Smrg
508f29dbc25Smrg    if (pGeode->useVGA) {
50904007ebaSmrg        VESARec *pVesa;
510f29dbc25Smrg
51104007ebaSmrg        if (!xf86LoadSubModule(pScrni, "int10"))
51204007ebaSmrg            return FALSE;
513f29dbc25Smrg
51404007ebaSmrg        pVesa = pGeode->vesa;
515f29dbc25Smrg
51604007ebaSmrg        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
51704007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
51804007ebaSmrg                       "Unable to initialize 1NT10 support\n");
51904007ebaSmrg            pGeode->useVGA = FALSE;
52004007ebaSmrg        }
521f29dbc25Smrg    }
522f29dbc25Smrg
523f29dbc25Smrg    /* Read the amount of framebuffer memory */
524f29dbc25Smrg    /* First try to read it from the framebuffer, and if that fails,
525f29dbc25Smrg     * do it the legacy way
526f29dbc25Smrg     */
527f29dbc25Smrg
528f29dbc25Smrg    if (pGeode->FBAvail == 0) {
52904007ebaSmrg        if (GeodeGetSizeFromFB(&pGeode->FBAvail)) {
53004007ebaSmrg            unsigned long value;
531f29dbc25Smrg
53204007ebaSmrg            cim_outw(0xAC1C, 0xFC53);
53304007ebaSmrg            cim_outw(0xAC1C, 0x0200);
534f29dbc25Smrg
53504007ebaSmrg            value = (unsigned long) (cim_inw(0xAC1E)) & 0xFE;
53604007ebaSmrg            pGeode->FBAvail = value << 20;
53704007ebaSmrg        }
538f29dbc25Smrg    }
539f29dbc25Smrg
540f29dbc25Smrg    pScrni->fbOffset = 0;
541f29dbc25Smrg
542f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
54304007ebaSmrg        pScrni->videoRam = pGeode->FBAvail / 1024;
544f29dbc25Smrg    else {
54504007ebaSmrg        pScrni->videoRam = pGeode->pEnt->device->videoRam;
54604007ebaSmrg        pGeode->FBAvail = pScrni->videoRam << 10;
547f29dbc25Smrg    }
548f29dbc25Smrg
549f29dbc25Smrg    /* If we have <= 16Mb of memory then compression is going
550f29dbc25Smrg       to hurt - so warn and disable */
551f29dbc25Smrg
55204007ebaSmrg    if (pGeode->tryCompression && pGeode->FBAvail <= 0x1000000) {
55304007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
55404007ebaSmrg                   "%x bytes of video memory is less then optimal\n",
55504007ebaSmrg                   pGeode->FBAvail);
55604007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
55704007ebaSmrg                   "when compression is on. Disabling compression.\n");
55804007ebaSmrg        pGeode->tryCompression = FALSE;
559f29dbc25Smrg    }
560f29dbc25Smrg
561f29dbc25Smrg    /* Carve out some memory for the command buffer */
562f29dbc25Smrg
563f29dbc25Smrg    pGeode->CmdBfrSize = CIM_CMD_BFR_SZ;
564f29dbc25Smrg    pGeode->FBAvail -= CIM_CMD_BFR_SZ;
565f29dbc25Smrg
566f29dbc25Smrg    pGeode->CmdBfrOffset = pGeode->FBAvail;
567f29dbc25Smrg
568f29dbc25Smrg    /* Allocate a a CRTC config structure */
569f29dbc25Smrg    xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs);
570f29dbc25Smrg
571f29dbc25Smrg    /* Set up the GPU CRTC */
572f29dbc25Smrg    LXSetupCrtc(pScrni);
573f29dbc25Smrg
574f29dbc25Smrg    xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT);
575f29dbc25Smrg
576f29dbc25Smrg    /* Setup the output */
577f29dbc25Smrg    LXSetupOutput(pScrni);
578f29dbc25Smrg
579f29dbc25Smrg    if (!xf86InitialConfiguration(pScrni, FALSE)) {
58004007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n");
58104007ebaSmrg        return FALSE;
582f29dbc25Smrg    }
583f29dbc25Smrg
584f29dbc25Smrg    xf86PrintModes(pScrni);
585f29dbc25Smrg
586f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
587f29dbc25Smrg
588f29dbc25Smrg    pGeode->Pitch = LXCalcPitch(pScrni);
589f29dbc25Smrg
590f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
591f29dbc25Smrg
592f29dbc25Smrg    /* Load the modules we'll need */
593f29dbc25Smrg
594f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
59504007ebaSmrg        return FALSE;
596f29dbc25Smrg    }
597f29dbc25Smrg
598f29dbc25Smrg    if (!pGeode->NoAccel) {
59904007ebaSmrg        if (!xf86LoadSubModule(pScrni, "exa"))
60004007ebaSmrg            return FALSE;
601f29dbc25Smrg    }
602f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
603f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
60404007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
60504007ebaSmrg                   "Couldn't register the resources.\n");
60604007ebaSmrg        return FALSE;
607f29dbc25Smrg    }
608f29dbc25Smrg#endif
609f29dbc25Smrg    return TRUE;
610f29dbc25Smrg}
611f29dbc25Smrg
612f29dbc25Smrgstatic void
613f29dbc25SmrgLXRestore(ScrnInfoPtr pScrni)
614f29dbc25Smrg{
615f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
616f29dbc25Smrg
617f29dbc25Smrg    if (pGeode->useVGA) {
61804007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
619f29dbc25Smrg
62004007ebaSmrg        vgaHWProtect(pScrni, TRUE);
62104007ebaSmrg        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
62204007ebaSmrg        vgaHWProtect(pScrni, FALSE);
623f29dbc25Smrg    }
624f29dbc25Smrg}
625f29dbc25Smrg
626f29dbc25Smrgstatic Bool
627f29dbc25SmrgLXUnmapMem(ScrnInfoPtr pScrni)
628f29dbc25Smrg{
629f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
630f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE);
631f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE);
63204007ebaSmrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE);
63304007ebaSmrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE);
6347f419768Smrg
6357f419768Smrg    xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000);
636f29dbc25Smrg#else
637f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
638f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
639f29dbc25Smrg
640f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE);
641f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE);
642f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE);
643f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE);
644f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ);
645f29dbc25Smrg
6467f419768Smrg    munmap(XpressROMPtr, 0x10000);
6477f419768Smrg#endif
648f29dbc25Smrg
649f29dbc25Smrg    return TRUE;
650f29dbc25Smrg}
651f29dbc25Smrg
652f29dbc25Smrg/* These should be correctly accounted for rotation */
653f29dbc25Smrg
654f29dbc25Smrgvoid
65504007ebaSmrgLXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
656f29dbc25Smrg{
65704007ebaSmrg    SCRN_INFO_PTR(arg);
658f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
659f29dbc25Smrg
660f29dbc25Smrg    unsigned long offset;
661f29dbc25Smrg
662f29dbc25Smrg    offset = (y * pGeode->Pitch);
663f29dbc25Smrg    offset += x * (pScrni->bitsPerPixel >> 3);
664f29dbc25Smrg
665f29dbc25Smrg    vg_set_display_offset(offset);
666f29dbc25Smrg}
667f29dbc25Smrg
668f29dbc25Smrgstatic Bool
66904007ebaSmrgLXSwitchMode(SWITCH_MODE_ARGS_DECL)
670f29dbc25Smrg{
67104007ebaSmrg    SCRN_INFO_PTR(arg);
672f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
673f29dbc25Smrg
674f29dbc25Smrg    /* Set the new mode */
675f29dbc25Smrg    return xf86SetSingleMode(pScrni, pMode, pGeode->rotation);
676f29dbc25Smrg}
677f29dbc25Smrg
678f29dbc25Smrgstatic void
679f29dbc25SmrgLXLeaveGraphics(ScrnInfoPtr pScrni)
680f29dbc25Smrg{
681f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
682f29dbc25Smrg    VG_PANNING_COORDINATES panning;
683f29dbc25Smrg
684f29dbc25Smrg    gp_wait_until_idle();
685f29dbc25Smrg
686f29dbc25Smrg    vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode),
68704007ebaSmrg                       pGeode->FBcimdisplaytiming.wBpp);
688f29dbc25Smrg
689f29dbc25Smrg    vg_set_compression_enable(0);
690f29dbc25Smrg
691f29dbc25Smrg    /* Restore the previous Compression state */
692f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
69304007ebaSmrg        vg_configure_compression(&(pGeode->FBCBData));
69404007ebaSmrg        vg_set_compression_enable(1);
695f29dbc25Smrg    }
696f29dbc25Smrg
697f29dbc25Smrg    vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch);
698f29dbc25Smrg    vg_set_display_offset(pGeode->FBDisplayOffset);
699f29dbc25Smrg
700f29dbc25Smrg    /* Restore Cursor */
701f29dbc25Smrg    vg_set_cursor_position(pGeode->FBCursor.cursor_x,
70204007ebaSmrg                           pGeode->FBCursor.cursor_y, &panning);
703f29dbc25Smrg
704f29dbc25Smrg    LXRestore(pScrni);
705f29dbc25Smrg
706f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
70704007ebaSmrg        pGeode->vesa->pInt->num = 0x10;
70804007ebaSmrg        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
70904007ebaSmrg        pGeode->vesa->pInt->bx = 0;
71004007ebaSmrg        xf86ExecX86int10(pGeode->vesa->pInt);
71104007ebaSmrg        vg_delay_milliseconds(3);
712f29dbc25Smrg    }
713f29dbc25Smrg
714f29dbc25Smrg    pScrni->vtSema = FALSE;
715f29dbc25Smrg}
716f29dbc25Smrg
717f29dbc25Smrgstatic Bool
71804007ebaSmrgLXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
719f29dbc25Smrg{
72004007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
721f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
722f29dbc25Smrg
723f29dbc25Smrg    if (pScrni->vtSema)
72404007ebaSmrg        LXLeaveGraphics(pScrni);
725f29dbc25Smrg
726f29dbc25Smrg    if (pGeode->pExa) {
72704007ebaSmrg        exaDriverFini(pScrn);
72804007ebaSmrg        free(pGeode->pExa);
72904007ebaSmrg        pGeode->pExa = NULL;
730f29dbc25Smrg    }
731f29dbc25Smrg
732f29dbc25Smrg    /* Unmap the offscreen allocations */
733f29dbc25Smrg    GeodeCloseOffscreen(pScrni);
734f29dbc25Smrg
735f29dbc25Smrg    LXUnmapMem(pScrni);
736f29dbc25Smrg
737f29dbc25Smrg    if (pGeode->useVGA)
73804007ebaSmrg        vgaHWUnmapMem(pScrni);
739f29dbc25Smrg
740f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
741f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
742f29dbc25Smrg
743f29dbc25Smrg    if (pScrn->CloseScreen)
74404007ebaSmrg        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
745f29dbc25Smrg
746f29dbc25Smrg    return TRUE;
747f29dbc25Smrg}
748f29dbc25Smrg
749f29dbc25Smrgstatic Bool
750f29dbc25SmrgLXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
751f29dbc25Smrg{
752f29dbc25Smrg    int bpp;
753f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
754f29dbc25Smrg
755f29dbc25Smrg    pGeode->VGAActive = gu3_get_vga_active();
756f29dbc25Smrg
757f29dbc25Smrg    gp_wait_until_idle();
758f29dbc25Smrg
759f29dbc25Smrg    vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode,
76004007ebaSmrg                                &bpp);
761f29dbc25Smrg
762f29dbc25Smrg    pGeode->FBcimdisplaytiming.wBpp = bpp;
763f29dbc25Smrg    pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch();
764f29dbc25Smrg
765f29dbc25Smrg    pGeode->FBDisplayOffset = vg_get_display_offset();
766f29dbc25Smrg
767f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
76804007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
769f29dbc25Smrg
77004007ebaSmrg        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
771f29dbc25Smrg    }
772f29dbc25Smrg
773f29dbc25Smrg    pGeode->FBCompressionEnable = vg_get_compression_enable();
774f29dbc25Smrg    vg_get_compression_info(&(pGeode->FBCBData));
775f29dbc25Smrg
776f29dbc25Smrg    /* Save Cursor offset */
777f29dbc25Smrg    vg_get_cursor_info(&pGeode->FBCursor);
778f29dbc25Smrg
779f29dbc25Smrg    /* Turn off the VGA */
780f29dbc25Smrg
781f29dbc25Smrg    if (pGeode->useVGA) {
78204007ebaSmrg        unsigned short sequencer;
78304007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
784f29dbc25Smrg
78504007ebaSmrg        /* Unlock VGA registers */
78604007ebaSmrg        vgaHWUnlock(pvgaHW);
787f29dbc25Smrg
78804007ebaSmrg        /* Save the current state and setup the current mode */
78904007ebaSmrg        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
790f29dbc25Smrg
79104007ebaSmrg        /* DISABLE VGA SEQUENCER */
79204007ebaSmrg        /* This allows the VGA state machine to terminate. We must delay */
79304007ebaSmrg        /* such that there are no pending MBUS requests.  */
794f29dbc25Smrg
79504007ebaSmrg        cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE);
79604007ebaSmrg        sequencer = cim_inb(DC3_SEQUENCER_DATA);
79704007ebaSmrg        sequencer |= DC3_CLK_MODE_SCREEN_OFF;
79804007ebaSmrg        cim_outb(DC3_SEQUENCER_DATA, sequencer);
799f29dbc25Smrg
80004007ebaSmrg        vg_delay_milliseconds(1);
801f29dbc25Smrg
80204007ebaSmrg        /* BLANK THE VGA DISPLAY */
80304007ebaSmrg        cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET);
80404007ebaSmrg        sequencer = cim_inb(DC3_SEQUENCER_DATA);
80504007ebaSmrg        sequencer &= ~DC3_RESET_VGA_DISP_ENABLE;
80604007ebaSmrg        cim_outb(DC3_SEQUENCER_DATA, sequencer);
807f29dbc25Smrg
80804007ebaSmrg        vg_delay_milliseconds(1);
809f29dbc25Smrg    }
810f29dbc25Smrg
811f29dbc25Smrg    /* Clear the framebuffer */
812f29dbc25Smrg    memset(pGeode->FBBase, 0, pGeode->displaySize);
813f29dbc25Smrg
814f29dbc25Smrg    /* Set the modes */
815f29dbc25Smrg    if (!xf86SetDesiredModes(pScrni))
81604007ebaSmrg        return FALSE;
817f29dbc25Smrg
818f29dbc25Smrg    pScrni->vtSema = TRUE;
819f29dbc25Smrg
820f29dbc25Smrg    return TRUE;
821f29dbc25Smrg}
822f29dbc25Smrg
823f29dbc25Smrgstatic void
824f29dbc25SmrgLXLoadPalette(ScrnInfoPtr pScrni,
82504007ebaSmrg              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
826f29dbc25Smrg{
827f29dbc25Smrg    int i, index, color;
828f29dbc25Smrg
829f29dbc25Smrg    for (i = 0; i < numColors; i++) {
83004007ebaSmrg        index = indizes[i] & 0xFF;
83104007ebaSmrg        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
83204007ebaSmrg            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
83304007ebaSmrg            ((unsigned long) (colors[index].blue & 0xFF));
834f29dbc25Smrg
83504007ebaSmrg        vg_set_display_palette_entry(index, color);
836f29dbc25Smrg    }
837f29dbc25Smrg}
838f29dbc25Smrg
839f29dbc25Smrgstatic Bool
84004007ebaSmrgLXScreenInit(SCREEN_INIT_ARGS_DECL)
841f29dbc25Smrg{
84204007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
843f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
844f29dbc25Smrg    int ret;
845f29dbc25Smrg    unsigned int dwidth;
846f29dbc25Smrg
847f29dbc25Smrg    pGeode->starting = TRUE;
848f29dbc25Smrg
849f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
850f29dbc25Smrg
851f29dbc25Smrg    if (pGeode->useVGA) {
852f29dbc25Smrg
85304007ebaSmrg        if (!vgaHWMapMem(pScrni))
85404007ebaSmrg            return FALSE;
855f29dbc25Smrg
85604007ebaSmrg        vgaHWGetIOBase(VGAHWPTR(pScrni));
857f29dbc25Smrg    }
858f29dbc25Smrg
859f29dbc25Smrg    if (!pGeode->NoAccel) {
860f29dbc25Smrg
86104007ebaSmrg        pGeode->pExa = exaDriverAlloc();
862f29dbc25Smrg
86304007ebaSmrg        if (pGeode->pExa) {
864f29dbc25Smrg
86504007ebaSmrg            pGeode->pExa->memoryBase = 0;
86604007ebaSmrg            pGeode->pExa->memorySize = 0;
867f29dbc25Smrg
86804007ebaSmrg            pGeode->pExa->pixmapOffsetAlign = 32;
86904007ebaSmrg            pGeode->pExa->pixmapPitchAlign = 32;
87004007ebaSmrg            pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS;
87104007ebaSmrg            pGeode->pExa->maxX = LX_MAX_WIDTH - 1;
87204007ebaSmrg            pGeode->pExa->maxY = LX_MAX_HEIGHT - 1;
87304007ebaSmrg        }
87404007ebaSmrg        else {
87504007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
87604007ebaSmrg                       "Couldn't allocate the EXA structure.\n");
87704007ebaSmrg            pGeode->NoAccel = TRUE;
87804007ebaSmrg        }
879f29dbc25Smrg    }
880f29dbc25Smrg
881f29dbc25Smrg    /* Map the memory here before doing anything else */
882f29dbc25Smrg
883f29dbc25Smrg    if (!LXMapMem(pScrni))
88404007ebaSmrg        return FALSE;
885f29dbc25Smrg
886f29dbc25Smrg    LXInitOffscreen(pScrni);
887f29dbc25Smrg
888f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
889f29dbc25Smrg    if (!LXEnterGraphics(pScrn, pScrni))
89004007ebaSmrg        return FALSE;
891f29dbc25Smrg
892f29dbc25Smrg    miClearVisualTypes();
893f29dbc25Smrg
894f29dbc25Smrg    /* XXX Again - take down anything? */
895f29dbc25Smrg
896f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
89704007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
89804007ebaSmrg                              TrueColorMask, pScrni->rgbBits,
89904007ebaSmrg                              pScrni->defaultVisual)) {
90004007ebaSmrg            return FALSE;
90104007ebaSmrg        }
90204007ebaSmrg    }
90304007ebaSmrg    else {
90404007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
90504007ebaSmrg                              miGetDefaultVisualMask(pScrni->depth),
90604007ebaSmrg                              pScrni->rgbBits, pScrni->defaultVisual)) {
90704007ebaSmrg            return FALSE;
90804007ebaSmrg        }
909f29dbc25Smrg    }
910f29dbc25Smrg
911f29dbc25Smrg    miSetPixmapDepths();
912f29dbc25Smrg
913f29dbc25Smrg    if (pScrni->virtualX > pScrni->displayWidth)
91404007ebaSmrg        pScrni->displayWidth = pScrni->virtualX;
915f29dbc25Smrg
916f29dbc25Smrg    /* Point at the visible area to start */
917f29dbc25Smrg
918f29dbc25Smrg    /* fbScreenInit assumes that the stride is display width *
919f29dbc25Smrg     * bytes per pixel.  If compression is on, then our stride might
920f29dbc25Smrg     * be completely different, so we divide the pitch by the
921f29dbc25Smrg     * bytes per pixel to fake fbScreenInit into doing the right thing */
922f29dbc25Smrg
923f29dbc25Smrg    dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
924f29dbc25Smrg
925f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase,
92604007ebaSmrg                       pScrni->virtualX, pScrni->virtualY,
92704007ebaSmrg                       pScrni->xDpi, pScrni->yDpi, dwidth,
92804007ebaSmrg                       pScrni->bitsPerPixel);
929f29dbc25Smrg
930f29dbc25Smrg    if (!ret)
93104007ebaSmrg        return FALSE;
932f29dbc25Smrg
933f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
934f29dbc25Smrg
935f29dbc25Smrg    /* Set up the color ordering */
936f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
93704007ebaSmrg        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
93804007ebaSmrg
93904007ebaSmrg        while (--visual >= pScrn->visuals) {
94004007ebaSmrg            if ((visual->class | DynamicClass) == DirectColor) {
94104007ebaSmrg                visual->offsetRed = pScrni->offset.red;
94204007ebaSmrg                visual->offsetGreen = pScrni->offset.green;
94304007ebaSmrg                visual->offsetBlue = pScrni->offset.blue;
94404007ebaSmrg                visual->redMask = pScrni->mask.red;
94504007ebaSmrg                visual->greenMask = pScrni->mask.green;
94604007ebaSmrg                visual->blueMask = pScrni->mask.blue;
94704007ebaSmrg            }
94804007ebaSmrg        }
949f29dbc25Smrg    }
950f29dbc25Smrg
951f29dbc25Smrg    /* Must follow the color ordering */
952f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
953f29dbc25Smrg
954f29dbc25Smrg    if (!pGeode->NoAccel)
95504007ebaSmrg        pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE;
956f29dbc25Smrg
957f29dbc25Smrg    xf86SetBackingStore(pScrn);
958f29dbc25Smrg
959f29dbc25Smrg    /* Set up the soft cursor */
960f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
961f29dbc25Smrg
962f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
963f29dbc25Smrg
964f29dbc25Smrg    if (pGeode->tryHWCursor) {
96504007ebaSmrg        if (!LXCursorInit(pScrn))
96604007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
96704007ebaSmrg                       "Hardware cursor initialization failed.\n");
968f29dbc25Smrg    }
969f29dbc25Smrg
970f29dbc25Smrg    /* Set up the color map */
971f29dbc25Smrg
972f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
97304007ebaSmrg        return FALSE;
974f29dbc25Smrg
975f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
97604007ebaSmrg        /* Must follow initialization of the default colormap */
97704007ebaSmrg
97804007ebaSmrg        if (!xf86HandleColormaps(pScrn, 256, 8,
97904007ebaSmrg                                 LXLoadPalette, NULL,
98004007ebaSmrg                                 CMAP_PALETTED_TRUECOLOR |
98104007ebaSmrg                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
98204007ebaSmrg            return FALSE;
98304007ebaSmrg        }
984f29dbc25Smrg    }
985f29dbc25Smrg    xf86DPMSInit(pScrn, xf86DPMSSet, 0);
986f29dbc25Smrg
987f29dbc25Smrg    LXInitVideo(pScrn);
988f29dbc25Smrg
989f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
990f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
991f29dbc25Smrg
992f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
993f29dbc25Smrg    pScrn->CloseScreen = LXCloseScreen;
994f29dbc25Smrg    pScrn->SaveScreen = LXSaveScreen;
995f29dbc25Smrg
996f29dbc25Smrg    if (!xf86CrtcScreenInit(pScrn)) {
99704007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n");
99804007ebaSmrg        return FALSE;
999f29dbc25Smrg    }
1000f29dbc25Smrg
1001f29dbc25Smrg    if (serverGeneration == 1)
100204007ebaSmrg        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1003f29dbc25Smrg
1004f29dbc25Smrg    pGeode->starting = FALSE;
1005f29dbc25Smrg
1006f29dbc25Smrg    return TRUE;
1007f29dbc25Smrg}
1008f29dbc25Smrg
1009f29dbc25Smrgstatic int
101004007ebaSmrgLXValidMode(VALID_MODE_ARGS_DECL)
1011f29dbc25Smrg{
1012f29dbc25Smrg    return MODE_OK;
1013f29dbc25Smrg}
1014f29dbc25Smrg
1015f29dbc25Smrgstatic Bool
101604007ebaSmrgLXEnterVT(VT_FUNC_ARGS_DECL)
1017f29dbc25Smrg{
101804007ebaSmrg    SCRN_INFO_PTR(arg);
101904007ebaSmrg    return LXEnterGraphics(NULL, pScrni);
1020f29dbc25Smrg}
1021f29dbc25Smrg
1022f29dbc25Smrgstatic void
102304007ebaSmrgLXLeaveVT(VT_FUNC_ARGS_DECL)
1024f29dbc25Smrg{
102504007ebaSmrg    SCRN_INFO_PTR(arg);
1026f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1027f29dbc25Smrg
1028f29dbc25Smrg    pGeode->PrevDisplayOffset = vg_get_display_offset();
1029f29dbc25Smrg    LXLeaveGraphics(pScrni);
1030f29dbc25Smrg}
1031f29dbc25Smrg
1032f29dbc25Smrgvoid
1033f29dbc25SmrgLXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1034f29dbc25Smrg{
1035f29dbc25Smrg    pScrn->PreInit = LXPreInit;
1036f29dbc25Smrg    pScrn->ScreenInit = LXScreenInit;
1037f29dbc25Smrg    pScrn->SwitchMode = LXSwitchMode;
1038f29dbc25Smrg    pScrn->AdjustFrame = LXAdjustFrame;
1039f29dbc25Smrg    pScrn->EnterVT = LXEnterVT;
1040f29dbc25Smrg    pScrn->LeaveVT = LXLeaveVT;
1041f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1042f29dbc25Smrg    pScrn->ValidMode = LXValidMode;
1043f29dbc25Smrg}
1044