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