gx_driver.c revision f29dbc25
1f29dbc25Smrg/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Portioned modeled from xf86-video-intel/src/i830_driver.c
4f29dbc25Smrg * Copyright 2001 VA Linux Systems Inc., Fremont, California.
5f29dbc25Smrg * Copyright \ufffd 2002 by David Dawes
6f29dbc25Smrg
7f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
8f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
9f29dbc25Smrg * deal in the Software without restriction, including without limitation the
10f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
12f29dbc25Smrg * furnished to do so, subject to the following conditions:
13f29dbc25Smrg *
14f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
15f29dbc25Smrg * all copies or substantial portions of the Software.
16f29dbc25Smrg *
17f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23f29dbc25Smrg * IN THE SOFTWARE.
24f29dbc25Smrg *
25f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
26f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
27f29dbc25Smrg * software without specific prior written permission.
28f29dbc25Smrg */
29f29dbc25Smrg
30f29dbc25Smrg#ifdef HAVE_CONFIG_H
31f29dbc25Smrg#include "config.h"
32f29dbc25Smrg#endif
33f29dbc25Smrg
34f29dbc25Smrg#include <stdio.h>
35f29dbc25Smrg
36f29dbc25Smrg#include "xf86.h"
37f29dbc25Smrg#include "xf86_OSproc.h"
38f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
39f29dbc25Smrg#include "xf86Resources.h"
40f29dbc25Smrg#endif
41f29dbc25Smrg#include "xf86cmap.h"
42f29dbc25Smrg#include "compiler.h"
43f29dbc25Smrg#include "mipointer.h"
44f29dbc25Smrg#include "shadow.h"
45f29dbc25Smrg#include <X11/extensions/randr.h>
46f29dbc25Smrg#include "fb.h"
47f29dbc25Smrg#include "miscstruct.h"
48f29dbc25Smrg#include "micmap.h"
49f29dbc25Smrg#include "vbe.h"
50f29dbc25Smrg#include "fb.h"
51f29dbc25Smrg#include "randrstr.h"
52f29dbc25Smrg
53f29dbc25Smrg#include "geode.h"
54f29dbc25Smrg#include "gfx_defs.h"
55f29dbc25Smrg#include "gfx_regs.h"
56f29dbc25Smrg#include "panel.h"
57f29dbc25Smrg
58f29dbc25Smrg/* Bring in VGA functions */
59f29dbc25Smrg#include "gx_vga.c"
60f29dbc25Smrg
61f29dbc25Smrg#define GX_MIN_PITCH 1024
62f29dbc25Smrg#define GX_MAX_PITCH 8192
63f29dbc25Smrg#define GX_MAX_WIDTH  1600
64f29dbc25Smrg#define GX_MIN_HEIGHT  400
65f29dbc25Smrg#define GX_MAX_HEIGHT 1200
66f29dbc25Smrg#define GX_CB_PITCH   544
67f29dbc25Smrg#define GX_CB_SIZE    544
68f29dbc25Smrg
69f29dbc25Smrg#define GX_CPU_REG_SIZE 0x4000
70f29dbc25Smrg#define GX_GP_REG_SIZE  0x4000
71f29dbc25Smrg#define GX_VID_REG_SIZE 0x4000
72f29dbc25Smrg
73f29dbc25Smrg#define DEFAULT_IMG_LINE_BUFS 20
74f29dbc25Smrg#define DEFAULT_CLR_LINE_BUFS 20
75f29dbc25Smrg
76f29dbc25Smrgextern OptionInfoRec GX_GeodeOptions[];
77f29dbc25Smrg
78f29dbc25Smrgunsigned char *XpressROMPtr;
79f29dbc25Smrg
80f29dbc25Smrgstatic inline void
81f29dbc25Smrggx_enable_dac_power(void)
82f29dbc25Smrg{
83f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
84f29dbc25Smrg	gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH);
85f29dbc25Smrg}
86f29dbc25Smrg
87f29dbc25Smrgstatic inline void
88f29dbc25Smrggx_disable_dac_power(void)
89f29dbc25Smrg{
90f29dbc25Smrg    gfx_write_vid32(RCDF_VID_MISC,
91f29dbc25Smrg	RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN |
92f29dbc25Smrg	(gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH));
93f29dbc25Smrg}
94f29dbc25Smrg
95f29dbc25Smrgstatic void
96f29dbc25SmrgGXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
97f29dbc25Smrg{
98f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
99f29dbc25Smrg
100f29dbc25Smrg    if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) {
101f29dbc25Smrg	pGeode->exaBfrOffset = *offset;
102f29dbc25Smrg	*offset += pGeode->exaBfrOffset;
103f29dbc25Smrg	*avail -= pGeode->exaBfrOffset;
104f29dbc25Smrg    }
105f29dbc25Smrg}
106f29dbc25Smrg
107f29dbc25Smrgstatic void
108f29dbc25SmrgGXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
109f29dbc25Smrg{
110f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
111f29dbc25Smrg    unsigned int size, i, pitch;
112f29dbc25Smrg
113f29dbc25Smrg    /* XXX - FIXME - What if we are out of room?  Then what? */
114f29dbc25Smrg    /* For now, we NULL them all out.                        */
115f29dbc25Smrg
116f29dbc25Smrg    if (pGeode->NoOfImgBuffers > 0) {
117f29dbc25Smrg	size = pGeode->displayPitch * pGeode->NoOfImgBuffers;
118f29dbc25Smrg	if (size <= *avail) {
119f29dbc25Smrg	    for (i = 0; i < pGeode->NoOfImgBuffers; i++) {
120f29dbc25Smrg		pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset;
121f29dbc25Smrg		*offset += pGeode->displayPitch;
122f29dbc25Smrg		*avail -= pGeode->displayPitch;
123f29dbc25Smrg	    }
124f29dbc25Smrg	} else {
125f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
126f29dbc25Smrg		"Not enough memory for image write buffers.\n");
127f29dbc25Smrg
128f29dbc25Smrg	    for (i = 0; i < pGeode->NoOfImgBuffers; i++)
129f29dbc25Smrg		pGeode->AccelImageWriteBuffers[i] = NULL;
130f29dbc25Smrg	}
131f29dbc25Smrg    }
132f29dbc25Smrg
133f29dbc25Smrg    if (pGeode->NoOfColorExpandLines > 0) {
134f29dbc25Smrg	pitch = ((pGeode->displayPitch + 31) >> 5) << 2;
135f29dbc25Smrg	size = pitch * pGeode->NoOfColorExpandLines;
136f29dbc25Smrg
137f29dbc25Smrg	if (size <= *avail) {
138f29dbc25Smrg	    for (i = 0; i < pGeode->NoOfColorExpandLines; i++) {
139f29dbc25Smrg		pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset;
140f29dbc25Smrg		*offset += pitch;
141f29dbc25Smrg		*avail -= pitch;
142f29dbc25Smrg	    }
143f29dbc25Smrg	} else {
144f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
145f29dbc25Smrg		"Not enough memory for color expansion buffers.\n");
146f29dbc25Smrg
147f29dbc25Smrg	    for (i = 0; i < pGeode->NoOfImgBuffers; i++)
148f29dbc25Smrg		pGeode->AccelColorExpandBuffers[i] = NULL;
149f29dbc25Smrg	}
150f29dbc25Smrg    }
151f29dbc25Smrg}
152f29dbc25Smrg
153f29dbc25Smrgstatic Bool
154f29dbc25SmrgGXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate)
155f29dbc25Smrg{
156f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
157f29dbc25Smrg
158f29dbc25Smrg    unsigned int fboffset, fbavail;
159f29dbc25Smrg    unsigned int size;
160f29dbc25Smrg    unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8;
161f29dbc25Smrg    BOOL ret = TRUE;
162f29dbc25Smrg
163f29dbc25Smrg    if (pGeode->tryCompression)
164f29dbc25Smrg	pGeode->displayPitch =
165f29dbc25Smrg	    GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
166f29dbc25Smrg    else
167f29dbc25Smrg	pGeode->displayPitch =
168f29dbc25Smrg	    ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
169f29dbc25Smrg
170f29dbc25Smrg    pGeode->Pitch = pGeode->displayPitch;
171f29dbc25Smrg    pGeode->displayWidth = pGeode->displayPitch / bytpp;
172f29dbc25Smrg    pScrni->displayWidth = pGeode->displayWidth;
173f29dbc25Smrg
174f29dbc25Smrg    fbavail = pGeode->FBAvail - 0x4000;
175f29dbc25Smrg
176f29dbc25Smrg    pGeode->displayOffset = fboffset = 0;
177f29dbc25Smrg    pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch;
178f29dbc25Smrg
179f29dbc25Smrg    fbavail -= pGeode->displaySize;
180f29dbc25Smrg    fboffset += pGeode->displaySize;
181f29dbc25Smrg
182f29dbc25Smrg    if (pGeode->tryCompression) {
183f29dbc25Smrg	size = pScrni->virtualY * GX_CB_PITCH;
184f29dbc25Smrg
185f29dbc25Smrg	if (size <= fbavail) {
186f29dbc25Smrg	    pGeode->CBData.compression_offset = fboffset;
187f29dbc25Smrg
188f29dbc25Smrg	    fboffset += size;
189f29dbc25Smrg	    fbavail -= size;
190f29dbc25Smrg
191f29dbc25Smrg	    pGeode->Compression = TRUE;
192f29dbc25Smrg	} else {
193f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
194f29dbc25Smrg		"Not enough memory for compression\n");
195f29dbc25Smrg	    pGeode->Compression = FALSE;
196f29dbc25Smrg	}
197f29dbc25Smrg    }
198f29dbc25Smrg
199f29dbc25Smrg    if (pGeode->tryHWCursor) {
200f29dbc25Smrg
201f29dbc25Smrg	if (fbavail >= 1024) {
202f29dbc25Smrg	    pGeode->CursorStartOffset = fboffset;
203f29dbc25Smrg	    fboffset += 1024;
204f29dbc25Smrg	    fbavail -= 1024;
205f29dbc25Smrg	    pGeode->HWCursor = TRUE;
206f29dbc25Smrg	} else {
207f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
208f29dbc25Smrg		"Not enough memory for the hardware cursor\n");
209f29dbc25Smrg	    pGeode->HWCursor = FALSE;
210f29dbc25Smrg	}
211f29dbc25Smrg    }
212f29dbc25Smrg
213f29dbc25Smrg    if (!pGeode->NoAccel) {
214f29dbc25Smrg	if (pGeode->useEXA)
215f29dbc25Smrg	    GXInitEXAMemory(pScrni, &fboffset, &fbavail);
216f29dbc25Smrg	else
217f29dbc25Smrg	    GXInitXAAMemory(pScrni, &fboffset, &fbavail);
218f29dbc25Smrg    }
219f29dbc25Smrg
220f29dbc25Smrg    pGeode->shadowSize = 0;
221f29dbc25Smrg
222f29dbc25Smrg    if (rotate != RR_Rotate_0) {
223f29dbc25Smrg	if (rotate & (RR_Rotate_90 | RR_Rotate_270))
224f29dbc25Smrg	    size = pGeode->displayPitch * pScrni->virtualX;
225f29dbc25Smrg	else
226f29dbc25Smrg	    size = pGeode->displayPitch * pScrni->virtualY;
227f29dbc25Smrg
228f29dbc25Smrg	if (size <= fbavail) {
229f29dbc25Smrg	    pGeode->shadowOffset = fboffset;
230f29dbc25Smrg	    pGeode->shadowSize = size;
231f29dbc25Smrg
232f29dbc25Smrg	    fboffset += size;
233f29dbc25Smrg	    fbavail -= size;
234f29dbc25Smrg	} else {
235f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
236f29dbc25Smrg		"Not enough memory for the shadow framebuffer\n");
237f29dbc25Smrg	    ret = FALSE;
238f29dbc25Smrg	}
239f29dbc25Smrg    }
240f29dbc25Smrg
241f29dbc25Smrg    /* XAA always exists - we can't remove it on demand like we can with EXA.
242f29dbc25Smrg     * So we assume the worse, and only give XAA enough offspace room to
243f29dbc25Smrg     * account for any eventuality that RandR might throw at us. */
244f29dbc25Smrg
245f29dbc25Smrg    if (!pGeode->NoAccel) {
246f29dbc25Smrg
247f29dbc25Smrg	if (pGeode->useEXA && pGeode->pExa) {
248f29dbc25Smrg	    ExaDriverPtr pExa = pGeode->pExa;
249f29dbc25Smrg
250f29dbc25Smrg	    pExa->offScreenBase = fboffset;
251f29dbc25Smrg	    pExa->memorySize = fboffset + fbavail;
252f29dbc25Smrg	}
253f29dbc25Smrg
254f29dbc25Smrg	if (!pGeode->useEXA) {
255f29dbc25Smrg
256f29dbc25Smrg	    if (!xf86FBManagerRunning(pScrn)) {
257f29dbc25Smrg
258f29dbc25Smrg		unsigned int offset = fboffset;
259f29dbc25Smrg		unsigned int avail = fbavail;
260f29dbc25Smrg		RegionRec OffscreenRegion;
261f29dbc25Smrg		BoxRec AvailBox;
262f29dbc25Smrg
263f29dbc25Smrg		/* Assume the shadow FB exists even if it doesnt */
264f29dbc25Smrg
265f29dbc25Smrg		if (pGeode->shadowSize == 0) {
266f29dbc25Smrg		    size = (pScrn->width * bytpp) * pScrni->virtualX;
267f29dbc25Smrg		    offset += size;
268f29dbc25Smrg		    avail -= size;
269f29dbc25Smrg		}
270f29dbc25Smrg
271f29dbc25Smrg		AvailBox.x1 = 0;
272f29dbc25Smrg		AvailBox.y1 =
273f29dbc25Smrg		    (offset + pGeode->displayPitch -
274f29dbc25Smrg		    1) / pGeode->displayPitch;
275f29dbc25Smrg
276f29dbc25Smrg		AvailBox.x2 = pGeode->displayWidth;
277f29dbc25Smrg		AvailBox.y2 = (offset + avail) / pGeode->displayPitch;
278f29dbc25Smrg
279f29dbc25Smrg		if (AvailBox.y1 < AvailBox.y2) {
280f29dbc25Smrg		    REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2);
281f29dbc25Smrg
282f29dbc25Smrg		    if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion))
283f29dbc25Smrg			xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
284f29dbc25Smrg			    "Memory manager initialization failed.\n");
285f29dbc25Smrg
286f29dbc25Smrg		    REGION_UNINIT(pScrn, &OffscreenRegion);
287f29dbc25Smrg		} else
288f29dbc25Smrg		    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
289f29dbc25Smrg			"Cache disabled - no offscreen memory available.\n");
290f29dbc25Smrg	    } else
291f29dbc25Smrg		xf86DrvMsg(pScrni->scrnIndex, X_INFO,
292f29dbc25Smrg		    "XAA offscreen memory has already been allocated.\n");
293f29dbc25Smrg	}
294f29dbc25Smrg    }
295f29dbc25Smrg    return ret;
296f29dbc25Smrg}
297f29dbc25Smrg
298f29dbc25Smrgstatic Bool
299f29dbc25SmrgGXSaveScreen(ScreenPtr pScrn, int mode)
300f29dbc25Smrg{
301f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
302f29dbc25Smrg    GeodePtr pGeode = GEODEPTR(pScrni);
303f29dbc25Smrg
304f29dbc25Smrg    if (pGeode->useVGA && !pScrni->vtSema)
305f29dbc25Smrg	return vgaHWSaveScreen(pScrn, mode);
306f29dbc25Smrg
307f29dbc25Smrg    return TRUE;
308f29dbc25Smrg}
309f29dbc25Smrg
310f29dbc25Smrg/* Common function - used by the LX too */
311f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS
312f29dbc25Smrgstatic inline void *
313f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram,
314f29dbc25Smrg    struct pci_device *dev, int bar, int size)
315f29dbc25Smrg{
316f29dbc25Smrg    void *ptr;
317f29dbc25Smrg    void **result = (void **)&ptr;
318f29dbc25Smrg    int map_size = size ? size : dev->regions[bar].size;
319f29dbc25Smrg
320f29dbc25Smrg    int err = pci_device_map_range(dev,
321f29dbc25Smrg	dev->regions[bar].base_addr,
322f29dbc25Smrg	map_size,
323f29dbc25Smrg	PCI_DEV_MAP_FLAG_WRITABLE |
324f29dbc25Smrg	(vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
325f29dbc25Smrg	result);
326f29dbc25Smrg
327f29dbc25Smrg    if (err)
328f29dbc25Smrg	return NULL;
329f29dbc25Smrg    return ptr;
330f29dbc25Smrg}
331f29dbc25Smrg#endif
332f29dbc25Smrg
333f29dbc25Smrgextern unsigned long gfx_gx2_scratch_base;
334f29dbc25Smrg
335f29dbc25Smrgstatic Bool
336f29dbc25SmrgGXMapMem(ScrnInfoPtr pScrni)
337f29dbc25Smrg{
338f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
339f29dbc25Smrg    int index = pScrni->scrnIndex;
340f29dbc25Smrg
341f29dbc25Smrg    pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
342f29dbc25Smrg
343f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
344f29dbc25Smrg    gfx_virt_regptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
345f29dbc25Smrg	pci->memBase[2], pci->size[2]);
346f29dbc25Smrg
347f29dbc25Smrg    gfx_virt_gpptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
348f29dbc25Smrg	pci->memBase[1], pci->size[1]);
349f29dbc25Smrg
350f29dbc25Smrg    gfx_virt_vidptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
351f29dbc25Smrg	pci->memBase[3], pci->size[3]);
352f29dbc25Smrg
353f29dbc25Smrg    gfx_virt_fbptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_FRAMEBUFFER,
354f29dbc25Smrg	pci->memBase[0], pGeode->FBAvail);
355f29dbc25Smrg#else
356f29dbc25Smrg    gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0);
357f29dbc25Smrg    gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0);
358f29dbc25Smrg    gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0);
359f29dbc25Smrg    gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail);
360f29dbc25Smrg#endif
361f29dbc25Smrg
362f29dbc25Smrg    gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000;
363f29dbc25Smrg
364f29dbc25Smrg    XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
365f29dbc25Smrg
366f29dbc25Smrg    pGeode->FBBase = gfx_virt_fbptr;
367f29dbc25Smrg
368f29dbc25Smrg    if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) ||
369f29dbc25Smrg	(!gfx_virt_vidptr) || (!gfx_virt_fbptr))
370f29dbc25Smrg	return FALSE;
371f29dbc25Smrg
372f29dbc25Smrg    if (!pGeode->NoAccel && pGeode->useEXA)
373f29dbc25Smrg	pGeode->pExa->memoryBase = pGeode->FBBase;
374f29dbc25Smrg
375f29dbc25Smrg    xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n",
376f29dbc25Smrg	pGeode->FBAvail, pGeode->FBBase);
377f29dbc25Smrg
378f29dbc25Smrg    return TRUE;
379f29dbc25Smrg}
380f29dbc25Smrg
381f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a
382f29dbc25Smrg   signature - if it doesn't match exactly, then we assume no VGA.
383f29dbc25Smrg*/
384f29dbc25Smrg
385f29dbc25Smrgstatic Bool
386f29dbc25SmrgGXCheckVGA(ScrnInfoPtr pScrni)
387f29dbc25Smrg{
388f29dbc25Smrg
389f29dbc25Smrg    unsigned char *ptr;
390f29dbc25Smrg    const char *vgasig = "IBM VGA Compatible";
391f29dbc25Smrg    int ret;
392f29dbc25Smrg
393f29dbc25Smrg    ptr =
394f29dbc25Smrg	xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
395f29dbc25Smrg	strlen(vgasig));
396f29dbc25Smrg
397f29dbc25Smrg    if (ptr == NULL)
398f29dbc25Smrg	return FALSE;
399f29dbc25Smrg
400f29dbc25Smrg    ret = memcmp(ptr, vgasig, strlen(vgasig));
401f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
402f29dbc25Smrg
403f29dbc25Smrg    return ret ? FALSE : TRUE;
404f29dbc25Smrg}
405f29dbc25Smrg
406f29dbc25Smrgstatic Bool
407f29dbc25SmrgGXPreInit(ScrnInfoPtr pScrni, int flags)
408f29dbc25Smrg{
409f29dbc25Smrg    GeodePtr pGeode;
410f29dbc25Smrg    ClockRangePtr GeodeClockRange;
411f29dbc25Smrg    OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0];
412f29dbc25Smrg    int ret;
413f29dbc25Smrg    QQ_WORD msrValue;
414f29dbc25Smrg    EntityInfoPtr pEnt;
415f29dbc25Smrg    rgb defaultWeight = { 0, 0, 0 };
416f29dbc25Smrg    int modecnt;
417f29dbc25Smrg    char *s, *panelgeo;
418f29dbc25Smrg    Bool useVGA;
419f29dbc25Smrg
420f29dbc25Smrg    if (pScrni->numEntities != 1)
421f29dbc25Smrg	return FALSE;
422f29dbc25Smrg
423f29dbc25Smrg    pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
424f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
425f29dbc25Smrg    if (pEnt->resources)
426f29dbc25Smrg	return FALSE;
427f29dbc25Smrg#endif
428f29dbc25Smrg
429f29dbc25Smrg    pGeode = pScrni->driverPrivate = xnfcalloc(sizeof(GeodeRec), 1);
430f29dbc25Smrg
431f29dbc25Smrg    if (pGeode == NULL)
432f29dbc25Smrg	return FALSE;
433f29dbc25Smrg
434f29dbc25Smrg    useVGA = GXCheckVGA(pScrni);
435f29dbc25Smrg
436f29dbc25Smrg    if (flags & PROBE_DETECT) {
437f29dbc25Smrg	GeodeProbeDDC(pScrni, pEnt->index);
438f29dbc25Smrg	return TRUE;
439f29dbc25Smrg    }
440f29dbc25Smrg
441f29dbc25Smrg    /* Probe for VGA */
442f29dbc25Smrg    pGeode->useVGA = useVGA;
443f29dbc25Smrg    pGeode->pEnt = pEnt;
444f29dbc25Smrg
445f29dbc25Smrg    if (pGeode->useVGA) {
446f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
447f29dbc25Smrg	    pGeode->useVGA = FALSE;
448f29dbc25Smrg
449f29dbc25Smrg#if INT10_SUPPORT
450f29dbc25Smrg	pGeode->vesa = xcalloc(sizeof(VESARec), 1);
451f29dbc25Smrg#endif
452f29dbc25Smrg    }
453f29dbc25Smrg
454f29dbc25Smrg    gfx_msr_init();
455f29dbc25Smrg
456f29dbc25Smrg    ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue);
457f29dbc25Smrg
458f29dbc25Smrg    if (!ret) {
459f29dbc25Smrg	pGeode->Output =
460f29dbc25Smrg	    ((msrValue.low & RCDF_CONFIG_FMT_MASK) ==
461f29dbc25Smrg	    RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT;
462f29dbc25Smrg    }
463f29dbc25Smrg
464f29dbc25Smrg    /* Fill in the monitor information */
465f29dbc25Smrg    pScrni->monitor = pScrni->confScreen->monitor;
466f29dbc25Smrg
467f29dbc25Smrg    if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
468f29dbc25Smrg	return FALSE;
469f29dbc25Smrg
470f29dbc25Smrg    switch (pScrni->depth) {
471f29dbc25Smrg    case 8:
472f29dbc25Smrg	pScrni->rgbBits = 8;
473f29dbc25Smrg    case 16:
474f29dbc25Smrg    case 24:
475f29dbc25Smrg    case 32:
476f29dbc25Smrg	break;
477f29dbc25Smrg    default:
478f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
479f29dbc25Smrg	    "The driver does not support %d as a depth.\n", pScrni->depth);
480f29dbc25Smrg	return FALSE;
481f29dbc25Smrg    }
482f29dbc25Smrg
483f29dbc25Smrg    xf86PrintDepthBpp(pScrni);
484f29dbc25Smrg
485f29dbc25Smrg    if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
486f29dbc25Smrg	return FALSE;
487f29dbc25Smrg
488f29dbc25Smrg    if (!xf86SetDefaultVisual(pScrni, -1))
489f29dbc25Smrg	return FALSE;
490f29dbc25Smrg
491f29dbc25Smrg    /*
492f29dbc25Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
493f29dbc25Smrg     * here.
494f29dbc25Smrg     */
495f29dbc25Smrg    {
496f29dbc25Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
497f29dbc25Smrg
498f29dbc25Smrg	if (!xf86SetGamma(pScrni, zeros)) {
499f29dbc25Smrg	    return FALSE;
500f29dbc25Smrg	}
501f29dbc25Smrg    }
502f29dbc25Smrg
503f29dbc25Smrg    pScrni->progClock = TRUE;
504f29dbc25Smrg    xf86CollectOptions(pScrni, NULL);
505f29dbc25Smrg    xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
506f29dbc25Smrg
507f29dbc25Smrg    /* Set up our various options that may get reversed as we go on */
508f29dbc25Smrg
509f29dbc25Smrg    pGeode->FBVGAActive = FALSE;
510f29dbc25Smrg    pGeode->tryHWCursor = TRUE;
511f29dbc25Smrg    pGeode->tryCompression = TRUE;
512f29dbc25Smrg
513f29dbc25Smrg    pGeode->NoAccel = FALSE;
514f29dbc25Smrg    pGeode->useEXA = FALSE;
515f29dbc25Smrg
516f29dbc25Smrg    pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE;
517f29dbc25Smrg
518f29dbc25Smrg    pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS;
519f29dbc25Smrg    pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS;
520f29dbc25Smrg    pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
521f29dbc25Smrg
522f29dbc25Smrg    xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR,
523f29dbc25Smrg	&pGeode->tryHWCursor);
524f29dbc25Smrg
525f29dbc25Smrg    if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE,
526f29dbc25Smrg	    (int *)&(pGeode->FBAvail)))
527f29dbc25Smrg	pGeode->FBAvail = 0;
528f29dbc25Smrg
529f29dbc25Smrg    /* For compatability - allow SWCursor too */
530f29dbc25Smrg
531f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE))
532f29dbc25Smrg	pGeode->tryHWCursor = FALSE;
533f29dbc25Smrg
534f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE))
535f29dbc25Smrg	pGeode->tryCompression = FALSE;
536f29dbc25Smrg
537f29dbc25Smrg    if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE))
538f29dbc25Smrg	pGeode->NoAccel = TRUE;
539f29dbc25Smrg
540f29dbc25Smrg    pGeode->rotation = RR_Rotate_0;
541f29dbc25Smrg
542f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) {
543f29dbc25Smrg
544f29dbc25Smrg	if (!xf86NameCmp(s, "LEFT"))
545f29dbc25Smrg	    pGeode->rotation = RR_Rotate_90;
546f29dbc25Smrg	else if (!xf86NameCmp(s, "INVERT"))
547f29dbc25Smrg	    pGeode->rotation = RR_Rotate_180;
548f29dbc25Smrg	else if (!xf86NameCmp(s, "CCW"))
549f29dbc25Smrg	    pGeode->rotation = RR_Rotate_270;
550f29dbc25Smrg	else
551f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
552f29dbc25Smrg		"Invalid rotation %s.\n", s);
553f29dbc25Smrg    }
554f29dbc25Smrg
555f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS,
556f29dbc25Smrg	&(pGeode->NoOfImgBuffers));
557f29dbc25Smrg
558f29dbc25Smrg    if (pGeode->NoOfImgBuffers <= 0)
559f29dbc25Smrg	pGeode->NoOfImgBuffers = 0;
560f29dbc25Smrg
561f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
562f29dbc25Smrg	&(pGeode->NoOfColorExpandLines));
563f29dbc25Smrg
564f29dbc25Smrg    if (pGeode->NoOfColorExpandLines <= 0)
565f29dbc25Smrg	pGeode->NoOfColorExpandLines = 0;
566f29dbc25Smrg
567f29dbc25Smrg    xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
568f29dbc25Smrg	(int *)&(pGeode->exaBfrSz));
569f29dbc25Smrg
570f29dbc25Smrg    if (pGeode->exaBfrSz <= 0)
571f29dbc25Smrg	pGeode->exaBfrSz = 0;
572f29dbc25Smrg
573f29dbc25Smrg    if (pGeode->Panel == TRUE) {
574f29dbc25Smrg	if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE))
575f29dbc25Smrg	    pGeode->Panel = FALSE;
576f29dbc25Smrg    }
577f29dbc25Smrg
578f29dbc25Smrg    panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY);
579f29dbc25Smrg
580f29dbc25Smrg    if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) {
581f29dbc25Smrg	if (!xf86NameCmp(s, "XAA"))
582f29dbc25Smrg	    pGeode->useEXA = FALSE;
583f29dbc25Smrg	else if (xf86NameCmp(s, "EXA"))
584f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
585f29dbc25Smrg		"Unknown accleration method %s.  Defaulting to XAA.\n", s);
586f29dbc25Smrg    }
587f29dbc25Smrg
588f29dbc25Smrg    xf86DrvMsg(pScrni->scrnIndex, X_INFO,
589f29dbc25Smrg	"Using %s acceleration architecture\n",
590f29dbc25Smrg	pGeode->useEXA ? "EXA" : "XAA");
591f29dbc25Smrg
592f29dbc25Smrg    /* Set up the panel */
593f29dbc25Smrg
594f29dbc25Smrg    if (pGeode->Panel) {
595f29dbc25Smrg	if (panelgeo != NULL) {
596f29dbc25Smrg	    if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX,
597f29dbc25Smrg		    &pGeode->PanelY))
598f29dbc25Smrg		pGeode->Panel = FALSE;
599f29dbc25Smrg	}
600f29dbc25Smrg#ifdef PNL_SUP
601f29dbc25Smrg	else {
602f29dbc25Smrg	    int b, f;
603f29dbc25Smrg
604f29dbc25Smrg	    /* The bitdepth and refresh isn't used anywhere else in the driver */
605f29dbc25Smrg
606f29dbc25Smrg	    if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS()))
607f29dbc25Smrg		Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b,
608f29dbc25Smrg		    &f);
609f29dbc25Smrg	}
610f29dbc25Smrg#endif
611f29dbc25Smrg    }
612f29dbc25Smrg
613f29dbc25Smrg    /* Set up the VGA */
614f29dbc25Smrg
615f29dbc25Smrg    if (pGeode->useVGA) {
616f29dbc25Smrg#if INT10_SUPPORT
617f29dbc25Smrg	VESARec *pVesa;
618f29dbc25Smrg
619f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "int10"))
620f29dbc25Smrg	    return FALSE;
621f29dbc25Smrg
622f29dbc25Smrg	pVesa = pGeode->vesa;
623f29dbc25Smrg
624f29dbc25Smrg	if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
625f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
626f29dbc25Smrg		"Unable to initialize 1NT10 support\n");
627f29dbc25Smrg	    pGeode->useVGA = FALSE;
628f29dbc25Smrg	}
629f29dbc25Smrg#endif
630f29dbc25Smrg    }
631f29dbc25Smrg
632f29dbc25Smrg    /* First try to get the framebuffer size from the framebuffer,
633f29dbc25Smrg     * and if that fails, revert all  the way back to the legacy
634f29dbc25Smrg     * method
635f29dbc25Smrg     */
636f29dbc25Smrg
637f29dbc25Smrg    if (pGeode->FBAvail == 0) {
638f29dbc25Smrg	if (GeodeGetSizeFromFB(&pGeode->FBAvail))
639f29dbc25Smrg	    pGeode->FBAvail = gfx_get_frame_buffer_size();
640f29dbc25Smrg    }
641f29dbc25Smrg
642f29dbc25Smrg    if (pScrni->memPhysBase == 0)
643f29dbc25Smrg	pScrni->memPhysBase = gfx_get_frame_buffer_base();
644f29dbc25Smrg
645f29dbc25Smrg    pScrni->fbOffset = 0;
646f29dbc25Smrg
647f29dbc25Smrg    if (pGeode->pEnt->device->videoRam == 0)
648f29dbc25Smrg	pScrni->videoRam = pGeode->FBAvail / 1024;
649f29dbc25Smrg    else
650f29dbc25Smrg	pScrni->videoRam = pGeode->pEnt->device->videoRam;
651f29dbc25Smrg
652f29dbc25Smrg    GeodeClockRange = (ClockRangePtr) xnfcalloc(sizeof(ClockRange), 1);
653f29dbc25Smrg    GeodeClockRange->next = NULL;
654f29dbc25Smrg    GeodeClockRange->minClock = 25175;
655f29dbc25Smrg    GeodeClockRange->maxClock = 229500;
656f29dbc25Smrg    GeodeClockRange->clockIndex = -1;
657f29dbc25Smrg    GeodeClockRange->interlaceAllowed = TRUE;
658f29dbc25Smrg    GeodeClockRange->doubleScanAllowed = FALSE;
659f29dbc25Smrg
660f29dbc25Smrg    pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index);
661f29dbc25Smrg
662f29dbc25Smrg    /* I'm still not 100% sure this uses the right values */
663f29dbc25Smrg
664f29dbc25Smrg    modecnt = xf86ValidateModes(pScrni,
665f29dbc25Smrg	pScrni->monitor->Modes,
666f29dbc25Smrg	pScrni->display->modes,
667f29dbc25Smrg	GeodeClockRange,
668f29dbc25Smrg	NULL, GX_MIN_PITCH, GX_MAX_PITCH,
669f29dbc25Smrg	32, GX_MIN_HEIGHT, GX_MAX_HEIGHT,
670f29dbc25Smrg	pScrni->display->virtualX,
671f29dbc25Smrg	pScrni->display->virtualY, pGeode->FBAvail, LOOKUP_BEST_REFRESH);
672f29dbc25Smrg
673f29dbc25Smrg    if (modecnt <= 0) {
674f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
675f29dbc25Smrg	return FALSE;
676f29dbc25Smrg    }
677f29dbc25Smrg
678f29dbc25Smrg    xf86PruneDriverModes(pScrni);
679f29dbc25Smrg
680f29dbc25Smrg    if (pScrni->modes == NULL) {
681f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
682f29dbc25Smrg	return FALSE;
683f29dbc25Smrg    }
684f29dbc25Smrg
685f29dbc25Smrg    xf86SetCrtcForModes(pScrni, 0);
686f29dbc25Smrg    pScrni->currentMode = pScrni->modes;
687f29dbc25Smrg
688f29dbc25Smrg    xf86PrintModes(pScrni);
689f29dbc25Smrg    xf86SetDpi(pScrni, 0, 0);
690f29dbc25Smrg
691f29dbc25Smrg    /* Load the modules we'll need */
692f29dbc25Smrg
693f29dbc25Smrg    if (xf86LoadSubModule(pScrni, "fb") == NULL) {
694f29dbc25Smrg	return FALSE;
695f29dbc25Smrg    }
696f29dbc25Smrg
697f29dbc25Smrg    if (pGeode->NoAccel == FALSE) {
698f29dbc25Smrg	const char *module = (pGeode->useEXA) ? "exa" : "xaa";
699f29dbc25Smrg
700f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, module)) {
701f29dbc25Smrg	    return FALSE;
702f29dbc25Smrg	}
703f29dbc25Smrg    }
704f29dbc25Smrg
705f29dbc25Smrg    if (pGeode->tryHWCursor == TRUE) {
706f29dbc25Smrg	if (!xf86LoadSubModule(pScrni, "ramdac")) {
707f29dbc25Smrg	    return FALSE;
708f29dbc25Smrg	}
709f29dbc25Smrg    }
710f29dbc25Smrg
711f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS
712f29dbc25Smrg    if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
713f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
714f29dbc25Smrg	    "Couldn't register the resources.\n");
715f29dbc25Smrg	return FALSE;
716f29dbc25Smrg    }
717f29dbc25Smrg#endif
718f29dbc25Smrg    return TRUE;
719f29dbc25Smrg}
720f29dbc25Smrg
721f29dbc25Smrgstatic void
722f29dbc25SmrgGXRestore(ScrnInfoPtr pScrni)
723f29dbc25Smrg{
724f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
725f29dbc25Smrg
726f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
727f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
728f29dbc25Smrg
729f29dbc25Smrg	vgaHWProtect(pScrni, TRUE);
730f29dbc25Smrg	vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
731f29dbc25Smrg	vgaHWProtect(pScrni, FALSE);
732f29dbc25Smrg    }
733f29dbc25Smrg}
734f29dbc25Smrg
735f29dbc25Smrgstatic Bool
736f29dbc25SmrgGXUnmapMem(ScrnInfoPtr pScrni)
737f29dbc25Smrg{
738f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
739f29dbc25Smrg
740f29dbc25Smrg    /* unmap all the memory map's */
741f29dbc25Smrg
742f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE);
743f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE);
744f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE);
745f29dbc25Smrg    xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail);
746f29dbc25Smrg    return TRUE;
747f29dbc25Smrg}
748f29dbc25Smrg
749f29dbc25Smrgstatic void
750f29dbc25SmrgGXSetDvLineSize(unsigned int pitch)
751f29dbc25Smrg{
752f29dbc25Smrg    unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024;
753f29dbc25Smrg
754f29dbc25Smrg    if (pitch > 1024) {
755f29dbc25Smrg	dv_size = MDC_DV_LINE_SIZE_2048;
756f29dbc25Smrg    }
757f29dbc25Smrg    if (pitch > 2048) {
758f29dbc25Smrg	dv_size = MDC_DV_LINE_SIZE_4096;
759f29dbc25Smrg    }
760f29dbc25Smrg    if (pitch > 4096) {
761f29dbc25Smrg	dv_size = MDC_DV_LINE_SIZE_8192;
762f29dbc25Smrg    }
763f29dbc25Smrg
764f29dbc25Smrg    /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
765f29dbc25Smrg
766f29dbc25Smrg    temp = READ_REG32(MDC_DV_CTL);
767f29dbc25Smrg    WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size);
768f29dbc25Smrg}
769f29dbc25Smrg
770f29dbc25Smrg/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */
771f29dbc25Smrg
772f29dbc25Smrgstatic void
773f29dbc25SmrgGXAdjustFrame(int scrnIndex, int x, int y, int flags)
774f29dbc25Smrg{
775f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
776f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
777f29dbc25Smrg    unsigned long offset;
778f29dbc25Smrg
779f29dbc25Smrg    offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3);
780f29dbc25Smrg
781f29dbc25Smrg    gfx_set_display_offset(offset);
782f29dbc25Smrg}
783f29dbc25Smrg
784f29dbc25Smrgstatic Bool
785f29dbc25SmrgGXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode)
786f29dbc25Smrg{
787f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
788f29dbc25Smrg    int flags = 0;
789f29dbc25Smrg    int custom = 0;
790f29dbc25Smrg
791f29dbc25Smrg    pScrni->vtSema = TRUE;
792f29dbc25Smrg
793f29dbc25Smrg    gx_disable_dac_power();
794f29dbc25Smrg
795f29dbc25Smrg    if (pMode->Flags & V_NHSYNC)
796f29dbc25Smrg	flags |= 1;
797f29dbc25Smrg    if (pMode->Flags & V_NVSYNC)
798f29dbc25Smrg	flags |= 2;
799f29dbc25Smrg
800f29dbc25Smrg    /* Check to see if we should use custom or built-in timings */
801f29dbc25Smrg
802f29dbc25Smrg    if (pGeode->Panel)
803f29dbc25Smrg	custom = (pMode->type & M_T_USERDEF);
804f29dbc25Smrg    else
805f29dbc25Smrg	custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
806f29dbc25Smrg
807f29dbc25Smrg    /* If we're not doing a custom mode, then just set the fixed timings,
808f29dbc25Smrg     * otherwise, do the whole shooting match */
809f29dbc25Smrg
810f29dbc25Smrg    if (!custom) {
811f29dbc25Smrg	GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY,
812f29dbc25Smrg		pMode->CrtcHDisplay, pMode->CrtcVDisplay,
813f29dbc25Smrg		pScrni->bitsPerPixel));
814f29dbc25Smrg    } else {
815f29dbc25Smrg	if (pGeode->Panel)
816f29dbc25Smrg	    GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY,
817f29dbc25Smrg		    pMode->CrtcHDisplay, pMode->CrtcVDisplay,
818f29dbc25Smrg		    pScrni->bitsPerPixel));
819f29dbc25Smrg
820f29dbc25Smrg	GFX(set_display_timings(pScrni->bitsPerPixel, flags,
821f29dbc25Smrg		pMode->CrtcHDisplay, pMode->CrtcHBlankStart,
822f29dbc25Smrg		pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd,
823f29dbc25Smrg		pMode->CrtcHBlankEnd, pMode->CrtcHTotal,
824f29dbc25Smrg		pMode->CrtcVDisplay, pMode->CrtcVBlankStart,
825f29dbc25Smrg		pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd,
826f29dbc25Smrg		pMode->CrtcVBlankEnd, pMode->CrtcVTotal,
827f29dbc25Smrg		(int)((pMode->SynthClock / 1000.0) * 0x10000)));
828f29dbc25Smrg    }
829f29dbc25Smrg
830f29dbc25Smrg    GFX(set_crt_enable(CRT_ENABLE));
831f29dbc25Smrg    GFX(set_display_pitch(pGeode->displayPitch));
832f29dbc25Smrg    GFX(set_display_offset(0L));
833f29dbc25Smrg    GFX(wait_vertical_blank());
834f29dbc25Smrg
835f29dbc25Smrg    if (pGeode->Compression) {
836f29dbc25Smrg	GXSetDvLineSize(pGeode->Pitch);
837f29dbc25Smrg
838f29dbc25Smrg	gfx_set_compression_offset(pGeode->CBData.compression_offset);
839f29dbc25Smrg	gfx_set_compression_pitch(GX_CB_PITCH);
840f29dbc25Smrg	gfx_set_compression_size(GX_CB_SIZE);
841f29dbc25Smrg
842f29dbc25Smrg	gfx_set_compression_enable(1);
843f29dbc25Smrg    }
844f29dbc25Smrg
845f29dbc25Smrg    if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) {
846f29dbc25Smrg	GXLoadCursorImage(pScrni, NULL);
847f29dbc25Smrg	GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0));
848f29dbc25Smrg	GXShowCursor(pScrni);
849f29dbc25Smrg    } else {
850f29dbc25Smrg	GFX(set_cursor_enable(0));
851f29dbc25Smrg	pGeode->HWCursor = FALSE;
852f29dbc25Smrg    }
853f29dbc25Smrg
854f29dbc25Smrg    GXAdjustFrame(pScrni->scrnIndex, pScrni->frameX0, pScrni->frameY0, 0);
855f29dbc25Smrg    gx_enable_dac_power();
856f29dbc25Smrg
857f29dbc25Smrg    return TRUE;
858f29dbc25Smrg}
859f29dbc25Smrg
860f29dbc25Smrgstatic Bool
861f29dbc25SmrgGXSwitchMode(int index, DisplayModePtr pMode, int flags)
862f29dbc25Smrg{
863f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[index];
864f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
865f29dbc25Smrg    int ret = TRUE;
866f29dbc25Smrg    int rotate;
867f29dbc25Smrg
868f29dbc25Smrg    /* Syn the engine and shutdown the DAC momentarily */
869f29dbc25Smrg
870f29dbc25Smrg    gfx_wait_until_idle();
871f29dbc25Smrg
872f29dbc25Smrg    /* Set up the memory for the new mode */
873f29dbc25Smrg    rotate = GXGetRotation(pScrni->pScreen);
874f29dbc25Smrg    ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate);
875f29dbc25Smrg
876f29dbc25Smrg    if (ret) {
877f29dbc25Smrg	if (pGeode->curMode != pMode)
878f29dbc25Smrg	    ret = GXSetVideoMode(pScrni, pMode);
879f29dbc25Smrg    }
880f29dbc25Smrg
881f29dbc25Smrg    if (ret)
882f29dbc25Smrg	ret = GXRotate(pScrni, pMode);
883f29dbc25Smrg
884f29dbc25Smrg    /* Go back the way it was */
885f29dbc25Smrg
886f29dbc25Smrg    if (ret == FALSE) {
887f29dbc25Smrg	if (!GXSetVideoMode(pScrni, pGeode->curMode))
888f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
889f29dbc25Smrg		"Could not restore the previous mode\n");
890f29dbc25Smrg    } else
891f29dbc25Smrg	pGeode->curMode = pMode;
892f29dbc25Smrg
893f29dbc25Smrg    return ret;
894f29dbc25Smrg}
895f29dbc25Smrg
896f29dbc25Smrgstatic void
897f29dbc25SmrgGXLeaveGraphics(ScrnInfoPtr pScrni)
898f29dbc25Smrg{
899f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
900f29dbc25Smrg
901f29dbc25Smrg    gfx_wait_until_idle();
902f29dbc25Smrg
903f29dbc25Smrg    /* Restore VG registers */
904f29dbc25Smrg    gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp,
905f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wPolarity,
906f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHActive,
907f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHBlankStart,
908f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHSyncStart,
909f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHSyncEnd,
910f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHBlankEnd,
911f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wHTotal,
912f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVActive,
913f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVBlankStart,
914f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVSyncStart,
915f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVSyncEnd,
916f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVBlankEnd,
917f29dbc25Smrg	pGeode->FBgfxdisplaytiming.wVTotal,
918f29dbc25Smrg	pGeode->FBgfxdisplaytiming.dwDotClock);
919f29dbc25Smrg
920f29dbc25Smrg    gfx_set_compression_enable(0);
921f29dbc25Smrg
922f29dbc25Smrg    /* Restore the previous Compression state */
923f29dbc25Smrg    if (pGeode->FBCompressionEnable) {
924f29dbc25Smrg	gfx_set_compression_offset(pGeode->FBCompressionOffset);
925f29dbc25Smrg	gfx_set_compression_pitch(pGeode->FBCompressionPitch);
926f29dbc25Smrg	gfx_set_compression_size(pGeode->FBCompressionSize);
927f29dbc25Smrg	gfx_set_compression_enable(1);
928f29dbc25Smrg    }
929f29dbc25Smrg
930f29dbc25Smrg    gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch);
931f29dbc25Smrg
932f29dbc25Smrg    gfx_set_display_offset(pGeode->FBDisplayOffset);
933f29dbc25Smrg
934f29dbc25Smrg    /* Restore Cursor */
935f29dbc25Smrg    gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0);
936f29dbc25Smrg
937f29dbc25Smrg    if (pGeode->useVGA) {
938f29dbc25Smrg	pGeode->vesa->pInt->num = 0x10;
939f29dbc25Smrg	pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
940f29dbc25Smrg	pGeode->vesa->pInt->bx = 0;
941f29dbc25Smrg	xf86ExecX86int10(pGeode->vesa->pInt);
942f29dbc25Smrg	gfx_delay_milliseconds(3);
943f29dbc25Smrg    }
944f29dbc25Smrg
945f29dbc25Smrg    GXRestore(pScrni);
946f29dbc25Smrg
947f29dbc25Smrg    gx_enable_dac_power();
948f29dbc25Smrg}
949f29dbc25Smrg
950f29dbc25Smrgstatic Bool
951f29dbc25SmrgGXCloseScreen(int scrnIndex, ScreenPtr pScrn)
952f29dbc25Smrg{
953f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
954f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
955f29dbc25Smrg
956f29dbc25Smrg    if (pScrni->vtSema)
957f29dbc25Smrg	GXLeaveGraphics(pScrni);
958f29dbc25Smrg
959f29dbc25Smrg    if (pGeode->AccelInfoRec)
960f29dbc25Smrg	XAADestroyInfoRec(pGeode->AccelInfoRec);
961f29dbc25Smrg
962f29dbc25Smrg    if (pGeode->AccelImageWriteBuffers) {
963f29dbc25Smrg	xfree(pGeode->AccelImageWriteBuffers[0]);
964f29dbc25Smrg	xfree(pGeode->AccelImageWriteBuffers);
965f29dbc25Smrg	pGeode->AccelImageWriteBuffers = NULL;
966f29dbc25Smrg    }
967f29dbc25Smrg
968f29dbc25Smrg    if (pGeode->AccelColorExpandBuffers) {
969f29dbc25Smrg	xfree(pGeode->AccelColorExpandBuffers);
970f29dbc25Smrg	pGeode->AccelColorExpandBuffers = NULL;
971f29dbc25Smrg    }
972f29dbc25Smrg
973f29dbc25Smrg    if (pGeode->pExa) {
974f29dbc25Smrg	exaDriverFini(pScrn);
975f29dbc25Smrg	xfree(pGeode->pExa);
976f29dbc25Smrg	pGeode->pExa = NULL;
977f29dbc25Smrg    }
978f29dbc25Smrg
979f29dbc25Smrg    pScrni->vtSema = FALSE;
980f29dbc25Smrg
981f29dbc25Smrg    GXUnmapMem(pScrni);
982f29dbc25Smrg
983f29dbc25Smrg    pScrni->PointerMoved = pGeode->PointerMoved;
984f29dbc25Smrg    pScrn->CloseScreen = pGeode->CloseScreen;
985f29dbc25Smrg
986f29dbc25Smrg    if (pScrn->CloseScreen)
987f29dbc25Smrg	return (*pScrn->CloseScreen) (scrnIndex, pScrn);
988f29dbc25Smrg
989f29dbc25Smrg    return TRUE;
990f29dbc25Smrg}
991f29dbc25Smrg
992f29dbc25Smrgstatic Bool
993f29dbc25SmrgGXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
994f29dbc25Smrg{
995f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
996f29dbc25Smrg
997f29dbc25Smrg    if (!GXMapMem(pScrni))
998f29dbc25Smrg	return FALSE;
999f29dbc25Smrg
1000f29dbc25Smrg    if (pGeode->useVGA)
1001f29dbc25Smrg	pGeode->FBVGAActive = gu2_get_vga_active();
1002f29dbc25Smrg
1003f29dbc25Smrg    gfx_wait_until_idle();
1004f29dbc25Smrg
1005f29dbc25Smrg    /* Save off the current state (should this be somewhere else)? */
1006f29dbc25Smrg
1007f29dbc25Smrg    pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency();
1008f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch();
1009f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp();
1010f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal();
1011f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive();
1012f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start();
1013f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end();
1014f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start();
1015f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end();
1016f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal();
1017f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive();
1018f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start();
1019f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end();
1020f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start();
1021f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end();
1022f29dbc25Smrg    pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities();
1023f29dbc25Smrg
1024f29dbc25Smrg    pGeode->FBDisplayOffset = gfx_get_display_offset();
1025f29dbc25Smrg
1026f29dbc25Smrg    if (pGeode->useVGA) {
1027f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1028f29dbc25Smrg
1029f29dbc25Smrg	pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
1030f29dbc25Smrg    }
1031f29dbc25Smrg
1032f29dbc25Smrg    pGeode->FBCompressionEnable = gfx_get_compression_enable();
1033f29dbc25Smrg    pGeode->FBCompressionOffset = gfx_get_compression_offset();
1034f29dbc25Smrg    pGeode->FBCompressionPitch = gfx_get_compression_pitch();
1035f29dbc25Smrg    pGeode->FBCompressionSize = gfx_get_compression_size();
1036f29dbc25Smrg
1037f29dbc25Smrg#ifdef PNL_SUP
1038f29dbc25Smrg    Pnl_SavePanelState();
1039f29dbc25Smrg#endif
1040f29dbc25Smrg
1041f29dbc25Smrg    /* Turn off the VGA */
1042f29dbc25Smrg
1043f29dbc25Smrg    if (pGeode->useVGA && pGeode->FBVGAActive) {
1044f29dbc25Smrg	unsigned short sequencer;
1045f29dbc25Smrg	vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
1046f29dbc25Smrg
1047f29dbc25Smrg	/* Map VGA aperture */
1048f29dbc25Smrg	if (!vgaHWMapMem(pScrni))
1049f29dbc25Smrg	    return FALSE;
1050f29dbc25Smrg
1051f29dbc25Smrg	/* Unlock VGA registers */
1052f29dbc25Smrg	vgaHWUnlock(pvgaHW);
1053f29dbc25Smrg
1054f29dbc25Smrg	/* Save the current state and setup the current mode */
1055f29dbc25Smrg	vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
1056f29dbc25Smrg
1057f29dbc25Smrg	/* DISABLE VGA SEQUENCER */
1058f29dbc25Smrg	/* This allows the VGA state machine to terminate. We must delay */
1059f29dbc25Smrg	/* such that there are no pending MBUS requests.  */
1060f29dbc25Smrg
1061f29dbc25Smrg	gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
1062f29dbc25Smrg	sequencer = gfx_inb(MDC_SEQUENCER_DATA);
1063f29dbc25Smrg	sequencer |= MDC_CLK_MODE_SCREEN_OFF;
1064f29dbc25Smrg	gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1065f29dbc25Smrg
1066f29dbc25Smrg	gfx_delay_milliseconds(1);
1067f29dbc25Smrg
1068f29dbc25Smrg	/* BLANK THE VGA DISPLAY */
1069f29dbc25Smrg	gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET);
1070f29dbc25Smrg	sequencer = gfx_inb(MDC_SEQUENCER_DATA);
1071f29dbc25Smrg	sequencer &= ~MDC_RESET_VGA_DISP_ENABLE;
1072f29dbc25Smrg	gfx_outb(MDC_SEQUENCER_DATA, sequencer);
1073f29dbc25Smrg
1074f29dbc25Smrg	gfx_delay_milliseconds(1);
1075f29dbc25Smrg    }
1076f29dbc25Smrg
1077f29dbc25Smrg    /* Set up the memory */
1078f29dbc25Smrg    /* XXX - FIXME - when we alow inital rotation, it should be here */
1079f29dbc25Smrg    GXAllocateMemory(pScrn, pScrni, pGeode->rotation);
1080f29dbc25Smrg
1081f29dbc25Smrg    /* Clear the framebuffer */
1082f29dbc25Smrg    memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize);
1083f29dbc25Smrg
1084f29dbc25Smrg    /* Set up the video mode */
1085f29dbc25Smrg    GXSetVideoMode(pScrni, pScrni->currentMode);
1086f29dbc25Smrg    pGeode->curMode = pScrni->currentMode;
1087f29dbc25Smrg
1088f29dbc25Smrg    return TRUE;
1089f29dbc25Smrg}
1090f29dbc25Smrg
1091f29dbc25Smrgstatic void
1092f29dbc25SmrgGXLoadPalette(ScrnInfoPtr pScrni,
1093f29dbc25Smrg    int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
1094f29dbc25Smrg{
1095f29dbc25Smrg    int i, index, color;
1096f29dbc25Smrg
1097f29dbc25Smrg    for (i = 0; i < numColors; i++) {
1098f29dbc25Smrg	index = indizes[i] & 0xFF;
1099f29dbc25Smrg	color = (((unsigned long)(colors[index].red & 0xFF)) << 16) |
1100f29dbc25Smrg	    (((unsigned long)(colors[index].green & 0xFF)) << 8) |
1101f29dbc25Smrg	    ((unsigned long)(colors[index].blue & 0xFF));
1102f29dbc25Smrg
1103f29dbc25Smrg	GFX(set_display_palette_entry(index, color));
1104f29dbc25Smrg    }
1105f29dbc25Smrg}
1106f29dbc25Smrg
1107f29dbc25Smrg#ifdef DPMSExtension
1108f29dbc25Smrgstatic void
1109f29dbc25SmrgGXPanelPower(int enable)
1110f29dbc25Smrg{
1111f29dbc25Smrg    unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT);
1112f29dbc25Smrg
1113f29dbc25Smrg    if (enable != 0)
1114f29dbc25Smrg	power |= RCDF_PM_PANEL_POWER_ON;
1115f29dbc25Smrg    else
1116f29dbc25Smrg	power &= ~RCDF_PM_PANEL_POWER_ON;
1117f29dbc25Smrg
1118f29dbc25Smrg    WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
1119f29dbc25Smrg}
1120f29dbc25Smrg
1121f29dbc25Smrgstatic void
1122f29dbc25SmrgGXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags)
1123f29dbc25Smrg{
1124f29dbc25Smrg    GeodeRec *pGeode;
1125f29dbc25Smrg
1126f29dbc25Smrg    pGeode = GEODEPTR(pScrni);
1127f29dbc25Smrg
1128f29dbc25Smrg    if (!pScrni->vtSema)
1129f29dbc25Smrg	return;
1130f29dbc25Smrg
1131f29dbc25Smrg    switch (mode) {
1132f29dbc25Smrg    case DPMSModeOn:
1133f29dbc25Smrg	/* Screen: On; HSync: On; VSync: On */
1134f29dbc25Smrg	GFX(set_crt_enable(CRT_ENABLE));
1135f29dbc25Smrg#if defined(PNL_SUP)
1136f29dbc25Smrg	if (pGeode->Panel) {
1137f29dbc25Smrg	    Pnl_PowerUp();
1138f29dbc25Smrg	    GXPanelPower(1);
1139f29dbc25Smrg	}
1140f29dbc25Smrg#endif
1141f29dbc25Smrg	break;
1142f29dbc25Smrg
1143f29dbc25Smrg    case DPMSModeStandby:
1144f29dbc25Smrg	/* Screen: Off; HSync: Off; VSync: On */
1145f29dbc25Smrg	GFX(set_crt_enable(CRT_STANDBY));
1146f29dbc25Smrg#if defined(PNL_SUP)
1147f29dbc25Smrg	if (pGeode->Panel) {
1148f29dbc25Smrg	    Pnl_PowerDown();
1149f29dbc25Smrg	    GXPanelPower(0);
1150f29dbc25Smrg	}
1151f29dbc25Smrg#endif
1152f29dbc25Smrg	break;
1153f29dbc25Smrg
1154f29dbc25Smrg    case DPMSModeSuspend:
1155f29dbc25Smrg	/* Screen: Off; HSync: On; VSync: Off */
1156f29dbc25Smrg	GFX(set_crt_enable(CRT_SUSPEND));
1157f29dbc25Smrg#if defined(PNL_SUP)
1158f29dbc25Smrg	if (pGeode->Panel) {
1159f29dbc25Smrg	    Pnl_PowerDown();
1160f29dbc25Smrg	    GXPanelPower(0);
1161f29dbc25Smrg	}
1162f29dbc25Smrg#endif
1163f29dbc25Smrg	break;
1164f29dbc25Smrg
1165f29dbc25Smrg    case DPMSModeOff:
1166f29dbc25Smrg	/* Screen: Off; HSync: Off; VSync: Off */
1167f29dbc25Smrg	GFX(set_crt_enable(CRT_DISABLE));
1168f29dbc25Smrg#if defined(PNL_SUP)
1169f29dbc25Smrg	if (pGeode->Panel) {
1170f29dbc25Smrg	    Pnl_PowerDown();
1171f29dbc25Smrg	    GXPanelPower(0);
1172f29dbc25Smrg	}
1173f29dbc25Smrg#endif
1174f29dbc25Smrg	break;
1175f29dbc25Smrg    }
1176f29dbc25Smrg}
1177f29dbc25Smrg#endif
1178f29dbc25Smrg
1179f29dbc25Smrgstatic Bool
1180f29dbc25SmrgGXCreateScreenResources(ScreenPtr pScreen)
1181f29dbc25Smrg{
1182f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum];
1183f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1184f29dbc25Smrg
1185f29dbc25Smrg    pScreen->CreateScreenResources = pGeode->CreateScreenResources;
1186f29dbc25Smrg    if (!(*pScreen->CreateScreenResources) (pScreen))
1187f29dbc25Smrg	return FALSE;
1188f29dbc25Smrg
1189f29dbc25Smrg    if (xf86LoaderCheckSymbol("GXRandRSetConfig")
1190f29dbc25Smrg	&& pGeode->rotation != RR_Rotate_0) {
1191f29dbc25Smrg	Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate,
1192f29dbc25Smrg	    RRScreenSizePtr pSize) = NULL;
1193f29dbc25Smrg
1194f29dbc25Smrg	RRScreenSize p;
1195f29dbc25Smrg	Rotation requestedRotation = pGeode->rotation;
1196f29dbc25Smrg
1197f29dbc25Smrg	pGeode->rotation = RR_Rotate_0;
1198f29dbc25Smrg
1199f29dbc25Smrg	/* Just setup enough for an initial rotate */
1200f29dbc25Smrg
1201f29dbc25Smrg	p.width = pScreen->width;
1202f29dbc25Smrg	p.height = pScreen->height;
1203f29dbc25Smrg	p.mmWidth = pScreen->mmWidth;
1204f29dbc25Smrg	p.mmHeight = pScreen->mmHeight;
1205f29dbc25Smrg
1206f29dbc25Smrg	GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig");
1207f29dbc25Smrg	if (GXRandRSetConfig) {
1208f29dbc25Smrg	    pGeode->starting = TRUE;
1209f29dbc25Smrg	    (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p);
1210f29dbc25Smrg	    pGeode->starting = FALSE;
1211f29dbc25Smrg	}
1212f29dbc25Smrg    }
1213f29dbc25Smrg
1214f29dbc25Smrg    return TRUE;
1215f29dbc25Smrg}
1216f29dbc25Smrg
1217f29dbc25Smrgstatic Bool
1218f29dbc25SmrgGXScreenInit(int scrnIndex, ScreenPtr pScrn, int argc, char **argv)
1219f29dbc25Smrg{
1220f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
1221f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1222f29dbc25Smrg    XF86ModReqInfo shadowReq;
1223f29dbc25Smrg    int maj, min, ret, rotate;
1224f29dbc25Smrg
1225f29dbc25Smrg    pGeode->starting = TRUE;
1226f29dbc25Smrg
1227f29dbc25Smrg    /* If we are using VGA then go ahead and map the memory */
1228f29dbc25Smrg
1229f29dbc25Smrg    if (pGeode->useVGA) {
1230f29dbc25Smrg
1231f29dbc25Smrg	if (!vgaHWMapMem(pScrni))
1232f29dbc25Smrg	    return FALSE;
1233f29dbc25Smrg
1234f29dbc25Smrg	vgaHWGetIOBase(VGAHWPTR(pScrni));
1235f29dbc25Smrg    }
1236f29dbc25Smrg
1237f29dbc25Smrg    if (!pGeode->NoAccel) {
1238f29dbc25Smrg
1239f29dbc25Smrg	if (pGeode->useEXA) {
1240f29dbc25Smrg
1241f29dbc25Smrg	    if (!(pGeode->pExa = exaDriverAlloc())) {
1242f29dbc25Smrg		xf86DrvMsg(scrnIndex, X_ERROR,
1243f29dbc25Smrg		    "Couldn't allocate the EXA structure.\n");
1244f29dbc25Smrg		pGeode->NoAccel = TRUE;
1245f29dbc25Smrg	    } else {
1246f29dbc25Smrg		ExaDriverPtr pExa = pGeode->pExa;
1247f29dbc25Smrg
1248f29dbc25Smrg		/* THis is set in GXAllocMem */
1249f29dbc25Smrg		pExa->memoryBase = 0;
1250f29dbc25Smrg
1251f29dbc25Smrg		/* This is set in GXAllocateMemory */
1252f29dbc25Smrg		pExa->memorySize = 0;
1253f29dbc25Smrg
1254f29dbc25Smrg		pExa->pixmapOffsetAlign = 32;
1255f29dbc25Smrg		pExa->pixmapPitchAlign = 32;
1256f29dbc25Smrg		pExa->flags = EXA_OFFSCREEN_PIXMAPS;
1257f29dbc25Smrg		pExa->maxX = GX_MAX_WIDTH - 1;
1258f29dbc25Smrg		pExa->maxY = GX_MAX_HEIGHT - 1;
1259f29dbc25Smrg	    }
1260f29dbc25Smrg	} else {
1261f29dbc25Smrg	    pGeode->AccelImageWriteBuffers =
1262f29dbc25Smrg		xcalloc(sizeof(pGeode->AccelImageWriteBuffers[0]),
1263f29dbc25Smrg		pGeode->NoOfImgBuffers);
1264f29dbc25Smrg	    pGeode->AccelColorExpandBuffers =
1265f29dbc25Smrg		xcalloc(sizeof(pGeode->AccelColorExpandBuffers[0]),
1266f29dbc25Smrg		pGeode->NoOfColorExpandLines);
1267f29dbc25Smrg	}
1268f29dbc25Smrg    }
1269f29dbc25Smrg
1270f29dbc25Smrg    /* XXX FIXME - Take down any of the structures on failure? */
1271f29dbc25Smrg
1272f29dbc25Smrg    if (!GXEnterGraphics(pScrn, pScrni))
1273f29dbc25Smrg	return FALSE;
1274f29dbc25Smrg
1275f29dbc25Smrg    miClearVisualTypes();
1276f29dbc25Smrg
1277f29dbc25Smrg    /* XXX Again - take down anything? */
1278f29dbc25Smrg
1279f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
1280f29dbc25Smrg	if (!miSetVisualTypes(pScrni->depth,
1281f29dbc25Smrg		TrueColorMask, pScrni->rgbBits, pScrni->defaultVisual)) {
1282f29dbc25Smrg	    return FALSE;
1283f29dbc25Smrg	}
1284f29dbc25Smrg    } else {
1285f29dbc25Smrg	if (!miSetVisualTypes(pScrni->depth,
1286f29dbc25Smrg		miGetDefaultVisualMask(pScrni->depth),
1287f29dbc25Smrg		pScrni->rgbBits, pScrni->defaultVisual)) {
1288f29dbc25Smrg	    return FALSE;
1289f29dbc25Smrg	}
1290f29dbc25Smrg    }
1291f29dbc25Smrg
1292f29dbc25Smrg    miSetPixmapDepths();
1293f29dbc25Smrg
1294f29dbc25Smrg    /* Point at the visible area to start */
1295f29dbc25Smrg
1296f29dbc25Smrg    ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset,
1297f29dbc25Smrg	pScrni->virtualX, pScrni->virtualY,
1298f29dbc25Smrg	pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth,
1299f29dbc25Smrg	pScrni->bitsPerPixel);
1300f29dbc25Smrg
1301f29dbc25Smrg    if (!ret)
1302f29dbc25Smrg	return FALSE;
1303f29dbc25Smrg
1304f29dbc25Smrg    xf86SetBlackWhitePixels(pScrn);
1305f29dbc25Smrg
1306f29dbc25Smrg    /* Set up the color ordering */
1307f29dbc25Smrg
1308f29dbc25Smrg    if (pScrni->bitsPerPixel > 8) {
1309f29dbc25Smrg	VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
1310f29dbc25Smrg
1311f29dbc25Smrg	while (--visual >= pScrn->visuals) {
1312f29dbc25Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
1313f29dbc25Smrg		visual->offsetRed = pScrni->offset.red;
1314f29dbc25Smrg		visual->offsetGreen = pScrni->offset.green;
1315f29dbc25Smrg		visual->offsetBlue = pScrni->offset.blue;
1316f29dbc25Smrg		visual->redMask = pScrni->mask.red;
1317f29dbc25Smrg		visual->greenMask = pScrni->mask.green;
1318f29dbc25Smrg		visual->blueMask = pScrni->mask.blue;
1319f29dbc25Smrg	    }
1320f29dbc25Smrg	}
1321f29dbc25Smrg    }
1322f29dbc25Smrg
1323f29dbc25Smrg    /* Must follow the color ordering */
1324f29dbc25Smrg    fbPictureInit(pScrn, 0, 0);
1325f29dbc25Smrg
1326f29dbc25Smrg    if (!pGeode->NoAccel)
1327f29dbc25Smrg	GXAccelInit(pScrn);
1328f29dbc25Smrg
1329f29dbc25Smrg    miInitializeBackingStore(pScrn);
1330f29dbc25Smrg    xf86SetBackingStore(pScrn);
1331f29dbc25Smrg
1332f29dbc25Smrg    /* Set up the soft cursor */
1333f29dbc25Smrg    miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
1334f29dbc25Smrg
1335f29dbc25Smrg    /* Set up the HW cursor - must follow the soft cursor init */
1336f29dbc25Smrg
1337f29dbc25Smrg    if (pGeode->tryHWCursor) {
1338f29dbc25Smrg	if (!GXHWCursorInit(pScrn))
1339f29dbc25Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
1340f29dbc25Smrg		"Hardware cursor initialization failed.\n");
1341f29dbc25Smrg    }
1342f29dbc25Smrg
1343f29dbc25Smrg    /* Set up the color map */
1344f29dbc25Smrg
1345f29dbc25Smrg    if (!miCreateDefColormap(pScrn))
1346f29dbc25Smrg	return FALSE;
1347f29dbc25Smrg
1348f29dbc25Smrg    if (pScrni->bitsPerPixel == 8) {
1349f29dbc25Smrg	/* Must follow initialization of the default colormap */
1350f29dbc25Smrg
1351f29dbc25Smrg	if (!xf86HandleColormaps(pScrn, 256, 8,
1352f29dbc25Smrg		GXLoadPalette, NULL,
1353f29dbc25Smrg		CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) {
1354f29dbc25Smrg	    return FALSE;
1355f29dbc25Smrg	}
1356f29dbc25Smrg    }
1357f29dbc25Smrg#ifdef DPMSExtension
1358f29dbc25Smrg    xf86DPMSInit(pScrn, GXDPMSSet, 0);
1359f29dbc25Smrg#endif
1360f29dbc25Smrg
1361f29dbc25Smrg    GXInitVideo(pScrn);
1362f29dbc25Smrg
1363f29dbc25Smrg    /* Set up RandR */
1364f29dbc25Smrg
1365f29dbc25Smrg    xf86DisableRandR();		       /* We provide our own RandR goodness */
1366f29dbc25Smrg
1367f29dbc25Smrg    /* Try to set up the shadow FB for rotation */
1368f29dbc25Smrg
1369f29dbc25Smrg    memset(&shadowReq, 0, sizeof(shadowReq));
1370f29dbc25Smrg    shadowReq.majorversion = 1;
1371f29dbc25Smrg    shadowReq.minorversion = 1;
1372f29dbc25Smrg
1373f29dbc25Smrg    if (LoadSubModule(pScrni->module, "shadow",
1374f29dbc25Smrg	    NULL, NULL, NULL, &shadowReq, &maj, &min)) {
1375f29dbc25Smrg
1376f29dbc25Smrg	rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
1377f29dbc25Smrg	shadowSetup(pScrn);
1378f29dbc25Smrg    } else {
1379f29dbc25Smrg	LoaderErrorMsg(NULL, "shadow", maj, min);
1380f29dbc25Smrg	xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1381f29dbc25Smrg	    "Error loading shadow - rotation not available.\n");
1382f29dbc25Smrg
1383f29dbc25Smrg	if (pGeode->rotation != RR_Rotate_0)
1384f29dbc25Smrg	    xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
1385f29dbc25Smrg		"Reverting back to normal rotation.\n");
1386f29dbc25Smrg
1387f29dbc25Smrg	rotate = pGeode->rotation = RR_Rotate_0;
1388f29dbc25Smrg    }
1389f29dbc25Smrg
1390f29dbc25Smrg    GXRandRInit(pScrn, rotate);
1391f29dbc25Smrg
1392f29dbc25Smrg    pGeode->PointerMoved = pScrni->PointerMoved;
1393f29dbc25Smrg    pScrni->PointerMoved = GeodePointerMoved;
1394f29dbc25Smrg
1395f29dbc25Smrg    pGeode->CreateScreenResources = pScrn->CreateScreenResources;
1396f29dbc25Smrg    pScrn->CreateScreenResources = GXCreateScreenResources;
1397f29dbc25Smrg
1398f29dbc25Smrg    pGeode->CloseScreen = pScrn->CloseScreen;
1399f29dbc25Smrg    pScrn->CloseScreen = GXCloseScreen;
1400f29dbc25Smrg    pScrn->SaveScreen = GXSaveScreen;
1401f29dbc25Smrg
1402f29dbc25Smrg    if (serverGeneration == 1)
1403f29dbc25Smrg	xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
1404f29dbc25Smrg
1405f29dbc25Smrg    pGeode->starting = FALSE;
1406f29dbc25Smrg
1407f29dbc25Smrg    return TRUE;
1408f29dbc25Smrg}
1409f29dbc25Smrg
1410f29dbc25Smrgstatic int
1411f29dbc25SmrgGXValidMode(int scrnIndex, DisplayModePtr pMode, Bool Verbose, int flags)
1412f29dbc25Smrg{
1413f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
1414f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1415f29dbc25Smrg    int p;
1416f29dbc25Smrg    int custom = 0;
1417f29dbc25Smrg
1418f29dbc25Smrg    if (pGeode->Panel)
1419f29dbc25Smrg	custom = (pMode->type & M_T_USERDEF);
1420f29dbc25Smrg    else
1421f29dbc25Smrg	custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
1422f29dbc25Smrg
1423f29dbc25Smrg    /* Use the durango lookup for !custom modes */
1424f29dbc25Smrg
1425f29dbc25Smrg    if (!custom && pGeode->Panel) {
1426f29dbc25Smrg        if (pMode->CrtcHDisplay > pGeode->PanelX ||
1427f29dbc25Smrg            pMode->CrtcVDisplay > pGeode->PanelY ||
1428f29dbc25Smrg            gfx_is_panel_mode_supported(pGeode->PanelX,
1429f29dbc25Smrg                                        pGeode->PanelY,
1430f29dbc25Smrg                                        pMode->CrtcHDisplay,
1431f29dbc25Smrg                                        pMode->CrtcVDisplay,
1432f29dbc25Smrg                                        pScrni->bitsPerPixel) < 0) {
1433f29dbc25Smrg
1434f29dbc25Smrg            return MODE_BAD;
1435f29dbc25Smrg        }
1436f29dbc25Smrg    }
1437f29dbc25Smrg
1438f29dbc25Smrg    if (gfx_is_display_mode_supported(pMode->CrtcHDisplay,
1439f29dbc25Smrg                                      pMode->CrtcVDisplay,
1440f29dbc25Smrg                                      pScrni->bitsPerPixel,
1441f29dbc25Smrg                                      GeodeGetRefreshRate(pMode)) < 0) {
1442f29dbc25Smrg        return MODE_BAD;
1443f29dbc25Smrg    }
1444f29dbc25Smrg
1445f29dbc25Smrg    if (pMode->Flags & V_INTERLACE)
1446f29dbc25Smrg	return MODE_NO_INTERLACE;
1447f29dbc25Smrg
1448f29dbc25Smrg    if (pGeode->tryCompression)
1449f29dbc25Smrg	p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay,
1450f29dbc25Smrg	    pScrni->bitsPerPixel);
1451f29dbc25Smrg    else
1452f29dbc25Smrg	p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
1453f29dbc25Smrg
1454f29dbc25Smrg    if (p * pMode->CrtcVDisplay > pGeode->FBAvail)
1455f29dbc25Smrg	return MODE_MEM;
1456f29dbc25Smrg
1457f29dbc25Smrg    return MODE_OK;
1458f29dbc25Smrg}
1459f29dbc25Smrg
1460f29dbc25Smrg/* XXX - Way more to do here */
1461f29dbc25Smrg
1462f29dbc25Smrgstatic Bool
1463f29dbc25SmrgGXEnterVT(int scrnIndex, int flags)
1464f29dbc25Smrg{
1465f29dbc25Smrg    return GXEnterGraphics(NULL, xf86Screens[scrnIndex]);
1466f29dbc25Smrg}
1467f29dbc25Smrg
1468f29dbc25Smrgstatic void
1469f29dbc25SmrgGXLeaveVT(int scrnIndex, int flags)
1470f29dbc25Smrg{
1471f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
1472f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1473f29dbc25Smrg
1474f29dbc25Smrg    pGeode->PrevDisplayOffset = gfx_get_display_offset();
1475f29dbc25Smrg    GXLeaveGraphics(xf86Screens[scrnIndex]);
1476f29dbc25Smrg}
1477f29dbc25Smrg
1478f29dbc25Smrgvoid
1479f29dbc25SmrgGXSetupChipsetFPtr(ScrnInfoPtr pScrn)
1480f29dbc25Smrg{
1481f29dbc25Smrg    pScrn->PreInit = GXPreInit;
1482f29dbc25Smrg    pScrn->ScreenInit = GXScreenInit;
1483f29dbc25Smrg    pScrn->SwitchMode = GXSwitchMode;
1484f29dbc25Smrg    pScrn->AdjustFrame = GXAdjustFrame;
1485f29dbc25Smrg    pScrn->EnterVT = GXEnterVT;
1486f29dbc25Smrg    pScrn->LeaveVT = GXLeaveVT;
1487f29dbc25Smrg    pScrn->FreeScreen = GeodeFreeScreen;
1488f29dbc25Smrg    pScrn->ValidMode = GXValidMode;
1489f29dbc25Smrg}
1490f29dbc25Smrg
1491f29dbc25Smrg/* ====== Common functions ======
1492f29dbc25Smrg * These are all the common functions that we use for both GX and LX - They live here
1493f29dbc25Smrg * because most of them came along for the GX first, and then were adapted to the LX.
1494f29dbc25Smrg *  We could move these to a common function, but there is no hurry
1495f29dbc25Smrg * ============================== */
1496f29dbc25Smrg
1497f29dbc25Smrgvoid
1498f29dbc25SmrgGeodePointerMoved(int index, int x, int y)
1499f29dbc25Smrg{
1500f29dbc25Smrg    ScrnInfoPtr pScrni = xf86Screens[index];
1501f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(pScrni);
1502f29dbc25Smrg
1503f29dbc25Smrg    int newX = x, newY = y;
1504f29dbc25Smrg
1505f29dbc25Smrg    switch (pGeode->rotation) {
1506f29dbc25Smrg    case RR_Rotate_0:
1507f29dbc25Smrg	break;
1508f29dbc25Smrg    case RR_Rotate_90:
1509f29dbc25Smrg	newX = y;
1510f29dbc25Smrg	newY = pScrni->pScreen->width - x - 1;
1511f29dbc25Smrg	break;
1512f29dbc25Smrg    case RR_Rotate_180:
1513f29dbc25Smrg	newX = pScrni->pScreen->width - x - 1;
1514f29dbc25Smrg	newY = pScrni->pScreen->height - y - 1;
1515f29dbc25Smrg	break;
1516f29dbc25Smrg    case RR_Rotate_270:
1517f29dbc25Smrg	newX = pScrni->pScreen->height - y - 1;
1518f29dbc25Smrg	newY = x;
1519f29dbc25Smrg	break;
1520f29dbc25Smrg    }
1521f29dbc25Smrg
1522f29dbc25Smrg    (*pGeode->PointerMoved) (index, newX, newY);
1523f29dbc25Smrg}
1524f29dbc25Smrg
1525f29dbc25Smrgint
1526f29dbc25SmrgGeodeGetFPGeometry(const char *str, int *width, int *height)
1527f29dbc25Smrg{
1528f29dbc25Smrg
1529f29dbc25Smrg    int ret = sscanf(str, "%dx%d", width, height);
1530f29dbc25Smrg
1531f29dbc25Smrg    return (ret == 2) ? 0 : 1;
1532f29dbc25Smrg}
1533f29dbc25Smrg
1534f29dbc25Smrgstatic void
1535f29dbc25SmrgGeodeFreeRec(ScrnInfoPtr pScrni)
1536f29dbc25Smrg{
1537f29dbc25Smrg    if (pScrni->driverPrivate != NULL) {
1538f29dbc25Smrg	xfree(pScrni->driverPrivate);
1539f29dbc25Smrg	pScrni->driverPrivate = NULL;
1540f29dbc25Smrg    }
1541f29dbc25Smrg}
1542f29dbc25Smrg
1543f29dbc25Smrgvoid
1544f29dbc25SmrgGeodeFreeScreen(int scrnIndex, int flags)
1545f29dbc25Smrg{
1546f29dbc25Smrg    GeodeRec *pGeode = GEODEPTR(xf86Screens[scrnIndex]);
1547f29dbc25Smrg
1548f29dbc25Smrg    if (pGeode == NULL)
1549f29dbc25Smrg	return;
1550f29dbc25Smrg
1551f29dbc25Smrg    if (pGeode->useVGA) {
1552f29dbc25Smrg	if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1553f29dbc25Smrg	    vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1554f29dbc25Smrg    }
1555f29dbc25Smrg
1556f29dbc25Smrg    GeodeFreeRec(xf86Screens[scrnIndex]);
1557f29dbc25Smrg}
1558f29dbc25Smrg
1559f29dbc25Smrgint
1560f29dbc25SmrgGeodeCalculatePitchBytes(unsigned int width, unsigned int bpp)
1561f29dbc25Smrg{
1562f29dbc25Smrg
1563f29dbc25Smrg    int delta = width * (bpp >> 3);
1564f29dbc25Smrg
1565f29dbc25Smrg    /* Less then 640 has doubling enabled */
1566f29dbc25Smrg
1567f29dbc25Smrg    if (width < 640)
1568f29dbc25Smrg	delta <<= 1;
1569f29dbc25Smrg
1570f29dbc25Smrg    /* Calculate the pitch (compression rquires a power of 2) */
1571f29dbc25Smrg
1572f29dbc25Smrg    if (delta > 4096)
1573f29dbc25Smrg	delta = 8192;
1574f29dbc25Smrg    else if (delta > 2048)
1575f29dbc25Smrg	delta = 4096;
1576f29dbc25Smrg    else if (delta > 1024)
1577f29dbc25Smrg	delta = 2048;
1578f29dbc25Smrg    else
1579f29dbc25Smrg	delta = 1024;
1580f29dbc25Smrg
1581f29dbc25Smrg    return delta;
1582f29dbc25Smrg}
1583