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: 12d2b10af6Smrg * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel, 13d2b10af6Smrg * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff, 14d2b10af6Smrg * Guy DESBIEF, Itai Nahshon. 1576888252Smrg */ 1676888252Smrg 1776888252Smrg#ifdef HAVE_CONFIG_H 1876888252Smrg#include "config.h" 1976888252Smrg#endif 2076888252Smrg 2176888252Smrg#define EXPERIMENTAL 2276888252Smrg 23d2b10af6Smrg/* 24d2b10af6Smrg * All drivers should typically include these. 25d2b10af6Smrg */ 2676888252Smrg#include "xf86.h" 2776888252Smrg#include "xf86_OSproc.h" 2876888252Smrg 29d2b10af6Smrg/* 30d2b10af6Smrg * All drivers need this. 31d2b10af6Smrg */ 3276888252Smrg 3376888252Smrg#include "compiler.h" 3476888252Smrg 35d2b10af6Smrg/* 36d2b10af6Smrg * Drivers that need to access the PCI config space directly need 37d2b10af6Smrg * this. 38d2b10af6Smrg */ 3976888252Smrg#include "xf86Pci.h" 4076888252Smrg 41d2b10af6Smrg/* 42d2b10af6Smrg * All drivers using the vgahw module need this. This driver needs 43d2b10af6Smrg * to be modified to not use vgaHW for multihead operation. 44d2b10af6Smrg */ 4576888252Smrg#include "vgaHW.h" 4676888252Smrg 471e66b2a2Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 4876888252Smrg#include "xf86RAC.h" 4976888252Smrg#include "xf86Resources.h" 501e66b2a2Smrg#endif 5176888252Smrg 52d2b10af6Smrg/* 53d2b10af6Smrg * All drivers initialising the SW cursor need this. 54d2b10af6Smrg */ 5576888252Smrg#include "mipointer.h" 5676888252Smrg 57d2b10af6Smrg/* 58d2b10af6Smrg * Need this for inputInfo. 59d2b10af6Smrg */ 60afee0becSmrg#include "inputstr.h" 61afee0becSmrg 6276888252Smrg#include "micmap.h" 6376888252Smrg 64d2b10af6Smrg/* 65d2b10af6Smrg * Needed by the shadowfb. 66d2b10af6Smrg */ 6776888252Smrg#include "shadowfb.h" 6876888252Smrg 6976888252Smrg#include "xf86int10.h" 7076888252Smrg 7176888252Smrg#include "fb.h" 7276888252Smrg 7376888252Smrg#include "xf86DDC.h" 7476888252Smrg 7576888252Smrg#undef LG_DEBUG 7676888252Smrg 7776888252Smrg#include "cir.h" 7876888252Smrg#define _LG_PRIVATE_ 7976888252Smrg#include "lg.h" 8076888252Smrg 8176888252Smrg#include "xf86xv.h" 8276888252Smrg#include <X11/extensions/Xv.h> 8376888252Smrg 8476888252Smrg/* 8576888252Smrg * Forward definitions for the functions that make up the driver. 8676888252Smrg */ 8776888252Smrg 88d2b10af6Smrg/* 89d2b10af6Smrg * Mandatory functions 90d2b10af6Smrg */ 9176888252SmrgBool LgPreInit(ScrnInfoPtr pScrn, int flags); 925c69f917SmrgBool LgScreenInit(SCREEN_INIT_ARGS_DECL); 935c69f917SmrgBool LgEnterVT(VT_FUNC_ARGS_DECL); 945c69f917Smrgvoid LgLeaveVT(VT_FUNC_ARGS_DECL); 95d2b10af6Smrgstatic Bool LgCloseScreen(CLOSE_SCREEN_ARGS_DECL); 96d2b10af6Smrgstatic Bool LgSaveScreen(ScreenPtr pScreen, Bool mode); 9776888252Smrg 98d2b10af6Smrg/* 99d2b10af6Smrg * Required if the driver supports mode switching. 100d2b10af6Smrg */ 1015c69f917SmrgBool LgSwitchMode(SWITCH_MODE_ARGS_DECL); 102d2b10af6Smrg/* 103d2b10af6Smrg * Required if the driver supports moving the viewport. 104d2b10af6Smrg */ 1055c69f917Smrgvoid LgAdjustFrame(ADJUST_FRAME_ARGS_DECL); 10676888252Smrg 107d2b10af6Smrg/* 108d2b10af6Smrg * Optional functions 109d2b10af6Smrg */ 1105c69f917Smrgvoid LgFreeScreen(FREE_SCREEN_ARGS_DECL); 1115c69f917SmrgModeStatus LgValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 112d2b10af6Smrg Bool verbose, int flags); 11376888252Smrg 114d2b10af6Smrg/* 115d2b10af6Smrg * Internal functions 116d2b10af6Smrg */ 11776888252Smrgstatic void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg); 11876888252Smrgstatic int LgFindLineData(int displayWidth, int bpp); 11976888252Smrgstatic CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq); 12076888252Smrgstatic void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base); 12176888252Smrg 12276888252Smrgstatic void LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, 123d2b10af6Smrg int PowerManagementMode, 124d2b10af6Smrg int flags); 12576888252Smrg 12676888252Smrg/* 12776888252Smrg * This is intentionally screen-independent. It indicates the binding 12876888252Smrg * choice made in the first PreInit. 12976888252Smrg */ 13076888252Smrgstatic int pix24bpp = 0; 13176888252Smrg 13276888252Smrg/* 13376888252Smrg * This contains the functions needed by the server after loading the 134d2b10af6Smrg * driver module. It must be supplied, and gets added the driver list 135d2b10af6Smrg * by the Module Setup function in the dynamic case. In the static 136d2b10af6Smrg * case a reference to this is compiled in, and this requires that the 137d2b10af6Smrg * name of this DriverRec be an upper-case version of the driver name. 13876888252Smrg */ 13976888252Smrg 14076888252Smrgtypedef enum { 141d2b10af6Smrg OPTION_HW_CURSOR, 142d2b10af6Smrg OPTION_PCI_RETRY, 143d2b10af6Smrg OPTION_ROTATE, 144d2b10af6Smrg OPTION_SHADOW_FB, 145d2b10af6Smrg OPTION_NOACCEL 14676888252Smrg} LgOpts; 14776888252Smrg 14876888252Smrgstatic const OptionInfoRec LgOptions[] = { 149d2b10af6Smrg { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 150d2b10af6Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 151d2b10af6Smrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 152d2b10af6Smrg { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 153d2b10af6Smrg/* 154d2b10af6Smrg * fifo_conservative/aggressive; fast/med/slow_dram; ... 155d2b10af6Smrg */ 156d2b10af6Smrg { -1, NULL, OPTV_NONE, {0}, FALSE } 15776888252Smrg}; 15876888252Smrg 159d2b10af6Smrg/* 160d2b10af6Smrg * 1/4 bpp 8 bpp 15/16 bpp 24 bpp 32 bpp 161d2b10af6Smrg */ 162d2b10af6Smrgstatic int gd5462_MaxClocks[] = 163d2b10af6Smrg { 170000, 170000, 135100, 135100, 85500 }; 164d2b10af6Smrgstatic int gd5464_MaxClocks[] = 165d2b10af6Smrg { 170000, 250000, 170000, 170000, 135100 }; 166d2b10af6Smrgstatic int gd5465_MaxClocks[] = 167d2b10af6Smrg { 170000, 250000, 170000, 170000, 135100 }; 16876888252Smrg 169d2b10af6Smrg/* 170d2b10af6Smrg * We're rather use skinny tiles, so put all of them at the head of 171d2b10af6Smrg * the table. 172d2b10af6Smrg */ 17376888252SmrgLgLineDataRec LgLineData[] = { 174d2b10af6Smrg { 5, 640, 0}, 175d2b10af6Smrg { 8, 1024, 0}, 176d2b10af6Smrg {10, 1280, 0}, 177d2b10af6Smrg {13, 1664, 0}, 178d2b10af6Smrg {16, 2048, 0}, 179d2b10af6Smrg {20, 2560, 0}, 180d2b10af6Smrg {10, 2560, 1}, 181d2b10af6Smrg {26, 3328, 0}, 182d2b10af6Smrg { 5, 1280, 1}, 183d2b10af6Smrg { 8, 2048, 1}, 184d2b10af6Smrg {13, 3328, 1}, 185d2b10af6Smrg {16, 4096, 1}, 186d2b10af6Smrg {20, 5120, 1}, 187d2b10af6Smrg {26, 6656, 1}, 188d2b10af6Smrg/* 189d2b10af6Smrg * Sentinel to indicate end of table. 190d2b10af6Smrg */ 191d2b10af6Smrg {-1, -1, -1} 19276888252Smrg}; 19376888252Smrg 19476888252Smrgstatic int LgLinePitches[4][11] = { 195d2b10af6Smrg/* 196d2b10af6Smrg * 8 bpp 197d2b10af6Smrg */ 198d2b10af6Smrg { 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 }, 199d2b10af6Smrg/* 200d2b10af6Smrg * 16 bpp 201d2b10af6Smrg */ 202d2b10af6Smrg { 320, 512, 640, 832, 1024, 1280, 1664, 2048, 2560, 3328, 0 }, 203d2b10af6Smrg/* 204d2b10af6Smrg * 24 bpp 205d2b10af6Smrg */ 206d2b10af6Smrg { 213, 341, 426, 554, 682, 853, 1109, 1365, 1706, 2218, 0 }, 207d2b10af6Smrg/* 208d2b10af6Smrg * 32 bpp 209d2b10af6Smrg */ 210d2b10af6Smrg { 160, 256, 320, 416, 512, 640, 832, 1024, 1280, 1664, 0 } 21176888252Smrg}; 21276888252Smrg 21376888252Smrg#ifdef XFree86LOADER 21476888252Smrg 21576888252Smrg#define LG_MAJOR_VERSION 1 21676888252Smrg#define LG_MINOR_VERSION 0 21776888252Smrg#define LG_PATCHLEVEL 0 21876888252Smrg 21976888252Smrgstatic XF86ModuleVersionInfo lgVersRec = 22076888252Smrg{ 221d2b10af6Smrg "cirrus_laguna", 222d2b10af6Smrg MODULEVENDORSTRING, 223d2b10af6Smrg MODINFOSTRING1, 224d2b10af6Smrg MODINFOSTRING2, 225d2b10af6Smrg XORG_VERSION_CURRENT, 226d2b10af6Smrg LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_PATCHLEVEL, 227d2b10af6Smrg/* 228d2b10af6Smrg * This is a video driver. 229d2b10af6Smrg */ 230d2b10af6Smrg ABI_CLASS_VIDEODRV, 231d2b10af6Smrg ABI_VIDEODRV_VERSION, 232d2b10af6Smrg MOD_CLASS_NONE, 233d2b10af6Smrg {0,0,0,0} 23476888252Smrg}; 23576888252Smrg 23676888252Smrg/* 23776888252Smrg * This is the module init data. 23876888252Smrg * Its name has to be the driver name followed by ModuleData. 23976888252Smrg */ 24076888252Smrg_X_EXPORT XF86ModuleData cirrus_lagunaModuleData = { 24176888252Smrg &lgVersRec, 242d2b10af6Smrg NULL, 24376888252Smrg NULL 24476888252Smrg}; 24576888252Smrg 24676888252Smrg#endif /* XFree86LOADER */ 24776888252Smrg 24876888252Smrg_X_EXPORT const OptionInfoRec * 249d2b10af6SmrgLgAvailableOptions(int chipid) { 25076888252Smrg return LgOptions; 25176888252Smrg} 25276888252Smrg 25376888252Smrg_X_EXPORT ScrnInfoPtr 25476888252SmrgLgProbe(int entity) 25576888252Smrg{ 25676888252Smrg ScrnInfoPtr pScrn = NULL; 257d2b10af6Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, 258d2b10af6Smrg CIRPciChipsets, 259d2b10af6Smrg NULL, NULL, NULL, 260d2b10af6Smrg NULL, NULL))) { 261d2b10af6Smrg pScrn->PreInit = LgPreInit; 262d2b10af6Smrg pScrn->ScreenInit = LgScreenInit; 263d2b10af6Smrg pScrn->SwitchMode = LgSwitchMode; 264d2b10af6Smrg pScrn->AdjustFrame = LgAdjustFrame; 265d2b10af6Smrg pScrn->EnterVT = LgEnterVT; 266d2b10af6Smrg pScrn->LeaveVT = LgLeaveVT; 267d2b10af6Smrg pScrn->FreeScreen = LgFreeScreen; 268d2b10af6Smrg pScrn->ValidMode = LgValidMode; 26976888252Smrg } 27076888252Smrg return pScrn; 27176888252Smrg} 27276888252Smrg 27376888252Smrgstatic Bool 27476888252SmrgLgGetRec(ScrnInfoPtr pScrn) 27576888252Smrg{ 276d2b10af6Smrg CirPtr pCir; 27776888252Smrg 278d2b10af6Smrg if (pScrn->driverPrivate != NULL) 279d2b10af6Smrg return TRUE; 28076888252Smrg 281d2b10af6Smrg pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1); 282d2b10af6Smrg ((CirPtr) pScrn->driverPrivate)->chip.lg = 283d2b10af6Smrg xnfcalloc(sizeof(LgRec), 1); 28476888252Smrg 285d2b10af6Smrg /* 286d2b10af6Smrg * Initialize it. 287d2b10af6Smrg */ 288d2b10af6Smrg pCir = CIRPTR(pScrn); 289d2b10af6Smrg pCir->chip.lg->oldBitmask = 0x00000000; 29076888252Smrg 291d2b10af6Smrg return TRUE; 29276888252Smrg} 29376888252Smrg 29476888252Smrgstatic void 29576888252SmrgLgFreeRec(ScrnInfoPtr pScrn) 29676888252Smrg{ 297d2b10af6Smrg if (pScrn->driverPrivate == NULL) 298d2b10af6Smrg return; 299d2b10af6Smrg free(pScrn->driverPrivate); 300d2b10af6Smrg pScrn->driverPrivate = NULL; 30176888252Smrg} 30276888252Smrg 30376888252Smrg/* 30476888252Smrg * LgCountRAM -- 30576888252Smrg * 30676888252Smrg * Counts amount of installed RAM 30776888252Smrg */ 308d2b10af6Smrg/* 309d2b10af6Smrg * XXX We need to get rid of this PIO (MArk) 310d2b10af6Smrg */ 31176888252Smrgstatic int 31276888252SmrgLgCountRam(ScrnInfoPtr pScrn) 31376888252Smrg{ 314d2b10af6Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 315d2b10af6Smrg CARD8 SR14; 31676888252Smrg 317d2b10af6Smrg vgaHWProtect(pScrn, TRUE); 31876888252Smrg 319d2b10af6Smrg /* 320d2b10af6Smrg * The ROM BIOS scratch pad registers contain, among other things, 321d2b10af6Smrg * the amount of installed RDRAM for the Laguna chip. 322d2b10af6Smrg */ 323d2b10af6Smrg SR14 = hwp->readSeq(hwp, 0x14); 32476888252Smrg 325d2b10af6Smrg ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n", 326d2b10af6Smrg hwp->readSeq(hwp, 9), 327d2b10af6Smrg hwp->readSeq(hwp, 10), 328d2b10af6Smrg SR14, 329d2b10af6Smrg hwp->readSeq(hwp, 0x15)); 33076888252Smrg 331d2b10af6Smrg vgaHWProtect(pScrn, FALSE); 33276888252Smrg 333d2b10af6Smrg return 1024 * ((SR14 & 0x7) + 1); 33476888252Smrg 335d2b10af6Smrg /* 336d2b10af6Smrg * !!! This function seems to be incorrect... 337d2b10af6Smrg */ 33876888252Smrg} 33976888252Smrg 34076888252Smrgstatic xf86MonPtr 34176888252SmrgLgDoDDC(ScrnInfoPtr pScrn) 34276888252Smrg{ 343d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 344d2b10af6Smrg xf86MonPtr MonInfo = NULL; 345d2b10af6Smrg 346d2b10af6Smrg /* 347d2b10af6Smrg * Map the CIR memory and MMIO areas. 348d2b10af6Smrg */ 349d2b10af6Smrg if (!CirMapMem(pCir, pScrn->scrnIndex)) 350d2b10af6Smrg return FALSE; 351d2b10af6Smrg 352d2b10af6Smrg if (!LgI2CInit(pScrn)) { 353d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 354d2b10af6Smrg "I2C initialization failed\n"); 355d2b10af6Smrg goto unmap_out; 356d2b10af6Smrg } 35776888252Smrg 358d2b10af6Smrg /* 359d2b10af6Smrg * Read and output monitor info using DDC2 over I2C bus. 360d2b10af6Smrg */ 361d2b10af6Smrg MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pCir->I2CPtr1); 362d2b10af6Smrg if (!MonInfo) { 363d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 364d2b10af6Smrg "Failed to obtain EDID.\n"); 365d2b10af6Smrg goto unmap_out; 366d2b10af6Smrg } 36776888252Smrg 368d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 369d2b10af6Smrg "I2C Monitor info: %p\n", (void *)MonInfo); 370d2b10af6Smrg xf86PrintEDID(MonInfo); 371d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 372d2b10af6Smrg "end of I2C Monitor info\n\n"); 37376888252Smrg 374d2b10af6Smrg xf86SetDDCproperties(pScrn, MonInfo); 37576888252Smrg 37676888252Smrgunmap_out: 377d2b10af6Smrg CirUnmapMem(pCir, pScrn->scrnIndex); 37876888252Smrg 379d2b10af6Smrg return MonInfo; 38076888252Smrg} 38176888252Smrg 382d2b10af6Smrg/* 383d2b10af6Smrg * Mandatory 384d2b10af6Smrg */ 38576888252SmrgBool 38676888252SmrgLgPreInit(ScrnInfoPtr pScrn, int flags) 38776888252Smrg{ 388d2b10af6Smrg CirPtr pCir; 389d2b10af6Smrg vgaHWPtr hwp; 390d2b10af6Smrg MessageType from; 391d2b10af6Smrg int i; 392d2b10af6Smrg ClockRangePtr clockRanges; 393d2b10af6Smrg int fbPCIReg, ioPCIReg; 394d2b10af6Smrg const char *s; 395d2b10af6Smrg 396d2b10af6Smrg if (flags & PROBE_DETECT) { 397d2b10af6Smrg cirProbeDDC(pScrn, 398d2b10af6Smrg xf86GetEntityInfo(pScrn->entityList[0])->index); 399d2b10af6Smrg return TRUE; 400d2b10af6Smrg } 401d2b10af6Smrg 40276888252Smrg#ifdef LG_DEBUG 403d2b10af6Smrg ErrorF("LgPreInit\n"); 40476888252Smrg#endif 40576888252Smrg 406d2b10af6Smrg /* 407d2b10af6Smrg * Check the number of entities, and fail if it isn't one. 408d2b10af6Smrg */ 409d2b10af6Smrg if (pScrn->numEntities != 1) 410d2b10af6Smrg return FALSE; 411d2b10af6Smrg 412d2b10af6Smrg /* 413d2b10af6Smrg * The vgahw module should be loaded here when needed. 414d2b10af6Smrg */ 415d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) 416d2b10af6Smrg return FALSE; 417d2b10af6Smrg 418d2b10af6Smrg /* 419d2b10af6Smrg * Allocate a vgaHWRec. 420d2b10af6Smrg */ 421d2b10af6Smrg if (!vgaHWGetHWRec(pScrn)) 422d2b10af6Smrg return FALSE; 423d2b10af6Smrg 424d2b10af6Smrg hwp = VGAHWPTR(pScrn); 425d2b10af6Smrg vgaHWSetStdFuncs(hwp); 426d2b10af6Smrg vgaHWGetIOBase(hwp); 427d2b10af6Smrg 428d2b10af6Smrg /* 429d2b10af6Smrg * Allocate the LgRec driverPrivate. 430d2b10af6Smrg */ 431d2b10af6Smrg if (!LgGetRec(pScrn)) 432d2b10af6Smrg return FALSE; 433d2b10af6Smrg 434d2b10af6Smrg pCir = CIRPTR(pScrn); 435d2b10af6Smrg pCir->pScrn = pScrn; 43676888252Smrg 437d2b10af6Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 438d2b10af6Smrg pCir->PIOReg = hwp->PIOOffset + 0x3CE; 439d2b10af6Smrg#else 440d2b10af6Smrg pCir->PIOReg = 0x3CE; 441d2b10af6Smrg#endif 44276888252Smrg 443d2b10af6Smrg /* 444d2b10af6Smrg * Get the entity, and make sure it is PCI. 445d2b10af6Smrg */ 446d2b10af6Smrg pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 447d2b10af6Smrg if (pCir->pEnt->location.type != BUS_PCI) 448d2b10af6Smrg return FALSE; 449d2b10af6Smrg pCir->Chipset = pCir->pEnt->chipset; 450d2b10af6Smrg 451d2b10af6Smrg /* 452d2b10af6Smrg * Find the PCI info for this screen. 453d2b10af6Smrg */ 454d2b10af6Smrg pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index); 455d2b10af6Smrg#ifndef XSERVER_LIBPCIACCESS 456d2b10af6Smrg pCir->PciTag = pciTag(PCI_DEV_BUS(pCir->PciInfo), 457d2b10af6Smrg PCI_DEV_DEV(pCir->PciInfo), PCI_DEV_FUNC(pCir->PciInfo)); 458d2b10af6Smrg#endif 45976888252Smrg 460d2b10af6Smrg if (xf86LoadSubModule(pScrn, "int10")) { 461d2b10af6Smrg xf86Int10InfoPtr int10InfoPtr; 46276888252Smrg 463d2b10af6Smrg int10InfoPtr = xf86InitInt10(pCir->pEnt->index); 46476888252Smrg 465d2b10af6Smrg if (int10InfoPtr) 466d2b10af6Smrg xf86FreeInt10(int10InfoPtr); 467d2b10af6Smrg } 4685c69f917Smrg 469d2b10af6Smrg /* 470d2b10af6Smrg * Set pScrn->monitor. 471d2b10af6Smrg */ 472d2b10af6Smrg pScrn->monitor = pScrn->confScreen->monitor; 473d2b10af6Smrg 474d2b10af6Smrg /* 475d2b10af6Smrg * The first thing we should figure out is the depth, bpp, etc. 476d2b10af6Smrg * We support both 24 bpp and 32 bpp layouts, so indicate that. 477d2b10af6Smrg */ 478d2b10af6Smrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | 479d2b10af6Smrg Support32bppFb | 480d2b10af6Smrg SupportConvert32to24 | 481d2b10af6Smrg PreferConvert32to24)) { 482d2b10af6Smrg return FALSE; 483d2b10af6Smrg } 484d2b10af6Smrg /* 485d2b10af6Smrg * Check that the returned depth is one we support. 486d2b10af6Smrg */ 487d2b10af6Smrg switch (pScrn->depth) { 488d2b10af6Smrg case 8: 489d2b10af6Smrg case 15: 490d2b10af6Smrg case 16: 491d2b10af6Smrg case 24: 492d2b10af6Smrg case 32: 493d2b10af6Smrg /* 494d2b10af6Smrg * OK 495d2b10af6Smrg */ 496d2b10af6Smrg break; 497d2b10af6Smrg default: 498d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 499d2b10af6Smrg "Given depth (%d) is not supported by this " 500d2b10af6Smrg "driver\n", pScrn->depth); 501d2b10af6Smrg return FALSE; 502d2b10af6Smrg } 503d2b10af6Smrg xf86PrintDepthBpp(pScrn); 504d2b10af6Smrg 505d2b10af6Smrg /* 506d2b10af6Smrg * Get the depth24 pixmap format. 507d2b10af6Smrg */ 508d2b10af6Smrg if (pScrn->depth == 24 && pix24bpp == 0) 509d2b10af6Smrg pix24bpp = xf86GetBppFromDepth(pScrn, 24); 510d2b10af6Smrg 511d2b10af6Smrg /* 512d2b10af6Smrg * This must happen after pScrn->display has been set because 513d2b10af6Smrg * xf86SetWeight references it. 514d2b10af6Smrg */ 515d2b10af6Smrg if (pScrn->depth > 8) { 516d2b10af6Smrg /* 517d2b10af6Smrg * The defaults are OK for us. 518d2b10af6Smrg */ 519d2b10af6Smrg rgb zeros = { 0, 0, 0 }; 520d2b10af6Smrg 521d2b10af6Smrg /* 522d2b10af6Smrg * !!! I think we can force 5-6-5 weight for 16bpp here for 523d2b10af6Smrg * the 5462. 524d2b10af6Smrg */ 525d2b10af6Smrg 526d2b10af6Smrg if (!xf86SetWeight(pScrn, zeros, zeros)) { 527d2b10af6Smrg return FALSE; 528d2b10af6Smrg } else { 529d2b10af6Smrg /* 530d2b10af6Smrg * XXX Check that weight returned is supported. 531d2b10af6Smrg */ 532d2b10af6Smrg ; 533d2b10af6Smrg } 534d2b10af6Smrg } 53576888252Smrg 536d2b10af6Smrg if (!xf86SetDefaultVisual(pScrn, -1)) 537d2b10af6Smrg return FALSE; 538d2b10af6Smrg 539d2b10af6Smrg /* 540d2b10af6Smrg * Collect all of the relevant option flags (fill in 541d2b10af6Smrg * pScrn->options). 542d2b10af6Smrg */ 543d2b10af6Smrg xf86CollectOptions(pScrn, NULL); 544d2b10af6Smrg 545d2b10af6Smrg /* 546d2b10af6Smrg * Process the options. 547d2b10af6Smrg */ 548d2b10af6Smrg if (!(pCir->Options = malloc(sizeof(LgOptions)))) 549d2b10af6Smrg return FALSE; 550d2b10af6Smrg memcpy(pCir->Options, LgOptions, sizeof(LgOptions)); 551d2b10af6Smrg xf86ProcessOptions(pScrn->scrnIndex, 552d2b10af6Smrg pScrn->options, 553d2b10af6Smrg pCir->Options); 554d2b10af6Smrg 555d2b10af6Smrg pScrn->rgbBits = 6; 556d2b10af6Smrg from = X_DEFAULT; 557d2b10af6Smrg pCir->HWCursor = FALSE; 558d2b10af6Smrg if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, 559d2b10af6Smrg &pCir->HWCursor)) 560d2b10af6Smrg from = X_CONFIG; 561d2b10af6Smrg 562d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 563d2b10af6Smrg pCir->HWCursor ? "HW" : "SW"); 564d2b10af6Smrg if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) { 565d2b10af6Smrg pCir->NoAccel = TRUE; 566d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 567d2b10af6Smrg "Acceleration disabled\n"); 568d2b10af6Smrg } 569d2b10af6Smrg if (pScrn->bitsPerPixel < 8) { 570d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 571d2b10af6Smrg "Cannot use in less than 8 bpp\n"); 572d2b10af6Smrg return FALSE; 573d2b10af6Smrg } 574d2b10af6Smrg /* 575d2b10af6Smrg * Set the ChipRev, allowing config file entries to override. 576d2b10af6Smrg */ 577d2b10af6Smrg if (pCir->pEnt->device->chipRev >= 0) { 578d2b10af6Smrg pCir->ChipRev = pCir->pEnt->device->chipRev; 579d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 580d2b10af6Smrg "ChipRev override: %d\n", pCir->ChipRev); 581d2b10af6Smrg } else { 582d2b10af6Smrg pCir->ChipRev = PCI_DEV_REVISION(pCir->PciInfo); 583d2b10af6Smrg } 58476888252Smrg 585d2b10af6Smrg /* 586d2b10af6Smrg * Cirrus Logic swapped the FB and IO registers in the 5465 587d2b10af6Smrg * (by design). 588d2b10af6Smrg */ 589d2b10af6Smrg if (PCI_CHIP_GD5465 == pCir->Chipset) { 590d2b10af6Smrg fbPCIReg = 0; 591d2b10af6Smrg ioPCIReg = 1; 592d2b10af6Smrg } else { 593d2b10af6Smrg fbPCIReg = 1; 594d2b10af6Smrg ioPCIReg = 0; 595d2b10af6Smrg } 59676888252Smrg 597d2b10af6Smrg /* 598d2b10af6Smrg * Find the frame buffer base address. 599d2b10af6Smrg */ 600d2b10af6Smrg if (pCir->pEnt->device->MemBase != 0) { 601d2b10af6Smrg /* 602d2b10af6Smrg * Require that the config file value matches one of the PCI 603d2b10af6Smrg * values. 604d2b10af6Smrg */ 605d2b10af6Smrg if (!xf86CheckPciMemBase(pCir->PciInfo, 606d2b10af6Smrg pCir->pEnt->device->MemBase)) { 607d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 608d2b10af6Smrg "MemBase 0x%08lX doesn't match any PCI base " 609d2b10af6Smrg "register.\n", 610d2b10af6Smrg pCir->pEnt->device->MemBase); 611d2b10af6Smrg return FALSE; 612d2b10af6Smrg } 613d2b10af6Smrg pCir->FbAddress = pCir->pEnt->device->MemBase; 614d2b10af6Smrg from = X_CONFIG; 615d2b10af6Smrg } else { 616d2b10af6Smrg if (PCI_REGION_BASE(pCir->PciInfo, 617d2b10af6Smrg fbPCIReg, 618d2b10af6Smrg REGION_MEM) != 0) { 619d2b10af6Smrg pCir->FbAddress = PCI_REGION_BASE(pCir->PciInfo, 620d2b10af6Smrg fbPCIReg, 621d2b10af6Smrg REGION_MEM) & 622d2b10af6Smrg 0xff000000; 623d2b10af6Smrg from = X_PROBED; 624d2b10af6Smrg } else { 625d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 626d2b10af6Smrg "No valid FB address in PCI config space\n"); 627d2b10af6Smrg LgFreeRec(pScrn); 628d2b10af6Smrg return FALSE; 629d2b10af6Smrg } 630d2b10af6Smrg } 631d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, from, 632d2b10af6Smrg "Linear framebuffer at 0x%lX\n", 633d2b10af6Smrg (unsigned long) pCir->FbAddress); 634d2b10af6Smrg 635d2b10af6Smrg /* 636d2b10af6Smrg * Find the MMIO base address. 637d2b10af6Smrg */ 638d2b10af6Smrg if (pCir->pEnt->device->IOBase != 0) { 639d2b10af6Smrg /* 640d2b10af6Smrg * Require that the config file value matches one of the PCI 641d2b10af6Smrg * values. 642d2b10af6Smrg */ 643d2b10af6Smrg if (!xf86CheckPciMemBase(pCir->PciInfo, 644d2b10af6Smrg pCir->pEnt->device->IOBase)) { 645d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 646d2b10af6Smrg "IOBase 0x%08lX doesn't match any PCI base " 647d2b10af6Smrg "register.\n", 648d2b10af6Smrg pCir->pEnt->device->IOBase); 649d2b10af6Smrg return FALSE; 650d2b10af6Smrg } 651d2b10af6Smrg pCir->IOAddress = pCir->pEnt->device->IOBase; 652d2b10af6Smrg from = X_CONFIG; 653d2b10af6Smrg } else { 654d2b10af6Smrg if (PCI_REGION_BASE(pCir->PciInfo, 655d2b10af6Smrg ioPCIReg, 656d2b10af6Smrg REGION_MEM) != 0) { 657d2b10af6Smrg pCir->IOAddress = PCI_REGION_BASE(pCir->PciInfo, 658d2b10af6Smrg ioPCIReg, 659d2b10af6Smrg REGION_MEM) & 660d2b10af6Smrg 0xfffff000; 661d2b10af6Smrg from = X_PROBED; 662d2b10af6Smrg } else { 663d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 664d2b10af6Smrg "No valid MMIO address in PCI config " 665d2b10af6Smrg "space\n"); 666d2b10af6Smrg } 667d2b10af6Smrg } 668d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, from, 669d2b10af6Smrg "MMIO registers at 0x%lX\n", 670d2b10af6Smrg (unsigned long) pCir->IOAddress); 671d2b10af6Smrg 672d2b10af6Smrg /* 673d2b10af6Smrg * If the user has specified the amount of memory in the 674d2b10af6Smrg * XF86Config file, we respect that setting. 675d2b10af6Smrg */ 676d2b10af6Smrg if (pCir->pEnt->device->videoRam != 0) { 677d2b10af6Smrg pScrn->videoRam = pCir->pEnt->device->videoRam; 678d2b10af6Smrg from = X_CONFIG; 679d2b10af6Smrg } else { 680d2b10af6Smrg pScrn->videoRam = LgCountRam(pScrn); 681d2b10af6Smrg from = X_PROBED; 682d2b10af6Smrg } 683d2b10af6Smrg if (2048 == pScrn->videoRam) { 684d2b10af6Smrg /* 685d2b10af6Smrg * Two-way interleaving 686d2b10af6Smrg */ 687d2b10af6Smrg pCir->chip.lg->memInterleave = 0x40; 688d2b10af6Smrg } else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) { 689d2b10af6Smrg /* 690d2b10af6Smrg * Four-way interleaving 691d2b10af6Smrg */ 692d2b10af6Smrg pCir->chip.lg->memInterleave = 0x80; 693d2b10af6Smrg } else { 694d2b10af6Smrg /* 695d2b10af6Smrg * One-way interleaving 696d2b10af6Smrg */ 697d2b10af6Smrg pCir->chip.lg->memInterleave = 0x00; 69876888252Smrg } 699d2b10af6Smrg 700d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, from, 701d2b10af6Smrg "VideoRAM: %d kByte\n", pScrn->videoRam); 702d2b10af6Smrg 703d2b10af6Smrg pCir->FbMapSize = pScrn->videoRam * 1024; 704d2b10af6Smrg /* 705d2b10af6Smrg * 16K for moment, will increase. 706d2b10af6Smrg */ 707d2b10af6Smrg pCir->IoMapSize = 0x4000; 70876888252Smrg 7091e66b2a2Smrg#ifndef XSERVER_LIBPCIACCESS 710d2b10af6Smrg pScrn->racIoFlags = RAC_COLORMAP 71176888252Smrg#ifndef EXPERIMENTAL 712d2b10af6Smrg | RAC_VIEWPORT 71376888252Smrg#endif 714d2b10af6Smrg ; 715d2b10af6Smrg xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr); 716d2b10af6Smrg 717d2b10af6Smrg /* 718d2b10af6Smrg * Register the PCI-assigned resources. 719d2b10af6Smrg */ 720d2b10af6Smrg if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) { 721d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 722d2b10af6Smrg "xf86RegisterResources() found resource " 723d2b10af6Smrg "conflicts\n"); 724d2b10af6Smrg return FALSE; 725d2b10af6Smrg } 7261e66b2a2Smrg#endif 727d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "ddc")) { 728d2b10af6Smrg LgFreeRec(pScrn); 729d2b10af6Smrg return FALSE; 730d2b10af6Smrg } 73176888252Smrg 73276888252Smrg#if LGuseI2C 733d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "i2c")) { 734d2b10af6Smrg LgFreeRec(pScrn); 735d2b10af6Smrg return FALSE; 736d2b10af6Smrg } 73776888252Smrg#endif 73876888252Smrg 739d2b10af6Smrg /* 740d2b10af6Smrg * Read and print the monitor DDC information. 741d2b10af6Smrg */ 742d2b10af6Smrg pScrn->monitor->DDC = LgDoDDC(pScrn); 743d2b10af6Smrg 744d2b10af6Smrg /* 745d2b10af6Smrg * The gamma fields must be initialised when using the new cmap 746d2b10af6Smrg * code. 747d2b10af6Smrg */ 748d2b10af6Smrg if (pScrn->depth > 1) { 749d2b10af6Smrg Gamma zeros = { 0.0, 0.0, 0.0 }; 750d2b10af6Smrg 751d2b10af6Smrg if (!xf86SetGamma(pScrn, zeros)) 752d2b10af6Smrg return FALSE; 753d2b10af6Smrg } 754d2b10af6Smrg if (xf86GetOptValBool(pCir->Options, 755d2b10af6Smrg OPTION_SHADOW_FB, 756d2b10af6Smrg &pCir->shadowFB)) 757d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 758d2b10af6Smrg "ShadowFB %s.\n", 759d2b10af6Smrg pCir->shadowFB ? "enabled" : "disabled"); 760d2b10af6Smrg 761d2b10af6Smrg if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) { 762d2b10af6Smrg if (!xf86NameCmp(s, "CW")) { 763d2b10af6Smrg /* 764d2b10af6Smrg * Acceleration is disabled below for shadowfb. 765d2b10af6Smrg */ 766d2b10af6Smrg pCir->shadowFB = TRUE; 767d2b10af6Smrg pCir->rotate = 1; 768d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 769d2b10af6Smrg "Rotating screen clockwise - " 770d2b10af6Smrg "acceleration disabled\n"); 771d2b10af6Smrg } else if (!xf86NameCmp(s, "CCW")) { 772d2b10af6Smrg pCir->shadowFB = TRUE; 773d2b10af6Smrg pCir->rotate = -1; 774d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 775d2b10af6Smrg "Rotating screen counter clockwise - " 776d2b10af6Smrg "acceleration disabled\n"); 777d2b10af6Smrg } else { 778d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 779d2b10af6Smrg "\"%s\" is not a valid value for Option " 780d2b10af6Smrg "\"Rotate\"\n", s); 781d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 782d2b10af6Smrg "Valid options are \"CW\" or \"CCW\"\n"); 783d2b10af6Smrg } 784d2b10af6Smrg } 785d2b10af6Smrg 786d2b10af6Smrg if (pCir->shadowFB && !pCir->NoAccel) { 787d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 788d2b10af6Smrg "HW acceleration not supported with " 789d2b10af6Smrg "\"shadowFB\".\n"); 790d2b10af6Smrg pCir->NoAccel = TRUE; 791d2b10af6Smrg } 792d2b10af6Smrg 793d2b10af6Smrg if (pCir->rotate && pCir->HWCursor) { 794d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 795d2b10af6Smrg "HW cursor not supported with \"rotate\".\n"); 796d2b10af6Smrg pCir->HWCursor = FALSE; 797d2b10af6Smrg } 798d2b10af6Smrg 799d2b10af6Smrg /* 800d2b10af6Smrg * We use a programmable clock. 801d2b10af6Smrg */ 802d2b10af6Smrg pScrn->progClock = TRUE; 803d2b10af6Smrg 804d2b10af6Smrg /* 805d2b10af6Smrg * XXX Set HW cursor use. 806d2b10af6Smrg */ 807d2b10af6Smrg 808d2b10af6Smrg /* 809d2b10af6Smrg * Set the min pixel clock. 810d2b10af6Smrg */ 811d2b10af6Smrg /* 812d2b10af6Smrg * XXX Guess, need to check this. 813d2b10af6Smrg */ 814d2b10af6Smrg pCir->MinClock = 12000; 815d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 816d2b10af6Smrg "Min pixel clock is %d MHz\n", 817d2b10af6Smrg pCir->MinClock / 1000); 818d2b10af6Smrg /* 819d2b10af6Smrg * If the user has specified RAMDAC speed in the XF86Config 820d2b10af6Smrg * file, we respect that setting. 821d2b10af6Smrg */ 822d2b10af6Smrg if (pCir->pEnt->device->dacSpeeds[0]) { 823d2b10af6Smrg ErrorF("Do not specify a Clocks line for Cirrus chips\n"); 824d2b10af6Smrg return FALSE; 825d2b10af6Smrg } else { 826d2b10af6Smrg int speed; 827d2b10af6Smrg int *p; 828d2b10af6Smrg switch (pCir->Chipset) { 829d2b10af6Smrg case PCI_CHIP_GD5462: 830d2b10af6Smrg p = gd5462_MaxClocks; 831d2b10af6Smrg break; 832d2b10af6Smrg case PCI_CHIP_GD5464: 833d2b10af6Smrg case PCI_CHIP_GD5464BD: 834d2b10af6Smrg p = gd5464_MaxClocks; 835d2b10af6Smrg break; 836d2b10af6Smrg case PCI_CHIP_GD5465: 837d2b10af6Smrg p = gd5465_MaxClocks; 838d2b10af6Smrg break; 839d2b10af6Smrg default: 840d2b10af6Smrg ErrorF("???\n"); 841d2b10af6Smrg return FALSE; 842d2b10af6Smrg } 843d2b10af6Smrg switch (pScrn->bitsPerPixel) { 844d2b10af6Smrg case 8: 845d2b10af6Smrg speed = p[1]; 846d2b10af6Smrg break; 847d2b10af6Smrg case 15: 848d2b10af6Smrg case 16: 849d2b10af6Smrg speed = p[2]; 850d2b10af6Smrg break; 851d2b10af6Smrg case 24: 852d2b10af6Smrg speed = p[3]; 853d2b10af6Smrg break; 854d2b10af6Smrg case 32: 855d2b10af6Smrg speed = p[4]; 856d2b10af6Smrg break; 857d2b10af6Smrg default: 858d2b10af6Smrg /* 859d2b10af6Smrg * Should not get here. 860d2b10af6Smrg */ 861d2b10af6Smrg speed = 0; 862d2b10af6Smrg break; 863d2b10af6Smrg } 864d2b10af6Smrg pCir->MaxClock = speed; 865d2b10af6Smrg from = X_PROBED; 866d2b10af6Smrg } 867d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 868d2b10af6Smrg pCir->MaxClock / 1000); 869d2b10af6Smrg 870d2b10af6Smrg /* 871d2b10af6Smrg * Setup the ClockRanges, which describe what clock ranges are 872d2b10af6Smrg * available, and what sort of modes they can be used for. 873d2b10af6Smrg */ 874d2b10af6Smrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 875d2b10af6Smrg clockRanges->next = NULL; 876d2b10af6Smrg clockRanges->minClock = pCir->MinClock; 877d2b10af6Smrg clockRanges->maxClock = pCir->MaxClock; 878d2b10af6Smrg /* 879d2b10af6Smrg * programmable 880d2b10af6Smrg */ 881d2b10af6Smrg clockRanges->clockIndex = -1; 882d2b10af6Smrg /* 883d2b10af6Smrg * XXX Check this. 884d2b10af6Smrg */ 885d2b10af6Smrg clockRanges->interlaceAllowed = FALSE; 886d2b10af6Smrg /* 887d2b10af6Smrg * XXX Check this. 888d2b10af6Smrg */ 889d2b10af6Smrg clockRanges->doubleScanAllowed = FALSE; 890d2b10af6Smrg /* 891d2b10af6Smrg * XXX Check this. 892d2b10af6Smrg */ 893d2b10af6Smrg clockRanges->doubleScanAllowed = FALSE; 894d2b10af6Smrg /* 895d2b10af6Smrg * XXX Check this. 896d2b10af6Smrg */ 897d2b10af6Smrg clockRanges->doubleScanAllowed = FALSE; 898d2b10af6Smrg clockRanges->ClockMulFactor = 1; 899d2b10af6Smrg clockRanges->ClockDivFactor = 1; 900d2b10af6Smrg clockRanges->PrivFlags = 0; 901d2b10af6Smrg 902d2b10af6Smrg /* 903d2b10af6Smrg * Depending upon what sized tiles used, either 128 or 256. 904d2b10af6Smrg */ 905d2b10af6Smrg /* 906d2b10af6Smrg * Aw, heck. Just say 128. 907d2b10af6Smrg */ 908d2b10af6Smrg pCir->Rounding = 128 >> pCir->BppShift; 909d2b10af6Smrg 910d2b10af6Smrg /* 911d2b10af6Smrg * xf86ValidateModes will check that the mode HTotal and VTotal 912d2b10af6Smrg * values don't exceed the chipset's limit if pScrn->maxHValue 913d2b10af6Smrg * and pScrn->maxVValue are set. Since our CIRValidMode() 914d2b10af6Smrg * already takes care of this, we don't worry about setting them 915d2b10af6Smrg * here. 916d2b10af6Smrg */ 917d2b10af6Smrg 918d2b10af6Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 919d2b10af6Smrg pScrn->display->modes, clockRanges, 920d2b10af6Smrg LgLinePitches[pScrn->bitsPerPixel / 8 - 1], 921d2b10af6Smrg 0, 0, 922d2b10af6Smrg 128 * 8, 0, 923d2b10af6Smrg /* 924d2b10af6Smrg * Any virtual height is allowed. 925d2b10af6Smrg */ 926d2b10af6Smrg 0, 927d2b10af6Smrg pScrn->display->virtualX, 928d2b10af6Smrg pScrn->display->virtualY, 929d2b10af6Smrg pCir->FbMapSize, LOOKUP_BEST_REFRESH); 930d2b10af6Smrg 931d2b10af6Smrg pCir->chip.lg->lineDataIndex = 932d2b10af6Smrg LgFindLineData(pScrn->displayWidth, 933d2b10af6Smrg pScrn->bitsPerPixel); 934d2b10af6Smrg 935d2b10af6Smrg if (i == -1) { 936d2b10af6Smrg LgFreeRec(pScrn); 937d2b10af6Smrg return FALSE; 938d2b10af6Smrg } 939d2b10af6Smrg 940d2b10af6Smrg /* 941d2b10af6Smrg * Prune the modes marked as invalid. 942d2b10af6Smrg */ 943d2b10af6Smrg xf86PruneDriverModes(pScrn); 944d2b10af6Smrg 945d2b10af6Smrg if (i == 0 || pScrn->modes == NULL) { 946d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 947d2b10af6Smrg "No valid modes found\n"); 948d2b10af6Smrg LgFreeRec(pScrn); 949d2b10af6Smrg return FALSE; 950d2b10af6Smrg } 951d2b10af6Smrg 952d2b10af6Smrg /* 953d2b10af6Smrg * Set the CRTC parameters for all of the modes based on the type 954d2b10af6Smrg * of mode, and the chipset's interlace requirements. Calling 955d2b10af6Smrg * this is required if the mode->Crtc* values are used by the 956d2b10af6Smrg * driver and if the driver doesn't provide code to set 957d2b10af6Smrg * them. They are not pre-initialised at all. 958d2b10af6Smrg */ 959d2b10af6Smrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 960d2b10af6Smrg 961d2b10af6Smrg /* 962d2b10af6Smrg * Set the current mode to the first in the list. 963d2b10af6Smrg */ 964d2b10af6Smrg pScrn->currentMode = pScrn->modes; 965d2b10af6Smrg 966d2b10af6Smrg /* 967d2b10af6Smrg * Print the list of modes being used. 968d2b10af6Smrg */ 969d2b10af6Smrg xf86PrintModes(pScrn); 970d2b10af6Smrg 971d2b10af6Smrg /* 972d2b10af6Smrg * Set display resolution. 973d2b10af6Smrg */ 974d2b10af6Smrg xf86SetDpi(pScrn, 0, 0); 975d2b10af6Smrg 976d2b10af6Smrg /* 977d2b10af6Smrg * Load bpp-specific modules. 978d2b10af6Smrg */ 979d2b10af6Smrg switch (pScrn->bitsPerPixel) { 980d2b10af6Smrg case 8: 981d2b10af6Smrg case 16: 982d2b10af6Smrg case 24: 983d2b10af6Smrg case 32: 984d2b10af6Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 985d2b10af6Smrg LgFreeRec(pScrn); 986d2b10af6Smrg return FALSE; 987d2b10af6Smrg } 988d2b10af6Smrg break; 989d2b10af6Smrg } 990d2b10af6Smrg 991d2b10af6Smrg /* 992d2b10af6Smrg * Load XAA if needed. 993d2b10af6Smrg */ 994d2b10af6Smrg if (!pCir->NoAccel) { 9955c69f917Smrg#ifdef HAVE_XAA_H 996d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "xaa")) 9975c69f917Smrg#else 998d2b10af6Smrg if (1) 9995c69f917Smrg#endif 1000d2b10af6Smrg { 1001d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1002d2b10af6Smrg "Falling back to shadowfb\n"); 1003d2b10af6Smrg pCir->NoAccel = TRUE; 1004d2b10af6Smrg pCir->shadowFB = TRUE; 1005d2b10af6Smrg } 1006d2b10af6Smrg } 1007d2b10af6Smrg 1008d2b10af6Smrg /* 1009d2b10af6Smrg * Load RAMDAC if needed. 1010d2b10af6Smrg */ 1011d2b10af6Smrg if (pCir->HWCursor) { 1012d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 1013d2b10af6Smrg LgFreeRec(pScrn); 1014d2b10af6Smrg return FALSE; 1015d2b10af6Smrg } 1016d2b10af6Smrg } 1017d2b10af6Smrg 1018d2b10af6Smrg if (pCir->shadowFB) { 1019d2b10af6Smrg if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1020d2b10af6Smrg LgFreeRec(pScrn); 1021d2b10af6Smrg return FALSE; 1022d2b10af6Smrg } 1023d2b10af6Smrg } 1024d2b10af6Smrg 1025d2b10af6Smrg return TRUE; 102676888252Smrg} 102776888252Smrg 102876888252Smrg/* 102976888252Smrg * This function saves the video state. 103076888252Smrg */ 103176888252Smrgstatic void 103276888252SmrgLgSave(ScrnInfoPtr pScrn) 103376888252Smrg{ 1034d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 1035d2b10af6Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 103676888252Smrg 103776888252Smrg#ifdef LG_DEBUG 1038d2b10af6Smrg ErrorF("LgSave\n"); 103976888252Smrg#endif 104076888252Smrg 1041d2b10af6Smrg vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL); 1042d2b10af6Smrg 1043d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1A] = 1044d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A); 1045d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] = 1046d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B); 1047d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1D] = 1048d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D); 1049d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] = 1050d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E); 1051d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[SR07] = 1052d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07); 1053d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[SR0E] = 1054d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E); 1055d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[SR1E] = 1056d2b10af6Smrg pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E); 1057d2b10af6Smrg 1058d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 1059d2b10af6Smrg pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0); 1060d2b10af6Smrg 1061d2b10af6Smrg pCir->chip.lg->ModeReg.VSC = 1062d2b10af6Smrg pCir->chip.lg->SavedReg.VSC = memrl(0x3FC); 1063d2b10af6Smrg 1064d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1065d2b10af6Smrg pCir->chip.lg->SavedReg.DTTC = memrw(0xEA); 1066d2b10af6Smrg 1067d2b10af6Smrg if (pCir->Chipset == PCI_CHIP_GD5465) { 1068d2b10af6Smrg pCir->chip.lg->ModeReg.TileCtrl = 1069d2b10af6Smrg pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4); 1070d2b10af6Smrg } 1071d2b10af6Smrg 1072d2b10af6Smrg pCir->chip.lg->ModeReg.TILE = 1073d2b10af6Smrg pCir->chip.lg->SavedReg.TILE = memrb(0x407); 1074d2b10af6Smrg 1075d2b10af6Smrg if (pCir->Chipset == PCI_CHIP_GD5465) 1076d2b10af6Smrg pCir->chip.lg->ModeReg.BCLK = 1077d2b10af6Smrg pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0); 1078d2b10af6Smrg else 1079d2b10af6Smrg pCir->chip.lg->ModeReg.BCLK = 1080d2b10af6Smrg pCir->chip.lg->SavedReg.BCLK = memrb(0x8C); 1081d2b10af6Smrg 1082d2b10af6Smrg pCir->chip.lg->ModeReg.CONTROL = 1083d2b10af6Smrg pCir->chip.lg->SavedReg.CONTROL = memrw(0x402); 1084d2b10af6Smrg 1085d2b10af6Smrg pCir->chip.lg->ModeReg.RIFCtrl = 1086d2b10af6Smrg pCir->chip.lg->SavedReg.RIFCtrl = memrw(0x200); 1087d2b10af6Smrg 1088d2b10af6Smrg pCir->chip.lg->ModeReg.RACCtrl = 1089d2b10af6Smrg pCir->chip.lg->SavedReg.RACCtrl = memrw(0x202); 109076888252Smrg} 109176888252Smrg 109276888252Smrg/* 109376888252Smrg * Initialise a new mode. This is currently still using the old 109476888252Smrg * "initialise struct, restore/write struct to HW" model. That could 109576888252Smrg * be changed. 109676888252Smrg */ 109776888252Smrgstatic Bool 109876888252SmrgLgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 109976888252Smrg{ 1100d2b10af6Smrg vgaHWPtr hwp; 1101d2b10af6Smrg CirPtr pCir; 1102d2b10af6Smrg int width; 1103d2b10af6Smrg Bool VDiv2 = FALSE; 1104d2b10af6Smrg CARD16 clockData; 1105d2b10af6Smrg LgLineDataPtr lineData; 110676888252Smrg 110776888252Smrg#ifdef LG_DEBUG 1108d2b10af6Smrg ErrorF("LgModeInit %d bpp, %d %d %d %d %d %d %d %d %d\n", 1109d2b10af6Smrg pScrn->bitsPerPixel, mode->Clock, 1110d2b10af6Smrg mode->HDisplay, mode->HSyncStart, 1111d2b10af6Smrg mode->HSyncEnd, mode->HTotal, 1112d2b10af6Smrg mode->VDisplay, mode->VSyncStart, 1113d2b10af6Smrg mode->VSyncEnd, mode->VTotal); 1114d2b10af6Smrg 1115d2b10af6Smrg ErrorF("LgModeInit: depth %d bits\n", pScrn->depth); 111676888252Smrg#endif 111776888252Smrg 1118d2b10af6Smrg pCir = CIRPTR(pScrn); 1119d2b10af6Smrg hwp = VGAHWPTR(pScrn); 1120d2b10af6Smrg vgaHWUnlock(hwp); 1121d2b10af6Smrg 1122d2b10af6Smrg if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) { 1123d2b10af6Smrg /* 1124d2b10af6Smrg * For non-interlaced vertical timing >= 1024, the vertical 1125d2b10af6Smrg * timings are divided by 2 and VGA CRTC 0x17 bit 2 is set. 1126d2b10af6Smrg */ 1127d2b10af6Smrg if (!mode->CrtcVAdjusted) { 1128d2b10af6Smrg mode->CrtcVDisplay >>= 1; 1129d2b10af6Smrg mode->CrtcVSyncStart >>= 1; 1130d2b10af6Smrg mode->CrtcVSyncEnd >>= 1; 1131d2b10af6Smrg mode->CrtcVTotal >>= 1; 1132d2b10af6Smrg mode->CrtcVAdjusted = TRUE; 1133d2b10af6Smrg } 1134d2b10af6Smrg VDiv2 = TRUE; 1135d2b10af6Smrg } 1136d2b10af6Smrg 1137d2b10af6Smrg /* 1138d2b10af6Smrg * Initialise the ModeReg values. 1139d2b10af6Smrg */ 1140d2b10af6Smrg if (!vgaHWInit(pScrn, mode)) 1141d2b10af6Smrg return FALSE; 1142d2b10af6Smrg pScrn->vtSema = TRUE; 1143d2b10af6Smrg 1144d2b10af6Smrg if (VDiv2) 1145d2b10af6Smrg hwp->ModeReg.CRTC[0x17] |= 0x04; 114676888252Smrg 114776888252Smrg#ifdef LG_DEBUG 1148d2b10af6Smrg ErrorF("SynthClock = %d\n", mode->SynthClock); 114976888252Smrg#endif 1150d2b10af6Smrg hwp->IOBase = 0x3D0; 1151d2b10af6Smrg hwp->ModeReg.MiscOutReg |= 0x01; 1152d2b10af6Smrg/* 1153d2b10af6Smrg * Mono address 1154d2b10af6Smrg */ 1155d2b10af6Smrg#if 0 1156d2b10af6Smrg hwp->IOBase = 0x3B0; 1157d2b10af6Smrg hwp->ModeReg.MiscOutReg &= ~0x01; 115876888252Smrg#endif 115976888252Smrg 1160d2b10af6Smrg /* 1161d2b10af6Smrg * ??? Should these be both ...End or ...Start, not one of each? 1162d2b10af6Smrg */ 1163d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1A] = 1164d2b10af6Smrg (((mode->CrtcVSyncStart + 1) & 0x300) >> 2) | 1165d2b10af6Smrg (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2); 1166d2b10af6Smrg 1167d2b10af6Smrg width = pScrn->displayWidth * pScrn->bitsPerPixel / 8; 1168d2b10af6Smrg if (pScrn->bitsPerPixel == 1) 1169d2b10af6Smrg width <<= 2; 1170d2b10af6Smrg hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3; 1171d2b10af6Smrg /* 1172d2b10af6Smrg * Offset extension (see CR13) 1173d2b10af6Smrg */ 1174d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF; 1175d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 1176d2b10af6Smrg (((width + 7) >> 3) & 0x100) ? 0x10 : 0x00; 1177d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22; 1178d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1D] = 1179d2b10af6Smrg (((width + 7) >> 3) & 0x200) ? 0x01 : 0x00; 1180d2b10af6Smrg 1181d2b10af6Smrg /* 1182d2b10af6Smrg * Set the 28th bit to enable extended modes. 1183d2b10af6Smrg */ 1184d2b10af6Smrg pCir->chip.lg->ModeReg.VSC = 0x10000000; 1185d2b10af6Smrg 1186d2b10af6Smrg /* 1187d2b10af6Smrg * Overflow register (sure are a lot of overflow bits around...) 1188d2b10af6Smrg */ 1189d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00; 1190d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1191d2b10af6Smrg (mode->CrtcHTotal >> 3 & 0x0100) ? 1 : 0) << 7; 1192d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1193d2b10af6Smrg (mode->CrtcHDisplay >> 3 & 0x0100) ? 1 : 0) << 6; 1194d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1195d2b10af6Smrg (mode->CrtcHSyncStart >> 3 & 0x0100) ? 1 : 0) << 5; 1196d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1197d2b10af6Smrg (mode->CrtcHSyncStart >> 3 & 0x0100) ? 1 : 0) << 4; 1198d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= 1199d2b10af6Smrg ((mode->CrtcVTotal & 0x0400) ? 1 : 0) << 3; 1200d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1201d2b10af6Smrg (mode->CrtcVDisplay & 0x0400) ? 1 : 0) << 2; 1202d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1203d2b10af6Smrg (mode->CrtcVSyncStart & 0x0400) ? 1 : 0) << 1; 1204d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ( 1205d2b10af6Smrg (mode->CrtcVSyncStart & 0x0400) ? 1 : 0) << 0; 1206d2b10af6Smrg 1207d2b10af6Smrg lineData = &LgLineData[pCir->chip.lg->lineDataIndex]; 1208d2b10af6Smrg 1209d2b10af6Smrg pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F; 1210d2b10af6Smrg 1211d2b10af6Smrg if (8 == pScrn->bitsPerPixel) { 1212d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 0x0000; 1213d2b10af6Smrg 1214d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1215d2b10af6Smrg (pCir->chip.lg->ModeReg.TILE << 8) | 1216d2b10af6Smrg 0x0080 | 1217d2b10af6Smrg (lineData->width << 6); 1218d2b10af6Smrg pCir->chip.lg->ModeReg.CONTROL = 0x0000 | 1219d2b10af6Smrg (lineData->width << 11); 1220d2b10af6Smrg 1221d2b10af6Smrg /* 1222d2b10af6Smrg * There is an optimal FIFO threshold value (lower 1223d2b10af6Smrg * 5 bits of DTTC) for every resolution and color depth 1224d2b10af6Smrg * combination. We'll hit the highlights here, and get 1225d2b10af6Smrg * close for anything that's not covered. 1226d2b10af6Smrg */ 1227d2b10af6Smrg if (mode->CrtcHDisplay <= 640) { 1228d2b10af6Smrg /* 1229d2b10af6Smrg * BAD numbers: 0x1E 1230d2b10af6Smrg * GOOD numbers: 0x14 1231d2b10af6Smrg */ 1232d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1233d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1234d2b10af6Smrg (0x0014); 1235d2b10af6Smrg } else if (mode->CrtcHDisplay <= 800) { 1236d2b10af6Smrg /* 1237d2b10af6Smrg * BAD numbers: 0x16 1238d2b10af6Smrg * GOOD numbers: 0x13 0x14 1239d2b10af6Smrg */ 1240d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1241d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1242d2b10af6Smrg (0x0014); 1243d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1024) { 1244d2b10af6Smrg /* 1245d2b10af6Smrg * BAD numbers: 1246d2b10af6Smrg * GOOD numbers: 0x15 1247d2b10af6Smrg */ 1248d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1249d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1250d2b10af6Smrg (0x0015); 1251d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1280) { 1252d2b10af6Smrg /* 1253d2b10af6Smrg * BAD numbers: 1254d2b10af6Smrg * GOOD numbers: 0x16 1255d2b10af6Smrg */ 1256d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1257d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1258d2b10af6Smrg (0x0016); 1259d2b10af6Smrg } else { 1260d2b10af6Smrg /* 1261d2b10af6Smrg * BAD numbers: 1262d2b10af6Smrg * GOOD numbers: 1263d2b10af6Smrg */ 1264d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1265d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1266d2b10af6Smrg (0x0017); 1267d2b10af6Smrg } 1268d2b10af6Smrg } else if (16 == pScrn->bitsPerPixel) { 1269d2b10af6Smrg /* 1270d2b10af6Smrg * !!! Assume 5-6-5 RGB mode (for now...). 1271d2b10af6Smrg */ 1272d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 0x1400; 1273d2b10af6Smrg 1274d2b10af6Smrg if (pScrn->depth == 15) 1275d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 0x1600; 1276d2b10af6Smrg 1277d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1278d2b10af6Smrg (pCir->chip.lg->ModeReg.TILE << 8) | 1279d2b10af6Smrg 0x0080 | 1280d2b10af6Smrg (lineData->width << 6); 1281d2b10af6Smrg pCir->chip.lg->ModeReg.CONTROL = 0x2000 | 1282d2b10af6Smrg (lineData->width << 11); 1283d2b10af6Smrg 1284d2b10af6Smrg if (mode->CrtcHDisplay <= 640) { 1285d2b10af6Smrg /* 1286d2b10af6Smrg * BAD numbers: 0x12 1287d2b10af6Smrg * GOOD numbers: 0x10 1288d2b10af6Smrg */ 1289d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1290d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1291d2b10af6Smrg (0x0010); 1292d2b10af6Smrg } else if (mode->CrtcHDisplay <= 800) { 1293d2b10af6Smrg /* 1294d2b10af6Smrg * BAD numbers: 0x13 1295d2b10af6Smrg * GOOD numbers: 0x11 1296d2b10af6Smrg */ 1297d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1298d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1299d2b10af6Smrg (0x0011); 1300d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1024) { 1301d2b10af6Smrg /* 1302d2b10af6Smrg * BAD numbers: 0x14 1303d2b10af6Smrg * GOOD numbers: 0x12 1304d2b10af6Smrg */ 1305d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1306d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1307d2b10af6Smrg (0x0012); 1308d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1280) { 1309d2b10af6Smrg /* 1310d2b10af6Smrg * BAD numbers: 0x08 0x10 1311d2b10af6Smrg * Borderline numbers: 0x12 1312d2b10af6Smrg * GOOD numbers: 0x15 1313d2b10af6Smrg */ 1314d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1315d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1316d2b10af6Smrg (0x0015); 1317d2b10af6Smrg } else { 1318d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1319d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1320d2b10af6Smrg (0x0017); 1321d2b10af6Smrg } 1322d2b10af6Smrg } else if (24 == pScrn->bitsPerPixel) { 1323d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 0x2400; 1324d2b10af6Smrg 1325d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1326d2b10af6Smrg (pCir->chip.lg->ModeReg.TILE << 8) | 1327d2b10af6Smrg 0x0080 | 1328d2b10af6Smrg (lineData->width << 6); 1329d2b10af6Smrg pCir->chip.lg->ModeReg.CONTROL = 0x4000 | 1330d2b10af6Smrg (lineData->width << 11); 1331d2b10af6Smrg 1332d2b10af6Smrg if (mode->CrtcHDisplay <= 640) { 1333d2b10af6Smrg /* 1334d2b10af6Smrg * BAD numbers: 1335d2b10af6Smrg * GOOD numbers: 0x10 1336d2b10af6Smrg */ 1337d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1338d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1339d2b10af6Smrg (0x0010); 1340d2b10af6Smrg } else if (mode->CrtcHDisplay <= 800) { 1341d2b10af6Smrg /* 1342d2b10af6Smrg * BAD numbers: 1343d2b10af6Smrg * GOOD numbers: 0x11 1344d2b10af6Smrg */ 1345d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1346d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1347d2b10af6Smrg (0x0011); 1348d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1024) { 1349d2b10af6Smrg /* 1350d2b10af6Smrg * BAD numbers: 0x12 0x13 1351d2b10af6Smrg * Borderline numbers: 0x15 1352d2b10af6Smrg * GOOD numbers: 0x17 1353d2b10af6Smrg */ 1354d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1355d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1356d2b10af6Smrg (0x0017); 1357d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1280) { 1358d2b10af6Smrg /* 1359d2b10af6Smrg * BAD numbers: 1360d2b10af6Smrg * GOOD numbers: 0x1E 1361d2b10af6Smrg */ 1362d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1363d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1364d2b10af6Smrg (0x001E); 1365d2b10af6Smrg } else { 1366d2b10af6Smrg /* 1367d2b10af6Smrg * BAD numbers: 1368d2b10af6Smrg * GOOD numbers: 1369d2b10af6Smrg */ 1370d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1371d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1372d2b10af6Smrg (0x0020); 1373d2b10af6Smrg } 1374d2b10af6Smrg } else if (32 == pScrn->bitsPerPixel) { 1375d2b10af6Smrg pCir->chip.lg->ModeReg.FORMAT = 0x3400; 1376d2b10af6Smrg 1377d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1378d2b10af6Smrg (pCir->chip.lg->ModeReg.TILE << 8) | 1379d2b10af6Smrg 0x0080 | 1380d2b10af6Smrg (lineData->width << 6); 1381d2b10af6Smrg pCir->chip.lg->ModeReg.CONTROL = 0x6000 | 1382d2b10af6Smrg (lineData->width << 11); 1383d2b10af6Smrg 1384d2b10af6Smrg if (mode->CrtcHDisplay <= 640) { 1385d2b10af6Smrg /* 1386d2b10af6Smrg * GOOD numbers: 0x0E 1387d2b10af6Smrg * BAD numbers: 1388d2b10af6Smrg */ 1389d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1390d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1391d2b10af6Smrg (0x000E); 1392d2b10af6Smrg } else if (mode->CrtcHDisplay <= 800) { 1393d2b10af6Smrg /* 1394d2b10af6Smrg * GOOD numbers: 0x17 1395d2b10af6Smrg * BAD numbers: 1396d2b10af6Smrg */ 1397d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1398d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1399d2b10af6Smrg (0x0017); 1400d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1024) { 1401d2b10af6Smrg /* 1402d2b10af6Smrg * GOOD numbers: 0x1D 1403d2b10af6Smrg * OKAY numbers: 0x15 0x14 0x16 0x18 0x19 1404d2b10af6Smrg * BAD numbers: 0x0E 0x12 0x13 0x0D 1405d2b10af6Smrg */ 1406d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1407d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1408d2b10af6Smrg (0x001D); 1409d2b10af6Smrg } else if (mode->CrtcHDisplay <= 1280) { 1410d2b10af6Smrg /* 1411d2b10af6Smrg * GOOD numbers: 1412d2b10af6Smrg * BAD numbers: 1413d2b10af6Smrg */ 1414d2b10af6Smrg /* 1415d2b10af6Smrg * 10 1416d2b10af6Smrg */ 1417d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1418d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1419d2b10af6Smrg (0x0022); 1420d2b10af6Smrg } else { 1421d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1422d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | 1423d2b10af6Smrg (0x0024); 1424d2b10af6Smrg } 1425d2b10af6Smrg } else { 1426d2b10af6Smrg /* 1427d2b10af6Smrg * ??? What could it be? Use some sane numbers. 1428d2b10af6Smrg */ 1429d2b10af6Smrg } 143076888252Smrg 1431d2b10af6Smrg /* 1432d2b10af6Smrg * Setup the appropriate memory interleaving. 1433d2b10af6Smrg */ 1434d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8); 1435d2b10af6Smrg pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0; 1436d2b10af6Smrg 1437d2b10af6Smrg if (PCI_CHIP_GD5465 == pCir->Chipset) { 1438d2b10af6Smrg /* 1439d2b10af6Smrg * The tile control information in the DTTC is also mirrored 1440d2b10af6Smrg * elsewhere. 1441d2b10af6Smrg */ 1442d2b10af6Smrg pCir->chip.lg->ModeReg.TileCtrl = 1443d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC & 0xFFC0; 1444d2b10af6Smrg 1445d2b10af6Smrg /* 1446d2b10af6Smrg * The 5465's DTTC records _fetches_ per line, not tiles per 1447d2b10af6Smrg * line. Fetches are 128-byte fetches. 1448d2b10af6Smrg */ 1449d2b10af6Smrg if (pCir->chip.lg->ModeReg.DTTC & 0x0040) { 1450d2b10af6Smrg /* 1451d2b10af6Smrg * Using 256-byte wide tiles. Double the fetches per 1452d2b10af6Smrg * line field. 1453d2b10af6Smrg */ 1454d2b10af6Smrg pCir->chip.lg->ModeReg.DTTC = 1455d2b10af6Smrg (pCir->chip.lg->ModeReg.DTTC & 0xC0FF) | 1456d2b10af6Smrg ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1); 1457d2b10af6Smrg } 1458d2b10af6Smrg } 145976888252Smrg 1460d2b10af6Smrg /* 1461d2b10af6Smrg * Programme the registers. 1462d2b10af6Smrg */ 1463d2b10af6Smrg vgaHWProtect(pScrn, TRUE); 1464d2b10af6Smrg hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg); 1465d2b10af6Smrg 1466d2b10af6Smrg clockData = LgSetClock(pCir, hwp, mode->SynthClock); 1467d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF; 1468d2b10af6Smrg pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF; 146976888252Smrg 1470d2b10af6Smrg /* 1471d2b10af6Smrg * Write those registers out to the card. 1472d2b10af6Smrg */ 1473d2b10af6Smrg LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg); 147476888252Smrg 1475d2b10af6Smrg /* 1476d2b10af6Smrg * Programme the registers. 1477d2b10af6Smrg */ 1478d2b10af6Smrg vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP); 147976888252Smrg 1480d2b10af6Smrg vgaHWProtect(pScrn, FALSE); 1481d2b10af6Smrg 1482d2b10af6Smrg return TRUE; 1483d2b10af6Smrg} 1484d2b10af6Smrg 1485d2b10af6Smrgstatic int 1486d2b10af6SmrgLgFindLineData(int displayWidth, int bpp) 1487d2b10af6Smrg{ 1488d2b10af6Smrg /* 1489d2b10af6Smrg * Find the smallest tile-line-pitch such that the total byte 1490d2b10af6Smrg * pitch is greater than or equal to displayWidth * Bpp. 1491d2b10af6Smrg */ 1492d2b10af6Smrg int i; 1493d2b10af6Smrg 1494d2b10af6Smrg /* 1495d2b10af6Smrg * Some pitch sizes are duplicates in the table. BUT, the 1496d2b10af6Smrg * invariant is that the _first_ time a pitch occurs in the table 1497d2b10af6Smrg * is always _before_ all other pitches greater than it. Said in 1498d2b10af6Smrg * another way... if all duplicate entries from the table were 1499d2b10af6Smrg * removed, then the resulting pitch values are strictly 1500d2b10af6Smrg * increasing. 1501d2b10af6Smrg */ 1502d2b10af6Smrg 1503d2b10af6Smrg for (i = 0; LgLineData[i].pitch > 0; i++) 1504d2b10af6Smrg if (LgLineData[i].pitch >= displayWidth * bpp >> 3) 1505d2b10af6Smrg return i; 1506d2b10af6Smrg 1507d2b10af6Smrg /* 1508d2b10af6Smrg * Um, uh oh! 1509d2b10af6Smrg */ 1510d2b10af6Smrg return -1; 1511d2b10af6Smrg} 151276888252Smrg 151376888252Smrgstatic void 151476888252SmrgLgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg) 151576888252Smrg{ 1516d2b10af6Smrg CirPtr pCir; 1517d2b10af6Smrg vgaHWPtr hwp; 1518d2b10af6Smrg CARD8 cr1D; 1519d2b10af6Smrg 1520d2b10af6Smrg pCir = CIRPTR(pScrn); 1521d2b10af6Smrg 1522d2b10af6Smrg /* 1523d2b10af6Smrg * First, VGAish registers. 1524d2b10af6Smrg */ 1525d2b10af6Smrg hwp = VGAHWPTR(pScrn); 1526d2b10af6Smrg hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]); 1527d2b10af6Smrg hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]); 1528d2b10af6Smrg cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | 1529d2b10af6Smrg (lgReg->ExtVga[CR1D] & 0x01); 1530d2b10af6Smrg hwp->writeCrtc(hwp, 0x1D, cr1D); 1531d2b10af6Smrg hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]); 1532d2b10af6Smrg 1533d2b10af6Smrg hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]); 1534d2b10af6Smrg hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]); 1535d2b10af6Smrg hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]); 1536d2b10af6Smrg memww(0xC0, lgReg->FORMAT); 1537d2b10af6Smrg 1538d2b10af6Smrg /* 1539d2b10af6Smrg * Vendor Specific Control is touchy. Only bit 28 is of concern. 1540d2b10af6Smrg */ 1541d2b10af6Smrg memwl(0x3FC, ((memrl(0x3FC) & ~(1 << 28)) | 1542d2b10af6Smrg (lgReg->VSC & (1 << 28)))); 1543d2b10af6Smrg 1544d2b10af6Smrg memww(0xEA, lgReg->DTTC); 1545d2b10af6Smrg 1546d2b10af6Smrg if (pCir->Chipset == PCI_CHIP_GD5465) { 1547d2b10af6Smrg memww(0x2C4, lgReg->TileCtrl); 1548d2b10af6Smrg } 1549d2b10af6Smrg 1550d2b10af6Smrg memwb(0x407, lgReg->TILE); 1551d2b10af6Smrg 1552d2b10af6Smrg if (pCir->Chipset == PCI_CHIP_GD5465) 1553d2b10af6Smrg memwb(0x2C0, lgReg->BCLK); 1554d2b10af6Smrg else 1555d2b10af6Smrg memwb(0x8C, lgReg->BCLK); 1556d2b10af6Smrg 1557d2b10af6Smrg memww(0x402, lgReg->CONTROL); 1558d2b10af6Smrg 1559d2b10af6Smrg memww(0x200, lgReg->RIFCtrl); 1560d2b10af6Smrg memww(0x202, lgReg->RACCtrl); 156176888252Smrg} 156276888252Smrg 156376888252Smrg/* 156476888252Smrg * Restore the initial (text) mode. 156576888252Smrg */ 156676888252Smrgstatic void 156776888252SmrgLgRestore(ScrnInfoPtr pScrn) 156876888252Smrg{ 1569d2b10af6Smrg vgaHWPtr hwp; 1570d2b10af6Smrg vgaRegPtr vgaReg; 1571d2b10af6Smrg CirPtr pCir; 1572d2b10af6Smrg LgRegPtr lgReg; 157376888252Smrg 157476888252Smrg#ifdef LG_DEBUG 1575d2b10af6Smrg ErrorF("LgRestore pScrn = %p\n", (void *) pScrn); 157676888252Smrg#endif 157776888252Smrg 1578d2b10af6Smrg pCir = CIRPTR(pScrn); 1579d2b10af6Smrg hwp = VGAHWPTR(pScrn); 1580d2b10af6Smrg vgaReg = &hwp->SavedReg; 1581d2b10af6Smrg lgReg = &pCir->chip.lg->SavedReg; 158276888252Smrg 1583d2b10af6Smrg vgaHWProtect(pScrn, TRUE); 158476888252Smrg 1585d2b10af6Smrg LgRestoreLgRegs(pScrn, lgReg); 158676888252Smrg 1587d2b10af6Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1588d2b10af6Smrg vgaHWProtect(pScrn, FALSE); 158976888252Smrg} 159076888252Smrg 1591d2b10af6Smrg/* 1592d2b10af6Smrg * This gets called at the start of each server generation 1593d2b10af6Smrg */ 1594d2b10af6Smrg/* 1595d2b10af6Smrg * Mandatory 1596d2b10af6Smrg */ 159776888252SmrgBool 15985c69f917SmrgLgScreenInit(SCREEN_INIT_ARGS_DECL) 159976888252Smrg{ 1600d2b10af6Smrg /* 1601d2b10af6Smrg * The vgaHW references will disappear one day 1602d2b10af6Smrg */ 1603d2b10af6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1604d2b10af6Smrg vgaHWPtr hwp; 1605d2b10af6Smrg CirPtr pCir; 1606d2b10af6Smrg int i, ret; 1607d2b10af6Smrg VisualPtr visual; 1608d2b10af6Smrg int displayWidth, width, height; 1609d2b10af6Smrg unsigned char * FbBase = NULL; 161076888252Smrg 161176888252Smrg#ifdef LG_DEBUG 1612d2b10af6Smrg ErrorF("LgScreenInit\n"); 161376888252Smrg#endif 161476888252Smrg 1615d2b10af6Smrg hwp = VGAHWPTR(pScrn); 161676888252Smrg 1617d2b10af6Smrg /* 1618d2b10af6Smrg * Standard 64k VGA window 1619d2b10af6Smrg */ 1620d2b10af6Smrg hwp->MapSize = 0x10000; 162176888252Smrg 1622d2b10af6Smrg pCir = CIRPTR(pScrn); 162376888252Smrg 1624d2b10af6Smrg /* 1625d2b10af6Smrg * Map the VGA memory and get the VGA IO base. 1626d2b10af6Smrg */ 1627d2b10af6Smrg if (!vgaHWMapMem(pScrn)) 1628d2b10af6Smrg return FALSE; 162976888252Smrg 1630d2b10af6Smrg /* 1631d2b10af6Smrg * Map the CIR memory and MMIO areas. 1632d2b10af6Smrg */ 1633d2b10af6Smrg if (!CirMapMem(pCir, pScrn->scrnIndex)) 1634d2b10af6Smrg return FALSE; 163576888252Smrg#ifdef EXPERIMENTAL 1636d2b10af6Smrg lg_vgaHWSetMmioFunc(hwp, pCir->IOBase); 163776888252Smrg#endif 1638d2b10af6Smrg vgaHWGetIOBase(hwp); 1639d2b10af6Smrg 1640d2b10af6Smrg /* 1641d2b10af6Smrg * Save the current state. 1642d2b10af6Smrg */ 1643d2b10af6Smrg LgSave(pScrn); 1644d2b10af6Smrg 1645d2b10af6Smrg /* 1646d2b10af6Smrg * Initialise the first mode. 1647d2b10af6Smrg */ 1648d2b10af6Smrg if (!LgModeInit(pScrn, pScrn->currentMode)) 1649d2b10af6Smrg return FALSE; 1650d2b10af6Smrg 1651d2b10af6Smrg /* 1652d2b10af6Smrg * Make things beautiful. 1653d2b10af6Smrg */ 1654d2b10af6Smrg LgSaveScreen(pScreen, SCREEN_SAVER_ON); 1655d2b10af6Smrg 1656d2b10af6Smrg /* 1657d2b10af6Smrg * Set the viewport. 1658d2b10af6Smrg */ 1659d2b10af6Smrg LgAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 1660d2b10af6Smrg pScrn->frameX0, 1661d2b10af6Smrg pScrn->frameY0)); 1662d2b10af6Smrg 1663d2b10af6Smrg /* 1664d2b10af6Smrg * The next step is to setup the screen's visuals, and initialise 1665d2b10af6Smrg * the framebuffer code. In cases where the framebuffer's default 1666d2b10af6Smrg * choices for things like visual layouts and bits per RGB are OK, 1667d2b10af6Smrg * this may be as simple as calling the framebuffer's ScreenInit() 1668d2b10af6Smrg * function. If not, the visuals will need to be setup before 1669d2b10af6Smrg * calling a fb ScreenInit() function and fixed up after. 1670d2b10af6Smrg */ 1671d2b10af6Smrg 1672d2b10af6Smrg /* 1673d2b10af6Smrg * Reset the visual list. 1674d2b10af6Smrg */ 1675d2b10af6Smrg miClearVisualTypes(); 1676d2b10af6Smrg 1677d2b10af6Smrg /* 1678d2b10af6Smrg * Setup the visuals we support. 1679d2b10af6Smrg */ 1680d2b10af6Smrg if (!miSetVisualTypes(pScrn->depth, 1681d2b10af6Smrg miGetDefaultVisualMask(pScrn->depth), 1682d2b10af6Smrg pScrn->rgbBits, 1683d2b10af6Smrg pScrn->defaultVisual)) 1684d2b10af6Smrg return FALSE; 1685d2b10af6Smrg 1686d2b10af6Smrg miSetPixmapDepths(); 168776888252Smrg 1688d2b10af6Smrg#ifdef LG_DEBUG 1689d2b10af6Smrg ErrorF("LgScreenInit after miSetVisualTypes\n"); 1690d2b10af6Smrg#endif 1691d2b10af6Smrg displayWidth = pScrn->displayWidth; 1692d2b10af6Smrg if (pCir->rotate) { 1693d2b10af6Smrg height = pScrn->virtualX; 1694d2b10af6Smrg width = pScrn->virtualY; 1695d2b10af6Smrg } else { 1696d2b10af6Smrg width = pScrn->virtualX; 1697d2b10af6Smrg height = pScrn->virtualY; 1698d2b10af6Smrg } 169976888252Smrg 1700d2b10af6Smrg if (pCir->shadowFB) { 1701d2b10af6Smrg pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 1702d2b10af6Smrg pCir->ShadowPtr = malloc(pCir->ShadowPitch * height); 1703d2b10af6Smrg displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3); 1704d2b10af6Smrg FbBase = pCir->ShadowPtr; 1705d2b10af6Smrg } else { 1706d2b10af6Smrg pCir->ShadowPtr = NULL; 1707d2b10af6Smrg FbBase = pCir->FbBase; 1708d2b10af6Smrg } 170976888252Smrg 1710d2b10af6Smrg /* 1711d2b10af6Smrg * Call the framebuffer layer's ScreenInit function, and fill in 1712d2b10af6Smrg * other pScreen fields. 1713d2b10af6Smrg */ 1714d2b10af6Smrg switch (pScrn->bitsPerPixel) { 1715d2b10af6Smrg case 8: 1716d2b10af6Smrg case 16: 1717d2b10af6Smrg case 24: 1718d2b10af6Smrg case 32: 1719d2b10af6Smrg ret = fbScreenInit(pScreen, FbBase, width, height, 1720d2b10af6Smrg pScrn->xDpi, pScrn->yDpi, 1721d2b10af6Smrg displayWidth, pScrn->bitsPerPixel); 1722d2b10af6Smrg break; 1723d2b10af6Smrg default: 1724d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1725d2b10af6Smrg "X11: Internal error: invalid bpp (%d) in " 1726d2b10af6Smrg "LgScreenInit\n", 1727d2b10af6Smrg pScrn->bitsPerPixel); 1728d2b10af6Smrg ret = FALSE; 1729d2b10af6Smrg break; 1730d2b10af6Smrg } 1731d2b10af6Smrg if (!ret) 1732d2b10af6Smrg return FALSE; 173376888252Smrg 173476888252Smrg#ifdef LG_DEBUG 1735d2b10af6Smrg ErrorF("LgScreenInit after depth dependent init\n"); 173676888252Smrg#endif 173776888252Smrg 1738d2b10af6Smrg /* 1739d2b10af6Smrg * Override the default mask/offset settings. 1740d2b10af6Smrg */ 1741d2b10af6Smrg if (pScrn->bitsPerPixel > 8) { 1742d2b10af6Smrg for (i = 0; i < pScreen->numVisuals; i++) { 1743d2b10af6Smrg visual = &pScreen->visuals[i]; 1744d2b10af6Smrg if ((visual->class | DynamicClass) == DirectColor) { 1745d2b10af6Smrg visual->offsetRed = pScrn->offset.red; 1746d2b10af6Smrg visual->offsetGreen = pScrn->offset.green; 1747d2b10af6Smrg visual->offsetBlue = pScrn->offset.blue; 1748d2b10af6Smrg visual->redMask = pScrn->mask.red; 1749d2b10af6Smrg visual->greenMask = pScrn->mask.green; 1750d2b10af6Smrg visual->blueMask = pScrn->mask.blue; 1751d2b10af6Smrg } 1752d2b10af6Smrg } 1753d2b10af6Smrg } 1754d2b10af6Smrg 1755d2b10af6Smrg /* 1756d2b10af6Smrg * Must be after RGB ordering fixed. 1757d2b10af6Smrg */ 175876888252Smrg 1759d2b10af6Smrg fbPictureInit(pScreen, 0, 0); 1760d2b10af6Smrg 1761d2b10af6Smrg /* 1762d2b10af6Smrg * Set initial black & white colourmap indices. 1763d2b10af6Smrg */ 1764d2b10af6Smrg xf86SetBlackWhitePixels(pScreen); 176576888252Smrg 17665c69f917Smrg#ifdef HAVE_XAA_H 1767d2b10af6Smrg /* 1768d2b10af6Smrg * Initialize XAA functions. 1769d2b10af6Smrg */ 1770d2b10af6Smrg if (!pCir->NoAccel) { 1771d2b10af6Smrg if (!LgXAAInit(pScreen)) 1772d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1773d2b10af6Smrg "Could not initialize XAA\n"); 1774d2b10af6Smrg } 17755c69f917Smrg#endif 177676888252Smrg#if 1 1777d2b10af6Smrg pCir->DGAModeInit = LgModeInit; 1778d2b10af6Smrg if (!CirDGAInit(pScreen)) 1779d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1780d2b10af6Smrg "DGA initialization failed\n"); 178176888252Smrg#endif 1782d2b10af6Smrg xf86SetSilkenMouse(pScreen); 1783d2b10af6Smrg 1784d2b10af6Smrg /* 1785d2b10af6Smrg * Initialise cursor functions. 1786d2b10af6Smrg */ 1787d2b10af6Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1788d2b10af6Smrg 1789d2b10af6Smrg /* 1790d2b10af6Smrg * Initialize HW cursor layer. 1791d2b10af6Smrg */ 1792d2b10af6Smrg if (pCir->HWCursor) { 1793d2b10af6Smrg if (!LgHWCursorInit(pScreen)) 1794d2b10af6Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1795d2b10af6Smrg "Hardware cursor initialization failed\n"); 1796d2b10af6Smrg } 179776888252Smrg 1798d2b10af6Smrg /* 1799d2b10af6Smrg * Initialise default colourmap. 1800d2b10af6Smrg */ 1801d2b10af6Smrg if (!miCreateDefColormap(pScreen)) 1802d2b10af6Smrg return FALSE; 180376888252Smrg 1804d2b10af6Smrg if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8) 1805d2b10af6Smrg vgaHWHandleColormaps(pScreen); 180676888252Smrg 1807d2b10af6Smrg xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 0); 180876888252Smrg 1809d2b10af6Smrg pScrn->memPhysBase = pCir->FbAddress; 1810d2b10af6Smrg pScrn->fbOffset = 0; 181176888252Smrg 1812d2b10af6Smrg { 1813d2b10af6Smrg XF86VideoAdaptorPtr *ptr; 1814d2b10af6Smrg int n; 181576888252Smrg 1816d2b10af6Smrg n = xf86XVListGenericAdaptors(pScrn, &ptr); 1817d2b10af6Smrg if (n) 1818d2b10af6Smrg xf86XVScreenInit(pScreen, ptr, n); 1819d2b10af6Smrg } 182076888252Smrg 1821d2b10af6Smrg /* 1822d2b10af6Smrg * Wrap the CloseScreen vector and set SaveScreen. 1823d2b10af6Smrg */ 1824d2b10af6Smrg pScreen->SaveScreen = LgSaveScreen; 1825d2b10af6Smrg pCir->CloseScreen = pScreen->CloseScreen; 1826d2b10af6Smrg pScreen->CloseScreen = LgCloseScreen; 1827d2b10af6Smrg 1828d2b10af6Smrg /* 1829d2b10af6Smrg * Report any unused options (only for the first generation). 1830d2b10af6Smrg */ 1831d2b10af6Smrg if (serverGeneration == 1) 1832d2b10af6Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1833d2b10af6Smrg 1834d2b10af6Smrg /* 1835d2b10af6Smrg * Done 1836d2b10af6Smrg */ 1837d2b10af6Smrg return TRUE; 183876888252Smrg} 183976888252Smrg 1840d2b10af6Smrg/* 1841d2b10af6Smrg * Usually mandatory 1842d2b10af6Smrg */ 184376888252SmrgBool 18445c69f917SmrgLgSwitchMode(SWITCH_MODE_ARGS_DECL) 184576888252Smrg{ 1846d2b10af6Smrg SCRN_INFO_PTR(arg); 1847d2b10af6Smrg return LgModeInit(pScrn, mode); 184876888252Smrg} 184976888252Smrg 1850d2b10af6Smrg#define ROUND_DOWN(x, mod) (((x) / (mod)) * (mod)) 1851d2b10af6Smrg#define ROUND_UP(x, mod) ((((x) + (mod) - 1) / (mod)) * (mod)) 185276888252Smrg 185376888252Smrg/* 185476888252Smrg * This function is used to initialize the Start Address - the first 185576888252Smrg * displayed location in the video memory. 185676888252Smrg */ 1857d2b10af6Smrg/* 1858d2b10af6Smrg * Usually mandatory 1859d2b10af6Smrg */ 1860d2b10af6Smrgvoid LgAdjustFrame(ADJUST_FRAME_ARGS_DECL) { 1861d2b10af6Smrg SCRN_INFO_PTR(arg); 1862d2b10af6Smrg int Base, tmp; 1863d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 1864d2b10af6Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 1865d2b10af6Smrg int cursorX, cursorY; 1866d2b10af6Smrg int middleX, middleY; 1867d2b10af6Smrg const LgLineDataPtr lineData = 1868d2b10af6Smrg &LgLineData[pCir->chip.lg->lineDataIndex]; 1869d2b10af6Smrg const int viewportXRes = 1870d2b10af6Smrg (PCI_CHIP_GD5465 == pCir->Chipset) ? 1871d2b10af6Smrg (24 == pScrn->bitsPerPixel ? 24 : 1) : 1872d2b10af6Smrg (lineData->width ? 256 : 128) 1873d2b10af6Smrg / (24 == pScrn->bitsPerPixel ? 1874d2b10af6Smrg 1 : (pScrn->bitsPerPixel >> 3)); 1875d2b10af6Smrg const int viewportYRes = 1876d2b10af6Smrg (PCI_CHIP_GD5465 == pCir->Chipset) ? 1877d2b10af6Smrg 1 : (24 == pScrn->bitsPerPixel ? 3 : 1); 1878d2b10af6Smrg 1879d2b10af6Smrg /* 1880d2b10af6Smrg * Where's the pointer? 1881d2b10af6Smrg */ 1882d2b10af6Smrg miPointerGetPosition(inputInfo.pointer, &cursorX, &cursorY); 1883d2b10af6Smrg 1884d2b10af6Smrg /* 1885d2b10af6Smrg * Where's the middle of the screen? We want to eventually know 1886d2b10af6Smrg * which side of the screen the pointer is on. 1887d2b10af6Smrg */ 1888d2b10af6Smrg middleX = (pScrn->frameX1 + pScrn->frameX0) / 2; 1889d2b10af6Smrg middleY = (pScrn->frameY1 + pScrn->frameY0) / 2; 1890d2b10af6Smrg 1891d2b10af6Smrg if (cursorX < middleX) { 1892d2b10af6Smrg /* 1893d2b10af6Smrg * Pointer is on left side of screen. Round the frame value 1894d2b10af6Smrg * down. 1895d2b10af6Smrg */ 1896d2b10af6Smrg pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes); 1897d2b10af6Smrg } else { 1898d2b10af6Smrg /* 1899d2b10af6Smrg * Pointer is on right side of screen. Round the frame value 1900d2b10af6Smrg * up. A side effect of this rounding up is that we might 1901d2b10af6Smrg * expose a part of the screen that's actually on the far 1902d2b10af6Smrg * /left/ of the frame buffer. That's because, although the 1903d2b10af6Smrg * virtual desktop might be an integral number of tiles, the 1904d2b10af6Smrg * display might not. We'll just live with this artifact. 1905d2b10af6Smrg */ 1906d2b10af6Smrg pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes); 1907d2b10af6Smrg } 1908d2b10af6Smrg pScrn->frameX1 = pScrn->frameX0 + 1909d2b10af6Smrg pScrn->currentMode->HDisplay - 1; 1910d2b10af6Smrg 1911d2b10af6Smrg if (cursorY < middleY) { 1912d2b10af6Smrg pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes); 1913d2b10af6Smrg } else { 1914d2b10af6Smrg pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes); 1915d2b10af6Smrg } 1916d2b10af6Smrg pScrn->frameY1 = pScrn->frameY0 + 1917d2b10af6Smrg pScrn->currentMode->VDisplay - 1; 1918d2b10af6Smrg 1919d2b10af6Smrg if (x != pScrn->frameX0 || y != pScrn->frameY0) { 1920d2b10af6Smrg /* 1921d2b10af6Smrg * !!! 1922d2b10af6Smrg */ 1923d2b10af6Smrg /* 1924d2b10af6Smrg * We moved the frame from where xf86SetViewport() placed 1925d2b10af6Smrg * it. If we're using a SW cursor, that's okay -- the 1926d2b10af6Smrg * pointer exists in the framebuffer, and those bits are 1927d2b10af6Smrg * still all aligned. But if we're using a HW cursor, then 1928d2b10af6Smrg * we need to re-align the pointer. Call SetCursorPosition() 1929d2b10af6Smrg * with the appropriate new pointer values, adjusted to be 1930d2b10af6Smrg * wrt the new frame. 1931d2b10af6Smrg */ 1932d2b10af6Smrg x = pScrn->frameX0; 1933d2b10af6Smrg y = pScrn->frameY0; 1934d2b10af6Smrg } 1935d2b10af6Smrg 1936d2b10af6Smrg /* 1937d2b10af6Smrg * ??? Will this work for 1bpp? 1938d2b10af6Smrg */ 1939d2b10af6Smrg Base = (y * lineData->pitch + (x * pScrn->bitsPerPixel / 8)) / 4; 1940d2b10af6Smrg 1941d2b10af6Smrg if ((Base & ~0x000FFFFF) != 0) { 1942d2b10af6Smrg /* 1943d2b10af6Smrg * ??? 1944d2b10af6Smrg */ 1945d2b10af6Smrg ErrorF("X11: Internal error: LgAdjustFrame: cannot handle " 1946d2b10af6Smrg "overflow\n"); 1947d2b10af6Smrg return; 1948d2b10af6Smrg } 1949d2b10af6Smrg 1950d2b10af6Smrg hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF); 1951d2b10af6Smrg hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); 1952d2b10af6Smrg tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2; 1953d2b10af6Smrg tmp |= (Base >> 16) & 0x01; 1954d2b10af6Smrg tmp |= (Base >> 15) & 0x0C; 1955d2b10af6Smrg hwp->writeCrtc(hwp, 0x1B, tmp); 1956d2b10af6Smrg tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7; 1957d2b10af6Smrg tmp |= (Base >> 16) & 0x18; 1958d2b10af6Smrg hwp->writeCrtc(hwp, 0x1D, tmp); 195976888252Smrg} 196076888252Smrg 196176888252Smrg/* 196276888252Smrg * This is called when VT switching back to the X server. Its job is 1963d2b10af6Smrg * to reinitialise the video mode. We may wish to unmap video/MMIO 1964d2b10af6Smrg * memory too. 1965d2b10af6Smrg */ 1966d2b10af6Smrg/* 1967d2b10af6Smrg * Mandatory 196876888252Smrg */ 196976888252SmrgBool 19705c69f917SmrgLgEnterVT(VT_FUNC_ARGS_DECL) 197176888252Smrg{ 1972d2b10af6Smrg SCRN_INFO_PTR(arg); 1973d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 197476888252Smrg#ifdef LG_DEBUG 1975d2b10af6Smrg ErrorF("LgEnterVT\n"); 197676888252Smrg#endif 197776888252Smrg 1978d2b10af6Smrg /* 1979d2b10af6Smrg * XXX Shouldn't this be in LeaveVT? 1980d2b10af6Smrg */ 1981d2b10af6Smrg /* 1982d2b10af6Smrg * Disable HW cursor. 1983d2b10af6Smrg */ 1984d2b10af6Smrg if (pCir->HWCursor) 1985d2b10af6Smrg LgHideCursor(pScrn); 1986d2b10af6Smrg 1987d2b10af6Smrg /* 1988d2b10af6Smrg * Should we re-save the text mode on each VT enter? 1989d2b10af6Smrg */ 1990d2b10af6Smrg return LgModeInit(pScrn, pScrn->currentMode); 199176888252Smrg} 199276888252Smrg 199376888252Smrg/* 1994d2b10af6Smrg * This is called when VT switching away from the X server. Its job 1995d2b10af6Smrg * is to restore the previous (text) mode. We may wish to remap 1996d2b10af6Smrg * video/MMIO memory too. 199776888252Smrg */ 1998d2b10af6Smrg/* 1999d2b10af6Smrg * Mandatory 2000d2b10af6Smrg */ 2001d2b10af6Smrgvoid LgLeaveVT(VT_FUNC_ARGS_DECL) { 2002d2b10af6Smrg SCRN_INFO_PTR(arg); 2003d2b10af6Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2004d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 200576888252Smrg#ifdef LG_DEBUG 2006d2b10af6Smrg ErrorF("LgLeaveVT\n"); 200776888252Smrg#endif 200876888252Smrg 2009d2b10af6Smrg /* 2010d2b10af6Smrg * XXX Shouldn't this be in EnterVT? 2011d2b10af6Smrg */ 2012d2b10af6Smrg /* 2013d2b10af6Smrg * Enable HW cursor. 2014d2b10af6Smrg */ 2015d2b10af6Smrg if (pCir->HWCursor) 2016d2b10af6Smrg LgShowCursor(pScrn); 2017d2b10af6Smrg 2018d2b10af6Smrg LgRestore(pScrn); 2019d2b10af6Smrg vgaHWLock(hwp); 202076888252Smrg} 202176888252Smrg 202276888252Smrg/* 2023d2b10af6Smrg * This is called at the end of each server generation. It restores 2024d2b10af6Smrg * the original (text) mode. It should also unmap the video memory, 2025d2b10af6Smrg * and free any per-generation data allocated by the driver. It 2026d2b10af6Smrg * should finish by unwrapping and calling the saved CloseScreen 2027d2b10af6Smrg * function. 2028d2b10af6Smrg */ 2029d2b10af6Smrg/* 2030d2b10af6Smrg * Mandatory 203176888252Smrg */ 203276888252Smrgstatic Bool 20335c69f917SmrgLgCloseScreen(CLOSE_SCREEN_ARGS_DECL) 203476888252Smrg{ 2035d2b10af6Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2036d2b10af6Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2037d2b10af6Smrg CirPtr pCir = CIRPTR(pScrn); 2038d2b10af6Smrg 2039d2b10af6Smrg if (pScrn->vtSema) { 2040d2b10af6Smrg LgRestore(pScrn); 2041d2b10af6Smrg if (pCir->HWCursor) 2042d2b10af6Smrg LgHideCursor(pScrn); 204376888252Smrg 2044d2b10af6Smrg vgaHWLock(hwp); 204576888252Smrg 2046d2b10af6Smrg CirUnmapMem(pCir, pScrn->scrnIndex); 2047d2b10af6Smrg } 204876888252Smrg 20495c69f917Smrg#ifdef HAVE_XAA_H 2050d2b10af6Smrg if (pCir->AccelInfoRec) 2051d2b10af6Smrg XAADestroyInfoRec(pCir->AccelInfoRec); 2052d2b10af6Smrg pCir->AccelInfoRec = NULL; 20535c69f917Smrg#endif 205476888252Smrg 2055d2b10af6Smrg if (pCir->CursorInfoRec) 2056d2b10af6Smrg xf86DestroyCursorInfoRec(pCir->CursorInfoRec); 2057d2b10af6Smrg pCir->CursorInfoRec = NULL; 2058d2b10af6Smrg if (pCir->DGAModes) 2059d2b10af6Smrg free(pCir->DGAModes); 2060d2b10af6Smrg pCir->DGAnumModes = 0; 2061d2b10af6Smrg pCir->DGAModes = NULL; 206276888252Smrg 2063d2b10af6Smrg pScrn->vtSema = FALSE; 206476888252Smrg 2065d2b10af6Smrg pScreen->CloseScreen = pCir->CloseScreen; 2066d2b10af6Smrg return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 206776888252Smrg} 206876888252Smrg 2069d2b10af6Smrg/* 2070d2b10af6Smrg * Free up any persistent data structures. 2071d2b10af6Smrg */ 2072d2b10af6Smrg/* 2073d2b10af6Smrg * Optional 2074d2b10af6Smrg */ 207576888252Smrgvoid 20765c69f917SmrgLgFreeScreen(FREE_SCREEN_ARGS_DECL) 207776888252Smrg{ 2078d2b10af6Smrg SCRN_INFO_PTR(arg); 207976888252Smrg#ifdef LG_DEBUG 2080d2b10af6Smrg ErrorF("LgFreeScreen\n"); 208176888252Smrg#endif 2082d2b10af6Smrg /* 2083d2b10af6Smrg * This only gets called when a screen is being deleted. It does 2084d2b10af6Smrg * not get called routinely at the end of a server generation. 2085d2b10af6Smrg */ 2086d2b10af6Smrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 2087d2b10af6Smrg vgaHWFreeHWRec(pScrn); 2088d2b10af6Smrg LgFreeRec(pScrn); 208976888252Smrg} 209076888252Smrg 2091d2b10af6Smrg/* 2092d2b10af6Smrg * Checks if a mode is suitable for the selected chipset. 2093d2b10af6Smrg */ 2094d2b10af6Smrg/* 2095d2b10af6Smrg * Optional 2096d2b10af6Smrg */ 209776888252SmrgModeStatus 2098d2b10af6SmrgLgValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 2099d2b10af6Smrg Bool verbose, int flags) 210076888252Smrg{ 2101d2b10af6Smrg int lace; 2102d2b10af6Smrg 2103d2b10af6Smrg lace = 1 + ((mode->Flags & V_INTERLACE) != 0); 2104d2b10af6Smrg 2105d2b10af6Smrg if ((mode->CrtcHDisplay <= 2048) && 2106d2b10af6Smrg (mode->CrtcHSyncStart <= 4096) && 2107d2b10af6Smrg (mode->CrtcHSyncEnd <= 4096) && 2108d2b10af6Smrg (mode->CrtcHTotal <= 4096) && 2109d2b10af6Smrg (mode->CrtcVDisplay <= 2048 * lace) && 2110d2b10af6Smrg (mode->CrtcVSyncStart <= 4096 * lace) && 2111d2b10af6Smrg (mode->CrtcVSyncEnd <= 4096 * lace) && 2112d2b10af6Smrg (mode->CrtcVTotal <= 4096 * lace)) { 2113d2b10af6Smrg return (MODE_OK); 2114d2b10af6Smrg } 2115d2b10af6Smrg return (MODE_BAD); 211676888252Smrg} 211776888252Smrg 2118d2b10af6Smrg/* 2119d2b10af6Smrg * Do screen blanking. 2120d2b10af6Smrg */ 2121d2b10af6Smrg/* 2122d2b10af6Smrg * Mandatory 2123d2b10af6Smrg */ 212476888252Smrgstatic Bool 212576888252SmrgLgSaveScreen(ScreenPtr pScreen, int mode) 212676888252Smrg{ 2127d2b10af6Smrg CirPtr pCir = CIRPTR(xf86ScreenToScrn(pScreen)); 2128d2b10af6Smrg ScrnInfoPtr pScrn = NULL; 2129d2b10af6Smrg Bool unblank; 2130d2b10af6Smrg 2131d2b10af6Smrg unblank = xf86IsUnblank(mode); 2132d2b10af6Smrg 2133d2b10af6Smrg if (pScreen != NULL) 2134d2b10af6Smrg pScrn = xf86ScreenToScrn(pScreen); 2135d2b10af6Smrg 2136d2b10af6Smrg if (pScrn != NULL && pScrn->vtSema) { 2137d2b10af6Smrg if (unblank) 2138d2b10af6Smrg /* 2139d2b10af6Smrg * Power up the palette DAC. 2140d2b10af6Smrg */ 2141d2b10af6Smrg memwb(0xB0, memrb(0xB0) & 0x7F); 2142d2b10af6Smrg else 2143d2b10af6Smrg /* 2144d2b10af6Smrg * Power down the palette DAC. 2145d2b10af6Smrg */ 2146d2b10af6Smrg memwb(0xB0, memrb(0xB0) | 0x80); 2147d2b10af6Smrg } 2148d2b10af6Smrg 2149d2b10af6Smrg return vgaHWSaveScreen(pScreen, mode); 215076888252Smrg} 215176888252Smrg 215276888252Smrgstatic CARD16 215376888252SmrgLgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq) 215476888252Smrg{ 2155d2b10af6Smrg int ffreq, num, den; 2156d2b10af6Smrg CARD8 tmp; 2157d2b10af6Smrg 2158d2b10af6Smrg ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000); 2159d2b10af6Smrg 2160d2b10af6Smrg ffreq = freq; 2161d2b10af6Smrg if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den)) 2162d2b10af6Smrg return 0; 2163d2b10af6Smrg 2164d2b10af6Smrg ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n", 2165d2b10af6Smrg num, den, ffreq / 1000, ffreq % 1000); 2166d2b10af6Smrg 2167d2b10af6Smrg /* 2168d2b10af6Smrg * Set VCLK3. 2169d2b10af6Smrg */ 2170d2b10af6Smrg /* 2171d2b10af6Smrg * The numerator and denominator registers are switched around 2172d2b10af6Smrg * in the Laguna chips. 2173d2b10af6Smrg */ 2174d2b10af6Smrg tmp = hwp->readSeq(hwp, 0x0E); 2175d2b10af6Smrg hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den); 2176d2b10af6Smrg hwp->writeSeq(hwp, 0x1E, num); 2177d2b10af6Smrg 2178d2b10af6Smrg return (den << 8) | num; 217976888252Smrg} 218076888252Smrg 218176888252Smrg/* 2182d2b10af6Smrg * LgDisplayPowerManagementSet -- 218376888252Smrg * 218476888252Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode. 218576888252Smrg */ 218676888252Smrgstatic void 2187d2b10af6SmrgLgDisplayPowerManagementSet(ScrnInfoPtr pScrn, 2188d2b10af6Smrg int PowerManagementMode, 2189d2b10af6Smrg int flags) 219076888252Smrg{ 2191d2b10af6Smrg unsigned char sr01, cr1a; 2192d2b10af6Smrg vgaHWPtr hwp; 219376888252Smrg 219476888252Smrg#ifdef LG_DEBUG 2195d2b10af6Smrg ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode); 219676888252Smrg#endif 219776888252Smrg 2198d2b10af6Smrg hwp = VGAHWPTR(pScrn); 2199d2b10af6Smrg 2200d2b10af6Smrg switch (PowerManagementMode) { 2201d2b10af6Smrg case DPMSModeOn: 2202d2b10af6Smrg /* 2203d2b10af6Smrg * Screen: On; HSync: On, VSync: On 2204d2b10af6Smrg */ 2205d2b10af6Smrg sr01 = 0x00; 2206d2b10af6Smrg cr1a = 0x00; 2207d2b10af6Smrg break; 2208d2b10af6Smrg case DPMSModeStandby: 2209d2b10af6Smrg /* 2210d2b10af6Smrg * Screen: Off; HSync: Off, VSync: On 2211d2b10af6Smrg */ 2212d2b10af6Smrg sr01 = 0x20; 2213d2b10af6Smrg cr1a = 0x08; 2214d2b10af6Smrg break; 2215d2b10af6Smrg case DPMSModeSuspend: 2216d2b10af6Smrg /* 2217d2b10af6Smrg * Screen: Off; HSync: On, VSync: Off 2218d2b10af6Smrg */ 2219d2b10af6Smrg sr01 = 0x20; 2220d2b10af6Smrg cr1a = 0x04; 2221d2b10af6Smrg break; 2222d2b10af6Smrg case DPMSModeOff: 2223d2b10af6Smrg /* 2224d2b10af6Smrg * Screen: Off; HSync: Off, VSync: Off 2225d2b10af6Smrg */ 2226d2b10af6Smrg sr01 = 0x20; 2227d2b10af6Smrg cr1a = 0x0c; 2228d2b10af6Smrg break; 2229d2b10af6Smrg default: 2230d2b10af6Smrg return; 2231d2b10af6Smrg } 2232d2b10af6Smrg 2233d2b10af6Smrg sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 2234d2b10af6Smrg hwp->writeSeq(hwp, 0x01, sr01); 2235d2b10af6Smrg cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C; 2236d2b10af6Smrg hwp->writeCrtc(hwp, 0x1A, cr1a); 223776888252Smrg} 223876888252Smrg 223976888252Smrg#define minb(p) MMIO_IN8(hwp->MMIOBase, (p)) 224076888252Smrg#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v)) 224176888252Smrg 224276888252Smrgstatic void 224376888252SmrgmmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) 224476888252Smrg{ 2245d2b10af6Smrg moutb(index << 2, value); 224676888252Smrg} 224776888252Smrg 224876888252Smrgstatic CARD8 224976888252SmrgmmioReadCrtc(vgaHWPtr hwp, CARD8 index) 225076888252Smrg{ 2251d2b10af6Smrg return minb(index << 2); 225276888252Smrg} 225376888252Smrg 225476888252Smrgstatic void 225576888252Smrglg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base) 225676888252Smrg{ 2257d2b10af6Smrg hwp->writeCrtc = mmioWriteCrtc; 2258d2b10af6Smrg hwp->readCrtc = mmioReadCrtc; 2259d2b10af6Smrg hwp->MMIOBase = base; 2260d2b10af6Smrg hwp->MMIOOffset = 0; 226176888252Smrg} 2262