#define EXPERIMENTAL
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "vgaHW.h"
#include "xf86RAC.h"
#include "xf86Resources.h"
#include "mipointer.h"
#include "mibstore.h"
#include "micmap.h"
#include "shadowfb.h"
#include "xf86int10.h"
#include "fb.h"
#include "xf86DDC.h"
#undef LG_DEBUG
#include "cir.h"
#define _LG_PRIVATE_
#include "lg.h"
#include "xf86xv.h"
#include "Xv.h"
Bool LgPreInit(ScrnInfoPtr pScrn, int flags);
Bool LgScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
Bool LgEnterVT(int scrnIndex, int flags);
void LgLeaveVT(int scrnIndex, int flags);
static Bool LgCloseScreen(int scrnIndex, ScreenPtr pScreen);
static Bool LgSaveScreen(ScreenPtr pScreen, Bool mode);
Bool LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
void LgAdjustFrame(int scrnIndex, int x, int y, int flags);
void LgFreeScreen(int scrnIndex, int flags);
ModeStatus LgValidMode(int scrnIndex, DisplayModePtr mode,
Bool verbose, int flags);
static void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg);
static int LgFindLineData(int displayWidth, int bpp);
static CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq);
static void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base);
static void LgDisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagementMode, int flags);
static int pix24bpp = 0;
typedef enum {
OPTION_HW_CURSOR,
OPTION_PCI_RETRY,
OPTION_ROTATE,
OPTION_SHADOW_FB,
OPTION_NOACCEL
} LgOpts;
static const OptionInfoRec LgOptions[] = {
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
static int gd5462_MaxClocks[] = { 170000, 170000, 135100, 135100, 85500 };
static int gd5464_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
static int gd5465_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
LgLineDataRec LgLineData[] = {
{ 5, 640, 0},
{ 8, 1024, 0},
{10, 1280, 0},
{13, 1664, 0},
{16, 2048, 0},
{20, 2560, 0},
{10, 2560, 1},
{26, 3328, 0},
{ 5, 1280, 1},
{ 8, 2048, 1},
{13, 3328, 1},
{16, 4096, 1},
{20, 5120, 1},
{26, 6656, 1},
{-1, -1, -1}
};
static int LgLinePitches[4][11] = {
{ 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 },
{ 320, 512, 640, 832, 1024, 1280, 1664, 2048, 2560, 3328, 0 },
{ 213, 341, 426, 554, 682, 853, 1109, 1365, 1706, 2218, 0 },
{ 160, 256, 320, 416, 512, 640, 832, 1024, 1280, 1664, 0 }
};
static const char *vgahwSymbols[] = {
"vgaHWFreeHWRec",
"vgaHWGetHWRec",
"vgaHWGetIOBase",
"vgaHWGetIndex",
"vgaHWHandleColormaps",
"vgaHWInit",
"vgaHWLock",
"vgaHWMapMem",
"vgaHWProtect",
"vgaHWRestore",
"vgaHWSave",
"vgaHWSaveScreen",
"vgaHWUnlock",
NULL
};
static const char *fbSymbols[] = {
"fbScreenInit",
"fbPictureInit",
NULL
};
static const char *xaaSymbols[] = {
"XAACreateInfoRec",
"XAADestroyInfoRec",
"XAAInit",
NULL
};
static const char *ramdacSymbols[] = {
"xf86CreateCursorInfoRec",
"xf86DestroyCursorInfoRec",
"xf86InitCursor",
NULL
};
#define LGuseI2C 1
static const char *ddcSymbols[] = {
"xf86PrintEDID",
#if LGuseI2C
"xf86DoEDID_DDC2",
#endif
"xf86SetDDCproperties",
NULL
};
static const char *i2cSymbols[] = {
"xf86CreateI2CBusRec",
"xf86I2CBusInit",
NULL
};
static const char *int10Symbols[] = {
"xf86FreeInt10",
"xf86InitInt10",
NULL
};
static const char *shadowSymbols[] = {
"ShadowFBInit",
NULL
};
#ifdef XFree86LOADER
#define LG_MAJOR_VERSION 1
#define LG_MINOR_VERSION 0
#define LG_PATCHLEVEL 0
static MODULESETUPPROTO(lgSetup);
static XF86ModuleVersionInfo lgVersRec =
{
"cirrus_laguna",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_NONE,
{0,0,0,0}
};
XF86ModuleData cirrus_lagunaModuleData = { &lgVersRec, lgSetup, NULL };
static pointer
lgSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
ramdacSymbols, ddcSymbols, i2cSymbols,
int10Symbols, NULL);
}
return (pointer)1;
}
#endif
const OptionInfoRec *
LgAvailableOptions(int chipid)
{
return LgOptions;
}
ScrnInfoPtr
LgProbe(int entity)
{
ScrnInfoPtr pScrn = NULL;
if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets,
NULL, NULL, NULL, NULL, NULL))) {
pScrn->PreInit = LgPreInit;
pScrn->ScreenInit = LgScreenInit;
pScrn->SwitchMode = LgSwitchMode;
pScrn->AdjustFrame = LgAdjustFrame;
pScrn->EnterVT = LgEnterVT;
pScrn->LeaveVT = LgLeaveVT;
pScrn->FreeScreen = LgFreeScreen;
pScrn->ValidMode = LgValidMode;
}
return pScrn;
}
static Bool
LgGetRec(ScrnInfoPtr pScrn)
{
CirPtr pCir;
if (pScrn->driverPrivate != NULL)
return TRUE;
pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1);
((CirPtr)pScrn->driverPrivate)->chip.lg = xnfcalloc(sizeof(LgRec),1);
pCir = CIRPTR(pScrn);
pCir->chip.lg->oldBitmask = 0x00000000;
return TRUE;
}
static void
LgFreeRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate == NULL)
return;
xfree(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
static int
LgCountRam(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
CARD8 SR14;
vgaHWProtect(pScrn, TRUE);
SR14 = hwp->readSeq(hwp, 0x14);
ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n",
hwp->readSeq(hwp, 9), hwp->readSeq(hwp, 10),
SR14, hwp->readSeq(hwp, 0x15));
vgaHWProtect(pScrn, FALSE);
return 1024 * ((SR14&0x7) + 1);
}
static xf86MonPtr
LgDoDDC(ScrnInfoPtr pScrn)
{
CirPtr pCir = CIRPTR(pScrn);
xf86MonPtr MonInfo = NULL;
if (!CirMapMem(pCir, pScrn->scrnIndex))
return FALSE;
#if LGuseI2C
if (!LgI2CInit(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed\n");
goto unmap_out;
}
MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pCir->I2CPtr1);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n",
(void *)MonInfo);
xf86PrintEDID(MonInfo);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n\n");
#endif
xf86SetDDCproperties(pScrn, MonInfo);
unmap_out:
CirUnmapMem(pCir, pScrn->scrnIndex);
return MonInfo;
}
Bool
LgPreInit(ScrnInfoPtr pScrn, int flags)
{
CirPtr pCir;
vgaHWPtr hwp;
MessageType from;
int i;
ClockRangePtr clockRanges;
int fbPCIReg, ioPCIReg;
char *s;
if (flags & PROBE_DETECT) {
cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
return TRUE;
}
#ifdef LG_DEBUG
ErrorF("LgPreInit\n");
#endif
if (pScrn->numEntities != 1)
return FALSE;
if (!xf86LoadSubModule(pScrn, "vgahw"))
return FALSE;
xf86LoaderReqSymLists(vgahwSymbols, NULL);
if (!vgaHWGetHWRec(pScrn))
return FALSE;
hwp = VGAHWPTR(pScrn);
vgaHWGetIOBase(hwp);
if (!LgGetRec(pScrn))
return FALSE;
pCir = CIRPTR(pScrn);
pCir->pScrn = pScrn;
pCir->PIOReg = hwp->PIOOffset + 0x3CE;
pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pCir->pEnt->location.type != BUS_PCI)
return FALSE;
pCir->Chipset = pCir->pEnt->chipset;
pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index);
pCir->PciTag = pciTag(pCir->PciInfo->bus,
pCir->PciInfo->device,
pCir->PciInfo->func);
if (xf86LoadSubModule(pScrn, "int10")) {
xf86Int10InfoPtr int10InfoPtr;
xf86LoaderReqSymLists(int10Symbols, NULL);
int10InfoPtr = xf86InitInt10(pCir->pEnt->index);
if (int10InfoPtr)
xf86FreeInt10(int10InfoPtr);
}
pScrn->monitor = pScrn->confScreen->monitor;
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
SupportConvert32to24 | PreferConvert32to24)) {
return FALSE;
}
switch (pScrn->depth) {
case 8:
case 15:
case 16:
case 24:
case 32:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given depth (%d) is not supported by this driver\n", pScrn->depth);
return FALSE;
}
xf86PrintDepthBpp(pScrn);
if (pScrn->depth == 24 && pix24bpp == 0)
pix24bpp = xf86GetBppFromDepth(pScrn, 24);
if (pScrn->depth > 8) {
rgb zeros = {0, 0, 0};
if (!xf86SetWeight(pScrn, zeros, zeros)) {
return FALSE;
} else {
;
}
}
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
xf86CollectOptions(pScrn, NULL);
if (!(pCir->Options = xalloc(sizeof(LgOptions))))
return FALSE;
memcpy(pCir->Options, LgOptions, sizeof(LgOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options);
pScrn->rgbBits = 6;
from = X_DEFAULT;
pCir->HWCursor = FALSE;
if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, &pCir->HWCursor))
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
pCir->HWCursor ? "HW" : "SW");
if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) {
pCir->NoAccel = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
}
if (pScrn->bitsPerPixel < 8) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Cannot use in less than 8 bpp\n");
return FALSE;
}
if (pCir->pEnt->device->chipRev >= 0) {
pCir->ChipRev = pCir->pEnt->device->chipRev;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pCir->ChipRev);
} else {
pCir->ChipRev = pCir->PciInfo->chipRev;
}
if (PCI_CHIP_GD5465 == pCir->Chipset) {
fbPCIReg = 0;
ioPCIReg = 1;
} else {
fbPCIReg = 1;
ioPCIReg = 0;
}
if (pCir->pEnt->device->MemBase != 0) {
if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->MemBase)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"MemBase 0x%08lX doesn't match any PCI base register.\n",
pCir->pEnt->device->MemBase);
return FALSE;
}
pCir->FbAddress = pCir->pEnt->device->MemBase;
from = X_CONFIG;
} else {
if (pCir->PciInfo->memBase[fbPCIReg] != 0) {
pCir->FbAddress = pCir->PciInfo->memBase[fbPCIReg] & 0xff000000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid FB address in PCI config space\n");
LgFreeRec(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
(unsigned long)pCir->FbAddress);
if (pCir->pEnt->device->IOBase != 0) {
if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->IOBase)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"IOBase 0x%08lX doesn't match any PCI base register.\n",
pCir->pEnt->device->IOBase);
return FALSE;
}
pCir->IOAddress = pCir->pEnt->device->IOBase;
from = X_CONFIG;
} else {
if (pCir->PciInfo->memBase[ioPCIReg] != 0) {
pCir->IOAddress = pCir->PciInfo->memBase[ioPCIReg] & 0xfffff000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid MMIO address in PCI config space\n");
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
(unsigned long)pCir->IOAddress);
if (pCir->pEnt->device->videoRam != 0) {
pScrn->videoRam = pCir->pEnt->device->videoRam;
from = X_CONFIG;
} else {
pScrn->videoRam = LgCountRam(pScrn);
from = X_PROBED;
}
if (2048 == pScrn->videoRam) {
pCir->chip.lg->memInterleave = 0x40;
} else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) {
pCir->chip.lg->memInterleave = 0x80;
} else {
pCir->chip.lg->memInterleave = 0x00;
}
xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
pScrn->videoRam);
pCir->FbMapSize = pScrn->videoRam * 1024;
pCir->IoMapSize = 0x4000;
pScrn->racIoFlags = RAC_COLORMAP
#ifndef EXPERIMENTAL
| RAC_VIEWPORT
#endif
;
xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr);
if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"xf86RegisterResources() found resource conflicts\n");
return FALSE;
}
if (!xf86LoadSubModule(pScrn, "ddc")) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(ddcSymbols, NULL);
#if LGuseI2C
if (!xf86LoadSubModule(pScrn, "i2c")) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(i2cSymbols, NULL);
#endif
pScrn->monitor->DDC = LgDoDDC(pScrn);
if (pScrn->depth > 1) {
Gamma zeros = {0.0, 0.0, 0.0};
if (!xf86SetGamma(pScrn, zeros))
return FALSE;
}
if (xf86GetOptValBool(pCir->Options,
OPTION_SHADOW_FB,&pCir->shadowFB))
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
pCir->shadowFB ? "enabled" : "disabled");
if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) {
if(!xf86NameCmp(s, "CW")) {
pCir->shadowFB = TRUE;
pCir->rotate = 1;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Rotating screen clockwise - acceleration disabled\n");
} else if(!xf86NameCmp(s, "CCW")) {
pCir->shadowFB = TRUE;
pCir->rotate = -1;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen"
"counter clockwise - acceleration disabled\n");
} else {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
"value for Option \"Rotate\"\n", s);
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Valid options are \"CW\" or \"CCW\"\n");
}
}
if (pCir->shadowFB && !pCir->NoAccel) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"HW acceleration not supported with \"shadowFB\".\n");
pCir->NoAccel = TRUE;
}
if (pCir->rotate && pCir->HWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"HW cursor not supported with \"rotate\".\n");
pCir->HWCursor = FALSE;
}
pScrn->progClock = TRUE;
pCir->MinClock = 12000;
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
pCir->MinClock / 1000);
if (pCir->pEnt->device->dacSpeeds[0]) {
ErrorF("Do not specify a Clocks line for Cirrus chips\n");
return FALSE;
} else {
int speed;
int *p;
switch (pCir->Chipset) {
case PCI_CHIP_GD5462:
p = gd5462_MaxClocks;
break;
case PCI_CHIP_GD5464:
case PCI_CHIP_GD5464BD:
p = gd5464_MaxClocks;
break;
case PCI_CHIP_GD5465:
p = gd5465_MaxClocks;
break;
default:
ErrorF("???\n");
return FALSE;
}
switch (pScrn->bitsPerPixel) {
case 8:
speed = p[1];
break;
case 15:
case 16:
speed = p[2];
break;
case 24:
speed = p[3];
break;
case 32:
speed = p[4];
break;
default:
speed = 0;
break;
}
pCir->MaxClock = speed;
from = X_PROBED;
}
xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
pCir->MaxClock / 1000);
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = pCir->MinClock;
clockRanges->maxClock = pCir->MaxClock;
clockRanges->clockIndex = -1;
clockRanges->interlaceAllowed = FALSE;
clockRanges->doubleScanAllowed = FALSE;
clockRanges->doubleScanAllowed = FALSE;
clockRanges->doubleScanAllowed = FALSE;
clockRanges->ClockMulFactor = 1;
clockRanges->ClockDivFactor = 1;
clockRanges->PrivFlags = 0;
pCir->Rounding = 128 >> pCir->BppShift;
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
clockRanges,
LgLinePitches[pScrn->bitsPerPixel / 8 - 1],
0, 0, 128 * 8,
0, 0,
pScrn->display->virtualX,
pScrn->display->virtualY,
pCir->FbMapSize,
LOOKUP_BEST_REFRESH);
pCir->chip.lg->lineDataIndex = LgFindLineData(pScrn->displayWidth,
pScrn->bitsPerPixel);
if (i == -1) {
LgFreeRec(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
if (i == 0 || pScrn->modes == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
LgFreeRec(pScrn);
return FALSE;
}
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
switch (pScrn->bitsPerPixel) {
case 8:
case 16:
case 24:
case 32:
if (xf86LoadSubModule(pScrn, "fb") == NULL) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(fbSymbols, NULL);
break;
}
if (!pCir->NoAccel) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(xaaSymbols, NULL);
}
if (pCir->HWCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(ramdacSymbols, NULL);
}
if (pCir->shadowFB) {
if (!xf86LoadSubModule(pScrn, "shadowfb")) {
LgFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(shadowSymbols, NULL);
}
return TRUE;
}
static void
LgSave(ScrnInfoPtr pScrn)
{
CirPtr pCir = CIRPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
#ifdef LG_DEBUG
ErrorF("LgSave\n");
#endif
vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL);
pCir->chip.lg->ModeReg.ExtVga[CR1A] = pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A);
pCir->chip.lg->ModeReg.ExtVga[CR1B] = pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B);
pCir->chip.lg->ModeReg.ExtVga[CR1D] = pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D);
pCir->chip.lg->ModeReg.ExtVga[CR1E] = pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E);
pCir->chip.lg->ModeReg.ExtVga[SR07] = pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07);
pCir->chip.lg->ModeReg.ExtVga[SR0E] = pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E);
pCir->chip.lg->ModeReg.ExtVga[SR12] = pCir->chip.lg->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12);
pCir->chip.lg->ModeReg.ExtVga[SR13] = pCir->chip.lg->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13);
pCir->chip.lg->ModeReg.ExtVga[SR1E] = pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E);
pCir->chip.lg->ModeReg.FORMAT = pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0);
pCir->chip.lg->ModeReg.VSC = pCir->chip.lg->SavedReg.VSC = memrl(0x3FC);
pCir->chip.lg->ModeReg.DTTC = pCir->chip.lg->SavedReg.DTTC = memrw(0xEA);
if (pCir->Chipset == PCI_CHIP_GD5465) {
pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4);
}
pCir->chip.lg->ModeReg.TILE = pCir->chip.lg->SavedReg.TILE = memrb(0x407);
if (pCir->Chipset == PCI_CHIP_GD5465)
pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0);
else
pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x8C);
pCir->chip.lg->ModeReg.CONTROL = pCir->chip.lg->SavedReg.CONTROL = memrw(0x402);
}
static Bool
LgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
vgaHWPtr hwp;
CirPtr pCir;
int width;
Bool VDiv2 = FALSE;
CARD16 clockData;
LgLineDataPtr lineData;
#ifdef LG_DEBUG
ErrorF("LgModeInit %d bpp, %d %d %d %d %d %d %d %d %d\n",
pScrn->bitsPerPixel,
mode->Clock,
mode->HDisplay,
mode->HSyncStart,
mode->HSyncEnd,
mode->HTotal,
mode->VDisplay,
mode->VSyncStart,
mode->VSyncEnd,
mode->VTotal);
ErrorF("LgModeInit: depth %d bits\n", pScrn->depth);
#endif
pCir = CIRPTR(pScrn);
hwp = VGAHWPTR(pScrn);
vgaHWUnlock(hwp);
if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) {
if (!mode->CrtcVAdjusted) {
mode->CrtcVDisplay >>= 1;
mode->CrtcVSyncStart >>= 1;
mode->CrtcVSyncEnd >>= 1;
mode->CrtcVTotal >>= 1;
mode->CrtcVAdjusted = TRUE;
}
VDiv2 = TRUE;
}
if (!vgaHWInit(pScrn, mode))
return FALSE;
pScrn->vtSema = TRUE;
if (VDiv2)
hwp->ModeReg.CRTC[0x17] |= 0x04;
#ifdef LG_DEBUG
ErrorF("SynthClock = %d\n", mode->SynthClock);
#endif
hwp->IOBase = 0x3D0;
hwp->ModeReg.MiscOutReg |= 0x01;
#if 0
hwp->IOBase = 0x3B0;
hwp->ModeReg.MiscOutReg &= ~0x01;
#endif
pCir->chip.lg->ModeReg.ExtVga[CR1A] = (((mode->CrtcVSyncStart + 1) & 0x300 ) >> 2)
| (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2);
width = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
if (pScrn->bitsPerPixel == 1)
width <<= 2;
hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3;
pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF;
pCir->chip.lg->ModeReg.ExtVga[CR1B] |= (((width + 7) >> 3) & 0x100)?0x10:0x00;
pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22;
pCir->chip.lg->ModeReg.ExtVga[CR1D] = (((width + 7) >> 3) & 0x200)?0x01:0x00;
pCir->chip.lg->ModeReg.VSC = 0x10000000;
pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHTotal>>3 & 0x0100)?1:0)<<7;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHDisplay>>3 & 0x0100)?1:0)<<6;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<5;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<4;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVTotal & 0x0400)?1:0)<<3;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVDisplay & 0x0400)?1:0)<<2;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<1;
pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<0;
lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F;
if (8 == pScrn->bitsPerPixel) {
pCir->chip.lg->ModeReg.FORMAT = 0x0000;
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
| (lineData->width << 6);
pCir->chip.lg->ModeReg.CONTROL = 0x0000 | (lineData->width << 11);
if (mode->CrtcHDisplay <= 640) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
} else if (mode->CrtcHDisplay <= 800) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
} else if (mode->CrtcHDisplay <= 1024) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
} else if (mode->CrtcHDisplay <= 1280) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0016);
} else {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
}
} else if (16 == pScrn->bitsPerPixel) {
pCir->chip.lg->ModeReg.FORMAT = 0x1400;
if (pScrn->depth == 15)
pCir->chip.lg->ModeReg.FORMAT = 0x1600;
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
| (lineData->width << 6);
pCir->chip.lg->ModeReg.CONTROL = 0x2000 | (lineData->width << 11);
if (mode->CrtcHDisplay <= 640) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
} else if (mode->CrtcHDisplay <= 800) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
} else if (mode->CrtcHDisplay <= 1024) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0012);
} else if (mode->CrtcHDisplay <= 1280) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
} else {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
}
} else if (24 == pScrn->bitsPerPixel) {
pCir->chip.lg->ModeReg.FORMAT = 0x2400;
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
| (lineData->width << 6);
pCir->chip.lg->ModeReg.CONTROL = 0x4000 | (lineData->width << 11);
if (mode->CrtcHDisplay <= 640) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
} else if (mode->CrtcHDisplay <= 800) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
} else if (mode->CrtcHDisplay <= 1024) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
} else if (mode->CrtcHDisplay <= 1280) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001E);
} else {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0020);
}
} else if (32 == pScrn->bitsPerPixel) {
pCir->chip.lg->ModeReg.FORMAT = 0x3400;
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
| (lineData->width << 6);
pCir->chip.lg->ModeReg.CONTROL = 0x6000 | (lineData->width << 11);
if (mode->CrtcHDisplay <= 640) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x000E);
} else if (mode->CrtcHDisplay <= 800) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
} else if (mode->CrtcHDisplay <= 1024) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001D);
} else if (mode->CrtcHDisplay <= 1280) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0022);
} else {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0024);
}
} else {
}
pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8);
pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0;
if (PCI_CHIP_GD5465 == pCir->Chipset) {
pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->ModeReg.DTTC & 0xFFC0;
if (pCir->chip.lg->ModeReg.DTTC & 0x0040) {
pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xC0FF)
| ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1);
}
}
vgaHWProtect(pScrn, TRUE);
hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg);
clockData = LgSetClock(pCir, hwp, mode->SynthClock);
pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF;
pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF;
LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg);
vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP);
vgaHWProtect(pScrn, FALSE);
return TRUE;
}
static int LgFindLineData(int displayWidth, int bpp)
{
int i;
for (i = 0; LgLineData[i].pitch > 0; i++)
if (LgLineData[i].pitch >= displayWidth*bpp>>3)
return i;
return -1;
}
static void
LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg)
{
CirPtr pCir;
vgaHWPtr hwp;
CARD8 cr1D;
pCir = CIRPTR(pScrn);
hwp = VGAHWPTR(pScrn);
hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]);
hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]);
cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | (lgReg->ExtVga[CR1D] & 0x01);
hwp->writeCrtc(hwp, 0x1D, cr1D);
hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]);
hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]);
hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]);
hwp->writeSeq(hwp, 0x12, lgReg->ExtVga[SR12]);
hwp->writeSeq(hwp, 0x13, lgReg->ExtVga[SR13]);
hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]);
memww(0xC0, lgReg->FORMAT);
memwl(0x3FC, ((memrl(0x3FC) & ~(1<<28)) | (lgReg->VSC & (1<<28))));
memww(0xEA, lgReg->DTTC);
if (pCir->Chipset == PCI_CHIP_GD5465) {
memww(0x2C4, lgReg->TileCtrl);
}
memwb(0x407, lgReg->TILE);
if (pCir->Chipset == PCI_CHIP_GD5465)
memwb(0x2C0, lgReg->BCLK);
else
memwb(0x8C, lgReg->BCLK);
memww(0x402, lgReg->CONTROL);
}
static void
LgRestore(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp;
vgaRegPtr vgaReg;
CirPtr pCir;
LgRegPtr lgReg;
#ifdef LG_DEBUG
ErrorF("LgRestore pScrn = %p\n", (void *)pScrn);
#endif
pCir = CIRPTR(pScrn);
hwp = VGAHWPTR(pScrn);
vgaReg = &hwp->SavedReg;
lgReg = &pCir->chip.lg->SavedReg;
vgaHWProtect(pScrn, TRUE);
LgRestoreLgRegs(pScrn, lgReg);
vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
vgaHWProtect(pScrn, FALSE);
}
Bool
LgScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn;
vgaHWPtr hwp;
CirPtr pCir;
int i, ret;
VisualPtr visual;
int displayWidth,width,height;
unsigned char * FbBase = NULL;
#ifdef LG_DEBUG
ErrorF("LgScreenInit\n");
#endif
pScrn = xf86Screens[pScreen->myNum];
hwp = VGAHWPTR(pScrn);
hwp->MapSize = 0x10000;
pCir = CIRPTR(pScrn);
if (!vgaHWMapMem(pScrn))
return FALSE;
if (!CirMapMem(pCir, pScrn->scrnIndex))
return FALSE;
#ifdef EXPERIMENTAL
lg_vgaHWSetMmioFunc(hwp, pCir->IOBase);
#endif
vgaHWGetIOBase(hwp);
LgSave(pScrn);
if (!LgModeInit(pScrn, pScrn->currentMode))
return FALSE;
LgSaveScreen(pScreen, SCREEN_SAVER_ON);
LgAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
miClearVisualTypes();
if (!miSetVisualTypes(pScrn->depth,
miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
miSetPixmapDepths ();
#ifdef LG_DEBUG
ErrorF("LgScreenInit after miSetVisualTypes\n");
#endif
displayWidth = pScrn->displayWidth;
if (pCir->rotate) {
height = pScrn->virtualX;
width = pScrn->virtualY;
} else {
width = pScrn->virtualX;
height = pScrn->virtualY;
}
if(pCir->shadowFB) {
pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
pCir->ShadowPtr = xalloc(pCir->ShadowPitch * height);
displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3);
FbBase = pCir->ShadowPtr;
} else {
pCir->ShadowPtr = NULL;
FbBase = pCir->FbBase;
}
switch (pScrn->bitsPerPixel) {
case 8:
case 16:
case 24:
case 32:
ret = fbScreenInit(pScreen, FbBase,
width,height,
pScrn->xDpi, pScrn->yDpi,
displayWidth,pScrn->bitsPerPixel);
break;
default:
xf86DrvMsg(scrnIndex, X_ERROR,
"X11: Internal error: invalid bpp (%d) in LgScreenInit\n",
pScrn->bitsPerPixel);
ret = FALSE;
break;
}
if (!ret)
return FALSE;
#ifdef LG_DEBUG
ErrorF("LgScreenInit after depth dependent init\n");
#endif
if (pScrn->bitsPerPixel > 8) {
for (i = 0; i < pScreen->numVisuals; i++) {
visual = &pScreen->visuals[i];
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);
miInitializeBackingStore(pScreen);
xf86SetBlackWhitePixels(pScreen);
if (!pCir->NoAccel) {
if (!LgXAAInit(pScreen))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialize XAA\n");
}
#if 1
pCir->DGAModeInit = LgModeInit;
if (!CirDGAInit(pScreen))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"DGA initialization failed\n");
#endif
xf86SetSilkenMouse(pScreen);
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
if (pCir->HWCursor) {
if (!LgHWCursorInit(pScreen))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
}
if (!miCreateDefColormap(pScreen))
return FALSE;
if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8)
vgaHWHandleColormaps(pScreen);
xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 0);
pScrn->memPhysBase = pCir->FbAddress;
pScrn->fbOffset = 0;
{
XF86VideoAdaptorPtr *ptr;
int n;
n = xf86XVListGenericAdaptors(pScrn,&ptr);
if (n)
xf86XVScreenInit(pScreen, ptr, n);
}
pScreen->SaveScreen = LgSaveScreen;
pCir->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = LgCloseScreen;
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
return TRUE;
}
Bool
LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
return LgModeInit(xf86Screens[scrnIndex], mode);
}
#define ROUND_DOWN(x, mod) (((x) / (mod)) * (mod))
#define ROUND_UP(x, mod) ((((x) + (mod) - 1) / (mod)) * (mod))
void
LgAdjustFrame(int scrnIndex, int x, int y, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
int Base, tmp;
CirPtr pCir = CIRPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
int cursorX, cursorY;
int middleX, middleY;
const LgLineDataPtr lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
const int viewportXRes =
(PCI_CHIP_GD5465 == pCir->Chipset) ? (24==pScrn->bitsPerPixel?24:1) :
(lineData->width?256:128) /
(24==pScrn->bitsPerPixel?1:(pScrn->bitsPerPixel>>3));
const int viewportYRes =
(PCI_CHIP_GD5465 == pCir->Chipset) ? 1 : (24==pScrn->bitsPerPixel?3:1);
miPointerPosition(&cursorX, &cursorY);
middleX = (pScrn->frameX1 + pScrn->frameX0) / 2;
middleY = (pScrn->frameY1 + pScrn->frameY0) / 2;
if (cursorX < middleX) {
pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes);
} else {
pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes);
}
pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
if (cursorY < middleY) {
pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes);
} else {
pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes);
}
pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
if (x != pScrn->frameX0 || y != pScrn->frameY0) {
x = pScrn->frameX0;
y = pScrn->frameY0;
}
Base = (y * lineData->pitch + (x*pScrn->bitsPerPixel/8)) / 4;
if ((Base & ~0x000FFFFF) != 0) {
ErrorF("X11: Internal error: LgAdjustFrame: cannot handle overflow\n");
return;
}
hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF);
hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2;
tmp |= (Base >> 16) & 0x01;
tmp |= (Base >> 15) & 0x0C;
hwp->writeCrtc(hwp, 0x1B, tmp);
tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7;
tmp |= (Base >> 16) & 0x18;
hwp->writeCrtc(hwp, 0x1D, tmp);
}
Bool
LgEnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
CirPtr pCir = CIRPTR(pScrn);
#ifdef LG_DEBUG
ErrorF("LgEnterVT\n");
#endif
if (pCir->HWCursor)
LgHideCursor(pScrn);
return LgModeInit(pScrn, pScrn->currentMode);
}
void
LgLeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
vgaHWPtr hwp = VGAHWPTR(pScrn);
CirPtr pCir = CIRPTR(pScrn);
#ifdef LG_DEBUG
ErrorF("LgLeaveVT\n");
#endif
if (pCir->HWCursor)
LgShowCursor(pScrn);
LgRestore(pScrn);
vgaHWLock(hwp);
}
static Bool
LgCloseScreen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
vgaHWPtr hwp = VGAHWPTR(pScrn);
CirPtr pCir = CIRPTR(pScrn);
if(pScrn->vtSema) {
LgRestore(pScrn);
if (pCir->HWCursor)
LgHideCursor(pScrn);
vgaHWLock(hwp);
CirUnmapMem(pCir, pScrn->scrnIndex);
}
if (pCir->AccelInfoRec)
XAADestroyInfoRec(pCir->AccelInfoRec);
pCir->AccelInfoRec = NULL;
if (pCir->CursorInfoRec)
xf86DestroyCursorInfoRec(pCir->CursorInfoRec);
pCir->CursorInfoRec = NULL;
if (pCir->DGAModes)
xfree(pCir->DGAModes);
pCir->DGAnumModes = 0;
pCir->DGAModes = NULL;
pScrn->vtSema = FALSE;
pScreen->CloseScreen = pCir->CloseScreen;
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
}
void
LgFreeScreen(int scrnIndex, int flags)
{
#ifdef LG_DEBUG
ErrorF("LgFreeScreen\n");
#endif
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
LgFreeRec(xf86Screens[scrnIndex]);
}
ModeStatus
LgValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
{
int lace;
lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
if ((mode->CrtcHDisplay <= 2048) &&
(mode->CrtcHSyncStart <= 4096) &&
(mode->CrtcHSyncEnd <= 4096) &&
(mode->CrtcHTotal <= 4096) &&
(mode->CrtcVDisplay <= 2048 * lace) &&
(mode->CrtcVSyncStart <= 4096 * lace) &&
(mode->CrtcVSyncEnd <= 4096 * lace) &&
(mode->CrtcVTotal <= 4096 * lace)) {
return(MODE_OK);
}
return(MODE_BAD);
}
static Bool
LgSaveScreen(ScreenPtr pScreen, int mode)
{
CirPtr pCir = CIRPTR(xf86Screens[pScreen->myNum]);
ScrnInfoPtr pScrn = NULL;
Bool unblank;
unblank = xf86IsUnblank(mode);
if (pScreen != NULL)
pScrn = xf86Screens[pScreen->myNum];
if (pScrn != NULL && pScrn->vtSema) {
if (unblank)
memwb(0xB0,memrb(0xB0) & 0x7F);
else
memwb(0xB0,memrb(0xB0) | 0x80);
}
return vgaHWSaveScreen(pScreen, mode);
}
static CARD16
LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq)
{
int ffreq, num, den;
CARD8 tmp;
ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000);
ffreq = freq;
if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den))
return 0;
ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n",
num, den, ffreq / 1000, ffreq % 1000);
tmp = hwp->readSeq(hwp, 0x0E);
hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den);
hwp->writeSeq(hwp, 0x1E, num);
return (den << 8) | num;
}
static void
LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
int flags)
{
unsigned char sr01, cr1a;
vgaHWPtr hwp;
#ifdef LG_DEBUG
ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode);
#endif
hwp = VGAHWPTR(pScrn);
switch (PowerManagementMode) {
case DPMSModeOn:
sr01 = 0x00;
cr1a = 0x00;
break;
case DPMSModeStandby:
sr01 = 0x20;
cr1a = 0x08;
break;
case DPMSModeSuspend:
sr01 = 0x20;
cr1a = 0x04;
break;
case DPMSModeOff:
sr01 = 0x20;
cr1a = 0x0c;
break;
default:
return;
}
sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20;
hwp->writeSeq(hwp, 0x01, sr01);
cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C;
hwp->writeCrtc(hwp, 0x1A, cr1a);
}
#define minb(p) MMIO_IN8(hwp->MMIOBase, (p))
#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v))
static void
mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
{
moutb(index << 2, value);
}
static CARD8
mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
{
return minb(index << 2);
}
static void
lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base)
{
hwp->writeCrtc = mmioWriteCrtc;
hwp->readCrtc = mmioReadCrtc;
hwp->MMIOBase = base;
hwp->MMIOOffset = 0;
}