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