1 
2 /**************************************************************************
3 
4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 All Rights Reserved.
6 
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sub license, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14 
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial portions
17 of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 
27 **************************************************************************/
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 /*
34  * Authors:
35  *   Keith Whitwell <keith@tungstengraphics.com>
36  *
37  * Add ARGB HW cursor support:
38  *   Alan Hourihane <alanh@tungstengraphics.com>
39  *
40  */
41 
42 /*
43  * This server does not support these XFree86 4.0 features yet
44  * shadowFb (if requested or acceleration is off)
45  * Overlay planes
46  * DGA
47  */
48 
49 #include <math.h>
50 #include <string.h>
51 #include <unistd.h>
52 
53 /*
54  * These are X and server generic header files.
55  */
56 #include "xorg-server.h"
57 #include "xf86.h"
58 #include "xf86_OSproc.h"
59 #include "xf86cmap.h"
60 
61 #include "compiler.h"
62 #include "vgaHW.h"
63 #include "mipointer.h"
64 #include "micmap.h"
65 
66 #include "fb.h"
67 #include "miscstruct.h"
68 #include "xf86xv.h"
69 #include <X11/extensions/Xv.h>
70 #include "vbe.h"
71 #include "xf86fbman.h"
72 
73 #include "i810.h"
74 
75 #ifdef HAVE_DRI1
76 #include "dri.h"
77 #endif
78 
79 #include "../legacy.h"
80 
81 static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
82 static Bool I810ScreenInit(SCREEN_INIT_ARGS_DECL);
83 static Bool I810EnterVT(VT_FUNC_ARGS_DECL);
84 static void I810LeaveVT(VT_FUNC_ARGS_DECL);
85 static Bool I810CloseScreen(CLOSE_SCREEN_ARGS_DECL);
86 static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank);
87 static void I810FreeScreen(FREE_SCREEN_ARGS_DECL);
88 static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn,
89 					  int PowerManagermentMode,
90 					  int flags);
91 static ModeStatus I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
92 				Bool verbose, int flags);
93 
94 typedef enum {
95    OPTION_NOACCEL,
96    OPTION_SW_CURSOR,
97    OPTION_COLOR_KEY,
98    OPTION_CACHE_LINES,
99    OPTION_DAC_6BIT,
100    OPTION_DRI,
101    OPTION_NO_DDC,
102    OPTION_SHOW_CACHE,
103    OPTION_XVMC_SURFACES,
104    OPTION_PAGEFLIP
105 } I810Opts;
106 
107 static const OptionInfoRec I810Options[] = {
108    {OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE},
109    {OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE},
110    {OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE},
111    {OPTION_CACHE_LINES,		"CacheLines",	OPTV_INTEGER,	{0}, FALSE},
112    {OPTION_DAC_6BIT,		"Dac6Bit",	OPTV_BOOLEAN,	{0}, FALSE},
113    {OPTION_DRI,			"DRI",		OPTV_BOOLEAN,	{0}, FALSE},
114    {OPTION_NO_DDC,		"NoDDC",	OPTV_BOOLEAN,	{0}, FALSE},
115    {OPTION_SHOW_CACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE},
116    {OPTION_XVMC_SURFACES,	"XvMCSurfaces",	OPTV_INTEGER,	{0}, FALSE},
117    {OPTION_PAGEFLIP,            "PageFlip",     OPTV_BOOLEAN, {0},   FALSE},
118    {-1,				NULL,		OPTV_NONE,	{0}, FALSE}
119 };
120 /* *INDENT-ON* */
121 
122 #ifndef I810_DEBUG
123 int I810_DEBUG = (0
124 /*     		  | DEBUG_ALWAYS_SYNC  */
125 /*    		  | DEBUG_VERBOSE_ACCEL */
126 /*  		  | DEBUG_VERBOSE_SYNC */
127 /*  		  | DEBUG_VERBOSE_VGA */
128 /*  		  | DEBUG_VERBOSE_RING */
129 /*  		  | DEBUG_VERBOSE_OUTREG */
130 /*  		  | DEBUG_VERBOSE_MEMORY */
131 /*  		  | DEBUG_VERBOSE_CURSOR */
132       );
133 #endif
134 
135 #ifdef HAVE_DRI1
136 static int i810_pitches[] = {
137    512,
138    1024,
139    2048,
140    4096,
141    0
142 };
143 #endif
144 
145 /*
146  * I810GetRec and I810FreeRec --
147  *
148  * Private data for the driver is stored in the screen structure.
149  * These two functions create and destroy that private data.
150  *
151  */
152 static Bool
I810GetRec(ScrnInfoPtr scrn)153 I810GetRec(ScrnInfoPtr scrn)
154 {
155    if (((uintptr_t)scrn->driverPrivate & 3) == 0)
156       return TRUE;
157 
158    scrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1);
159    return TRUE;
160 }
161 
162 static void
I810FreeRec(ScrnInfoPtr scrn)163 I810FreeRec(ScrnInfoPtr scrn)
164 {
165    if (!scrn)
166       return;
167    if (!scrn->driverPrivate)
168       return;
169    free(scrn->driverPrivate);
170    scrn->driverPrivate = NULL;
171 }
172 
173 struct pci_device *
intel_host_bridge(void)174 intel_host_bridge (void)
175 {
176     static const struct pci_slot_match bridge_match = {
177 	0, 0, 0, PCI_MATCH_ANY, 0
178     };
179     struct pci_device_iterator	*slot_iterator;
180     struct pci_device		*bridge;
181 
182     slot_iterator = pci_slot_match_iterator_create (&bridge_match);
183     bridge = pci_device_next (slot_iterator);
184     pci_iterator_destroy (slot_iterator);
185     return bridge;
186 }
187 
188 static void
I810ProbeDDC(ScrnInfoPtr scrn,int index)189 I810ProbeDDC(ScrnInfoPtr scrn, int index)
190 {
191    vbeInfoPtr pVbe;
192 
193    if (xf86LoadSubModule(scrn, "vbe")) {
194       pVbe = VBEInit(NULL, index);
195       ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
196       vbeFree(pVbe);
197    }
198 }
199 
200 static xf86MonPtr
I810DoDDC(ScrnInfoPtr scrn,int index)201 I810DoDDC(ScrnInfoPtr scrn, int index)
202 {
203    vbeInfoPtr pVbe;
204    xf86MonPtr MonInfo = NULL;
205    I810Ptr pI810 = I810PTR(scrn);
206 
207    /* Honour Option "noDDC" */
208    if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) {
209       return MonInfo;
210    }
211 
212    if (xf86LoadSubModule(scrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
213       MonInfo = vbeDoEDID(pVbe, NULL);
214       xf86PrintEDID(MonInfo);
215       xf86SetDDCproperties(scrn, MonInfo);
216       vbeFree(pVbe);
217    } else {
218       xf86DrvMsg(scrn->scrnIndex, X_INFO,
219 		 "this driver cannot do DDC without VBE\n");
220    }
221 
222    return MonInfo;
223 }
224 
225 /*
226  * I810PreInit --
227  *
228  * Do initial setup of the board before we know what resolution we will
229  * be running at.
230  *
231  */
232 static Bool
I810PreInit(ScrnInfoPtr scrn,int flags)233 I810PreInit(ScrnInfoPtr scrn, int flags)
234 {
235    I810Ptr pI810;
236    ClockRangePtr clockRanges;
237    int i;
238    MessageType from;
239    int flags24;
240    rgb defaultWeight = { 0, 0, 0 };
241    int mem;
242    Bool enable;
243 
244    if (scrn->numEntities != 1)
245       return FALSE;
246 
247    /* Allocate driverPrivate */
248    if (!I810GetRec(scrn))
249       return FALSE;
250 
251    pI810 = I810PTR(scrn);
252 
253    pI810->pEnt = xf86GetEntityInfo(scrn->entityList[0]);
254    if (pI810->pEnt == NULL || pI810->pEnt->location.type != BUS_PCI)
255       return FALSE;
256 
257    if (flags & PROBE_DETECT) {
258       I810ProbeDDC(scrn, pI810->pEnt->index);
259       return TRUE;
260    }
261 
262    /* The vgahw module should be loaded here when needed */
263    if (!xf86LoadSubModule(scrn, "vgahw"))
264       return FALSE;
265 
266    /* Allocate a vgaHWRec */
267    if (!vgaHWGetHWRec(scrn))
268       return FALSE;
269 
270    pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
271 
272    /* Set scrn->monitor */
273    scrn->monitor = scrn->confScreen->monitor;
274 
275    flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
276    if (!xf86SetDepthBpp(scrn, 16, 0, 16, flags24)) {
277       return FALSE;
278    } else {
279       switch (scrn->depth) {
280       case 8:
281       case 15:
282       case 16:
283       case 24:
284 	 break;
285       default:
286 	 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
287 		    "Given depth (%d) is not supported by i810 driver\n",
288 		    scrn->depth);
289 	 return FALSE;
290       }
291    }
292    xf86PrintDepthBpp(scrn);
293 
294    switch (scrn->bitsPerPixel) {
295    case 8:
296    case 16:
297    case 24:
298       break;
299    default:
300       xf86DrvMsg(scrn->scrnIndex, X_ERROR,
301 		 "Given bpp (%d) is not supported by i810 driver\n",
302 		 scrn->bitsPerPixel);
303       return FALSE;
304    }
305 
306    if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
307       return FALSE;
308 
309    if (!xf86SetDefaultVisual(scrn, -1))
310       return FALSE;
311 
312    /* We use a programmable clock */
313    scrn->progClock = TRUE;
314 
315    pI810->cpp = scrn->bitsPerPixel / 8;
316 
317    /* Process the options */
318    xf86CollectOptions(scrn, NULL);
319    if (!(pI810->Options = malloc(sizeof(I810Options))))
320       return FALSE;
321    memcpy(pI810->Options, I810Options, sizeof(I810Options));
322    xf86ProcessOptions(scrn->scrnIndex, scrn->options, pI810->Options);
323 
324    scrn->rgbBits = 8;
325    if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
326       scrn->rgbBits = 6;
327 
328    if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE))
329      pI810->showCache = TRUE;
330    else
331      pI810->showCache = FALSE;
332 
333    /* 6-BIT dac isn't reasonable for modes with > 8bpp */
334    if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) &&
335        scrn->bitsPerPixel > 8) {
336       OptionInfoPtr ptr;
337 
338       ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT);
339       ptr->found = FALSE;
340    }
341 
342    if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
343       pI810->noAccel = TRUE;
344 
345    if (!pI810->noAccel && !xf86LoadSubModule(scrn, "xaa"))
346       pI810->noAccel = TRUE;
347 
348 #ifdef HAVE_DRI1
349    pI810->directRenderingDisabled =
350      !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
351 
352    if (!pI810->directRenderingDisabled) {
353      if (scrn->depth!=16) {
354        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "DRI is disabled because it "
355 		  "runs only at 16-bit depth.\n");
356        pI810->directRenderingDisabled=TRUE;
357      }
358    }
359 #endif
360 
361    /* Get DDC info from monitor */
362    /* after xf86ProcessOptions,
363     * because it is controlled by options [no]vbe and [no]ddc
364     */
365    I810DoDDC(scrn, pI810->pEnt->index);
366 
367    intel_detect_chipset(scrn, NULL);
368 
369    pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr;
370    xf86DrvMsg(scrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n",
371 	      (unsigned long)pI810->LinearAddr);
372 
373    pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr;
374    xf86DrvMsg(scrn->scrnIndex, X_PROBED, "IO registers at addr 0x%lX\n",
375 	      (unsigned long)pI810->MMIOAddr);
376 
377    /* AGP GART support is required.  Don't proceed any further if it isn't
378     * present.
379     */
380    if (!xf86AgpGARTSupported()) {
381       xf86DrvMsg(scrn->scrnIndex, X_ERROR,
382 		 "AGP GART support is not available.  Make sure your kernel has\n"
383 		 "\tagpgart support or that the agpgart kernel module is loaded.\n");
384       return FALSE;
385    }
386 
387    /* Find out memory bus frequency.
388     */
389    {
390       uint32_t whtcfg_pamr_drp;
391 
392       pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP);
393 
394       /* Need this for choosing watermarks.
395        */
396       if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133)
397 	 pI810->LmFreqSel = 133;
398       else
399 	 pI810->LmFreqSel = 100;
400    }
401 
402    /* Default to 4MB framebuffer, which is sufficient for all
403     * supported 2d resolutions.  If the user has specified a different
404     * size in the XF86Config, use that amount instead.
405     *
406     *  Changed to 8 Meg so we can have acceleration by default (Mark).
407     */
408    mem = I810CheckAvailableMemory(scrn);
409    if (pI810->directRenderingDisabled || mem < 131072)  /* < 128 MB */
410        scrn->videoRam = 8192;
411    else if (mem < 196608)
412        scrn->videoRam = 16384;  /* < 192 MB */
413    else
414        scrn->videoRam = 24576;
415 
416    from = X_DEFAULT;
417 
418    if (pI810->pEnt->device->videoRam) {
419       scrn->videoRam = pI810->pEnt->device->videoRam;
420       from = X_CONFIG;
421    }
422 
423    if (mem > 0 && mem < scrn->videoRam) {
424       xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
425 		 " but the\n\t maximum AGP memory available is %dk.\n",
426 		 scrn->videoRam, mem);
427       from = X_PROBED;
428       if (mem > (6 * 1024)) {
429 	 xf86DrvMsg(scrn->scrnIndex, X_INFO,
430 		    "Reducing video memory to 4MB\n");
431 	 scrn->videoRam = 4096;
432       } else {
433 	 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
434 		    " is available. Cannot proceed.\n");
435 	 I810FreeRec(scrn);
436 	 return FALSE;
437       }
438    }
439 
440    xf86DrvMsg(scrn->scrnIndex, from,
441 	      "Will alloc AGP framebuffer: %d kByte\n", scrn->videoRam);
442 
443    /* Calculate Fixed Offsets depending on graphics aperture size */
444    {
445       struct pci_device *bridge = intel_host_bridge ();
446       uint32_t   smram_miscc;
447 
448       pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC);
449 
450       if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
451 	 pI810->FbMapSize = 0x1000000;
452 	 pI810->DepthOffset = 0x1000000;
453 	 pI810->BackOffset = 0x1800000;
454       } else {
455 	 pI810->FbMapSize = 0x3000000;
456 	 pI810->DepthOffset = 0x3000000;
457 	 pI810->BackOffset = 0x3800000;
458       }
459    }
460 
461    /*
462     * If the driver can do gamma correction, it should call xf86SetGamma()
463     * here.
464     */
465    {
466       Gamma zeros = { 0.0, 0.0, 0.0 };
467 
468       if (!xf86SetGamma(scrn, zeros)) {
469 	 return FALSE;
470       }
471    }
472 
473    pI810->MaxClock = 0;
474    if (pI810->pEnt->device->dacSpeeds[0]) {
475       switch (scrn->bitsPerPixel) {
476       case 8:
477 	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8];
478 	 break;
479       case 16:
480 	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16];
481 	 break;
482       case 24:
483 	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24];
484 	 break;
485       case 32:				/* not supported */
486 	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32];
487 	 break;
488       }
489       if (!pI810->MaxClock)
490 	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0];
491    } else {
492       switch (scrn->bitsPerPixel) {
493       case 8:
494 	 pI810->MaxClock = 203000;
495 	 break;
496       case 16:
497 	 pI810->MaxClock = 163000;
498 	 break;
499       case 24:
500 	 pI810->MaxClock = 136000;
501 	 break;
502       case 32:				/* not supported */
503 	 pI810->MaxClock = 86000;
504       }
505    }
506    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
507    clockRanges->next = NULL;
508    /* 9.4MHz appears to be the smallest that works. */
509    clockRanges->minClock = 9500;
510    clockRanges->maxClock = pI810->MaxClock;
511    clockRanges->clockIndex = -1;
512    clockRanges->interlaceAllowed = TRUE;
513    clockRanges->doubleScanAllowed = FALSE;
514 
515    i = xf86ValidateModes(scrn, scrn->monitor->Modes,
516 			 scrn->display->modes, clockRanges,
517 #ifndef HAVE_DRI1
518 			 0, 320, 1600, 64 * scrn->bitsPerPixel,
519 #else
520 			 i810_pitches, 0, 0, 64 * scrn->bitsPerPixel,
521 #endif
522 			 200, 1200,
523 			 scrn->display->virtualX, scrn->display->virtualY,
524 			 scrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
525 
526    if (i == -1) {
527       I810FreeRec(scrn);
528       return FALSE;
529    }
530 
531    xf86PruneDriverModes(scrn);
532 
533    if (!i || !scrn->modes) {
534       xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No valid modes found\n");
535       I810FreeRec(scrn);
536       return FALSE;
537    }
538 
539    xf86SetCrtcForModes(scrn, INTERLACE_HALVE_V);
540 
541    scrn->currentMode = scrn->modes;
542 
543    xf86PrintModes(scrn);
544 
545    xf86SetDpi(scrn, 0, 0);
546 
547    if (!xf86LoadSubModule(scrn, "fb")) {
548       I810FreeRec(scrn);
549       return FALSE;
550    }
551 
552    if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
553       if (!xf86LoadSubModule(scrn, "ramdac")) {
554 	 I810FreeRec(scrn);
555 	 return FALSE;
556       }
557    }
558 
559    if (xf86GetOptValInteger
560        (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) {
561       xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
562 		 "video overlay key set to 0x%x\n", pI810->colorKey);
563    } else {
564       pI810->colorKey = (1 << scrn->offset.red) |
565 	    (1 << scrn->offset.green) |
566 	    (((scrn->mask.blue >> scrn->offset.blue) -
567 	      1) << scrn->offset.blue);
568    }
569 
570    pI810->allowPageFlip=FALSE;
571    enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
572 
573 #ifdef HAVE_DRI1
574    if (!pI810->directRenderingDisabled) {
575      pI810->allowPageFlip = enable;
576      if (pI810->allowPageFlip == TRUE)
577      {
578        if (!xf86LoadSubModule(scrn, "shadowfb")) {
579 	 pI810->allowPageFlip = 0;
580 	 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
581 		    "Couldn't load shadowfb module:\n");
582        }
583      }
584 
585      xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "page flipping %s\n",
586 		enable ? "enabled" : "disabled");
587 
588    }
589 #endif
590 
591    if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
592 			    &(pI810->numSurfaces))) {
593       xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
594 		 pI810->numSurfaces);
595       if (pI810->numSurfaces > 7) {
596 	 xf86DrvMsg(scrn->scrnIndex, X_PROBED,
597 		    "Using 7 XvMC Surfaces (Maximum Allowed).\n");
598 	 pI810->numSurfaces = 7;
599       }
600       if (pI810->numSurfaces < 6) {
601 	 xf86DrvMsg(scrn->scrnIndex, X_PROBED,
602 		    "Using 6 XvMC Surfaces (Minimum Allowed).\n");
603 	 pI810->numSurfaces = 6;
604       }
605    } else {
606       xf86DrvMsg(scrn->scrnIndex, X_INFO,
607 		 "XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
608       pI810->numSurfaces = 0;
609    }
610 
611 #ifdef HAVE_DRI1
612    /* Load the dri module if requested. */
613    if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
614       xf86LoadSubModule(scrn, "dri");
615    }
616 #endif
617 
618    return TRUE;
619 }
620 
621 static Bool
I810MapMMIO(ScrnInfoPtr scrn)622 I810MapMMIO(ScrnInfoPtr scrn)
623 {
624    I810Ptr pI810 = I810PTR(scrn);
625    struct pci_device *const device = pI810->PciInfo;
626    int err;
627 
628    err = pci_device_map_range (device,
629 			       pI810->MMIOAddr,
630 			       I810_REG_SIZE,
631 			       PCI_DEV_MAP_FLAG_WRITABLE,
632 			       (void **) &pI810->MMIOBase);
633    if (err)
634    {
635       xf86DrvMsg (scrn->scrnIndex, X_ERROR,
636 		  "Unable to map mmio BAR. %s (%d)\n",
637 		  strerror (err), err);
638       return FALSE;
639    }
640    return TRUE;
641 }
642 
643 static Bool
I810MapMem(ScrnInfoPtr scrn)644 I810MapMem(ScrnInfoPtr scrn)
645 {
646    I810Ptr pI810 = I810PTR(scrn);
647    struct pci_device *const device = pI810->PciInfo;
648    int err;
649 
650    if (!I810MapMMIO(scrn))
651       return FALSE;
652 
653    err = pci_device_map_range (device,
654 			       pI810->LinearAddr,
655 			       pI810->FbMapSize,
656 			       PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
657 			       (void **) &pI810->FbBase);
658    if (err)
659    {
660       xf86DrvMsg (scrn->scrnIndex, X_ERROR,
661 		  "Unable to map frame buffer BAR. %s (%d)\n",
662 		  strerror (err), err);
663       return FALSE;
664    }
665 
666    pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
667 
668    return TRUE;
669 }
670 
671 static void
I810UnmapMMIO(ScrnInfoPtr scrn)672 I810UnmapMMIO(ScrnInfoPtr scrn)
673 {
674    I810Ptr pI810 = I810PTR(scrn);
675 
676    pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE);
677    pI810->MMIOBase = NULL;
678 }
679 
680 static Bool
I810UnmapMem(ScrnInfoPtr scrn)681 I810UnmapMem(ScrnInfoPtr scrn)
682 {
683    I810Ptr pI810 = I810PTR(scrn);
684 
685    pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize);
686    pI810->FbBase = NULL;
687    I810UnmapMMIO(scrn);
688    return TRUE;
689 }
690 
691 /* Famous last words
692  */
693 void
I810PrintErrorState(ScrnInfoPtr scrn)694 I810PrintErrorState(ScrnInfoPtr scrn)
695 {
696    I810Ptr pI810 = I810PTR(scrn);
697 
698    ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
699 	  (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR));
700 
701    ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR),
702 	  (unsigned long) INREG(IPEHR));
703 
704    ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
705 	  (unsigned long) INREG(LP_RING + RING_TAIL),
706 	  (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
707 	  (unsigned long) INREG(LP_RING + RING_LEN),
708 	  (unsigned long) INREG(LP_RING + RING_START));
709 
710    ErrorF("eir: %x esr: %x emr: %x\n",
711 	  INREG16(EIR), INREG16(ESR), INREG16(EMR));
712 
713    ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
714 
715    ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE),
716 	  (unsigned long) INREG(INST_PS));
717 
718    ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
719 	  INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
720 }
721 
722 /*
723  * I810Save --
724  *
725  * This function saves the video state.  It reads all of the SVGA registers
726  * into the vgaI810Rec data structure.  There is in general no need to
727  * mask out bits here - just read the registers.
728  */
729 static void
DoSave(ScrnInfoPtr scrn,vgaRegPtr vgaReg,I810RegPtr i810Reg,Bool saveFonts)730 DoSave(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
731        Bool saveFonts)
732 {
733    I810Ptr pI810;
734    vgaHWPtr hwp;
735    int i;
736 
737    pI810 = I810PTR(scrn);
738    hwp = VGAHWPTR(scrn);
739 
740    /*
741     * This function will handle creating the data structure and filling
742     * in the generic VGA portion.
743     */
744    if (saveFonts)
745       vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP);
746    else
747       vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
748 
749    /*
750     * The port I/O code necessary to read in the extended registers
751     * into the fields of the vgaI810Rec structure goes here.
752     */
753    i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL);
754    i810Reg->AddressMapping = hwp->readGr(hwp, ADDRESS_MAPPING);
755    i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
756    i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
757    i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
758    i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
759 
760    i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL);
761    i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
762    i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
763    i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
764    i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
765    i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
766    i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET);
767    i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL);
768 
769    i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
770    i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
771    i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
772    i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
773    i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
774 
775    for (i = 0; i < 8; i++)
776       i810Reg->Fence[i] = INREG(FENCE + i * 4);
777 
778    i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
779    i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
780    i810Reg->LprbStart = INREG(LP_RING + RING_START);
781    i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
782 
783    if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
784        i810Reg->LprbLen & RING_VALID) {
785       I810PrintErrorState(scrn);
786       FatalError("Active ring not flushed\n");
787    }
788 }
789 
790 static void
I810Save(ScrnInfoPtr scrn)791 I810Save(ScrnInfoPtr scrn)
792 {
793    vgaHWPtr hwp;
794    I810Ptr pI810;
795    uint32_t temp;
796 
797    hwp = VGAHWPTR(scrn);
798    pI810 = I810PTR(scrn);
799    DoSave(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
800 
801    temp = INREG(MEMMODE);
802    temp |= 4;
803    OUTREG(MEMMODE, temp);
804 }
805 
806 static void
i810PrintMode(vgaRegPtr vgaReg,I810RegPtr mode)807 i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode)
808 {
809    int i;
810 
811    ErrorF("   MiscOut: %x\n", vgaReg->MiscOutReg);
812 
813    ErrorF("SEQ: ");
814    for (i = 0; i < vgaReg->numSequencer; i++) {
815       if ((i & 7) == 0)
816 	 ErrorF("\n");
817       ErrorF("   %d: %x", i, vgaReg->Sequencer[i]);
818    }
819    ErrorF("\n");
820 
821    ErrorF("CRTC: ");
822    for (i = 0; i < vgaReg->numCRTC; i++) {
823       if ((i & 3) == 0)
824 	 ErrorF("\n");
825       ErrorF("   %d: %x", i, vgaReg->CRTC[i]);
826    }
827    ErrorF("\n");
828 
829    ErrorF("GFX: ");
830    for (i = 0; i < vgaReg->numGraphics; i++) {
831       if ((i & 7) == 0)
832 	 ErrorF("\n");
833       ErrorF("   %d: %x", i, vgaReg->Graphics[i]);
834    }
835    ErrorF("\n");
836 
837    ErrorF("ATTR: ");
838    for (i = 0; i < vgaReg->numAttribute; i++) {
839       if ((i & 7) == 0)
840 	 ErrorF("\n");
841       ErrorF("   %d: %x", i, vgaReg->Attribute[i]);
842    }
843    ErrorF("\n");
844 
845    ErrorF("   DisplayControl: %x\n", mode->DisplayControl);
846    ErrorF("   PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
847    ErrorF("   PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
848    ErrorF("   PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
849    ErrorF("   VideoClk2_M: %x\n", mode->VideoClk2_M);
850    ErrorF("   VideoClk2_N: %x\n", mode->VideoClk2_N);
851    ErrorF("   VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
852    ErrorF("   AddressMapping: %x\n", mode->AddressMapping);
853    ErrorF("   IOControl: %x\n", mode->IOControl);
854    ErrorF("   BitBLTControl: %x\n", mode->BitBLTControl);
855    ErrorF("   ExtVertTotal: %x\n", mode->ExtVertTotal);
856    ErrorF("   ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
857    ErrorF("   ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
858    ErrorF("   ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
859    ErrorF("   ExtHorizTotal: %x\n", mode->ExtHorizTotal);
860    ErrorF("   ExtHorizBlank: %x\n", mode->ExtHorizBlank);
861    ErrorF("   ExtOffset: %x\n", mode->ExtOffset);
862    ErrorF("   InterlaceControl: %x\n", mode->InterlaceControl);
863    ErrorF("   LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
864    ErrorF("   LprbTail: %x\n", mode->LprbTail);
865    ErrorF("   LprbHead: %x\n", mode->LprbHead);
866    ErrorF("   LprbStart: %x\n", mode->LprbStart);
867    ErrorF("   LprbLen: %x\n", mode->LprbLen);
868 }
869 
870 static void
DoRestore(ScrnInfoPtr scrn,vgaRegPtr vgaReg,I810RegPtr i810Reg,Bool restoreFonts)871 DoRestore(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
872 	  Bool restoreFonts)
873 {
874    I810Ptr pI810;
875    vgaHWPtr hwp;
876    unsigned char temp;
877    unsigned int itemp;
878    int i;
879 
880    pI810 = I810PTR(scrn);
881    hwp = VGAHWPTR(scrn);
882 
883    if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
884       ErrorF("Setting mode in I810Restore:\n");
885       i810PrintMode(vgaReg, i810Reg);
886    }
887 
888    vgaHWProtect(scrn, TRUE);
889 
890    usleep(50000);
891 
892    /* Turn off DRAM Refresh */
893    temp = INREG8(DRAM_ROW_CNTL_HI);
894    temp &= ~DRAM_REFRESH_RATE;
895    temp |= DRAM_REFRESH_DISABLE;
896    OUTREG8(DRAM_ROW_CNTL_HI, temp);
897 
898    usleep(1000);			/* Wait 1 ms */
899 
900    /* Write the M, N and P values */
901    OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M);
902    OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N);
903    OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
904 
905    /*
906     * Turn on 8 bit dac mode, if requested.  This is needed to make
907     * sure that vgaHWRestore writes the values into the DAC properly.
908     * The problem occurs if 8 bit dac mode is requested and the HW is
909     * in 6 bit dac mode.  If this happens, all the values are
910     * automatically shifted left twice by the HW and incorrect colors
911     * will be displayed on the screen.  The only time this can happen
912     * is at server startup time and when switching back from a VT.
913     */
914    temp = INREG8(PIXPIPE_CONFIG_0);
915    temp &= 0x7F;			/* Save all but the 8 bit dac mode bit */
916    temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
917    OUTREG8(PIXPIPE_CONFIG_0, temp);
918 
919    /*
920     * Code to restore any SVGA registers that have been saved/modified
921     * goes here.  Note that it is allowable, and often correct, to
922     * only modify certain bits in a register by a read/modify/write cycle.
923     *
924     * A special case - when using an external clock-setting program,
925     * this function must not change bits associated with the clock
926     * selection.  This condition can be checked by the condition:
927     *
928     *   if (i810Reg->std.NoClock >= 0)
929     *           restore clock-select bits.
930     */
931    if (restoreFonts)
932       vgaHWRestore(scrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
933    else
934       vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
935 
936    hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
937    hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
938    hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
939    hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
940    hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
941    hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
942    hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);
943 
944    temp = hwp->readCrtc(hwp, INTERLACE_CNTL);
945    temp &= ~INTERLACE_ENABLE;
946    temp |= i810Reg->InterlaceControl;
947    hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
948 
949    temp = hwp->readGr(hwp, ADDRESS_MAPPING);
950    temp &= 0xE0;			/* Save reserved bits 7:5 */
951    temp |= i810Reg->AddressMapping;
952    hwp->writeGr(hwp, ADDRESS_MAPPING, temp);
953 
954    /* Setting the OVRACT Register for video overlay */
955    {
956        uint32_t LCD_TV_Control = INREG(LCD_TV_C);
957        uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL);
958        uint32_t ActiveStart, ActiveEnd;
959 
960        if((LCD_TV_Control & LCD_TV_ENABLE)
961 	  && !(LCD_TV_Control & LCD_TV_VGAMOD)
962 	   && TV_HTotal) {
963 	   ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
964 	   ActiveEnd = (TV_HTotal & 0x3ff) - 31;
965        } else {
966 	   ActiveStart = i810Reg->OverlayActiveStart;
967 	   ActiveEnd = i810Reg->OverlayActiveEnd;
968        }
969        OUTREG(LCD_TV_OVRACT,
970 	      (ActiveEnd << 16) | ActiveStart);
971    }
972 
973    /* Turn on DRAM Refresh */
974    temp = INREG8(DRAM_ROW_CNTL_HI);
975    temp &= ~DRAM_REFRESH_RATE;
976    temp |= DRAM_REFRESH_60HZ;
977    OUTREG8(DRAM_ROW_CNTL_HI, temp);
978 
979    temp = INREG8(BITBLT_CNTL);
980    temp &= ~COLEXP_MODE;
981    temp |= i810Reg->BitBLTControl;
982    OUTREG8(BITBLT_CNTL, temp);
983 
984    temp = INREG8(DISPLAY_CNTL);
985    temp &= ~(VGA_WRAP_MODE | GUI_MODE);
986    temp |= i810Reg->DisplayControl;
987    OUTREG8(DISPLAY_CNTL, temp);
988 
989    temp = INREG8(PIXPIPE_CONFIG_0);
990    temp &= 0x64;			/* Save reserved bits 6:5,2 */
991    temp |= i810Reg->PixelPipeCfg0;
992    OUTREG8(PIXPIPE_CONFIG_0, temp);
993 
994    temp = INREG8(PIXPIPE_CONFIG_2);
995    temp &= 0xF3;			/* Save reserved bits 7:4,1:0 */
996    temp |= i810Reg->PixelPipeCfg2;
997    OUTREG8(PIXPIPE_CONFIG_2, temp);
998 
999    temp = INREG8(PIXPIPE_CONFIG_1);
1000    temp &= ~DISPLAY_COLOR_MODE;
1001    temp &= 0xEF;			/* Restore the CRT control bit */
1002    temp |= i810Reg->PixelPipeCfg1;
1003    OUTREG8(PIXPIPE_CONFIG_1, temp);
1004 
1005    OUTREG16(EIR, 0);
1006 
1007    itemp = INREG(FWATER_BLC);
1008    itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
1009 	      MM_BURST_LENGTH | MM_FIFO_WATERMARK);
1010    itemp |= i810Reg->LMI_FIFO_Watermark;
1011    OUTREG(FWATER_BLC, itemp);
1012 
1013    for (i = 0; i < 8; i++) {
1014       OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
1015       if (I810_DEBUG & DEBUG_VERBOSE_VGA)
1016 	 ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
1017    }
1018 
1019    /* First disable the ring buffer (Need to wait for empty first?, if so
1020     * should probably do it before entering this section)
1021     */
1022    itemp = INREG(LP_RING + RING_LEN);
1023    itemp &= ~RING_VALID_MASK;
1024    OUTREG(LP_RING + RING_LEN, itemp);
1025 
1026    /* Set up the low priority ring buffer.
1027     */
1028    OUTREG(LP_RING + RING_TAIL, 0);
1029    OUTREG(LP_RING + RING_HEAD, 0);
1030 
1031    pI810->LpRing->head = 0;
1032    pI810->LpRing->tail = 0;
1033 
1034    itemp = INREG(LP_RING + RING_START);
1035    itemp &= ~(START_ADDR);
1036    itemp |= i810Reg->LprbStart;
1037    OUTREG(LP_RING + RING_START, itemp);
1038 
1039    itemp = INREG(LP_RING + RING_LEN);
1040    itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
1041    itemp |= i810Reg->LprbLen;
1042    OUTREG(LP_RING + RING_LEN, itemp);
1043 
1044    if (!(vgaReg->Attribute[0x10] & 0x1)) {
1045       usleep(50000);
1046       if (restoreFonts)
1047 	 vgaHWRestore(scrn, vgaReg,
1048 		      VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
1049       else
1050 	 vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1051    }
1052 
1053    vgaHWProtect(scrn, FALSE);
1054 
1055    temp = hwp->readCrtc(hwp, IO_CTNL);
1056    temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
1057    temp |= i810Reg->IOControl;
1058    hwp->writeCrtc(hwp, IO_CTNL, temp);
1059 }
1060 
1061 static void
I810SetRingRegs(ScrnInfoPtr scrn)1062 I810SetRingRegs(ScrnInfoPtr scrn)
1063 {
1064    unsigned int itemp;
1065    I810Ptr pI810 = I810PTR(scrn);
1066 
1067    OUTREG(LP_RING + RING_TAIL, 0);
1068    OUTREG(LP_RING + RING_HEAD, 0);
1069 
1070    itemp = INREG(LP_RING + RING_START);
1071    itemp &= ~(START_ADDR);
1072    itemp |= pI810->LpRing->mem.Start;
1073    OUTREG(LP_RING + RING_START, itemp);
1074 
1075    itemp = INREG(LP_RING + RING_LEN);
1076    itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
1077    itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
1078    OUTREG(LP_RING + RING_LEN, itemp);
1079 }
1080 
1081 static void
I810Restore(ScrnInfoPtr scrn)1082 I810Restore(ScrnInfoPtr scrn)
1083 {
1084    vgaHWPtr hwp;
1085    I810Ptr pI810;
1086 
1087    hwp = VGAHWPTR(scrn);
1088    pI810 = I810PTR(scrn);
1089 
1090    DoRestore(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
1091 }
1092 
1093 /*
1094  * I810CalcVCLK --
1095  *
1096  * Determine the closest clock frequency to the one requested.
1097  */
1098 
1099 #define MAX_VCO_FREQ 600.0
1100 #define TARGET_MAX_N 30
1101 #define REF_FREQ 24.0
1102 
1103 #define CALC_VCLK(m,n,p) \
1104     (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
1105 
1106 static void
I810CalcVCLK(ScrnInfoPtr scrn,double freq)1107 I810CalcVCLK(ScrnInfoPtr scrn, double freq)
1108 {
1109    I810Ptr pI810 = I810PTR(scrn);
1110    I810RegPtr i810Reg = &pI810->ModeReg;
1111    int m, n, p;
1112    double f_out;
1113    double f_err;
1114    double f_vco;
1115    int m_best = 0, n_best = 0, p_best = 0;
1116    double f_target = freq;
1117    double err_max = 0.005;
1118    double err_target = 0.001;
1119    double err_best = 999999.0;
1120 
1121    p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);
1122    /* Make sure p is within range. */
1123    if (p_best > 5) {
1124       p_best = p = 5;
1125    }
1126 
1127    f_vco = f_target * (1 << p);
1128 
1129    n = 2;
1130    do {
1131       n++;
1132       m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
1133       if (m < 3)
1134 	 m = 3;
1135       f_out = CALC_VCLK(m, n, p);
1136       f_err = 1.0 - (f_target / f_out);
1137       if (fabs(f_err) < err_max) {
1138 	 m_best = m;
1139 	 n_best = n;
1140 	 err_best = f_err;
1141       }
1142    } while ((fabs(f_err) >= err_target) &&
1143 	    ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
1144 
1145    if (fabs(f_err) < err_target) {
1146       m_best = m;
1147       n_best = n;
1148    }
1149 
1150    i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;
1151    i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;
1152    i810Reg->VideoClk2_DivisorSel = (p_best << 4);
1153 
1154    xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, 3,
1155 		  "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
1156 		  "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
1157 		  i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
1158 		  i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
1159 }
1160 
1161 static Bool
I810SetMode(ScrnInfoPtr scrn,DisplayModePtr mode)1162 I810SetMode(ScrnInfoPtr scrn, DisplayModePtr mode)
1163 {
1164    I810Ptr pI810 = I810PTR(scrn);
1165    I810RegPtr i810Reg = &pI810->ModeReg;
1166    vgaRegPtr pVga = &VGAHWPTR(scrn)->ModeReg;
1167    double dclk = mode->Clock / 1000.0;
1168 
1169    switch (scrn->bitsPerPixel) {
1170    case 8:
1171       pVga->CRTC[0x13] = scrn->displayWidth >> 3;
1172       i810Reg->ExtOffset = scrn->displayWidth >> 11;
1173       i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
1174       i810Reg->BitBLTControl = COLEXP_8BPP;
1175       break;
1176    case 16:
1177       if (scrn->weight.green == 5) {
1178 	 i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
1179       } else {
1180 	 i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
1181       }
1182       pVga->CRTC[0x13] = scrn->displayWidth >> 2;
1183       i810Reg->ExtOffset = scrn->displayWidth >> 10;
1184       i810Reg->BitBLTControl = COLEXP_16BPP;
1185 
1186       /* Enable Palette Programming for Direct Color visuals. -jens */
1187       i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
1188       break;
1189    case 24:
1190       pVga->CRTC[0x13] = (scrn->displayWidth * 3) >> 3;
1191       i810Reg->ExtOffset = (scrn->displayWidth * 3) >> 11;
1192 
1193       i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
1194       i810Reg->BitBLTControl = COLEXP_24BPP;
1195 
1196       /* Enable Palette Programming for Direct Color visuals. -jens */
1197       i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
1198       break;
1199    default:
1200       break;
1201    }
1202 
1203    /* Turn on 8 bit dac if requested */
1204    if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
1205       i810Reg->PixelPipeCfg0 = DAC_6_BIT;
1206    else
1207       i810Reg->PixelPipeCfg0 = DAC_8_BIT;
1208 
1209    /* Do not delay CRT Blank: needed for video overlay */
1210    i810Reg->PixelPipeCfg1 |= 0x10;
1211 
1212    /* Turn on Extended VGA Interpretation */
1213    i810Reg->IOControl = EXTENDED_CRTC_CNTL;
1214 
1215    /* Turn on linear and page mapping */
1216    i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
1217 
1218    /* Turn on GUI mode */
1219    i810Reg->DisplayControl = HIRES_MODE;
1220 
1221    /* Calculate the extended CRTC regs */
1222    i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
1223    i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
1224    i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
1225    i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
1226    i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
1227    i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
1228 
1229    /*
1230     * the KGA fix in vgaHW.c results in the first
1231     * scanline and the first character clock (8 pixels)
1232     * of each scanline thereafter on display with an i810
1233     * to be blank. Restoring CRTC 3, 5, & 22 to their
1234     * "theoretical" values corrects the problem. KAO.
1235     */
1236    pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1237    pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1238 	 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1239    pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1240 
1241    i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
1242    vgaHWVBlankKGA(mode, pVga, 8, 0);
1243 
1244    /*
1245     * The following workarounds are needed to get video overlay working
1246     * at 1024x768 and 1280x1024 display resolutions.
1247     */
1248    if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
1249       i810Reg->ExtVertBlankStart = 2;
1250    }
1251    if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
1252       i810Reg->ExtVertBlankStart = 3;
1253    }
1254 
1255    /* OVRACT Register */
1256    i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
1257    i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
1258 
1259    /* Turn on interlaced mode if necessary */
1260    if (mode->Flags & V_INTERLACE) {
1261       i810Reg->InterlaceControl = INTERLACE_ENABLE;
1262       i810Reg->ExtVertDispEnd *= 2;
1263    } else
1264       i810Reg->InterlaceControl = INTERLACE_DISABLE;
1265 
1266    /*
1267     * Set the overscan color to 0.
1268     * NOTE: This only affects >8bpp mode.
1269     */
1270    pVga->Attribute[0x11] = 0;
1271 
1272    /*
1273     * Calculate the VCLK that most closely matches the requested dot
1274     * clock.
1275     */
1276    I810CalcVCLK(scrn, dclk);
1277 
1278    /* Since we program the clocks ourselves, always use VCLK2. */
1279    pVga->MiscOutReg |= 0x0C;
1280 
1281    /* Calculate the FIFO Watermark and Burst Length. */
1282    i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(scrn, dclk, FALSE);
1283 
1284    /* Setup the ring buffer */
1285    i810Reg->LprbTail = 0;
1286    i810Reg->LprbHead = 0;
1287    i810Reg->LprbStart = pI810->LpRing->mem.Start;
1288 
1289    if (i810Reg->LprbStart)
1290       i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |
1291 			  RING_NO_REPORT | RING_VALID);
1292    else
1293       i810Reg->LprbLen = RING_INVALID;
1294 
1295    return TRUE;
1296 }
1297 
1298 static Bool
I810ModeInit(ScrnInfoPtr scrn,DisplayModePtr mode)1299 I810ModeInit(ScrnInfoPtr scrn, DisplayModePtr mode)
1300 {
1301    vgaHWPtr hwp;
1302    I810Ptr pI810;
1303 
1304    hwp = VGAHWPTR(scrn);
1305    pI810 = I810PTR(scrn);
1306 
1307    vgaHWUnlock(hwp);
1308 
1309    if (!vgaHWInit(scrn, mode))
1310       return FALSE;
1311 
1312    scrn->vtSema = TRUE;
1313 
1314    if (!I810SetMode(scrn, mode))
1315       return FALSE;
1316 
1317 #ifdef HAVE_DRI1
1318    if (pI810->directRenderingEnabled) {
1319       DRILock(xf86ScrnToScreen(scrn), 0);
1320       pI810->LockHeld = 1;
1321    }
1322 #endif
1323 
1324    DoRestore(scrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
1325 
1326 #ifdef HAVE_DRI1
1327    if (pI810->directRenderingEnabled) {
1328       DRIUnlock(xf86ScrnToScreen(scrn));
1329       pI810->LockHeld = 0;
1330    }
1331 #endif
1332 
1333    return TRUE;
1334 }
1335 
1336 static void
I810LoadPalette15(ScrnInfoPtr scrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1337 I810LoadPalette15(ScrnInfoPtr scrn, int numColors, int *indices,
1338 		  LOCO * colors, VisualPtr pVisual)
1339 {
1340    vgaHWPtr hwp;
1341    int i, j, index;
1342    unsigned char r, g, b;
1343 
1344    hwp = VGAHWPTR(scrn);
1345 
1346    for (i = 0; i < numColors; i++) {
1347       index = indices[i];
1348       r = colors[index].red;
1349       g = colors[index].green;
1350       b = colors[index].blue;
1351       for (j = 0; j < 8; j++) {
1352 	 hwp->writeDacWriteAddr(hwp, (index << 3) + j);
1353 	 hwp->writeDacData(hwp, r);
1354 	 hwp->writeDacData(hwp, g);
1355 	 hwp->writeDacData(hwp, b);
1356       }
1357    }
1358 }
1359 
1360 static void
I810LoadPalette16(ScrnInfoPtr scrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1361 I810LoadPalette16(ScrnInfoPtr scrn, int numColors, int *indices,
1362 		  LOCO * colors, VisualPtr pVisual)
1363 {
1364    vgaHWPtr hwp;
1365    int i, index;
1366    unsigned char r, g, b;
1367 
1368    hwp = VGAHWPTR(scrn);
1369 
1370    /* Load all four entries in each of the 64 color ranges.  -jens */
1371    for (i = 0; i < numColors; i++) {
1372       index = indices[i / 2];
1373       r = colors[index].red;
1374       b = colors[index].blue;
1375       index = indices[i];
1376       g = colors[index].green;
1377 
1378       hwp->writeDacWriteAddr(hwp, index << 2);
1379       hwp->writeDacData(hwp, r);
1380       hwp->writeDacData(hwp, g);
1381       hwp->writeDacData(hwp, b);
1382 
1383       hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
1384       hwp->writeDacData(hwp, r);
1385       hwp->writeDacData(hwp, g);
1386       hwp->writeDacData(hwp, b);
1387 
1388       hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
1389       hwp->writeDacData(hwp, r);
1390       hwp->writeDacData(hwp, g);
1391       hwp->writeDacData(hwp, b);
1392 
1393       hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
1394       hwp->writeDacData(hwp, r);
1395       hwp->writeDacData(hwp, g);
1396       hwp->writeDacData(hwp, b);
1397 
1398       i++;
1399       index = indices[i];
1400       g = colors[index].green;
1401 
1402       hwp->writeDacWriteAddr(hwp, index << 2);
1403       hwp->writeDacData(hwp, r);
1404       hwp->writeDacData(hwp, g);
1405       hwp->writeDacData(hwp, b);
1406 
1407       hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
1408       hwp->writeDacData(hwp, r);
1409       hwp->writeDacData(hwp, g);
1410       hwp->writeDacData(hwp, b);
1411 
1412       hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
1413       hwp->writeDacData(hwp, r);
1414       hwp->writeDacData(hwp, g);
1415       hwp->writeDacData(hwp, b);
1416 
1417       hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
1418       hwp->writeDacData(hwp, r);
1419       hwp->writeDacData(hwp, g);
1420       hwp->writeDacData(hwp, b);
1421    }
1422 }
1423 
1424 static void
I810LoadPalette24(ScrnInfoPtr scrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1425 I810LoadPalette24(ScrnInfoPtr scrn, int numColors, int *indices,
1426 		  LOCO * colors, VisualPtr pVisual)
1427 {
1428    vgaHWPtr hwp;
1429    int i, index;
1430    unsigned char r, g, b;
1431 
1432    hwp = VGAHWPTR(scrn);
1433 
1434    for (i = 0; i < numColors; i++) {
1435       index = indices[i];
1436       r = colors[index].red;
1437       g = colors[index].green;
1438       b = colors[index].blue;
1439       hwp->writeDacWriteAddr(hwp, index);
1440       hwp->writeDacData(hwp, r);
1441       hwp->writeDacData(hwp, g);
1442       hwp->writeDacData(hwp, b);
1443    }
1444 }
1445 
1446 Bool
I810AllocateFront(ScrnInfoPtr scrn)1447 I810AllocateFront(ScrnInfoPtr scrn)
1448 {
1449    I810Ptr pI810 = I810PTR(scrn);
1450    int cache_lines = -1;
1451 
1452    if (pI810->DoneFrontAlloc)
1453       return TRUE;
1454 
1455    memset(&(pI810->FbMemBox), 0, sizeof(BoxRec));
1456    /* Alloc FrontBuffer/Ring/Accel memory */
1457    pI810->FbMemBox.x1 = 0;
1458    pI810->FbMemBox.x2 = scrn->displayWidth;
1459    pI810->FbMemBox.y1 = 0;
1460    pI810->FbMemBox.y2 = scrn->virtualY;
1461 
1462    xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines);
1463 
1464    if (cache_lines < 0) {
1465       /* make sure there is enough for two DVD sized YUV buffers */
1466       cache_lines = (scrn->depth == 24) ? 256 : 384;
1467       if (scrn->displayWidth <= 1024)
1468 	 cache_lines *= 2;
1469    }
1470    /* Make sure there's enough space for cache_lines.
1471     *
1472     * Had a bug here where maxCacheLines was computed to be less than 0.
1473     * Not sure why 256 was initially subtracted from videoRam in the
1474     * maxCacheLines calculation, but that was causing a problem
1475     * for configurations that have exactly enough Ram for the framebuffer.
1476     * Common code should catch the case where there isn't enough space for
1477     * framebuffer, we'll just check for no space for cache_lines.  -jens
1478     *
1479     */
1480    {
1481       int maxCacheLines;
1482 
1483       maxCacheLines = (scrn->videoRam * 1024 /
1484 		       (scrn->bitsPerPixel / 8) /
1485 		       scrn->displayWidth) - scrn->virtualY;
1486       if (maxCacheLines < 0)
1487 	 maxCacheLines = 0;
1488       if (cache_lines > maxCacheLines)
1489 	 cache_lines = maxCacheLines;
1490    }
1491    pI810->FbMemBox.y2 += cache_lines;
1492 
1493    xf86DrvMsg(scrn->scrnIndex, X_INFO,
1494 	      "Adding %i scanlines for pixmap caching\n", cache_lines);
1495 
1496    /* Reserve room for the framebuffer and pixcache.  Put at the top
1497     * of memory so we can have nice alignment for the tiled regions at
1498     * the start of memory.
1499     */
1500 
1501    if (!I810AllocLow(&(pI810->FrontBuffer),
1502 		     &(pI810->SysMem),
1503 		     ALIGN((pI810->FbMemBox.x2 * pI810->FbMemBox.y2 * pI810->cpp), 4096))) {
1504       xf86DrvMsg(scrn->scrnIndex,
1505 		 X_WARNING, "Framebuffer allocation failed\n");
1506       return FALSE;
1507    }
1508 
1509    memset(pI810->LpRing, 0, sizeof(I810RingBuffer));
1510    if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) {
1511       pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1;
1512       pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
1513       pI810->LpRing->head = 0;
1514       pI810->LpRing->tail = 0;
1515       pI810->LpRing->space = 0;
1516    } else {
1517       xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1518 		 "Ring buffer allocation failed\n");
1519       return (FALSE);
1520    }
1521 
1522    if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) ||
1523        I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) {
1524       xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n");
1525    } else {
1526       xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1527 		 "Scratch memory allocation failed\n");
1528       return (FALSE);
1529    }
1530 
1531    pI810->DoneFrontAlloc = TRUE;
1532    return TRUE;
1533 }
1534 
1535 static Bool
I810ScreenInit(SCREEN_INIT_ARGS_DECL)1536 I810ScreenInit(SCREEN_INIT_ARGS_DECL)
1537 {
1538    ScrnInfoPtr scrn;
1539    vgaHWPtr hwp;
1540    I810Ptr pI810;
1541    VisualPtr visual;
1542 
1543    scrn = xf86ScreenToScrn(screen);
1544    pI810 = I810PTR(scrn);
1545    hwp = VGAHWPTR(scrn);
1546 
1547    pI810->LpRing = calloc(sizeof(I810RingBuffer),1);
1548    if (!pI810->LpRing) {
1549      xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1550 		"Could not allocate lpring data structure.\n");
1551      return FALSE;
1552    }
1553 
1554    miClearVisualTypes();
1555 
1556    /* Re-implemented Direct Color support, -jens */
1557    if (!miSetVisualTypes(scrn->depth, miGetDefaultVisualMask(scrn->depth),
1558 			 scrn->rgbBits, scrn->defaultVisual))
1559       return FALSE;
1560 
1561    if (!miSetPixmapDepths())
1562       return FALSE;
1563 
1564    {
1565       I810RegPtr i810Reg = &pI810->ModeReg;
1566       int i;
1567 
1568       for (i = 0; i < 8; i++)
1569 	 i810Reg->Fence[i] = 0;
1570    }
1571 
1572    /* Have to init the DRM earlier than in other drivers to get agp
1573     * memory.  Wonder if this is going to be a problem...
1574     */
1575 
1576 #ifdef HAVE_DRI1
1577    /*
1578     * Setup DRI after visuals have been established, but before fbScreenInit
1579     * is called.   fbScreenInit will eventually call into the drivers
1580     * InitGLXVisuals call back.
1581     */
1582    /*
1583     * pI810->directRenderingDisabled is set once in PreInit.  Reinitialise
1584     * pI810->directRenderingEnabled based on it each generation.
1585     */
1586    pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
1587 
1588    if (pI810->directRenderingEnabled==TRUE)
1589      pI810->directRenderingEnabled = I810DRIScreenInit(screen);
1590 
1591 #else
1592    pI810->directRenderingEnabled = FALSE;
1593    if (!I810AllocateGARTMemory(scrn))
1594       return FALSE;
1595    if (!I810AllocateFront(scrn))
1596       return FALSE;
1597 #endif
1598 
1599    if (!I810MapMem(scrn))
1600       return FALSE;
1601 
1602    scrn->memPhysBase = (unsigned long)pI810->LinearAddr;
1603    scrn->fbOffset = 0;
1604 
1605    vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0);
1606    vgaHWGetIOBase(hwp);
1607    if (!vgaHWMapMem(scrn))
1608       return FALSE;
1609 
1610    I810Save(scrn);
1611    if (!I810ModeInit(scrn, scrn->currentMode))
1612       return FALSE;
1613 
1614    I810SaveScreen(screen, FALSE);
1615    I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0));
1616 
1617    if (!fbScreenInit(screen, pI810->FbBase + scrn->fbOffset,
1618 		     scrn->virtualX, scrn->virtualY,
1619 		     scrn->xDpi, scrn->yDpi,
1620 		     scrn->displayWidth, scrn->bitsPerPixel))
1621       return FALSE;
1622 
1623    if (scrn->bitsPerPixel > 8) {
1624       /* Fixup RGB ordering */
1625       visual = screen->visuals + screen->numVisuals;
1626       while (--visual >= screen->visuals) {
1627 	 if ((visual->class | DynamicClass) == DirectColor) {
1628 	    visual->offsetRed = scrn->offset.red;
1629 	    visual->offsetGreen = scrn->offset.green;
1630 	    visual->offsetBlue = scrn->offset.blue;
1631 	    visual->redMask = scrn->mask.red;
1632 	    visual->greenMask = scrn->mask.green;
1633 	    visual->blueMask = scrn->mask.blue;
1634 	 }
1635       }
1636    }
1637 
1638    fbPictureInit(screen, NULL, 0);
1639 
1640    xf86SetBlackWhitePixels(screen);
1641 
1642 #ifdef HAVE_DRI1
1643    if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) {
1644       pI810->directRenderingEnabled = FALSE;
1645       I810DRICloseScreen(screen);
1646    }
1647 
1648    if (!pI810->directRenderingEnabled) {
1649       pI810->DoneFrontAlloc = FALSE;
1650       if (!I810AllocateGARTMemory(scrn))
1651 	 return FALSE;
1652       if (!I810AllocateFront(scrn))
1653 	 return FALSE;
1654    }
1655 #endif
1656 
1657 #ifdef HAVE_DGAPROC_H
1658    I810DGAInit(screen);
1659 #endif
1660 
1661    if (!xf86InitFBManager(screen, &(pI810->FbMemBox))) {
1662       xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1663 		 "Failed to init memory manager\n");
1664       return FALSE;
1665    }
1666 
1667    if (pI810->LpRing->mem.Size != 0) {
1668       I810SetRingRegs(scrn);
1669 
1670       if (!pI810->noAccel && !I810AccelInit(screen)) {
1671 	 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1672 		    "Hardware acceleration initialization failed\n");
1673       }
1674 
1675       I810EmitFlush(scrn);
1676    }
1677 
1678    xf86SetBackingStore(screen);
1679    xf86SetSilkenMouse(screen);
1680 
1681    miDCInitialize(screen, xf86GetPointerScreenFuncs());
1682 
1683    if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
1684       if (!I810CursorInit(screen)) {
1685 	 xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1686 		    "Hardware cursor initialization failed\n");
1687       }
1688    }
1689 
1690    if (!miCreateDefColormap(screen))
1691       return FALSE;
1692 
1693    /* Use driver specific palette load routines for Direct Color support. -jens */
1694    if (scrn->bitsPerPixel == 16) {
1695       if (scrn->depth == 15) {
1696 	 if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette15, NULL,
1697 				  CMAP_PALETTED_TRUECOLOR |
1698 				  CMAP_RELOAD_ON_MODE_SWITCH))
1699 	    return FALSE;
1700       } else {
1701 	 if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette16, NULL,
1702 				  CMAP_PALETTED_TRUECOLOR |
1703 				  CMAP_RELOAD_ON_MODE_SWITCH))
1704 	    return FALSE;
1705       }
1706    } else {
1707       if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette24, NULL,
1708 			       CMAP_PALETTED_TRUECOLOR |
1709 			       CMAP_RELOAD_ON_MODE_SWITCH))
1710 	 return FALSE;
1711    }
1712 
1713    xf86DPMSInit(screen, I810DisplayPowerManagementSet, 0);
1714 
1715    I810InitVideo(screen);
1716 
1717 #ifdef HAVE_DRI1
1718    if (pI810->directRenderingEnabled) {
1719       /* Now that mi, fb, drm and others have done their thing,
1720        * complete the DRI setup.
1721        */
1722       pI810->directRenderingEnabled = I810DRIFinishScreenInit(screen);
1723    }
1724 #ifdef XvMCExtension
1725    if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
1726       /* Initialize the hardware motion compensation code */
1727       I810InitMC(screen);
1728    }
1729 #endif
1730 #endif
1731 
1732    if (pI810->directRenderingEnabled) {
1733       xf86DrvMsg(scrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
1734    } else {
1735       xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
1736    }
1737 
1738    screen->SaveScreen = I810SaveScreen;
1739    pI810->CloseScreen = screen->CloseScreen;
1740    screen->CloseScreen = I810CloseScreen;
1741 
1742    if (serverGeneration == 1)
1743       xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1744 
1745    return TRUE;
1746 }
1747 
1748 Bool
I810SwitchMode(SWITCH_MODE_ARGS_DECL)1749 I810SwitchMode(SWITCH_MODE_ARGS_DECL)
1750 {
1751    SCRN_INFO_PTR(arg);
1752 #if 0
1753    I810Ptr pI810 = I810PTR(scrn);
1754 #endif
1755    if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
1756       ErrorF("I810SwitchMode %p\n", (void *)mode);
1757 
1758 #if 0
1759 /*
1760  * This has been added to prevent lockups on mode switch by modeling
1761  * it after I810Leave()/I810Enter() but the call to I810DRILeave()
1762  * was missing so it caused the opposite.
1763  * The version below works but it is doubtful it does any good.
1764  * If lockups on mode switch are still seen revisit this code. (EE)
1765  */
1766 
1767 # ifdef HAVE_DRI1
1768    if (pI810->directRenderingEnabled) {
1769       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1770 	 ErrorF("calling dri lock\n");
1771       DRILock(screenInfo.screens[scrnIndex], 0);
1772       pI810->LockHeld = 1;
1773    }
1774 # endif
1775    if (pI810->AccelInfoRec != NULL) {
1776       I810RefreshRing(scrn);
1777       I810Sync(scrn);
1778       pI810->AccelInfoRec->NeedToSync = FALSE;
1779    }
1780    I810Restore(scrn);
1781 
1782 # ifdef HAVE_DRI1
1783    if (pI810->directRenderingEnabled) {
1784        if (!I810DRILeave(scrn))
1785 	   return FALSE;
1786        if (!I810DRIEnter(scrn))
1787 	   return FALSE;
1788 
1789        if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1790 	   ErrorF("calling dri unlock\n");
1791        DRIUnlock(screenInfo.screens[scrnIndex]);
1792        pI810->LockHeld = 0;
1793    }
1794 # endif
1795 #endif
1796    return I810ModeInit(scrn, mode);
1797 }
1798 
1799 void
I810AdjustFrame(ADJUST_FRAME_ARGS_DECL)1800 I810AdjustFrame(ADJUST_FRAME_ARGS_DECL)
1801 {
1802    SCRN_INFO_PTR(arg);
1803    I810Ptr pI810 = I810PTR(scrn);
1804    vgaHWPtr hwp = VGAHWPTR(scrn);
1805    int Base;
1806 
1807 #if 1
1808    if (pI810->showCache) {
1809      int lastline = pI810->FbMapSize /
1810        ((scrn->displayWidth * scrn->bitsPerPixel) / 8);
1811      lastline -= scrn->currentMode->VDisplay;
1812      if (y > 0)
1813        y += scrn->currentMode->VDisplay;
1814      if (y > lastline) y = lastline;
1815    }
1816 #endif
1817    Base = (y * scrn->displayWidth + x) >> 2;
1818 
1819    if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
1820       ErrorF("I810AdjustFrame %d,%d\n", x, y);
1821 
1822    switch (scrn->bitsPerPixel) {
1823    case 8:
1824       break;
1825    case 16:
1826       Base *= 2;
1827       break;
1828    case 24:
1829       /* KW: Need to do 16-pixel alignment for i810, otherwise you
1830        * get bad watermark problems.  Need to fixup the mouse
1831        * pointer positioning to take this into account.
1832        */
1833       pI810->CursorOffset = (Base & 0x3) * 4;
1834       Base &= ~0x3;
1835       Base *= 3;
1836       break;
1837    case 32:
1838       Base *= 4;
1839       break;
1840    }
1841 
1842    hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF);
1843    hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8);
1844    hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22);
1845    hwp->writeCrtc(hwp, EXT_START_ADDR,
1846 		  ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE));
1847 }
1848 
1849 /* These functions are usually called with the lock **not held**.
1850  */
1851 static Bool
I810EnterVT(VT_FUNC_ARGS_DECL)1852 I810EnterVT(VT_FUNC_ARGS_DECL)
1853 {
1854    SCRN_INFO_PTR(arg);
1855 
1856 #ifdef HAVE_DRI1
1857    I810Ptr pI810 = I810PTR(scrn);
1858 #endif
1859 
1860    if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1861       ErrorF("\n\nENTER VT\n");
1862 
1863    if (!I810BindGARTMemory(scrn)) {
1864       return FALSE;
1865    }
1866 #ifdef HAVE_DRI1
1867    if (!I810DRIEnter(scrn)) {
1868       return FALSE;
1869    }
1870    if (pI810->directRenderingEnabled) {
1871       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1872 	 ErrorF("calling dri unlock\n");
1873       DRIUnlock(xf86ScrnToScreen(scrn));
1874       pI810->LockHeld = 0;
1875    }
1876 #endif
1877 
1878    if (!I810ModeInit(scrn, scrn->currentMode))
1879       return FALSE;
1880    I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0));
1881    return TRUE;
1882 }
1883 
1884 static void
I810LeaveVT(VT_FUNC_ARGS_DECL)1885 I810LeaveVT(VT_FUNC_ARGS_DECL)
1886 {
1887    SCRN_INFO_PTR(arg);
1888    vgaHWPtr hwp = VGAHWPTR(scrn);
1889    I810Ptr pI810 = I810PTR(scrn);
1890 
1891    if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1892       ErrorF("\n\n\nLeave VT\n");
1893 
1894 #ifdef HAVE_DRI1
1895    if (pI810->directRenderingEnabled) {
1896       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
1897 	 ErrorF("calling dri lock\n");
1898       DRILock(xf86ScrnToScreen(scrn), 0);
1899       pI810->LockHeld = 1;
1900    }
1901 #endif
1902 
1903 #ifdef HAVE_XAA_H
1904    if (pI810->AccelInfoRec != NULL) {
1905       I810RefreshRing(scrn);
1906       I810Sync(scrn);
1907       pI810->AccelInfoRec->NeedToSync = FALSE;
1908    }
1909 #endif
1910    I810Restore(scrn);
1911 
1912    if (!I810UnbindGARTMemory(scrn))
1913       return;
1914 #ifdef HAVE_DRI1
1915    if (!I810DRILeave(scrn))
1916       return;
1917 #endif
1918 
1919    vgaHWLock(hwp);
1920 }
1921 
1922 static Bool
I810CloseScreen(CLOSE_SCREEN_ARGS_DECL)1923 I810CloseScreen(CLOSE_SCREEN_ARGS_DECL)
1924 {
1925    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1926    vgaHWPtr hwp = VGAHWPTR(scrn);
1927    I810Ptr pI810 = I810PTR(scrn);
1928 #ifdef HAVE_XAA_H
1929    XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
1930 #endif
1931 
1932    if (scrn->vtSema == TRUE) {
1933 #ifdef HAVE_XAA_H
1934       if (pI810->AccelInfoRec != NULL) {
1935 	 I810RefreshRing(scrn);
1936 	 I810Sync(scrn);
1937 	 pI810->AccelInfoRec->NeedToSync = FALSE;
1938       }
1939 #endif
1940       I810Restore(scrn);
1941       vgaHWLock(hwp);
1942    }
1943 #ifdef HAVE_DRI1
1944    if (pI810->directRenderingEnabled) {
1945       I810DRICloseScreen(screen);
1946       pI810->directRenderingEnabled = FALSE;
1947    }
1948 #endif
1949 
1950    if (scrn->vtSema == TRUE) {
1951       I810UnbindGARTMemory(scrn);
1952       I810Restore(scrn);
1953       vgaHWLock(hwp);
1954    }
1955 
1956    I810UnmapMem(scrn);
1957    vgaHWUnmapMem(scrn);
1958 
1959    if (pI810->ScanlineColorExpandBuffers) {
1960       free(pI810->ScanlineColorExpandBuffers);
1961       pI810->ScanlineColorExpandBuffers = NULL;
1962    }
1963 
1964 #ifdef HAVE_XAA_H
1965    if (infoPtr) {
1966       if (infoPtr->ScanlineColorExpandBuffers)
1967 	 free(infoPtr->ScanlineColorExpandBuffers);
1968       XAADestroyInfoRec(infoPtr);
1969       pI810->AccelInfoRec = NULL;
1970    }
1971 #endif
1972 
1973    if (pI810->CursorInfoRec) {
1974       xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
1975       pI810->CursorInfoRec = NULL;
1976    }
1977 
1978    /* Free all allocated video ram.
1979     */
1980    pI810->SysMem = pI810->SavedSysMem;
1981    pI810->DcacheMem = pI810->SavedDcacheMem;
1982    pI810->DoneFrontAlloc = FALSE;
1983 
1984    /* Need to actually close the gart fd, or the unbound memory will just sit
1985     * around.  Will prevent the Xserver from recycling.
1986     */
1987    xf86GARTCloseScreen(scrn->scrnIndex);
1988 
1989    free(pI810->LpRing);
1990    pI810->LpRing = NULL;
1991 
1992    scrn->vtSema = FALSE;
1993    screen->CloseScreen = pI810->CloseScreen;
1994    return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
1995 }
1996 
1997 static void
I810FreeScreen(FREE_SCREEN_ARGS_DECL)1998 I810FreeScreen(FREE_SCREEN_ARGS_DECL)
1999 {
2000    SCRN_INFO_PTR(arg);
2001    I810FreeRec(scrn);
2002    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
2003      vgaHWFreeHWRec(scrn);
2004 }
2005 
2006 static ModeStatus
I810ValidMode(SCRN_ARG_TYPE arg,DisplayModePtr mode,Bool verbose,int flags)2007 I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
2008 {
2009    SCRN_INFO_PTR(arg);
2010    if (mode->Flags & V_INTERLACE) {
2011       if (verbose) {
2012 	 xf86DrvMsg(scrn->scrnIndex, X_PROBED,
2013 		    "Removing interlaced mode \"%s\"\n", mode->name);
2014       }
2015       return MODE_BAD;
2016    }
2017    return MODE_OK;
2018 }
2019 
2020 static Bool
I810SaveScreen(ScreenPtr screen,Bool unblack)2021 I810SaveScreen(ScreenPtr screen, Bool unblack)
2022 {
2023    return vgaHWSaveScreen(screen, unblack);
2024 }
2025 
2026 static void
I810DisplayPowerManagementSet(ScrnInfoPtr scrn,int PowerManagementMode,int flags)2027 I810DisplayPowerManagementSet(ScrnInfoPtr scrn, int PowerManagementMode,
2028 			      int flags)
2029 {
2030    I810Ptr pI810;
2031    unsigned char SEQ01 = 0;
2032    int DPMSSyncSelect = 0;
2033    vgaHWPtr hwp;
2034 
2035    pI810 = I810PTR(scrn);
2036    switch (PowerManagementMode) {
2037    case DPMSModeOn:
2038       /* Screen: On; HSync: On, VSync: On */
2039       SEQ01 = 0x00;
2040       DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
2041       break;
2042    case DPMSModeStandby:
2043       /* Screen: Off; HSync: Off, VSync: On */
2044       SEQ01 = 0x20;
2045       DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
2046       break;
2047    case DPMSModeSuspend:
2048       /* Screen: Off; HSync: On, VSync: Off */
2049       SEQ01 = 0x20;
2050       DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
2051       break;
2052    case DPMSModeOff:
2053       /* Screen: Off; HSync: Off, VSync: Off */
2054       SEQ01 = 0x20;
2055       DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
2056       break;
2057    }
2058 
2059    hwp = VGAHWPTR(scrn);
2060 
2061    /* Turn the screen on/off */
2062    SEQ01 |= hwp->readSeq(hwp, 0x01) & ~0x20;
2063    hwp->writeSeq(hwp, 0x01, SEQ01);
2064 
2065    /* Set the DPMS mode */
2066    OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
2067 }
2068 
2069 const OptionInfoRec *
lg_i810_available_options(int chipid,int busid)2070 lg_i810_available_options(int chipid, int busid)
2071 {
2072    return I810Options;
2073 }
2074 
2075 
lg_i810_init(ScrnInfoPtr scrn)2076 Bool lg_i810_init(ScrnInfoPtr scrn)
2077 {
2078     scrn->PreInit = I810PreInit;
2079     scrn->ScreenInit = I810ScreenInit;
2080     scrn->SwitchMode = I810SwitchMode;
2081     scrn->AdjustFrame = I810AdjustFrame;
2082     scrn->EnterVT = I810EnterVT;
2083     scrn->LeaveVT = I810LeaveVT;
2084     scrn->FreeScreen = I810FreeScreen;
2085     scrn->ValidMode = I810ValidMode;
2086     return TRUE;
2087 }
2088