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