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
4000be8644Schristos#include "xorg-server.h"
4100be8644Schristos
42f29dbc25Smrg#include "xf86.h"
43f29dbc25Smrg#include "xf86_OSproc.h"
44f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
45f29dbc25Smrg#include "xf86Resources.h"
46f29dbc25Smrg#endif
47f29dbc25Smrg#include "xf86i2c.h"
48f29dbc25Smrg#include "xf86Crtc.h"
49f29dbc25Smrg#include "xf86cmap.h"
50f29dbc25Smrg#include "compiler.h"
51f29dbc25Smrg#include "mipointer.h"
52f29dbc25Smrg#include "fb.h"
53f29dbc25Smrg#include "miscstruct.h"
54f29dbc25Smrg#include "micmap.h"
55f29dbc25Smrg#include "vbe.h"
56f29dbc25Smrg#include "fb.h"
57f29dbc25Smrg#include "cim_defs.h"
58f29dbc25Smrg#include "cim_regs.h"
59f29dbc25Smrg#include "geode.h"
60f29dbc25Smrg
61f29dbc25Smrg/* Bring in VGA functions */
62f29dbc25Smrg#include "lx_vga.c"
63f29dbc25Smrg
64f29dbc25Smrg#define LX_MAX_WIDTH  1940
65f29dbc25Smrg#define LX_MAX_HEIGHT 1600
66f29dbc25Smrg
67f29dbc25Smrg/* Size of the register blocks */
68f29dbc25Smrg
69f29dbc25Smrg#define LX_GP_REG_SIZE  0x4000
70f29dbc25Smrg#define LX_VG_REG_SIZE  0x4000
71f29dbc25Smrg#define LX_VID_REG_SIZE 0x4000
72f29dbc25Smrg#define LX_VIP_REG_SIZE 0x4000
73f29dbc25Smrg
74f29dbc25Smrg/* Size of the Cimarron command buffer */
75f29dbc25Smrg#define CIM_CMD_BFR_SZ 0x200000
76f29dbc25Smrg
77f29dbc25Smrgextern OptionInfoRec LX_GeodeOptions[];
78f29dbc25Smrg
79ad01e365Sjoergextern unsigned char *XpressROMPtr;
80f29dbc25Smrg
81f29dbc25Smrgstatic Bool
82f29dbc25SmrgLXSaveScreen(ScreenPtr pScrn, int mode)
83f29dbc25Smrg{
8404007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
85f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
86f29dbc25Smrg
87f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
8804007ebaSmrg        return vgaHWSaveScreen(pScrn, mode);
89f29dbc25Smrg
90f29dbc25Smrg    return TRUE;
91f29dbc25Smrg}
92f29dbc25Smrg
93f29dbc25Smrg/* This is an overly complex MSR read mechanism */
94f29dbc25Smrg
95f29dbc25Smrg/* From Cimarron - the VSAII read/write methods - we use these as fallback */
96f29dbc25Smrg
97f29dbc25Smrg#define LX_MSR_READ(adr,lo,hi)              \
98f29dbc25Smrg     __asm__ __volatile__(                      \
99f29dbc25Smrg        " mov $0x0AC1C, %%edx\n"                \
100f29dbc25Smrg        " mov $0xFC530007, %%eax\n"             \
101f29dbc25Smrg        " out %%eax,%%dx\n"                     \
102f29dbc25Smrg        " add $2,%%dl\n"                        \
103f29dbc25Smrg        " in %%dx, %%ax"                        \
104f29dbc25Smrg        : "=a" (lo), "=d" (hi)                  \
105f29dbc25Smrg        : "c" (adr))
106f29dbc25Smrg
107f29dbc25Smrg#define LX_MSR_WRITE(adr,low,high) \
108f29dbc25Smrg  { int d0, d1, d2, d3, d4;        \
109f29dbc25Smrg  __asm__ __volatile__(            \
110f29dbc25Smrg    " push %%ebx\n"                \
111f29dbc25Smrg    " mov $0x0AC1C, %%edx\n"       \
112f29dbc25Smrg    " mov $0xFC530007, %%eax\n"    \
113f29dbc25Smrg    " out %%eax,%%dx\n"            \
114f29dbc25Smrg    " add $2,%%dl\n"               \
115f29dbc25Smrg    " mov %6, %%ebx\n"             \
116f29dbc25Smrg    " mov %7, %0\n"                \
117f29dbc25Smrg    " mov %5, %3\n"                \
118f29dbc25Smrg    " xor %2, %2\n"                \
119f29dbc25Smrg    " xor %1, %1\n"                \
120f29dbc25Smrg    " out %%ax, %%dx\n"            \
121f29dbc25Smrg    " pop %%ebx\n"                 \
122f29dbc25Smrg    : "=a"(d0),"=&D"(d1),"=&S"(d2), \
123f29dbc25Smrg      "=c"(d3),"=d"(d4)  \
124f29dbc25Smrg    : "1"(adr),"2"(high),"3"(low)); \
125f29dbc25Smrg  }
126f29dbc25Smrg
127f29dbc25Smrgstatic void
128f29dbc25SmrgLXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi)
129f29dbc25Smrg{
130f29dbc25Smrg    if (GeodeReadMSR(addr, lo, hi) == -1) {
13104007ebaSmrg        unsigned int l, h;
132f29dbc25Smrg
13304007ebaSmrg        LX_MSR_READ(addr, l, h);
13404007ebaSmrg        *lo = l;
13504007ebaSmrg        *hi = h;
136f29dbc25Smrg    }
137f29dbc25Smrg}
138f29dbc25Smrg
139f29dbc25Smrgstatic void
140f29dbc25SmrgLXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi)
141f29dbc25Smrg{
142f29dbc25Smrg    if (GeodeWriteMSR(addr, lo, hi) == -1)
14304007ebaSmrg        LX_MSR_WRITE(addr, lo, hi);
144f29dbc25Smrg}
145f29dbc25Smrg
146f29dbc25Smrgstatic unsigned int
147f29dbc25SmrgLXCalcPitch(ScrnInfoPtr pScrni)
148f29dbc25Smrg{
149f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
150f29dbc25Smrg
151f29dbc25Smrg    if (pGeode->tryCompression)
15204007ebaSmrg        return GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
153f29dbc25Smrg    else
15404007ebaSmrg        return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
155f29dbc25Smrg}
156f29dbc25Smrg
157f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
158f29dbc25Smrgstatic inline void *
159f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
16004007ebaSmrg            struct pci_device *dev, int bar, int size)
161f29dbc25Smrg{
162f29dbc25Smrg    void *ptr;
163f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
164f29dbc25Smrg
165f29dbc25Smrg    int err = pci_device_map_range(dev,
16604007ebaSmrg                                   dev->regions[bar].base_addr,
16704007ebaSmrg                                   map_size,
16804007ebaSmrg                                   PCI_DEV_MAP_FLAG_WRITABLE |
16904007ebaSmrg                                   (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
1707f419768Smrg                                   &ptr);
171f29dbc25Smrg
172f29dbc25Smrg    if (err)
17304007ebaSmrg        return NULL;
174f29dbc25Smrg    return ptr;
175f29dbc25Smrg}
176f29dbc25Smrg
177f29dbc25Smrgstatic inline int
178f29dbc25Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
179f29dbc25Smrg{
180f29dbc25Smrg    return pci_device_unmap_range(dev, ptr, size);
181f29dbc25Smrg}
182f29dbc25Smrg
183f29dbc25Smrg#endif
184f29dbc25Smrg
185f29dbc25Smrgstatic Bool
186f29dbc25SmrgLXMapMem(ScrnInfoPtr pScrni)
187f29dbc25Smrg{
188f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
189f29dbc25Smrg    int index = pScrni->scrnIndex;
190f29dbc25Smrg    unsigned long cmd_bfr_phys;
191f29dbc25Smrg
192f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
193f29dbc25Smrg
194f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
195f29dbc25Smrg    PCITAG tag;
196f29dbc25Smrg
197f29dbc25Smrg    tag = pciTag(pci->bus, pci->device, pci->func);
198f29dbc25Smrg
19904007ebaSmrg    cim_gp_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
20004007ebaSmrg                                                 tag, pci->memBase[1],
20104007ebaSmrg                                                 LX_GP_REG_SIZE);
202f29dbc25Smrg
20304007ebaSmrg    cim_vg_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
20404007ebaSmrg                                                 tag, pci->memBase[2],
20504007ebaSmrg                                                 LX_VG_REG_SIZE);
206f29dbc25Smrg
20704007ebaSmrg    cim_vid_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
20804007ebaSmrg                                                  tag, pci->memBase[3],
20904007ebaSmrg                                                  LX_VID_REG_SIZE);
210f29dbc25Smrg
21104007ebaSmrg    cim_vip_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
21204007ebaSmrg                                                  tag, pci->memBase[4],
21304007ebaSmrg                                                  LX_VIP_REG_SIZE);
214f29dbc25Smrg
21504007ebaSmrg    cim_fb_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_FRAMEBUFFER,
21604007ebaSmrg                                                 tag, pci->memBase[0],
21704007ebaSmrg                                                 pGeode->FBAvail +
21804007ebaSmrg                                                 CIM_CMD_BFR_SZ);
219f29dbc25Smrg#else
220f29dbc25Smrg    cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE);
221f29dbc25Smrg    cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE);
222f29dbc25Smrg    cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE);
223f29dbc25Smrg    cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE);
224f29dbc25Smrg    cim_fb_ptr =
22504007ebaSmrg        map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ);
226f29dbc25Smrg#endif
227f29dbc25Smrg
228f29dbc25Smrg    if (pScrni->memPhysBase == 0)
22904007ebaSmrg        pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM);
230f29dbc25Smrg
231f29dbc25Smrg    cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset;
232f29dbc25Smrg    cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset;
233f29dbc25Smrg
234f29dbc25Smrg    if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr ||
23504007ebaSmrg        !cim_vip_ptr)
23604007ebaSmrg        return FALSE;
237f29dbc25Smrg
238f29dbc25Smrg    gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM),
23904007ebaSmrg                             pGeode->FBAvail);
240f29dbc25Smrg    gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize);
241f29dbc25Smrg
2427f419768Smrg#ifndef XSERVER_LIBPCIACCESS
243f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
2447f419768Smrg#else
2457f419768Smrg    {
2467f419768Smrg        int fd = open("/dev/mem", O_RDWR);
2477f419768Smrg        if (fd < 0) {
2487f419768Smrg            xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n");
2497f419768Smrg            return FALSE;
2507f419768Smrg        }
2517f419768Smrg        XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000);
2527f419768Smrg        close(fd);
2537f419768Smrg    }
2547f419768Smrg#endif
255f29dbc25Smrg
256f29dbc25Smrg    pGeode->FBBase = cim_fb_ptr;
257f29dbc25Smrg
258f29dbc25Smrg    if (!pGeode->NoAccel)
25904007ebaSmrg        pGeode->pExa->memoryBase = pGeode->FBBase;
260f29dbc25Smrg
261f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n",
26204007ebaSmrg               pGeode->FBAvail, pGeode->FBBase);
263f29dbc25Smrg
264f29dbc25Smrg    return TRUE;
265f29dbc25Smrg}
266f29dbc25Smrg
267f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
268f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
269f29dbc25Smrg*/
270f29dbc25Smrg
271f29dbc25Smrgstatic Bool
2727f419768SmrgLXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt)
273f29dbc25Smrg{
2747f419768Smrg#ifndef XSERVER_LIBPCIACCESS
275f29dbc25Smrg    unsigned char *ptr;
276f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
277f29dbc25Smrg    int ret;
278f29dbc25Smrg
279f29dbc25Smrg    ptr =
28004007ebaSmrg        xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
28104007ebaSmrg                      strlen(vgasig));
282f29dbc25Smrg
283f29dbc25Smrg    if (ptr == NULL)
28404007ebaSmrg        return FALSE;
285f29dbc25Smrg
286f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
287f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
288f29dbc25Smrg
289f29dbc25Smrg    return ret ? FALSE : TRUE;
2907f419768Smrg#else
2917f419768Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index);
2927f419768Smrg
2937f419768Smrg    return pci_device_is_boot_vga(pci);
2947f419768Smrg#endif
295f29dbc25Smrg}
296f29dbc25Smrg
297f29dbc25Smrgstatic Bool
298f29dbc25SmrgLXCrtcResize(ScrnInfoPtr pScrni, int width, int height)
299f29dbc25Smrg{
300f29dbc25Smrg    return TRUE;
301f29dbc25Smrg}
302f29dbc25Smrg
303f29dbc25Smrgstatic const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = {
304f29dbc25Smrg    LXCrtcResize,
305f29dbc25Smrg};
306f29dbc25Smrg
307f29dbc25Smrgstatic Bool
308f29dbc25SmrgLXPreInit(ScrnInfoPtr pScrni, int flags)
309f29dbc25Smrg{
310f29dbc25Smrg    GeodePtr pGeode;
311f29dbc25Smrg    EntityInfoPtr pEnt;
312f29dbc25Smrg    OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0];
313f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
3143406bd8eSmrg    const char *s;
315f29dbc25Smrg
316f29dbc25Smrg    if (pScrni->numEntities != 1)
31704007ebaSmrg        return FALSE;
318f29dbc25Smrg
319f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
320f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
321f29dbc25Smrg    if (pEnt->resources)
32204007ebaSmrg        return FALSE;
323f29dbc25Smrg#endif
324f29dbc25Smrg    if (flags & PROBE_DETECT) {
32504007ebaSmrg        GeodeProbeDDC(pScrni, pEnt->index);
32604007ebaSmrg        return TRUE;
327f29dbc25Smrg    }
328f29dbc25Smrg
32904007ebaSmrg    pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
330f29dbc25Smrg
331f29dbc25Smrg    if (pGeode == NULL)
33204007ebaSmrg        return FALSE;
333f29dbc25Smrg
3347f419768Smrg    pGeode->useVGA = LXCheckVGA(pScrni, pEnt);
335f29dbc25Smrg    pGeode->VGAActive = FALSE;
336f29dbc25Smrg    pGeode->pEnt = pEnt;
337f29dbc25Smrg
338f29dbc25Smrg    if (pGeode->useVGA) {
33904007ebaSmrg        if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
34004007ebaSmrg            pGeode->useVGA = FALSE;
34104007ebaSmrg        else
34204007ebaSmrg            vgaHWSetStdFuncs(VGAHWPTR(pScrni));
343f29dbc25Smrg
34404007ebaSmrg        pGeode->vesa = calloc(1, sizeof(VESARec));
345f29dbc25Smrg    }
346f29dbc25Smrg
347f29dbc25Smrg    cim_rdmsr = LXReadMSR;
348f29dbc25Smrg    cim_wrmsr = LXWriteMSR;
349f29dbc25Smrg
350f29dbc25Smrg    /* Set up the Cimarron MSR tables */
351f29dbc25Smrg    msr_init_table();
352f29dbc25Smrg
353f29dbc25Smrg    /* By default, we support panel and CRT - the config file should
354f29dbc25Smrg     * disable the ones we don't want
355f29dbc25Smrg     */
356f29dbc25Smrg
357f29dbc25Smrg    pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT;
358f29dbc25Smrg
359f29dbc25Smrg    /* Fill in the monitor information */
360f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
361f29dbc25Smrg
362f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
36304007ebaSmrg        return FALSE;
364f29dbc25Smrg
365f29dbc25Smrg    switch (pScrni->depth) {
366f29dbc25Smrg    case 8:
36704007ebaSmrg        pScrni->rgbBits = 8;
368f29dbc25Smrg    case 16:
369f29dbc25Smrg    case 24:
370f29dbc25Smrg    case 32:
37104007ebaSmrg        break;
372f29dbc25Smrg    default:
37304007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
37404007ebaSmrg                   "The driver does not support %d as a depth.\n",
37504007ebaSmrg                   pScrni->depth);
37604007ebaSmrg        return FALSE;
377f29dbc25Smrg    }
378f29dbc25Smrg
379f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
380f29dbc25Smrg
381f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
38204007ebaSmrg        return FALSE;
383f29dbc25Smrg
384f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
38504007ebaSmrg        return FALSE;
386f29dbc25Smrg
387f29dbc25Smrg    /*
388f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
389f29dbc25Smrg     * here.
390f29dbc25Smrg     */
391f29dbc25Smrg    {
39204007ebaSmrg        Gamma zeros = { 0.0, 0.0, 0.0 };
393f29dbc25Smrg
39404007ebaSmrg        if (!xf86SetGamma(pScrni, zeros)) {
39504007ebaSmrg            return FALSE;
39604007ebaSmrg        }
397f29dbc25Smrg    }
398f29dbc25Smrg
399f29dbc25Smrg    pScrni->progClock = TRUE;
400f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
401f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
402f29dbc25Smrg
403f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
404f29dbc25Smrg
405f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
406f29dbc25Smrg    pGeode->tryCompression = TRUE;
407f29dbc25Smrg
408f29dbc25Smrg    /* Protect against old versions of EXA */
409f29dbc25Smrg
410f29dbc25Smrg#if (EXA_VERSION_MAJOR < 2)
411f29dbc25Smrg    pGeode->NoAccel = TRUE;
412f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41304007ebaSmrg               "*** This driver was compiled with EXA version %d\n");
414f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41504007ebaSmrg               "*** we need version 2 or greater\n");
416f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
41704007ebaSmrg               "*** All accelerations are being turned off.\n");
418f29dbc25Smrg#else
419f29dbc25Smrg    pGeode->NoAccel = FALSE;
420f29dbc25Smrg#endif
421f29dbc25Smrg
422f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
423f29dbc25Smrg
42404007ebaSmrg    xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
425f29dbc25Smrg
426f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE,
42704007ebaSmrg                              (int *) &(pGeode->FBAvail)))
42804007ebaSmrg        pGeode->FBAvail = 0;
429f29dbc25Smrg
430c744f008Smrg    /* For compatibility - allow SWCursor too */
431f29dbc25Smrg
432f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE))
43304007ebaSmrg        pGeode->tryHWCursor = FALSE;
434f29dbc25Smrg
435f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE))
43604007ebaSmrg        pGeode->tryCompression = FALSE;
437f29dbc25Smrg
438f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE))
43904007ebaSmrg        pGeode->NoAccel = TRUE;
440f29dbc25Smrg
441f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
442f29dbc25Smrg
443f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) {
444f29dbc25Smrg
44504007ebaSmrg        if (!xf86NameCmp(s, "LEFT"))
44604007ebaSmrg            pGeode->rotation = RR_Rotate_90;
44704007ebaSmrg        else if (!xf86NameCmp(s, "INVERT"))
44804007ebaSmrg            pGeode->rotation = RR_Rotate_180;
44904007ebaSmrg        else if (!xf86NameCmp(s, "CCW"))
45004007ebaSmrg            pGeode->rotation = RR_Rotate_270;
45104007ebaSmrg        else
45204007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
453f29dbc25Smrg    }
454f29dbc25Smrg
455f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ,
45604007ebaSmrg                         (int *) &(pGeode->exaBfrSz));
457f29dbc25Smrg
458f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
45904007ebaSmrg        pGeode->exaBfrSz = 0;
460f29dbc25Smrg
461f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL) {
46204007ebaSmrg        if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE))
46304007ebaSmrg            pGeode->Output &= ~OUTPUT_PANEL;
464f29dbc25Smrg    }
465f29dbc25Smrg
466f29dbc25Smrg    /* Panel detection code -
467f29dbc25Smrg     * 1.  See if an OLPC DCON is attached - we can make some assumptions
468f29dbc25Smrg     * about the panel if so.
469f29dbc25Smrg     * 2.  Use panel mode specified in the config
470f29dbc25Smrg     * 3.  "Autodetect" the panel through VSA
471f29dbc25Smrg     */
472f29dbc25Smrg
473f29dbc25Smrg    if (dcon_init(pScrni)) {
47404007ebaSmrg        pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON;
47504007ebaSmrg    }
47604007ebaSmrg    else if (pGeode->Output & OUTPUT_PANEL) {
477861b9feeSmrg        const char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE);
478f29dbc25Smrg
47904007ebaSmrg        if (pmode != NULL)
48004007ebaSmrg            pGeode->panelMode = LXGetManualPanelMode(pmode);
481f29dbc25Smrg
48204007ebaSmrg        if (pGeode->panelMode == NULL)
48304007ebaSmrg            pGeode->panelMode = LXGetLegacyPanelMode(pScrni);
484f29dbc25Smrg
48504007ebaSmrg        if (pGeode->panelMode == NULL)
48604007ebaSmrg            pGeode->Output &= ~OUTPUT_PANEL;
487f29dbc25Smrg    }
488f29dbc25Smrg
489f29dbc25Smrg    /* Default to turn scaling on for panels */
490f29dbc25Smrg
491f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL)
49204007ebaSmrg        pGeode->Scale = TRUE;
493f29dbc25Smrg
494f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n");
495f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n",
49604007ebaSmrg               pGeode->Output & OUTPUT_CRT ? "YES" : "NO");
497f29dbc25Smrg
498f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n",
49904007ebaSmrg               pGeode->Output & OUTPUT_PANEL ? "YES" : "NO");
500f29dbc25Smrg
501f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n",
50204007ebaSmrg               pGeode->Output & OUTPUT_DCON ? "YES" : "NO");
503f29dbc25Smrg
504f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n",
50504007ebaSmrg               pGeode->useVGA ? "YES" : "NO");
506f29dbc25Smrg
507f29dbc25Smrg    /* Set up VGA */
508f29dbc25Smrg
509f29dbc25Smrg    if (pGeode->useVGA) {
51004007ebaSmrg        VESARec *pVesa;
511f29dbc25Smrg
51204007ebaSmrg        if (!xf86LoadSubModule(pScrni, "int10"))
51304007ebaSmrg            return FALSE;
514f29dbc25Smrg
51504007ebaSmrg        pVesa = pGeode->vesa;
516f29dbc25Smrg
51704007ebaSmrg        if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
51804007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
51904007ebaSmrg                       "Unable to initialize 1NT10 support\n");
52004007ebaSmrg            pGeode->useVGA = FALSE;
52104007ebaSmrg        }
522f29dbc25Smrg    }
523f29dbc25Smrg
524f29dbc25Smrg    /* Read the amount of framebuffer memory */
525f29dbc25Smrg    /* First try to read it from the framebuffer, and if that fails,
526f29dbc25Smrg     * do it the legacy way
527f29dbc25Smrg     */
528f29dbc25Smrg
529f29dbc25Smrg    if (pGeode->FBAvail == 0) {
53004007ebaSmrg        if (GeodeGetSizeFromFB(&pGeode->FBAvail)) {
53104007ebaSmrg            unsigned long value;
532f29dbc25Smrg
53304007ebaSmrg            cim_outw(0xAC1C, 0xFC53);
53404007ebaSmrg            cim_outw(0xAC1C, 0x0200);
535f29dbc25Smrg
53604007ebaSmrg            value = (unsigned long) (cim_inw(0xAC1E)) & 0xFE;
53704007ebaSmrg            pGeode->FBAvail = value << 20;
53804007ebaSmrg        }
539f29dbc25Smrg    }
540f29dbc25Smrg
541f29dbc25Smrg    pScrni->fbOffset = 0;
542f29dbc25Smrg
543f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
54404007ebaSmrg        pScrni->videoRam = pGeode->FBAvail / 1024;
545f29dbc25Smrg    else {
54604007ebaSmrg        pScrni->videoRam = pGeode->pEnt->device->videoRam;
54704007ebaSmrg        pGeode->FBAvail = pScrni->videoRam << 10;
548f29dbc25Smrg    }
549f29dbc25Smrg
550f29dbc25Smrg    /* If we have <= 16Mb of memory then compression is going
551f29dbc25Smrg       to hurt - so warn and disable */
552f29dbc25Smrg
55304007ebaSmrg    if (pGeode->tryCompression && pGeode->FBAvail <= 0x1000000) {
55404007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
55504007ebaSmrg                   "%x bytes of video memory is less then optimal\n",
55604007ebaSmrg                   pGeode->FBAvail);
55704007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_INFO,
55804007ebaSmrg                   "when compression is on. Disabling compression.\n");
55904007ebaSmrg        pGeode->tryCompression = FALSE;
560f29dbc25Smrg    }
561f29dbc25Smrg
562f29dbc25Smrg    /* Carve out some memory for the command buffer */
563f29dbc25Smrg
564f29dbc25Smrg    pGeode->CmdBfrSize = CIM_CMD_BFR_SZ;
565f29dbc25Smrg    pGeode->FBAvail -= CIM_CMD_BFR_SZ;
566f29dbc25Smrg
567f29dbc25Smrg    pGeode->CmdBfrOffset = pGeode->FBAvail;
568f29dbc25Smrg
569f29dbc25Smrg    /* Allocate a a CRTC config structure */
570f29dbc25Smrg    xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs);
571f29dbc25Smrg
572f29dbc25Smrg    /* Set up the GPU CRTC */
573f29dbc25Smrg    LXSetupCrtc(pScrni);
574f29dbc25Smrg
575f29dbc25Smrg    xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT);
576f29dbc25Smrg
577f29dbc25Smrg    /* Setup the output */
578f29dbc25Smrg    LXSetupOutput(pScrni);
579f29dbc25Smrg
580f29dbc25Smrg    if (!xf86InitialConfiguration(pScrni, FALSE)) {
58104007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n");
58204007ebaSmrg        return FALSE;
583f29dbc25Smrg    }
584f29dbc25Smrg
585f29dbc25Smrg    xf86PrintModes(pScrni);
586f29dbc25Smrg
587f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
588f29dbc25Smrg
589f29dbc25Smrg    pGeode->Pitch = LXCalcPitch(pScrni);
590f29dbc25Smrg
591f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
592f29dbc25Smrg
593f29dbc25Smrg    /* Load the modules we'll need */
594f29dbc25Smrg
595f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
59604007ebaSmrg        return FALSE;
597f29dbc25Smrg    }
598f29dbc25Smrg
599f29dbc25Smrg    if (!pGeode->NoAccel) {
60004007ebaSmrg        if (!xf86LoadSubModule(pScrni, "exa"))
60104007ebaSmrg            return FALSE;
602f29dbc25Smrg    }
603f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
604f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
60504007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
60604007ebaSmrg                   "Couldn't register the resources.\n");
60704007ebaSmrg        return FALSE;
608f29dbc25Smrg    }
609f29dbc25Smrg#endif
610f29dbc25Smrg    return TRUE;
611f29dbc25Smrg}
612f29dbc25Smrg
613f29dbc25Smrgstatic void
614f29dbc25SmrgLXRestore(ScrnInfoPtr pScrni)
615f29dbc25Smrg{
616f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
617f29dbc25Smrg
618f29dbc25Smrg    if (pGeode->useVGA) {
61904007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
620f29dbc25Smrg
62104007ebaSmrg        vgaHWProtect(pScrni, TRUE);
62204007ebaSmrg        vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
62304007ebaSmrg        vgaHWProtect(pScrni, FALSE);
624f29dbc25Smrg    }
625f29dbc25Smrg}
626f29dbc25Smrg
627f29dbc25Smrgstatic Bool
628f29dbc25SmrgLXUnmapMem(ScrnInfoPtr pScrni)
629f29dbc25Smrg{
630f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
631f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE);
632f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE);
63304007ebaSmrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE);
63404007ebaSmrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE);
6357f419768Smrg
6367f419768Smrg    xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000);
637f29dbc25Smrg#else
638f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
639f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
640f29dbc25Smrg
641f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE);
642f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE);
643f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE);
644f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE);
645f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ);
646f29dbc25Smrg
6477f419768Smrg    munmap(XpressROMPtr, 0x10000);
6487f419768Smrg#endif
649f29dbc25Smrg
650f29dbc25Smrg    return TRUE;
651f29dbc25Smrg}
652f29dbc25Smrg
653f29dbc25Smrg/* These should be correctly accounted for rotation */
654f29dbc25Smrg
655f29dbc25Smrgvoid
65604007ebaSmrgLXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
657f29dbc25Smrg{
65804007ebaSmrg    SCRN_INFO_PTR(arg);
659f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
660f29dbc25Smrg
661f29dbc25Smrg    unsigned long offset;
662f29dbc25Smrg
663f29dbc25Smrg    offset = (y * pGeode->Pitch);
664f29dbc25Smrg    offset += x * (pScrni->bitsPerPixel >> 3);
665f29dbc25Smrg
666f29dbc25Smrg    vg_set_display_offset(offset);
667f29dbc25Smrg}
668f29dbc25Smrg
669f29dbc25Smrgstatic Bool
67004007ebaSmrgLXSwitchMode(SWITCH_MODE_ARGS_DECL)
671f29dbc25Smrg{
67204007ebaSmrg    SCRN_INFO_PTR(arg);
673f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
674f29dbc25Smrg
675f29dbc25Smrg    /* Set the new mode */
676f29dbc25Smrg    return xf86SetSingleMode(pScrni, pMode, pGeode->rotation);
677f29dbc25Smrg}
678f29dbc25Smrg
679f29dbc25Smrgstatic void
680f29dbc25SmrgLXLeaveGraphics(ScrnInfoPtr pScrni)
681f29dbc25Smrg{
682f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
683f29dbc25Smrg    VG_PANNING_COORDINATES panning;
684f29dbc25Smrg
685f29dbc25Smrg    gp_wait_until_idle();
686f29dbc25Smrg
68744802259Smrg    lx_disable_dac_power(pScrni, DF_CRT_DISABLE);
68844802259Smrg
689f29dbc25Smrg    vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode),
69004007ebaSmrg                       pGeode->FBcimdisplaytiming.wBpp);
691f29dbc25Smrg
692f29dbc25Smrg    vg_set_compression_enable(0);
693f29dbc25Smrg
694f29dbc25Smrg    /* Restore the previous Compression state */
695f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
69604007ebaSmrg        vg_configure_compression(&(pGeode->FBCBData));
69704007ebaSmrg        vg_set_compression_enable(1);
698f29dbc25Smrg    }
699f29dbc25Smrg
700f29dbc25Smrg    vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch);
701f29dbc25Smrg    vg_set_display_offset(pGeode->FBDisplayOffset);
702f29dbc25Smrg
703f29dbc25Smrg    /* Restore Cursor */
704f29dbc25Smrg    vg_set_cursor_position(pGeode->FBCursor.cursor_x,
70504007ebaSmrg                           pGeode->FBCursor.cursor_y, &panning);
706f29dbc25Smrg
707f29dbc25Smrg    LXRestore(pScrni);
708f29dbc25Smrg
709f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
71004007ebaSmrg        pGeode->vesa->pInt->num = 0x10;
71104007ebaSmrg        pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
71204007ebaSmrg        pGeode->vesa->pInt->bx = 0;
71304007ebaSmrg        xf86ExecX86int10(pGeode->vesa->pInt);
71404007ebaSmrg        vg_delay_milliseconds(3);
715f29dbc25Smrg    }
716f29dbc25Smrg
71744802259Smrg    lx_enable_dac_power(pScrni, 1);
718f29dbc25Smrg    pScrni->vtSema = FALSE;
719f29dbc25Smrg}
720f29dbc25Smrg
721f29dbc25Smrgstatic Bool
72204007ebaSmrgLXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
723f29dbc25Smrg{
72404007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
725f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
726f29dbc25Smrg
727f29dbc25Smrg    if (pScrni->vtSema)
72804007ebaSmrg        LXLeaveGraphics(pScrni);
729f29dbc25Smrg
730f29dbc25Smrg    if (pGeode->pExa) {
73104007ebaSmrg        exaDriverFini(pScrn);
73204007ebaSmrg        free(pGeode->pExa);
73304007ebaSmrg        pGeode->pExa = NULL;
734f29dbc25Smrg    }
735f29dbc25Smrg
736f29dbc25Smrg    /* Unmap the offscreen allocations */
737f29dbc25Smrg    GeodeCloseOffscreen(pScrni);
738f29dbc25Smrg
739f29dbc25Smrg    LXUnmapMem(pScrni);
740f29dbc25Smrg
741f29dbc25Smrg    if (pGeode->useVGA)
74204007ebaSmrg        vgaHWUnmapMem(pScrni);
743f29dbc25Smrg
744f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
745f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
746f29dbc25Smrg
747f29dbc25Smrg    if (pScrn->CloseScreen)
74804007ebaSmrg        return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
749f29dbc25Smrg
750f29dbc25Smrg    return TRUE;
751f29dbc25Smrg}
752f29dbc25Smrg
753f29dbc25Smrgstatic Bool
754f29dbc25SmrgLXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
755f29dbc25Smrg{
756f29dbc25Smrg    int bpp;
757f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
758f29dbc25Smrg
759f29dbc25Smrg    pGeode->VGAActive = gu3_get_vga_active();
760f29dbc25Smrg
761f29dbc25Smrg    gp_wait_until_idle();
762f29dbc25Smrg
763f29dbc25Smrg    vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode,
76404007ebaSmrg                                &bpp);
765f29dbc25Smrg
766f29dbc25Smrg    pGeode->FBcimdisplaytiming.wBpp = bpp;
767f29dbc25Smrg    pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch();
768f29dbc25Smrg
769f29dbc25Smrg    pGeode->FBDisplayOffset = vg_get_display_offset();
770f29dbc25Smrg
771f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
77204007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
773f29dbc25Smrg
77404007ebaSmrg        pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
775f29dbc25Smrg    }
776f29dbc25Smrg
777f29dbc25Smrg    pGeode->FBCompressionEnable = vg_get_compression_enable();
778f29dbc25Smrg    vg_get_compression_info(&(pGeode->FBCBData));
779f29dbc25Smrg
780f29dbc25Smrg    /* Save Cursor offset */
781f29dbc25Smrg    vg_get_cursor_info(&pGeode->FBCursor);
782f29dbc25Smrg
783f29dbc25Smrg    /* Turn off the VGA */
784f29dbc25Smrg
785f29dbc25Smrg    if (pGeode->useVGA) {
78604007ebaSmrg        unsigned short sequencer;
78704007ebaSmrg        vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
788f29dbc25Smrg
78904007ebaSmrg        /* Unlock VGA registers */
79004007ebaSmrg        vgaHWUnlock(pvgaHW);
791f29dbc25Smrg
79204007ebaSmrg        /* Save the current state and setup the current mode */
79304007ebaSmrg        vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
794f29dbc25Smrg
79504007ebaSmrg        /* DISABLE VGA SEQUENCER */
79604007ebaSmrg        /* This allows the VGA state machine to terminate. We must delay */
79704007ebaSmrg        /* such that there are no pending MBUS requests.  */
798f29dbc25Smrg
79904007ebaSmrg        cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE);
80004007ebaSmrg        sequencer = cim_inb(DC3_SEQUENCER_DATA);
80104007ebaSmrg        sequencer |= DC3_CLK_MODE_SCREEN_OFF;
80204007ebaSmrg        cim_outb(DC3_SEQUENCER_DATA, sequencer);
803f29dbc25Smrg
80404007ebaSmrg        vg_delay_milliseconds(1);
805f29dbc25Smrg
80604007ebaSmrg        /* BLANK THE VGA DISPLAY */
80704007ebaSmrg        cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET);
80804007ebaSmrg        sequencer = cim_inb(DC3_SEQUENCER_DATA);
80904007ebaSmrg        sequencer &= ~DC3_RESET_VGA_DISP_ENABLE;
81004007ebaSmrg        cim_outb(DC3_SEQUENCER_DATA, sequencer);
811f29dbc25Smrg
81204007ebaSmrg        vg_delay_milliseconds(1);
813f29dbc25Smrg    }
814f29dbc25Smrg
815f29dbc25Smrg    /* Clear the framebuffer */
816f29dbc25Smrg    memset(pGeode->FBBase, 0, pGeode->displaySize);
817f29dbc25Smrg
818f29dbc25Smrg    /* Set the modes */
819f29dbc25Smrg    if (!xf86SetDesiredModes(pScrni))
82004007ebaSmrg        return FALSE;
821f29dbc25Smrg
822f29dbc25Smrg    pScrni->vtSema = TRUE;
823f29dbc25Smrg
824f29dbc25Smrg    return TRUE;
825f29dbc25Smrg}
826f29dbc25Smrg
827f29dbc25Smrgstatic void
828f29dbc25SmrgLXLoadPalette(ScrnInfoPtr pScrni,
82904007ebaSmrg              int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
830f29dbc25Smrg{
831f29dbc25Smrg    int i, index, color;
832f29dbc25Smrg
833f29dbc25Smrg    for (i = 0; i < numColors; i++) {
83404007ebaSmrg        index = indizes[i] & 0xFF;
83504007ebaSmrg        color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
83604007ebaSmrg            (((unsigned long) (colors[index].green & 0xFF)) << 8) |
83704007ebaSmrg            ((unsigned long) (colors[index].blue & 0xFF));
838f29dbc25Smrg
83904007ebaSmrg        vg_set_display_palette_entry(index, color);
840f29dbc25Smrg    }
841f29dbc25Smrg}
842f29dbc25Smrg
843f29dbc25Smrgstatic Bool
84404007ebaSmrgLXScreenInit(SCREEN_INIT_ARGS_DECL)
845f29dbc25Smrg{
84604007ebaSmrg    ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
847f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
848f29dbc25Smrg    int ret;
849f29dbc25Smrg    unsigned int dwidth;
850f29dbc25Smrg
851f29dbc25Smrg    pGeode->starting = TRUE;
852f29dbc25Smrg
853f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
854f29dbc25Smrg
855f29dbc25Smrg    if (pGeode->useVGA) {
856f29dbc25Smrg
85704007ebaSmrg        if (!vgaHWMapMem(pScrni))
85804007ebaSmrg            return FALSE;
859f29dbc25Smrg
86004007ebaSmrg        vgaHWGetIOBase(VGAHWPTR(pScrni));
861f29dbc25Smrg    }
862f29dbc25Smrg
863f29dbc25Smrg    if (!pGeode->NoAccel) {
864f29dbc25Smrg
86504007ebaSmrg        pGeode->pExa = exaDriverAlloc();
866f29dbc25Smrg
86704007ebaSmrg        if (pGeode->pExa) {
868f29dbc25Smrg
86904007ebaSmrg            pGeode->pExa->memoryBase = 0;
87004007ebaSmrg            pGeode->pExa->memorySize = 0;
871f29dbc25Smrg
87204007ebaSmrg            pGeode->pExa->pixmapOffsetAlign = 32;
87304007ebaSmrg            pGeode->pExa->pixmapPitchAlign = 32;
87404007ebaSmrg            pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS;
87504007ebaSmrg            pGeode->pExa->maxX = LX_MAX_WIDTH - 1;
87604007ebaSmrg            pGeode->pExa->maxY = LX_MAX_HEIGHT - 1;
87704007ebaSmrg        }
87804007ebaSmrg        else {
87904007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
88004007ebaSmrg                       "Couldn't allocate the EXA structure.\n");
88104007ebaSmrg            pGeode->NoAccel = TRUE;
88204007ebaSmrg        }
883f29dbc25Smrg    }
884f29dbc25Smrg
885f29dbc25Smrg    /* Map the memory here before doing anything else */
886f29dbc25Smrg
887f29dbc25Smrg    if (!LXMapMem(pScrni))
88804007ebaSmrg        return FALSE;
889f29dbc25Smrg
890f29dbc25Smrg    LXInitOffscreen(pScrni);
891f29dbc25Smrg
892f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
893f29dbc25Smrg    if (!LXEnterGraphics(pScrn, pScrni))
89404007ebaSmrg        return FALSE;
895f29dbc25Smrg
896f29dbc25Smrg    miClearVisualTypes();
897f29dbc25Smrg
898f29dbc25Smrg    /* XXX Again - take down anything? */
899f29dbc25Smrg
900f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
90104007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
90204007ebaSmrg                              TrueColorMask, pScrni->rgbBits,
90304007ebaSmrg                              pScrni->defaultVisual)) {
90404007ebaSmrg            return FALSE;
90504007ebaSmrg        }
90604007ebaSmrg    }
90704007ebaSmrg    else {
90804007ebaSmrg        if (!miSetVisualTypes(pScrni->depth,
90904007ebaSmrg                              miGetDefaultVisualMask(pScrni->depth),
91004007ebaSmrg                              pScrni->rgbBits, pScrni->defaultVisual)) {
91104007ebaSmrg            return FALSE;
91204007ebaSmrg        }
913f29dbc25Smrg    }
914f29dbc25Smrg
915f29dbc25Smrg    miSetPixmapDepths();
916f29dbc25Smrg
917f29dbc25Smrg    if (pScrni->virtualX > pScrni->displayWidth)
91804007ebaSmrg        pScrni->displayWidth = pScrni->virtualX;
919f29dbc25Smrg
920f29dbc25Smrg    /* Point at the visible area to start */
921f29dbc25Smrg
922f29dbc25Smrg    /* fbScreenInit assumes that the stride is display width *
923f29dbc25Smrg     * bytes per pixel.  If compression is on, then our stride might
924f29dbc25Smrg     * be completely different, so we divide the pitch by the
925f29dbc25Smrg     * bytes per pixel to fake fbScreenInit into doing the right thing */
926f29dbc25Smrg
927f29dbc25Smrg    dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
928f29dbc25Smrg
929f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase,
93004007ebaSmrg                       pScrni->virtualX, pScrni->virtualY,
93104007ebaSmrg                       pScrni->xDpi, pScrni->yDpi, dwidth,
93204007ebaSmrg                       pScrni->bitsPerPixel);
933f29dbc25Smrg
934f29dbc25Smrg    if (!ret)
93504007ebaSmrg        return FALSE;
936f29dbc25Smrg
937f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
938f29dbc25Smrg
939f29dbc25Smrg    /* Set up the color ordering */
940f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
94104007ebaSmrg        VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
94204007ebaSmrg
94304007ebaSmrg        while (--visual >= pScrn->visuals) {
94404007ebaSmrg            if ((visual->class | DynamicClass) == DirectColor) {
94504007ebaSmrg                visual->offsetRed = pScrni->offset.red;
94604007ebaSmrg                visual->offsetGreen = pScrni->offset.green;
94704007ebaSmrg                visual->offsetBlue = pScrni->offset.blue;
94804007ebaSmrg                visual->redMask = pScrni->mask.red;
94904007ebaSmrg                visual->greenMask = pScrni->mask.green;
95004007ebaSmrg                visual->blueMask = pScrni->mask.blue;
95104007ebaSmrg            }
95204007ebaSmrg        }
953f29dbc25Smrg    }
954f29dbc25Smrg
955f29dbc25Smrg    /* Must follow the color ordering */
956f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
957f29dbc25Smrg
958f29dbc25Smrg    if (!pGeode->NoAccel)
95904007ebaSmrg        pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE;
960f29dbc25Smrg
961f29dbc25Smrg    xf86SetBackingStore(pScrn);
962f29dbc25Smrg
963f29dbc25Smrg    /* Set up the soft cursor */
964f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
965f29dbc25Smrg
966f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
967f29dbc25Smrg
968f29dbc25Smrg    if (pGeode->tryHWCursor) {
96904007ebaSmrg        if (!LXCursorInit(pScrn))
97004007ebaSmrg            xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
97104007ebaSmrg                       "Hardware cursor initialization failed.\n");
972f29dbc25Smrg    }
973f29dbc25Smrg
974f29dbc25Smrg    /* Set up the color map */
975f29dbc25Smrg
976f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
97704007ebaSmrg        return FALSE;
978f29dbc25Smrg
979f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
98004007ebaSmrg        /* Must follow initialization of the default colormap */
98104007ebaSmrg
98204007ebaSmrg        if (!xf86HandleColormaps(pScrn, 256, 8,
98304007ebaSmrg                                 LXLoadPalette, NULL,
98404007ebaSmrg                                 CMAP_PALETTED_TRUECOLOR |
98504007ebaSmrg                                 CMAP_RELOAD_ON_MODE_SWITCH)) {
98604007ebaSmrg            return FALSE;
98704007ebaSmrg        }
988f29dbc25Smrg    }
989f29dbc25Smrg    xf86DPMSInit(pScrn, xf86DPMSSet, 0);
990f29dbc25Smrg
991f29dbc25Smrg    LXInitVideo(pScrn);
992f29dbc25Smrg
993f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
994f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
995f29dbc25Smrg
996f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
997f29dbc25Smrg    pScrn->CloseScreen = LXCloseScreen;
998f29dbc25Smrg    pScrn->SaveScreen = LXSaveScreen;
999f29dbc25Smrg
1000f29dbc25Smrg    if (!xf86CrtcScreenInit(pScrn)) {
100104007ebaSmrg        xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n");
100204007ebaSmrg        return FALSE;
1003f29dbc25Smrg    }
1004f29dbc25Smrg
1005f29dbc25Smrg    if (serverGeneration == 1)
100604007ebaSmrg        xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1007f29dbc25Smrg
1008f29dbc25Smrg    pGeode->starting = FALSE;
1009f29dbc25Smrg
1010f29dbc25Smrg    return TRUE;
1011f29dbc25Smrg}
1012f29dbc25Smrg
1013f29dbc25Smrgstatic int
101404007ebaSmrgLXValidMode(VALID_MODE_ARGS_DECL)
1015f29dbc25Smrg{
1016f29dbc25Smrg    return MODE_OK;
1017f29dbc25Smrg}
1018f29dbc25Smrg
1019f29dbc25Smrgstatic Bool
102004007ebaSmrgLXEnterVT(VT_FUNC_ARGS_DECL)
1021f29dbc25Smrg{
102204007ebaSmrg    SCRN_INFO_PTR(arg);
102304007ebaSmrg    return LXEnterGraphics(NULL, pScrni);
1024f29dbc25Smrg}
1025f29dbc25Smrg
1026f29dbc25Smrgstatic void
102704007ebaSmrgLXLeaveVT(VT_FUNC_ARGS_DECL)
1028f29dbc25Smrg{
102904007ebaSmrg    SCRN_INFO_PTR(arg);
1030f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1031f29dbc25Smrg
1032f29dbc25Smrg    pGeode->PrevDisplayOffset = vg_get_display_offset();
1033f29dbc25Smrg    LXLeaveGraphics(pScrni);
1034f29dbc25Smrg}
1035f29dbc25Smrg
1036f29dbc25Smrgvoid
1037f29dbc25SmrgLXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1038f29dbc25Smrg{
1039f29dbc25Smrg    pScrn->PreInit = LXPreInit;
1040f29dbc25Smrg    pScrn->ScreenInit = LXScreenInit;
1041f29dbc25Smrg    pScrn->SwitchMode = LXSwitchMode;
1042f29dbc25Smrg    pScrn->AdjustFrame = LXAdjustFrame;
1043f29dbc25Smrg    pScrn->EnterVT = LXEnterVT;
1044f29dbc25Smrg    pScrn->LeaveVT = LXLeaveVT;
1045f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1046f29dbc25Smrg    pScrn->ValidMode = LXValidMode;
1047f29dbc25Smrg}
1048