xenocara/driver/xf86-video-geode/src/geode_driver.c
2008-06-14 22:15:30 +00:00

606 lines
15 KiB
C

/*
* Copyright (c) 2006 Avanced Micro Devices, Inc.
*
* 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.
*/
/*
* File Contents: This is the main module configures the interfacing
* with the X server. The individual modules will be
* loaded based upon the options selected from the
* XF86Config. This file also has modules for finding
* supported modes, turning on the modes based on options.
*
* Project: Amd Xfree Frame buffer device driver.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Includes that are used by all drivers */
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86cmap.h"
#include "geode.h"
#define RC_MAX_DEPTH 24
#include "fb.h"
/* Machine independent stuff */
#include "mipointer.h"
#include "mibank.h"
#include "micmap.h"
/* All drivers implementing backing store need this */
#include "mibstore.h"
#include "vgaHW.h"
#include "vbe.h"
/* Check for some extensions */
#ifdef XFreeXDGA
#define _XF86_DGA_SERVER_
#include <X11/extensions/xf86dgastr.h>
#endif /* XFreeXDGA */
#ifdef DPMSExtension
#include "globals.h"
#include "opaque.h"
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif /* DPMSExtension */
/* A few things all drivers should have */
#define GEODE_NAME "GEODE"
#define GEODE_DRIVER_NAME "geode"
#define GEODE_VERSION 4000
#define GEODE_VERSION_MAJOR PACKAGE_VERSION_MAJOR
#define GEODE_VERSION_MINOR PACKAGE_VERSION_MINOR
#define GEODE_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
/* Forward definitions */
static const OptionInfoRec *AmdAvailableOptions(int chipid, int busid);
static void AmdIdentify(int);
#ifdef XSERVER_LIBPCIACCESS
static Bool AmdPciProbe(DriverPtr, int, struct pci_device *, intptr_t);
#else
static Bool AmdProbe(DriverPtr, int);
#endif
#ifdef XSERVER_LIBPCIACCESS
static const struct pci_id_match amdDeviceMatch[] = {
{PCI_VENDOR_ID_NS, PCI_CHIP_GEODEGX, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0,
0},
{PCI_VENDOR_ID_AMD, PCI_CHIP_GEODELX, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0,
0},
{0, 0, 0}
};
#endif /* XSERVER_LIBPCIACCESS */
/* driver record contains the functions needed by the server after loading
* the driver module.
*/
_X_EXPORT DriverRec AMD = {
GEODE_VERSION,
"amd",
AmdIdentify,
#ifdef XSERVER_LIBPCIACCESS
NULL,
#else
AmdProbe,
#endif
AmdAvailableOptions,
NULL,
0,
NULL,
#ifdef XSERVER_LIBPCIACCESS
amdDeviceMatch,
AmdPciProbe
#endif
};
_X_EXPORT DriverRec GEODE = {
GEODE_VERSION,
"geode",
AmdIdentify,
#ifdef XSERVER_LIBPCIACCESS
NULL,
#else
AmdProbe,
#endif
AmdAvailableOptions,
NULL,
0,
NULL,
#ifdef XSERVER_LIBPCIACCESS
amdDeviceMatch,
AmdPciProbe
#endif
};
/* Advanced Micro Devices Chip Models */
typedef struct _DEVICE_MODEL
{
int DeviceId;
int Model;
}
DeviceModel;
DeviceModel ChipModel[] = {
#ifdef HAVE_LX
{PCI_CHIP_GEODELX, LX},
#endif
#ifdef HAVE_GX
{PCI_CHIP_GEODEGX, GX},
#endif
{-1, 0}
};
/* Supported chipsets */
SymTabRec GeodeChipsets[] = {
#ifdef HAVE_LX
{PCI_CHIP_GEODELX, "Geode LX"},
#endif
#ifdef HAVE_GX
{PCI_CHIP_GEODEGX, "Geode GX"},
#endif
{-1, NULL}
};
PciChipsets GeodePCIchipsets[] = {
#ifdef HAVE_LX
{PCI_CHIP_GEODELX, PCI_CHIP_GEODELX, RES_SHARED_VGA},
#endif
#ifdef HAVE_GX
{PCI_CHIP_GEODEGX, PCI_CHIP_GEODEGX, RES_SHARED_VGA},
#endif
{-1, -1, RES_UNDEFINED},
};
#ifdef HAVE_LX
OptionInfoRec LX_GeodeOptions[] = {
{LX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{LX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
{LX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
{LX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{LX_OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
{LX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
{LX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
{LX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
{LX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
{LX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
{LX_OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
{LX_OPTION_EXA_SCRATCH_BFRSZ, "ExaScratch", OPTV_INTEGER, {0}, FALSE},
{LX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
{LX_OPTION_PANEL_GEOMETRY, "PanelGeometry", OPTV_STRING, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
#endif
#ifdef HAVE_GX
OptionInfoRec GX_GeodeOptions[] = {
{GX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{GX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
{GX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
{GX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{GX_OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
{GX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
{GX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
{GX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
{GX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
{GX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
{GX_OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
{GX_OPTION_OSM_IMG_BUFS, "OSMImageBuffers", OPTV_INTEGER, {0}, FALSE},
{GX_OPTION_OSM_CLR_BUFS, "OSMColorExpBuffers", OPTV_INTEGER, {0}, FALSE},
{GX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
{GX_OPTION_PANEL_GEOMETRY, "PanelGeometry", OPTV_STRING, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
#endif
OptionInfoRec no_GeodeOptions[] = {
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
/* List of symbols from other modules that this module references.The purpose
* is that to avoid unresolved symbol warnings
*/
const char *amdVgahwSymbols[] = {
"vgaHWGetHWRec",
"vgaHWUnlock",
"vgaHWInit",
"vgaHWSave",
"vgaHWRestore",
"vgaHWProtect",
"vgaHWGetIOBase",
"vgaHWMapMem",
"vgaHWLock",
"vgaHWFreeHWRec",
"vgaHWSaveScreen",
NULL
};
const char *amdVbeSymbols[] = {
"VBEInit",
"vbeDoEDID",
"vbeFree",
NULL
};
const char *amdInt10Symbols[] = {
"xf86ExecX86int10",
"xf86InitInt10",
"xf86Int10AllocPages",
"xf86Int10Addr",
NULL
};
const char *amdFbSymbols[] = {
"fbScreenInit",
"fbPictureInit",
NULL
};
const char *amdXaaSymbols[] = {
"XAADestroyInfoRec",
"XAACreateInfoRec",
"XAAInit",
"XAAScreenIndex",
NULL
};
const char *amdExaSymbols[] = {
"exaGetVersion",
"exaDriverInit",
"exaDriverFini",
"exaOffscreenAlloc",
"exaOffscreenFree",
NULL
};
const char *amdRamdacSymbols[] = {
"xf86InitCursor",
"xf86CreateCursorInfoRec",
"xf86DestroyCursorInfoRec",
NULL
};
#ifdef XFree86LOADER
/* Module loader interface */
static MODULESETUPPROTO(AmdSetup);
static XF86ModuleVersionInfo AmdVersionRec = {
"amd",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
ABI_CLASS_VIDEODRV, /* This is a video driver */
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
static XF86ModuleVersionInfo GeodeVersionRec = {
"geode",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
ABI_CLASS_VIDEODRV, /* This is a video driver */
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
static pointer
GeodeSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
{
static Bool init = FALSE;
int flag = 0;
#ifdef XSERVER_LIBPCIACCESS
flag = HaveDriverFuncs;
#endif
if (init) {
*ErrorMajor = LDR_ONCEONLY;
return (pointer) NULL;
}
init = TRUE;
xf86AddDriver(&GEODE, Module, flag);
LoaderRefSymLists(amdVgahwSymbols, amdVbeSymbols,
amdFbSymbols, amdXaaSymbols, amdInt10Symbols, amdRamdacSymbols, NULL);
return (pointer) TRUE;
}
static pointer
AmdSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
{
static Bool Initialised = FALSE;
if (!Initialised) {
Initialised = TRUE;
xf86AddDriver(&AMD, Module,
#ifdef XSERVER_LIBPCIACCESS
HaveDriverFuncs
#else
0
#endif
);
/* Tell the loader about symbols from other modules that this
* module might refer to.
*/
LoaderRefSymLists(amdVgahwSymbols, amdVbeSymbols,
amdFbSymbols, amdXaaSymbols,
amdInt10Symbols, amdRamdacSymbols, NULL);
return (pointer) TRUE;
}
/*The return value must be non-NULL on success */
if (ErrorMajor)
*ErrorMajor = LDR_ONCEONLY;
return NULL;
}
_X_EXPORT XF86ModuleData amdModuleData = { &AmdVersionRec, AmdSetup, NULL };
_X_EXPORT XF86ModuleData geodeModuleData =
{ &GeodeVersionRec, GeodeSetup, NULL };
#endif /*End of XFree86Loader */
/*-------------------------------------------------------------------------
* AmdIdentify.
*
* Description : This function identify an Amdfamily version.
*
*
* Parameters.
* flags : flags may be used in PreInit*
*
* Returns : none
*
* Comments : none
*
*------------------------------------------------------------------------
*/
static void
AmdIdentify(int flags)
{
xf86PrintChipsets(GEODE_NAME, "Driver for AMD Geode Chipsets",
GeodeChipsets);
}
/*----------------------------------------------------------------------------
* AmdAvailableOptions.
*
* Description :This function returns the geodeoptions set geodeoption
*
* Parameters.
* chipid :This will identify the chipset.
* busid :This will identify the PCI busid
*
* Returns :ptr to GeodeOptions.
*
* Comments :none
*
*----------------------------------------------------------------------------
*/
static const OptionInfoRec *
AmdAvailableOptions(int chipid, int busid)
{
switch (chipid) {
#ifdef HAVE_LX
case PCI_CHIP_GEODELX:
return LX_GeodeOptions;
#endif
#ifdef HAVE_GX
case PCI_CHIP_GEODEGX:
return GX_GeodeOptions;
#endif
}
return no_GeodeOptions;
}
#ifdef XSERVER_LIBPCIACCESS
static Bool
AmdPciProbe(DriverPtr driver,
int entity_num, struct pci_device *device, intptr_t match_data)
{
ScrnInfoPtr scrn = NULL;
int cpu_detected;
ErrorF("AmdPciProbe: Probing for supported devices!\n");
scrn = xf86ConfigPciEntity(scrn, 0, entity_num, GeodePCIchipsets,
NULL, NULL, NULL, NULL, NULL);
if (scrn != NULL) {
scrn->driverName = GEODE_DRIVER_NAME;
scrn->driverVersion = GEODE_VERSION;
scrn->name = GEODE_NAME;
scrn->Probe = NULL;
switch (device->device_id) {
#ifdef HAVE_LX
case PCI_CHIP_GEODELX:
cpu_detected = LX;
LXSetupChipsetFPtr(scrn);
break;
#endif
#ifdef HAVE_GX
case PCI_CHIP_GEODEGX:
cpu_detected = GX;
GXSetupChipsetFPtr(scrn);
break;
#endif
default:
ErrorF("AmdPciProbe: unknown device ID\n");
return FALSE;
}
DEBUGMSG(1, (0, X_INFO, "AmdPciProbe: CPUDetected %d!\n",
cpu_detected));
}
return scrn != NULL;
}
#else /* XSERVER_LIBPCIACCESS */
/*----------------------------------------------------------------------------
* AmdProbe.
*
* Description :This is to find that hardware is claimed by another
* driver if not claim the slot & allocate ScreenInfoRec.
*
* Parameters.
* drv :a pointer to the geode driver
* flags :flags may passed to check the config and probe detect
*
* Returns :TRUE on success and FALSE on failure.
*
* Comments :This should ne minimal probe and it should under no
* circumstances change the state of the hardware.Don't do
* any intiallizations other than the required
* ScreenInforec.
*----------------------------------------------------------------------------
*/
static Bool
AmdProbe(DriverPtr drv, int flags)
{
Bool foundScreen = FALSE;
int numDevSections, numUsed;
GDevPtr *devSections = NULL;
int *usedChips = NULL;
int i;
void (*drvr_setup) (ScrnInfoPtr pScrni) = NULL;
int CPUDetected;
DEBUGMSG(1, (0, X_INFO, "AmdProbe: Probing for supported devices!\n"));
/*
* * Find the config file Device sections that match this
* * driver, and return if there are none.
*/
if ((numDevSections = xf86MatchDevice(GEODE_NAME, &devSections)) <= 0) {
DEBUGMSG(1, (0, X_INFO, "AmdProbe: failed 1!\n"));
return FALSE;
}
DEBUGMSG(1, (0, X_INFO, "AmdProbe: Before MatchPciInstances!\n"));
/* PCI BUS */
if (xf86GetPciVideoInfo()) {
numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_NS,
GeodeChipsets, GeodePCIchipsets,
devSections, numDevSections, drv, &usedChips);
if (numUsed <= 0)
numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_AMD,
GeodeChipsets, GeodePCIchipsets,
devSections, numDevSections, drv, &usedChips);
DEBUGMSG(1, (0, X_INFO, "AmdProbe: MatchPCI (%d)!\n", numUsed));
if (numUsed > 0) {
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else {
/* Durango only supports one instance, */
/* so take the first one */
for (i = 0; i < numUsed; i++) {
/* Allocate a ScrnInfoRec */
ScrnInfoPtr pScrni = xf86AllocateScreen(drv, 0);
EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);
PciChipsets *p_id;
for (p_id = GeodePCIchipsets; p_id->numChipset != -1;
p_id++) {
if (pEnt->chipset == p_id->numChipset) {
switch (pEnt->chipset) {
#ifdef HAVE_LX
case PCI_CHIP_GEODELX:
CPUDetected = LX;
drvr_setup = &LXSetupChipsetFPtr;
break;
#endif
#ifdef HAVE_GX
case PCI_CHIP_GEODEGX:
CPUDetected = GX;
drvr_setup = &GXSetupChipsetFPtr;
break;
#endif
default:
break;
}
break;
}
}
xfree(pEnt);
if (drvr_setup == NULL)
return FALSE;
DEBUGMSG(1, (0, X_INFO, "AmdProbe: CPUDetected %d!\n",
CPUDetected));
pScrni->driverName = GEODE_DRIVER_NAME;
pScrni->driverVersion = GEODE_VERSION;
pScrni->name = GEODE_NAME;
pScrni->Probe = AmdProbe;
drvr_setup(pScrni);
foundScreen = TRUE;
xf86ConfigActivePciEntity(pScrni, usedChips[i],
GeodePCIchipsets, NULL, NULL, NULL, NULL, NULL);
}
}
}
}
if (usedChips)
xfree(usedChips);
if (devSections)
xfree(devSections);
DEBUGMSG(1, (0, X_INFO, "AmdProbe: result (%d)!\n", foundScreen));
return foundScreen;
}
#endif /* else XSERVER_LIBPCIACCESS */