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