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