lx_driver.c revision f29dbc25
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>
36f29dbc25Smrg
37f29dbc25Smrg#include "xf86.h"
38f29dbc25Smrg#include "xf86_OSproc.h"
39f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
40f29dbc25Smrg#include "xf86Resources.h"
41f29dbc25Smrg#endif
42f29dbc25Smrg#include "xf86i2c.h"
43f29dbc25Smrg#include "xf86Crtc.h"
44f29dbc25Smrg#include "xf86cmap.h"
45f29dbc25Smrg#include "compiler.h"
46f29dbc25Smrg#include "mipointer.h"
47f29dbc25Smrg#include "fb.h"
48f29dbc25Smrg#include "miscstruct.h"
49f29dbc25Smrg#include "micmap.h"
50f29dbc25Smrg#include "vbe.h"
51f29dbc25Smrg#include "fb.h"
52f29dbc25Smrg#include "cim_defs.h"
53f29dbc25Smrg#include "cim_regs.h"
54f29dbc25Smrg#include "geode.h"
55f29dbc25Smrg
56f29dbc25Smrg/* Bring in VGA functions */
57f29dbc25Smrg#include "lx_vga.c"
58f29dbc25Smrg
59f29dbc25Smrg#define LX_MAX_WIDTH  1940
60f29dbc25Smrg#define LX_MAX_HEIGHT 1600
61f29dbc25Smrg
62f29dbc25Smrg/* Size of the register blocks */
63f29dbc25Smrg
64f29dbc25Smrg#define LX_GP_REG_SIZE  0x4000
65f29dbc25Smrg#define LX_VG_REG_SIZE  0x4000
66f29dbc25Smrg#define LX_VID_REG_SIZE 0x4000
67f29dbc25Smrg#define LX_VIP_REG_SIZE 0x4000
68f29dbc25Smrg
69f29dbc25Smrg/* Size of the Cimarron command buffer */
70f29dbc25Smrg#define CIM_CMD_BFR_SZ 0x200000
71f29dbc25Smrg
72f29dbc25Smrgextern OptionInfoRec LX_GeodeOptions[];
73f29dbc25Smrg
74f29dbc25Smrgunsigned char *XpressROMPtr;
75f29dbc25Smrg
76f29dbc25Smrgstatic Bool
77f29dbc25SmrgLXSaveScreen(ScreenPtr pScrn, int mode)
78f29dbc25Smrg{
79f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
80f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
81f29dbc25Smrg
82f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
83f29dbc25Smrg	return vgaHWSaveScreen(pScrn, mode);
84f29dbc25Smrg
85f29dbc25Smrg    return TRUE;
86f29dbc25Smrg}
87f29dbc25Smrg
88f29dbc25Smrg/* This is an overly complex MSR read mechanism */
89f29dbc25Smrg
90f29dbc25Smrg/* From Cimarron - the VSAII read/write methods - we use these as fallback */
91f29dbc25Smrg
92f29dbc25Smrg#define LX_MSR_READ(adr,lo,hi)              \
93f29dbc25Smrg     __asm__ __volatile__(                      \
94f29dbc25Smrg        " mov $0x0AC1C, %%edx\n"                \
95f29dbc25Smrg        " mov $0xFC530007, %%eax\n"             \
96f29dbc25Smrg        " out %%eax,%%dx\n"                     \
97f29dbc25Smrg        " add $2,%%dl\n"                        \
98f29dbc25Smrg        " in %%dx, %%ax"                        \
99f29dbc25Smrg        : "=a" (lo), "=d" (hi)                  \
100f29dbc25Smrg        : "c" (adr))
101f29dbc25Smrg
102f29dbc25Smrg#define LX_MSR_WRITE(adr,low,high) \
103f29dbc25Smrg  { int d0, d1, d2, d3, d4;        \
104f29dbc25Smrg  __asm__ __volatile__(            \
105f29dbc25Smrg    " push %%ebx\n"                \
106f29dbc25Smrg    " mov $0x0AC1C, %%edx\n"       \
107f29dbc25Smrg    " mov $0xFC530007, %%eax\n"    \
108f29dbc25Smrg    " out %%eax,%%dx\n"            \
109f29dbc25Smrg    " add $2,%%dl\n"               \
110f29dbc25Smrg    " mov %6, %%ebx\n"             \
111f29dbc25Smrg    " mov %7, %0\n"                \
112f29dbc25Smrg    " mov %5, %3\n"                \
113f29dbc25Smrg    " xor %2, %2\n"                \
114f29dbc25Smrg    " xor %1, %1\n"                \
115f29dbc25Smrg    " out %%ax, %%dx\n"            \
116f29dbc25Smrg    " pop %%ebx\n"                 \
117f29dbc25Smrg    : "=a"(d0),"=&D"(d1),"=&S"(d2), \
118f29dbc25Smrg      "=c"(d3),"=d"(d4)  \
119f29dbc25Smrg    : "1"(adr),"2"(high),"3"(low)); \
120f29dbc25Smrg  }
121f29dbc25Smrg
122f29dbc25Smrgstatic void
123f29dbc25SmrgLXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi)
124f29dbc25Smrg{
125f29dbc25Smrg    if (GeodeReadMSR(addr, lo, hi) == -1) {
126f29dbc25Smrg	unsigned int l, h;
127f29dbc25Smrg
128f29dbc25Smrg	LX_MSR_READ(addr, l, h);
129f29dbc25Smrg	*lo = l;
130f29dbc25Smrg	*hi = h;
131f29dbc25Smrg    }
132f29dbc25Smrg}
133f29dbc25Smrg
134f29dbc25Smrgstatic void
135f29dbc25SmrgLXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi)
136f29dbc25Smrg{
137f29dbc25Smrg    if (GeodeWriteMSR(addr, lo, hi) == -1)
138f29dbc25Smrg	LX_MSR_WRITE(addr, lo, hi);
139f29dbc25Smrg}
140f29dbc25Smrg
141f29dbc25Smrgstatic unsigned int
142f29dbc25SmrgLXCalcPitch(ScrnInfoPtr pScrni)
143f29dbc25Smrg{
144f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
145f29dbc25Smrg
146f29dbc25Smrg    if (pGeode->tryCompression)
147f29dbc25Smrg	return
148f29dbc25Smrg	    GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
149f29dbc25Smrg    else
150f29dbc25Smrg	return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
151f29dbc25Smrg}
152f29dbc25Smrg
153f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
154f29dbc25Smrgstatic inline void *
155f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
156f29dbc25Smrg    struct pci_device *dev, int bar, int size)
157f29dbc25Smrg{
158f29dbc25Smrg    void *ptr;
159f29dbc25Smrg    void **result = (void **)&ptr;
160f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
161f29dbc25Smrg
162f29dbc25Smrg    int err = pci_device_map_range(dev,
163f29dbc25Smrg	dev->regions[bar].base_addr,
164f29dbc25Smrg	map_size,
165f29dbc25Smrg	PCI_DEV_MAP_FLAG_WRITABLE |
166f29dbc25Smrg	(vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
167f29dbc25Smrg	result);
168f29dbc25Smrg
169f29dbc25Smrg    if (err)
170f29dbc25Smrg	return NULL;
171f29dbc25Smrg    return ptr;
172f29dbc25Smrg}
173f29dbc25Smrg
174f29dbc25Smrgstatic inline int
175f29dbc25Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
176f29dbc25Smrg{
177f29dbc25Smrg    return pci_device_unmap_range(dev, ptr, size);
178f29dbc25Smrg}
179f29dbc25Smrg
180f29dbc25Smrg#endif
181f29dbc25Smrg
182f29dbc25Smrgstatic Bool
183f29dbc25SmrgLXMapMem(ScrnInfoPtr pScrni)
184f29dbc25Smrg{
185f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
186f29dbc25Smrg    int index = pScrni->scrnIndex;
187f29dbc25Smrg    unsigned long cmd_bfr_phys;
188f29dbc25Smrg
189f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
190f29dbc25Smrg
191f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
192f29dbc25Smrg    PCITAG tag;
193f29dbc25Smrg
194f29dbc25Smrg    tag = pciTag(pci->bus, pci->device, pci->func);
195f29dbc25Smrg
196f29dbc25Smrg    cim_gp_ptr = (unsigned char *)xf86MapPciMem(index, VIDMEM_MMIO,
197f29dbc25Smrg	tag, pci->memBase[1], LX_GP_REG_SIZE);
198f29dbc25Smrg
199f29dbc25Smrg    cim_vg_ptr = (unsigned char *)xf86MapPciMem(index, VIDMEM_MMIO,
200f29dbc25Smrg	tag, pci->memBase[2], LX_VG_REG_SIZE);
201f29dbc25Smrg
202f29dbc25Smrg    cim_vid_ptr = (unsigned char *)xf86MapPciMem(index, VIDMEM_MMIO,
203f29dbc25Smrg	tag, pci->memBase[3], LX_VID_REG_SIZE);
204f29dbc25Smrg
205f29dbc25Smrg    cim_vip_ptr = (unsigned char *)xf86MapPciMem(index, VIDMEM_MMIO,
206f29dbc25Smrg	tag, pci->memBase[4], LX_VIP_REG_SIZE);
207f29dbc25Smrg
208f29dbc25Smrg    cim_fb_ptr = (unsigned char *)xf86MapPciMem(index, VIDMEM_FRAMEBUFFER,
209f29dbc25Smrg	tag, pci->memBase[0], pGeode->FBAvail + CIM_CMD_BFR_SZ);
210f29dbc25Smrg#else
211f29dbc25Smrg    cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE);
212f29dbc25Smrg    cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE);
213f29dbc25Smrg    cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE);
214f29dbc25Smrg    cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE);
215f29dbc25Smrg    cim_fb_ptr =
216f29dbc25Smrg	map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ);
217f29dbc25Smrg#endif
218f29dbc25Smrg
219f29dbc25Smrg    if (pScrni->memPhysBase == 0)
220f29dbc25Smrg	pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM);
221f29dbc25Smrg
222f29dbc25Smrg    cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset;
223f29dbc25Smrg    cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset;
224f29dbc25Smrg
225f29dbc25Smrg    if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr ||
226f29dbc25Smrg	!cim_vip_ptr)
227f29dbc25Smrg	return FALSE;
228f29dbc25Smrg
229f29dbc25Smrg    gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM),
230f29dbc25Smrg	pGeode->FBAvail);
231f29dbc25Smrg    gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize);
232f29dbc25Smrg
233f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
234f29dbc25Smrg
235f29dbc25Smrg    pGeode->FBBase = cim_fb_ptr;
236f29dbc25Smrg
237f29dbc25Smrg    if (!pGeode->NoAccel)
238f29dbc25Smrg	pGeode->pExa->memoryBase = pGeode->FBBase;
239f29dbc25Smrg
240f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n",
241f29dbc25Smrg	pGeode->FBAvail, pGeode->FBBase);
242f29dbc25Smrg
243f29dbc25Smrg    return TRUE;
244f29dbc25Smrg}
245f29dbc25Smrg
246f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
247f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
248f29dbc25Smrg*/
249f29dbc25Smrg
250f29dbc25Smrgstatic Bool
251f29dbc25SmrgLXCheckVGA(ScrnInfoPtr pScrni)
252f29dbc25Smrg{
253f29dbc25Smrg
254f29dbc25Smrg    unsigned char *ptr;
255f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
256f29dbc25Smrg    int ret;
257f29dbc25Smrg
258f29dbc25Smrg    ptr =
259f29dbc25Smrg	xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
260f29dbc25Smrg	strlen(vgasig));
261f29dbc25Smrg
262f29dbc25Smrg    if (ptr == NULL)
263f29dbc25Smrg	return FALSE;
264f29dbc25Smrg
265f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
266f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
267f29dbc25Smrg
268f29dbc25Smrg    return ret ? FALSE : TRUE;
269f29dbc25Smrg}
270f29dbc25Smrg
271f29dbc25Smrgstatic Bool
272f29dbc25SmrgLXCrtcResize(ScrnInfoPtr pScrni, int width, int height)
273f29dbc25Smrg{
274f29dbc25Smrg    return TRUE;
275f29dbc25Smrg}
276f29dbc25Smrg
277f29dbc25Smrgstatic const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = {
278f29dbc25Smrg    LXCrtcResize,
279f29dbc25Smrg};
280f29dbc25Smrg
281f29dbc25Smrgstatic Bool
282f29dbc25SmrgLXPreInit(ScrnInfoPtr pScrni, int flags)
283f29dbc25Smrg{
284f29dbc25Smrg    GeodePtr pGeode;
285f29dbc25Smrg    EntityInfoPtr pEnt;
286f29dbc25Smrg    OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0];
287f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
288f29dbc25Smrg    char *s;
289f29dbc25Smrg
290f29dbc25Smrg    if (pScrni->numEntities != 1)
291f29dbc25Smrg	return FALSE;
292f29dbc25Smrg
293f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
294f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
295f29dbc25Smrg    if (pEnt->resources)
296f29dbc25Smrg	return FALSE;
297f29dbc25Smrg#endif
298f29dbc25Smrg    if (flags & PROBE_DETECT) {
299f29dbc25Smrg	GeodeProbeDDC(pScrni, pEnt->index);
300f29dbc25Smrg	return TRUE;
301f29dbc25Smrg    }
302f29dbc25Smrg
303f29dbc25Smrg    pGeode = pScrni->driverPrivate = xnfcalloc(sizeof(GeodeRec), 1);
304f29dbc25Smrg
305f29dbc25Smrg    if (pGeode == NULL)
306f29dbc25Smrg	return FALSE;
307f29dbc25Smrg
308f29dbc25Smrg    pGeode->useVGA = LXCheckVGA(pScrni);
309f29dbc25Smrg    pGeode->VGAActive = FALSE;
310f29dbc25Smrg    pGeode->pEnt = pEnt;
311f29dbc25Smrg
312f29dbc25Smrg    if (pGeode->useVGA) {
313f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
314f29dbc25Smrg	    pGeode->useVGA = FALSE;
315f29dbc25Smrg
316f29dbc25Smrg	pGeode->vesa = xcalloc(sizeof(VESARec), 1);
317f29dbc25Smrg    }
318f29dbc25Smrg
319f29dbc25Smrg    cim_rdmsr = LXReadMSR;
320f29dbc25Smrg    cim_wrmsr = LXWriteMSR;
321f29dbc25Smrg
322f29dbc25Smrg    /* Set up the Cimarron MSR tables */
323f29dbc25Smrg    msr_init_table();
324f29dbc25Smrg
325f29dbc25Smrg    /* By default, we support panel and CRT - the config file should
326f29dbc25Smrg     * disable the ones we don't want
327f29dbc25Smrg     */
328f29dbc25Smrg
329f29dbc25Smrg    pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT;
330f29dbc25Smrg
331f29dbc25Smrg    /* Fill in the monitor information */
332f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
333f29dbc25Smrg
334f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
335f29dbc25Smrg	return FALSE;
336f29dbc25Smrg
337f29dbc25Smrg    switch (pScrni->depth) {
338f29dbc25Smrg    case 8:
339f29dbc25Smrg	pScrni->rgbBits = 8;
340f29dbc25Smrg    case 16:
341f29dbc25Smrg    case 24:
342f29dbc25Smrg    case 32:
343f29dbc25Smrg	break;
344f29dbc25Smrg    default:
345f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
346f29dbc25Smrg	    "The driver does not support %d as a depth.\n", pScrni->depth);
347f29dbc25Smrg	return FALSE;
348f29dbc25Smrg    }
349f29dbc25Smrg
350f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
351f29dbc25Smrg
352f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
353f29dbc25Smrg	return FALSE;
354f29dbc25Smrg
355f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
356f29dbc25Smrg	return FALSE;
357f29dbc25Smrg
358f29dbc25Smrg    /*
359f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
360f29dbc25Smrg     * here.
361f29dbc25Smrg     */
362f29dbc25Smrg    {
363f29dbc25Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
364f29dbc25Smrg
365f29dbc25Smrg	if (!xf86SetGamma(pScrni, zeros)) {
366f29dbc25Smrg	    return FALSE;
367f29dbc25Smrg	}
368f29dbc25Smrg    }
369f29dbc25Smrg
370f29dbc25Smrg    pScrni->progClock = TRUE;
371f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
372f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
373f29dbc25Smrg
374f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
375f29dbc25Smrg
376f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
377f29dbc25Smrg    pGeode->tryCompression = TRUE;
378f29dbc25Smrg
379f29dbc25Smrg    /* Protect against old versions of EXA */
380f29dbc25Smrg
381f29dbc25Smrg#if (EXA_VERSION_MAJOR < 2)
382f29dbc25Smrg    pGeode->NoAccel = TRUE;
383f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
384f29dbc25Smrg	"*** This driver was compiled with EXA version %d\n");
385f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
386f29dbc25Smrg	"*** we need version 2 or greater\n");
387f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
388f29dbc25Smrg	"*** All accelerations are being turned off.\n");
389f29dbc25Smrg#else
390f29dbc25Smrg    pGeode->NoAccel = FALSE;
391f29dbc25Smrg#endif
392f29dbc25Smrg
393f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
394f29dbc25Smrg
395f29dbc25Smrg    xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR,
396f29dbc25Smrg	&pGeode->tryHWCursor);
397f29dbc25Smrg
398f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE,
399f29dbc25Smrg	    (int *)&(pGeode->FBAvail)))
400f29dbc25Smrg	pGeode->FBAvail = 0;
401f29dbc25Smrg
402f29dbc25Smrg    /* For compatability - allow SWCursor too */
403f29dbc25Smrg
404f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE))
405f29dbc25Smrg	pGeode->tryHWCursor = FALSE;
406f29dbc25Smrg
407f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE))
408f29dbc25Smrg	pGeode->tryCompression = FALSE;
409f29dbc25Smrg
410f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE))
411f29dbc25Smrg	pGeode->NoAccel = TRUE;
412f29dbc25Smrg
413f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
414f29dbc25Smrg
415f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) {
416f29dbc25Smrg
417f29dbc25Smrg	if (!xf86NameCmp(s, "LEFT"))
418f29dbc25Smrg	    pGeode->rotation = RR_Rotate_90;
419f29dbc25Smrg	else if (!xf86NameCmp(s, "INVERT"))
420f29dbc25Smrg	    pGeode->rotation = RR_Rotate_180;
421f29dbc25Smrg	else if (!xf86NameCmp(s, "CCW"))
422f29dbc25Smrg	    pGeode->rotation = RR_Rotate_270;
423f29dbc25Smrg	else
424f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
425f29dbc25Smrg		"Invalid rotation %s.\n", s);
426f29dbc25Smrg    }
427f29dbc25Smrg
428f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ,
429f29dbc25Smrg	(int *)&(pGeode->exaBfrSz));
430f29dbc25Smrg
431f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
432f29dbc25Smrg	pGeode->exaBfrSz = 0;
433f29dbc25Smrg
434f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL) {
435f29dbc25Smrg	if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE))
436f29dbc25Smrg	    pGeode->Output &= ~OUTPUT_PANEL;
437f29dbc25Smrg    }
438f29dbc25Smrg
439f29dbc25Smrg    /* Panel detection code -
440f29dbc25Smrg     * 1.  See if an OLPC DCON is attached - we can make some assumptions
441f29dbc25Smrg     * about the panel if so.
442f29dbc25Smrg     * 2.  Use panel mode specified in the config
443f29dbc25Smrg     * 3.  "Autodetect" the panel through VSA
444f29dbc25Smrg     */
445f29dbc25Smrg
446f29dbc25Smrg    if (dcon_init(pScrni)) {
447f29dbc25Smrg	pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON;
448f29dbc25Smrg    } else if (pGeode->Output & OUTPUT_PANEL) {
449f29dbc25Smrg	char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE);
450f29dbc25Smrg
451f29dbc25Smrg	if (pmode != NULL)
452f29dbc25Smrg	    pGeode->panelMode = LXGetManualPanelMode(pmode);
453f29dbc25Smrg
454f29dbc25Smrg	if (pGeode->panelMode == NULL)
455f29dbc25Smrg	    pGeode->panelMode = LXGetLegacyPanelMode();
456f29dbc25Smrg
457f29dbc25Smrg	if (pGeode->panelMode == NULL)
458f29dbc25Smrg	    pGeode->Output &= ~OUTPUT_PANEL;
459f29dbc25Smrg    }
460f29dbc25Smrg
461f29dbc25Smrg    /* Default to turn scaling on for panels */
462f29dbc25Smrg
463f29dbc25Smrg    if (pGeode->Output & OUTPUT_PANEL)
464f29dbc25Smrg	pGeode->Scale = TRUE;
465f29dbc25Smrg
466f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n");
467f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n",
468f29dbc25Smrg	pGeode->Output & OUTPUT_CRT ? "YES" : "NO");
469f29dbc25Smrg
470f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n",
471f29dbc25Smrg	pGeode->Output & OUTPUT_PANEL ? "YES" : "NO");
472f29dbc25Smrg
473f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n",
474f29dbc25Smrg	pGeode->Output & OUTPUT_DCON ? "YES" : "NO");
475f29dbc25Smrg
476f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n",
477f29dbc25Smrg	pGeode->useVGA ? "YES" : "NO");
478f29dbc25Smrg
479f29dbc25Smrg    /* Set up VGA */
480f29dbc25Smrg
481f29dbc25Smrg    if (pGeode->useVGA) {
482f29dbc25Smrg	VESARec *pVesa;
483f29dbc25Smrg
484f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "int10"))
485f29dbc25Smrg	    return FALSE;
486f29dbc25Smrg
487f29dbc25Smrg	pVesa = pGeode->vesa;
488f29dbc25Smrg
489f29dbc25Smrg	if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
490f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
491f29dbc25Smrg		"Unable to initialize 1NT10 support\n");
492f29dbc25Smrg	    pGeode->useVGA = FALSE;
493f29dbc25Smrg	}
494f29dbc25Smrg    }
495f29dbc25Smrg
496f29dbc25Smrg    /* Read the amount of framebuffer memory */
497f29dbc25Smrg    /* First try to read it from the framebuffer, and if that fails,
498f29dbc25Smrg     * do it the legacy way
499f29dbc25Smrg     */
500f29dbc25Smrg
501f29dbc25Smrg    if (pGeode->FBAvail == 0) {
502f29dbc25Smrg	if (GeodeGetSizeFromFB(&pGeode->FBAvail)) {
503f29dbc25Smrg	    unsigned long value;
504f29dbc25Smrg
505f29dbc25Smrg	    cim_outw(0xAC1C, 0xFC53);
506f29dbc25Smrg	    cim_outw(0xAC1C, 0x0200);
507f29dbc25Smrg
508f29dbc25Smrg	    value = (unsigned long)(cim_inw(0xAC1E)) & 0xFE;
509f29dbc25Smrg	    pGeode->FBAvail = value << 20;
510f29dbc25Smrg	}
511f29dbc25Smrg    }
512f29dbc25Smrg
513f29dbc25Smrg    pScrni->fbOffset = 0;
514f29dbc25Smrg
515f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
516f29dbc25Smrg	pScrni->videoRam = pGeode->FBAvail / 1024;
517f29dbc25Smrg    else {
518f29dbc25Smrg	pScrni->videoRam = pGeode->pEnt->device->videoRam;
519f29dbc25Smrg	pGeode->FBAvail = pScrni->videoRam << 10;
520f29dbc25Smrg    }
521f29dbc25Smrg
522f29dbc25Smrg    /* If we have <= 16Mb of memory then compression is going
523f29dbc25Smrg       to hurt - so warn and disable */
524f29dbc25Smrg
525f29dbc25Smrg    if (pGeode->tryCompression &&
526f29dbc25Smrg	pGeode->FBAvail <= 0x1000000) {
527f29dbc25Smrg    	xf86DrvMsg(pScrni->scrnIndex, X_INFO,
528f29dbc25Smrg	"%x bytes of video memory is less then optimal\n", pGeode->FBAvail);
529f29dbc25Smrg    	xf86DrvMsg(pScrni->scrnIndex, X_INFO,
530f29dbc25Smrg	"when compression is on. Disabling compression.\n");
531f29dbc25Smrg	pGeode->tryCompression = FALSE;
532f29dbc25Smrg    }
533f29dbc25Smrg
534f29dbc25Smrg    /* Carve out some memory for the command buffer */
535f29dbc25Smrg
536f29dbc25Smrg    pGeode->CmdBfrSize = CIM_CMD_BFR_SZ;
537f29dbc25Smrg    pGeode->FBAvail -= CIM_CMD_BFR_SZ;
538f29dbc25Smrg
539f29dbc25Smrg    pGeode->CmdBfrOffset = pGeode->FBAvail;
540f29dbc25Smrg
541f29dbc25Smrg    /* Allocate a a CRTC config structure */
542f29dbc25Smrg    xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs);
543f29dbc25Smrg
544f29dbc25Smrg    /* Set up the GPU CRTC */
545f29dbc25Smrg    LXSetupCrtc(pScrni);
546f29dbc25Smrg
547f29dbc25Smrg    xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT);
548f29dbc25Smrg
549f29dbc25Smrg    /* Setup the output */
550f29dbc25Smrg    LXSetupOutput(pScrni);
551f29dbc25Smrg
552f29dbc25Smrg    if (!xf86InitialConfiguration(pScrni, FALSE)) {
553f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n");
554f29dbc25Smrg	return FALSE;
555f29dbc25Smrg    }
556f29dbc25Smrg
557f29dbc25Smrg    xf86PrintModes(pScrni);
558f29dbc25Smrg
559f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
560f29dbc25Smrg
561f29dbc25Smrg    pGeode->Pitch = LXCalcPitch(pScrni);
562f29dbc25Smrg
563f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
564f29dbc25Smrg
565f29dbc25Smrg    /* Load the modules we'll need */
566f29dbc25Smrg
567f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
568f29dbc25Smrg	return FALSE;
569f29dbc25Smrg    }
570f29dbc25Smrg
571f29dbc25Smrg    if (!pGeode->NoAccel) {
572f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "exa"))
573f29dbc25Smrg	    return FALSE;
574f29dbc25Smrg    }
575f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
576f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
577f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
578f29dbc25Smrg	    "Couldn't register the resources.\n");
579f29dbc25Smrg	return FALSE;
580f29dbc25Smrg    }
581f29dbc25Smrg#endif
582f29dbc25Smrg    return TRUE;
583f29dbc25Smrg}
584f29dbc25Smrg
585f29dbc25Smrgstatic void
586f29dbc25SmrgLXRestore(ScrnInfoPtr pScrni)
587f29dbc25Smrg{
588f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
589f29dbc25Smrg
590f29dbc25Smrg    if (pGeode->useVGA) {
591f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
592f29dbc25Smrg
593f29dbc25Smrg	vgaHWProtect(pScrni, TRUE);
594f29dbc25Smrg	vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
595f29dbc25Smrg	vgaHWProtect(pScrni, FALSE);
596f29dbc25Smrg    }
597f29dbc25Smrg}
598f29dbc25Smrg
599f29dbc25Smrgstatic Bool
600f29dbc25SmrgLXUnmapMem(ScrnInfoPtr pScrni)
601f29dbc25Smrg{
602f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
603f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE);
604f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE);
605f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr,
606f29dbc25Smrg	LX_VID_REG_SIZE);
607f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr,
608f29dbc25Smrg	LX_VIP_REG_SIZE);
609f29dbc25Smrg#else
610f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
611f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
612f29dbc25Smrg
613f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE);
614f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE);
615f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE);
616f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE);
617f29dbc25Smrg    unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ);
618f29dbc25Smrg#endif
619f29dbc25Smrg
620f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000);
621f29dbc25Smrg
622f29dbc25Smrg    return TRUE;
623f29dbc25Smrg}
624f29dbc25Smrg
625f29dbc25Smrg/* These should be correctly accounted for rotation */
626f29dbc25Smrg
627f29dbc25Smrgvoid
628f29dbc25SmrgLXAdjustFrame(int scrnIndex, int x, int y, int flags)
629f29dbc25Smrg{
630f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
631f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
632f29dbc25Smrg
633f29dbc25Smrg    unsigned long offset;
634f29dbc25Smrg
635f29dbc25Smrg    offset = (y * pGeode->Pitch);
636f29dbc25Smrg    offset += x * (pScrni->bitsPerPixel >> 3);
637f29dbc25Smrg
638f29dbc25Smrg    vg_set_display_offset(offset);
639f29dbc25Smrg}
640f29dbc25Smrg
641f29dbc25Smrgstatic Bool
642f29dbc25SmrgLXSwitchMode(int index, DisplayModePtr pMode, int flags)
643f29dbc25Smrg{
644f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[index];
645f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
646f29dbc25Smrg
647f29dbc25Smrg    /* Set the new mode */
648f29dbc25Smrg    return xf86SetSingleMode(pScrni, pMode, pGeode->rotation);
649f29dbc25Smrg}
650f29dbc25Smrg
651f29dbc25Smrgstatic void
652f29dbc25SmrgLXLeaveGraphics(ScrnInfoPtr pScrni)
653f29dbc25Smrg{
654f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
655f29dbc25Smrg    VG_PANNING_COORDINATES panning;
656f29dbc25Smrg
657f29dbc25Smrg    gp_wait_until_idle();
658f29dbc25Smrg
659f29dbc25Smrg    vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode),
660f29dbc25Smrg	pGeode->FBcimdisplaytiming.wBpp);
661f29dbc25Smrg
662f29dbc25Smrg    vg_set_compression_enable(0);
663f29dbc25Smrg
664f29dbc25Smrg    /* Restore the previous Compression state */
665f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
666f29dbc25Smrg	vg_configure_compression(&(pGeode->FBCBData));
667f29dbc25Smrg	vg_set_compression_enable(1);
668f29dbc25Smrg    }
669f29dbc25Smrg
670f29dbc25Smrg    vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch);
671f29dbc25Smrg    vg_set_display_offset(pGeode->FBDisplayOffset);
672f29dbc25Smrg
673f29dbc25Smrg    /* Restore Cursor */
674f29dbc25Smrg    vg_set_cursor_position(pGeode->FBCursor.cursor_x,
675f29dbc25Smrg	pGeode->FBCursor.cursor_y, &panning);
676f29dbc25Smrg
677f29dbc25Smrg    LXRestore(pScrni);
678f29dbc25Smrg
679f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
680f29dbc25Smrg	pGeode->vesa->pInt->num = 0x10;
681f29dbc25Smrg	pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
682f29dbc25Smrg	pGeode->vesa->pInt->bx = 0;
683f29dbc25Smrg	xf86ExecX86int10(pGeode->vesa->pInt);
684f29dbc25Smrg	vg_delay_milliseconds(3);
685f29dbc25Smrg    }
686f29dbc25Smrg
687f29dbc25Smrg    pScrni->vtSema = FALSE;
688f29dbc25Smrg}
689f29dbc25Smrg
690f29dbc25Smrgstatic Bool
691f29dbc25SmrgLXCloseScreen(int scrnIndex, ScreenPtr pScrn)
692f29dbc25Smrg{
693f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
694f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
695f29dbc25Smrg
696f29dbc25Smrg    if (pScrni->vtSema)
697f29dbc25Smrg	LXLeaveGraphics(pScrni);
698f29dbc25Smrg
699f29dbc25Smrg    if (pGeode->pExa) {
700f29dbc25Smrg	exaDriverFini(pScrn);
701f29dbc25Smrg	xfree(pGeode->pExa);
702f29dbc25Smrg	pGeode->pExa = NULL;
703f29dbc25Smrg    }
704f29dbc25Smrg
705f29dbc25Smrg    /* Unmap the offscreen allocations */
706f29dbc25Smrg    GeodeCloseOffscreen(pScrni);
707f29dbc25Smrg
708f29dbc25Smrg    LXUnmapMem(pScrni);
709f29dbc25Smrg
710f29dbc25Smrg    if (pGeode->useVGA)
711f29dbc25Smrg	vgaHWUnmapMem(pScrni);
712f29dbc25Smrg
713f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
714f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
715f29dbc25Smrg
716f29dbc25Smrg    if (pScrn->CloseScreen)
717f29dbc25Smrg	return (*pScrn->CloseScreen) (scrnIndex, pScrn);
718f29dbc25Smrg
719f29dbc25Smrg    return TRUE;
720f29dbc25Smrg}
721f29dbc25Smrg
722f29dbc25Smrgstatic Bool
723f29dbc25SmrgLXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
724f29dbc25Smrg{
725f29dbc25Smrg    int bpp;
726f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
727f29dbc25Smrg
728f29dbc25Smrg    pGeode->VGAActive = gu3_get_vga_active();
729f29dbc25Smrg
730f29dbc25Smrg    gp_wait_until_idle();
731f29dbc25Smrg
732f29dbc25Smrg    vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode,
733f29dbc25Smrg	&bpp);
734f29dbc25Smrg
735f29dbc25Smrg    pGeode->FBcimdisplaytiming.wBpp = bpp;
736f29dbc25Smrg    pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch();
737f29dbc25Smrg
738f29dbc25Smrg    pGeode->FBDisplayOffset = vg_get_display_offset();
739f29dbc25Smrg
740f29dbc25Smrg    if (pGeode->useVGA && pGeode->VGAActive) {
741f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
742f29dbc25Smrg
743f29dbc25Smrg	pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
744f29dbc25Smrg    }
745f29dbc25Smrg
746f29dbc25Smrg    pGeode->FBCompressionEnable = vg_get_compression_enable();
747f29dbc25Smrg    vg_get_compression_info(&(pGeode->FBCBData));
748f29dbc25Smrg
749f29dbc25Smrg    /* Save Cursor offset */
750f29dbc25Smrg    vg_get_cursor_info(&pGeode->FBCursor);
751f29dbc25Smrg
752f29dbc25Smrg    /* Turn off the VGA */
753f29dbc25Smrg
754f29dbc25Smrg    if (pGeode->useVGA) {
755f29dbc25Smrg	unsigned short sequencer;
756f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
757f29dbc25Smrg
758f29dbc25Smrg	/* Unlock VGA registers */
759f29dbc25Smrg	vgaHWUnlock(pvgaHW);
760f29dbc25Smrg
761f29dbc25Smrg	/* Save the current state and setup the current mode */
762f29dbc25Smrg	vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
763f29dbc25Smrg
764f29dbc25Smrg	/* DISABLE VGA SEQUENCER */
765f29dbc25Smrg	/* This allows the VGA state machine to terminate. We must delay */
766f29dbc25Smrg	/* such that there are no pending MBUS requests.  */
767f29dbc25Smrg
768f29dbc25Smrg	cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE);
769f29dbc25Smrg	sequencer = cim_inb(DC3_SEQUENCER_DATA);
770f29dbc25Smrg	sequencer |= DC3_CLK_MODE_SCREEN_OFF;
771f29dbc25Smrg	cim_outb(DC3_SEQUENCER_DATA, sequencer);
772f29dbc25Smrg
773f29dbc25Smrg	vg_delay_milliseconds(1);
774f29dbc25Smrg
775f29dbc25Smrg	/* BLANK THE VGA DISPLAY */
776f29dbc25Smrg	cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET);
777f29dbc25Smrg	sequencer = cim_inb(DC3_SEQUENCER_DATA);
778f29dbc25Smrg	sequencer &= ~DC3_RESET_VGA_DISP_ENABLE;
779f29dbc25Smrg	cim_outb(DC3_SEQUENCER_DATA, sequencer);
780f29dbc25Smrg
781f29dbc25Smrg	vg_delay_milliseconds(1);
782f29dbc25Smrg    }
783f29dbc25Smrg
784f29dbc25Smrg    /* Clear the framebuffer */
785f29dbc25Smrg    memset(pGeode->FBBase, 0, pGeode->displaySize);
786f29dbc25Smrg
787f29dbc25Smrg    /* Set the modes */
788f29dbc25Smrg    if (!xf86SetDesiredModes(pScrni))
789f29dbc25Smrg	return FALSE;
790f29dbc25Smrg
791f29dbc25Smrg    pScrni->vtSema = TRUE;
792f29dbc25Smrg
793f29dbc25Smrg    return TRUE;
794f29dbc25Smrg}
795f29dbc25Smrg
796f29dbc25Smrgstatic void
797f29dbc25SmrgLXLoadPalette(ScrnInfoPtr pScrni,
798f29dbc25Smrg    int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
799f29dbc25Smrg{
800f29dbc25Smrg    int i, index, color;
801f29dbc25Smrg
802f29dbc25Smrg    for (i = 0; i < numColors; i++) {
803f29dbc25Smrg	index = indizes[i] & 0xFF;
804f29dbc25Smrg	color = (((unsigned long)(colors[index].red & 0xFF)) << 16) |
805f29dbc25Smrg	    (((unsigned long)(colors[index].green & 0xFF)) << 8) |
806f29dbc25Smrg	    ((unsigned long)(colors[index].blue & 0xFF));
807f29dbc25Smrg
808f29dbc25Smrg	vg_set_display_palette_entry(index, color);
809f29dbc25Smrg    }
810f29dbc25Smrg}
811f29dbc25Smrg
812f29dbc25Smrgstatic Bool
813f29dbc25SmrgLXScreenInit(int scrnIndex, ScreenPtr pScrn, int argc, char **argv)
814f29dbc25Smrg{
815f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
816f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
817f29dbc25Smrg    int ret;
818f29dbc25Smrg    unsigned int dwidth;
819f29dbc25Smrg
820f29dbc25Smrg    pGeode->starting = TRUE;
821f29dbc25Smrg
822f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
823f29dbc25Smrg
824f29dbc25Smrg    if (pGeode->useVGA) {
825f29dbc25Smrg
826f29dbc25Smrg	if (!vgaHWMapMem(pScrni))
827f29dbc25Smrg	    return FALSE;
828f29dbc25Smrg
829f29dbc25Smrg	vgaHWGetIOBase(VGAHWPTR(pScrni));
830f29dbc25Smrg    }
831f29dbc25Smrg
832f29dbc25Smrg    if (!pGeode->NoAccel) {
833f29dbc25Smrg
834f29dbc25Smrg	pGeode->pExa = exaDriverAlloc();
835f29dbc25Smrg
836f29dbc25Smrg	if (pGeode->pExa) {
837f29dbc25Smrg
838f29dbc25Smrg	    pGeode->pExa->memoryBase = 0;
839f29dbc25Smrg	    pGeode->pExa->memorySize = 0;
840f29dbc25Smrg
841f29dbc25Smrg	    pGeode->pExa->pixmapOffsetAlign = 32;
842f29dbc25Smrg	    pGeode->pExa->pixmapPitchAlign = 32;
843f29dbc25Smrg	    pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS;
844f29dbc25Smrg	    pGeode->pExa->maxX = LX_MAX_WIDTH - 1;
845f29dbc25Smrg	    pGeode->pExa->maxY = LX_MAX_HEIGHT - 1;
846f29dbc25Smrg	} else {
847f29dbc25Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
848f29dbc25Smrg		"Couldn't allocate the EXA structure.\n");
849f29dbc25Smrg	    pGeode->NoAccel = TRUE;
850f29dbc25Smrg	}
851f29dbc25Smrg    }
852f29dbc25Smrg
853f29dbc25Smrg    /* Map the memory here before doing anything else */
854f29dbc25Smrg
855f29dbc25Smrg    if (!LXMapMem(pScrni))
856f29dbc25Smrg	return FALSE;
857f29dbc25Smrg
858f29dbc25Smrg    LXInitOffscreen(pScrni);
859f29dbc25Smrg
860f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
861f29dbc25Smrg    if (!LXEnterGraphics(pScrn, pScrni))
862f29dbc25Smrg	return FALSE;
863f29dbc25Smrg
864f29dbc25Smrg    miClearVisualTypes();
865f29dbc25Smrg
866f29dbc25Smrg    /* XXX Again - take down anything? */
867f29dbc25Smrg
868f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
869f29dbc25Smrg	if (!miSetVisualTypes(pScrni->depth,
870f29dbc25Smrg		TrueColorMask, pScrni->rgbBits, pScrni->defaultVisual)) {
871f29dbc25Smrg	    return FALSE;
872f29dbc25Smrg	}
873f29dbc25Smrg    } else {
874f29dbc25Smrg	if (!miSetVisualTypes(pScrni->depth,
875f29dbc25Smrg		miGetDefaultVisualMask(pScrni->depth),
876f29dbc25Smrg		pScrni->rgbBits, pScrni->defaultVisual)) {
877f29dbc25Smrg	    return FALSE;
878f29dbc25Smrg	}
879f29dbc25Smrg    }
880f29dbc25Smrg
881f29dbc25Smrg    miSetPixmapDepths();
882f29dbc25Smrg
883f29dbc25Smrg    if (pScrni->virtualX > pScrni->displayWidth)
884f29dbc25Smrg	pScrni->displayWidth = pScrni->virtualX;
885f29dbc25Smrg
886f29dbc25Smrg    /* Point at the visible area to start */
887f29dbc25Smrg
888f29dbc25Smrg    /* fbScreenInit assumes that the stride is display width *
889f29dbc25Smrg     * bytes per pixel.  If compression is on, then our stride might
890f29dbc25Smrg     * be completely different, so we divide the pitch by the
891f29dbc25Smrg     * bytes per pixel to fake fbScreenInit into doing the right thing */
892f29dbc25Smrg
893f29dbc25Smrg    dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
894f29dbc25Smrg
895f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase,
896f29dbc25Smrg	pScrni->virtualX, pScrni->virtualY,
897f29dbc25Smrg	pScrni->xDpi, pScrni->yDpi, dwidth, pScrni->bitsPerPixel);
898f29dbc25Smrg
899f29dbc25Smrg    if (!ret)
900f29dbc25Smrg	return FALSE;
901f29dbc25Smrg
902f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
903f29dbc25Smrg
904f29dbc25Smrg    /* Set up the color ordering */
905f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
906f29dbc25Smrg	VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
907f29dbc25Smrg
908f29dbc25Smrg	while (--visual >= pScrn->visuals) {
909f29dbc25Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
910f29dbc25Smrg		visual->offsetRed = pScrni->offset.red;
911f29dbc25Smrg		visual->offsetGreen = pScrni->offset.green;
912f29dbc25Smrg		visual->offsetBlue = pScrni->offset.blue;
913f29dbc25Smrg		visual->redMask = pScrni->mask.red;
914f29dbc25Smrg		visual->greenMask = pScrni->mask.green;
915f29dbc25Smrg		visual->blueMask = pScrni->mask.blue;
916f29dbc25Smrg	    }
917f29dbc25Smrg	}
918f29dbc25Smrg    }
919f29dbc25Smrg
920f29dbc25Smrg    /* Must follow the color ordering */
921f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
922f29dbc25Smrg
923f29dbc25Smrg    if (!pGeode->NoAccel)
924f29dbc25Smrg	pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE;
925f29dbc25Smrg
926f29dbc25Smrg    miInitializeBackingStore(pScrn);
927f29dbc25Smrg    xf86SetBackingStore(pScrn);
928f29dbc25Smrg
929f29dbc25Smrg    /* Set up the soft cursor */
930f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
931f29dbc25Smrg
932f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
933f29dbc25Smrg
934f29dbc25Smrg    if (pGeode->tryHWCursor) {
935f29dbc25Smrg	if (!LXCursorInit(pScrn))
936f29dbc25Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
937f29dbc25Smrg		"Hardware cursor initialization failed.\n");
938f29dbc25Smrg    }
939f29dbc25Smrg
940f29dbc25Smrg    /* Set up the color map */
941f29dbc25Smrg
942f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
943f29dbc25Smrg	return FALSE;
944f29dbc25Smrg
945f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
946f29dbc25Smrg	/* Must follow initialization of the default colormap */
947f29dbc25Smrg
948f29dbc25Smrg	if (!xf86HandleColormaps(pScrn, 256, 8,
949f29dbc25Smrg		LXLoadPalette, NULL,
950f29dbc25Smrg		CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) {
951f29dbc25Smrg	    return FALSE;
952f29dbc25Smrg	}
953f29dbc25Smrg    }
954f29dbc25Smrg    xf86DPMSInit(pScrn, xf86DPMSSet, 0);
955f29dbc25Smrg
956f29dbc25Smrg    LXInitVideo(pScrn);
957f29dbc25Smrg
958f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
959f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
960f29dbc25Smrg
961f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
962f29dbc25Smrg    pScrn->CloseScreen = LXCloseScreen;
963f29dbc25Smrg    pScrn->SaveScreen = LXSaveScreen;
964f29dbc25Smrg
965f29dbc25Smrg    if (!xf86CrtcScreenInit(pScrn)) {
966f29dbc25Smrg	xf86DrvMsg(scrnIndex, X_ERROR, "CRTCScreenInit failed.\n");
967f29dbc25Smrg	return FALSE;
968f29dbc25Smrg    }
969f29dbc25Smrg
970f29dbc25Smrg    if (serverGeneration == 1)
971f29dbc25Smrg	xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
972f29dbc25Smrg
973f29dbc25Smrg    pGeode->starting = FALSE;
974f29dbc25Smrg
975f29dbc25Smrg    return TRUE;
976f29dbc25Smrg}
977f29dbc25Smrg
978f29dbc25Smrgstatic int
979f29dbc25SmrgLXValidMode(int scrnIndex, DisplayModePtr pMode, Bool Verbose, int flags)
980f29dbc25Smrg{
981f29dbc25Smrg    return MODE_OK;
982f29dbc25Smrg}
983f29dbc25Smrg
984f29dbc25Smrgstatic Bool
985f29dbc25SmrgLXEnterVT(int scrnIndex, int flags)
986f29dbc25Smrg{
987f29dbc25Smrg    return LXEnterGraphics(NULL, xf86Screens[scrnIndex]);
988f29dbc25Smrg}
989f29dbc25Smrg
990f29dbc25Smrgstatic void
991f29dbc25SmrgLXLeaveVT(int scrnIndex, int flags)
992f29dbc25Smrg{
993f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
994f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
995f29dbc25Smrg
996f29dbc25Smrg    pGeode->PrevDisplayOffset = vg_get_display_offset();
997f29dbc25Smrg    LXLeaveGraphics(pScrni);
998f29dbc25Smrg}
999f29dbc25Smrg
1000f29dbc25Smrgvoid
1001f29dbc25SmrgLXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1002f29dbc25Smrg{
1003f29dbc25Smrg    pScrn->PreInit = LXPreInit;
1004f29dbc25Smrg    pScrn->ScreenInit = LXScreenInit;
1005f29dbc25Smrg    pScrn->SwitchMode = LXSwitchMode;
1006f29dbc25Smrg    pScrn->AdjustFrame = LXAdjustFrame;
1007f29dbc25Smrg    pScrn->EnterVT = LXEnterVT;
1008f29dbc25Smrg    pScrn->LeaveVT = LXLeaveVT;
1009f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1010f29dbc25Smrg    pScrn->ValidMode = LXValidMode;
1011f29dbc25Smrg}
1012