#include "xf86.h"
#include "xf86_ansic.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86RAC.h"
#include "xf86cmap.h"
#include "compiler.h"
#include "mibstore.h"
#include "vgaHW.h"
#include "mipointer.h"
#include "micmap.h"
#include "fb.h"
#include "regionstr.h"
#include "xf86xv.h"
#include "Xv.h"
#include "vbe.h"
#include "i810.h"
#ifdef XF86DRI
#include "dri.h"
#endif
static void I810Identify(int flags);
static Bool I810Probe(DriverPtr drv, int flags);
#ifndef I830_ONLY
static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc,
char **argv);
static Bool I810EnterVT(int scrnIndex, int flags);
static void I810LeaveVT(int scrnIndex, int flags);
static Bool I810CloseScreen(int scrnIndex, ScreenPtr pScreen);
static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank);
static void I810FreeScreen(int scrnIndex, int flags);
static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagermentMode,
int flags);
static ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode,
Bool verbose, int flags);
#endif
DriverRec I810 = {
I810_VERSION,
I810_DRIVER_NAME,
I810Identify,
I810Probe,
I810AvailableOptions,
NULL,
0
};
static SymTabRec I810Chipsets[] = {
#ifndef I830_ONLY
{PCI_CHIP_I810, "i810"},
{PCI_CHIP_I810_DC100, "i810-dc100"},
{PCI_CHIP_I810_E, "i810e"},
{PCI_CHIP_I815, "i815"},
#endif
{PCI_CHIP_I830_M, "i830M"},
{PCI_CHIP_845_G, "845G"},
{PCI_CHIP_I855_GM, "852GM/855GM"},
{PCI_CHIP_I865_G, "865G"},
{-1, NULL}
};
static PciChipsets I810PciChipsets[] = {
#ifndef I830_ONLY
{PCI_CHIP_I810, PCI_CHIP_I810, RES_SHARED_VGA},
{PCI_CHIP_I810_DC100, PCI_CHIP_I810_DC100, RES_SHARED_VGA},
{PCI_CHIP_I810_E, PCI_CHIP_I810_E, RES_SHARED_VGA},
{PCI_CHIP_I815, PCI_CHIP_I815, RES_SHARED_VGA},
#endif
{PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA},
{PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA},
{PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA},
{PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA},
{-1, -1, RES_UNDEFINED }
};
#ifndef I830_ONLY
typedef enum {
OPTION_NOACCEL,
OPTION_SW_CURSOR,
OPTION_COLOR_KEY,
OPTION_CACHE_LINES,
OPTION_DAC_6BIT,
OPTION_DRI,
OPTION_NO_DDC,
OPTION_SHOW_CACHE,
OPTION_XVMC_SURFACES,
OPTION_PAGEFLIP
} I810Opts;
static const OptionInfoRec I810Options[] = {
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
{OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
{OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE},
{OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
#endif
const char *I810vgahwSymbols[] = {
"vgaHWFreeHWRec",
"vgaHWGetHWRec",
"vgaHWGetIOBase",
"vgaHWGetIndex",
"vgaHWInit",
"vgaHWLock",
"vgaHWMapMem",
"vgaHWProtect",
"vgaHWRestore",
"vgaHWSave",
"vgaHWSaveScreen",
"vgaHWSetMmioFuncs",
"vgaHWUnlock",
"vgaHWUnmapMem",
NULL
};
const char *I810fbSymbols[] = {
"fbPictureInit",
"fbScreenInit",
NULL
};
const char *I810vbeSymbols[] = {
"VBEFreeModeInfo",
"VBEFreeVBEInfo",
"VBEGetModeInfo",
"VBEGetModePool",
"VBEGetVBEInfo",
"VBEGetVBEMode",
"VBEInit",
"VBEPrintModes",
"VBESaveRestore",
"VBESetDisplayStart",
"VBESetGetDACPaletteFormat",
"VBESetGetLogicalScanlineLength",
"VBESetGetPaletteData",
"VBESetModeNames",
"VBESetModeParameters",
"VBESetVBEMode",
"VBEValidateModes",
"vbeDoEDID",
"vbeFree",
NULL
};
#ifdef XFree86LOADER
static const char *vbeOptionalSymbols[] = {
"VBEDPMSSet",
"VBEGetPixelClock",
NULL
};
#endif
const char *I810ddcSymbols[] = {
"xf86PrintEDID",
"xf86SetDDCproperties",
NULL
};
const char *I810int10Symbols[] = {
"xf86ExecX86int10",
"xf86InitInt10",
"xf86Int10AllocPages",
"xf86int10Addr",
NULL
};
const char *I810xaaSymbols[] = {
"XAACreateInfoRec",
"XAADestroyInfoRec",
"XAAInit",
"XAACopyROP",
"XAAPatternROP",
NULL
};
const char *I810ramdacSymbols[] = {
"xf86CreateCursorInfoRec",
"xf86DestroyCursorInfoRec",
"xf86InitCursor",
NULL
};
#ifdef XF86DRI
const char *I810drmSymbols[] = {
"drmAddBufs",
"drmAddMap",
"drmAgpAcquire",
"drmAgpAlloc",
"drmAgpBind",
"drmAgpEnable",
"drmAgpFree",
"drmAgpRelease",
"drmAgpUnbind",
"drmAuthMagic",
"drmCommandWrite",
"drmCreateContext",
"drmCtlInstHandler",
"drmCtlUninstHandler",
"drmDestroyContext",
"drmFreeVersion",
"drmGetInterruptFromBusID",
"drmGetLibVersion",
"drmGetVersion",
NULL
};
const char *I810driSymbols[] = {
"DRICloseScreen",
"DRICreateInfoRec",
"DRIDestroyInfoRec",
"DRIFinishScreenInit",
"DRIGetSAREAPrivate",
"DRILock",
"DRIQueryVersion",
"DRIScreenInit",
"DRIUnlock",
"GlxSetVisualConfigs",
NULL
};
#ifdef XF86DRI
static const char *driShadowFBSymbols[] = {
"ShadowFBInit",
NULL
};
const char *I810shadowSymbols[] = {
"shadowInit",
"shadowSetup",
"shadowAdd",
NULL
};
#endif
#endif
#ifndef I810_DEBUG
int I810_DEBUG = (0
);
#endif
#ifndef I830_ONLY
#ifdef XF86DRI
static int i810_pitches[] = {
512,
1024,
2048,
4096,
0
};
#endif
#endif
#ifdef XFree86LOADER
static MODULESETUPPROTO(i810Setup);
static XF86ModuleVersionInfo i810VersRec = {
"i810",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
I810_MAJOR_VERSION, I810_MINOR_VERSION, I810_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, 0 };
static pointer
i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = 0;
if (!setupDone) {
setupDone = 1;
xf86AddDriver(&I810, module, 0);
LoaderRefSymLists(I810vgahwSymbols,
I810fbSymbols, I810xaaSymbols, I810ramdacSymbols,
#ifdef XF86DRI
I810drmSymbols,
I810driSymbols,
I810shadowSymbols,
driShadowFBSymbols,
#endif
I810vbeSymbols, vbeOptionalSymbols,
I810ddcSymbols, I810int10Symbols, NULL);
return (pointer) 1;
} else {
if (errmaj)
*errmaj = LDR_ONCEONLY;
return NULL;
}
}
#endif
#ifndef I830_ONLY
static Bool
I810GetRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate)
return TRUE;
pScrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1);
return TRUE;
}
static void
I810FreeRec(ScrnInfoPtr pScrn)
{
if (!pScrn)
return;
if (!pScrn->driverPrivate)
return;
xfree(pScrn->driverPrivate);
pScrn->driverPrivate = 0;
}
#endif
static void
I810Identify(int flags)
{
xf86PrintChipsets(I810_NAME, "Driver for Intel Integrated Graphics Chipsets",
I810Chipsets);
}
const OptionInfoRec *
I810AvailableOptions(int chipid, int busid)
{
#ifndef I830_ONLY
const OptionInfoRec *pOptions;
if ((pOptions = I830BIOSAvailableOptions(chipid, busid)))
return pOptions;
return I810Options;
#else
return I830BIOSAvailableOptions(chipid, busid);
#endif
}
static Bool
I810Probe(DriverPtr drv, int flags)
{
int i, numUsed, numDevSections, *usedChips;
GDevPtr *devSections;
Bool foundScreen = FALSE;
pciVideoPtr *VideoInfo;
pciVideoPtr *ppPci;
PciChipsets *id;
if ((numDevSections =
xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0) {
return FALSE;
}
if (!(VideoInfo = xf86GetPciVideoInfo()))
return FALSE;
for (ppPci = VideoInfo; ppPci != NULL && *ppPci != NULL; ppPci++) {
if ((*ppPci)->vendor == PCI_VENDOR_INTEL &&
(*ppPci)->func == 1) {
for (id = I810PciChipsets; id->PCIid != -1; id++) {
if (id->PCIid == (*ppPci)->chipType) {
if (xf86CheckPciSlot((*ppPci)->bus, (*ppPci)->device,
(*ppPci)->func)) {
xf86ClaimPciSlot((*ppPci)->bus, (*ppPci)->device,
(*ppPci)->func, drv, id->PCIid,
NULL, FALSE);
}
break;
}
}
}
}
numUsed = xf86MatchPciInstances(I810_NAME, PCI_VENDOR_INTEL,
I810Chipsets, I810PciChipsets,
devSections, numDevSections,
drv, &usedChips);
if (flags & PROBE_DETECT) {
if (numUsed > 0)
foundScreen = TRUE;
} else {
for (i = 0; i < numUsed; i++) {
ScrnInfoPtr pScrn = NULL;
if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
I810PciChipsets, 0, 0, 0, 0, 0))) {
EntityInfoPtr pEnt;
pEnt = xf86GetEntityInfo(usedChips[i]);
pScrn->driverVersion = I810_VERSION;
pScrn->driverName = I810_DRIVER_NAME;
pScrn->name = I810_NAME;
pScrn->Probe = I810Probe;
foundScreen = TRUE;
switch (pEnt->chipset) {
case PCI_CHIP_I830_M:
case PCI_CHIP_845_G:
case PCI_CHIP_I855_GM:
case PCI_CHIP_I865_G:
I830InitpScrn(pScrn);
break;
#ifndef I830_ONLY
default:
pScrn->PreInit = I810PreInit;
pScrn->ScreenInit = I810ScreenInit;
pScrn->SwitchMode = I810SwitchMode;
pScrn->AdjustFrame = I810AdjustFrame;
pScrn->EnterVT = I810EnterVT;
pScrn->LeaveVT = I810LeaveVT;
pScrn->FreeScreen = I810FreeScreen;
pScrn->ValidMode = I810ValidMode;
break;
#endif
}
}
}
}
xfree(usedChips);
xfree(devSections);
return foundScreen;
}
#ifndef I830_ONLY
static void
I810ProbeDDC(ScrnInfoPtr pScrn, int index)
{
vbeInfoPtr pVbe;
if (xf86LoadSubModule(pScrn, "vbe")) {
pVbe = VBEInit(NULL, index);
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
vbeFree(pVbe);
}
}
static xf86MonPtr
I810DoDDC(ScrnInfoPtr pScrn, int index)
{
vbeInfoPtr pVbe;
xf86MonPtr MonInfo = NULL;
I810Ptr pI810 = I810PTR(pScrn);
if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) {
return MonInfo;
}
if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
xf86LoaderReqSymLists(I810vbeSymbols, NULL);
MonInfo = vbeDoEDID(pVbe, NULL);
xf86PrintEDID(MonInfo);
xf86SetDDCproperties(pScrn, MonInfo);
vbeFree(pVbe);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"this driver cannot do DDC without VBE\n");
}
return MonInfo;
}
static Bool
I810PreInit(ScrnInfoPtr pScrn, int flags)
{
vgaHWPtr hwp;
I810Ptr pI810;
ClockRangePtr clockRanges;
int i;
MessageType from;
int flags24;
rgb defaultWeight = { 0, 0, 0 };
int mem;
Bool enable;
if (pScrn->numEntities != 1)
return FALSE;
if (!I810GetRec(pScrn))
return FALSE;
pI810 = I810PTR(pScrn);
pI810->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pI810->pEnt->location.type != BUS_PCI)
return FALSE;
if (flags & PROBE_DETECT) {
I810ProbeDDC(pScrn, pI810->pEnt->index);
return TRUE;
}
if (!xf86LoadSubModule(pScrn, "vgahw"))
return FALSE;
xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
if (!vgaHWGetHWRec(pScrn))
return FALSE;
hwp = VGAHWPTR(pScrn);
pI810->ioBase = hwp->PIOOffset;
pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
pI810->PciTag = pciTag(pI810->PciInfo->bus, pI810->PciInfo->device,
pI810->PciInfo->func);
if (xf86RegisterResources(pI810->pEnt->index, 0, ResNone))
return FALSE;
pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
pScrn->monitor = pScrn->confScreen->monitor;
flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
return FALSE;
} else {
switch (pScrn->depth) {
case 8:
case 15:
case 16:
case 24:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given depth (%d) is not supported by i810 driver\n",
pScrn->depth);
return FALSE;
}
}
xf86PrintDepthBpp(pScrn);
switch (pScrn->bitsPerPixel) {
case 8:
case 16:
case 24:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given bpp (%d) is not supported by i810 driver\n",
pScrn->bitsPerPixel);
return FALSE;
}
if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
return FALSE;
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
pScrn->progClock = TRUE;
pI810->cpp = pScrn->bitsPerPixel / 8;
xf86CollectOptions(pScrn, NULL);
if (!(pI810->Options = xalloc(sizeof(I810Options))))
return FALSE;
memcpy(pI810->Options, I810Options, sizeof(I810Options));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options);
pScrn->rgbBits = 8;
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
pScrn->rgbBits = 6;
if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE))
pI810->showCache = TRUE;
else
pI810->showCache = FALSE;
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) &&
pScrn->bitsPerPixel > 8) {
OptionInfoPtr ptr;
ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT);
ptr->found = FALSE;
}
pScrn->monitor->DDC = I810DoDDC(pScrn, pI810->pEnt->index);
I810SetPIOAccess(pI810);
if (pI810->pEnt->device->chipset && *pI810->pEnt->device->chipset) {
pScrn->chipset = pI810->pEnt->device->chipset;
from = X_CONFIG;
} else if (pI810->pEnt->device->chipID >= 0) {
pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
pI810->pEnt->device->chipID);
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
pI810->pEnt->device->chipID);
} else {
from = X_PROBED;
pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
pI810->PciInfo->chipType);
}
if (pI810->pEnt->device->chipRev >= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pI810->pEnt->device->chipRev);
}
xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
(pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
if (pI810->pEnt->device->MemBase != 0) {
pI810->LinearAddr = pI810->pEnt->device->MemBase;
from = X_CONFIG;
} else {
if (pI810->PciInfo->memBase[1] != 0) {
pI810->LinearAddr = pI810->PciInfo->memBase[0] & 0xFF000000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid FB address in PCI config space\n");
I810FreeRec(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
(unsigned long)pI810->LinearAddr);
if (pI810->pEnt->device->IOBase != 0) {
pI810->MMIOAddr = pI810->pEnt->device->IOBase;
from = X_CONFIG;
} else {
if (pI810->PciInfo->memBase[1]) {
pI810->MMIOAddr = pI810->PciInfo->memBase[1] & 0xFFF80000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid MMIO address in PCI config space\n");
I810FreeRec(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
(unsigned long)pI810->MMIOAddr);
if (!xf86AgpGARTSupported()) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"AGP GART support is not available. Make sure your kernel has\n"
"\tagpgart support or that the agpgart kernel module is loaded.\n");
return FALSE;
}
{
unsigned long whtcfg_pamr_drp = pciReadLong(pI810->PciTag,
WHTCFG_PAMR_DRP);
if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133)
pI810->LmFreqSel = 133;
else
pI810->LmFreqSel = 100;
}
pScrn->videoRam = 8192;
from = X_DEFAULT;
if (pI810->pEnt->device->videoRam) {
pScrn->videoRam = pI810->pEnt->device->videoRam;
from = X_CONFIG;
}
mem = I810CheckAvailableMemory(pScrn);
if (mem > 0 && mem < pScrn->videoRam) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
" but the\n\t maximum AGP memory available is %dk.\n",
pScrn->videoRam, mem);
from = X_PROBED;
if (mem > (6 * 1024)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Reducing video memory to 4MB\n");
pScrn->videoRam = 4096;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
" is available. Cannot proceed.\n");
I810FreeRec(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from,
"Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam);
{
PCITAG bridge;
long smram_miscc;
bridge = pciTag(0, 0, 0);
smram_miscc = pciReadLong(bridge, SMRAM_MISCC);
if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
pI810->FbMapSize = 0x1000000;
pI810->DepthOffset = 0x1000000;
pI810->BackOffset = 0x1800000;
} else {
pI810->FbMapSize = 0x3000000;
pI810->DepthOffset = 0x3000000;
pI810->BackOffset = 0x3800000;
}
}
{
Gamma zeros = { 0.0, 0.0, 0.0 };
if (!xf86SetGamma(pScrn, zeros)) {
return FALSE;
}
}
pI810->MaxClock = 0;
if (pI810->pEnt->device->dacSpeeds[0]) {
switch (pScrn->bitsPerPixel) {
case 8:
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8];
break;
case 16:
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16];
break;
case 24:
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24];
break;
case 32:
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32];
break;
}
if (!pI810->MaxClock)
pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0];
from = X_CONFIG;
} else {
switch (pScrn->bitsPerPixel) {
case 8:
pI810->MaxClock = 203000;
break;
case 16:
pI810->MaxClock = 163000;
break;
case 24:
pI810->MaxClock = 136000;
break;
case 32:
pI810->MaxClock = 86000;
}
}
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = 9500;
clockRanges->maxClock = pI810->MaxClock;
clockRanges->clockIndex = -1;
clockRanges->interlaceAllowed = TRUE;
clockRanges->doubleScanAllowed = FALSE;
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
pScrn->display->modes, clockRanges,
#ifndef XF86DRI
0, 320, 1600, 64 * pScrn->bitsPerPixel,
#else
i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel,
#endif
200, 1200,
pScrn->display->virtualX, pScrn->display->virtualY,
pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
if (i == -1) {
I810FreeRec(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
if (!i || !pScrn->modes) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
I810FreeRec(pScrn);
return FALSE;
}
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
if (!xf86LoadSubModule(pScrn, "fb")) {
I810FreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810fbSymbols, NULL);
if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
pI810->noAccel = TRUE;
if (!pI810->noAccel) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
I810FreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810xaaSymbols, NULL);
}
if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
I810FreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
}
if (xf86GetOptValInteger
(pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"video overlay key set to 0x%x\n", pI810->colorKey);
} else {
pI810->colorKey = (1 << pScrn->offset.red) |
(1 << pScrn->offset.green) |
(((pScrn->mask.blue >> pScrn->offset.blue) -
1) << pScrn->offset.blue);
}
pI810->directRenderingDisabled =
!xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
#ifdef XF86DRI
if (!pI810->directRenderingDisabled) {
if (pI810->noAccel) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"needs 2D acceleration.\n");
pI810->directRenderingDisabled=TRUE;
} else if (pScrn->depth!=16) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"runs only at 16-bit depth.\n");
pI810->directRenderingDisabled=TRUE;
}
}
#endif
pI810->allowPageFlip=FALSE;
enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
#ifdef XF86DRI
if (!pI810->directRenderingDisabled) {
pI810->allowPageFlip = enable;
if (pI810->allowPageFlip == enable)
{
if (!xf86LoadSubModule(pScrn, "shadowfb")) {
pI810->allowPageFlip = 0;
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Couldn't load shadowfb module:\n");
}
else {
xf86LoaderReqSymLists(driShadowFBSymbols, NULL);
}
}
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
enable ? "enabled" : "disabled");
}
#endif
if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
&(pI810->numSurfaces))) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
pI810->numSurfaces);
if (pI810->numSurfaces > 7) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Using 7 XvMC Surfaces (Maximum Allowed).\n");
pI810->numSurfaces = 7;
}
if (pI810->numSurfaces < 6) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Using 6 XvMC Surfaces (Minimum Allowed).\n");
pI810->numSurfaces = 6;
}
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
pI810->numSurfaces = 0;
}
#ifdef XF86DRI
if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
if (xf86LoadSubModule(pScrn, "dri")) {
xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
}
}
#endif
I810SetMMIOAccess(pI810);
xf86SetOperatingState(resVgaIo, pI810->pEnt->index, ResUnusedOpr);
xf86SetOperatingState(resVgaMem, pI810->pEnt->index, ResDisableOpr);
return TRUE;
}
static Bool
I810MapMMIO(ScrnInfoPtr pScrn)
{
int mmioFlags;
I810Ptr pI810 = I810PTR(pScrn);
#if !defined(__alpha__)
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
#else
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
#endif
pI810->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
pI810->PciTag,
pI810->MMIOAddr, I810_REG_SIZE);
if (!pI810->MMIOBase)
return FALSE;
return TRUE;
}
static Bool
I810MapMem(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
unsigned i;
for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
pI810->FbMapSize = i;
if (!I810MapMMIO(pScrn))
return FALSE;
pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
pI810->PciTag,
pI810->LinearAddr, pI810->FbMapSize);
if (!pI810->FbBase)
return FALSE;
pI810->LpRing.virtual_start = pI810->FbBase + pI810->LpRing.mem.Start;
return TRUE;
}
static void
I810UnmapMMIO(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
I810_REG_SIZE);
pI810->MMIOBase = 0;
}
static Bool
I810UnmapMem(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
pI810->FbMapSize);
pI810->FbBase = 0;
I810UnmapMMIO(pScrn);
return TRUE;
}
void
I810PrintErrorState(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
INREG(PGETBL_CTL), INREG(PGE_ERR));
ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
INREG(LP_RING + RING_TAIL),
INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START));
ErrorF("eir: %x esr: %x emr: %x\n",
INREG16(EIR), INREG16(ESR), INREG16(EMR));
ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS));
ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
}
static void
DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
Bool saveFonts)
{
I810Ptr pI810;
vgaHWPtr hwp;
int i;
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
if (saveFonts)
vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP);
else
vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL);
i810Reg->AddressMapping = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL);
i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET);
i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL);
i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
for (i = 0; i < 8; i++)
i810Reg->Fence[i] = INREG(FENCE + i * 4);
i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
i810Reg->LprbStart = INREG(LP_RING + RING_START);
i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
i810Reg->LprbLen & RING_VALID) {
I810PrintErrorState(pScrn);
FatalError("Active ring not flushed\n");
}
}
static void
I810Save(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp;
I810Ptr pI810;
CARD32 temp;
hwp = VGAHWPTR(pScrn);
pI810 = I810PTR(pScrn);
DoSave(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
temp = INREG(MEMMODE);
temp |= 4;
OUTREG(MEMMODE, temp);
}
static void
i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode)
{
int i;
ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg);
ErrorF("SEQ: ");
for (i = 0; i < vgaReg->numSequencer; i++) {
if ((i & 7) == 0)
ErrorF("\n");
ErrorF(" %d: %x", i, vgaReg->Sequencer[i]);
}
ErrorF("\n");
ErrorF("CRTC: ");
for (i = 0; i < vgaReg->numCRTC; i++) {
if ((i & 3) == 0)
ErrorF("\n");
ErrorF(" %d: %x", i, vgaReg->CRTC[i]);
}
ErrorF("\n");
ErrorF("GFX: ");
for (i = 0; i < vgaReg->numGraphics; i++) {
if ((i & 7) == 0)
ErrorF("\n");
ErrorF(" %d: %x", i, vgaReg->Graphics[i]);
}
ErrorF("\n");
ErrorF("ATTR: ");
for (i = 0; i < vgaReg->numAttribute; i++) {
if ((i & 7) == 0)
ErrorF("\n");
ErrorF(" %d: %x", i, vgaReg->Attribute[i]);
}
ErrorF("\n");
ErrorF(" DisplayControl: %x\n", mode->DisplayControl);
ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M);
ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N);
ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
ErrorF(" AddressMapping: %x\n", mode->AddressMapping);
ErrorF(" IOControl: %x\n", mode->IOControl);
ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl);
ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal);
ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal);
ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank);
ErrorF(" ExtOffset: %x\n", mode->ExtOffset);
ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl);
ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
ErrorF(" LprbTail: %x\n", mode->LprbTail);
ErrorF(" LprbHead: %x\n", mode->LprbHead);
ErrorF(" LprbStart: %x\n", mode->LprbStart);
ErrorF(" LprbLen: %x\n", mode->LprbLen);
}
static void
DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
Bool restoreFonts)
{
I810Ptr pI810;
vgaHWPtr hwp;
unsigned char temp;
unsigned int itemp;
int i;
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
ErrorF("Setting mode in I810Restore:\n");
i810PrintMode(vgaReg, i810Reg);
}
vgaHWProtect(pScrn, TRUE);
usleep(50000);
temp = INREG8(DRAM_ROW_CNTL_HI);
temp &= ~DRAM_REFRESH_RATE;
temp |= DRAM_REFRESH_DISABLE;
OUTREG8(DRAM_ROW_CNTL_HI, temp);
usleep(1000);
OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M);
OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N);
OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
temp = INREG8(PIXPIPE_CONFIG_0);
temp &= 0x7F;
temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
OUTREG8(PIXPIPE_CONFIG_0, temp);
if (restoreFonts)
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
else
vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);
temp = hwp->readCrtc(hwp, INTERLACE_CNTL);
temp &= ~INTERLACE_ENABLE;
temp |= i810Reg->InterlaceControl;
hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
temp &= 0xE0;
temp |= i810Reg->AddressMapping;
pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp);
{
CARD32 LCD_TV_Control = INREG(LCD_TV_C);
CARD32 TV_HTotal = INREG(LCD_TV_HTOTAL);
CARD32 ActiveStart, ActiveEnd;
if((LCD_TV_Control & LCD_TV_ENABLE)
&& !(LCD_TV_Control & LCD_TV_VGAMOD)
&& TV_HTotal) {
ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
ActiveEnd = (TV_HTotal & 0x3ff) - 31;
} else {
ActiveStart = i810Reg->OverlayActiveStart;
ActiveEnd = i810Reg->OverlayActiveEnd;
}
OUTREG(LCD_TV_OVRACT,
(ActiveEnd << 16) | ActiveStart);
}
temp = INREG8(DRAM_ROW_CNTL_HI);
temp &= ~DRAM_REFRESH_RATE;
temp |= DRAM_REFRESH_60HZ;
OUTREG8(DRAM_ROW_CNTL_HI, temp);
temp = INREG8(BITBLT_CNTL);
temp &= ~COLEXP_MODE;
temp |= i810Reg->BitBLTControl;
OUTREG8(BITBLT_CNTL, temp);
temp = INREG8(DISPLAY_CNTL);
temp &= ~(VGA_WRAP_MODE | GUI_MODE);
temp |= i810Reg->DisplayControl;
OUTREG8(DISPLAY_CNTL, temp);
temp = INREG8(PIXPIPE_CONFIG_0);
temp &= 0x64;
temp |= i810Reg->PixelPipeCfg0;
OUTREG8(PIXPIPE_CONFIG_0, temp);
temp = INREG8(PIXPIPE_CONFIG_2);
temp &= 0xF3;
temp |= i810Reg->PixelPipeCfg2;
OUTREG8(PIXPIPE_CONFIG_2, temp);
temp = INREG8(PIXPIPE_CONFIG_1);
temp &= ~DISPLAY_COLOR_MODE;
temp &= 0xEF;
temp |= i810Reg->PixelPipeCfg1;
OUTREG8(PIXPIPE_CONFIG_1, temp);
OUTREG16(EIR, 0);
itemp = INREG(FWATER_BLC);
itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
MM_BURST_LENGTH | MM_FIFO_WATERMARK);
itemp |= i810Reg->LMI_FIFO_Watermark;
OUTREG(FWATER_BLC, itemp);
for (i = 0; i < 8; i++) {
OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
if (I810_DEBUG & DEBUG_VERBOSE_VGA)
ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
}
itemp = INREG(LP_RING + RING_LEN);
itemp &= ~RING_VALID_MASK;
OUTREG(LP_RING + RING_LEN, itemp);
OUTREG(LP_RING + RING_TAIL, 0);
OUTREG(LP_RING + RING_HEAD, 0);
pI810->LpRing.head = 0;
pI810->LpRing.tail = 0;
itemp = INREG(LP_RING + RING_START);
itemp &= ~(START_ADDR);
itemp |= i810Reg->LprbStart;
OUTREG(LP_RING + RING_START, itemp);
itemp = INREG(LP_RING + RING_LEN);
itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
itemp |= i810Reg->LprbLen;
OUTREG(LP_RING + RING_LEN, itemp);
if (!(vgaReg->Attribute[0x10] & 0x1)) {
usleep(50000);
if (restoreFonts)
vgaHWRestore(pScrn, vgaReg,
VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
else
vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
}
vgaHWProtect(pScrn, FALSE);
temp = hwp->readCrtc(hwp, IO_CTNL);
temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
temp |= i810Reg->IOControl;
hwp->writeCrtc(hwp, IO_CTNL, temp);
}
static void
I810SetRingRegs(ScrnInfoPtr pScrn)
{
unsigned int itemp;
I810Ptr pI810 = I810PTR(pScrn);
OUTREG(LP_RING + RING_TAIL, 0);
OUTREG(LP_RING + RING_HEAD, 0);
itemp = INREG(LP_RING + RING_START);
itemp &= ~(START_ADDR);
itemp |= pI810->LpRing.mem.Start;
OUTREG(LP_RING + RING_START, itemp);
itemp = INREG(LP_RING + RING_LEN);
itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
itemp |= ((pI810->LpRing.mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
OUTREG(LP_RING + RING_LEN, itemp);
}
static void
I810Restore(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp;
I810Ptr pI810;
hwp = VGAHWPTR(pScrn);
pI810 = I810PTR(pScrn);
DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
}
#define MAX_VCO_FREQ 600.0
#define TARGET_MAX_N 30
#define REF_FREQ 24.0
#define CALC_VCLK(m,n,p) \
(double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
static void
I810CalcVCLK(ScrnInfoPtr pScrn, double freq)
{
I810Ptr pI810 = I810PTR(pScrn);
I810RegPtr i810Reg = &pI810->ModeReg;
int m, n, p;
double f_out, f_best;
double f_err;
double f_vco;
int m_best = 0, n_best = 0, p_best = 0;
double f_target = freq;
double err_max = 0.005;
double err_target = 0.001;
double err_best = 999999.0;
p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);
if (p_best > 5) {
p_best = p = 5;
}
f_vco = f_target * (1 << p);
n = 2;
do {
n++;
m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
if (m < 3)
m = 3;
f_out = CALC_VCLK(m, n, p);
f_err = 1.0 - (f_target / f_out);
if (fabs(f_err) < err_max) {
m_best = m;
n_best = n;
f_best = f_out;
err_best = f_err;
}
} while ((fabs(f_err) >= err_target) &&
((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
if (fabs(f_err) < err_target) {
m_best = m;
n_best = n;
}
i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;
i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;
i810Reg->VideoClk2_DivisorSel = (p_best << 4);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
"Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
"[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
}
static Bool
I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
I810Ptr pI810 = I810PTR(pScrn);
I810RegPtr i810Reg = &pI810->ModeReg;
vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
double dclk = mode->Clock / 1000.0;
switch (pScrn->bitsPerPixel) {
case 8:
pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
i810Reg->ExtOffset = pScrn->displayWidth >> 11;
i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
i810Reg->BitBLTControl = COLEXP_8BPP;
break;
case 16:
if (pScrn->weight.green == 5) {
i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
} else {
i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
}
pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
i810Reg->ExtOffset = pScrn->displayWidth >> 10;
i810Reg->BitBLTControl = COLEXP_16BPP;
i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
break;
case 24:
pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
i810Reg->BitBLTControl = COLEXP_24BPP;
i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
break;
default:
break;
}
if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
i810Reg->PixelPipeCfg0 = DAC_6_BIT;
else
i810Reg->PixelPipeCfg0 = DAC_8_BIT;
i810Reg->PixelPipeCfg1 |= 0x10;
i810Reg->IOControl = EXTENDED_CRTC_CNTL;
i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
i810Reg->DisplayControl = HIRES_MODE;
i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
i810Reg->ExtVertBlankStart = 2;
}
if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
i810Reg->ExtVertBlankStart = 3;
}
i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
if (mode->Flags & V_INTERLACE) {
i810Reg->InterlaceControl = INTERLACE_ENABLE;
i810Reg->ExtVertDispEnd *= 2;
} else
i810Reg->InterlaceControl = INTERLACE_DISABLE;
pVga->Attribute[0x11] = 0;
I810CalcVCLK(pScrn, dclk);
pVga->MiscOutReg |= 0x0C;
i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);
i810Reg->LprbTail = 0;
i810Reg->LprbHead = 0;
i810Reg->LprbStart = pI810->LpRing.mem.Start;
if (i810Reg->LprbStart)
i810Reg->LprbLen = ((pI810->LpRing.mem.Size - 4096) |
RING_NO_REPORT | RING_VALID);
else
i810Reg->LprbLen = RING_INVALID;
return TRUE;
}
static Bool
I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
vgaHWPtr hwp;
I810Ptr pI810;
vgaRegPtr pVga;
hwp = VGAHWPTR(pScrn);
pI810 = I810PTR(pScrn);
vgaHWUnlock(hwp);
if (!vgaHWInit(pScrn, mode))
return FALSE;
pVga = &VGAHWPTR(pScrn)->ModeReg;
pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
pScrn->vtSema = TRUE;
if (!I810SetMode(pScrn, mode))
return FALSE;
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
pI810->LockHeld = 1;
}
#endif
DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
pI810->LockHeld = 0;
}
#endif
return TRUE;
}
static void
I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
I810Ptr pI810;
vgaHWPtr hwp;
int i, j, index;
unsigned char r, g, b;
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
for (i = 0; i < numColors; i++) {
index = indices[i];
r = colors[index].red;
g = colors[index].green;
b = colors[index].blue;
for (j = 0; j < 8; j++) {
hwp->writeDacWriteAddr(hwp, (index << 3) + j);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
}
}
}
static void
I810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
I810Ptr pI810;
vgaHWPtr hwp;
int i, index;
unsigned char r, g, b;
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
for (i = 0; i < numColors; i++) {
index = indices[i / 2];
r = colors[index].red;
b = colors[index].blue;
index = indices[i];
g = colors[index].green;
hwp->writeDacWriteAddr(hwp, index << 2);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
i++;
index = indices[i];
g = colors[index].green;
hwp->writeDacWriteAddr(hwp, index << 2);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
}
}
static void
I810LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
I810Ptr pI810;
vgaHWPtr hwp;
int i, index;
unsigned char r, g, b;
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
for (i = 0; i < numColors; i++) {
index = indices[i];
r = colors[index].red;
g = colors[index].green;
b = colors[index].blue;
hwp->writeDacWriteAddr(hwp, index);
hwp->writeDacData(hwp, r);
hwp->writeDacData(hwp, g);
hwp->writeDacData(hwp, b);
}
}
Bool
I810AllocateFront(ScrnInfoPtr pScrn)
{
I810Ptr pI810 = I810PTR(pScrn);
int cache_lines = -1;
if (pI810->DoneFrontAlloc)
return TRUE;
memset(&(pI810->FbMemBox), 0, sizeof(BoxRec));
pI810->FbMemBox.x1 = 0;
pI810->FbMemBox.x2 = pScrn->displayWidth;
pI810->FbMemBox.y1 = 0;
pI810->FbMemBox.y2 = pScrn->virtualY;
xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines);
if (cache_lines < 0) {
cache_lines = (pScrn->depth == 24) ? 256 : 384;
if (pScrn->displayWidth <= 1024)
cache_lines *= 2;
}
{
int maxCacheLines;
maxCacheLines = (pScrn->videoRam * 1024 /
(pScrn->bitsPerPixel / 8) /
pScrn->displayWidth) - pScrn->virtualY;
if (maxCacheLines < 0)
maxCacheLines = 0;
if (cache_lines > maxCacheLines)
cache_lines = maxCacheLines;
}
pI810->FbMemBox.y2 += cache_lines;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Adding %i scanlines for pixmap caching\n", cache_lines);
if (!I810AllocLow(&(pI810->FrontBuffer),
&(pI810->SysMem),
((pI810->FbMemBox.x2 *
pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095)) {
xf86DrvMsg(pScrn->scrnIndex,
X_WARNING, "Framebuffer allocation failed\n");
return FALSE;
} else
DPRINTF(PFX,
"Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
pI810->FrontBuffer.Start,
pI810->FrontBuffer.Size / 1024, pI810->FrontBuffer.Size);
memset(&(pI810->LpRing), 0, sizeof(I810RingBuffer));
if (I810AllocLow(&(pI810->LpRing.mem), &(pI810->SysMem), 16 * 4096)) {
DPRINTF(PFX,
"Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
pI810->LpRing.mem.Start,
pI810->LpRing.mem.Size / 1024, pI810->LpRing.mem.Size);
pI810->LpRing.tail_mask = pI810->LpRing.mem.Size - 1;
pI810->LpRing.virtual_start = pI810->FbBase + pI810->LpRing.mem.Start;
pI810->LpRing.head = 0;
pI810->LpRing.tail = 0;
pI810->LpRing.space = 0;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Ring buffer allocation failed\n");
return (FALSE);
}
if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) ||
I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) {
DPRINTF(PFX,
"Scratch memory at 0x%.8x (%luk, %lu bytes)\n",
pI810->Scratch.Start,
pI810->Scratch.Size / 1024, pI810->Scratch.Size);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n");
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Scratch memory allocation failed\n");
return (FALSE);
}
pI810->DoneFrontAlloc = TRUE;
return TRUE;
}
static Bool
I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn;
vgaHWPtr hwp;
I810Ptr pI810;
VisualPtr visual;
MessageType driFrom = X_DEFAULT;
pScrn = xf86Screens[pScreen->myNum];
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
miClearVisualTypes();
if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
if (!miSetPixmapDepths())
return FALSE;
{
I810RegPtr i810Reg = &pI810->ModeReg;
int i;
for (i = 0; i < 8; i++)
i810Reg->Fence[i] = 0;
}
#ifdef XF86DRI
pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
if (pI810->directRenderingEnabled==TRUE)
pI810->directRenderingEnabled = I810DRIScreenInit(pScreen);
else
driFrom = X_CONFIG;
#else
pI810->directRenderingEnabled = FALSE;
if (!I810AllocateGARTMemory(pScrn))
return FALSE;
if (!I810AllocateFront(pScrn))
return FALSE;
#endif
if (!I810MapMem(pScrn))
return FALSE;
pScrn->memPhysBase = (unsigned long)pI810->LinearAddr;
pScrn->fbOffset = 0;
vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0);
vgaHWGetIOBase(hwp);
if (!vgaHWMapMem(pScrn))
return FALSE;
I810Save(pScrn);
if (!I810ModeInit(pScrn, pScrn->currentMode))
return FALSE;
I810SaveScreen(pScreen, FALSE);
I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
if (!fbScreenInit(pScreen, pI810->FbBase + pScrn->fbOffset,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi,
pScrn->displayWidth, pScrn->bitsPerPixel))
return FALSE;
if (pScrn->bitsPerPixel > 8) {
visual = pScreen->visuals + pScreen->numVisuals;
while (--visual >= pScreen->visuals) {
if ((visual->class | DynamicClass) == DirectColor) {
visual->offsetRed = pScrn->offset.red;
visual->offsetGreen = pScrn->offset.green;
visual->offsetBlue = pScrn->offset.blue;
visual->redMask = pScrn->mask.red;
visual->greenMask = pScrn->mask.green;
visual->blueMask = pScrn->mask.blue;
}
}
}
fbPictureInit(pScreen, 0, 0);
xf86SetBlackWhitePixels(pScreen);
#ifdef XF86DRI
if (pI810->LpRing.mem.Start == 0 && pI810->directRenderingEnabled) {
pI810->directRenderingEnabled = FALSE;
driFrom = X_PROBED;
I810DRICloseScreen(pScreen);
}
if (!pI810->directRenderingEnabled) {
pI810->DoneFrontAlloc = FALSE;
if (!I810AllocateGARTMemory(pScrn))
return FALSE;
if (!I810AllocateFront(pScrn))
return FALSE;
}
#endif
I810DGAInit(pScreen);
if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to init memory manager\n");
return FALSE;
}
if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) {
if (pI810->LpRing.mem.Size != 0) {
I810SetRingRegs(pScrn);
if (!I810AccelInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware acceleration initialization failed\n");
}
}
}
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
if (!I810CursorInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
}
}
if (!miCreateDefColormap(pScreen))
return FALSE;
if (pScrn->bitsPerPixel == 16) {
if (pScrn->depth == 15) {
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, 0,
CMAP_PALETTED_TRUECOLOR |
CMAP_RELOAD_ON_MODE_SWITCH))
return FALSE;
} else {
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, 0,
CMAP_PALETTED_TRUECOLOR |
CMAP_RELOAD_ON_MODE_SWITCH))
return FALSE;
}
} else {
if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, 0,
CMAP_PALETTED_TRUECOLOR |
CMAP_RELOAD_ON_MODE_SWITCH))
return FALSE;
}
xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0);
I810InitVideo(pScreen);
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
}
#ifdef XvMCExtension
if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
I810InitMC(pScreen);
}
#endif
#endif
if (pI810->directRenderingEnabled) {
xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering enabled\n");
} else {
xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering disabled\n");
}
pScreen->SaveScreen = I810SaveScreen;
pI810->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = I810CloseScreen;
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
return TRUE;
}
Bool
I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I810Ptr pI810 = I810PTR(pScrn);
if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags);
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("calling dri lock\n");
DRILock(screenInfo.screens[scrnIndex], 0);
pI810->LockHeld = 1;
}
#endif
if (pI810->AccelInfoRec != NULL) {
I810RefreshRing(pScrn);
I810Sync(pScrn);
pI810->AccelInfoRec->NeedToSync = FALSE;
}
I810Restore(pScrn);
#ifdef XF86DRI
if (!I810DRIEnter(pScrn)) {
return FALSE;
}
if (pI810->directRenderingEnabled) {
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("calling dri unlock\n");
DRIUnlock(screenInfo.screens[scrnIndex]);
pI810->LockHeld = 0;
}
#endif
return I810ModeInit(pScrn, mode);
}
void
I810AdjustFrame(int scrnIndex, int x, int y, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I810Ptr pI810 = I810PTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
int Base;
#if 1
if (pI810->showCache) {
int lastline = pI810->FbMapSize /
((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
lastline -= pScrn->currentMode->VDisplay;
if (y > 0)
y += pScrn->currentMode->VDisplay;
if (y > lastline) y = lastline;
}
#endif
Base = (y * pScrn->displayWidth + x) >> 2;
if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags);
switch (pScrn->bitsPerPixel) {
case 8:
break;
case 16:
Base *= 2;
break;
case 24:
pI810->CursorOffset = (Base & 0x3) * 4;
Base &= ~0x3;
Base *= 3;
break;
case 32:
Base *= 4;
break;
}
hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF);
hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8);
hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22);
hwp->writeCrtc(hwp, EXT_START_ADDR,
((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE));
}
static Bool
I810EnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
#ifdef XF86DRI
I810Ptr pI810 = I810PTR(pScrn);
#endif
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("\n\nENTER VT\n");
if (!I810BindGARTMemory(pScrn)) {
return FALSE;
}
#ifdef XF86DRI
if (!I810DRIEnter(pScrn)) {
return FALSE;
}
if (pI810->directRenderingEnabled) {
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("calling dri unlock\n");
DRIUnlock(screenInfo.screens[scrnIndex]);
pI810->LockHeld = 0;
}
#endif
if (!I810ModeInit(pScrn, pScrn->currentMode))
return FALSE;
I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
return TRUE;
}
static void
I810LeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
vgaHWPtr hwp = VGAHWPTR(pScrn);
I810Ptr pI810 = I810PTR(pScrn);
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("\n\n\nLeave VT\n");
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
if (I810_DEBUG & DEBUG_VERBOSE_DRI)
ErrorF("calling dri lock\n");
DRILock(screenInfo.screens[scrnIndex], 0);
pI810->LockHeld = 1;
}
#endif
if (pI810->AccelInfoRec != NULL) {
I810RefreshRing(pScrn);
I810Sync(pScrn);
pI810->AccelInfoRec->NeedToSync = FALSE;
}
I810Restore(pScrn);
if (!I810UnbindGARTMemory(pScrn))
return;
#ifdef XF86DRI
if (!I810DRILeave(pScrn))
return;
#endif
vgaHWLock(hwp);
}
static Bool
I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
vgaHWPtr hwp = VGAHWPTR(pScrn);
I810Ptr pI810 = I810PTR(pScrn);
XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
if (pScrn->vtSema == TRUE) {
if (pI810->AccelInfoRec != NULL) {
I810RefreshRing(pScrn);
I810Sync(pScrn);
pI810->AccelInfoRec->NeedToSync = FALSE;
}
I810Restore(pScrn);
vgaHWLock(hwp);
}
#ifdef XF86DRI
if (pI810->directRenderingEnabled) {
I810DRICloseScreen(pScreen);
pI810->directRenderingEnabled = FALSE;
}
#endif
if (pScrn->vtSema == TRUE) {
I810UnbindGARTMemory(pScrn);
I810Restore(pScrn);
vgaHWLock(hwp);
}
I810UnmapMem(pScrn);
vgaHWUnmapMem(pScrn);
if (pI810->ScanlineColorExpandBuffers) {
xfree(pI810->ScanlineColorExpandBuffers);
pI810->ScanlineColorExpandBuffers = 0;
}
if (infoPtr) {
if (infoPtr->ScanlineColorExpandBuffers)
xfree(infoPtr->ScanlineColorExpandBuffers);
XAADestroyInfoRec(infoPtr);
pI810->AccelInfoRec = 0;
}
if (pI810->CursorInfoRec) {
xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
pI810->CursorInfoRec = 0;
}
pI810->SysMem = pI810->SavedSysMem;
pI810->DcacheMem = pI810->SavedDcacheMem;
pI810->DoneFrontAlloc = FALSE;
xf86GARTCloseScreen(scrnIndex);
pScrn->vtSema = FALSE;
pScreen->CloseScreen = pI810->CloseScreen;
return (*pScreen->CloseScreen) (scrnIndex, pScreen);
}
static void
I810FreeScreen(int scrnIndex, int flags)
{
I810FreeRec(xf86Screens[scrnIndex]);
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
}
static ModeStatus
I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
{
if (mode->Flags & V_INTERLACE) {
if (verbose) {
xf86DrvMsg(scrnIndex, X_PROBED,
"Removing interlaced mode \"%s\"\n", mode->name);
}
return MODE_BAD;
}
return MODE_OK;
}
static Bool
I810SaveScreen(ScreenPtr pScreen, Bool unblack)
{
return vgaHWSaveScreen(pScreen, unblack);
}
static void
I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
int flags)
{
I810Ptr pI810;
unsigned char SEQ01 = 0;
int DPMSSyncSelect = 0;
pI810 = I810PTR(pScrn);
switch (PowerManagementMode) {
case DPMSModeOn:
SEQ01 = 0x00;
DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
break;
case DPMSModeStandby:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
break;
case DPMSModeSuspend:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
break;
case DPMSModeOff:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
break;
}
SEQ01 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20;
pI810->writeControl(pI810, SRX, 0x01, SEQ01);
OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
}
#endif