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