01d2267411
with and ok matthieu
1597 lines
40 KiB
C
1597 lines
40 KiB
C
/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc.
|
|
*
|
|
* Portioned modeled from xf86-video-intel/src/i830_driver.c
|
|
* Copyright 2001 VA Linux Systems Inc., Fremont, California.
|
|
* Copyright \ufffd 2002 by David Dawes
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*
|
|
* Neither the name of the Advanced Micro Devices, Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
#include "xf86Resources.h"
|
|
#include "xf86cmap.h"
|
|
#include "compiler.h"
|
|
#include "mipointer.h"
|
|
#include "shadow.h"
|
|
#include <X11/extensions/randr.h>
|
|
#include "fb.h"
|
|
#include "miscstruct.h"
|
|
#include "micmap.h"
|
|
#include "vbe.h"
|
|
#include "fb.h"
|
|
#include "randrstr.h"
|
|
|
|
#include "geode.h"
|
|
#include "gfx_defs.h"
|
|
#include "gfx_regs.h"
|
|
#include "panel.h"
|
|
|
|
/* Bring in VGA functions */
|
|
#include "gx_vga.c"
|
|
|
|
#define GX_MIN_PITCH 1024
|
|
#define GX_MAX_PITCH 8192
|
|
#define GX_MAX_WIDTH 1600
|
|
#define GX_MIN_HEIGHT 400
|
|
#define GX_MAX_HEIGHT 1200
|
|
#define GX_CB_PITCH 544
|
|
#define GX_CB_SIZE 544
|
|
|
|
#define GX_CPU_REG_SIZE 0x4000
|
|
#define GX_GP_REG_SIZE 0x4000
|
|
#define GX_VID_REG_SIZE 0x4000
|
|
|
|
extern OptionInfoRec GX_GeodeOptions[];
|
|
|
|
extern const char *amdVgahwSymbols[];
|
|
extern const char *amdVbeSymbols[];
|
|
extern const char *amdInt10Symbols[];
|
|
extern const char *amdFbSymbols[];
|
|
extern const char *amdXaaSymbols[];
|
|
extern const char *amdExaSymbols[];
|
|
extern const char *amdRamdacSymbols[];
|
|
|
|
unsigned char *XpressROMPtr;
|
|
|
|
static inline void
|
|
gx_enable_dac_power(void)
|
|
{
|
|
gfx_write_vid32(RCDF_VID_MISC,
|
|
gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH);
|
|
}
|
|
|
|
static inline void
|
|
gx_disable_dac_power(void)
|
|
{
|
|
gfx_write_vid32(RCDF_VID_MISC,
|
|
RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN |
|
|
(gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH));
|
|
}
|
|
|
|
static void
|
|
GXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
|
|
{
|
|
GeodePtr pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) {
|
|
pGeode->exaBfrOffset = *offset;
|
|
*offset += pGeode->exaBfrOffset;
|
|
*avail -= pGeode->exaBfrOffset;
|
|
}
|
|
}
|
|
|
|
static void
|
|
GXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail)
|
|
{
|
|
GeodePtr pGeode = GEODEPTR(pScrni);
|
|
unsigned int size, i, pitch;
|
|
|
|
/* XXX - FIXME - What if we are out of room? Then what? */
|
|
/* For now, we NULL them all out. */
|
|
|
|
if (pGeode->NoOfImgBuffers > 0) {
|
|
size = pGeode->displayPitch * pGeode->NoOfImgBuffers;
|
|
if (size <= *avail) {
|
|
for (i = 0; i < pGeode->NoOfImgBuffers; i++) {
|
|
pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset;
|
|
*offset += pGeode->displayPitch;
|
|
*avail -= pGeode->displayPitch;
|
|
}
|
|
} else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Not enough memory for image write buffers.\n");
|
|
|
|
for (i = 0; i < pGeode->NoOfImgBuffers; i++)
|
|
pGeode->AccelImageWriteBuffers[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if (pGeode->NoOfColorExpandLines > 0) {
|
|
pitch = ((pGeode->displayPitch + 31) >> 5) << 2;
|
|
size = pitch * pGeode->NoOfColorExpandLines;
|
|
|
|
if (size <= *avail) {
|
|
for (i = 0; i < pGeode->NoOfColorExpandLines; i++) {
|
|
pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset;
|
|
*offset += pitch;
|
|
*avail -= pitch;
|
|
}
|
|
} else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Not enough memory for color expansion buffers.\n");
|
|
|
|
for (i = 0; i < pGeode->NoOfImgBuffers; i++)
|
|
pGeode->AccelColorExpandBuffers[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
GXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate)
|
|
{
|
|
GeodePtr pGeode = GEODEPTR(pScrni);
|
|
|
|
unsigned int fboffset, fbavail;
|
|
unsigned int size;
|
|
unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8;
|
|
BOOL ret = TRUE;
|
|
|
|
if (pGeode->tryCompression)
|
|
pGeode->displayPitch =
|
|
GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
|
|
else
|
|
pGeode->displayPitch =
|
|
((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
|
|
|
|
pGeode->Pitch = pGeode->displayPitch;
|
|
pGeode->displayWidth = pGeode->displayPitch / bytpp;
|
|
pScrni->displayWidth = pGeode->displayWidth;
|
|
|
|
fbavail = pGeode->FBAvail - 0x4000;
|
|
|
|
pGeode->displayOffset = fboffset = 0;
|
|
pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch;
|
|
|
|
fbavail -= pGeode->displaySize;
|
|
fboffset += pGeode->displaySize;
|
|
|
|
if (pGeode->tryCompression) {
|
|
size = pScrni->virtualY * GX_CB_PITCH;
|
|
|
|
if (size <= fbavail) {
|
|
pGeode->CBData.compression_offset = fboffset;
|
|
|
|
fboffset += size;
|
|
fbavail -= size;
|
|
|
|
pGeode->Compression = TRUE;
|
|
} else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Not enough memory for compression\n");
|
|
pGeode->Compression = FALSE;
|
|
}
|
|
}
|
|
|
|
if (pGeode->tryHWCursor) {
|
|
pGeode->CursorSize = 1024;
|
|
|
|
if (pGeode->CursorSize <= fbavail) {
|
|
pGeode->CursorStartOffset = fboffset;
|
|
fboffset += pGeode->CursorSize;
|
|
fbavail -= pGeode->CursorSize;
|
|
pGeode->HWCursor = TRUE;
|
|
} else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Not enough memory for the hardware cursor\n");
|
|
pGeode->HWCursor = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!pGeode->NoAccel) {
|
|
if (pGeode->useEXA)
|
|
GXInitEXAMemory(pScrni, &fboffset, &fbavail);
|
|
else
|
|
GXInitXAAMemory(pScrni, &fboffset, &fbavail);
|
|
}
|
|
|
|
pGeode->shadowSize = 0;
|
|
|
|
if (rotate != RR_Rotate_0) {
|
|
if (rotate & (RR_Rotate_90 | RR_Rotate_270))
|
|
size = pGeode->displayPitch * pScrni->virtualX;
|
|
else
|
|
size = pGeode->displayPitch * pScrni->virtualY;
|
|
|
|
if (size <= fbavail) {
|
|
pGeode->shadowOffset = fboffset;
|
|
pGeode->shadowSize = size;
|
|
|
|
fboffset += size;
|
|
fbavail -= size;
|
|
} else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Not enough memory for the shadow framebuffer\n");
|
|
ret = FALSE;
|
|
}
|
|
}
|
|
|
|
/* XAA always exists - we can't remove it on demand like we can with EXA.
|
|
* So we assume the worse, and only give XAA enough offspace room to
|
|
* account for any eventuality that RandR might throw at us. */
|
|
|
|
if (!pGeode->NoAccel) {
|
|
|
|
if (pGeode->useEXA && pGeode->pExa) {
|
|
ExaDriverPtr pExa = pGeode->pExa;
|
|
|
|
pExa->offScreenBase = fboffset;
|
|
pExa->memorySize = fboffset + fbavail;
|
|
}
|
|
|
|
if (!pGeode->useEXA) {
|
|
|
|
if (!xf86FBManagerRunning(pScrn)) {
|
|
|
|
unsigned int offset = fboffset;
|
|
unsigned int avail = fbavail;
|
|
RegionRec OffscreenRegion;
|
|
BoxRec AvailBox;
|
|
|
|
/* Assume the shadow FB exists even if it doesnt */
|
|
|
|
if (pGeode->shadowSize == 0) {
|
|
size = (pScrn->width * bytpp) * pScrni->virtualX;
|
|
offset += size;
|
|
avail -= size;
|
|
}
|
|
|
|
AvailBox.x1 = 0;
|
|
AvailBox.y1 =
|
|
(offset + pGeode->displayPitch -
|
|
1) / pGeode->displayPitch;
|
|
|
|
AvailBox.x2 = pGeode->displayWidth;
|
|
AvailBox.y2 = (offset + avail) / pGeode->displayPitch;
|
|
|
|
if (AvailBox.y1 < AvailBox.y2) {
|
|
REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2);
|
|
|
|
if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion))
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Memory manager initialization failed.\n");
|
|
|
|
REGION_UNINIT(pScrn, &OffscreenRegion);
|
|
} else
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO,
|
|
"Cache disabled - no offscreen memory available.\n");
|
|
} else
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO,
|
|
"XAA offscreen memory has already been allocated.\n");
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static Bool
|
|
GXSaveScreen(ScreenPtr pScrn, int mode)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
|
|
GeodePtr pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->useVGA && !pScrni->vtSema)
|
|
return vgaHWSaveScreen(pScrn, mode);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Common function - used by the LX too */
|
|
#ifdef XSERVER_LIBPCIACCESS
|
|
static inline void *
|
|
map_pci_mem(ScrnInfoPtr pScrni, int vram,
|
|
struct pci_device *dev, int bar, int size)
|
|
{
|
|
void *ptr;
|
|
void **result = (void **)&ptr;
|
|
int map_size = size ? size : dev->regions[bar].size;
|
|
|
|
int err = pci_device_map_range(dev,
|
|
dev->regions[bar].base_addr,
|
|
map_size,
|
|
PCI_DEV_MAP_FLAG_WRITABLE |
|
|
(vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
|
|
result);
|
|
|
|
if (err)
|
|
return NULL;
|
|
return ptr;
|
|
}
|
|
#endif
|
|
|
|
extern unsigned long gfx_gx2_scratch_base;
|
|
|
|
static Bool
|
|
GXMapMem(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int index = pScrni->scrnIndex;
|
|
|
|
pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
|
|
|
|
#ifndef XSERVER_LIBPCIACCESS
|
|
gfx_virt_regptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
|
|
pci->memBase[2], pci->size[2]);
|
|
|
|
gfx_virt_gpptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
|
|
pci->memBase[1], pci->size[1]);
|
|
|
|
gfx_virt_vidptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_MMIO,
|
|
pci->memBase[3], pci->size[3]);
|
|
|
|
gfx_virt_fbptr = (unsigned char *)xf86MapVidMem(index, VIDMEM_FRAMEBUFFER,
|
|
pci->memBase[0], pGeode->FBAvail);
|
|
#else
|
|
gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0);
|
|
gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0);
|
|
gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0);
|
|
gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail);
|
|
#endif
|
|
|
|
gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000;
|
|
|
|
XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
|
|
|
|
pGeode->FBBase = gfx_virt_fbptr;
|
|
|
|
if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) ||
|
|
(!gfx_virt_vidptr) || (!gfx_virt_fbptr))
|
|
return FALSE;
|
|
|
|
if (!pGeode->NoAccel && pGeode->useEXA)
|
|
pGeode->pExa->memoryBase = pGeode->FBBase;
|
|
|
|
xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n",
|
|
pGeode->FBAvail, pGeode->FBBase);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Check to see if VGA exists - we map the space and look for a
|
|
signature - if it doesn't match exactly, then we assume no VGA.
|
|
*/
|
|
|
|
static Bool
|
|
GXCheckVGA(ScrnInfoPtr pScrni)
|
|
{
|
|
|
|
unsigned char *ptr;
|
|
const char *vgasig = "IBM VGA Compatible";
|
|
int ret;
|
|
|
|
ptr =
|
|
xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
|
|
strlen(vgasig));
|
|
|
|
if (ptr == NULL)
|
|
return FALSE;
|
|
|
|
ret = memcmp(ptr, vgasig, strlen(vgasig));
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
|
|
|
|
return ret ? FALSE : TRUE;
|
|
}
|
|
|
|
static Bool
|
|
GXPreInit(ScrnInfoPtr pScrni, int flags)
|
|
{
|
|
GeodePtr pGeode;
|
|
ClockRangePtr GeodeClockRange;
|
|
OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0];
|
|
int ret;
|
|
QQ_WORD msrValue;
|
|
EntityInfoPtr pEnt;
|
|
rgb defaultWeight = { 0, 0, 0 };
|
|
int modecnt;
|
|
char *s, *panelgeo;
|
|
Bool useVGA;
|
|
|
|
if (pScrni->numEntities != 1)
|
|
return FALSE;
|
|
|
|
pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
|
|
if (pEnt->resources)
|
|
return FALSE;
|
|
|
|
pGeode = pScrni->driverPrivate = xnfcalloc(sizeof(GeodeRec), 1);
|
|
|
|
if (pGeode == NULL)
|
|
return FALSE;
|
|
|
|
useVGA = GXCheckVGA(pScrni);
|
|
|
|
if (flags & PROBE_DETECT) {
|
|
GeodeProbeDDC(pScrni, pEnt->index);
|
|
return TRUE;
|
|
}
|
|
|
|
/* Probe for VGA */
|
|
pGeode->useVGA = useVGA;
|
|
pGeode->pEnt = pEnt;
|
|
|
|
if (pGeode->useVGA) {
|
|
if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
|
|
pGeode->useVGA = FALSE;
|
|
|
|
#if INT10_SUPPORT
|
|
pGeode->vesa = xcalloc(sizeof(VESARec), 1);
|
|
#endif
|
|
}
|
|
|
|
gfx_msr_init();
|
|
|
|
ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue);
|
|
|
|
if (!ret) {
|
|
pGeode->Output =
|
|
((msrValue.low & RCDF_CONFIG_FMT_MASK) ==
|
|
RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT;
|
|
}
|
|
|
|
/* Fill in the monitor information */
|
|
pScrni->monitor = pScrni->confScreen->monitor;
|
|
|
|
if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
|
|
return FALSE;
|
|
|
|
switch (pScrni->depth) {
|
|
case 8:
|
|
pScrni->rgbBits = 8;
|
|
case 16:
|
|
case 24:
|
|
case 32:
|
|
break;
|
|
default:
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"The driver does not support %d as a depth.\n", pScrni->depth);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PrintDepthBpp(pScrni);
|
|
|
|
if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
|
|
return FALSE;
|
|
|
|
if (!xf86SetDefaultVisual(pScrni, -1))
|
|
return FALSE;
|
|
|
|
/*
|
|
* If the driver can do gamma correction, it should call xf86SetGamma()
|
|
* here.
|
|
*/
|
|
{
|
|
Gamma zeros = { 0.0, 0.0, 0.0 };
|
|
|
|
if (!xf86SetGamma(pScrni, zeros)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pScrni->progClock = TRUE;
|
|
xf86CollectOptions(pScrni, NULL);
|
|
xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
|
|
|
|
/* Set up our various options that may get reversed as we go on */
|
|
|
|
pGeode->FBVGAActive = FALSE;
|
|
pGeode->tryHWCursor = TRUE;
|
|
pGeode->tryCompression = TRUE;
|
|
|
|
pGeode->NoAccel = FALSE;
|
|
pGeode->useEXA = TRUE;
|
|
|
|
pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE;
|
|
|
|
pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS;
|
|
pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS;
|
|
pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
|
|
|
|
xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR,
|
|
&pGeode->tryHWCursor);
|
|
|
|
if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE,
|
|
(int *)&(pGeode->FBAvail)))
|
|
pGeode->FBAvail = 0;
|
|
|
|
/* For compatability - allow SWCursor too */
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE))
|
|
pGeode->tryHWCursor = FALSE;
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE))
|
|
pGeode->tryCompression = FALSE;
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE))
|
|
pGeode->NoAccel = TRUE;
|
|
|
|
pGeode->rotation = RR_Rotate_0;
|
|
|
|
if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) {
|
|
|
|
if (!xf86NameCmp(s, "LEFT"))
|
|
pGeode->rotation = RR_Rotate_90;
|
|
else if (!xf86NameCmp(s, "INVERT"))
|
|
pGeode->rotation = RR_Rotate_180;
|
|
else if (!xf86NameCmp(s, "CCW"))
|
|
pGeode->rotation = RR_Rotate_270;
|
|
else
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Invalid rotation %s.\n", s);
|
|
}
|
|
|
|
xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS,
|
|
&(pGeode->NoOfImgBuffers));
|
|
|
|
if (pGeode->NoOfImgBuffers <= 0)
|
|
pGeode->NoOfImgBuffers = 0;
|
|
|
|
xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
|
|
&(pGeode->NoOfColorExpandLines));
|
|
|
|
if (pGeode->NoOfColorExpandLines <= 0)
|
|
pGeode->NoOfColorExpandLines = 0;
|
|
|
|
xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS,
|
|
(int *)&(pGeode->exaBfrSz));
|
|
|
|
if (pGeode->exaBfrSz <= 0)
|
|
pGeode->exaBfrSz = 0;
|
|
|
|
if (pGeode->Panel == TRUE) {
|
|
if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE))
|
|
pGeode->Panel = FALSE;
|
|
}
|
|
|
|
panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY);
|
|
|
|
if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) {
|
|
if (!xf86NameCmp(s, "XAA"))
|
|
pGeode->useEXA = FALSE;
|
|
else if (xf86NameCmp(s, "EXA"))
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Unknown accleration method %s. Defaulting to EXA.\n", s);
|
|
}
|
|
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO,
|
|
"Using %s acceleration architecture\n",
|
|
pGeode->useEXA ? "EXA" : "XAA");
|
|
|
|
/* Set up the panel */
|
|
|
|
if (pGeode->Panel) {
|
|
if (panelgeo != NULL) {
|
|
if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX,
|
|
&pGeode->PanelY))
|
|
pGeode->Panel = FALSE;
|
|
}
|
|
#ifdef PNL_SUP
|
|
else {
|
|
int b, f;
|
|
|
|
/* The bitdepth and refresh isn't used anywhere else in the driver */
|
|
|
|
if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS()))
|
|
Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b,
|
|
&f);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Set up the VGA */
|
|
|
|
if (pGeode->useVGA) {
|
|
#if INT10_SUPPORT
|
|
VESARec *pVesa;
|
|
|
|
if (!xf86LoadSubModule(pScrni, "int10"))
|
|
return FALSE;
|
|
xf86LoaderReqSymLists(amdInt10Symbols, NULL);
|
|
|
|
pVesa = pGeode->vesa;
|
|
|
|
if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Unable to initialize 1NT10 support\n");
|
|
pGeode->useVGA = FALSE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* First try to get the framebuffer size from the framebuffer,
|
|
* and if that fails, revert all the way back to the legacy
|
|
* method
|
|
*/
|
|
|
|
if (pGeode->FBAvail == 0) {
|
|
if (GeodeGetSizeFromFB(&pGeode->FBAvail))
|
|
pGeode->FBAvail = gfx_get_frame_buffer_size();
|
|
}
|
|
|
|
if (pScrni->memPhysBase == 0)
|
|
pScrni->memPhysBase = gfx_get_frame_buffer_base();
|
|
|
|
pScrni->fbOffset = 0;
|
|
|
|
if (pGeode->pEnt->device->videoRam == 0)
|
|
pScrni->videoRam = pGeode->FBAvail / 1024;
|
|
else
|
|
pScrni->videoRam = pGeode->pEnt->device->videoRam;
|
|
|
|
pGeode->maxWidth = GX_MAX_WIDTH;
|
|
pGeode->maxHeight = GX_MAX_HEIGHT;
|
|
|
|
GeodeClockRange = (ClockRangePtr) xnfcalloc(sizeof(ClockRange), 1);
|
|
GeodeClockRange->next = NULL;
|
|
GeodeClockRange->minClock = 25175;
|
|
GeodeClockRange->maxClock = 229500;
|
|
GeodeClockRange->clockIndex = -1;
|
|
GeodeClockRange->interlaceAllowed = TRUE;
|
|
GeodeClockRange->doubleScanAllowed = FALSE;
|
|
|
|
pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index);
|
|
|
|
/* I'm still not 100% sure this uses the right values */
|
|
|
|
modecnt = xf86ValidateModes(pScrni,
|
|
pScrni->monitor->Modes,
|
|
pScrni->display->modes,
|
|
GeodeClockRange,
|
|
NULL, GX_MIN_PITCH, GX_MAX_PITCH,
|
|
32, GX_MIN_HEIGHT, GX_MAX_HEIGHT,
|
|
pScrni->display->virtualX,
|
|
pScrni->display->virtualY, pGeode->FBAvail, LOOKUP_BEST_REFRESH);
|
|
|
|
if (modecnt <= 0) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PruneDriverModes(pScrni);
|
|
|
|
if (pScrni->modes == NULL) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n");
|
|
return FALSE;
|
|
}
|
|
|
|
xf86SetCrtcForModes(pScrni, 0);
|
|
pScrni->currentMode = pScrni->modes;
|
|
|
|
xf86PrintModes(pScrni);
|
|
xf86SetDpi(pScrni, 0, 0);
|
|
|
|
/* Load the modules we'll need */
|
|
|
|
if (xf86LoadSubModule(pScrni, "fb") == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(amdFbSymbols, NULL);
|
|
|
|
if (pGeode->NoAccel == FALSE) {
|
|
const char *module = (pGeode->useEXA) ? "exa" : "xaa";
|
|
const char **symbols = (pGeode->useEXA) ?
|
|
&amdExaSymbols[0] : &amdXaaSymbols[0];
|
|
|
|
if (!xf86LoadSubModule(pScrni, module)) {
|
|
return FALSE;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(symbols, NULL);
|
|
}
|
|
|
|
if (pGeode->tryHWCursor == TRUE) {
|
|
if (!xf86LoadSubModule(pScrni, "ramdac")) {
|
|
return FALSE;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(amdRamdacSymbols, NULL);
|
|
}
|
|
|
|
if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Couldn't register the resources.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
GXRestore(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->useVGA && pGeode->FBVGAActive) {
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
vgaHWProtect(pScrni, TRUE);
|
|
vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
|
|
vgaHWProtect(pScrni, FALSE);
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
GXUnmapMem(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
/* unmap all the memory map's */
|
|
|
|
xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
GXSetDvLineSize(unsigned int pitch)
|
|
{
|
|
unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024;
|
|
|
|
if (pitch > 1024) {
|
|
dv_size = MDC_DV_LINE_SIZE_2048;
|
|
}
|
|
if (pitch > 2048) {
|
|
dv_size = MDC_DV_LINE_SIZE_4096;
|
|
}
|
|
if (pitch > 4096) {
|
|
dv_size = MDC_DV_LINE_SIZE_8192;
|
|
}
|
|
|
|
/* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
|
|
|
|
temp = READ_REG32(MDC_DV_CTL);
|
|
WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size);
|
|
}
|
|
|
|
/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */
|
|
|
|
static void
|
|
GXAdjustFrame(int scrnIndex, int x, int y, int flags)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
unsigned long offset;
|
|
|
|
offset =
|
|
pGeode->FBOffset + y * pGeode->Pitch +
|
|
x * (pScrni->bitsPerPixel >> 3);
|
|
|
|
gfx_set_display_offset(offset);
|
|
}
|
|
|
|
static Bool
|
|
GXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int flags = 0;
|
|
int custom = 0;
|
|
|
|
pScrni->vtSema = TRUE;
|
|
|
|
gx_disable_dac_power();
|
|
|
|
if (pMode->Flags & V_NHSYNC)
|
|
flags |= 1;
|
|
if (pMode->Flags & V_NVSYNC)
|
|
flags |= 2;
|
|
|
|
/* Check to see if we should use custom or built-in timings */
|
|
|
|
if (pGeode->Panel)
|
|
custom = (pMode->type & M_T_USERDEF);
|
|
else
|
|
custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
|
|
|
|
/* If we're not doing a custom mode, then just set the fixed timings,
|
|
* otherwise, do the whole shooting match */
|
|
|
|
if (!custom) {
|
|
GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY,
|
|
pMode->CrtcHDisplay, pMode->CrtcVDisplay,
|
|
pScrni->bitsPerPixel));
|
|
} else {
|
|
if (pGeode->Panel)
|
|
GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY,
|
|
pMode->CrtcHDisplay, pMode->CrtcVDisplay,
|
|
pScrni->bitsPerPixel));
|
|
|
|
GFX(set_display_timings(pScrni->bitsPerPixel, flags,
|
|
pMode->CrtcHDisplay, pMode->CrtcHBlankStart,
|
|
pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd,
|
|
pMode->CrtcHBlankEnd, pMode->CrtcHTotal,
|
|
pMode->CrtcVDisplay, pMode->CrtcVBlankStart,
|
|
pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd,
|
|
pMode->CrtcVBlankEnd, pMode->CrtcVTotal,
|
|
(int)((pMode->SynthClock / 1000.0) * 0x10000)));
|
|
}
|
|
|
|
GFX(set_crt_enable(CRT_ENABLE));
|
|
GFX(set_display_pitch(pGeode->displayPitch));
|
|
GFX(set_display_offset(0L));
|
|
GFX(wait_vertical_blank());
|
|
|
|
if (pGeode->Compression) {
|
|
GXSetDvLineSize(pGeode->Pitch);
|
|
|
|
gfx_set_compression_offset(pGeode->CBData.compression_offset);
|
|
gfx_set_compression_pitch(GX_CB_PITCH);
|
|
gfx_set_compression_size(GX_CB_SIZE);
|
|
|
|
gfx_set_compression_enable(1);
|
|
}
|
|
|
|
if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) {
|
|
GXLoadCursorImage(pScrni, NULL);
|
|
GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0));
|
|
GXShowCursor(pScrni);
|
|
} else {
|
|
GFX(set_cursor_enable(0));
|
|
pGeode->HWCursor = FALSE;
|
|
}
|
|
|
|
GXAdjustFrame(pScrni->scrnIndex, pScrni->frameX0, pScrni->frameY0, 0);
|
|
gx_enable_dac_power();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
GXSwitchMode(int index, DisplayModePtr pMode, int flags)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[index];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int ret = TRUE;
|
|
int rotate;
|
|
|
|
/* Syn the engine and shutdown the DAC momentarily */
|
|
|
|
gfx_wait_until_idle();
|
|
|
|
/* Set up the memory for the new mode */
|
|
rotate = GXGetRotation(pScrni->pScreen);
|
|
ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate);
|
|
|
|
if (ret) {
|
|
if (pGeode->curMode != pMode)
|
|
ret = GXSetVideoMode(pScrni, pMode);
|
|
}
|
|
|
|
if (ret)
|
|
ret = GXRotate(pScrni, pMode);
|
|
|
|
/* Go back the way it was */
|
|
|
|
if (ret == FALSE) {
|
|
if (!GXSetVideoMode(pScrni, pGeode->curMode))
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Could not restore the previous mode\n");
|
|
} else
|
|
pGeode->curMode = pMode;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
GXLeaveGraphics(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
gfx_wait_until_idle();
|
|
|
|
/* Restore VG registers */
|
|
gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp,
|
|
pGeode->FBgfxdisplaytiming.wPolarity,
|
|
pGeode->FBgfxdisplaytiming.wHActive,
|
|
pGeode->FBgfxdisplaytiming.wHBlankStart,
|
|
pGeode->FBgfxdisplaytiming.wHSyncStart,
|
|
pGeode->FBgfxdisplaytiming.wHSyncEnd,
|
|
pGeode->FBgfxdisplaytiming.wHBlankEnd,
|
|
pGeode->FBgfxdisplaytiming.wHTotal,
|
|
pGeode->FBgfxdisplaytiming.wVActive,
|
|
pGeode->FBgfxdisplaytiming.wVBlankStart,
|
|
pGeode->FBgfxdisplaytiming.wVSyncStart,
|
|
pGeode->FBgfxdisplaytiming.wVSyncEnd,
|
|
pGeode->FBgfxdisplaytiming.wVBlankEnd,
|
|
pGeode->FBgfxdisplaytiming.wVTotal,
|
|
pGeode->FBgfxdisplaytiming.dwDotClock);
|
|
|
|
gfx_set_compression_enable(0);
|
|
|
|
/* Restore the previous Compression state */
|
|
if (pGeode->FBCompressionEnable) {
|
|
gfx_set_compression_offset(pGeode->FBCompressionOffset);
|
|
gfx_set_compression_pitch(pGeode->FBCompressionPitch);
|
|
gfx_set_compression_size(pGeode->FBCompressionSize);
|
|
gfx_set_compression_enable(1);
|
|
}
|
|
|
|
gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch);
|
|
|
|
gfx_set_display_offset(pGeode->FBDisplayOffset);
|
|
|
|
/* Restore Cursor */
|
|
gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0);
|
|
|
|
if (pGeode->useVGA) {
|
|
pGeode->vesa->pInt->num = 0x10;
|
|
pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
|
|
pGeode->vesa->pInt->bx = 0;
|
|
xf86ExecX86int10(pGeode->vesa->pInt);
|
|
gfx_delay_milliseconds(3);
|
|
}
|
|
|
|
GXRestore(pScrni);
|
|
|
|
gx_enable_dac_power();
|
|
}
|
|
|
|
static Bool
|
|
GXCloseScreen(int scrnIndex, ScreenPtr pScrn)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pScrni->vtSema)
|
|
GXLeaveGraphics(pScrni);
|
|
|
|
if (pGeode->AccelInfoRec)
|
|
XAADestroyInfoRec(pGeode->AccelInfoRec);
|
|
|
|
if (pGeode->AccelImageWriteBuffers) {
|
|
xfree(pGeode->AccelImageWriteBuffers[0]);
|
|
xfree(pGeode->AccelImageWriteBuffers);
|
|
pGeode->AccelImageWriteBuffers = NULL;
|
|
}
|
|
|
|
if (pGeode->AccelColorExpandBuffers) {
|
|
xfree(pGeode->AccelColorExpandBuffers);
|
|
pGeode->AccelColorExpandBuffers = NULL;
|
|
}
|
|
|
|
if (pGeode->pExa) {
|
|
exaDriverFini(pScrn);
|
|
xfree(pGeode->pExa);
|
|
pGeode->pExa = NULL;
|
|
}
|
|
|
|
pScrni->vtSema = FALSE;
|
|
|
|
GXUnmapMem(pScrni);
|
|
|
|
pScrni->PointerMoved = pGeode->PointerMoved;
|
|
pScrn->CloseScreen = pGeode->CloseScreen;
|
|
|
|
if (pScrn->CloseScreen)
|
|
return (*pScrn->CloseScreen) (scrnIndex, pScrn);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
GXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (!GXMapMem(pScrni))
|
|
return FALSE;
|
|
|
|
if (pGeode->useVGA)
|
|
pGeode->FBVGAActive = gu2_get_vga_active();
|
|
|
|
gfx_wait_until_idle();
|
|
|
|
/* Save off the current state (should this be somewhere else)? */
|
|
|
|
pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency();
|
|
pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch();
|
|
pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp();
|
|
pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal();
|
|
pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive();
|
|
pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start();
|
|
pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end();
|
|
pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start();
|
|
pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end();
|
|
pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal();
|
|
pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive();
|
|
pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start();
|
|
pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end();
|
|
pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start();
|
|
pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end();
|
|
pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities();
|
|
|
|
pGeode->FBDisplayOffset = gfx_get_display_offset();
|
|
|
|
if (pGeode->useVGA) {
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
|
|
}
|
|
|
|
pGeode->FBCompressionEnable = gfx_get_compression_enable();
|
|
pGeode->FBCompressionOffset = gfx_get_compression_offset();
|
|
pGeode->FBCompressionPitch = gfx_get_compression_pitch();
|
|
pGeode->FBCompressionSize = gfx_get_compression_size();
|
|
|
|
#ifdef PNL_SUP
|
|
Pnl_SavePanelState();
|
|
#endif
|
|
|
|
/* Turn off the VGA */
|
|
|
|
if (pGeode->useVGA && pGeode->FBVGAActive) {
|
|
unsigned short sequencer;
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
/* Map VGA aperture */
|
|
if (!vgaHWMapMem(pScrni))
|
|
return FALSE;
|
|
|
|
/* Unlock VGA registers */
|
|
vgaHWUnlock(pvgaHW);
|
|
|
|
/* Save the current state and setup the current mode */
|
|
vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
|
|
|
|
/* DISABLE VGA SEQUENCER */
|
|
/* This allows the VGA state machine to terminate. We must delay */
|
|
/* such that there are no pending MBUS requests. */
|
|
|
|
gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
|
|
sequencer = gfx_inb(MDC_SEQUENCER_DATA);
|
|
sequencer |= MDC_CLK_MODE_SCREEN_OFF;
|
|
gfx_outb(MDC_SEQUENCER_DATA, sequencer);
|
|
|
|
gfx_delay_milliseconds(1);
|
|
|
|
/* BLANK THE VGA DISPLAY */
|
|
gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET);
|
|
sequencer = gfx_inb(MDC_SEQUENCER_DATA);
|
|
sequencer &= ~MDC_RESET_VGA_DISP_ENABLE;
|
|
gfx_outb(MDC_SEQUENCER_DATA, sequencer);
|
|
|
|
gfx_delay_milliseconds(1);
|
|
}
|
|
|
|
/* Set up the memory */
|
|
/* XXX - FIXME - when we alow inital rotation, it should be here */
|
|
GXAllocateMemory(pScrn, pScrni, pGeode->rotation);
|
|
|
|
/* Clear the framebuffer */
|
|
memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize);
|
|
|
|
/* Set up the video mode */
|
|
GXSetVideoMode(pScrni, pScrni->currentMode);
|
|
pGeode->curMode = pScrni->currentMode;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
GXLoadPalette(ScrnInfoPtr pScrni,
|
|
int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
|
|
{
|
|
int i, index, color;
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
index = indizes[i] & 0xFF;
|
|
color = (((unsigned long)(colors[index].red & 0xFF)) << 16) |
|
|
(((unsigned long)(colors[index].green & 0xFF)) << 8) |
|
|
((unsigned long)(colors[index].blue & 0xFF));
|
|
|
|
GFX(set_display_palette_entry(index, color));
|
|
}
|
|
}
|
|
|
|
#ifdef DPMSExtension
|
|
static void
|
|
GXPanelPower(int enable)
|
|
{
|
|
unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT);
|
|
|
|
if (enable != 0)
|
|
power |= RCDF_PM_PANEL_POWER_ON;
|
|
else
|
|
power &= ~RCDF_PM_PANEL_POWER_ON;
|
|
|
|
WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
|
|
}
|
|
|
|
static void
|
|
GXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags)
|
|
{
|
|
GeodeRec *pGeode;
|
|
|
|
pGeode = GEODEPTR(pScrni);
|
|
|
|
if (!pScrni->vtSema)
|
|
return;
|
|
|
|
switch (mode) {
|
|
case DPMSModeOn:
|
|
/* Screen: On; HSync: On; VSync: On */
|
|
GFX(set_crt_enable(CRT_ENABLE));
|
|
#if defined(PNL_SUP)
|
|
if (pGeode->Panel) {
|
|
Pnl_PowerUp();
|
|
GXPanelPower(1);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case DPMSModeStandby:
|
|
/* Screen: Off; HSync: Off; VSync: On */
|
|
GFX(set_crt_enable(CRT_STANDBY));
|
|
#if defined(PNL_SUP)
|
|
if (pGeode->Panel) {
|
|
Pnl_PowerDown();
|
|
GXPanelPower(0);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case DPMSModeSuspend:
|
|
/* Screen: Off; HSync: On; VSync: Off */
|
|
GFX(set_crt_enable(CRT_SUSPEND));
|
|
#if defined(PNL_SUP)
|
|
if (pGeode->Panel) {
|
|
Pnl_PowerDown();
|
|
GXPanelPower(0);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case DPMSModeOff:
|
|
/* Screen: Off; HSync: Off; VSync: Off */
|
|
GFX(set_crt_enable(CRT_DISABLE));
|
|
#if defined(PNL_SUP)
|
|
if (pGeode->Panel) {
|
|
Pnl_PowerDown();
|
|
GXPanelPower(0);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static Bool
|
|
GXCreateScreenResources(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[pScreen->myNum];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
pScreen->CreateScreenResources = pGeode->CreateScreenResources;
|
|
if (!(*pScreen->CreateScreenResources) (pScreen))
|
|
return FALSE;
|
|
|
|
if (xf86LoaderCheckSymbol("GXRandRSetConfig")
|
|
&& pGeode->rotation != RR_Rotate_0) {
|
|
Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate,
|
|
RRScreenSizePtr pSize) = NULL;
|
|
|
|
RRScreenSize p;
|
|
Rotation requestedRotation = pGeode->rotation;
|
|
|
|
pGeode->rotation = RR_Rotate_0;
|
|
|
|
/* Just setup enough for an initial rotate */
|
|
|
|
p.width = pScreen->width;
|
|
p.height = pScreen->height;
|
|
p.mmWidth = pScreen->mmWidth;
|
|
p.mmHeight = pScreen->mmHeight;
|
|
|
|
GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig");
|
|
if (GXRandRSetConfig) {
|
|
pGeode->starting = TRUE;
|
|
(*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p);
|
|
pGeode->starting = FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
GXScreenInit(int scrnIndex, ScreenPtr pScrn, int argc, char **argv)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
XF86ModReqInfo shadowReq;
|
|
int maj, min, ret, rotate;
|
|
|
|
pGeode->starting = TRUE;
|
|
|
|
/* If we are using VGA then go ahead and map the memory */
|
|
|
|
if (pGeode->useVGA) {
|
|
|
|
if (!vgaHWMapMem(pScrni))
|
|
return FALSE;
|
|
|
|
vgaHWGetIOBase(VGAHWPTR(pScrni));
|
|
}
|
|
|
|
if (!pGeode->NoAccel) {
|
|
|
|
if (pGeode->useEXA) {
|
|
|
|
if (!(pGeode->pExa = xnfcalloc(sizeof(ExaDriverRec), 1))) {
|
|
xf86DrvMsg(scrnIndex, X_ERROR,
|
|
"Couldn't allocate the EXA structure.\n");
|
|
pGeode->NoAccel = TRUE;
|
|
} else {
|
|
ExaDriverPtr pExa = pGeode->pExa;
|
|
|
|
/* THis is set in GXAllocMem */
|
|
pExa->memoryBase = 0;
|
|
|
|
/* This is set in GXAllocateMemory */
|
|
pExa->memorySize = 0;
|
|
|
|
pExa->pixmapOffsetAlign = 32;
|
|
pExa->pixmapPitchAlign = 32;
|
|
pExa->flags = EXA_OFFSCREEN_PIXMAPS;
|
|
pExa->maxX = pGeode->maxWidth - 1;
|
|
pExa->maxY = pGeode->maxHeight - 1;
|
|
}
|
|
} else {
|
|
pGeode->AccelImageWriteBuffers =
|
|
xcalloc(sizeof(pGeode->AccelImageWriteBuffers[0]),
|
|
pGeode->NoOfImgBuffers);
|
|
pGeode->AccelColorExpandBuffers =
|
|
xcalloc(sizeof(pGeode->AccelColorExpandBuffers[0]),
|
|
pGeode->NoOfColorExpandLines);
|
|
}
|
|
}
|
|
|
|
/* XXX FIXME - Take down any of the structures on failure? */
|
|
|
|
if (!GXEnterGraphics(pScrn, pScrni))
|
|
return FALSE;
|
|
|
|
miClearVisualTypes();
|
|
|
|
/* XXX Again - take down anything? */
|
|
|
|
if (pScrni->bitsPerPixel > 8) {
|
|
if (!miSetVisualTypes(pScrni->depth,
|
|
TrueColorMask, pScrni->rgbBits, pScrni->defaultVisual)) {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
if (!miSetVisualTypes(pScrni->depth,
|
|
miGetDefaultVisualMask(pScrni->depth),
|
|
pScrni->rgbBits, pScrni->defaultVisual)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
miSetPixmapDepths();
|
|
|
|
/* Point at the visible area to start */
|
|
|
|
ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset,
|
|
pScrni->virtualX, pScrni->virtualY,
|
|
pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth,
|
|
pScrni->bitsPerPixel);
|
|
|
|
if (!ret)
|
|
return FALSE;
|
|
|
|
xf86SetBlackWhitePixels(pScrn);
|
|
|
|
/* Set up the color ordering */
|
|
|
|
if (pScrni->bitsPerPixel > 8) {
|
|
VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
|
|
|
|
while (--visual >= pScrn->visuals) {
|
|
if ((visual->class | DynamicClass) == DirectColor) {
|
|
visual->offsetRed = pScrni->offset.red;
|
|
visual->offsetGreen = pScrni->offset.green;
|
|
visual->offsetBlue = pScrni->offset.blue;
|
|
visual->redMask = pScrni->mask.red;
|
|
visual->greenMask = pScrni->mask.green;
|
|
visual->blueMask = pScrni->mask.blue;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Must follow the color ordering */
|
|
fbPictureInit(pScrn, 0, 0);
|
|
|
|
if (!pGeode->NoAccel)
|
|
GXAccelInit(pScrn);
|
|
|
|
miInitializeBackingStore(pScrn);
|
|
xf86SetBackingStore(pScrn);
|
|
|
|
/* Set up the soft cursor */
|
|
miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
|
|
|
|
/* Set up the HW cursor - must follow the soft cursor init */
|
|
|
|
if (pGeode->tryHWCursor) {
|
|
if (!GXHWCursorInit(pScrn))
|
|
xf86DrvMsg(scrnIndex, X_ERROR,
|
|
"Hardware cursor initialization failed.\n");
|
|
}
|
|
|
|
/* Set up the color map */
|
|
|
|
if (!miCreateDefColormap(pScrn))
|
|
return FALSE;
|
|
|
|
if (pScrni->bitsPerPixel == 8) {
|
|
/* Must follow initialization of the default colormap */
|
|
|
|
if (!xf86HandleColormaps(pScrn, 256, 8,
|
|
GXLoadPalette, NULL,
|
|
CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
#ifdef DPMSExtension
|
|
xf86DPMSInit(pScrn, GXDPMSSet, 0);
|
|
#endif
|
|
|
|
GXInitVideo(pScrn);
|
|
|
|
/* Set up RandR */
|
|
|
|
xf86DisableRandR(); /* We provide our own RandR goodness */
|
|
|
|
/* Try to set up the shadow FB for rotation */
|
|
|
|
memset(&shadowReq, 0, sizeof(shadowReq));
|
|
shadowReq.majorversion = 1;
|
|
shadowReq.minorversion = 1;
|
|
|
|
if (LoadSubModule(pScrni->module, "shadow",
|
|
NULL, NULL, NULL, &shadowReq, &maj, &min)) {
|
|
|
|
rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
|
|
shadowSetup(pScrn);
|
|
} else {
|
|
LoaderErrorMsg(NULL, "shadow", maj, min);
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Error loading shadow - rotation not available.\n");
|
|
|
|
if (pGeode->rotation != RR_Rotate_0)
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Reverting back to normal rotation.\n");
|
|
|
|
rotate = pGeode->rotation = RR_Rotate_0;
|
|
}
|
|
|
|
GXRandRInit(pScrn, rotate);
|
|
|
|
pGeode->PointerMoved = pScrni->PointerMoved;
|
|
pScrni->PointerMoved = GeodePointerMoved;
|
|
|
|
pGeode->CreateScreenResources = pScrn->CreateScreenResources;
|
|
pScrn->CreateScreenResources = GXCreateScreenResources;
|
|
|
|
pGeode->CloseScreen = pScrn->CloseScreen;
|
|
pScrn->CloseScreen = GXCloseScreen;
|
|
pScrn->SaveScreen = GXSaveScreen;
|
|
|
|
if (serverGeneration == 1)
|
|
xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
|
|
|
|
pGeode->starting = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
GXValidMode(int scrnIndex, DisplayModePtr pMode, Bool Verbose, int flags)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int p, ret;
|
|
int custom = 0;
|
|
|
|
if (pGeode->Panel)
|
|
custom = (pMode->type & M_T_USERDEF);
|
|
else
|
|
custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT));
|
|
|
|
/* Use the durango lookup for !custom modes */
|
|
|
|
if (!custom) {
|
|
if (pGeode->Panel) {
|
|
if (pMode->CrtcHDisplay > pGeode->PanelX ||
|
|
pMode->CrtcVDisplay > pGeode->PanelY ||
|
|
gfx_is_panel_mode_supported(pGeode->PanelX, pGeode->PanelY,
|
|
pMode->CrtcHDisplay, pMode->CrtcVDisplay,
|
|
pScrni->bitsPerPixel) < 0) {
|
|
|
|
return MODE_BAD;
|
|
}
|
|
}
|
|
|
|
ret = gfx_is_display_mode_supported(pMode->CrtcHDisplay,
|
|
pMode->CrtcVDisplay,
|
|
pScrni->bitsPerPixel, GeodeGetRefreshRate(pMode));
|
|
if (ret < 0)
|
|
return MODE_BAD;
|
|
}
|
|
|
|
if (pMode->Flags & V_INTERLACE)
|
|
return MODE_NO_INTERLACE;
|
|
|
|
if (pGeode->tryCompression)
|
|
p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay,
|
|
pScrni->bitsPerPixel);
|
|
else
|
|
p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
|
|
|
|
if (p * pMode->CrtcVDisplay > pGeode->FBAvail)
|
|
return MODE_MEM;
|
|
|
|
return MODE_OK;
|
|
}
|
|
|
|
/* XXX - Way more to do here */
|
|
|
|
static Bool
|
|
GXEnterVT(int scrnIndex, int flags)
|
|
{
|
|
return GXEnterGraphics(NULL, xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
static void
|
|
GXLeaveVT(int scrnIndex, int flags)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[scrnIndex];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
pGeode->PrevDisplayOffset = gfx_get_display_offset();
|
|
GXLeaveGraphics(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
void
|
|
GXSetupChipsetFPtr(ScrnInfoPtr pScrn)
|
|
{
|
|
pScrn->PreInit = GXPreInit;
|
|
pScrn->ScreenInit = GXScreenInit;
|
|
pScrn->SwitchMode = GXSwitchMode;
|
|
pScrn->AdjustFrame = GXAdjustFrame;
|
|
pScrn->EnterVT = GXEnterVT;
|
|
pScrn->LeaveVT = GXLeaveVT;
|
|
pScrn->FreeScreen = GeodeFreeScreen;
|
|
pScrn->ValidMode = GXValidMode;
|
|
}
|
|
|
|
/* ====== Common functions ======
|
|
* These are all the common functions that we use for both GX and LX - They live here
|
|
* because most of them came along for the GX first, and then were adapted to the LX.
|
|
* We could move these to a common function, but there is no hurry
|
|
* ============================== */
|
|
|
|
void
|
|
GeodePointerMoved(int index, int x, int y)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86Screens[index];
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
int newX = x, newY = y;
|
|
|
|
switch (pGeode->rotation) {
|
|
case RR_Rotate_0:
|
|
break;
|
|
case RR_Rotate_90:
|
|
newX = y;
|
|
newY = pScrni->pScreen->width - x - 1;
|
|
break;
|
|
case RR_Rotate_180:
|
|
newX = pScrni->pScreen->width - x - 1;
|
|
newY = pScrni->pScreen->height - y - 1;
|
|
break;
|
|
case RR_Rotate_270:
|
|
newX = pScrni->pScreen->height - y - 1;
|
|
newY = x;
|
|
break;
|
|
}
|
|
|
|
(*pGeode->PointerMoved) (index, newX, newY);
|
|
}
|
|
|
|
int
|
|
GeodeGetFPGeometry(const char *str, int *width, int *height)
|
|
{
|
|
|
|
int ret = sscanf(str, "%dx%d", width, height);
|
|
|
|
return (ret == 2) ? 0 : 1;
|
|
}
|
|
|
|
static void
|
|
GeodeFreeRec(ScrnInfoPtr pScrni)
|
|
{
|
|
if (pScrni->driverPrivate != NULL) {
|
|
xfree(pScrni->driverPrivate);
|
|
pScrni->driverPrivate = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
GeodeFreeScreen(int scrnIndex, int flags)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(xf86Screens[scrnIndex]);
|
|
|
|
if (pGeode == NULL)
|
|
return;
|
|
|
|
if (pGeode->useVGA) {
|
|
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
|
|
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
GeodeFreeRec(xf86Screens[scrnIndex]);
|
|
}
|
|
|
|
int
|
|
GeodeCalculatePitchBytes(unsigned int width, unsigned int bpp)
|
|
{
|
|
|
|
int delta = width * (bpp >> 3);
|
|
|
|
/* Less then 640 has doubling enabled */
|
|
|
|
if (width < 640)
|
|
delta <<= 1;
|
|
|
|
/* Calculate the pitch (compression rquires a power of 2) */
|
|
|
|
if (delta > 4096)
|
|
delta = 8192;
|
|
else if (delta > 2048)
|
|
delta = 4096;
|
|
else if (delta > 1024)
|
|
delta = 2048;
|
|
else
|
|
delta = 1024;
|
|
|
|
return delta;
|
|
}
|