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