#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "cir.h"
#include "alp.h"
#include "lg.h"
#include "vbe.h"
static const OptionInfoRec * CIRAvailableOptions(int chipid, int busid);
static void CIRIdentify(int flags);
static Bool CIRProbe(DriverPtr drv, int flags);
static Bool lg_loaded = FALSE;
static Bool alp_loaded = FALSE;
#define VERSION 4000
#define CIR_NAME "CIRRUS"
#define CIR_DRIVER_NAME "cirrus"
#define CIR_MAJOR_VERSION 1
#define CIR_MINOR_VERSION 0
#define CIR_PATCHLEVEL 0
DriverRec CIRRUS = {
VERSION,
CIR_DRIVER_NAME,
CIRIdentify,
CIRProbe,
CIRAvailableOptions,
NULL,
0
};
SymTabRec CIRChipsets[] = {
{ PCI_CHIP_GD5430, "CLGD5430" },
{ PCI_CHIP_GD5434_4, "CLGD5434-4" },
{ PCI_CHIP_GD5434_8, "CLGD5434-8" },
{ PCI_CHIP_GD5436, "CLGD5436" },
{ PCI_CHIP_GD5446, "CLGD5446" },
{ PCI_CHIP_GD5480, "CLGD5480" },
{ PCI_CHIP_GD5462, "CL-GD5462" },
{ PCI_CHIP_GD5464, "CL-GD5464" },
{ PCI_CHIP_GD5464BD, "CL-GD5464BD" },
{ PCI_CHIP_GD5465, "CL-GD5465" },
{ PCI_CHIP_GD7548, "CL-GD7548" },
{-1, NULL }
};
PciChipsets CIRPciChipsets[] = {
{ PCI_CHIP_GD5430, PCI_CHIP_GD5430, RES_SHARED_VGA },
{ PCI_CHIP_GD5434_4,PCI_CHIP_GD5434_4, RES_SHARED_VGA },
{ PCI_CHIP_GD5434_8,PCI_CHIP_GD5434_8, RES_SHARED_VGA },
{ PCI_CHIP_GD5436, PCI_CHIP_GD5436, RES_SHARED_VGA },
{ PCI_CHIP_GD5446, PCI_CHIP_GD5446, RES_SHARED_VGA },
{ PCI_CHIP_GD5480, PCI_CHIP_GD5480, RES_SHARED_VGA },
{ PCI_CHIP_GD5462, PCI_CHIP_GD5462, RES_SHARED_VGA },
{ PCI_CHIP_GD5464, PCI_CHIP_GD5464, RES_SHARED_VGA },
{ PCI_CHIP_GD5464BD,PCI_CHIP_GD5464BD, RES_SHARED_VGA },
{ PCI_CHIP_GD5465, PCI_CHIP_GD5465, RES_SHARED_VGA },
{ PCI_CHIP_GD7548, PCI_CHIP_GD7548, RES_SHARED_VGA },
{ -1, -1, RES_UNDEFINED}
};
static const char *alpSymbols[] = {
"AlpAvailableOptions",
"AlpProbe",
NULL
};
static const char *lgSymbols[] = {
"LgAvailableOptions",
"LgProbe",
NULL
};
static const char *vbeSymbols[] = {
"VBEInit",
"vbeDoEDID",
"vbeFree",
NULL
};
#ifdef XFree86LOADER
static MODULESETUPPROTO(cirSetup);
static XF86ModuleVersionInfo cirVersRec =
{
"cirrus",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
CIR_MAJOR_VERSION, CIR_MINOR_VERSION, CIR_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0,0,0,0}
};
XF86ModuleData cirrusModuleData = { &cirVersRec, cirSetup, NULL };
static pointer
cirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
xf86AddDriver(&CIRRUS, module, 0);
LoaderRefSymLists(alpSymbols, lgSymbols, vbeSymbols, NULL);
return (pointer)1;
}
if (errmaj) *errmaj = LDR_ONCEONLY;
return NULL;
}
#endif
static void
CIRIdentify(int flags)
{
xf86PrintChipsets(CIR_NAME, "driver for Cirrus chipsets", CIRChipsets);
}
static const OptionInfoRec *
CIRAvailableOptions(int chipid, int busid)
{
int chip = chipid & 0xffff;
switch (chip)
{
case PCI_CHIP_GD5462:
case PCI_CHIP_GD5464:
case PCI_CHIP_GD5464BD:
case PCI_CHIP_GD5465:
if (lg_loaded)
return LgAvailableOptions(chipid);
else
return NULL;
default:
if (alp_loaded)
return AlpAvailableOptions(chipid);
else
return NULL;
}
}
static Bool
CIRProbe(DriverPtr drv, int flags)
{
int i;
GDevPtr *devSections;
pciVideoPtr pPci;
int *usedChips;
int numDevSections;
int numUsed;
Bool foundScreen = FALSE;
ScrnInfoPtr (*subProbe)(int entity);
ScrnInfoPtr pScrn;
#ifdef CIR_DEBUG
ErrorF("CirProbe\n");
#endif
if (flags & PROBE_DETECT) {
if (!lg_loaded) {
if (xf86LoadDrvSubModule(drv, "cirrus_laguna")) {
xf86LoaderReqSymLists(lgSymbols, NULL);
lg_loaded = TRUE;
}
}
if (!alp_loaded) {
if (xf86LoadDrvSubModule(drv, "cirrus_alpine")) {
xf86LoaderReqSymLists(alpSymbols, NULL);
alp_loaded = TRUE;
}
}
}
if ((numDevSections = xf86MatchDevice(CIR_DRIVER_NAME,
&devSections)) <= 0) {
return FALSE;
}
if (xf86GetPciVideoInfo() == NULL) {
return FALSE;
}
numUsed = xf86MatchPciInstances(CIR_NAME, PCI_VENDOR_CIRRUS,
CIRChipsets, CIRPciChipsets, devSections,
numDevSections, drv, &usedChips);
xfree(devSections);
if (numUsed <= 0)
return FALSE;
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else for (i = 0; i < numUsed; i++) {
pPci = xf86GetPciInfoForEntity(usedChips[i]);
if (pPci && (pPci->chipType == PCI_CHIP_GD5462 ||
pPci->chipType == PCI_CHIP_GD5464 ||
pPci->chipType == PCI_CHIP_GD5464BD ||
pPci->chipType == PCI_CHIP_GD5465)) {
if (!lg_loaded) {
if (!xf86LoadDrvSubModule(drv, "cirrus_laguna"))
continue;
xf86LoaderReqSymLists(lgSymbols, NULL);
lg_loaded = TRUE;
}
subProbe = LgProbe;
} else {
if (!alp_loaded) {
if (!xf86LoadDrvSubModule(drv, "cirrus_alpine"))
continue;
xf86LoaderReqSymLists(alpSymbols, NULL);
alp_loaded = TRUE;
}
subProbe = AlpProbe;
}
pScrn = NULL;
if ((pScrn = subProbe(usedChips[i]))) {
foundScreen = TRUE;
pScrn->driverVersion = VERSION;
pScrn->driverName = CIR_DRIVER_NAME;
pScrn->name = CIR_NAME;
pScrn->Probe = NULL;
}
}
xfree(usedChips);
return foundScreen;
}
Bool
CirMapMem(CirPtr pCir, int scrnIndex)
{
int mmioFlags;
#ifdef CIR_DEBUG
ErrorF("CirMapMem\n");
#endif
if (pCir->FbMapSize) {
pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
pCir->PciTag, pCir->FbAddress,
pCir->FbMapSize);
if (pCir->FbBase == NULL)
return FALSE;
}
#ifdef CIR_DEBUG
ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase);
#endif
if (pCir->IOAddress == 0) {
pCir->IOBase = NULL;
} else {
mmioFlags = VIDMEM_MMIO;
pCir->IOBase =
xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag,
pCir->IOAddress, pCir->IoMapSize);
if (pCir->IOBase == NULL)
return FALSE;
}
#ifdef CIR_DEBUG
ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n",
pCir->IOBase, pCir->IoMapSize, pCir->IOAddress);
ErrorF("MMIO[GR31] = %2X\n", (int)
((volatile unsigned char*) pCir->IOBase)[0x40]);
#endif
return TRUE;
}
Bool
CirUnmapMem(CirPtr pCir, int scrnIndex)
{
#ifdef CIR_DEBUG
ErrorF("CirUnmapMem\n");
#endif
if (pCir->IOBase != NULL) {
xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize);
pCir->IOBase = NULL;
}
xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize);
pCir->FbBase = NULL;
return TRUE;
}
void
cirProbeDDC(ScrnInfoPtr pScrn, int index)
{
vbeInfoPtr pVbe;
if (xf86LoadSubModule(pScrn, "vbe")) {
xf86LoaderReqSymLists(vbeSymbols,NULL);
pVbe = VBEInit(NULL,index);
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
vbeFree(pVbe);
}
}