lg_driver.c revision 1e66b2a2
176888252Smrg/* 276888252Smrg * Driver for CL-GD546x -- The Laguna family 376888252Smrg * 476888252Smrg * lg_driver.c 576888252Smrg * 676888252Smrg * (c) 1998 Corin Anderson. 776888252Smrg * corina@the4cs.com 876888252Smrg * Tukwila, WA 976888252Smrg * 1076888252Smrg * This driver is derived from the cir_driver.c module. 1176888252Smrg * Original authors and contributors list include: 1276888252Smrg * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel, 1376888252Smrg * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff, 1476888252Smrg * Guy DESBIEF, Itai Nahshon. 1576888252Smrg */ 1676888252Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_driver.c,v 1.49 2003/11/03 05:11:09 tsi Exp $ */ 1776888252Smrg 1876888252Smrg#ifdef HAVE_CONFIG_H 1976888252Smrg#include "config.h" 2076888252Smrg#endif 2176888252Smrg 2276888252Smrg#define EXPERIMENTAL 2376888252Smrg 2476888252Smrg/* All drivers should typically include these */ 2576888252Smrg#include "xf86.h" 2676888252Smrg#include "xf86_OSproc.h" 2776888252Smrg 2876888252Smrg/* All drivers need this */ 2976888252Smrg 3076888252Smrg#include "compiler.h" 3176888252Smrg 3276888252Smrg/* Drivers for PCI hardware need this */ 3376888252Smrg#include "xf86PciInfo.h" 3476888252Smrg 3576888252Smrg/* Drivers that need to access the PCI config space directly need this */ 3676888252Smrg#include "xf86Pci.h" 3776888252Smrg 3876888252Smrg/* All drivers using the vgahw module need this */ 3976888252Smrg/* This driver needs to be modified to not use vgaHW for multihead operation */ 4076888252Smrg#include "vgaHW.h" 4176888252Smrg 421e66b2a2Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 4376888252Smrg#include "xf86RAC.h" 4476888252Smrg#include "xf86Resources.h" 451e66b2a2Smrg#endif 4676888252Smrg 4776888252Smrg/* All drivers initialising the SW cursor need this */ 4876888252Smrg#include "mipointer.h" 4976888252Smrg 50afee0becSmrg/* need this for inputInfo */ 51afee0becSmrg#include "inputstr.h" 52afee0becSmrg 5376888252Smrg/* All drivers implementing backing store need this */ 5476888252Smrg#include "mibstore.h" 5576888252Smrg 5676888252Smrg#include "micmap.h" 5776888252Smrg 5876888252Smrg/* Needed by the Shadow Framebuffer */ 5976888252Smrg#include "shadowfb.h" 6076888252Smrg 6176888252Smrg#include "xf86int10.h" 6276888252Smrg 6376888252Smrg#include "fb.h" 6476888252Smrg 6510219488Smrg#include "inputstr.h" 6610219488Smrg 6776888252Smrg#include "xf86DDC.h" 6876888252Smrg 6976888252Smrg#undef LG_DEBUG 7076888252Smrg 7176888252Smrg#include "cir.h" 7276888252Smrg#define _LG_PRIVATE_ 7376888252Smrg#include "lg.h" 7476888252Smrg 7576888252Smrg#include "xf86xv.h" 7676888252Smrg#include <X11/extensions/Xv.h> 7776888252Smrg 7876888252Smrg/* 7976888252Smrg * Forward definitions for the functions that make up the driver. 8076888252Smrg */ 8176888252Smrg 8276888252Smrg/* Mandatory functions */ 8376888252SmrgBool LgPreInit(ScrnInfoPtr pScrn, int flags); 8476888252SmrgBool LgScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); 8576888252SmrgBool LgEnterVT(int scrnIndex, int flags); 8676888252Smrgvoid LgLeaveVT(int scrnIndex, int flags); 8776888252Smrgstatic Bool LgCloseScreen(int scrnIndex, ScreenPtr pScreen); 8876888252Smrgstatic Bool LgSaveScreen(ScreenPtr pScreen, Bool mode); 8976888252Smrg 9076888252Smrg/* Required if the driver supports mode switching */ 9176888252SmrgBool LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); 9276888252Smrg/* Required if the driver supports moving the viewport */ 9376888252Smrgvoid LgAdjustFrame(int scrnIndex, int x, int y, int flags); 9476888252Smrg 9576888252Smrg/* Optional functions */ 9676888252Smrgvoid LgFreeScreen(int scrnIndex, int flags); 9776888252SmrgModeStatus LgValidMode(int scrnIndex, DisplayModePtr mode, 9876888252Smrg Bool verbose, int flags); 9976888252Smrg 10076888252Smrg/* Internally used functions */ 10176888252Smrgstatic void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg); 10276888252Smrgstatic int LgFindLineData(int displayWidth, int bpp); 10376888252Smrgstatic CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq); 10476888252Smrgstatic void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base); 10576888252Smrg 10676888252Smrgstatic void LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, 10776888252Smrg int PowerManagementMode, int flags); 10876888252Smrg 10976888252Smrg/* 11076888252Smrg * This is intentionally screen-independent. It indicates the binding 11176888252Smrg * choice made in the first PreInit. 11276888252Smrg */ 11376888252Smrgstatic int pix24bpp = 0; 11476888252Smrg 11576888252Smrg/* 11676888252Smrg * This contains the functions needed by the server after loading the 11776888252Smrg * driver module. It must be supplied, and gets added the driver list by 11876888252Smrg * the Module Setup funtion in the dynamic case. In the static case a 11976888252Smrg * reference to this is compiled in, and this requires that the name of 12076888252Smrg * this DriverRec be an upper-case version of the driver name. 12176888252Smrg */ 12276888252Smrg 12376888252Smrgtypedef enum { 12476888252Smrg OPTION_HW_CURSOR, 12576888252Smrg OPTION_PCI_RETRY, 12676888252Smrg OPTION_ROTATE, 12776888252Smrg OPTION_SHADOW_FB, 12876888252Smrg OPTION_NOACCEL 12976888252Smrg} LgOpts; 13076888252Smrg 13176888252Smrgstatic const OptionInfoRec LgOptions[] = { 13276888252Smrg { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 13376888252Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 13476888252Smrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 13576888252Smrg { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 13676888252Smrg /* fifo_conservative/aggressive; fast/med/slow_dram; ... */ 13776888252Smrg { -1, NULL, OPTV_NONE, {0}, FALSE } 13876888252Smrg}; 13976888252Smrg 14076888252Smrg 14176888252Smrg/* 1/4bpp 8bpp 15/16bpp 24bpp 32bpp */ 14276888252Smrgstatic int gd5462_MaxClocks[] = { 170000, 170000, 135100, 135100, 85500 }; 14376888252Smrgstatic int gd5464_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 }; 14476888252Smrgstatic int gd5465_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 }; 14576888252Smrg 14676888252SmrgLgLineDataRec LgLineData[] = { 14776888252Smrg { 5, 640, 0}, /* We're rather use skinny tiles, so put all of */ 14876888252Smrg { 8, 1024, 0}, /* them at the head of the table */ 14976888252Smrg {10, 1280, 0}, 15076888252Smrg {13, 1664, 0}, 15176888252Smrg {16, 2048, 0}, 15276888252Smrg {20, 2560, 0}, 15376888252Smrg {10, 2560, 1}, 15476888252Smrg {26, 3328, 0}, 15576888252Smrg { 5, 1280, 1}, 15676888252Smrg { 8, 2048, 1}, 15776888252Smrg {13, 3328, 1}, 15876888252Smrg {16, 4096, 1}, 15976888252Smrg {20, 5120, 1}, 16076888252Smrg {26, 6656, 1}, 16176888252Smrg {-1, -1, -1} /* Sentinal to indicate end of table */ 16276888252Smrg}; 16376888252Smrg 16476888252Smrgstatic int LgLinePitches[4][11] = { 16576888252Smrg /* 8 */ { 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 }, 16676888252Smrg /* 16 */ { 320, 512, 640, 832, 1024, 1280, 1664, 2048, 2560, 3328, 0 }, 16776888252Smrg /* 24 */ { 213, 341, 426, 554, 682, 853, 1109, 1365, 1706, 2218, 0 }, 16876888252Smrg /* 32 */ { 160, 256, 320, 416, 512, 640, 832, 1024, 1280, 1664, 0 } 16976888252Smrg}; 17076888252Smrg 17176888252Smrg#ifdef XFree86LOADER 17276888252Smrg 17376888252Smrg#define LG_MAJOR_VERSION 1 17476888252Smrg#define LG_MINOR_VERSION 0 17576888252Smrg#define LG_PATCHLEVEL 0 17676888252Smrg 17776888252Smrgstatic MODULESETUPPROTO(lgSetup); 17876888252Smrg 17976888252Smrgstatic XF86ModuleVersionInfo lgVersRec = 18076888252Smrg{ 18176888252Smrg "cirrus_laguna", 18276888252Smrg MODULEVENDORSTRING, 18376888252Smrg MODINFOSTRING1, 18476888252Smrg MODINFOSTRING2, 18576888252Smrg XORG_VERSION_CURRENT, 18676888252Smrg LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_PATCHLEVEL, 18776888252Smrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 18876888252Smrg ABI_VIDEODRV_VERSION, 18976888252Smrg MOD_CLASS_NONE, 19076888252Smrg {0,0,0,0} 19176888252Smrg}; 19276888252Smrg 19376888252Smrg/* 19476888252Smrg * This is the module init data. 19576888252Smrg * Its name has to be the driver name followed by ModuleData. 19676888252Smrg */ 19776888252Smrg_X_EXPORT XF86ModuleData cirrus_lagunaModuleData = { 19876888252Smrg &lgVersRec, 19976888252Smrg lgSetup, 20076888252Smrg NULL 20176888252Smrg}; 20276888252Smrg 20376888252Smrgstatic pointer 20476888252SmrglgSetup(pointer module, pointer opts, int *errmaj, int *errmin) 20576888252Smrg{ 20676888252Smrg static Bool setupDone = FALSE; 20776888252Smrg 20876888252Smrg if (!setupDone) { 20976888252Smrg setupDone = TRUE; 21076888252Smrg } 21176888252Smrg return (pointer)1; 21276888252Smrg} 21376888252Smrg 21476888252Smrg#endif /* XFree86LOADER */ 21576888252Smrg 21676888252Smrg_X_EXPORT const OptionInfoRec * 21776888252SmrgLgAvailableOptions(int chipid) 21876888252Smrg{ 21976888252Smrg return LgOptions; 22076888252Smrg} 22176888252Smrg 22276888252Smrg_X_EXPORT ScrnInfoPtr 22376888252SmrgLgProbe(int entity) 22476888252Smrg{ 22576888252Smrg ScrnInfoPtr pScrn = NULL; 22676888252Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets, 22776888252Smrg NULL, NULL, NULL, NULL, NULL))) { 22876888252Smrg pScrn->PreInit = LgPreInit; 22976888252Smrg pScrn->ScreenInit = LgScreenInit; 23076888252Smrg pScrn->SwitchMode = LgSwitchMode; 23176888252Smrg pScrn->AdjustFrame = LgAdjustFrame; 23276888252Smrg pScrn->EnterVT = LgEnterVT; 23376888252Smrg pScrn->LeaveVT = LgLeaveVT; 23476888252Smrg pScrn->FreeScreen = LgFreeScreen; 23576888252Smrg pScrn->ValidMode = LgValidMode; 23676888252Smrg } 23776888252Smrg return pScrn; 23876888252Smrg} 23976888252Smrg 24076888252Smrg 24176888252Smrgstatic Bool 24276888252SmrgLgGetRec(ScrnInfoPtr pScrn) 24376888252Smrg{ 24476888252Smrg CirPtr pCir; 24576888252Smrg 24676888252Smrg if (pScrn->driverPrivate != NULL) 24776888252Smrg return TRUE; 24876888252Smrg 24976888252Smrg pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1); 25076888252Smrg ((CirPtr)pScrn->driverPrivate)->chip.lg = xnfcalloc(sizeof(LgRec),1); 25176888252Smrg 25276888252Smrg /* Initialize it */ 25376888252Smrg pCir = CIRPTR(pScrn); 25476888252Smrg pCir->chip.lg->oldBitmask = 0x00000000; 25576888252Smrg 25676888252Smrg return TRUE; 25776888252Smrg} 25876888252Smrg 25976888252Smrgstatic void 26076888252SmrgLgFreeRec(ScrnInfoPtr pScrn) 26176888252Smrg{ 26276888252Smrg if (pScrn->driverPrivate == NULL) 26376888252Smrg return; 26476888252Smrg xfree(pScrn->driverPrivate); 26576888252Smrg pScrn->driverPrivate = NULL; 26676888252Smrg} 26776888252Smrg 26876888252Smrg 26976888252Smrg 27076888252Smrg/* 27176888252Smrg * LgCountRAM -- 27276888252Smrg * 27376888252Smrg * Counts amount of installed RAM 27476888252Smrg */ 27576888252Smrg 27676888252Smrg/* XXX We need to get rid of this PIO (MArk) */ 27776888252Smrgstatic int 27876888252SmrgLgCountRam(ScrnInfoPtr pScrn) 27976888252Smrg{ 28076888252Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 28176888252Smrg CARD8 SR14; 28276888252Smrg 28376888252Smrg vgaHWProtect(pScrn, TRUE); 28476888252Smrg 28576888252Smrg /* The ROM BIOS scratchpad registers contain, 28676888252Smrg among other things, the amount of installed 28776888252Smrg RDRAM on the laguna chip. */ 28876888252Smrg SR14 = hwp->readSeq(hwp, 0x14); 28976888252Smrg 29076888252Smrg ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n", 29176888252Smrg hwp->readSeq(hwp, 9), hwp->readSeq(hwp, 10), 29276888252Smrg SR14, hwp->readSeq(hwp, 0x15)); 29376888252Smrg 29476888252Smrg vgaHWProtect(pScrn, FALSE); 29576888252Smrg 29676888252Smrg return 1024 * ((SR14&0x7) + 1); 29776888252Smrg 29876888252Smrg /* !!! This function seems to be incorrect... */ 29976888252Smrg} 30076888252Smrg 30176888252Smrgstatic xf86MonPtr 30276888252SmrgLgDoDDC(ScrnInfoPtr pScrn) 30376888252Smrg{ 30476888252Smrg CirPtr pCir = CIRPTR(pScrn); 30576888252Smrg xf86MonPtr MonInfo = NULL; 30676888252Smrg 30776888252Smrg /* Map the CIR memory and MMIO areas */ 30876888252Smrg if (!CirMapMem(pCir, pScrn->scrnIndex)) 30976888252Smrg return FALSE; 31076888252Smrg 31176888252Smrg#if LGuseI2C 31276888252Smrg if (!LgI2CInit(pScrn)) { 31376888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed\n"); 31476888252Smrg 31576888252Smrg goto unmap_out; 31676888252Smrg } 31776888252Smrg 31876888252Smrg /* Read and output monitor info using DDC2 over I2C bus */ 31976888252Smrg MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pCir->I2CPtr1); 32076888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n", 32176888252Smrg (void *)MonInfo); 32276888252Smrg xf86PrintEDID(MonInfo); 32376888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n\n"); 32476888252Smrg#endif /* LGuseI2C */ 32576888252Smrg 32676888252Smrg xf86SetDDCproperties(pScrn, MonInfo); 32776888252Smrg 32876888252Smrgunmap_out: 32976888252Smrg CirUnmapMem(pCir, pScrn->scrnIndex); 33076888252Smrg 33176888252Smrg return MonInfo; 33276888252Smrg} 33376888252Smrg 33476888252Smrg/* Mandatory */ 33576888252SmrgBool 33676888252SmrgLgPreInit(ScrnInfoPtr pScrn, int flags) 33776888252Smrg{ 33876888252Smrg CirPtr pCir; 33976888252Smrg vgaHWPtr hwp; 34076888252Smrg MessageType from; 34176888252Smrg int i; 34276888252Smrg ClockRangePtr clockRanges; 34376888252Smrg int fbPCIReg, ioPCIReg; 34476888252Smrg char *s; 34576888252Smrg 34676888252Smrg if (flags & PROBE_DETECT) { 34776888252Smrg cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 34876888252Smrg return TRUE; 34976888252Smrg } 35076888252Smrg 35176888252Smrg#ifdef LG_DEBUG 35276888252Smrg ErrorF("LgPreInit\n"); 35376888252Smrg#endif 35476888252Smrg 35576888252Smrg /* Check the number of entities, and fail if it isn't one. */ 35676888252Smrg if (pScrn->numEntities != 1) 35776888252Smrg return FALSE; 35876888252Smrg 35976888252Smrg /* The vgahw module should be loaded here when needed */ 36076888252Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) 36176888252Smrg return FALSE; 36276888252Smrg 36376888252Smrg /* 36476888252Smrg * Allocate a vgaHWRec 36576888252Smrg */ 36676888252Smrg if (!vgaHWGetHWRec(pScrn)) 36776888252Smrg return FALSE; 36876888252Smrg 36976888252Smrg hwp = VGAHWPTR(pScrn); 37076888252Smrg vgaHWGetIOBase(hwp); 37176888252Smrg 37276888252Smrg /* Allocate the LgRec driverPrivate */ 37376888252Smrg if (!LgGetRec(pScrn)) 37476888252Smrg return FALSE; 37576888252Smrg 37676888252Smrg pCir = CIRPTR(pScrn); 37776888252Smrg pCir->pScrn = pScrn; 37876888252Smrg pCir->PIOReg = hwp->PIOOffset + 0x3CE; 37976888252Smrg 38076888252Smrg /* Get the entity, and make sure it is PCI. */ 38176888252Smrg pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 38276888252Smrg if (pCir->pEnt->location.type != BUS_PCI) 38376888252Smrg return FALSE; 38476888252Smrg pCir->Chipset = pCir->pEnt->chipset; 38576888252Smrg 38676888252Smrg /* Find the PCI info for this screen */ 38776888252Smrg pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index); 3881ae1b5e8Smrg pCir->PciTag = pciTag(PCI_DEV_BUS(pCir->PciInfo), 3891ae1b5e8Smrg PCI_DEV_DEV(pCir->PciInfo), 3901ae1b5e8Smrg PCI_DEV_FUNC(pCir->PciInfo)); 39176888252Smrg 39276888252Smrg if (xf86LoadSubModule(pScrn, "int10")) { 39376888252Smrg xf86Int10InfoPtr int10InfoPtr; 39476888252Smrg 39576888252Smrg int10InfoPtr = xf86InitInt10(pCir->pEnt->index); 39676888252Smrg 39776888252Smrg if (int10InfoPtr) 39876888252Smrg xf86FreeInt10(int10InfoPtr); 39976888252Smrg } 40076888252Smrg 40176888252Smrg /* Set pScrn->monitor */ 40276888252Smrg pScrn->monitor = pScrn->confScreen->monitor; 40376888252Smrg 40476888252Smrg /* 40576888252Smrg * The first thing we should figure out is the depth, bpp, etc. 40676888252Smrg * We support both 24bpp and 32bpp layouts, so indicate that. 40776888252Smrg */ 40876888252Smrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | 40976888252Smrg SupportConvert32to24 | PreferConvert32to24)) { 41076888252Smrg return FALSE; 41176888252Smrg } 41276888252Smrg /* Check that the returned depth is one we support */ 41376888252Smrg switch (pScrn->depth) { 41476888252Smrg case 8: 41576888252Smrg case 15: 41676888252Smrg case 16: 41776888252Smrg case 24: 41876888252Smrg case 32: 41976888252Smrg /* OK */ 42076888252Smrg break; 42176888252Smrg default: 42276888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 42376888252Smrg "Given depth (%d) is not supported by this driver\n", pScrn->depth); 42476888252Smrg return FALSE; 42576888252Smrg } 42676888252Smrg xf86PrintDepthBpp(pScrn); 42776888252Smrg 42876888252Smrg /* Get the depth24 pixmap format */ 42976888252Smrg if (pScrn->depth == 24 && pix24bpp == 0) 43076888252Smrg pix24bpp = xf86GetBppFromDepth(pScrn, 24); 43176888252Smrg 43276888252Smrg /* 43376888252Smrg * This must happen after pScrn->display has been set because 43476888252Smrg * xf86SetWeight references it. 43576888252Smrg */ 43676888252Smrg if (pScrn->depth > 8) { 43776888252Smrg /* The defaults are OK for us */ 43876888252Smrg rgb zeros = {0, 0, 0}; 43976888252Smrg 44076888252Smrg /* !!! I think we can force 5-6-5 weight for 16bpp here for 44176888252Smrg the 5462. */ 44276888252Smrg 44376888252Smrg if (!xf86SetWeight(pScrn, zeros, zeros)) { 44476888252Smrg return FALSE; 44576888252Smrg } else { 44676888252Smrg /* XXX check that weight returned is supported */ 44776888252Smrg ; 44876888252Smrg } 44976888252Smrg } 45076888252Smrg 45176888252Smrg if (!xf86SetDefaultVisual(pScrn, -1)) 45276888252Smrg return FALSE; 45376888252Smrg 45476888252Smrg 45576888252Smrg /* Collect all of the relevant option flags (fill in pScrn->options) */ 45676888252Smrg xf86CollectOptions(pScrn, NULL); 45776888252Smrg 45876888252Smrg /* Process the options */ 45976888252Smrg if (!(pCir->Options = xalloc(sizeof(LgOptions)))) 46076888252Smrg return FALSE; 46176888252Smrg memcpy(pCir->Options, LgOptions, sizeof(LgOptions)); 46276888252Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options); 46376888252Smrg 46476888252Smrg pScrn->rgbBits = 6; 46576888252Smrg from = X_DEFAULT; 46676888252Smrg pCir->HWCursor = FALSE; 46776888252Smrg if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, &pCir->HWCursor)) 46876888252Smrg from = X_CONFIG; 46976888252Smrg 47076888252Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 47176888252Smrg pCir->HWCursor ? "HW" : "SW"); 47276888252Smrg if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) { 47376888252Smrg pCir->NoAccel = TRUE; 47476888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 47576888252Smrg } 47676888252Smrg if (pScrn->bitsPerPixel < 8) { 47776888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 47876888252Smrg "Cannot use in less than 8 bpp\n"); 47976888252Smrg return FALSE; 48076888252Smrg } 48176888252Smrg /* 48276888252Smrg * Set the ChipRev, allowing config file entries to 48376888252Smrg * override. 48476888252Smrg */ 48576888252Smrg if (pCir->pEnt->device->chipRev >= 0) { 48676888252Smrg pCir->ChipRev = pCir->pEnt->device->chipRev; 48776888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 48876888252Smrg pCir->ChipRev); 48976888252Smrg } else { 4901ae1b5e8Smrg pCir->ChipRev = PCI_DEV_REVISION(pCir->PciInfo); 49176888252Smrg } 49276888252Smrg 49376888252Smrg /* Cirrus swapped the FB and IO registers in the 5465 (by design). */ 49476888252Smrg if (PCI_CHIP_GD5465 == pCir->Chipset) { 49576888252Smrg fbPCIReg = 0; 49676888252Smrg ioPCIReg = 1; 49776888252Smrg } else { 49876888252Smrg fbPCIReg = 1; 49976888252Smrg ioPCIReg = 0; 50076888252Smrg } 50176888252Smrg 50276888252Smrg /* Find the frame buffer base address */ 50376888252Smrg if (pCir->pEnt->device->MemBase != 0) { 50476888252Smrg /* Require that the config file value matches one of the PCI values. */ 50576888252Smrg if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->MemBase)) { 50676888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 50776888252Smrg "MemBase 0x%08lX doesn't match any PCI base register.\n", 50876888252Smrg pCir->pEnt->device->MemBase); 50976888252Smrg return FALSE; 51076888252Smrg } 51176888252Smrg pCir->FbAddress = pCir->pEnt->device->MemBase; 51276888252Smrg from = X_CONFIG; 51376888252Smrg } else { 5141ae1b5e8Smrg if (PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) != 0) { 5151ae1b5e8Smrg pCir->FbAddress = PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) & 0xff000000; 51676888252Smrg from = X_PROBED; 51776888252Smrg } else { 51876888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 51976888252Smrg "No valid FB address in PCI config space\n"); 52076888252Smrg LgFreeRec(pScrn); 52176888252Smrg return FALSE; 52276888252Smrg } 52376888252Smrg } 52476888252Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 52576888252Smrg (unsigned long)pCir->FbAddress); 52676888252Smrg 52776888252Smrg /* Find the MMIO base address */ 52876888252Smrg if (pCir->pEnt->device->IOBase != 0) { 52976888252Smrg /* Require that the config file value matches one of the PCI values. */ 53076888252Smrg if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->IOBase)) { 53176888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 53276888252Smrg "IOBase 0x%08lX doesn't match any PCI base register.\n", 53376888252Smrg pCir->pEnt->device->IOBase); 53476888252Smrg return FALSE; 53576888252Smrg } 53676888252Smrg pCir->IOAddress = pCir->pEnt->device->IOBase; 53776888252Smrg from = X_CONFIG; 53876888252Smrg } else { 5391ae1b5e8Smrg if (PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) != 0) { 5401ae1b5e8Smrg pCir->IOAddress = PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) & 0xfffff000; 54176888252Smrg from = X_PROBED; 54276888252Smrg } else { 54376888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 54476888252Smrg "No valid MMIO address in PCI config space\n"); 54576888252Smrg } 54676888252Smrg } 54776888252Smrg xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", 54876888252Smrg (unsigned long)pCir->IOAddress); 54976888252Smrg 55076888252Smrg /* 55176888252Smrg * If the user has specified the amount of memory in the XF86Config 55276888252Smrg * file, we respect that setting. 55376888252Smrg */ 55476888252Smrg if (pCir->pEnt->device->videoRam != 0) { 55576888252Smrg pScrn->videoRam = pCir->pEnt->device->videoRam; 55676888252Smrg from = X_CONFIG; 55776888252Smrg } else { 55876888252Smrg pScrn->videoRam = LgCountRam(pScrn); 55976888252Smrg from = X_PROBED; 56076888252Smrg } 56176888252Smrg if (2048 == pScrn->videoRam) { 56276888252Smrg /* Two-way interleaving */ 56376888252Smrg pCir->chip.lg->memInterleave = 0x40; 56476888252Smrg } else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) { 56576888252Smrg /* Four-way interleaving */ 56676888252Smrg pCir->chip.lg->memInterleave = 0x80; 56776888252Smrg } else { 56876888252Smrg /* One-way interleaving */ 56976888252Smrg pCir->chip.lg->memInterleave = 0x00; 57076888252Smrg } 57176888252Smrg 57276888252Smrg xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", 57376888252Smrg pScrn->videoRam); 57476888252Smrg 57576888252Smrg pCir->FbMapSize = pScrn->videoRam * 1024; 57676888252Smrg pCir->IoMapSize = 0x4000; /* 16K for moment, will increase */ 57776888252Smrg 5781e66b2a2Smrg#ifndef XSERVER_LIBPCIACCESS 57976888252Smrg pScrn->racIoFlags = RAC_COLORMAP 58076888252Smrg#ifndef EXPERIMENTAL 58176888252Smrg | RAC_VIEWPORT 58276888252Smrg#endif 58376888252Smrg; 58476888252Smrg xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr); 58576888252Smrg 58676888252Smrg /* Register the PCI-assigned resources. */ 58776888252Smrg if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) { 58876888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 58976888252Smrg "xf86RegisterResources() found resource conflicts\n"); 59076888252Smrg return FALSE; 59176888252Smrg } 5921e66b2a2Smrg#endif 59376888252Smrg if (!xf86LoadSubModule(pScrn, "ddc")) { 59476888252Smrg LgFreeRec(pScrn); 59576888252Smrg return FALSE; 59676888252Smrg } 59776888252Smrg 59876888252Smrg#if LGuseI2C 59976888252Smrg if (!xf86LoadSubModule(pScrn, "i2c")) { 60076888252Smrg LgFreeRec(pScrn); 60176888252Smrg return FALSE; 60276888252Smrg } 60376888252Smrg#endif 60476888252Smrg 60576888252Smrg /* Read and print the monitor DDC information */ 60676888252Smrg pScrn->monitor->DDC = LgDoDDC(pScrn); 60776888252Smrg 60876888252Smrg /* The gamma fields must be initialised when using the new cmap code */ 60976888252Smrg if (pScrn->depth > 1) { 61076888252Smrg Gamma zeros = {0.0, 0.0, 0.0}; 61176888252Smrg 61276888252Smrg if (!xf86SetGamma(pScrn, zeros)) 61376888252Smrg return FALSE; 61476888252Smrg } 61576888252Smrg if (xf86GetOptValBool(pCir->Options, 61676888252Smrg OPTION_SHADOW_FB,&pCir->shadowFB)) 61776888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", 61876888252Smrg pCir->shadowFB ? "enabled" : "disabled"); 61976888252Smrg 62076888252Smrg if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) { 62176888252Smrg if(!xf86NameCmp(s, "CW")) { 62276888252Smrg /* accel is disabled below for shadowFB */ 62376888252Smrg pCir->shadowFB = TRUE; 62476888252Smrg pCir->rotate = 1; 62576888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 62676888252Smrg "Rotating screen clockwise - acceleration disabled\n"); 62776888252Smrg } else if(!xf86NameCmp(s, "CCW")) { 62876888252Smrg pCir->shadowFB = TRUE; 62976888252Smrg pCir->rotate = -1; 63076888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 63176888252Smrg "counter clockwise - acceleration disabled\n"); 63276888252Smrg } else { 63376888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 63476888252Smrg "value for Option \"Rotate\"\n", s); 63576888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 63676888252Smrg "Valid options are \"CW\" or \"CCW\"\n"); 63776888252Smrg } 63876888252Smrg } 63976888252Smrg 64076888252Smrg if (pCir->shadowFB && !pCir->NoAccel) { 64176888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 64276888252Smrg "HW acceleration not supported with \"shadowFB\".\n"); 64376888252Smrg pCir->NoAccel = TRUE; 64476888252Smrg } 64576888252Smrg 64676888252Smrg if (pCir->rotate && pCir->HWCursor) { 64776888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 64876888252Smrg "HW cursor not supported with \"rotate\".\n"); 64976888252Smrg pCir->HWCursor = FALSE; 65076888252Smrg } 65176888252Smrg 65276888252Smrg /* We use a programmable clock */ 65376888252Smrg pScrn->progClock = TRUE; 65476888252Smrg 65576888252Smrg /* XXX Set HW cursor use */ 65676888252Smrg 65776888252Smrg /* Set the min pixel clock */ 65876888252Smrg pCir->MinClock = 12000; /* XXX Guess, need to check this */ 65976888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 66076888252Smrg pCir->MinClock / 1000); 66176888252Smrg /* 66276888252Smrg * If the user has specified ramdac speed in the XF86Config 66376888252Smrg * file, we respect that setting. 66476888252Smrg */ 66576888252Smrg if (pCir->pEnt->device->dacSpeeds[0]) { 66676888252Smrg ErrorF("Do not specify a Clocks line for Cirrus chips\n"); 66776888252Smrg return FALSE; 66876888252Smrg } else { 66976888252Smrg int speed; 67076888252Smrg int *p; 67176888252Smrg switch (pCir->Chipset) { 67276888252Smrg case PCI_CHIP_GD5462: 67376888252Smrg p = gd5462_MaxClocks; 67476888252Smrg break; 67576888252Smrg case PCI_CHIP_GD5464: 67676888252Smrg case PCI_CHIP_GD5464BD: 67776888252Smrg p = gd5464_MaxClocks; 67876888252Smrg break; 67976888252Smrg case PCI_CHIP_GD5465: 68076888252Smrg p = gd5465_MaxClocks; 68176888252Smrg break; 68276888252Smrg default: 68376888252Smrg ErrorF("???\n"); 68476888252Smrg return FALSE; 68576888252Smrg } 68676888252Smrg switch (pScrn->bitsPerPixel) { 68776888252Smrg case 8: 68876888252Smrg speed = p[1]; 68976888252Smrg break; 69076888252Smrg case 15: 69176888252Smrg case 16: 69276888252Smrg speed = p[2]; 69376888252Smrg break; 69476888252Smrg case 24: 69576888252Smrg speed = p[3]; 69676888252Smrg break; 69776888252Smrg case 32: 69876888252Smrg speed = p[4]; 69976888252Smrg break; 70076888252Smrg default: 70176888252Smrg /* Should not get here */ 70276888252Smrg speed = 0; 70376888252Smrg break; 70476888252Smrg } 70576888252Smrg pCir->MaxClock = speed; 70676888252Smrg from = X_PROBED; 70776888252Smrg } 70876888252Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 70976888252Smrg pCir->MaxClock / 1000); 71076888252Smrg 71176888252Smrg /* 71276888252Smrg * Setup the ClockRanges, which describe what clock ranges are available, 71376888252Smrg * and what sort of modes they can be used for. 71476888252Smrg */ 71576888252Smrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 71676888252Smrg clockRanges->next = NULL; 71776888252Smrg clockRanges->minClock = pCir->MinClock; 71876888252Smrg clockRanges->maxClock = pCir->MaxClock; 71976888252Smrg clockRanges->clockIndex = -1; /* programmable */ 72076888252Smrg clockRanges->interlaceAllowed = FALSE; /* XXX check this */ 72176888252Smrg clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 72276888252Smrg clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 72376888252Smrg clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 72476888252Smrg clockRanges->ClockMulFactor = 1; 72576888252Smrg clockRanges->ClockDivFactor = 1; 72676888252Smrg clockRanges->PrivFlags = 0; 72776888252Smrg 72876888252Smrg /* Depending upon what sized tiles used, either 128 or 256. */ 72976888252Smrg /* Aw, heck. Just say 128. */ 73076888252Smrg pCir->Rounding = 128 >> pCir->BppShift; 73176888252Smrg 73276888252Smrg /* 73376888252Smrg * xf86ValidateModes will check that the mode HTotal and VTotal values 73476888252Smrg * don't exceed the chipset's limit if pScrn->maxHValue and 73576888252Smrg * pScrn->maxVValue are set. Since our CIRValidMode() already takes 73676888252Smrg * care of this, we don't worry about setting them here. 73776888252Smrg */ 73876888252Smrg 73976888252Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, 74076888252Smrg clockRanges, 74176888252Smrg LgLinePitches[pScrn->bitsPerPixel / 8 - 1], 74276888252Smrg 0, 0, 128 * 8, 74376888252Smrg 0, 0, /* Any virtual height is allowed. */ 74476888252Smrg pScrn->display->virtualX, 74576888252Smrg pScrn->display->virtualY, 74676888252Smrg pCir->FbMapSize, 74776888252Smrg LOOKUP_BEST_REFRESH); 74876888252Smrg 74976888252Smrg pCir->chip.lg->lineDataIndex = LgFindLineData(pScrn->displayWidth, 75076888252Smrg pScrn->bitsPerPixel); 75176888252Smrg 75276888252Smrg if (i == -1) { 75376888252Smrg LgFreeRec(pScrn); 75476888252Smrg return FALSE; 75576888252Smrg } 75676888252Smrg 75776888252Smrg /* Prune the modes marked as invalid */ 75876888252Smrg xf86PruneDriverModes(pScrn); 75976888252Smrg 76076888252Smrg if (i == 0 || pScrn->modes == NULL) { 76176888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 76276888252Smrg LgFreeRec(pScrn); 76376888252Smrg return FALSE; 76476888252Smrg } 76576888252Smrg 76676888252Smrg /* 76776888252Smrg * Set the CRTC parameters for all of the modes based on the type 76876888252Smrg * of mode, and the chipset's interlace requirements. 76976888252Smrg * 77076888252Smrg * Calling this is required if the mode->Crtc* values are used by the 77176888252Smrg * driver and if the driver doesn't provide code to set them. They 77276888252Smrg * are not pre-initialised at all. 77376888252Smrg */ 77476888252Smrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 77576888252Smrg 77676888252Smrg /* Set the current mode to the first in the list */ 77776888252Smrg pScrn->currentMode = pScrn->modes; 77876888252Smrg 77976888252Smrg /* Print the list of modes being used */ 78076888252Smrg xf86PrintModes(pScrn); 78176888252Smrg 78276888252Smrg /* Set display resolution */ 78376888252Smrg xf86SetDpi(pScrn, 0, 0); 78476888252Smrg 78576888252Smrg /* Load bpp-specific modules */ 78676888252Smrg switch (pScrn->bitsPerPixel) { 78776888252Smrg case 8: 78876888252Smrg case 16: 78976888252Smrg case 24: 79076888252Smrg case 32: 79176888252Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 79276888252Smrg LgFreeRec(pScrn); 79376888252Smrg return FALSE; 79476888252Smrg } 79576888252Smrg break; 79676888252Smrg } 79776888252Smrg 79876888252Smrg /* Load XAA if needed */ 79976888252Smrg if (!pCir->NoAccel) { 80076888252Smrg if (!xf86LoadSubModule(pScrn, "xaa")) { 80176888252Smrg LgFreeRec(pScrn); 80276888252Smrg return FALSE; 80376888252Smrg } 80476888252Smrg } 80576888252Smrg 80676888252Smrg /* Load ramdac if needed */ 80776888252Smrg if (pCir->HWCursor) { 80876888252Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 80976888252Smrg LgFreeRec(pScrn); 81076888252Smrg return FALSE; 81176888252Smrg } 81276888252Smrg } 81376888252Smrg 81476888252Smrg if (pCir->shadowFB) { 81576888252Smrg if (!xf86LoadSubModule(pScrn, "shadowfb")) { 81676888252Smrg LgFreeRec(pScrn); 81776888252Smrg return FALSE; 81876888252Smrg } 81976888252Smrg } 82076888252Smrg 82176888252Smrg return TRUE; 82276888252Smrg} 82376888252Smrg 82476888252Smrg/* 82576888252Smrg * This function saves the video state. 82676888252Smrg */ 82776888252Smrgstatic void 82876888252SmrgLgSave(ScrnInfoPtr pScrn) 82976888252Smrg{ 83076888252Smrg CirPtr pCir = CIRPTR(pScrn); 83176888252Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 83276888252Smrg 83376888252Smrg#ifdef LG_DEBUG 83476888252Smrg ErrorF("LgSave\n"); 83576888252Smrg#endif 83676888252Smrg 83776888252Smrg vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL); 83876888252Smrg 83976888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1A] = pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A); 84076888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] = pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B); 84176888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1D] = pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D); 84276888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] = pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E); 84376888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR07] = pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07); 84476888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR0E] = pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E); 84576888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR12] = pCir->chip.lg->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12); 84676888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR13] = pCir->chip.lg->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13); 84776888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR1E] = pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E); 84876888252Smrg 84976888252Smrg pCir->chip.lg->ModeReg.FORMAT = pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0); 85076888252Smrg 85176888252Smrg pCir->chip.lg->ModeReg.VSC = pCir->chip.lg->SavedReg.VSC = memrl(0x3FC); 85276888252Smrg 85376888252Smrg pCir->chip.lg->ModeReg.DTTC = pCir->chip.lg->SavedReg.DTTC = memrw(0xEA); 85476888252Smrg 85576888252Smrg if (pCir->Chipset == PCI_CHIP_GD5465) { 85676888252Smrg pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4); 85776888252Smrg } 85876888252Smrg 85976888252Smrg pCir->chip.lg->ModeReg.TILE = pCir->chip.lg->SavedReg.TILE = memrb(0x407); 86076888252Smrg 86176888252Smrg if (pCir->Chipset == PCI_CHIP_GD5465) 86276888252Smrg pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0); 86376888252Smrg else 86476888252Smrg pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x8C); 86576888252Smrg 86676888252Smrg pCir->chip.lg->ModeReg.CONTROL = pCir->chip.lg->SavedReg.CONTROL = memrw(0x402); 86776888252Smrg} 86876888252Smrg 86976888252Smrg/* 87076888252Smrg * Initialise a new mode. This is currently still using the old 87176888252Smrg * "initialise struct, restore/write struct to HW" model. That could 87276888252Smrg * be changed. 87376888252Smrg */ 87476888252Smrg 87576888252Smrgstatic Bool 87676888252SmrgLgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 87776888252Smrg{ 87876888252Smrg vgaHWPtr hwp; 87976888252Smrg CirPtr pCir; 88076888252Smrg int width; 88176888252Smrg Bool VDiv2 = FALSE; 88276888252Smrg CARD16 clockData; 88376888252Smrg LgLineDataPtr lineData; 88476888252Smrg 88576888252Smrg#ifdef LG_DEBUG 88676888252Smrg ErrorF("LgModeInit %d bpp, %d %d %d %d %d %d %d %d %d\n", 88776888252Smrg pScrn->bitsPerPixel, 88876888252Smrg mode->Clock, 88976888252Smrg mode->HDisplay, 89076888252Smrg mode->HSyncStart, 89176888252Smrg mode->HSyncEnd, 89276888252Smrg mode->HTotal, 89376888252Smrg mode->VDisplay, 89476888252Smrg mode->VSyncStart, 89576888252Smrg mode->VSyncEnd, 89676888252Smrg mode->VTotal); 89776888252Smrg 89876888252Smrg ErrorF("LgModeInit: depth %d bits\n", pScrn->depth); 89976888252Smrg#endif 90076888252Smrg 90176888252Smrg pCir = CIRPTR(pScrn); 90276888252Smrg hwp = VGAHWPTR(pScrn); 90376888252Smrg vgaHWUnlock(hwp); 90476888252Smrg 90576888252Smrg if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) { 90676888252Smrg /* For non-interlaced vertical timing >= 1024, the vertical timings */ 90776888252Smrg /* are divided by 2 and VGA CRTC 0x17 bit 2 is set. */ 90876888252Smrg if (!mode->CrtcVAdjusted) { 90976888252Smrg mode->CrtcVDisplay >>= 1; 91076888252Smrg mode->CrtcVSyncStart >>= 1; 91176888252Smrg mode->CrtcVSyncEnd >>= 1; 91276888252Smrg mode->CrtcVTotal >>= 1; 91376888252Smrg mode->CrtcVAdjusted = TRUE; 91476888252Smrg } 91576888252Smrg VDiv2 = TRUE; 91676888252Smrg } 91776888252Smrg 91876888252Smrg /* Initialise the ModeReg values */ 91976888252Smrg if (!vgaHWInit(pScrn, mode)) 92076888252Smrg return FALSE; 92176888252Smrg pScrn->vtSema = TRUE; 92276888252Smrg 92376888252Smrg if (VDiv2) 92476888252Smrg hwp->ModeReg.CRTC[0x17] |= 0x04; 92576888252Smrg 92676888252Smrg#ifdef LG_DEBUG 92776888252Smrg ErrorF("SynthClock = %d\n", mode->SynthClock); 92876888252Smrg#endif 92976888252Smrg hwp->IOBase = 0x3D0; 93076888252Smrg hwp->ModeReg.MiscOutReg |= 0x01; 93176888252Smrg#if 0 /* Mono address */ 93276888252Smrg hwp->IOBase = 0x3B0; 93376888252Smrg hwp->ModeReg.MiscOutReg &= ~0x01; 93476888252Smrg#endif 93576888252Smrg 93676888252Smrg 93776888252Smrg /* ??? Should these be both ...End or ...Start, not one of each? */ 93876888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1A] = (((mode->CrtcVSyncStart + 1) & 0x300 ) >> 2) 93976888252Smrg | (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2); 94076888252Smrg 94176888252Smrg width = pScrn->displayWidth * pScrn->bitsPerPixel / 8; 94276888252Smrg if (pScrn->bitsPerPixel == 1) 94376888252Smrg width <<= 2; 94476888252Smrg hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3; 94576888252Smrg /* Offset extension (see CR13) */ 94676888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF; 94776888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] |= (((width + 7) >> 3) & 0x100)?0x10:0x00; 94876888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22; 94976888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1D] = (((width + 7) >> 3) & 0x200)?0x01:0x00; 95076888252Smrg 95176888252Smrg /* Set the 28th bit to enable extended modes. */ 95276888252Smrg pCir->chip.lg->ModeReg.VSC = 0x10000000; 95376888252Smrg 95476888252Smrg /* Overflow register (sure are a lot of overflow bits around...) */ 95576888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00; 95676888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHTotal>>3 & 0x0100)?1:0)<<7; 95776888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHDisplay>>3 & 0x0100)?1:0)<<6; 95876888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<5; 95976888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<4; 96076888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVTotal & 0x0400)?1:0)<<3; 96176888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVDisplay & 0x0400)?1:0)<<2; 96276888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<1; 96376888252Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<0; 96476888252Smrg 96576888252Smrg lineData = &LgLineData[pCir->chip.lg->lineDataIndex]; 96676888252Smrg 96776888252Smrg pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F; 96876888252Smrg 96976888252Smrg if (8 == pScrn->bitsPerPixel) { 97076888252Smrg pCir->chip.lg->ModeReg.FORMAT = 0x0000; 97176888252Smrg 97276888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 97376888252Smrg | (lineData->width << 6); 97476888252Smrg pCir->chip.lg->ModeReg.CONTROL = 0x0000 | (lineData->width << 11); 97576888252Smrg 97676888252Smrg 97776888252Smrg /* There is an optimal FIFO threshold value (lower 5 bits of DTTC) 97876888252Smrg for every resolution and color depth combination. We'll hit 97976888252Smrg the highlights here, and get close for anything that's not 98076888252Smrg covered. */ 98176888252Smrg if (mode->CrtcHDisplay <= 640) { 98276888252Smrg /* BAD numbers: 0x1E */ 98376888252Smrg /* GOOD numbers: 0x14 */ 98476888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014); 98576888252Smrg } else if (mode->CrtcHDisplay <= 800) { 98676888252Smrg /* BAD numbers: 0x16 */ 98776888252Smrg /* GOOD numbers: 0x13 0x14 */ 98876888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014); 98976888252Smrg } else if (mode->CrtcHDisplay <= 1024) { 99076888252Smrg /* BAD numbers: */ 99176888252Smrg /* GOOD numbers: 0x15 */ 99276888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015); 99376888252Smrg } else if (mode->CrtcHDisplay <= 1280) { 99476888252Smrg /* BAD numbers: */ 99576888252Smrg /* GOOD numbers: 0x16 */ 99676888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0016); 99776888252Smrg } else { 99876888252Smrg /* BAD numbers: */ 99976888252Smrg /* GOOD numbers: */ 100076888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 100176888252Smrg } 100276888252Smrg } else if (16 == pScrn->bitsPerPixel) { 100376888252Smrg /* !!! Assume 5-6-5 RGB mode (for now...) */ 100476888252Smrg pCir->chip.lg->ModeReg.FORMAT = 0x1400; 100576888252Smrg 100676888252Smrg if (pScrn->depth == 15) 100776888252Smrg pCir->chip.lg->ModeReg.FORMAT = 0x1600; 100876888252Smrg 100976888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 101076888252Smrg | (lineData->width << 6); 101176888252Smrg pCir->chip.lg->ModeReg.CONTROL = 0x2000 | (lineData->width << 11); 101276888252Smrg 101376888252Smrg if (mode->CrtcHDisplay <= 640) { 101476888252Smrg /* BAD numbers: 0x12 */ 101576888252Smrg /* GOOD numbers: 0x10 */ 101676888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010); 101776888252Smrg } else if (mode->CrtcHDisplay <= 800) { 101876888252Smrg /* BAD numbers: 0x13 */ 101976888252Smrg /* GOOD numbers: 0x11 */ 102076888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011); 102176888252Smrg } else if (mode->CrtcHDisplay <= 1024) { 102276888252Smrg /* BAD numbers: 0x14 */ 102376888252Smrg /* GOOD numbers: 0x12 */ 102476888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0012); 102576888252Smrg } else if (mode->CrtcHDisplay <= 1280) { 102676888252Smrg /* BAD numbers: 0x08 0x10 */ 102776888252Smrg /* Borderline numbers: 0x12 */ 102876888252Smrg /* GOOD numbers: 0x15 */ 102976888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015); 103076888252Smrg } else { 103176888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 103276888252Smrg } 103376888252Smrg } else if (24 == pScrn->bitsPerPixel) { 103476888252Smrg pCir->chip.lg->ModeReg.FORMAT = 0x2400; 103576888252Smrg 103676888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 103776888252Smrg | (lineData->width << 6); 103876888252Smrg pCir->chip.lg->ModeReg.CONTROL = 0x4000 | (lineData->width << 11); 103976888252Smrg 104076888252Smrg if (mode->CrtcHDisplay <= 640) { 104176888252Smrg /* BAD numbers: */ 104276888252Smrg /* GOOD numbers: 0x10 */ 104376888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010); 104476888252Smrg } else if (mode->CrtcHDisplay <= 800) { 104576888252Smrg /* BAD numbers: */ 104676888252Smrg /* GOOD numbers: 0x11 */ 104776888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011); 104876888252Smrg } else if (mode->CrtcHDisplay <= 1024) { 104976888252Smrg /* BAD numbers: 0x12 0x13 */ 105076888252Smrg /* Borderline numbers: 0x15 */ 105176888252Smrg /* GOOD numbers: 0x17 */ 105276888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 105376888252Smrg } else if (mode->CrtcHDisplay <= 1280) { 105476888252Smrg /* BAD numbers: */ 105576888252Smrg /* GOOD numbers: 0x1E */ 105676888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001E); 105776888252Smrg } else { 105876888252Smrg /* BAD numbers: */ 105976888252Smrg /* GOOD numbers: */ 106076888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0020); 106176888252Smrg } 106276888252Smrg } else if (32 == pScrn->bitsPerPixel) { 106376888252Smrg pCir->chip.lg->ModeReg.FORMAT = 0x3400; 106476888252Smrg 106576888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 106676888252Smrg | (lineData->width << 6); 106776888252Smrg pCir->chip.lg->ModeReg.CONTROL = 0x6000 | (lineData->width << 11); 106876888252Smrg 106976888252Smrg if (mode->CrtcHDisplay <= 640) { 107076888252Smrg /* GOOD numbers: 0x0E */ 107176888252Smrg /* BAD numbers: */ 107276888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x000E); 107376888252Smrg } else if (mode->CrtcHDisplay <= 800) { 107476888252Smrg /* GOOD numbers: 0x17 */ 107576888252Smrg /* BAD numbers: */ 107676888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 107776888252Smrg } else if (mode->CrtcHDisplay <= 1024) { 107876888252Smrg /* GOOD numbers: 0x1D */ 107976888252Smrg /* OKAY numbers: 0x15 0x14 0x16 0x18 0x19 */ 108076888252Smrg /* BAD numbers: 0x0E 0x12 0x13 0x0D */ 108176888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001D); 108276888252Smrg } else if (mode->CrtcHDisplay <= 1280) { 108376888252Smrg /* GOOD numbers: */ 108476888252Smrg /* BAD numbers: */ 108576888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0022); /* 10 */ 108676888252Smrg } else { 108776888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0024); 108876888252Smrg } 108976888252Smrg } else { 109076888252Smrg /* ??? What could it be? Use some sane numbers. */ 109176888252Smrg } 109276888252Smrg 109376888252Smrg /* Setup the appropriate memory interleaving */ 109476888252Smrg pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8); 109576888252Smrg pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0; 109676888252Smrg 109776888252Smrg if (PCI_CHIP_GD5465 == pCir->Chipset) { 109876888252Smrg /* The tile control information in the DTTC is also mirrored 109976888252Smrg elsewhere. */ 110076888252Smrg pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->ModeReg.DTTC & 0xFFC0; 110176888252Smrg 110276888252Smrg /* The 5465's DTTC records _fetches_ per line, not 110376888252Smrg tiles per line. Fetchs are 128-byte fetches. */ 110476888252Smrg if (pCir->chip.lg->ModeReg.DTTC & 0x0040) { 110576888252Smrg /* Using 256-byte wide tiles. Double the fetches 110676888252Smrg per line field. */ 110776888252Smrg pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xC0FF) 110876888252Smrg | ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1); 110976888252Smrg } 111076888252Smrg } 111176888252Smrg 111276888252Smrg /* Program the registers */ 111376888252Smrg vgaHWProtect(pScrn, TRUE); 111476888252Smrg hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg); 111576888252Smrg 111676888252Smrg clockData = LgSetClock(pCir, hwp, mode->SynthClock); 111776888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF; 111876888252Smrg pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF; 111976888252Smrg 112076888252Smrg /* Write those registers out to the card. */ 112176888252Smrg LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg); 112276888252Smrg 112376888252Smrg /* Programme the registers */ 112476888252Smrg vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP); 112576888252Smrg 112676888252Smrg vgaHWProtect(pScrn, FALSE); 112776888252Smrg 112876888252Smrg return TRUE; 112976888252Smrg} 113076888252Smrg 113176888252Smrgstatic int LgFindLineData(int displayWidth, int bpp) 113276888252Smrg{ 113376888252Smrg /* Find the smallest tile-line-pitch such that the total byte pitch 113476888252Smrg is greater than or equal to displayWidth*Bpp. */ 113576888252Smrg int i; 113676888252Smrg 113776888252Smrg /* Some pitch sizes are duplicates in the table. BUT, the invariant is 113876888252Smrg that the _first_ time a pitch occurs in the table is always _before_ 113976888252Smrg all other pitches greater than it. Said in another way... if all 114076888252Smrg duplicate entries from the table were removed, then the resulting pitch 114176888252Smrg values are strictly increasing. */ 114276888252Smrg 114376888252Smrg for (i = 0; LgLineData[i].pitch > 0; i++) 114476888252Smrg if (LgLineData[i].pitch >= displayWidth*bpp>>3) 114576888252Smrg return i; 114676888252Smrg 114776888252Smrg /* Um, uh oh! */ 114876888252Smrg return -1; 114976888252Smrg} 115076888252Smrg 115176888252Smrg 115276888252Smrg 115376888252Smrg 115476888252Smrgstatic void 115576888252SmrgLgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg) 115676888252Smrg{ 115776888252Smrg CirPtr pCir; 115876888252Smrg vgaHWPtr hwp; 115976888252Smrg CARD8 cr1D; 116076888252Smrg 116176888252Smrg pCir = CIRPTR(pScrn); 116276888252Smrg 116376888252Smrg /* First, VGAish registers. */ 116476888252Smrg hwp = VGAHWPTR(pScrn); 116576888252Smrg hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]); 116676888252Smrg hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]); 116776888252Smrg cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | (lgReg->ExtVga[CR1D] & 0x01); 116876888252Smrg hwp->writeCrtc(hwp, 0x1D, cr1D); 116976888252Smrg hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]); 117076888252Smrg 117176888252Smrg hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]); 117276888252Smrg hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]); 117376888252Smrg hwp->writeSeq(hwp, 0x12, lgReg->ExtVga[SR12]); 117476888252Smrg hwp->writeSeq(hwp, 0x13, lgReg->ExtVga[SR13]); 117576888252Smrg hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]); 117676888252Smrg memww(0xC0, lgReg->FORMAT); 117776888252Smrg 117876888252Smrg /* Vendor Specific Control is touchy. Only bit 28 is of concern. */ 117976888252Smrg memwl(0x3FC, ((memrl(0x3FC) & ~(1<<28)) | (lgReg->VSC & (1<<28)))); 118076888252Smrg 118176888252Smrg memww(0xEA, lgReg->DTTC); 118276888252Smrg 118376888252Smrg if (pCir->Chipset == PCI_CHIP_GD5465) { 118476888252Smrg memww(0x2C4, lgReg->TileCtrl); 118576888252Smrg } 118676888252Smrg 118776888252Smrg memwb(0x407, lgReg->TILE); 118876888252Smrg 118976888252Smrg if (pCir->Chipset == PCI_CHIP_GD5465) 119076888252Smrg memwb(0x2C0, lgReg->BCLK); 119176888252Smrg else 119276888252Smrg memwb(0x8C, lgReg->BCLK); 119376888252Smrg 119476888252Smrg memww(0x402, lgReg->CONTROL); 119576888252Smrg} 119676888252Smrg 119776888252Smrg/* 119876888252Smrg * Restore the initial (text) mode. 119976888252Smrg */ 120076888252Smrgstatic void 120176888252SmrgLgRestore(ScrnInfoPtr pScrn) 120276888252Smrg{ 120376888252Smrg vgaHWPtr hwp; 120476888252Smrg vgaRegPtr vgaReg; 120576888252Smrg CirPtr pCir; 120676888252Smrg LgRegPtr lgReg; 120776888252Smrg 120876888252Smrg#ifdef LG_DEBUG 120976888252Smrg ErrorF("LgRestore pScrn = %p\n", (void *)pScrn); 121076888252Smrg#endif 121176888252Smrg 121276888252Smrg pCir = CIRPTR(pScrn); 121376888252Smrg hwp = VGAHWPTR(pScrn); 121476888252Smrg vgaReg = &hwp->SavedReg; 121576888252Smrg lgReg = &pCir->chip.lg->SavedReg; 121676888252Smrg 121776888252Smrg vgaHWProtect(pScrn, TRUE); 121876888252Smrg 121976888252Smrg LgRestoreLgRegs(pScrn, lgReg); 122076888252Smrg 122176888252Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 122276888252Smrg vgaHWProtect(pScrn, FALSE); 122376888252Smrg} 122476888252Smrg 122576888252Smrg/* Mandatory */ 122676888252Smrg 122776888252Smrg/* This gets called at the start of each server generation */ 122876888252Smrg 122976888252SmrgBool 123076888252SmrgLgScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 123176888252Smrg{ 123276888252Smrg /* The vgaHW references will disappear one day */ 123376888252Smrg ScrnInfoPtr pScrn; 123476888252Smrg vgaHWPtr hwp; 123576888252Smrg CirPtr pCir; 123676888252Smrg int i, ret; 123776888252Smrg VisualPtr visual; 123876888252Smrg int displayWidth,width,height; 123976888252Smrg unsigned char * FbBase = NULL; 124076888252Smrg 124176888252Smrg#ifdef LG_DEBUG 124276888252Smrg ErrorF("LgScreenInit\n"); 124376888252Smrg#endif 124476888252Smrg 124576888252Smrg /* 124676888252Smrg * First get the ScrnInfoRec 124776888252Smrg */ 124876888252Smrg pScrn = xf86Screens[pScreen->myNum]; 124976888252Smrg 125076888252Smrg hwp = VGAHWPTR(pScrn); 125176888252Smrg 125276888252Smrg hwp->MapSize = 0x10000; /* Standard 64k VGA window */ 125376888252Smrg 125476888252Smrg pCir = CIRPTR(pScrn); 125576888252Smrg 125676888252Smrg /* Map the VGA memory and get the VGA IO base */ 125776888252Smrg if (!vgaHWMapMem(pScrn)) 125876888252Smrg return FALSE; 125976888252Smrg 126076888252Smrg /* Map the CIR memory and MMIO areas */ 126176888252Smrg if (!CirMapMem(pCir, pScrn->scrnIndex)) 126276888252Smrg return FALSE; 126376888252Smrg#ifdef EXPERIMENTAL 126476888252Smrg lg_vgaHWSetMmioFunc(hwp, pCir->IOBase); 126576888252Smrg#endif 126676888252Smrg vgaHWGetIOBase(hwp); 126776888252Smrg 126876888252Smrg /* Save the current state */ 126976888252Smrg LgSave(pScrn); 127076888252Smrg 127176888252Smrg /* Initialise the first mode */ 127276888252Smrg if (!LgModeInit(pScrn, pScrn->currentMode)) 127376888252Smrg return FALSE; 127476888252Smrg 127576888252Smrg /* Make things beautiful */ 127676888252Smrg LgSaveScreen(pScreen, SCREEN_SAVER_ON); 127776888252Smrg 127876888252Smrg /* Set the viewport */ 127976888252Smrg LgAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 128076888252Smrg 128176888252Smrg /* 128276888252Smrg * The next step is to setup the screen's visuals, and initialise the 128376888252Smrg * framebuffer code. In cases where the framebuffer's default 128476888252Smrg * choices for things like visual layouts and bits per RGB are OK, 128576888252Smrg * this may be as simple as calling the framebuffer's ScreenInit() 128676888252Smrg * function. If not, the visuals will need to be setup before calling 128776888252Smrg * a fb ScreenInit() function and fixed up after. 128876888252Smrg * 128976888252Smrg */ 129076888252Smrg 129176888252Smrg /* 129276888252Smrg * Reset the visual list. 129376888252Smrg */ 129476888252Smrg miClearVisualTypes(); 129576888252Smrg 129676888252Smrg /* Setup the visuals we support. */ 129776888252Smrg 129876888252Smrg if (!miSetVisualTypes(pScrn->depth, 129976888252Smrg miGetDefaultVisualMask(pScrn->depth), 130076888252Smrg pScrn->rgbBits, pScrn->defaultVisual)) 130176888252Smrg return FALSE; 130276888252Smrg 130376888252Smrg miSetPixmapDepths (); 130476888252Smrg 130576888252Smrg#ifdef LG_DEBUG 130676888252Smrg ErrorF("LgScreenInit after miSetVisualTypes\n"); 130776888252Smrg#endif 130876888252Smrg displayWidth = pScrn->displayWidth; 130976888252Smrg if (pCir->rotate) { 131076888252Smrg height = pScrn->virtualX; 131176888252Smrg width = pScrn->virtualY; 131276888252Smrg } else { 131376888252Smrg width = pScrn->virtualX; 131476888252Smrg height = pScrn->virtualY; 131576888252Smrg } 131676888252Smrg 131776888252Smrg if(pCir->shadowFB) { 131876888252Smrg pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 131976888252Smrg pCir->ShadowPtr = xalloc(pCir->ShadowPitch * height); 132076888252Smrg displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3); 132176888252Smrg FbBase = pCir->ShadowPtr; 132276888252Smrg } else { 132376888252Smrg pCir->ShadowPtr = NULL; 132476888252Smrg FbBase = pCir->FbBase; 132576888252Smrg } 132676888252Smrg 132776888252Smrg /* 132876888252Smrg * Call the framebuffer layer's ScreenInit function, and fill in other 132976888252Smrg * pScreen fields. 133076888252Smrg */ 133176888252Smrg switch (pScrn->bitsPerPixel) { 133276888252Smrg case 8: 133376888252Smrg case 16: 133476888252Smrg case 24: 133576888252Smrg case 32: 133676888252Smrg ret = fbScreenInit(pScreen, FbBase, 133776888252Smrg width,height, 133876888252Smrg pScrn->xDpi, pScrn->yDpi, 133976888252Smrg displayWidth,pScrn->bitsPerPixel); 134076888252Smrg break; 134176888252Smrg default: 134276888252Smrg xf86DrvMsg(scrnIndex, X_ERROR, 134376888252Smrg "X11: Internal error: invalid bpp (%d) in LgScreenInit\n", 134476888252Smrg pScrn->bitsPerPixel); 134576888252Smrg ret = FALSE; 134676888252Smrg break; 134776888252Smrg } 134876888252Smrg if (!ret) 134976888252Smrg return FALSE; 135076888252Smrg 135176888252Smrg#ifdef LG_DEBUG 135276888252Smrg ErrorF("LgScreenInit after depth dependent init\n"); 135376888252Smrg#endif 135476888252Smrg 135576888252Smrg /* Override the default mask/offset settings */ 135676888252Smrg if (pScrn->bitsPerPixel > 8) { 135776888252Smrg for (i = 0; i < pScreen->numVisuals; i++) { 135876888252Smrg visual = &pScreen->visuals[i]; 135976888252Smrg if ((visual->class | DynamicClass) == DirectColor) { 136076888252Smrg visual->offsetRed = pScrn->offset.red; 136176888252Smrg visual->offsetGreen = pScrn->offset.green; 136276888252Smrg visual->offsetBlue = pScrn->offset.blue; 136376888252Smrg visual->redMask = pScrn->mask.red; 136476888252Smrg visual->greenMask = pScrn->mask.green; 136576888252Smrg visual->blueMask = pScrn->mask.blue; 136676888252Smrg } 136776888252Smrg } 136876888252Smrg } 136976888252Smrg 137076888252Smrg /* must be after RGB ordering fixed */ 137176888252Smrg 137276888252Smrg fbPictureInit(pScreen, 0, 0); 137376888252Smrg 137476888252Smrg miInitializeBackingStore(pScreen); 137576888252Smrg 137676888252Smrg /* 137776888252Smrg * Set initial black & white colourmap indices. 137876888252Smrg */ 137976888252Smrg xf86SetBlackWhitePixels(pScreen); 138076888252Smrg 138176888252Smrg if (!pCir->NoAccel) { /* Initialize XAA functions */ 138276888252Smrg if (!LgXAAInit(pScreen)) 138376888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialize XAA\n"); 138476888252Smrg } 138576888252Smrg#if 1 138676888252Smrg pCir->DGAModeInit = LgModeInit; 138776888252Smrg if (!CirDGAInit(pScreen)) 138876888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 138976888252Smrg "DGA initialization failed\n"); 139076888252Smrg#endif 139176888252Smrg xf86SetSilkenMouse(pScreen); 139276888252Smrg 139376888252Smrg /* Initialise cursor functions */ 139476888252Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 139576888252Smrg 139676888252Smrg if (pCir->HWCursor) { /* Initialize HW cursor layer */ 139776888252Smrg if (!LgHWCursorInit(pScreen)) 139876888252Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 139976888252Smrg "Hardware cursor initialization failed\n"); 140076888252Smrg } 140176888252Smrg 140276888252Smrg /* Initialise default colourmap */ 140376888252Smrg if (!miCreateDefColormap(pScreen)) 140476888252Smrg return FALSE; 140576888252Smrg 140676888252Smrg if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8) 140776888252Smrg vgaHWHandleColormaps(pScreen); 140876888252Smrg 140976888252Smrg xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 0); 141076888252Smrg 141176888252Smrg pScrn->memPhysBase = pCir->FbAddress; 141276888252Smrg pScrn->fbOffset = 0; 141376888252Smrg 141476888252Smrg { 141576888252Smrg XF86VideoAdaptorPtr *ptr; 141676888252Smrg int n; 141776888252Smrg 141876888252Smrg n = xf86XVListGenericAdaptors(pScrn,&ptr); 141976888252Smrg if (n) 142076888252Smrg xf86XVScreenInit(pScreen, ptr, n); 142176888252Smrg } 142276888252Smrg 142376888252Smrg /* 142476888252Smrg * Wrap the CloseScreen vector and set SaveScreen. 142576888252Smrg */ 142676888252Smrg pScreen->SaveScreen = LgSaveScreen; 142776888252Smrg pCir->CloseScreen = pScreen->CloseScreen; 142876888252Smrg pScreen->CloseScreen = LgCloseScreen; 142976888252Smrg 143076888252Smrg /* Report any unused options (only for the first generation) */ 143176888252Smrg if (serverGeneration == 1) 143276888252Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 143376888252Smrg 143476888252Smrg /* Done */ 143576888252Smrg return TRUE; 143676888252Smrg} 143776888252Smrg 143876888252Smrg 143976888252Smrg/* Usually mandatory */ 144076888252SmrgBool 144176888252SmrgLgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 144276888252Smrg{ 144376888252Smrg return LgModeInit(xf86Screens[scrnIndex], mode); 144476888252Smrg} 144576888252Smrg 144676888252Smrg#define ROUND_DOWN(x, mod) (((x) / (mod)) * (mod)) 144776888252Smrg#define ROUND_UP(x, mod) ((((x) + (mod) - 1) / (mod)) * (mod)) 144876888252Smrg 144976888252Smrg/* 145076888252Smrg * This function is used to initialize the Start Address - the first 145176888252Smrg * displayed location in the video memory. 145276888252Smrg */ 145376888252Smrg/* Usually mandatory */ 145476888252Smrgvoid 145576888252SmrgLgAdjustFrame(int scrnIndex, int x, int y, int flags) 145676888252Smrg{ 145776888252Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 145876888252Smrg int Base, tmp; 145976888252Smrg CirPtr pCir = CIRPTR(pScrn); 146076888252Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 146176888252Smrg int cursorX, cursorY; 146276888252Smrg int middleX, middleY; 146376888252Smrg const LgLineDataPtr lineData = &LgLineData[pCir->chip.lg->lineDataIndex]; 146476888252Smrg const int viewportXRes = 146576888252Smrg (PCI_CHIP_GD5465 == pCir->Chipset) ? (24==pScrn->bitsPerPixel?24:1) : 146676888252Smrg (lineData->width?256:128) / 146776888252Smrg (24==pScrn->bitsPerPixel?1:(pScrn->bitsPerPixel>>3)); 146876888252Smrg const int viewportYRes = 146976888252Smrg (PCI_CHIP_GD5465 == pCir->Chipset) ? 1 : (24==pScrn->bitsPerPixel?3:1); 147076888252Smrg 147176888252Smrg /* Where's the pointer? */ 14721ae1b5e8Smrg miPointerGetPosition(inputInfo.pointer, &cursorX, &cursorY); 147376888252Smrg 147476888252Smrg /* Where's the middle of the screen? We want to eventually know 147576888252Smrg which side of the screen the pointer is on. */ 147676888252Smrg middleX = (pScrn->frameX1 + pScrn->frameX0) / 2; 147776888252Smrg middleY = (pScrn->frameY1 + pScrn->frameY0) / 2; 147876888252Smrg 147976888252Smrg if (cursorX < middleX) { 148076888252Smrg /* Pointer is on left side of screen. Round the frame value down. */ 148176888252Smrg pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes); 148276888252Smrg } else { 148376888252Smrg /* Pointer is on right side of screen. Round the frame value 148476888252Smrg up. A side effect of this rounding up is that we might expose 148576888252Smrg a part of the screen that's actually on the far /left/ of the 148676888252Smrg frame buffer. That's because, although the virtual desktop might 148776888252Smrg be an integral number of tiles, the display might not. We'll 148876888252Smrg just live with this artifact. */ 148976888252Smrg pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes); 149076888252Smrg } 149176888252Smrg pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; 149276888252Smrg 149376888252Smrg if (cursorY < middleY) { 149476888252Smrg pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes); 149576888252Smrg } else { 149676888252Smrg pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes); 149776888252Smrg } 149876888252Smrg pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; 149976888252Smrg 150076888252Smrg 150176888252Smrg if (x != pScrn->frameX0 || y != pScrn->frameY0) { 150276888252Smrg /* !!! */ 150376888252Smrg /* We moved the frame from where xf86SetViewport() placed it. 150476888252Smrg If we're using a SW cursor, that's okay -- the pointer exists in 150576888252Smrg the framebuffer, and those bits are still all aligned. But 150676888252Smrg if we're using a HW cursor, then we need to re-align the pointer. 150776888252Smrg Call SetCursorPosition() with the appropriate new pointer 150876888252Smrg values, adjusted to be wrt the new frame. */ 150976888252Smrg 151076888252Smrg x = pScrn->frameX0; 151176888252Smrg y = pScrn->frameY0; 151276888252Smrg } 151376888252Smrg 151476888252Smrg /* ??? Will this work for 1bpp? */ 151576888252Smrg Base = (y * lineData->pitch + (x*pScrn->bitsPerPixel/8)) / 4; 151676888252Smrg 151776888252Smrg if ((Base & ~0x000FFFFF) != 0) { 151876888252Smrg /* ??? */ 151976888252Smrg ErrorF("X11: Internal error: LgAdjustFrame: cannot handle overflow\n"); 152076888252Smrg return; 152176888252Smrg } 152276888252Smrg 152376888252Smrg hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF); 152476888252Smrg hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); 152576888252Smrg tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2; 152676888252Smrg tmp |= (Base >> 16) & 0x01; 152776888252Smrg tmp |= (Base >> 15) & 0x0C; 152876888252Smrg hwp->writeCrtc(hwp, 0x1B, tmp); 152976888252Smrg tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7; 153076888252Smrg tmp |= (Base >> 16) & 0x18; 153176888252Smrg hwp->writeCrtc(hwp, 0x1D, tmp); 153276888252Smrg} 153376888252Smrg 153476888252Smrg/* 153576888252Smrg * This is called when VT switching back to the X server. Its job is 153676888252Smrg * to reinitialise the video mode. 153776888252Smrg * 153876888252Smrg * We may wish to unmap video/MMIO memory too. 153976888252Smrg */ 154076888252Smrg 154176888252Smrg/* Mandatory */ 154276888252SmrgBool 154376888252SmrgLgEnterVT(int scrnIndex, int flags) 154476888252Smrg{ 154576888252Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 154676888252Smrg CirPtr pCir = CIRPTR(pScrn); 154776888252Smrg#ifdef LG_DEBUG 154876888252Smrg ErrorF("LgEnterVT\n"); 154976888252Smrg#endif 155076888252Smrg 155176888252Smrg /* XXX Shouldn't this be in LeaveVT? */ 155276888252Smrg /* Disable HW cursor */ 155376888252Smrg if (pCir->HWCursor) 155476888252Smrg LgHideCursor(pScrn); 155576888252Smrg 155676888252Smrg /* Should we re-save the text mode on each VT enter? */ 155776888252Smrg return LgModeInit(pScrn, pScrn->currentMode); 155876888252Smrg} 155976888252Smrg 156076888252Smrg 156176888252Smrg/* 156276888252Smrg * This is called when VT switching away from the X server. Its job is 156376888252Smrg * to restore the previous (text) mode. 156476888252Smrg * 156576888252Smrg * We may wish to remap video/MMIO memory too. 156676888252Smrg */ 156776888252Smrg 156876888252Smrg/* Mandatory */ 156976888252Smrgvoid 157076888252SmrgLgLeaveVT(int scrnIndex, int flags) 157176888252Smrg{ 157276888252Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 157376888252Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 157476888252Smrg CirPtr pCir = CIRPTR(pScrn); 157576888252Smrg#ifdef LG_DEBUG 157676888252Smrg ErrorF("LgLeaveVT\n"); 157776888252Smrg#endif 157876888252Smrg 157976888252Smrg /* XXX Shouldn't this be in EnterVT? */ 158076888252Smrg /* Enable HW cursor */ 158176888252Smrg if (pCir->HWCursor) 158276888252Smrg LgShowCursor(pScrn); 158376888252Smrg 158476888252Smrg LgRestore(pScrn); 158576888252Smrg vgaHWLock(hwp); 158676888252Smrg} 158776888252Smrg 158876888252Smrg 158976888252Smrg/* 159076888252Smrg * This is called at the end of each server generation. It restores the 159176888252Smrg * original (text) mode. It should also unmap the video memory, and free 159276888252Smrg * any per-generation data allocated by the driver. It should finish 159376888252Smrg * by unwrapping and calling the saved CloseScreen function. 159476888252Smrg */ 159576888252Smrg 159676888252Smrg/* Mandatory */ 159776888252Smrgstatic Bool 159876888252SmrgLgCloseScreen(int scrnIndex, ScreenPtr pScreen) 159976888252Smrg{ 160076888252Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 160176888252Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 160276888252Smrg CirPtr pCir = CIRPTR(pScrn); 160376888252Smrg 160476888252Smrg if(pScrn->vtSema) { 160576888252Smrg LgRestore(pScrn); 160676888252Smrg if (pCir->HWCursor) 160776888252Smrg LgHideCursor(pScrn); 160876888252Smrg 160976888252Smrg vgaHWLock(hwp); 161076888252Smrg 161176888252Smrg CirUnmapMem(pCir, pScrn->scrnIndex); 161276888252Smrg } 161376888252Smrg 161476888252Smrg if (pCir->AccelInfoRec) 161576888252Smrg XAADestroyInfoRec(pCir->AccelInfoRec); 161676888252Smrg pCir->AccelInfoRec = NULL; 161776888252Smrg 161876888252Smrg if (pCir->CursorInfoRec) 161976888252Smrg xf86DestroyCursorInfoRec(pCir->CursorInfoRec); 162076888252Smrg pCir->CursorInfoRec = NULL; 162176888252Smrg if (pCir->DGAModes) 162276888252Smrg xfree(pCir->DGAModes); 162376888252Smrg pCir->DGAnumModes = 0; 162476888252Smrg pCir->DGAModes = NULL; 162576888252Smrg 162676888252Smrg pScrn->vtSema = FALSE; 162776888252Smrg 162876888252Smrg pScreen->CloseScreen = pCir->CloseScreen; 162976888252Smrg return (*pScreen->CloseScreen)(scrnIndex, pScreen); 163076888252Smrg} 163176888252Smrg 163276888252Smrg 163376888252Smrg/* Free up any persistent data structures */ 163476888252Smrg 163576888252Smrg/* Optional */ 163676888252Smrgvoid 163776888252SmrgLgFreeScreen(int scrnIndex, int flags) 163876888252Smrg{ 163976888252Smrg#ifdef LG_DEBUG 164076888252Smrg ErrorF("LgFreeScreen\n"); 164176888252Smrg#endif 164276888252Smrg /* 164376888252Smrg * This only gets called when a screen is being deleted. It does not 164476888252Smrg * get called routinely at the end of a server generation. 164576888252Smrg */ 164676888252Smrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 164776888252Smrg vgaHWFreeHWRec(xf86Screens[scrnIndex]); 164876888252Smrg LgFreeRec(xf86Screens[scrnIndex]); 164976888252Smrg} 165076888252Smrg 165176888252Smrg 165276888252Smrg/* Checks if a mode is suitable for the selected chipset. */ 165376888252Smrg 165476888252Smrg/* Optional */ 165576888252SmrgModeStatus 165676888252SmrgLgValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 165776888252Smrg{ 165876888252Smrg int lace; 165976888252Smrg 166076888252Smrg lace = 1 + ((mode->Flags & V_INTERLACE) != 0); 166176888252Smrg 166276888252Smrg if ((mode->CrtcHDisplay <= 2048) && 166376888252Smrg (mode->CrtcHSyncStart <= 4096) && 166476888252Smrg (mode->CrtcHSyncEnd <= 4096) && 166576888252Smrg (mode->CrtcHTotal <= 4096) && 166676888252Smrg (mode->CrtcVDisplay <= 2048 * lace) && 166776888252Smrg (mode->CrtcVSyncStart <= 4096 * lace) && 166876888252Smrg (mode->CrtcVSyncEnd <= 4096 * lace) && 166976888252Smrg (mode->CrtcVTotal <= 4096 * lace)) { 167076888252Smrg return(MODE_OK); 167176888252Smrg } 167276888252Smrg return(MODE_BAD); 167376888252Smrg} 167476888252Smrg 167576888252Smrg 167676888252Smrg/* Do screen blanking */ 167776888252Smrg 167876888252Smrg/* Mandatory */ 167976888252Smrgstatic Bool 168076888252SmrgLgSaveScreen(ScreenPtr pScreen, int mode) 168176888252Smrg{ 168276888252Smrg CirPtr pCir = CIRPTR(xf86Screens[pScreen->myNum]); 168376888252Smrg ScrnInfoPtr pScrn = NULL; 168476888252Smrg Bool unblank; 168576888252Smrg 168676888252Smrg unblank = xf86IsUnblank(mode); 168776888252Smrg 168876888252Smrg if (pScreen != NULL) 168976888252Smrg pScrn = xf86Screens[pScreen->myNum]; 169076888252Smrg 169176888252Smrg if (pScrn != NULL && pScrn->vtSema) { 169276888252Smrg if (unblank) 169376888252Smrg /* Power up the palette DAC */ 169476888252Smrg memwb(0xB0,memrb(0xB0) & 0x7F); 169576888252Smrg else 169676888252Smrg /* Power down the palette DAC */ 169776888252Smrg memwb(0xB0,memrb(0xB0) | 0x80); 169876888252Smrg } 169976888252Smrg 170076888252Smrg return vgaHWSaveScreen(pScreen, mode); 170176888252Smrg} 170276888252Smrg 170376888252Smrgstatic CARD16 170476888252SmrgLgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq) 170576888252Smrg{ 170676888252Smrg int ffreq, num, den; 170776888252Smrg CARD8 tmp; 170876888252Smrg 170976888252Smrg ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000); 171076888252Smrg 171176888252Smrg ffreq = freq; 171276888252Smrg if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den)) 171376888252Smrg return 0; 171476888252Smrg 171576888252Smrg ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n", 171676888252Smrg num, den, ffreq / 1000, ffreq % 1000); 171776888252Smrg 171876888252Smrg /* Set VCLK3. */ 171976888252Smrg /* The numerator and denominator registers are switched 172076888252Smrg around in the Laguna chips. */ 172176888252Smrg tmp = hwp->readSeq(hwp, 0x0E); 172276888252Smrg hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den); 172376888252Smrg hwp->writeSeq(hwp, 0x1E, num); 172476888252Smrg 172576888252Smrg return (den << 8) | num; 172676888252Smrg} 172776888252Smrg 172876888252Smrg/* 172976888252Smrg * CIRDisplayPowerManagementSet -- 173076888252Smrg * 173176888252Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode. 173276888252Smrg */ 173376888252Smrgstatic void 173476888252SmrgLgDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 173576888252Smrg int flags) 173676888252Smrg{ 173776888252Smrg unsigned char sr01, cr1a; 173876888252Smrg vgaHWPtr hwp; 173976888252Smrg 174076888252Smrg#ifdef LG_DEBUG 174176888252Smrg ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode); 174276888252Smrg#endif 174376888252Smrg 174476888252Smrg hwp = VGAHWPTR(pScrn); 174576888252Smrg 174676888252Smrg switch (PowerManagementMode) { 174776888252Smrg case DPMSModeOn: 174876888252Smrg /* Screen: On; HSync: On, VSync: On */ 174976888252Smrg sr01 = 0x00; 175076888252Smrg cr1a = 0x00; 175176888252Smrg break; 175276888252Smrg case DPMSModeStandby: 175376888252Smrg /* Screen: Off; HSync: Off, VSync: On */ 175476888252Smrg sr01 = 0x20; 175576888252Smrg cr1a = 0x08; 175676888252Smrg break; 175776888252Smrg case DPMSModeSuspend: 175876888252Smrg /* Screen: Off; HSync: On, VSync: Off */ 175976888252Smrg sr01 = 0x20; 176076888252Smrg cr1a = 0x04; 176176888252Smrg break; 176276888252Smrg case DPMSModeOff: 176376888252Smrg /* Screen: Off; HSync: Off, VSync: Off */ 176476888252Smrg sr01 = 0x20; 176576888252Smrg cr1a = 0x0c; 176676888252Smrg break; 176776888252Smrg default: 176876888252Smrg return; 176976888252Smrg } 177076888252Smrg 177176888252Smrg sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 177276888252Smrg hwp->writeSeq(hwp, 0x01, sr01); 177376888252Smrg cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C; 177476888252Smrg hwp->writeCrtc(hwp, 0x1A, cr1a); 177576888252Smrg} 177676888252Smrg 177776888252Smrg#define minb(p) MMIO_IN8(hwp->MMIOBase, (p)) 177876888252Smrg#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v)) 177976888252Smrg 178076888252Smrgstatic void 178176888252SmrgmmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) 178276888252Smrg{ 178376888252Smrg moutb(index << 2, value); 178476888252Smrg} 178576888252Smrg 178676888252Smrgstatic CARD8 178776888252SmrgmmioReadCrtc(vgaHWPtr hwp, CARD8 index) 178876888252Smrg{ 178976888252Smrg return minb(index << 2); 179076888252Smrg} 179176888252Smrg 179276888252Smrgstatic void 179376888252Smrglg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base) 179476888252Smrg{ 179576888252Smrg hwp->writeCrtc = mmioWriteCrtc; 179676888252Smrg hwp->readCrtc = mmioReadCrtc; 179776888252Smrg hwp->MMIOBase = base; 179876888252Smrg hwp->MMIOOffset = 0; 179976888252Smrg} 1800