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