lg_driver.c revision 1ae1b5e8
1/*
2 * Driver for CL-GD546x -- The Laguna family
3 *
4 * lg_driver.c
5 *
6 * (c) 1998 Corin Anderson.
7 *          corina@the4cs.com
8 *          Tukwila, WA
9 *
10 * This driver is derived from the cir_driver.c module.
11 * Original authors and contributors list include:
12 *	Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel,
13 *	David Dawes, Andrew E. Mileski, Leonard N. Zubkoff,
14 *	Guy DESBIEF, Itai Nahshon.
15 */
16/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_driver.c,v 1.49 2003/11/03 05:11:09 tsi Exp $ */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#define EXPERIMENTAL
23
24/* All drivers should typically include these */
25#include "xf86.h"
26#include "xf86_OSproc.h"
27
28/* All drivers need this */
29
30#include "compiler.h"
31
32/* Drivers for PCI hardware need this */
33#include "xf86PciInfo.h"
34
35/* Drivers that need to access the PCI config space directly need this */
36#include "xf86Pci.h"
37
38/* All drivers using the vgahw module need this */
39/* This driver needs to be modified to not use vgaHW for multihead operation */
40#include "vgaHW.h"
41
42#include "xf86RAC.h"
43#include "xf86Resources.h"
44
45/* All drivers initialising the SW cursor need this */
46#include "mipointer.h"
47
48/* All drivers implementing backing store need this */
49#include "mibstore.h"
50
51#include "micmap.h"
52
53/* Needed by the Shadow Framebuffer */
54#include "shadowfb.h"
55
56#include "xf86int10.h"
57
58#include "fb.h"
59
60#include "xf86DDC.h"
61
62#undef LG_DEBUG
63
64#include "cir.h"
65#define _LG_PRIVATE_
66#include "lg.h"
67
68#include "xf86xv.h"
69#include <X11/extensions/Xv.h>
70
71/*
72 * Forward definitions for the functions that make up the driver.
73 */
74
75/* Mandatory functions */
76Bool LgPreInit(ScrnInfoPtr pScrn, int flags);
77Bool LgScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
78Bool LgEnterVT(int scrnIndex, int flags);
79void LgLeaveVT(int scrnIndex, int flags);
80static Bool	LgCloseScreen(int scrnIndex, ScreenPtr pScreen);
81static Bool	LgSaveScreen(ScreenPtr pScreen, Bool mode);
82
83/* Required if the driver supports mode switching */
84Bool LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
85/* Required if the driver supports moving the viewport */
86void LgAdjustFrame(int scrnIndex, int x, int y, int flags);
87
88/* Optional functions */
89void LgFreeScreen(int scrnIndex, int flags);
90ModeStatus LgValidMode(int scrnIndex, DisplayModePtr mode,
91		       Bool verbose, int flags);
92
93/* Internally used functions */
94static void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg);
95static int LgFindLineData(int displayWidth, int bpp);
96static CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq);
97static void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base);
98
99static void LgDisplayPowerManagementSet(ScrnInfoPtr pScrn,
100				        int PowerManagementMode, int flags);
101
102/*
103 * This is intentionally screen-independent.  It indicates the binding
104 * choice made in the first PreInit.
105 */
106static int pix24bpp = 0;
107
108/*
109 * This contains the functions needed by the server after loading the
110 * driver module.  It must be supplied, and gets added the driver list by
111 * the Module Setup funtion in the dynamic case.  In the static case a
112 * reference to this is compiled in, and this requires that the name of
113 * this DriverRec be an upper-case version of the driver name.
114 */
115
116typedef enum {
117	OPTION_HW_CURSOR,
118	OPTION_PCI_RETRY,
119	OPTION_ROTATE,
120	OPTION_SHADOW_FB,
121	OPTION_NOACCEL
122} LgOpts;
123
124static const OptionInfoRec LgOptions[] = {
125    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
126    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
127    { OPTION_SHADOW_FB,         "ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
128    { OPTION_ROTATE, 	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
129    /* fifo_conservative/aggressive; fast/med/slow_dram; ... */
130    { -1,					NULL,		OPTV_NONE,		{0}, FALSE }
131};
132
133
134/*                                1/4bpp   8bpp   15/16bpp  24bpp  32bpp */
135static int gd5462_MaxClocks[] = { 170000, 170000, 135100, 135100,  85500 };
136static int gd5464_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
137static int gd5465_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
138
139LgLineDataRec LgLineData[] = {
140	{ 5,  640, 0},		/* We're rather use skinny tiles, so put all of */
141	{ 8, 1024, 0},		/* them at the head of the table */
142	{10, 1280, 0},
143	{13, 1664, 0},
144	{16, 2048, 0},
145	{20, 2560, 0},
146	{10, 2560, 1},
147	{26, 3328, 0},
148	{ 5, 1280, 1},
149	{ 8, 2048, 1},
150	{13, 3328, 1},
151	{16, 4096, 1},
152	{20, 5120, 1},
153	{26, 6656, 1},
154	{-1, -1, -1}		/* Sentinal to indicate end of table */
155};
156
157static int LgLinePitches[4][11] = {
158	/*  8 */ { 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 },
159	/* 16 */ { 320,  512,  640,  832, 1024, 1280, 1664, 2048, 2560, 3328, 0 },
160	/* 24 */ { 213,  341,  426,  554,  682,  853, 1109, 1365, 1706, 2218, 0 },
161	/* 32 */ { 160,  256,  320,  416,  512,  640,  832, 1024, 1280, 1664, 0 }
162};
163
164/*
165 * List of symbols from other modules that this module references.  This
166 * list is used to tell the loader that it is OK for symbols here to be
167 * unresolved providing that it hasn't been told that they haven't been
168 * told that they are essential via a call to xf86LoaderReqSymbols() or
169 * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
170 * unresolved symbols that are not required.
171 */
172
173static const char *vgahwSymbols[] = {
174	"vgaHWFreeHWRec",
175	"vgaHWGetHWRec",
176	"vgaHWGetIOBase",
177	"vgaHWGetIndex",
178	"vgaHWHandleColormaps",
179	"vgaHWInit",
180	"vgaHWLock",
181	"vgaHWMapMem",
182	"vgaHWProtect",
183	"vgaHWRestore",
184	"vgaHWSave",
185	"vgaHWSaveScreen",
186	"vgaHWUnlock",
187	NULL
188};
189
190static const char *fbSymbols[] = {
191	"fbScreenInit",
192	"fbPictureInit",
193	NULL
194};
195
196static const char *xaaSymbols[] = {
197	"XAACreateInfoRec",
198	"XAADestroyInfoRec",
199	"XAAInit",
200	NULL
201};
202
203static const char *ramdacSymbols[] = {
204	"xf86CreateCursorInfoRec",
205	"xf86DestroyCursorInfoRec",
206	"xf86InitCursor",
207	NULL
208};
209
210#define LGuseI2C 1
211
212static const char *ddcSymbols[] = {
213	"xf86PrintEDID",
214#if LGuseI2C
215	"xf86DoEDID_DDC2",
216#endif
217	"xf86SetDDCproperties",
218	NULL
219};
220
221static const char *i2cSymbols[] = {
222	"xf86CreateI2CBusRec",
223	"xf86I2CBusInit",
224	NULL
225};
226
227static const char *int10Symbols[] = {
228	"xf86FreeInt10",
229	"xf86InitInt10",
230	NULL
231};
232
233static const char *shadowSymbols[] = {
234    "ShadowFBInit",
235    NULL
236};
237
238#ifdef XFree86LOADER
239
240#define LG_MAJOR_VERSION 1
241#define LG_MINOR_VERSION 0
242#define LG_PATCHLEVEL 0
243
244static MODULESETUPPROTO(lgSetup);
245
246static XF86ModuleVersionInfo lgVersRec =
247{
248	"cirrus_laguna",
249	MODULEVENDORSTRING,
250	MODINFOSTRING1,
251	MODINFOSTRING2,
252	XORG_VERSION_CURRENT,
253	LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_PATCHLEVEL,
254	ABI_CLASS_VIDEODRV,			/* This is a video driver */
255	ABI_VIDEODRV_VERSION,
256	MOD_CLASS_NONE,
257	{0,0,0,0}
258};
259
260/*
261 * This is the module init data.
262 * Its name has to be the driver name followed by ModuleData.
263 */
264_X_EXPORT XF86ModuleData cirrus_lagunaModuleData = {
265    &lgVersRec,
266    lgSetup,
267    NULL
268};
269
270static pointer
271lgSetup(pointer module, pointer opts, int *errmaj, int *errmin)
272{
273    static Bool setupDone = FALSE;
274
275    if (!setupDone) {
276	setupDone = TRUE;
277	LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
278			  ramdacSymbols, ddcSymbols, i2cSymbols,
279			  int10Symbols, NULL);
280    }
281    return (pointer)1;
282}
283
284#endif /* XFree86LOADER */
285
286_X_EXPORT const OptionInfoRec *
287LgAvailableOptions(int chipid)
288{
289    return LgOptions;
290}
291
292_X_EXPORT ScrnInfoPtr
293LgProbe(int entity)
294{
295    ScrnInfoPtr pScrn = NULL;
296    if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets,
297					   NULL, NULL, NULL, NULL, NULL))) {
298	pScrn->PreInit		= LgPreInit;
299	pScrn->ScreenInit	= LgScreenInit;
300	pScrn->SwitchMode	= LgSwitchMode;
301	pScrn->AdjustFrame	= LgAdjustFrame;
302	pScrn->EnterVT		= LgEnterVT;
303	pScrn->LeaveVT		= LgLeaveVT;
304	pScrn->FreeScreen	= LgFreeScreen;
305	pScrn->ValidMode	= LgValidMode;
306    }
307    return pScrn;
308}
309
310
311static Bool
312LgGetRec(ScrnInfoPtr pScrn)
313{
314	CirPtr pCir;
315
316	if (pScrn->driverPrivate != NULL)
317		return TRUE;
318
319	pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1);
320	((CirPtr)pScrn->driverPrivate)->chip.lg = xnfcalloc(sizeof(LgRec),1);
321
322	/* Initialize it */
323	pCir = CIRPTR(pScrn);
324	pCir->chip.lg->oldBitmask = 0x00000000;
325
326	return TRUE;
327}
328
329static void
330LgFreeRec(ScrnInfoPtr pScrn)
331{
332	if (pScrn->driverPrivate == NULL)
333		return;
334	xfree(pScrn->driverPrivate);
335	pScrn->driverPrivate = NULL;
336}
337
338
339
340/*
341 * LgCountRAM --
342 *
343 * Counts amount of installed RAM
344 */
345
346/* XXX We need to get rid of this PIO (MArk) */
347static int
348LgCountRam(ScrnInfoPtr pScrn)
349{
350	vgaHWPtr hwp = VGAHWPTR(pScrn);
351	CARD8 SR14;
352
353	vgaHWProtect(pScrn, TRUE);
354
355	/* The ROM BIOS scratchpad registers contain,
356	   among other things, the amount of installed
357	   RDRAM on the laguna chip. */
358	SR14 = hwp->readSeq(hwp, 0x14);
359
360	ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n",
361		hwp->readSeq(hwp, 9), hwp->readSeq(hwp, 10),
362		SR14, hwp->readSeq(hwp, 0x15));
363
364	vgaHWProtect(pScrn, FALSE);
365
366	return 1024 * ((SR14&0x7) + 1);
367
368	/* !!! This function seems to be incorrect... */
369}
370
371static xf86MonPtr
372LgDoDDC(ScrnInfoPtr pScrn)
373{
374	CirPtr pCir = CIRPTR(pScrn);
375	xf86MonPtr MonInfo = NULL;
376
377	/* Map the CIR memory and MMIO areas */
378	if (!CirMapMem(pCir, pScrn->scrnIndex))
379		return FALSE;
380
381#if LGuseI2C
382	if (!LgI2CInit(pScrn)) {
383		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed\n");
384
385		goto unmap_out;
386	}
387
388	/* Read and output monitor info using DDC2 over I2C bus */
389	MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pCir->I2CPtr1);
390	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n",
391		   (void *)MonInfo);
392	xf86PrintEDID(MonInfo);
393	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n\n");
394#endif /* LGuseI2C */
395
396	xf86SetDDCproperties(pScrn, MonInfo);
397
398unmap_out:
399	CirUnmapMem(pCir, pScrn->scrnIndex);
400
401	return MonInfo;
402}
403
404/* Mandatory */
405Bool
406LgPreInit(ScrnInfoPtr pScrn, int flags)
407{
408	CirPtr pCir;
409	vgaHWPtr hwp;
410	MessageType from;
411	int i;
412	ClockRangePtr clockRanges;
413	int fbPCIReg, ioPCIReg;
414	char *s;
415
416	if (flags & PROBE_DETECT)  {
417	  cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
418	  return TRUE;
419	}
420
421#ifdef LG_DEBUG
422	ErrorF("LgPreInit\n");
423#endif
424
425	/* Check the number of entities, and fail if it isn't one. */
426	if (pScrn->numEntities != 1)
427		return FALSE;
428
429	/* The vgahw module should be loaded here when needed */
430	if (!xf86LoadSubModule(pScrn, "vgahw"))
431		return FALSE;
432
433	xf86LoaderReqSymLists(vgahwSymbols, NULL);
434
435	/*
436	 * Allocate a vgaHWRec
437	 */
438	if (!vgaHWGetHWRec(pScrn))
439		return FALSE;
440
441	hwp = VGAHWPTR(pScrn);
442	vgaHWGetIOBase(hwp);
443
444	/* Allocate the LgRec driverPrivate */
445	if (!LgGetRec(pScrn))
446		return FALSE;
447
448	pCir = CIRPTR(pScrn);
449	pCir->pScrn = pScrn;
450	pCir->PIOReg = hwp->PIOOffset + 0x3CE;
451
452	/* Get the entity, and make sure it is PCI. */
453	pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
454	if (pCir->pEnt->location.type != BUS_PCI)
455		return FALSE;
456	pCir->Chipset = pCir->pEnt->chipset;
457
458	/* Find the PCI info for this screen */
459	pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index);
460	pCir->PciTag = pciTag(PCI_DEV_BUS(pCir->PciInfo),
461			      PCI_DEV_DEV(pCir->PciInfo),
462			      PCI_DEV_FUNC(pCir->PciInfo));
463
464	if (xf86LoadSubModule(pScrn, "int10")) {
465	    xf86Int10InfoPtr int10InfoPtr;
466	    xf86LoaderReqSymLists(int10Symbols, NULL);
467
468	    int10InfoPtr = xf86InitInt10(pCir->pEnt->index);
469
470	    if (int10InfoPtr)
471		xf86FreeInt10(int10InfoPtr);
472	}
473
474	/* Set pScrn->monitor */
475	pScrn->monitor = pScrn->confScreen->monitor;
476
477	/*
478	 * The first thing we should figure out is the depth, bpp, etc.
479	 * We support both 24bpp and 32bpp layouts, so indicate that.
480	 */
481	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
482							SupportConvert32to24 | PreferConvert32to24)) {
483		return FALSE;
484    }
485	/* Check that the returned depth is one we support */
486	switch (pScrn->depth) {
487	case 8:
488	case 15:
489	case 16:
490	case 24:
491	case 32:
492		/* OK */
493		break;
494	default:
495		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
496			"Given depth (%d) is not supported by this driver\n", pScrn->depth);
497		return FALSE;
498	}
499	xf86PrintDepthBpp(pScrn);
500
501	/* Get the depth24 pixmap format */
502	if (pScrn->depth == 24 && pix24bpp == 0)
503		pix24bpp = xf86GetBppFromDepth(pScrn, 24);
504
505	/*
506	 * This must happen after pScrn->display has been set because
507	 * xf86SetWeight references it.
508	 */
509	if (pScrn->depth > 8) {
510		/* The defaults are OK for us */
511		rgb zeros = {0, 0, 0};
512
513		/* !!! I think we can force 5-6-5 weight for 16bpp here for
514		   the 5462. */
515
516		if (!xf86SetWeight(pScrn, zeros, zeros)) {
517			return FALSE;
518		} else {
519			/* XXX check that weight returned is supported */
520			;
521		}
522	}
523
524	if (!xf86SetDefaultVisual(pScrn, -1))
525		return FALSE;
526
527
528	/* Collect all of the relevant option flags (fill in pScrn->options) */
529	xf86CollectOptions(pScrn, NULL);
530
531	/* Process the options */
532	if (!(pCir->Options = xalloc(sizeof(LgOptions))))
533		return FALSE;
534	memcpy(pCir->Options, LgOptions, sizeof(LgOptions));
535	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options);
536
537	pScrn->rgbBits = 6;
538	from = X_DEFAULT;
539	pCir->HWCursor = FALSE;
540	if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, &pCir->HWCursor))
541		from = X_CONFIG;
542
543	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
544		pCir->HWCursor ? "HW" : "SW");
545	if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) {
546		pCir->NoAccel = TRUE;
547		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
548	}
549	if (pScrn->bitsPerPixel < 8) {
550		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
551			"Cannot use in less than 8 bpp\n");
552		return FALSE;
553	}
554	/*
555	 * Set the ChipRev, allowing config file entries to
556	 * override.
557	 */
558	if (pCir->pEnt->device->chipRev >= 0) {
559		pCir->ChipRev = pCir->pEnt->device->chipRev;
560		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
561			pCir->ChipRev);
562	} else {
563	        pCir->ChipRev = PCI_DEV_REVISION(pCir->PciInfo);
564	}
565
566	/* Cirrus swapped the FB and IO registers in the 5465 (by design). */
567	if (PCI_CHIP_GD5465 == pCir->Chipset) {
568		fbPCIReg = 0;
569		ioPCIReg = 1;
570	} else {
571		fbPCIReg = 1;
572		ioPCIReg = 0;
573	}
574
575	/* Find the frame buffer base address */
576	if (pCir->pEnt->device->MemBase != 0) {
577		/* Require that the config file value matches one of the PCI values. */
578		if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->MemBase)) {
579			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
580				"MemBase 0x%08lX doesn't match any PCI base register.\n",
581				pCir->pEnt->device->MemBase);
582			return FALSE;
583		}
584		pCir->FbAddress = pCir->pEnt->device->MemBase;
585		from = X_CONFIG;
586	} else {
587		if (PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) != 0) {
588			pCir->FbAddress = PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) & 0xff000000;
589			from = X_PROBED;
590		} else {
591			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
592				"No valid FB address in PCI config space\n");
593			LgFreeRec(pScrn);
594			return FALSE;
595		}
596	}
597	xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
598		(unsigned long)pCir->FbAddress);
599
600	/* Find the MMIO base address */
601	if (pCir->pEnt->device->IOBase != 0) {
602		/* Require that the config file value matches one of the PCI values. */
603		if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->IOBase)) {
604			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
605				"IOBase 0x%08lX doesn't match any PCI base register.\n",
606				pCir->pEnt->device->IOBase);
607			return FALSE;
608		}
609		pCir->IOAddress = pCir->pEnt->device->IOBase;
610		from = X_CONFIG;
611	} else {
612		if (PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) != 0) {
613			pCir->IOAddress = PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) & 0xfffff000;
614			from = X_PROBED;
615		} else {
616			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
617			"No valid MMIO address in PCI config space\n");
618		}
619	}
620	xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
621		(unsigned long)pCir->IOAddress);
622
623	/*
624	 * If the user has specified the amount of memory in the XF86Config
625	 * file, we respect that setting.
626	 */
627	if (pCir->pEnt->device->videoRam != 0) {
628		pScrn->videoRam = pCir->pEnt->device->videoRam;
629		from = X_CONFIG;
630	} else {
631		pScrn->videoRam = LgCountRam(pScrn);
632		from = X_PROBED;
633	}
634	if (2048 == pScrn->videoRam) {
635		/* Two-way interleaving */
636		pCir->chip.lg->memInterleave = 0x40;
637	} else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) {
638		/* Four-way interleaving */
639		pCir->chip.lg->memInterleave = 0x80;
640	} else {
641		/* One-way interleaving */
642		pCir->chip.lg->memInterleave = 0x00;
643	}
644
645	xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
646				pScrn->videoRam);
647
648	pCir->FbMapSize = pScrn->videoRam * 1024;
649	pCir->IoMapSize = 0x4000;	/* 16K for moment,  will increase */
650
651	pScrn->racIoFlags =   RAC_COLORMAP
652#ifndef EXPERIMENTAL
653	  | RAC_VIEWPORT
654#endif
655;
656 	xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr);
657
658	/* Register the PCI-assigned resources. */
659	if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) {
660		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
661			"xf86RegisterResources() found resource conflicts\n");
662		return FALSE;
663	}
664
665	if (!xf86LoadSubModule(pScrn, "ddc")) {
666		LgFreeRec(pScrn);
667		return FALSE;
668	}
669	xf86LoaderReqSymLists(ddcSymbols, NULL);
670
671#if LGuseI2C
672	if (!xf86LoadSubModule(pScrn, "i2c")) {
673		LgFreeRec(pScrn);
674		return FALSE;
675	}
676	xf86LoaderReqSymLists(i2cSymbols, NULL);
677#endif
678
679	/* Read and print the monitor DDC information */
680	pScrn->monitor->DDC = LgDoDDC(pScrn);
681
682	/* The gamma fields must be initialised when using the new cmap code */
683	if (pScrn->depth > 1) {
684		Gamma zeros = {0.0, 0.0, 0.0};
685
686		if (!xf86SetGamma(pScrn, zeros))
687			return FALSE;
688	}
689	if (xf86GetOptValBool(pCir->Options,
690			      OPTION_SHADOW_FB,&pCir->shadowFB))
691	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
692		       pCir->shadowFB ? "enabled" : "disabled");
693
694	if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) {
695	    if(!xf86NameCmp(s, "CW")) {
696		/* accel is disabled below for shadowFB */
697		pCir->shadowFB = TRUE;
698		pCir->rotate = 1;
699		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
700			   "Rotating screen clockwise - acceleration disabled\n");
701	    } else if(!xf86NameCmp(s, "CCW")) {
702		pCir->shadowFB = TRUE;
703		pCir->rotate = -1;
704		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
705			   "counter clockwise - acceleration disabled\n");
706	    } else {
707		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
708			   "value for Option \"Rotate\"\n", s);
709		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
710			   "Valid options are \"CW\" or \"CCW\"\n");
711	    }
712	}
713
714	if (pCir->shadowFB && !pCir->NoAccel) {
715	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
716		       "HW acceleration not supported with \"shadowFB\".\n");
717	    pCir->NoAccel = TRUE;
718	}
719
720	if (pCir->rotate && pCir->HWCursor) {
721	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
722		       "HW cursor not supported with \"rotate\".\n");
723	    pCir->HWCursor = FALSE;
724	}
725
726	/* We use a programmable clock */
727	pScrn->progClock = TRUE;
728
729	/* XXX Set HW cursor use */
730
731	/* Set the min pixel clock */
732	pCir->MinClock = 12000;	/* XXX Guess, need to check this */
733	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
734				pCir->MinClock / 1000);
735	/*
736	 * If the user has specified ramdac speed in the XF86Config
737	 * file, we respect that setting.
738	 */
739	if (pCir->pEnt->device->dacSpeeds[0]) {
740		ErrorF("Do not specify a Clocks line for Cirrus chips\n");
741		return FALSE;
742	} else {
743		int speed;
744		int *p;
745		switch (pCir->Chipset) {
746		case PCI_CHIP_GD5462:
747			p = gd5462_MaxClocks;
748			break;
749		case PCI_CHIP_GD5464:
750		case PCI_CHIP_GD5464BD:
751			p = gd5464_MaxClocks;
752			break;
753		case PCI_CHIP_GD5465:
754			p = gd5465_MaxClocks;
755			break;
756		default:
757			ErrorF("???\n");
758			return FALSE;
759		}
760		switch (pScrn->bitsPerPixel) {
761		case 8:
762			speed = p[1];
763			break;
764		case 15:
765		case 16:
766			speed = p[2];
767			break;
768		case 24:
769			speed = p[3];
770			break;
771		case 32:
772			speed = p[4];
773			break;
774		default:
775			/* Should not get here */
776			speed = 0;
777			break;
778		}
779		pCir->MaxClock = speed;
780		from = X_PROBED;
781	}
782	xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
783				pCir->MaxClock / 1000);
784
785	/*
786	 * Setup the ClockRanges, which describe what clock ranges are available,
787	 * and what sort of modes they can be used for.
788	 */
789	clockRanges = xnfcalloc(sizeof(ClockRange), 1);
790	clockRanges->next = NULL;
791	clockRanges->minClock = pCir->MinClock;
792	clockRanges->maxClock = pCir->MaxClock;
793	clockRanges->clockIndex = -1;		/* programmable */
794	clockRanges->interlaceAllowed = FALSE;	/* XXX check this */
795	clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
796	clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
797	clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
798	clockRanges->ClockMulFactor = 1;
799	clockRanges->ClockDivFactor = 1;
800	clockRanges->PrivFlags = 0;
801
802	/* Depending upon what sized tiles used, either 128 or 256. */
803	/* Aw, heck.  Just say 128. */
804	pCir->Rounding = 128 >> pCir->BppShift;
805
806	/*
807	 * xf86ValidateModes will check that the mode HTotal and VTotal values
808	 * don't exceed the chipset's limit if pScrn->maxHValue and
809	 * pScrn->maxVValue are set.  Since our CIRValidMode() already takes
810	 * care of this, we don't worry about setting them here.
811	 */
812
813	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
814							clockRanges,
815							LgLinePitches[pScrn->bitsPerPixel / 8 - 1],
816							0, 0, 128 * 8,
817							0, 0, /* Any virtual height is allowed. */
818							pScrn->display->virtualX,
819							pScrn->display->virtualY,
820							pCir->FbMapSize,
821							LOOKUP_BEST_REFRESH);
822
823	pCir->chip.lg->lineDataIndex = LgFindLineData(pScrn->displayWidth,
824										pScrn->bitsPerPixel);
825
826	if (i == -1) {
827		LgFreeRec(pScrn);
828		return FALSE;
829	}
830
831	/* Prune the modes marked as invalid */
832	xf86PruneDriverModes(pScrn);
833
834	if (i == 0 || pScrn->modes == NULL) {
835		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
836		LgFreeRec(pScrn);
837		return FALSE;
838	}
839
840	/*
841	 * Set the CRTC parameters for all of the modes based on the type
842	 * of mode, and the chipset's interlace requirements.
843	 *
844	 * Calling this is required if the mode->Crtc* values are used by the
845	 * driver and if the driver doesn't provide code to set them.  They
846	 * are not pre-initialised at all.
847	 */
848	xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
849
850	/* Set the current mode to the first in the list */
851	pScrn->currentMode = pScrn->modes;
852
853	/* Print the list of modes being used */
854	xf86PrintModes(pScrn);
855
856	/* Set display resolution */
857	xf86SetDpi(pScrn, 0, 0);
858
859	/* Load bpp-specific modules */
860	switch (pScrn->bitsPerPixel) {
861	case 8:
862	case 16:
863	case 24:
864	case 32:
865	    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
866	         LgFreeRec(pScrn);
867		 return FALSE;
868	    }
869	    xf86LoaderReqSymLists(fbSymbols, NULL);
870	    break;
871	}
872
873	/* Load XAA if needed */
874	if (!pCir->NoAccel) {
875		if (!xf86LoadSubModule(pScrn, "xaa")) {
876			LgFreeRec(pScrn);
877			return FALSE;
878		}
879		xf86LoaderReqSymLists(xaaSymbols, NULL);
880	}
881
882	/* Load ramdac if needed */
883	if (pCir->HWCursor) {
884		if (!xf86LoadSubModule(pScrn, "ramdac")) {
885			LgFreeRec(pScrn);
886			return FALSE;
887		}
888		xf86LoaderReqSymLists(ramdacSymbols, NULL);
889	}
890
891	if (pCir->shadowFB) {
892	    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
893		LgFreeRec(pScrn);
894		return FALSE;
895	    }
896	    xf86LoaderReqSymLists(shadowSymbols, NULL);
897	}
898
899	return TRUE;
900}
901
902/*
903 * This function saves the video state.
904 */
905static void
906LgSave(ScrnInfoPtr pScrn)
907{
908	CirPtr pCir = CIRPTR(pScrn);
909	vgaHWPtr hwp = VGAHWPTR(pScrn);
910
911#ifdef LG_DEBUG
912	ErrorF("LgSave\n");
913#endif
914
915	vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL);
916
917	pCir->chip.lg->ModeReg.ExtVga[CR1A] = pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A);
918	pCir->chip.lg->ModeReg.ExtVga[CR1B] = pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B);
919	pCir->chip.lg->ModeReg.ExtVga[CR1D] = pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D);
920	pCir->chip.lg->ModeReg.ExtVga[CR1E] = pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E);
921	pCir->chip.lg->ModeReg.ExtVga[SR07] = pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07);
922	pCir->chip.lg->ModeReg.ExtVga[SR0E] = pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E);
923	pCir->chip.lg->ModeReg.ExtVga[SR12] = pCir->chip.lg->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12);
924	pCir->chip.lg->ModeReg.ExtVga[SR13] = pCir->chip.lg->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13);
925	pCir->chip.lg->ModeReg.ExtVga[SR1E] = pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E);
926
927	pCir->chip.lg->ModeReg.FORMAT = pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0);
928
929	pCir->chip.lg->ModeReg.VSC = pCir->chip.lg->SavedReg.VSC = memrl(0x3FC);
930
931	pCir->chip.lg->ModeReg.DTTC = pCir->chip.lg->SavedReg.DTTC = memrw(0xEA);
932
933	if (pCir->Chipset == PCI_CHIP_GD5465) {
934	    pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4);
935	}
936
937	pCir->chip.lg->ModeReg.TILE = pCir->chip.lg->SavedReg.TILE = memrb(0x407);
938
939	if (pCir->Chipset == PCI_CHIP_GD5465)
940	    pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0);
941	else
942	    pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x8C);
943
944	pCir->chip.lg->ModeReg.CONTROL = pCir->chip.lg->SavedReg.CONTROL = memrw(0x402);
945}
946
947/*
948 * Initialise a new mode.  This is currently still using the old
949 * "initialise struct, restore/write struct to HW" model.  That could
950 * be changed.
951 */
952
953static Bool
954LgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
955{
956	vgaHWPtr hwp;
957	CirPtr pCir;
958	int width;
959	Bool VDiv2 = FALSE;
960	CARD16 clockData;
961	LgLineDataPtr lineData;
962
963#ifdef LG_DEBUG
964	ErrorF("LgModeInit %d bpp,   %d   %d %d %d %d   %d %d %d %d\n",
965				pScrn->bitsPerPixel,
966				mode->Clock,
967				mode->HDisplay,
968				mode->HSyncStart,
969				mode->HSyncEnd,
970				mode->HTotal,
971				mode->VDisplay,
972				mode->VSyncStart,
973				mode->VSyncEnd,
974				mode->VTotal);
975
976	ErrorF("LgModeInit: depth %d bits\n", pScrn->depth);
977#endif
978
979	pCir = CIRPTR(pScrn);
980	hwp = VGAHWPTR(pScrn);
981	vgaHWUnlock(hwp);
982
983	if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) {
984		/* For non-interlaced vertical timing >= 1024, the vertical timings */
985		/* are divided by 2 and VGA CRTC 0x17 bit 2 is set. */
986		if (!mode->CrtcVAdjusted) {
987			mode->CrtcVDisplay >>= 1;
988			mode->CrtcVSyncStart >>= 1;
989			mode->CrtcVSyncEnd >>= 1;
990			mode->CrtcVTotal >>= 1;
991			mode->CrtcVAdjusted = TRUE;
992		}
993		VDiv2 = TRUE;
994	}
995
996	/* Initialise the ModeReg values */
997	if (!vgaHWInit(pScrn, mode))
998		return FALSE;
999	pScrn->vtSema = TRUE;
1000
1001	if (VDiv2)
1002		hwp->ModeReg.CRTC[0x17] |= 0x04;
1003
1004#ifdef LG_DEBUG
1005	ErrorF("SynthClock = %d\n", mode->SynthClock);
1006#endif
1007	hwp->IOBase = 0x3D0;
1008	hwp->ModeReg.MiscOutReg |= 0x01;
1009#if 0 /* Mono address */
1010	hwp->IOBase = 0x3B0;
1011	hwp->ModeReg.MiscOutReg &= ~0x01;
1012#endif
1013
1014
1015	/* ??? Should these be both ...End or ...Start, not one of each? */
1016	pCir->chip.lg->ModeReg.ExtVga[CR1A] = (((mode->CrtcVSyncStart + 1) & 0x300 ) >> 2)
1017								| (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2);
1018
1019	width = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
1020	if (pScrn->bitsPerPixel == 1)
1021		width <<= 2;
1022	hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3;
1023	/* Offset extension (see CR13) */
1024	pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF;
1025	pCir->chip.lg->ModeReg.ExtVga[CR1B] |= (((width + 7) >> 3) & 0x100)?0x10:0x00;
1026	pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22;
1027	pCir->chip.lg->ModeReg.ExtVga[CR1D] = (((width + 7) >> 3) & 0x200)?0x01:0x00;
1028
1029	/* Set the 28th bit to enable extended modes. */
1030	pCir->chip.lg->ModeReg.VSC = 0x10000000;
1031
1032	/* Overflow register (sure are a lot of overflow bits around...) */
1033	pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00;
1034	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHTotal>>3 & 0x0100)?1:0)<<7;
1035	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHDisplay>>3 & 0x0100)?1:0)<<6;
1036	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<5;
1037	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<4;
1038	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVTotal & 0x0400)?1:0)<<3;
1039	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVDisplay & 0x0400)?1:0)<<2;
1040	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<1;
1041	pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<0;
1042
1043	lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
1044
1045	pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F;
1046
1047	if (8 == pScrn->bitsPerPixel) {
1048		pCir->chip.lg->ModeReg.FORMAT = 0x0000;
1049
1050		pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
1051							| (lineData->width << 6);
1052		pCir->chip.lg->ModeReg.CONTROL = 0x0000 | (lineData->width << 11);
1053
1054
1055		/* There is an optimal FIFO threshold value (lower 5 bits of DTTC)
1056		   for every resolution and color depth combination.  We'll hit
1057		   the highlights here, and get close for anything that's not
1058		   covered. */
1059		if (mode->CrtcHDisplay <= 640) {
1060			/* BAD numbers:  0x1E */
1061			/* GOOD numbers:  0x14 */
1062			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
1063		} else if (mode->CrtcHDisplay <= 800) {
1064			/* BAD numbers:  0x16 */
1065			/* GOOD numbers:  0x13 0x14 */
1066			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
1067		} else if (mode->CrtcHDisplay <= 1024) {
1068			/* BAD numbers:  */
1069			/* GOOD numbers: 0x15 */
1070			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
1071		} else if (mode->CrtcHDisplay <= 1280) {
1072			/* BAD numbers:  */
1073			/* GOOD numbers:  0x16 */
1074			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0016);
1075		} else {
1076			/* BAD numbers:  */
1077			/* GOOD numbers:  */
1078			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
1079		}
1080	} else if (16 == pScrn->bitsPerPixel) {
1081		/* !!! Assume 5-6-5 RGB mode (for now...) */
1082		pCir->chip.lg->ModeReg.FORMAT = 0x1400;
1083
1084		if (pScrn->depth == 15)
1085			pCir->chip.lg->ModeReg.FORMAT = 0x1600;
1086
1087		pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
1088							| (lineData->width << 6);
1089		pCir->chip.lg->ModeReg.CONTROL = 0x2000 | (lineData->width << 11);
1090
1091		if (mode->CrtcHDisplay <= 640) {
1092			/* BAD numbers:  0x12 */
1093			/* GOOD numbers: 0x10 */
1094			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
1095		} else if (mode->CrtcHDisplay <= 800) {
1096			/* BAD numbers:  0x13 */
1097			/* GOOD numbers:  0x11 */
1098			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
1099		} else if (mode->CrtcHDisplay <= 1024) {
1100			/* BAD numbers:  0x14 */
1101			/* GOOD numbers: 0x12  */
1102			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0012);
1103		} else if (mode->CrtcHDisplay <= 1280) {
1104			/* BAD numbers:   0x08 0x10 */
1105			/* Borderline numbers: 0x12 */
1106			/* GOOD numbers:  0x15 */
1107			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
1108		} else {
1109			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
1110		}
1111	} else if (24 == pScrn->bitsPerPixel) {
1112		pCir->chip.lg->ModeReg.FORMAT = 0x2400;
1113
1114		pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
1115							| (lineData->width << 6);
1116		pCir->chip.lg->ModeReg.CONTROL = 0x4000 | (lineData->width << 11);
1117
1118		if (mode->CrtcHDisplay <= 640) {
1119			/* BAD numbers:   */
1120			/* GOOD numbers:  0x10 */
1121			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
1122		} else if (mode->CrtcHDisplay <= 800) {
1123			/* BAD numbers:   */
1124			/* GOOD numbers:   0x11 */
1125			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
1126		} else if (mode->CrtcHDisplay <= 1024) {
1127			/* BAD numbers:  0x12 0x13 */
1128			/* Borderline numbers:  0x15 */
1129			/* GOOD numbers:  0x17 */
1130			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
1131		} else if (mode->CrtcHDisplay <= 1280) {
1132			/* BAD numbers:   */
1133			/* GOOD numbers:  0x1E */
1134			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001E);
1135		} else {
1136			/* BAD numbers:   */
1137			/* GOOD numbers:  */
1138			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0020);
1139		}
1140	} else if (32 == pScrn->bitsPerPixel) {
1141		pCir->chip.lg->ModeReg.FORMAT = 0x3400;
1142
1143		pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
1144							| (lineData->width << 6);
1145		pCir->chip.lg->ModeReg.CONTROL = 0x6000 | (lineData->width << 11);
1146
1147		if (mode->CrtcHDisplay <= 640) {
1148			/* GOOD numbers:  0x0E */
1149			/* BAD numbers:  */
1150			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x000E);
1151		} else if (mode->CrtcHDisplay <= 800) {
1152			/* GOOD numbers:  0x17 */
1153			/* BAD numbers:  */
1154			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
1155		} else if (mode->CrtcHDisplay <= 1024) {
1156			/* GOOD numbers: 0x1D */
1157			/* OKAY numbers:  0x15 0x14 0x16 0x18 0x19 */
1158			/* BAD numbers:  0x0E 0x12 0x13 0x0D */
1159			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001D);
1160		} else if (mode->CrtcHDisplay <= 1280) {
1161			/* GOOD numbers:  */
1162			/* BAD numbers:  */
1163			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0022); /* 10 */
1164		} else {
1165			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0024);
1166		}
1167	} else {
1168		/* ??? What could it be?  Use some sane numbers. */
1169	}
1170
1171	/* Setup the appropriate memory interleaving */
1172	pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8);
1173	pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0;
1174
1175	if (PCI_CHIP_GD5465 == pCir->Chipset) {
1176		/* The tile control information in the DTTC is also mirrored
1177		   elsewhere. */
1178		pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->ModeReg.DTTC & 0xFFC0;
1179
1180		/* The 5465's DTTC records _fetches_ per line, not
1181		   tiles per line.  Fetchs are 128-byte fetches. */
1182		if (pCir->chip.lg->ModeReg.DTTC & 0x0040) {
1183			/* Using 256-byte wide tiles.  Double the fetches
1184			   per line field. */
1185			pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xC0FF)
1186								| ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1);
1187		}
1188	}
1189
1190	/* Program the registers */
1191	vgaHWProtect(pScrn, TRUE);
1192	hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg);
1193
1194	clockData = LgSetClock(pCir, hwp, mode->SynthClock);
1195	pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF;
1196	pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF;
1197
1198	/* Write those registers out to the card. */
1199	LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg);
1200
1201	/* Programme the registers */
1202	vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP);
1203
1204	vgaHWProtect(pScrn, FALSE);
1205
1206	return TRUE;
1207}
1208
1209static int LgFindLineData(int displayWidth, int bpp)
1210{
1211	/* Find the smallest tile-line-pitch such that the total byte pitch
1212	 is greater than or equal to displayWidth*Bpp. */
1213	int i;
1214
1215	/* Some pitch sizes are duplicates in the table.  BUT, the invariant is
1216	 that the _first_ time a pitch occurs in the table is always _before_
1217	 all other pitches greater than it.  Said in another way... if all
1218	 duplicate entries from the table were removed, then the resulting pitch
1219	 values are strictly increasing. */
1220
1221	for (i = 0; LgLineData[i].pitch > 0; i++)
1222		if (LgLineData[i].pitch >= displayWidth*bpp>>3)
1223			return i;
1224
1225	/* Um, uh oh! */
1226	return -1;
1227}
1228
1229
1230
1231
1232static void
1233LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg)
1234{
1235	CirPtr pCir;
1236	vgaHWPtr hwp;
1237	CARD8 cr1D;
1238
1239	pCir = CIRPTR(pScrn);
1240
1241	/* First, VGAish registers. */
1242	hwp = VGAHWPTR(pScrn);
1243	hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]);
1244	hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]);
1245	cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | (lgReg->ExtVga[CR1D] & 0x01);
1246	hwp->writeCrtc(hwp, 0x1D, cr1D);
1247	hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]);
1248
1249	hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]);
1250	hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]);
1251	hwp->writeSeq(hwp, 0x12, lgReg->ExtVga[SR12]);
1252	hwp->writeSeq(hwp, 0x13, lgReg->ExtVga[SR13]);
1253	hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]);
1254	memww(0xC0, lgReg->FORMAT);
1255
1256    /* Vendor Specific Control is touchy.  Only bit 28 is of concern. */
1257	memwl(0x3FC, ((memrl(0x3FC) & ~(1<<28)) | (lgReg->VSC & (1<<28))));
1258
1259	memww(0xEA, lgReg->DTTC);
1260
1261	if (pCir->Chipset == PCI_CHIP_GD5465) {
1262	    memww(0x2C4, lgReg->TileCtrl);
1263	}
1264
1265	memwb(0x407, lgReg->TILE);
1266
1267	if (pCir->Chipset == PCI_CHIP_GD5465)
1268	    memwb(0x2C0, lgReg->BCLK);
1269	else
1270	    memwb(0x8C, lgReg->BCLK);
1271
1272	memww(0x402, lgReg->CONTROL);
1273}
1274
1275/*
1276 * Restore the initial (text) mode.
1277 */
1278static void
1279LgRestore(ScrnInfoPtr pScrn)
1280{
1281	vgaHWPtr hwp;
1282	vgaRegPtr vgaReg;
1283	CirPtr pCir;
1284	LgRegPtr lgReg;
1285
1286#ifdef LG_DEBUG
1287	ErrorF("LgRestore  pScrn = %p\n", (void *)pScrn);
1288#endif
1289
1290	pCir = CIRPTR(pScrn);
1291	hwp = VGAHWPTR(pScrn);
1292	vgaReg = &hwp->SavedReg;
1293	lgReg = &pCir->chip.lg->SavedReg;
1294
1295	vgaHWProtect(pScrn, TRUE);
1296
1297	LgRestoreLgRegs(pScrn, lgReg);
1298
1299	vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1300	vgaHWProtect(pScrn, FALSE);
1301}
1302
1303/* Mandatory */
1304
1305/* This gets called at the start of each server generation */
1306
1307Bool
1308LgScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1309{
1310	/* The vgaHW references will disappear one day */
1311	ScrnInfoPtr pScrn;
1312	vgaHWPtr hwp;
1313	CirPtr pCir;
1314	int i, ret;
1315	VisualPtr visual;
1316	int displayWidth,width,height;
1317	unsigned char * FbBase = NULL;
1318
1319#ifdef LG_DEBUG
1320	ErrorF("LgScreenInit\n");
1321#endif
1322
1323	/*
1324	 * First get the ScrnInfoRec
1325	 */
1326	pScrn = xf86Screens[pScreen->myNum];
1327
1328	hwp = VGAHWPTR(pScrn);
1329
1330	hwp->MapSize = 0x10000;		/* Standard 64k VGA window */
1331
1332	pCir = CIRPTR(pScrn);
1333
1334	/* Map the VGA memory and get the VGA IO base */
1335	if (!vgaHWMapMem(pScrn))
1336		return FALSE;
1337
1338	/* Map the CIR memory and MMIO areas */
1339	if (!CirMapMem(pCir, pScrn->scrnIndex))
1340		return FALSE;
1341#ifdef EXPERIMENTAL
1342	lg_vgaHWSetMmioFunc(hwp, pCir->IOBase);
1343#endif
1344	vgaHWGetIOBase(hwp);
1345
1346	/* Save the current state */
1347	LgSave(pScrn);
1348
1349	/* Initialise the first mode */
1350	if (!LgModeInit(pScrn, pScrn->currentMode))
1351		return FALSE;
1352
1353	/* Make things beautiful */
1354	LgSaveScreen(pScreen, SCREEN_SAVER_ON);
1355
1356	/* Set the viewport */
1357	LgAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1358
1359	/*
1360	 * The next step is to setup the screen's visuals, and initialise the
1361	 * framebuffer code.  In cases where the framebuffer's default
1362	 * choices for things like visual layouts and bits per RGB are OK,
1363	 * this may be as simple as calling the framebuffer's ScreenInit()
1364	 * function.  If not, the visuals will need to be setup before calling
1365	 * a fb ScreenInit() function and fixed up after.
1366	 *
1367	 */
1368
1369	/*
1370	 * Reset the visual list.
1371	 */
1372	miClearVisualTypes();
1373
1374	/* Setup the visuals we support. */
1375
1376	if (!miSetVisualTypes(pScrn->depth,
1377			      miGetDefaultVisualMask(pScrn->depth),
1378			      pScrn->rgbBits, pScrn->defaultVisual))
1379	  return FALSE;
1380
1381	miSetPixmapDepths ();
1382
1383#ifdef LG_DEBUG
1384	ErrorF("LgScreenInit after miSetVisualTypes\n");
1385#endif
1386	displayWidth = pScrn->displayWidth;
1387	if (pCir->rotate) {
1388	    height = pScrn->virtualX;
1389	    width = pScrn->virtualY;
1390	} else {
1391	    width = pScrn->virtualX;
1392	    height = pScrn->virtualY;
1393	}
1394
1395	if(pCir->shadowFB) {
1396	    pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
1397	    pCir->ShadowPtr = xalloc(pCir->ShadowPitch * height);
1398	    displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3);
1399	    FbBase = pCir->ShadowPtr;
1400	} else {
1401	    pCir->ShadowPtr = NULL;
1402	    FbBase = pCir->FbBase;
1403	}
1404
1405	/*
1406	 * Call the framebuffer layer's ScreenInit function, and fill in other
1407	 * pScreen fields.
1408	 */
1409	switch (pScrn->bitsPerPixel) {
1410	case 8:
1411	case 16:
1412	case 24:
1413	case 32:
1414	    ret = fbScreenInit(pScreen, FbBase,
1415				width,height,
1416				pScrn->xDpi, pScrn->yDpi,
1417				displayWidth,pScrn->bitsPerPixel);
1418	    break;
1419	default:
1420		xf86DrvMsg(scrnIndex, X_ERROR,
1421			   "X11: Internal error: invalid bpp (%d) in LgScreenInit\n",
1422			   pScrn->bitsPerPixel);
1423		ret = FALSE;
1424		break;
1425	}
1426	if (!ret)
1427		return FALSE;
1428
1429#ifdef LG_DEBUG
1430	ErrorF("LgScreenInit after depth dependent init\n");
1431#endif
1432
1433	/* Override the default mask/offset settings */
1434	if (pScrn->bitsPerPixel > 8) {
1435		for (i = 0; i < pScreen->numVisuals; i++) {
1436			visual = &pScreen->visuals[i];
1437			if ((visual->class | DynamicClass) == DirectColor) {
1438				visual->offsetRed = pScrn->offset.red;
1439				visual->offsetGreen = pScrn->offset.green;
1440				visual->offsetBlue = pScrn->offset.blue;
1441				visual->redMask = pScrn->mask.red;
1442				visual->greenMask = pScrn->mask.green;
1443				visual->blueMask = pScrn->mask.blue;
1444			}
1445		}
1446	}
1447
1448	/* must be after RGB ordering fixed */
1449
1450	fbPictureInit(pScreen, 0, 0);
1451
1452	miInitializeBackingStore(pScreen);
1453
1454	/*
1455	 * Set initial black & white colourmap indices.
1456	 */
1457	xf86SetBlackWhitePixels(pScreen);
1458
1459	if (!pCir->NoAccel) { /* Initialize XAA functions */
1460		if (!LgXAAInit(pScreen))
1461			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialize XAA\n");
1462	}
1463#if 1
1464	pCir->DGAModeInit = LgModeInit;
1465	if (!CirDGAInit(pScreen))
1466	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1467		     "DGA initialization failed\n");
1468#endif
1469        xf86SetSilkenMouse(pScreen);
1470
1471	/* Initialise cursor functions */
1472	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1473
1474	if (pCir->HWCursor) { /* Initialize HW cursor layer */
1475		if (!LgHWCursorInit(pScreen))
1476			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1477				"Hardware cursor initialization failed\n");
1478	}
1479
1480	/* Initialise default colourmap */
1481	if (!miCreateDefColormap(pScreen))
1482		return FALSE;
1483
1484	if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8)
1485		vgaHWHandleColormaps(pScreen);
1486
1487	xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 0);
1488
1489	pScrn->memPhysBase = pCir->FbAddress;
1490	pScrn->fbOffset = 0;
1491
1492	{
1493		XF86VideoAdaptorPtr *ptr;
1494		int n;
1495
1496		n = xf86XVListGenericAdaptors(pScrn,&ptr);
1497		if (n)
1498			xf86XVScreenInit(pScreen, ptr, n);
1499	}
1500
1501	/*
1502	 * Wrap the CloseScreen vector and set SaveScreen.
1503	 */
1504	pScreen->SaveScreen = LgSaveScreen;
1505	pCir->CloseScreen = pScreen->CloseScreen;
1506	pScreen->CloseScreen = LgCloseScreen;
1507
1508	/* Report any unused options (only for the first generation) */
1509	if (serverGeneration == 1)
1510		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1511
1512	/* Done */
1513	return TRUE;
1514}
1515
1516
1517/* Usually mandatory */
1518Bool
1519LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1520{
1521	return LgModeInit(xf86Screens[scrnIndex], mode);
1522}
1523
1524#define ROUND_DOWN(x, mod)	(((x) / (mod)) * (mod))
1525#define ROUND_UP(x, mod)	((((x) + (mod) - 1) / (mod)) * (mod))
1526
1527/*
1528 * This function is used to initialize the Start Address - the first
1529 * displayed location in the video memory.
1530 */
1531/* Usually mandatory */
1532void
1533LgAdjustFrame(int scrnIndex, int x, int y, int flags)
1534{
1535	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1536	int Base, tmp;
1537	CirPtr pCir = CIRPTR(pScrn);
1538	vgaHWPtr hwp = VGAHWPTR(pScrn);
1539	int cursorX, cursorY;
1540	int middleX, middleY;
1541	const LgLineDataPtr lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
1542	const int viewportXRes =
1543		(PCI_CHIP_GD5465 == pCir->Chipset) ? (24==pScrn->bitsPerPixel?24:1) :
1544			(lineData->width?256:128) /
1545			(24==pScrn->bitsPerPixel?1:(pScrn->bitsPerPixel>>3));
1546	const int viewportYRes =
1547		(PCI_CHIP_GD5465 == pCir->Chipset) ? 1 : (24==pScrn->bitsPerPixel?3:1);
1548
1549	/* Where's the pointer? */
1550	miPointerGetPosition(inputInfo.pointer, &cursorX, &cursorY);
1551
1552	/* Where's the middle of the screen?  We want to eventually know
1553	   which side of the screen the pointer is on. */
1554	middleX = (pScrn->frameX1 + pScrn->frameX0) / 2;
1555	middleY = (pScrn->frameY1 + pScrn->frameY0) / 2;
1556
1557	if (cursorX < middleX) {
1558		/* Pointer is on left side of screen.  Round the frame value down. */
1559		pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes);
1560	} else {
1561		/* Pointer is on right side of screen.  Round the frame value
1562		   up.  A side effect of this rounding up is that we might expose
1563		   a part of the screen that's actually on the far /left/ of the
1564		   frame buffer.  That's because, although the virtual desktop might
1565		   be an integral number of tiles, the display might not.  We'll
1566		   just live with this artifact. */
1567		pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes);
1568	}
1569	pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
1570
1571	if (cursorY < middleY) {
1572		pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes);
1573	} else {
1574		pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes);
1575	}
1576	pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
1577
1578
1579	if (x != pScrn->frameX0 || y != pScrn->frameY0) {
1580		/* !!! */
1581		/* We moved the frame from where xf86SetViewport() placed it.
1582		   If we're using a SW cursor, that's okay -- the pointer exists in
1583		   the framebuffer, and those bits are still all aligned.  But
1584		   if we're using a HW cursor, then we need to re-align the pointer.
1585		   Call SetCursorPosition() with the appropriate new pointer
1586		   values, adjusted to be wrt the new frame. */
1587
1588		x = pScrn->frameX0;
1589		y = pScrn->frameY0;
1590	}
1591
1592	/* ??? Will this work for 1bpp?  */
1593	Base = (y * lineData->pitch + (x*pScrn->bitsPerPixel/8)) / 4;
1594
1595	if ((Base & ~0x000FFFFF) != 0) {
1596		/* ??? */
1597		ErrorF("X11: Internal error: LgAdjustFrame: cannot handle overflow\n");
1598		return;
1599	}
1600
1601	hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF);
1602	hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
1603	tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2;
1604	tmp |= (Base >> 16) & 0x01;
1605	tmp |= (Base >> 15) & 0x0C;
1606	hwp->writeCrtc(hwp, 0x1B, tmp);
1607	tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7;
1608	tmp |= (Base >> 16) & 0x18;
1609	hwp->writeCrtc(hwp, 0x1D, tmp);
1610}
1611
1612/*
1613 * This is called when VT switching back to the X server.  Its job is
1614 * to reinitialise the video mode.
1615 *
1616 * We may wish to unmap video/MMIO memory too.
1617 */
1618
1619/* Mandatory */
1620Bool
1621LgEnterVT(int scrnIndex, int flags)
1622{
1623	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1624	CirPtr pCir = CIRPTR(pScrn);
1625#ifdef LG_DEBUG
1626	ErrorF("LgEnterVT\n");
1627#endif
1628
1629	/* XXX Shouldn't this be in LeaveVT? */
1630	/* Disable HW cursor */
1631	if (pCir->HWCursor)
1632		LgHideCursor(pScrn);
1633
1634	/* Should we re-save the text mode on each VT enter? */
1635	return LgModeInit(pScrn, pScrn->currentMode);
1636}
1637
1638
1639/*
1640 * This is called when VT switching away from the X server.  Its job is
1641 * to restore the previous (text) mode.
1642 *
1643 * We may wish to remap video/MMIO memory too.
1644 */
1645
1646/* Mandatory */
1647void
1648LgLeaveVT(int scrnIndex, int flags)
1649{
1650	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1651	vgaHWPtr hwp = VGAHWPTR(pScrn);
1652	CirPtr pCir = CIRPTR(pScrn);
1653#ifdef LG_DEBUG
1654	ErrorF("LgLeaveVT\n");
1655#endif
1656
1657	/* XXX Shouldn't this be in EnterVT? */
1658	/* Enable HW cursor */
1659	if (pCir->HWCursor)
1660		LgShowCursor(pScrn);
1661
1662	LgRestore(pScrn);
1663	vgaHWLock(hwp);
1664}
1665
1666
1667/*
1668 * This is called at the end of each server generation.  It restores the
1669 * original (text) mode.  It should also unmap the video memory, and free
1670 * any per-generation data allocated by the driver.  It should finish
1671 * by unwrapping and calling the saved CloseScreen function.
1672 */
1673
1674/* Mandatory */
1675static Bool
1676LgCloseScreen(int scrnIndex, ScreenPtr pScreen)
1677{
1678	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1679	vgaHWPtr hwp = VGAHWPTR(pScrn);
1680	CirPtr pCir = CIRPTR(pScrn);
1681
1682	if(pScrn->vtSema) {
1683	LgRestore(pScrn);
1684	if (pCir->HWCursor)
1685	    LgHideCursor(pScrn);
1686
1687	vgaHWLock(hwp);
1688
1689	CirUnmapMem(pCir, pScrn->scrnIndex);
1690	}
1691
1692	if (pCir->AccelInfoRec)
1693		XAADestroyInfoRec(pCir->AccelInfoRec);
1694	pCir->AccelInfoRec = NULL;
1695
1696	if (pCir->CursorInfoRec)
1697		xf86DestroyCursorInfoRec(pCir->CursorInfoRec);
1698	pCir->CursorInfoRec = NULL;
1699	if (pCir->DGAModes)
1700		xfree(pCir->DGAModes);
1701	pCir->DGAnumModes = 0;
1702	pCir->DGAModes = NULL;
1703
1704	pScrn->vtSema = FALSE;
1705
1706	pScreen->CloseScreen = pCir->CloseScreen;
1707	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1708}
1709
1710
1711/* Free up any persistent data structures */
1712
1713/* Optional */
1714void
1715LgFreeScreen(int scrnIndex, int flags)
1716{
1717#ifdef LG_DEBUG
1718	ErrorF("LgFreeScreen\n");
1719#endif
1720	/*
1721	 * This only gets called when a screen is being deleted.  It does not
1722	 * get called routinely at the end of a server generation.
1723	 */
1724	if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1725		vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1726	LgFreeRec(xf86Screens[scrnIndex]);
1727}
1728
1729
1730/* Checks if a mode is suitable for the selected chipset. */
1731
1732/* Optional */
1733ModeStatus
1734LgValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1735{
1736	int lace;
1737
1738	lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
1739
1740	if ((mode->CrtcHDisplay <= 2048) &&
1741		(mode->CrtcHSyncStart <= 4096) &&
1742		(mode->CrtcHSyncEnd <= 4096) &&
1743		(mode->CrtcHTotal <= 4096) &&
1744		(mode->CrtcVDisplay <= 2048 * lace) &&
1745		(mode->CrtcVSyncStart <= 4096 * lace) &&
1746		(mode->CrtcVSyncEnd <= 4096 * lace) &&
1747		(mode->CrtcVTotal <= 4096 * lace)) {
1748		return(MODE_OK);
1749	}
1750	return(MODE_BAD);
1751}
1752
1753
1754/* Do screen blanking */
1755
1756/* Mandatory */
1757static Bool
1758LgSaveScreen(ScreenPtr pScreen, int mode)
1759{
1760	CirPtr pCir = CIRPTR(xf86Screens[pScreen->myNum]);
1761	ScrnInfoPtr pScrn = NULL;
1762	Bool unblank;
1763
1764	unblank = xf86IsUnblank(mode);
1765
1766	if (pScreen != NULL)
1767	    pScrn = xf86Screens[pScreen->myNum];
1768
1769	if (pScrn != NULL && pScrn->vtSema) {
1770	    if (unblank)
1771		/* Power up the palette DAC */
1772		memwb(0xB0,memrb(0xB0) & 0x7F);
1773	    else
1774		/* Power down the palette DAC */
1775		memwb(0xB0,memrb(0xB0) | 0x80);
1776	}
1777
1778	return vgaHWSaveScreen(pScreen, mode);
1779}
1780
1781static CARD16
1782LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq)
1783{
1784	int ffreq, num, den;
1785	CARD8 tmp;
1786
1787	ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000);
1788
1789	ffreq = freq;
1790	if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den))
1791		return 0;
1792
1793	ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n",
1794		num, den, ffreq / 1000, ffreq % 1000);
1795
1796	/* Set VCLK3. */
1797	/* The numerator and denominator registers are switched
1798	   around in the Laguna chips. */
1799	tmp = hwp->readSeq(hwp, 0x0E);
1800	hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den);
1801	hwp->writeSeq(hwp, 0x1E, num);
1802
1803	return (den << 8) | num;
1804}
1805
1806/*
1807 * CIRDisplayPowerManagementSet --
1808 *
1809 * Sets VESA Display Power Management Signaling (DPMS) Mode.
1810 */
1811static void
1812LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
1813							int flags)
1814{
1815	unsigned char sr01, cr1a;
1816	vgaHWPtr hwp;
1817
1818#ifdef LG_DEBUG
1819	ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode);
1820#endif
1821
1822	hwp = VGAHWPTR(pScrn);
1823
1824	switch (PowerManagementMode) {
1825	case DPMSModeOn:
1826		/* Screen: On; HSync: On, VSync: On */
1827		sr01 = 0x00;
1828		cr1a = 0x00;
1829		break;
1830	case DPMSModeStandby:
1831		/* Screen: Off; HSync: Off, VSync: On */
1832		sr01 = 0x20;
1833		cr1a = 0x08;
1834		break;
1835	case DPMSModeSuspend:
1836		/* Screen: Off; HSync: On, VSync: Off */
1837		sr01 = 0x20;
1838		cr1a = 0x04;
1839		break;
1840	case DPMSModeOff:
1841		/* Screen: Off; HSync: Off, VSync: Off */
1842		sr01 = 0x20;
1843		cr1a = 0x0c;
1844		break;
1845	default:
1846		return;
1847	}
1848
1849	sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20;
1850	hwp->writeSeq(hwp, 0x01, sr01);
1851	cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C;
1852	hwp->writeCrtc(hwp, 0x1A, cr1a);
1853}
1854
1855#define minb(p) MMIO_IN8(hwp->MMIOBase, (p))
1856#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v))
1857
1858static void
1859mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
1860{
1861  moutb(index << 2, value);
1862}
1863
1864static CARD8
1865mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
1866{
1867  return minb(index << 2);
1868}
1869
1870static void
1871lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base)
1872{
1873    hwp->writeCrtc		= mmioWriteCrtc;
1874    hwp->readCrtc		= mmioReadCrtc;
1875    hwp->MMIOBase		= base;
1876    hwp->MMIOOffset		= 0;
1877}
1878