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