1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include "apm.h"
7 #include "xf86cmap.h"
8 #include "shadowfb.h"
9 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
10 #include "xf86Resources.h"
11 #include "xf86RAC.h"
12 #endif
13 #include "xf86int10.h"
14 #include "vbe.h"
15
16 #include "opaque.h"
17 #ifdef HAVE_XEXTPROTO_71
18 #include <X11/extensions/dpmsconst.h>
19 #else
20 #define DPMS_SERVER
21 #include <X11/extensions/dpms.h>
22 #endif
23
24
25 #define APM_VERSION 4000
26 #define APM_NAME "APM"
27 #define APM_DRIVER_NAME "apm"
28 #define APM_MAJOR_VERSION PACKAGE_VERSION_MAJOR
29 #define APM_MINOR_VERSION PACKAGE_VERSION_MINOR
30 #define APM_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
31
32 #define PCI_VENDOR_ALLIANCE 0x1142
33 #define PCI_CHIP_AP6422 0x6422
34 #define PCI_CHIP_AT24 0x6424
35 #define PCI_CHIP_AT3D 0x643D
36
37 /* bytes to save for text/font data */
38 #define TEXT_AMOUNT 32768
39
40 /* Mandatory functions */
41 static const OptionInfoRec * ApmAvailableOptions(int chipid, int busid);
42 static void ApmIdentify(int flags);
43 static Bool ApmProbe(DriverPtr drv, int flags);
44 static Bool ApmPreInit(ScrnInfoPtr pScrn, int flags);
45 static Bool ApmScreenInit(SCREEN_INIT_ARGS_DECL);
46 static Bool ApmEnterVT(VT_FUNC_ARGS_DECL);
47 static void ApmLeaveVT(VT_FUNC_ARGS_DECL);
48 static Bool ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL);
49 static void ApmFreeScreen(FREE_SCREEN_ARGS_DECL);
50 static ModeStatus ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
51 Bool verbose, int flags);
52 static Bool ApmSaveScreen(ScreenPtr pScreen, int mode);
53 static void ApmUnlock(ApmPtr pApm);
54 static void ApmLock(ApmPtr pApm);
55 static void ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg,
56 ApmRegPtr ApmReg);
57 static void ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
58 LOCO *colors, VisualPtr pVisual);
59 static void ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn,
60 int PowerManagementMode,
61 int flags);
62 static void ApmProbeDDC(ScrnInfoPtr pScrn, int index);
63
64 #ifdef XF86RUSH
65 int ApmPixmapIndex = -1;
66 static unsigned long ApmGeneration = 0;
67 #endif
68
69 _X_EXPORT DriverRec APM = {
70 APM_VERSION,
71 APM_DRIVER_NAME,
72 ApmIdentify,
73 ApmProbe,
74 ApmAvailableOptions,
75 NULL,
76 0
77 };
78
79 static SymTabRec ApmChipsets[] = {
80 { AP6422, "AP6422" },
81 { AT24, "AT24" },
82 { AT3D, "AT3D" },
83 { -1, NULL }
84 };
85
86 static PciChipsets ApmPciChipsets[] = {
87 { PCI_CHIP_AP6422, PCI_CHIP_AP6422, RES_SHARED_VGA },
88 { PCI_CHIP_AT24, PCI_CHIP_AT24, RES_SHARED_VGA },
89 { PCI_CHIP_AT3D, PCI_CHIP_AT3D, RES_SHARED_VGA },
90 { -1, -1, RES_UNDEFINED }
91 };
92
93 typedef enum {
94 OPTION_SET_MCLK,
95 OPTION_SW_CURSOR,
96 OPTION_HW_CURSOR,
97 OPTION_NOLINEAR,
98 OPTION_NOACCEL,
99 OPTION_SHADOW_FB,
100 OPTION_PCI_BURST,
101 OPTION_REMAP_DPMS_ON,
102 OPTION_REMAP_DPMS_STANDBY,
103 OPTION_REMAP_DPMS_SUSPEND,
104 OPTION_REMAP_DPMS_OFF,
105 OPTION_PCI_RETRY
106 } ApmOpts;
107
108 static const OptionInfoRec ApmOptions[] =
109 {
110 {OPTION_SET_MCLK, "SetMclk", OPTV_FREQ,
111 {0}, FALSE},
112 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN,
113 {0}, FALSE},
114 {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN,
115 {0}, TRUE},
116 {OPTION_NOLINEAR, "NoLinear", OPTV_BOOLEAN,
117 {0}, FALSE},
118 {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN,
119 {0}, FALSE},
120 {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN,
121 {0}, FALSE},
122 {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN,
123 {0}, FALSE},
124 {OPTION_REMAP_DPMS_ON, "Remap_DPMS_On", OPTV_ANYSTR,
125 {0}, FALSE},
126 {OPTION_REMAP_DPMS_STANDBY, "Remap_DPMS_Standby", OPTV_ANYSTR,
127 {0}, FALSE},
128 {OPTION_REMAP_DPMS_SUSPEND, "Remap_DPMS_Suspend", OPTV_ANYSTR,
129 {0}, FALSE},
130 {OPTION_REMAP_DPMS_OFF, "Remap_DPMS_Off", OPTV_ANYSTR,
131 {0}, FALSE},
132 {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN,
133 {0}, FALSE},
134 {-1, NULL, OPTV_NONE,
135 {0}, FALSE}
136 };
137
138 #ifdef XFree86LOADER
139
140 static XF86ModuleVersionInfo apmVersRec = {
141 "apm",
142 MODULEVENDORSTRING,
143 MODINFOSTRING1,
144 MODINFOSTRING2,
145 XORG_VERSION_CURRENT,
146 APM_MAJOR_VERSION, APM_MINOR_VERSION, APM_PATCHLEVEL,
147 ABI_CLASS_VIDEODRV, /* This is a video driver */
148 ABI_VIDEODRV_VERSION,
149 MOD_CLASS_VIDEODRV,
150 {0,0,0,0}
151 };
152
153 static MODULESETUPPROTO(apmSetup);
154
155 /*
156 * This is the module init data.
157 * Its name has to be the driver name followed by ModuleData.
158 */
159 _X_EXPORT XF86ModuleData apmModuleData = { &apmVersRec, apmSetup, NULL };
160
161 static pointer
apmSetup(pointer module,pointer opts,int * errmaj,int * errmain)162 apmSetup(pointer module, pointer opts, int *errmaj, int *errmain)
163 {
164 static Bool setupDone = FALSE;
165
166 if (!setupDone) {
167 setupDone = TRUE;
168 xf86AddDriver(&APM, module, 0);
169
170 return (pointer)1;
171 }
172 else {
173 if (errmaj) *errmaj = LDR_ONCEONLY;
174 return NULL;
175 }
176 }
177 #endif
178
179 static Bool
ApmGetRec(ScrnInfoPtr pScrn)180 ApmGetRec(ScrnInfoPtr pScrn)
181 {
182 if (pScrn->driverPrivate)
183 return TRUE;
184 pScrn->driverPrivate = xnfcalloc(sizeof(ApmRec), 1);
185 /* pScrn->driverPrivate != NULL at this point */
186
187 return TRUE;
188 }
189
190 static void
ApmFreeRec(ScrnInfoPtr pScrn)191 ApmFreeRec(ScrnInfoPtr pScrn)
192 {
193 free(pScrn->driverPrivate);
194 pScrn->driverPrivate = NULL;
195 }
196
197
198 /* unlock Alliance registers */
199 static void
ApmUnlock(ApmPtr pApm)200 ApmUnlock(ApmPtr pApm)
201 {
202 if (pApm->Chipset >= AT3D)
203 ApmWriteSeq(0x10, 0x12);
204 else
205 wrinx(pApm->xport, 0x10, 0x12);
206 }
207
208 /* lock Alliance registers */
209 static void
ApmLock(ApmPtr pApm)210 ApmLock(ApmPtr pApm)
211 {
212 if (pApm->Chipset >= AT3D)
213 ApmWriteSeq(0x10, pApm->savedSR10 ? 0 : 0x12);
214 else
215 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
216 }
217
218 static void
ApmIdentify(int flags)219 ApmIdentify(int flags)
220 {
221 xf86PrintChipsets(APM_NAME, "driver for the Alliance chipsets",
222 ApmChipsets);
223 }
224
225 static const OptionInfoRec *
ApmAvailableOptions(int chipid,int busid)226 ApmAvailableOptions(int chipid, int busid)
227 {
228 return ApmOptions;
229 }
230
231 static void
ApmAssignFPtr(ScrnInfoPtr pScrn)232 ApmAssignFPtr(ScrnInfoPtr pScrn)
233 {
234 pScrn->driverVersion = APM_VERSION;
235 pScrn->driverName = APM_DRIVER_NAME;
236 pScrn->name = APM_NAME;
237 pScrn->Probe = ApmProbe;
238 pScrn->PreInit = ApmPreInit;
239 pScrn->ScreenInit = ApmScreenInit;
240 pScrn->SwitchMode = ApmSwitchMode;
241 pScrn->AdjustFrame = ApmAdjustFrame;
242 pScrn->EnterVT = ApmEnterVT;
243 pScrn->LeaveVT = ApmLeaveVT;
244 pScrn->FreeScreen = ApmFreeScreen;
245 pScrn->ValidMode = ApmValidMode;
246 }
247
248 static Bool
ApmProbe(DriverPtr drv,int flags)249 ApmProbe(DriverPtr drv, int flags)
250 {
251 int numDevSections, numUsed, i;
252 GDevPtr *DevSections;
253 int *usedChips;
254 int foundScreen = FALSE;
255
256 /*
257 * Check if there is a chipset override in the config file
258 */
259 if ((numDevSections = xf86MatchDevice(APM_DRIVER_NAME,
260 &DevSections)) <= 0)
261 return FALSE;
262
263 /*
264 * We need to probe the hardware first. We then need to see how this
265 * fits in with what is given in the config file, and allow the config
266 * file info to override any contradictions.
267 */
268
269 #ifndef XSERVER_LIBPCIACCESS
270 if (xf86GetPciVideoInfo() == NULL) {
271 return FALSE;
272 }
273 #endif
274 numUsed = xf86MatchPciInstances(APM_NAME, PCI_VENDOR_ALLIANCE,
275 ApmChipsets, ApmPciChipsets, DevSections, numDevSections,
276 drv, &usedChips);
277
278 if (numUsed > 0) {
279 if (flags & PROBE_DETECT)
280 foundScreen = TRUE;
281 else for (i = 0; i < numUsed; i++) {
282 ScrnInfoPtr pScrn;
283
284 /*
285 * Allocate a ScrnInfoRec and claim the slot
286 */
287 pScrn = NULL;
288 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
289 ApmPciChipsets, NULL,
290 NULL,NULL,NULL,NULL))){
291
292 /*
293 * Fill in what we can of the ScrnInfoRec
294 */
295 ApmAssignFPtr(pScrn);
296 foundScreen = TRUE;
297 }
298 }
299 }
300
301
302 free(DevSections);
303 return foundScreen;
304 }
305
306 /*
307 * GetAccelPitchValues -
308 *
309 * This function returns a list of display width (pitch) values that can
310 * be used in accelerated mode.
311 */
312 static int *
GetAccelPitchValues(ScrnInfoPtr pScrn)313 GetAccelPitchValues(ScrnInfoPtr pScrn)
314 {
315 int *linePitches = NULL;
316 int linep[] = {640, 800, 1024, 1152, 1280, 0};
317
318 if (sizeof linep > 0) {
319 linePitches = (int *)xnfalloc(sizeof linep);
320 memcpy(linePitches, linep, sizeof linep);
321 }
322
323 return linePitches;
324 }
325
326 static unsigned int
ddc1Read(ScrnInfoPtr pScrn)327 ddc1Read(ScrnInfoPtr pScrn)
328 {
329 APMDECL(pScrn);
330 unsigned char tmp;
331
332 tmp = RDXB_IOP(0xD0);
333 WRXB_IOP(0xD0, tmp & 0x07);
334 while (STATUS_IOP() & 0x800);
335 while (!(STATUS_IOP() & 0x800));
336 return (STATUS_IOP() & STATUS_SDA) != 0;
337 }
338
339 static void
ApmProbeDDC(ScrnInfoPtr pScrn,int index)340 ApmProbeDDC(ScrnInfoPtr pScrn, int index)
341 {
342 vbeInfoPtr pVbe;
343
344 if (xf86LoadSubModule(pScrn, "vbe")) {
345 pVbe = VBEInit(NULL, index);
346 ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
347 vbeFree(pVbe);
348 }
349 }
350
351 static Bool
ApmPreInit(ScrnInfoPtr pScrn,int flags)352 ApmPreInit(ScrnInfoPtr pScrn, int flags)
353 {
354 APMDECL(pScrn);
355 EntityInfoPtr pEnt;
356 vgaHWPtr hwp;
357 MessageType from;
358 char *mod = NULL;
359 const char *s;
360 ClockRangePtr clockRanges;
361 int i;
362 xf86MonPtr MonInfo = NULL;
363 double real;
364
365 /*
366 * Note: This function is only called once at server startup, and
367 * not at the start of each server generation. This means that
368 * only things that are persistent across server generations can
369 * be initialised here. xf86Screens[] is (pScrn is a pointer to one
370 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex()
371 * are too, and should be used for data that must persist across
372 * server generations.
373 *
374 * Per-generation data should be allocated with
375 * AllocateScreenPrivateIndex() from the ScreenInit() function.
376 */
377
378 /* Check the number of entities, and fail if it isn't one. */
379 if (pScrn->numEntities != 1)
380 return FALSE;
381
382 /* Allocate the ApmRec driverPrivate */
383 if (!ApmGetRec(pScrn)) {
384 return FALSE;
385 }
386 pApm = APMPTR(pScrn);
387
388 /* Get the entity */
389 pEnt = pApm->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
390 if (pEnt->location.type == BUS_PCI) {
391 pApm->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
392 #ifndef XSERVER_LIBPCIACCESS
393 pApm->PciTag = pciTag(pApm->PciInfo->bus, pApm->PciInfo->device,
394 pApm->PciInfo->func);
395 #endif
396 }
397 else {
398 pApm->PciInfo = NULL;
399 #ifndef XSERVER_LIBPCIACCESS
400 pApm->PciTag = 0;
401 #endif
402 }
403
404 if (flags & PROBE_DETECT) {
405 ApmProbeDDC(pScrn, pEnt->index);
406 return TRUE;
407 }
408
409 /* The vgahw module should be allocated here when needed */
410 if (!xf86LoadSubModule(pScrn, "vgahw"))
411 return FALSE;
412
413 /*
414 * Allocate a vgaHWRec
415 */
416 if (!vgaHWGetHWRec(pScrn))
417 return FALSE;
418
419 hwp = VGAHWPTR(pScrn);
420 vgaHWSetStdFuncs(hwp);
421 vgaHWGetIOBase(hwp);
422 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
423 #define PIOOFFSET hwp->PIOOffset
424 #else
425 /* FIXME reintroduce domain support */
426 #define PIOOFFSET 0
427 #endif
428 pApm->iobase = PIOOFFSET;
429 pApm->xport = PIOOFFSET + 0x3C4;
430
431 /* Set pScrn->monitor */
432 pScrn->monitor = pScrn->confScreen->monitor;
433
434 /* XXX: Access funcs */
435 /*
436 * The first thing we should figure out is the depth, bpp, etc.
437 */
438 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) {
439 return FALSE;
440 } else {
441 /* Check that the returned depth is one we support */
442 switch (pScrn->depth) {
443 case 4:
444 case 8:
445 case 15:
446 case 16:
447 case 24:
448 /* OK */
449 break;
450 default:
451 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
452 "Given depth (%d) is not supported by this driver\n",
453 pScrn->depth);
454 return FALSE;
455 }
456 }
457 xf86PrintDepthBpp(pScrn);
458
459 /*
460 * This must happen after pScrn->display has been set because
461 * xf86SetWeight references it.
462 */
463 if (pScrn->depth > 8) {
464 /* The defaults are OK for us */
465 rgb zeros = {0, 0, 0};
466
467 if (!xf86SetWeight(pScrn, zeros, zeros)) {
468 return FALSE;
469 } else {
470 /* XXX check that weight returned is supported */
471 ;
472 }
473 }
474
475 if (!xf86SetDefaultVisual(pScrn, -1)) {
476 return FALSE;
477 } else {
478 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
479 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
480 " (%s) is not supported at depth %d\n",
481 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
482 return FALSE;
483 }
484 }
485
486 /* We use a programmable clock */
487 pScrn->progClock = TRUE;
488
489 /* Collect all of the relevant option flags (fill in pScrn->options) */
490 xf86CollectOptions(pScrn, NULL);
491
492 /* Process the options */
493 if (!(pApm->Options = malloc(sizeof(ApmOptions))))
494 return FALSE;
495 memcpy(pApm->Options, ApmOptions, sizeof(ApmOptions));
496 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pApm->Options);
497
498 pApm->scrnIndex = pScrn->scrnIndex;
499 /* Set the bits per RGB for 8bpp mode */
500 if (pScrn->depth > 1 && pScrn->depth <= 8) {
501 /* Default to 8 */
502 pScrn->rgbBits = 8;
503 }
504 from = X_DEFAULT;
505 pApm->hwCursor = FALSE;
506 if (xf86GetOptValBool(pApm->Options, OPTION_HW_CURSOR, &pApm->hwCursor))
507 from = X_CONFIG;
508 if (xf86ReturnOptValBool(pApm->Options, OPTION_SW_CURSOR, FALSE)) {
509 from = X_CONFIG;
510 pApm->hwCursor = FALSE;
511 }
512 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
513 pApm->hwCursor ? "HW" : "SW");
514 from = X_DEFAULT;
515 if (pScrn->bitsPerPixel < 8)
516 pApm->NoAccel = TRUE;
517 if (xf86ReturnOptValBool(pApm->Options, OPTION_NOACCEL, FALSE)) {
518 from = X_CONFIG;
519 pApm->NoAccel = TRUE;
520 }
521 if (pApm->NoAccel)
522 xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration disabled\n");
523 if (xf86GetOptValFreq(pApm->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
524 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MCLK used is %.1f MHz\n", real);
525 pApm->MemClk = (int)(real * 1000.0);
526 }
527 if (xf86ReturnOptValBool(pApm->Options, OPTION_SHADOW_FB, FALSE)) {
528 pApm->ShadowFB = TRUE;
529 pApm->NoAccel = TRUE;
530 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
531 "Using \"Shadow Framebuffer\" - acceleration disabled\n");
532 }
533 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_RETRY, FALSE)) {
534 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_BURST, FALSE)) {
535 pApm->UsePCIRetry = TRUE;
536 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
537 }
538 else
539 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires pci_burst \"on\".\n");
540 }
541 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn;
542 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby;
543 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend;
544 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff;
545 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_ON))) {
546 if (!strcmp(s, "on"))
547 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn;
548 else if (!strcmp(s, "standby"))
549 pApm->DPMSMask[DPMSModeOn] = DPMSModeStandby;
550 else if (!strcmp(s, "suspend"))
551 pApm->DPMSMask[DPMSModeOn] = DPMSModeSuspend;
552 else if (!strcmp(s, "off"))
553 pApm->DPMSMask[DPMSModeOn] = DPMSModeOff;
554 else if (s[0] >= '0' && s[0] <= '9') {
555 pApm->DPMSMask[DPMSModeOn] = strtol(s, NULL, 0);
556 if (pApm->DPMSMask[DPMSModeOn] > (sizeof pApm->DPMSMask)-1)
557 pApm->DPMSMask[DPMSModeOn] = (sizeof pApm->DPMSMask) - 1;
558 }
559 }
560 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_STANDBY))) {
561 if (!strcmp(s, "on"))
562 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOn;
563 else if (!strcmp(s, "standby"))
564 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby;
565 else if (!strcmp(s, "suspend"))
566 pApm->DPMSMask[DPMSModeStandby] = DPMSModeSuspend;
567 else if (!strcmp(s, "off"))
568 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOff;
569 else if (s[0] >= '0' && s[0] <= '9') {
570 pApm->DPMSMask[DPMSModeStandby] = strtol(s, NULL, 0);
571 if (pApm->DPMSMask[DPMSModeStandby] > (sizeof pApm->DPMSMask)-1)
572 pApm->DPMSMask[DPMSModeStandby] = (sizeof pApm->DPMSMask) - 1;
573 }
574 }
575 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_SUSPEND))) {
576 if (!strcmp(s, "on"))
577 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOn;
578 else if (!strcmp(s, "standby"))
579 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeStandby;
580 else if (!strcmp(s, "suspend"))
581 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend;
582 else if (!strcmp(s, "off"))
583 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOff;
584 else if (s[0] >= '0' && s[0] <= '9') {
585 pApm->DPMSMask[DPMSModeSuspend] = strtol(s, NULL, 0);
586 if (pApm->DPMSMask[DPMSModeSuspend] > (sizeof pApm->DPMSMask)-1)
587 pApm->DPMSMask[DPMSModeSuspend] = (sizeof pApm->DPMSMask) - 1;
588 }
589 }
590 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_OFF))) {
591 if (!strcmp(s, "on"))
592 pApm->DPMSMask[DPMSModeOff] = DPMSModeOn;
593 else if (!strcmp(s, "standby"))
594 pApm->DPMSMask[DPMSModeOff] = DPMSModeStandby;
595 else if (!strcmp(s, "suspend"))
596 pApm->DPMSMask[DPMSModeOff] = DPMSModeSuspend;
597 else if (!strcmp(s, "off"))
598 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff;
599 else if (s[0] >= '0' && s[0] <= '9') {
600 pApm->DPMSMask[DPMSModeOff] = strtol(s, NULL, 0);
601 if (pApm->DPMSMask[DPMSModeOff] > (sizeof pApm->DPMSMask)-1)
602 pApm->DPMSMask[DPMSModeOff] = (sizeof pApm->DPMSMask) - 1;
603 }
604 }
605
606 /*
607 * Set the Chipset and ChipRev, allowing config file entries to
608 * override.
609 */
610 if (pEnt->device->chipset && *pEnt->device->chipset) {
611 pScrn->chipset = pEnt->device->chipset;
612 pApm->Chipset = xf86StringToToken(ApmChipsets, pScrn->chipset);
613 from = X_CONFIG;
614 } else if (pEnt->device->chipID >= 0) {
615 pApm->Chipset = pEnt->device->chipID;
616 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
617
618 from = X_CONFIG;
619 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
620 pApm->Chipset);
621 } else {
622 from = X_PROBED;
623 if (pApm->PciInfo)
624 pApm->Chipset = PCI_DEV_DEVICE_ID(pApm->PciInfo);
625 else
626 pApm->Chipset = pEnt->chipset;
627 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
628 }
629 if (pScrn->bitsPerPixel == 24 && pApm->Chipset < AT24) {
630 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
631 "Given depth (%d) is not supported by this driver\n",
632 pScrn->depth);
633 return FALSE;
634 }
635 if (pEnt->device->chipRev >= 0) {
636 pApm->ChipRev = pEnt->device->chipRev;
637 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
638 pApm->ChipRev);
639 } else if (pApm->PciInfo) {
640 pApm->ChipRev = PCI_DEV_REVISION(pApm->PciInfo);
641 }
642
643 /*
644 * This shouldn't happen because such problems should be caught in
645 * ApmProbe(), but check it just in case.
646 */
647 if (pScrn->chipset == NULL) {
648 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
649 "ChipID 0x%04X is not recognised\n", pApm->Chipset);
650 return FALSE;
651 }
652 if (pApm->Chipset < 0) {
653 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
654 "Chipset \"%s\" is not recognised\n", pScrn->chipset);
655 return FALSE;
656 }
657
658 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
659
660 if (pEnt->device->MemBase != 0) {
661 pApm->LinAddress = pEnt->device->MemBase;
662 from = X_CONFIG;
663 } else if (pApm->PciInfo) {
664 pApm->LinAddress = PCI_REGION_BASE(pApm->PciInfo, 0, REGION_MEM) & 0xFF800000;
665 from = X_PROBED;
666 } else {
667 /*
668 * VESA local bus.
669 * Pray that 2048MB works.
670 */
671 pApm->LinAddress = 0x80000000;
672 }
673
674 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
675 (unsigned long)pApm->LinAddress);
676
677 if (xf86LoadSubModule(pScrn, "ddc")) {
678 if (xf86LoadSubModule(pScrn, "i2c")) {
679 pApm->I2C = TRUE;
680 }
681 }
682
683 if (pApm->Chipset >= AT3D)
684 pApm->LinMapSize = 16 * 1024 * 1024;
685 else
686 pApm->LinMapSize = 6 * 1024 * 1024;
687 pApm->FbMapSize = 4 * 1024 * 1024;
688
689 if (xf86LoadSubModule(pScrn, "int10")) {
690 void *ptr;
691
692 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
693 ptr = xf86InitInt10(pEnt->index);
694 if (ptr)
695 xf86FreeInt10(ptr);
696 }
697
698 #ifndef XSERVER_LIBPCIACCESS
699 xf86RegisterResources(pEnt->index, NULL, ResNone);
700 xf86SetOperatingState(resVga, pEnt->index, ResDisableOpr);
701 pScrn->racMemFlags = 0; /* For noLinear, access to 0xA0000 */
702 if (pApm->VGAMap)
703 pScrn->racIoFlags = 0;
704 else
705 pScrn->racIoFlags = RAC_COLORMAP | RAC_VIEWPORT;
706 #endif
707 if (pEnt->device->videoRam != 0) {
708 pScrn->videoRam = pEnt->device->videoRam;
709 from = X_CONFIG;
710 } else if (pApm->Chipset >= AT3D) {
711 unsigned char d9, db, uc;
712 /*unsigned long save;*/
713 volatile unsigned char *LinMap;
714
715 #ifndef XSERVER_LIBPCIACCESS
716 LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
717 pApm->PciTag, pApm->LinAddress,
718 pApm->LinMapSize);
719 #else
720 {
721 void** result = (void**)&LinMap;
722 int err = pci_device_map_range(pApm->PciInfo,
723 pApm->LinAddress,
724 pApm->LinMapSize,
725 PCI_DEV_MAP_FLAG_WRITABLE,
726 result);
727
728 if (err)
729 return FALSE;
730 }
731 #endif
732
733 /*save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
734 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_MEM_ENABLE);*/
735 d9 = LinMap[0xFFECD9];
736 db = LinMap[0xFFECDB];
737 LinMap[0xFFECDB] = (db & 0xF4) | 0x0A;
738 LinMap[0xFFECD9] = (d9 & 0xCF) | 0x20;
739 LinMap[0xFFF3C4] = 0x1C;
740 uc = LinMap[0xFFF3C5];
741 LinMap[0xFFF3C5] = 0x3F;
742 LinMap[0xFFF3C4] = 0x20;
743 pScrn->videoRam = LinMap[0xFFF3C5] * 64;
744 LinMap[0xFFF3C4] = 0x10;
745 pApm->savedSR10 = LinMap[0xFFF3C5];
746 LinMap[0xFFF3C4] = 0x1E;
747 pApm->xbase = LinMap[0xFFF3C5];
748 LinMap[0xFFF3C4] = 0x1F;
749 pApm->xbase |= LinMap[0xFFF3C5] << 8;
750 LinMap[0xFFF3C4] = 0x1C;
751 LinMap[0xFFF3C5] = uc;
752 LinMap[0xFFECDB] = db;
753 LinMap[0xFFECD9] = d9;
754 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
755 #ifndef XSERVER_LIBPCIACCESS
756 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)LinMap, pApm->LinMapSize);
757 #else
758 pci_device_unmap_range(pApm->PciInfo, (pointer)LinMap, pApm->LinMapSize);
759 #endif
760 from = X_PROBED;
761 }
762 else {
763 /*unsigned long save;
764
765 save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
766 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_IO_ENABLE);*/
767 pApm->savedSR10 = rdinx(pApm->xport, 0x10);
768 wrinx(pApm->xport, 0x10, 0x12);
769 pScrn->videoRam = rdinx(pApm->xport, 0x20) * 64;
770 pApm->xbase = rdinx(pApm->xport, 0x1F) << 8;
771 pApm->xbase |= rdinx(pApm->xport, 0x1E);
772 pApm->xbase += pApm->iobase;
773 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
774 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
775 from = X_PROBED;
776 }
777 if (pApm->Chipset < AT3D && pScrn->videoRam >= 4096)
778 pScrn->videoRam -= 32;
779
780 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
781 pScrn->videoRam);
782
783 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
784 if (!xf86IsPc98())
785 #endif
786 {
787 hwp->MapSize = 0x10000;
788 vgaHWMapMem(pScrn);
789 if (pApm->I2C) {
790 if (!ApmI2CInit(pScrn)) {
791 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
792 }
793 else {
794 MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pApm->I2CPtr);
795 }
796 }
797 if (0 && !MonInfo)
798 MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),vgaHWddc1SetSpeed,ddc1Read);
799 if (MonInfo) {
800 xf86PrintEDID(MonInfo);
801 xf86SetDDCproperties(pScrn, MonInfo);
802 }
803 pScrn->monitor->DDC = MonInfo;
804 }
805
806 /* The gamma fields must be initialised when using the new cmap code */
807 if (pScrn->depth > 1) {
808 Gamma zeros = {0.0, 0.0, 0.0};
809
810 if (!xf86SetGamma(pScrn, zeros)) {
811 return FALSE;
812 }
813 }
814
815 pApm->MinClock = 23125;
816 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock set to %d MHz\n",
817 pApm->MinClock / 1000);
818
819 /*
820 * If the user has specified ramdac speed in the XF86Config
821 * file, we respect that setting.
822 */
823 from = X_DEFAULT;
824 if (pEnt->device->dacSpeeds[0]) {
825 int speed = 0;
826
827 switch (pScrn->bitsPerPixel) {
828 case 4:
829 case 8:
830 speed = pEnt->device->dacSpeeds[DAC_BPP8];
831 break;
832 case 16:
833 speed = pEnt->device->dacSpeeds[DAC_BPP16];
834 break;
835 case 24:
836 speed = pEnt->device->dacSpeeds[DAC_BPP24];
837 break;
838 case 32:
839 speed = pEnt->device->dacSpeeds[DAC_BPP32];
840 break;
841 }
842 if (speed == 0)
843 pApm->MaxClock = pEnt->device->dacSpeeds[0];
844 else
845 pApm->MaxClock = speed;
846 from = X_CONFIG;
847 } else {
848 switch(pApm->Chipset)
849 {
850 /* These values come from the Manual for AT24 and AT3D
851 in the overview of various modes. I've taken the largest
852 number for the different modes. Alliance wouldn't
853 tell me what the maximum frequency was, so...
854 */
855 case AT24:
856 switch(pScrn->bitsPerPixel)
857 {
858 case 4:
859 case 8:
860 pApm->MaxClock = 160000;
861 break;
862 case 16:
863 pApm->MaxClock = 144000;
864 break;
865 case 24:
866 pApm->MaxClock = 75000; /* Hmm. */
867 break;
868 case 32:
869 pApm->MaxClock = 94500;
870 break;
871 default:
872 return FALSE;
873 }
874 break;
875 case AT3D:
876 switch(pScrn->bitsPerPixel)
877 {
878 case 4:
879 case 8:
880 pApm->MaxClock = 175500;
881 break;
882 case 16:
883 pApm->MaxClock = 144000;
884 break;
885 case 24:
886 pApm->MaxClock = 94000; /* Changed from 75000 by Grenié */
887 break;
888 case 32:
889 pApm->MaxClock = 94500;
890 break;
891 default:
892 return FALSE;
893 }
894 break;
895 case AP6422:
896 switch(pScrn->bitsPerPixel)
897 {
898 case 4:
899 case 8:
900 pApm->MaxClock = 135000;
901 break;
902 case 16:
903 pApm->MaxClock = 75000;
904 break;
905 case 32:
906 pApm->MaxClock = 60000;
907 break;
908 default:
909 return FALSE;
910 }
911 break;
912 default:
913 pApm->MaxClock = 135000;
914 break;
915 }
916 }
917 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
918 pApm->MaxClock / 1000);
919
920 /*
921 * Setup the ClockRanges, which describe what clock ranges are available,
922 * and what sort of modes they can be used for.
923 */
924 clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1);
925 clockRanges->next = NULL;
926 clockRanges->minClock = pApm->MinClock;
927 clockRanges->maxClock = pApm->MaxClock;
928 clockRanges->clockIndex = -1; /* programmable */
929 clockRanges->interlaceAllowed = FALSE; /* XXX change this */
930 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */
931
932 /* Select valid modes from those available */
933 if (pApm->NoAccel) {
934 /*
935 * XXX Assuming min pitch 256, max 2048
936 * XXX Assuming min height 128, max 1024 (changed EE)
937 */
938 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
939 pScrn->display->modes, clockRanges,
940 NULL, 256, 2048,
941 pScrn->bitsPerPixel, 128, 1024,
942 pScrn->display->virtualX,
943 pScrn->display->virtualY,
944 pApm->FbMapSize,
945 LOOKUP_BEST_REFRESH);
946 } else {
947 /*
948 * XXX Assuming min height 128, max 2048
949 */
950 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
951 pScrn->display->modes, clockRanges,
952 GetAccelPitchValues(pScrn), 0, 0,
953 pScrn->bitsPerPixel, 128, 1024,
954 pScrn->display->virtualX,
955 pScrn->display->virtualY,
956 pApm->FbMapSize,
957 LOOKUP_BEST_REFRESH);
958 }
959
960 if (i == -1) {
961 ApmFreeRec(pScrn);
962 return FALSE;
963 }
964
965 /* Prune the modes marked as invalid */
966 xf86PruneDriverModes(pScrn);
967
968 if (i == 0 || pScrn->modes == NULL) {
969 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
970 ApmFreeRec(pScrn);
971 return FALSE;
972 }
973
974 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
975
976 /* Set the current mode to the first in the list */
977 pScrn->currentMode = pScrn->modes;
978
979 /* Print the list of modes being used */
980 xf86PrintModes(pScrn);
981
982 /* Set display resolution */
983 xf86SetDpi(pScrn, 0, 0);
984
985 /* Load bpp-specific modules */
986 switch (pScrn->bitsPerPixel) {
987 case 8:
988 case 16:
989 case 24:
990 case 32:
991 mod = "fb";
992 break;
993 }
994
995 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
996 ApmFreeRec(pScrn);
997 return FALSE;
998 }
999
1000 /* Load XAA if needed */
1001 if (!pApm->NoAccel) {
1002 #ifdef HAVE_XAA_H
1003 if (!xf86LoadSubModule(pScrn, "xaa")) {
1004 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n");
1005 pApm->NoAccel = TRUE;
1006 pApm->ShadowFB = TRUE;
1007 }
1008 #else
1009 pApm->NoAccel = TRUE;
1010 pApm->ShadowFB = TRUE;
1011 #endif
1012 }
1013
1014 /* Load ramdac if needed */
1015 if (pApm->hwCursor) {
1016 if (!xf86LoadSubModule(pScrn, "ramdac")) {
1017 ApmFreeRec(pScrn);
1018 return FALSE;
1019 }
1020 }
1021
1022 /* Load shadowfb if needed */
1023 if (pApm->ShadowFB) {
1024 if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1025 ApmFreeRec(pScrn);
1026 return FALSE;
1027 }
1028 }
1029
1030 pApm->CurrentLayout.displayWidth = pScrn->virtualX;
1031 pApm->CurrentLayout.displayHeight = pScrn->virtualY;
1032 pApm->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
1033 pApm->CurrentLayout.bytesPerScanline= (pApm->CurrentLayout.displayWidth * pApm->CurrentLayout.bitsPerPixel) >> 3;
1034 pApm->CurrentLayout.depth = pScrn->depth;
1035 pApm->CurrentLayout.Scanlines = 2 * (pScrn->videoRam << 10) / pApm->CurrentLayout.bytesPerScanline;
1036 if (pScrn->bitsPerPixel == 24)
1037 pApm->CurrentLayout.mask32 = 3;
1038 else
1039 pApm->CurrentLayout.mask32 = 32 / pScrn->bitsPerPixel - 1;
1040
1041 return TRUE;
1042 }
1043
1044 /*
1045 * Map the framebuffer and MMIO memory.
1046 */
1047
1048 static Bool
ApmMapMem(ScrnInfoPtr pScrn)1049 ApmMapMem(ScrnInfoPtr pScrn)
1050 {
1051 APMDECL(pScrn);
1052 vgaHWPtr hwp = VGAHWPTR(pScrn);
1053
1054 #ifndef XSERVER_LIBPCIACCESS
1055 pApm->LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1056 pApm->PciTag,
1057 (unsigned long)pApm->LinAddress,
1058 pApm->LinMapSize);
1059 #else
1060 {
1061 void** result = (void**)&pApm->LinMap;
1062 int err = pci_device_map_range(pApm->PciInfo,
1063 pApm->LinAddress,
1064 pApm->LinMapSize,
1065 PCI_DEV_MAP_FLAG_WRITABLE |
1066 PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1067 result);
1068
1069 if (err)
1070 return FALSE;
1071 }
1072 #endif
1073
1074
1075 if (pApm->LinMap == NULL)
1076 return FALSE;
1077
1078 if (pApm->Chipset >= AT3D) {
1079 pApm->FbBase = (void *)(((char *)pApm->LinMap) + 0x800000);
1080 pApm->VGAMap = ((char *)pApm->LinMap) + 0xFFF000;
1081 pApm->MemMap = ((char *)pApm->LinMap) + 0xFFEC00;
1082 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
1083 }
1084 else {
1085 pApm->FbBase = (void *)pApm->LinMap;
1086 pApm->VGAMap = NULL;
1087 if (pScrn->videoRam == 6 * 1024 - 32) {
1088 pApm->MemMap = ((char *)pApm->LinMap) + 0x5FF800;
1089 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x5F8000);
1090 }
1091 else {
1092 pApm->MemMap = ((char *)pApm->LinMap) + 0x3FF800;
1093 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
1094 }
1095 }
1096
1097 /*
1098 * Initialize chipset
1099 */
1100 pApm->c9 = RDXB(0xC9);
1101 if (pApm->Chipset >= AT3D) {
1102 pApm->d9 = RDXB(0xD9);
1103 pApm->db = RDXB(0xDB);
1104
1105 /* If you change these two, change them also in apm_funcs.c */
1106 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A);
1107 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
1108
1109 vgaHWSetMmioFuncs(hwp, (CARD8 *)pApm->LinMap, 0xFFF000);
1110 }
1111 if (pApm->Chipset >= AP6422)
1112 WRXB(0xC9, pApm->c9 | 0x10);
1113
1114 /*
1115 * Save color mode
1116 */
1117 pApm->MiscOut = hwp->readMiscOut(hwp);
1118
1119 return TRUE;
1120 }
1121
1122 /*
1123 * Unmap the framebuffer and MMIO memory
1124 */
1125
1126 static Bool
ApmUnmapMem(ScrnInfoPtr pScrn)1127 ApmUnmapMem(ScrnInfoPtr pScrn)
1128 {
1129 APMDECL(pScrn);
1130 vgaHWPtr hwp = VGAHWPTR(pScrn);
1131
1132 /*
1133 * Reset color mode
1134 */
1135 hwp->writeMiscOut(hwp, pApm->MiscOut);
1136 if (pApm->LinMap) {
1137 if (pApm->Chipset >= AT3D) {
1138 WRXB(0xD9, pApm->d9);
1139 WRXB(0xDB, pApm->db);
1140 }
1141 WRXB(0xC9, pApm->c9);
1142 #ifndef XSERVER_LIBPCIACCESS
1143 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, pApm->LinMapSize);
1144 #else
1145 pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, pApm->LinMapSize);
1146 #endif
1147 pApm->LinMap = NULL;
1148 }
1149 else if (pApm->FbBase)
1150 #ifndef XSERVER_LIBPCIACCESS
1151 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, 0x10000);
1152 #else
1153 pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, 0x10000);
1154 #endif
1155
1156 return TRUE;
1157 }
1158
1159 /*
1160 * This function saves the video state.
1161 */
1162 static void
ApmSave(ScrnInfoPtr pScrn)1163 ApmSave(ScrnInfoPtr pScrn)
1164 {
1165 APMDECL(pScrn);
1166 ApmRegPtr ApmReg = &pApm->SavedReg;
1167 vgaHWPtr hwp = VGAHWPTR(pScrn);
1168
1169 if (pApm->VGAMap) {
1170 ApmReg->SEQ[0x1B] = ApmReadSeq(0x1B);
1171 ApmReg->SEQ[0x1C] = ApmReadSeq(0x1C);
1172
1173 /*
1174 * Save fonts
1175 */
1176 if (!(hwp->SavedReg.Attribute[0x10] & 1)) {
1177 if (pApm->FontInfo || (pApm->FontInfo = malloc(TEXT_AMOUNT))) {
1178 int locked;
1179
1180 locked = ApmReadSeq(0x10);
1181 if (locked)
1182 ApmWriteSeq(0x10, 0x12);
1183 ApmWriteSeq(0x1C, 0x3F);
1184 memcpy(pApm->FontInfo, pApm->FbBase, TEXT_AMOUNT);
1185 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
1186 if (locked)
1187 ApmWriteSeq(0x10, 0);
1188 }
1189 }
1190 /*
1191 * This function will handle creating the data structure and filling
1192 * in the generic VGA portion.
1193 */
1194 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_CMAP);
1195
1196 /* Hardware cursor registers. */
1197 ApmReg->EX[XR140] = RDXL(0x140);
1198 ApmReg->EX[XR144] = RDXW(0x144);
1199 ApmReg->EX[XR148] = RDXL(0x148);
1200 ApmReg->EX[XR14C] = RDXW(0x14C);
1201
1202 ApmReg->CRT[0x19] = ApmReadCrtc(0x19);
1203 ApmReg->CRT[0x1A] = ApmReadCrtc(0x1A);
1204 ApmReg->CRT[0x1B] = ApmReadCrtc(0x1B);
1205 ApmReg->CRT[0x1C] = ApmReadCrtc(0x1C);
1206 ApmReg->CRT[0x1D] = ApmReadCrtc(0x1D);
1207 ApmReg->CRT[0x1E] = ApmReadCrtc(0x1E);
1208
1209 /* RAMDAC registers. */
1210 ApmReg->EX[XRE8] = RDXL(0xE8);
1211 ApmReg->EX[XREC] = RDXL(0xEC);
1212
1213 /* Color correction */
1214 ApmReg->EX[XRE0] = RDXL(0xE0);
1215
1216 ApmReg->EX[XR80] = RDXB(0x80);
1217 }
1218 else {
1219 /*
1220 * This function will handle creating the data structure and filling
1221 * in the generic VGA portion.
1222 */
1223 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
1224
1225 ApmReg->SEQ[0x1B] = rdinx(pApm->xport, 0x1B);
1226 ApmReg->SEQ[0x1C] = rdinx(pApm->xport, 0x1C);
1227
1228 /* Hardware cursor registers. */
1229 ApmReg->EX[XR140] = RDXL(0x140);
1230 ApmReg->EX[XR144] = RDXW(0x144);
1231 ApmReg->EX[XR148] = RDXL(0x148);
1232 ApmReg->EX[XR14C] = RDXW(0x14C);
1233
1234 ApmReg->CRT[0x19] = rdinx(pApm->iobase + 0x3D4, 0x19);
1235 ApmReg->CRT[0x1A] = rdinx(pApm->iobase + 0x3D4, 0x1A);
1236 ApmReg->CRT[0x1B] = rdinx(pApm->iobase + 0x3D4, 0x1B);
1237 ApmReg->CRT[0x1C] = rdinx(pApm->iobase + 0x3D4, 0x1C);
1238 ApmReg->CRT[0x1D] = rdinx(pApm->iobase + 0x3D4, 0x1D);
1239 ApmReg->CRT[0x1E] = rdinx(pApm->iobase + 0x3D4, 0x1E);
1240
1241 /* RAMDAC registers. */
1242 ApmReg->EX[XRE8] = RDXL(0xE8);
1243 ApmReg->EX[XREC] = RDXL(0xEC);
1244
1245 /* Color correction */
1246 ApmReg->EX[XRE0] = RDXL(0xE0);
1247
1248 ApmReg->EX[XR80] = RDXB(0x80);
1249 }
1250 }
1251
1252 #define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2)))
1253
1254 static unsigned
comp_lmn(ApmPtr pApm,long clock)1255 comp_lmn(ApmPtr pApm, long clock)
1256 {
1257 int n, m, l, f;
1258 double fvco;
1259 double fout;
1260 double fmax, fmin;
1261 double fref;
1262 double fvco_goal;
1263 double k, c;
1264 double fout_best = 0;
1265 unsigned int best = 0;
1266
1267 if (pApm->Chipset >= AT3D)
1268 fmax = 370000.0;
1269 else
1270 fmax = 250000.0;
1271
1272 fref = 14318.0;
1273 fmin = fmax / 2.0;
1274
1275 for (m = 1; m <= 5; m++)
1276 {
1277 for (l = 3; l >= 0; l--)
1278 {
1279 for (n = 8; n <= 127; n++)
1280 {
1281 fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l));
1282 fvco_goal = (double)clock * (double)(1 << l);
1283 fvco = fout * (double)(1 << l);
1284 if (!WITHIN(fvco, 0.99*fvco_goal, 1.01*fvco_goal))
1285 continue;
1286 if (!WITHIN(fvco, fmin, fmax))
1287 continue;
1288 if (!WITHIN(fvco / (double)(n+1), 300.0, 300000.0))
1289 continue;
1290 if (!WITHIN(fref / (double)(m+1), 300.0, 300000.0))
1291 continue;
1292
1293 if (fout_best != 0) {
1294 double diff_new = clock - fout;
1295 double diff_old = clock - best;
1296 diff_new = diff_new < 0 ? -diff_new : diff_new;
1297 diff_old = diff_old < 0 ? -diff_old : diff_old;
1298 if (diff_new > diff_old)
1299 continue;
1300 }
1301 fout_best = fout;
1302
1303 /* The following formula was empirically derived by
1304 matching a number of fvco values with acceptable
1305 values of f.
1306
1307 (fvco can be 185MHz - 370MHz on AT3D)
1308 (fvco can be 125MHz - 250MHz on AT24/AP6422)
1309
1310 The table that was measured up follows:
1311
1312 AT3D
1313
1314 fvco f
1315 (125) (x-7) guess
1316 200 5-7
1317 219 4-7
1318 253 3-6
1319 289 2-5
1320 320 0-4
1321 (400) (0-x) guess
1322
1323 AT24
1324
1325 fvco f
1326 126 7
1327 200 5-7
1328 211 4-7
1329
1330 AP6422
1331
1332 fvco f
1333 126 7
1334 169 5-7
1335 200 4-5
1336 211 4-5
1337
1338 From this, a function "f = k * fvco + c" was derived.
1339
1340 For AT3D, this table was measured with MCLK == 50MHz.
1341 The driver has since been set to use MCLK == 57.3MHz for,
1342 but I don't think that makes a difference here.
1343 */
1344
1345 if (pApm->Chipset >= AT24)
1346 {
1347 k = 7.0 / (175.0 - 380.0);
1348 c = -k * 380.0;
1349 f = (int)(k * fvco/1000.0 + c + 0.5);
1350 if (f > 7) f = 7;
1351 if (f < 0) f = 0;
1352 } else { /* i.e AP6422 */
1353 c = (211.0*6.0-169.0*4.5)/(211.0-169.0);
1354 k = (4.5-c)/211.0;
1355 f = (int)(k * fvco/1000.0 + c + 0.5);
1356 if (f > 7) f = 7;
1357 if (f < 0) f = 0;
1358 }
1359
1360 best = (n << 16) | (m << 8) | (l << 2) | (f << 4);
1361 }
1362 }
1363 }
1364
1365 if (fout_best != 0)
1366 return best;
1367
1368 xf86DrvMsg(pApm->scrnIndex, X_PROBED,
1369 "Cannot find register values for clock %6.2f MHz. "
1370 "Please use a (slightly) different clock.\n",
1371 (double)clock / 1000.0);
1372 return 0;
1373 }
1374
1375 /*
1376 * Initialise a new mode. This is currently still using the old
1377 * "initialise struct, restore/write struct to HW" model. That could
1378 * be changed.
1379 */
1380
1381 static Bool
ApmModeInit(ScrnInfoPtr pScrn,DisplayModePtr mode)1382 ApmModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1383 {
1384 APMDECL(pScrn);
1385 ApmRegPtr ApmReg = &pApm->ModeReg;
1386 vgaHWPtr hwp;
1387
1388
1389 /* set clockIndex to "2" for programmable clocks */
1390 if (pScrn->progClock)
1391 mode->ClockIndex = 2;
1392
1393 /* prepare standard VGA register contents */
1394 if (!vgaHWInit(pScrn, mode))
1395 return FALSE;
1396 pScrn->vtSema = TRUE;
1397 hwp = VGAHWPTR(pScrn);
1398
1399 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
1400
1401 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1402 if (xf86IsPc98())
1403 outb(0xFAC, 0xFF);
1404 #endif
1405
1406 memcpy(ApmReg, &pApm->SavedReg, sizeof pApm->SavedReg);
1407
1408 /*
1409 * The APM chips have a scale factor of 8 for the
1410 * scanline offset. There are four extended bit in addition
1411 * to the 8 VGA bits.
1412 */
1413 {
1414 int offset;
1415
1416 offset = (pApm->CurrentLayout.displayWidth *
1417 pApm->CurrentLayout.bitsPerPixel / 8) >> 3;
1418 hwp->ModeReg.CRTC[0x13] = offset;
1419 /* Bit 8 resides at CR1C bits 7:4. */
1420 ApmReg->CRT[0x1C] = (offset & 0xF00) >> 4;
1421 }
1422
1423 /* Set pixel depth. */
1424 switch(pApm->CurrentLayout.bitsPerPixel)
1425 {
1426 case 4:
1427 ApmReg->EX[XR80] = 0x01;
1428 break;
1429 case 8:
1430 ApmReg->EX[XR80] = 0x02;
1431 break;
1432 case 16:
1433 if (pApm->CurrentLayout.depth == 15)
1434 ApmReg->EX[XR80] = 0x0C;
1435 else
1436 ApmReg->EX[XR80] = 0x0D;
1437 break;
1438 case 24:
1439 ApmReg->EX[XR80] = 0x0E;
1440 break;
1441 case 32:
1442 ApmReg->EX[XR80] = 0x0F;
1443 break;
1444 default:
1445 FatalError("Unsupported bit depth %d\n", pApm->CurrentLayout.depth);
1446 break;
1447 }
1448
1449 /* Set banking register to zero. */
1450 ApmReg->EX[XRC0] = 0;
1451
1452 /* Handle the CRTC overflow bits. */
1453 {
1454 unsigned char val;
1455 /* Vertical Overflow. */
1456 val = 0;
1457 if ((mode->CrtcVTotal - 2) & 0x400)
1458 val |= 0x01;
1459 if ((mode->CrtcVDisplay - 1) & 0x400)
1460 val |= 0x02;
1461 /* VBlankStart is equal to VSyncStart + 1. */
1462 if (mode->CrtcVSyncStart & 0x400)
1463 val |= 0x04;
1464 /* VRetraceStart is equal to VSyncStart + 1. */
1465 if (mode->CrtcVSyncStart & 0x400)
1466 val |= 0x08;
1467 ApmReg->CRT[0x1A] = val;
1468
1469 /* Horizontal Overflow. */
1470 val = 0;
1471 if ((mode->CrtcHTotal / 8 - 5) & 0x100)
1472 val |= 1;
1473 if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
1474 val |= 2;
1475 /* HBlankStart is equal to HSyncStart - 1. */
1476 if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
1477 val |= 4;
1478 /* HRetraceStart is equal to HSyncStart. */
1479 if ((mode->CrtcHSyncStart / 8) & 0x100)
1480 val |= 8;
1481 ApmReg->CRT[0x1B] = val;
1482
1483 /* Assume the CRTC is not KGA (see vgaHWInit) */
1484 hwp->ModeReg.CRTC[3] = (hwp->ModeReg.CRTC[3] & 0xE0) |
1485 (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1486 hwp->ModeReg.CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1487 | (hwp->ModeReg.CRTC[5] & 0x7F);
1488 hwp->ModeReg.CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1489 }
1490 ApmReg->CRT[0x1E] = 1; /* disable autoreset feature */
1491
1492 /* Program clock select. */
1493 ApmReg->EX[XREC] = comp_lmn(pApm, mode->Clock);
1494 if (!ApmReg->EX[XREC])
1495 return FALSE;
1496 hwp->ModeReg.MiscOutReg |= 0x0C;
1497
1498 /* Set up the RAMDAC registers. */
1499
1500 if (pApm->CurrentLayout.bitsPerPixel > 8)
1501 /* Get rid of white border. */
1502 hwp->ModeReg.Attribute[0x11] = 0x00;
1503 else
1504 hwp->ModeReg.Attribute[0x11] = 0xFF;
1505 if (pApm->MemClk)
1506 ApmReg->EX[XRE8] = comp_lmn(pApm, pApm->MemClk);
1507 else if (pApm->Chipset >= AT3D)
1508 ApmReg->EX[XRE8] = 0x071F01E8; /* Enable 58MHz MCLK (actually 57.3 MHz)
1509 This is what is used in the Windows
1510 drivers. The BIOS sets it to 50MHz. */
1511 else
1512 ApmReg->EX[XRE8] = RDXL(0xE8); /* No change */
1513
1514 ApmReg->EX[XRE0] = 0x10;
1515
1516 /* If you change it, change in apm_funcs.c as well */
1517 if (pApm->Chipset >= AT3D) {
1518 ApmReg->SEQ[0x1B] = 0x20;
1519 ApmReg->SEQ[0x1C] = 0x2F;
1520 }
1521 else {
1522 ApmReg->SEQ[0x1B] = 0x24;
1523 if (pScrn->videoRam >= 6 * 1024)
1524 ApmReg->SEQ[0x1C] = 0x2F;
1525 else
1526 ApmReg->SEQ[0x1C] = 0x2D;
1527 }
1528
1529 /* ICICICICI */
1530 ApmRestore(pScrn, &hwp->ModeReg, ApmReg);
1531
1532 return TRUE;
1533 }
1534
1535 /*
1536 * Restore the initial mode.
1537 */
1538 static void
ApmRestore(ScrnInfoPtr pScrn,vgaRegPtr vgaReg,ApmRegPtr ApmReg)1539 ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, ApmRegPtr ApmReg)
1540 {
1541 APMDECL(pScrn);
1542
1543 vgaHWProtect(pScrn, TRUE);
1544 ApmUnlock(pApm);
1545
1546 if (pApm->VGAMap) {
1547 /*
1548 * Restore fonts
1549 */
1550 if (!(vgaReg->Attribute[0x10] & 1) && pApm->FontInfo) {
1551 ApmWriteSeq(0x1C, 0x3F);
1552 memcpy(pApm->FbBase, pApm->FontInfo, TEXT_AMOUNT);
1553 }
1554
1555 /* Set aperture index to 0. */
1556 WRXW(0xC0, 0);
1557
1558 /*
1559 * Write the extended registers first
1560 */
1561 ApmWriteSeq(0x1B, ApmReg->SEQ[0x1B]);
1562 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
1563
1564 /* Hardware cursor registers. */
1565 WRXL(0x140, ApmReg->EX[XR140]);
1566 WRXW(0x144, ApmReg->EX[XR144]);
1567 WRXL(0x148, ApmReg->EX[XR148]);
1568 WRXW(0x14C, ApmReg->EX[XR14C]);
1569
1570 ApmWriteCrtc(0x19, ApmReg->CRT[0x19]);
1571 ApmWriteCrtc(0x1A, ApmReg->CRT[0x1A]);
1572 ApmWriteCrtc(0x1B, ApmReg->CRT[0x1B]);
1573 ApmWriteCrtc(0x1D, ApmReg->CRT[0x1D]);
1574 ApmWriteCrtc(0x1E, ApmReg->CRT[0x1E]);
1575
1576 /* RAMDAC registers. */
1577 WRXL(0xE8, ApmReg->EX[XRE8]);
1578
1579 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
1580 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
1581
1582 /* Color correction */
1583 WRXL(0xE0, ApmReg->EX[XRE0]);
1584
1585 /*
1586 * This function handles restoring the generic VGA registers.
1587 */
1588 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1589
1590 /* set these after setting the default VGA registers */
1591 ApmWriteCrtc(0x1C, ApmReg->CRT[0x1C]);
1592 WRXB(0x80, ApmReg->EX[XR80]);
1593 }
1594 else {
1595 /* Set aperture index to 0. */
1596 WRXW(0xC0, 0);
1597
1598 /*
1599 * Write the extended registers first
1600 */
1601 wrinx(pApm->xport, 0x1B, ApmReg->SEQ[0x1B]);
1602 wrinx(pApm->xport, 0x1C, ApmReg->SEQ[0x1C]);
1603
1604 /* Hardware cursor registers. */
1605 WRXL(0x140, ApmReg->EX[XR140]);
1606 WRXW(0x144, ApmReg->EX[XR144]);
1607 WRXL(0x148, ApmReg->EX[XR148]);
1608 WRXW(0x14C, ApmReg->EX[XR14C]);
1609
1610 wrinx(pApm->iobase + 0x3D4, 0x19, ApmReg->CRT[0x19]);
1611 wrinx(pApm->iobase + 0x3D4, 0x1A, ApmReg->CRT[0x1A]);
1612 wrinx(pApm->iobase + 0x3D4, 0x1B, ApmReg->CRT[0x1B]);
1613 wrinx(pApm->iobase + 0x3D4, 0x1C, ApmReg->CRT[0x1C]);
1614 wrinx(pApm->iobase + 0x3D4, 0x1D, ApmReg->CRT[0x1D]);
1615 wrinx(pApm->iobase + 0x3D4, 0x1E, ApmReg->CRT[0x1E]);
1616
1617 /* RAMDAC registers. */
1618 WRXL(0xE8, ApmReg->EX[XRE8]);
1619 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
1620 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
1621
1622 /* Color correction */
1623 WRXL(0xE0, ApmReg->EX[XRE0]);
1624
1625 WRXB(0x80, ApmReg->EX[XR80]);
1626
1627 /*
1628 * This function handles restoring the generic VGA registers.
1629 */
1630 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1631 }
1632
1633 vgaHWProtect(pScrn, FALSE);
1634 }
1635
1636
1637 /* Refresh a region of the shadow framebuffer to the screen */
1638 static void
ApmRefreshArea(ScrnInfoPtr pScrn,int num,BoxPtr pbox)1639 ApmRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
1640 {
1641 APMDECL(pScrn);
1642 int width, height, Bpp, FBPitch;
1643 unsigned char *src, *dst;
1644
1645 Bpp = pApm->CurrentLayout.bitsPerPixel >> 3;
1646 FBPitch = pApm->CurrentLayout.bytesPerScanline;
1647
1648 while(num--) {
1649 width = (pbox->x2 - pbox->x1) * Bpp;
1650 height = pbox->y2 - pbox->y1;
1651 src = pApm->ShadowPtr + (pbox->y1 * pApm->ShadowPitch) +
1652 (pbox->x1 * Bpp);
1653 dst = (unsigned char *)pApm->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
1654
1655 while(height--) {
1656 memcpy(dst, src, width);
1657 dst += FBPitch;
1658 src += pApm->ShadowPitch;
1659 }
1660
1661 pbox++;
1662 }
1663 }
1664
1665
1666 /* Mandatory */
1667
1668 /* This gets called at the start of each server generation */
1669
1670 static Bool
ApmScreenInit(SCREEN_INIT_ARGS_DECL)1671 ApmScreenInit(SCREEN_INIT_ARGS_DECL)
1672 {
1673 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1674 APMDECL(pScrn);
1675 int ret;
1676 unsigned char *FbBase;
1677
1678 pApm->pScreen = pScreen;
1679
1680 /* Map the chip memory and MMIO areas */
1681 if (!ApmMapMem(pScrn))
1682 return FALSE;
1683
1684 /* No memory reserved yet */
1685 pApm->OffscreenReserved = 0;
1686
1687 /* Save the current state */
1688 ApmSave(pScrn);
1689
1690 /* Initialise the first mode */
1691 ApmModeInit(pScrn, pScrn->currentMode);
1692 pApm->CurrentLayout.pMode = pScrn->currentMode;
1693
1694 /* Darken the screen for aesthetic reasons and set the viewport */
1695 ApmSaveScreen(pScreen, SCREEN_SAVER_ON);
1696 ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1697
1698 /*
1699 * Reset fb's visual list.
1700 */
1701 miClearVisualTypes();
1702
1703 /* Setup the visuals we support. */
1704
1705 /*
1706 * For bpp > 8, the default visuals are not acceptable because we only
1707 * support TrueColor and not DirectColor. To deal with this, call
1708 * miSetVisualTypes for each visual supported.
1709 */
1710
1711 if (pApm->CurrentLayout.bitsPerPixel > 8) {
1712 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
1713 pScrn->defaultVisual))
1714 return FALSE;
1715 } else {
1716 if (!miSetVisualTypes(pScrn->depth,
1717 miGetDefaultVisualMask(pScrn->depth),
1718 pScrn->rgbBits, pScrn->defaultVisual))
1719 return FALSE;
1720 }
1721
1722 /*
1723 * Call the framebuffer layer's ScreenInit function, and fill in other
1724 * pScreen fields.
1725 */
1726
1727 if(pApm->ShadowFB) {
1728 pApm->ShadowPitch =
1729 ((pScrn->virtualX * pScrn->bitsPerPixel >> 3) + 3) & ~3L;
1730 pApm->ShadowPtr = malloc(pApm->ShadowPitch * pScrn->virtualY);
1731 FbBase = pApm->ShadowPtr;
1732 } else {
1733 pApm->ShadowPtr = NULL;
1734 FbBase = pApm->FbBase;
1735 }
1736
1737 /* Reserve memory */
1738 ApmHWCursorReserveSpace(pApm);
1739 ApmAccelReserveSpace(pApm);
1740
1741 miSetPixmapDepths();
1742
1743 switch (pScrn->bitsPerPixel) {
1744 case 8:
1745 case 16:
1746 case 24:
1747 case 32:
1748 ret = fbScreenInit(pScreen, FbBase, pScrn->virtualX,
1749 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
1750 pScrn->displayWidth, pScrn->bitsPerPixel);
1751 break;
1752 default:
1753 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1754 "Internal error: invalid bpp (%d) in ApmScrnInit\n",
1755 pScrn->bitsPerPixel);
1756 ret = FALSE;
1757 break;
1758 }
1759 if (!ret)
1760 return FALSE;
1761
1762 if (pScrn->bitsPerPixel > 8) {
1763 VisualPtr visual;
1764
1765 /* Fixup RGB ordering */
1766 visual = pScreen->visuals + pScreen->numVisuals;
1767 while (--visual >= pScreen->visuals) {
1768 if ((visual->class | DynamicClass) == DirectColor) {
1769 visual->offsetRed = pScrn->offset.red;
1770 visual->offsetGreen = pScrn->offset.green;
1771 visual->offsetBlue = pScrn->offset.blue;
1772 visual->redMask = pScrn->mask.red;
1773 visual->greenMask = pScrn->mask.green;
1774 visual->blueMask = pScrn->mask.blue;
1775 }
1776 }
1777 }
1778
1779 /* must be after visual RGB order fixed */
1780 if (pScrn->bitsPerPixel > 4)
1781 fbPictureInit(pScreen, 0, 0);
1782
1783 xf86SetBlackWhitePixels(pScreen);
1784
1785 if (!pApm->ShadowFB) { /* hardware cursor needs to wrap this layer */
1786 if(!ApmDGAInit(pScreen)) {
1787 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DGA initialization failed\n");
1788 }
1789 }
1790
1791 /*
1792 * Initialize the acceleration interface.
1793 */
1794 #ifdef HAVE_XAA_H
1795 if (!pApm->NoAccel) {
1796 ApmAccelInit(pScreen); /* set up XAA interface */
1797 }
1798 #endif
1799
1800 xf86SetBackingStore(pScreen);
1801 xf86SetSilkenMouse(pScreen);
1802
1803 /* Initialise cursor functions */
1804 miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
1805
1806 /* Initialize HW cursor layer (after DGA and SW cursor) */
1807 if (pApm->hwCursor) {
1808 if (!ApmHWCursorInit(pScreen))
1809 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1810 "Hardware cursor initialization failed\n");
1811 }
1812
1813
1814 /* Initialise default colourmap */
1815 if (!miCreateDefColormap(pScreen))
1816 return FALSE;
1817
1818 /*
1819 * Initialize colormap layer.
1820 * Must follow initialization of the default colormap.
1821 */
1822 if (!xf86HandleColormaps(pScreen, 256, 8, ApmLoadPalette, NULL,
1823 CMAP_RELOAD_ON_MODE_SWITCH)) {
1824 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Colormap initialization failed\n");
1825 return FALSE;
1826 }
1827
1828 if (pApm->ShadowFB)
1829 ShadowFBInit(pScreen, ApmRefreshArea);
1830
1831 xf86DPMSInit(pScreen, ApmDisplayPowerManagementSet, 0);
1832
1833 ApmInitVideo(pScreen);
1834
1835 pScreen->SaveScreen = ApmSaveScreen;
1836
1837 pApm->CloseScreen = pScreen->CloseScreen;
1838 pScreen->CloseScreen = ApmCloseScreen;
1839
1840 pScrn->memPhysBase = pApm->LinAddress;
1841 pScrn->fbOffset = (((char *)pApm->FbBase) - ((char *)pApm->LinMap));
1842
1843 /* Report any unused options (only for the first generation) */
1844 if (serverGeneration == 1) {
1845 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1846 }
1847
1848 #ifdef XF86RUSH
1849 if (ApmGeneration != serverGeneration) {
1850 if ((ApmPixmapIndex = AllocatePixmapPrivateIndex()) < 0)
1851 return FALSE;
1852 ApmGeneration = serverGeneration;
1853 }
1854
1855 if (!AllocatePixmapPrivate(pScreen, ApmPixmapIndex, sizeof(ApmPixmapRec)))
1856 return FALSE;
1857 #endif
1858
1859 /* Done */
1860 return TRUE;
1861 }
1862
1863 /* mandatory */
1864 static void
ApmLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1865 ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1866 VisualPtr pVisual)
1867 {
1868 APMDECL(pScrn);
1869 int i, index, last = -1;
1870
1871 if (pApm->VGAMap) {
1872 for (i = 0; i < numColors; i++) {
1873 index = indices[i];
1874 if (index != last)
1875 ApmWriteDacWriteAddr(index);
1876 last = index + 1;
1877 ApmWriteDacData(colors[index].red);
1878 ApmWriteDacData(colors[index].green);
1879 ApmWriteDacData(colors[index].blue);
1880 }
1881 }
1882 else {
1883 for (i = 0; i < numColors; i++) {
1884 index = indices[i];
1885 if (index != last)
1886 outb(pApm->iobase + 0x3C8, index);
1887 last = index + 1;
1888 outb(pApm->iobase + 0x3C9, colors[index].red);
1889 outb(pApm->iobase + 0x3C9, colors[index].green);
1890 outb(pApm->iobase + 0x3C9, colors[index].blue);
1891 }
1892 }
1893 }
1894
1895 /* Usually mandatory */
1896 Bool
ApmSwitchMode(SWITCH_MODE_ARGS_DECL)1897 ApmSwitchMode(SWITCH_MODE_ARGS_DECL)
1898 {
1899 SCRN_INFO_PTR(arg);
1900 return ApmModeInit(pScrn, mode);
1901 }
1902
1903 /*
1904 * This function is used to initialize the Start Address - the first
1905 * displayed location in the video memory.
1906 */
1907 /* Usually mandatory */
1908 void
ApmAdjustFrame(ADJUST_FRAME_ARGS_DECL)1909 ApmAdjustFrame(ADJUST_FRAME_ARGS_DECL)
1910 {
1911 SCRN_INFO_PTR(arg);
1912 APMDECL(pScrn);
1913 int Base;
1914
1915 if (pApm->CurrentLayout.bitsPerPixel == 24)
1916 x = (x + 3) & ~3;
1917 Base = ((y * pApm->CurrentLayout.displayWidth + x) * (pApm->CurrentLayout.bitsPerPixel / 8)) >> 2;
1918 /*
1919 * These are the generic starting address registers.
1920 */
1921 if (pApm->VGAMap) {
1922 ApmWriteCrtc(0x0C, Base >> 8);
1923 ApmWriteCrtc(0x0D, Base);
1924
1925 /*
1926 * Here the high-order bits are masked and shifted, and put into
1927 * the appropriate extended registers.
1928 */
1929 ApmWriteCrtc(0x1C, (ApmReadCrtc(0x1C) & 0xF0) | ((Base & 0x0F0000) >> 16));
1930 }
1931 else {
1932 outw(pApm->iobase + 0x3D4, (Base & 0x00FF00) | 0x0C);
1933 outw(pApm->iobase + 0x3D4, ((Base & 0x00FF) << 8) | 0x0D);
1934
1935 /*
1936 * Here the high-order bits are masked and shifted, and put into
1937 * the appropriate extended registers.
1938 */
1939 modinx(pApm->iobase + 0x3D4, 0x1C, 0x0F, (Base & 0x0F0000) >> 16);
1940 }
1941 }
1942
1943 /*
1944 * This is called when VT switching back to the X server. Its job is
1945 * to reinitialise the video mode.
1946 *
1947 * We may wish to unmap video/MMIO memory too.
1948 */
1949
1950 /* Mandatory */
1951 static Bool
ApmEnterVT(VT_FUNC_ARGS_DECL)1952 ApmEnterVT(VT_FUNC_ARGS_DECL)
1953 {
1954 SCRN_INFO_PTR(arg);
1955 APMDECL(pScrn);
1956 vgaHWPtr hwp = VGAHWPTR(pScrn);
1957
1958 if (pApm->Chipset >= AT3D) {
1959 /* If you change it, change it also in apm_funcs.c */
1960 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A | pApm->Rush);
1961 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
1962 }
1963 if (pApm->Chipset >= AP6422)
1964 WRXB(0xC9, pApm->c9 | 0x10);
1965 ApmUnlock(APMPTR(pScrn));
1966 vgaHWUnlock(hwp);
1967 /*
1968 * Set color mode
1969 */
1970 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
1971
1972 if (!ApmModeInit(pScrn, pScrn->currentMode))
1973 return FALSE;
1974 ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1975
1976 return TRUE;
1977 }
1978
1979 /* Mandatory */
1980 static void
ApmLeaveVT(VT_FUNC_ARGS_DECL)1981 ApmLeaveVT(VT_FUNC_ARGS_DECL)
1982 {
1983 SCRN_INFO_PTR(arg);
1984 APMDECL(pScrn);
1985 vgaHWPtr hwp = VGAHWPTR(pScrn);
1986
1987 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
1988 /*
1989 * Reset color mode
1990 */
1991 (*hwp->writeMiscOut)(hwp, pApm->MiscOut);
1992 vgaHWLock(hwp);
1993 ApmLock(pApm);
1994 if (pApm->Chipset >= AT3D) {
1995 WRXB(0xD9, pApm->d9);
1996 WRXB(0xDB, pApm->db);
1997 }
1998 WRXB(0xC9, pApm->c9);
1999
2000 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
2001 if (xf86IsPc98())
2002 outb(0xFAC, 0xFE);
2003 #endif
2004 }
2005
2006 /*
2007 * This is called at the end of each server generation. It restores the
2008 * original (text) mode. It should really also unmap the video memory too.
2009 */
2010
2011 /* Mandatory */
2012 static Bool
ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL)2013 ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL)
2014 {
2015 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2016 vgaHWPtr hwp = VGAHWPTR(pScrn);
2017 APMDECL(pScrn);
2018
2019 if (pScrn->vtSema) {
2020 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
2021 vgaHWLock(hwp);
2022 ApmUnmapMem(pScrn);
2023 }
2024 #ifdef HAVE_XAA_H
2025 if(pApm->AccelInfoRec)
2026 XAADestroyInfoRec(pApm->AccelInfoRec);
2027 if(pApm->DGAXAAInfo)
2028 XAADestroyInfoRec(pApm->DGAXAAInfo);
2029 pApm->AccelInfoRec = NULL;
2030 #endif
2031 if(pApm->CursorInfoRec)
2032 xf86DestroyCursorInfoRec(pApm->CursorInfoRec);
2033 pApm->CursorInfoRec = NULL;
2034 free(pApm->DGAModes);
2035 free(pApm->adaptor);
2036
2037 pScrn->vtSema = FALSE;
2038
2039 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
2040 if (xf86IsPc98())
2041 outb(0xFAC, 0xFE);
2042 #endif
2043
2044 pScreen->CloseScreen = pApm->CloseScreen;
2045 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
2046 }
2047
2048 /* Free up any per-generation data structures */
2049
2050 /* Optional */
2051 static void
ApmFreeScreen(FREE_SCREEN_ARGS_DECL)2052 ApmFreeScreen(FREE_SCREEN_ARGS_DECL)
2053 {
2054 SCRN_INFO_PTR(arg);
2055 vgaHWFreeHWRec(pScrn);
2056 ApmFreeRec(pScrn);
2057 }
2058
2059 /* Checks if a mode is suitable for the selected chipset. */
2060
2061 /* Optional */
2062 static ModeStatus
ApmValidMode(SCRN_ARG_TYPE arg,DisplayModePtr mode,Bool verbose,int flags)2063 ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
2064 {
2065 if (mode->Flags & V_INTERLACE)
2066 return(MODE_BAD);
2067
2068 return(MODE_OK);
2069 }
2070
2071
2072 /*
2073 * ApmDisplayPowerManagementSet --
2074 *
2075 * Sets VESA Display Power Management Signaling (DPMS) Mode.
2076 */
2077 static void
ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn,int PowerManagementMode,int flags)2078 ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
2079 int flags)
2080 {
2081 APMDECL(pScrn);
2082 unsigned char dpmsreg, tmp;
2083
2084 if (PowerManagementMode < sizeof pApm->DPMSMask &&
2085 PowerManagementMode >= 0)
2086 PowerManagementMode = pApm->DPMSMask[PowerManagementMode];
2087 switch (PowerManagementMode)
2088 {
2089 case DPMSModeOn:
2090 /* Screen: On; HSync: On, VSync: On */
2091 dpmsreg = 0x00;
2092 break;
2093 case DPMSModeStandby:
2094 /* Screen: Off; HSync: Off, VSync: On */
2095 dpmsreg = 0x01;
2096 break;
2097 case DPMSModeSuspend:
2098 /* Screen: Off; HSync: On, VSync: Off */
2099 dpmsreg = 0x02;
2100 break;
2101 case DPMSModeOff:
2102 /* Screen: Off; HSync: Off, VSync: Off */
2103 dpmsreg = 0x03;
2104 break;
2105 default:
2106 dpmsreg = 0;
2107 }
2108 tmp = RDXB(0xD0);
2109 WRXB(0xD0, (tmp & 0xFC) | dpmsreg);
2110 }
2111
2112 static Bool
ApmSaveScreen(ScreenPtr pScreen,int mode)2113 ApmSaveScreen(ScreenPtr pScreen, int mode)
2114 {
2115 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2116 Bool unblank;
2117
2118 unblank = xf86IsUnblank(mode);
2119
2120 if (unblank)
2121 SetTimeSinceLastInputEvent();
2122
2123 if (pScrn->vtSema)
2124 vgaHWBlankScreen(pScrn, unblank);
2125 return TRUE;
2126 }
2127
2128 #ifdef APM_DEBUG
2129 unsigned char _L_ACR(unsigned char *x);
_L_ACR(unsigned char * x)2130 unsigned char _L_ACR(unsigned char *x)
2131 {
2132 return *x;
2133 }
2134
2135 unsigned short _L_ASR(unsigned short *x);
_L_ASR(unsigned short * x)2136 unsigned short _L_ASR(unsigned short *x)
2137 {
2138 return *x;
2139 }
2140
2141 unsigned int _L_AIR(unsigned int *x);
_L_AIR(unsigned int * x)2142 unsigned int _L_AIR(unsigned int *x)
2143 {
2144 return *x;
2145 }
2146
2147 void _L_ACW(char *x, char y);
_L_ACW(char * x,char y)2148 void _L_ACW(char *x, char y)
2149 {
2150 *x = y;
2151 }
2152
2153 void _L_ASW(short *x, short y);
_L_ASW(short * x,short y)2154 void _L_ASW(short *x, short y)
2155 {
2156 *x = y;
2157 }
2158
2159 void _L_AIW(int *x, int y);
_L_AIW(int * x,int y)2160 void _L_AIW(int *x, int y)
2161 {
2162 *x = y;
2163 }
2164 #endif
2165