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