ast_driver.c revision de78e416
1/*
2 * Copyright (c) 2005 ASPEED Technology Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  The authors makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26#include "xf86.h"
27#include "xf86_OSproc.h"
28#include "xf86Resources.h"
29#include "xf86RAC.h"
30#include "xf86cmap.h"
31#include "compiler.h"
32#include "mibstore.h"
33#include "vgaHW.h"
34#include "mipointer.h"
35#include "micmap.h"
36
37#include "fb.h"
38#include "regionstr.h"
39#include "xf86xv.h"
40#include <X11/extensions/Xv.h>
41#include "vbe.h"
42
43#include "xf86PciInfo.h"
44#include "xf86Pci.h"
45
46/* framebuffer offscreen manager */
47#include "xf86fbman.h"
48
49/* include xaa includes */
50#include "xaa.h"
51#include "xaarop.h"
52
53/* H/W cursor support */
54#include "xf86Cursor.h"
55
56/* Driver specific headers */
57#include "ast.h"
58
59/* external reference fucntion */
60extern Bool ASTMapMem(ScrnInfoPtr pScrn);
61extern Bool ASTUnmapMem(ScrnInfoPtr pScrn);
62extern Bool ASTMapMMIO(ScrnInfoPtr pScrn);
63extern void ASTUnmapMMIO(ScrnInfoPtr pScrn);
64
65extern void vASTOpenKey(ScrnInfoPtr pScrn);
66extern Bool bASTRegInit(ScrnInfoPtr pScrn);
67extern void GetDRAMInfo(ScrnInfoPtr pScrn);
68extern ULONG GetVRAMInfo(ScrnInfoPtr pScrn);
69extern ULONG GetMaxDCLK(ScrnInfoPtr pScrn);
70extern void GetChipType(ScrnInfoPtr pScrn);
71extern void vASTLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual);
72extern void ASTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
73extern void vSetStartAddressCRT1(ASTRecPtr pAST, ULONG base);
74extern Bool ASTSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode);
75extern Bool GetVGA2EDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer);
76extern void vInitDRAMReg(ScrnInfoPtr pScrn);
77extern Bool bIsVGAEnabled(ScrnInfoPtr pScrn);
78extern void ASTBlankScreen(ScrnInfoPtr pScreen, Bool unblack);
79extern Bool InitVGA(ScrnInfoPtr pScrn);
80
81extern Bool bInitCMDQInfo(ScrnInfoPtr pScrn, ASTRecPtr pAST);
82extern Bool bEnableCMDQ(ScrnInfoPtr pScrn, ASTRecPtr pAST);
83extern void vDisable2D(ScrnInfoPtr pScrn, ASTRecPtr pAST);
84
85extern Bool ASTAccelInit(ScreenPtr pScreen);
86
87extern Bool ASTCursorInit(ScreenPtr pScreen);
88extern void ASTHideCursor(ScrnInfoPtr pScrn);
89
90/* Mandatory functions */
91static void ASTIdentify(int flags);
92const OptionInfoRec *ASTAvailableOptions(int chipid, int busid);
93static Bool ASTProbe(DriverPtr drv, int flags);
94static Bool ASTPreInit(ScrnInfoPtr pScrn, int flags);
95static Bool ASTScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
96Bool ASTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
97void ASTAdjustFrame(int scrnIndex, int x, int y, int flags);
98static Bool ASTEnterVT(int scrnIndex, int flags);
99static void ASTLeaveVT(int scrnIndex, int flags);
100static void ASTFreeScreen(int scrnIndex, int flags);
101static ModeStatus ASTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags);
102
103/* Internally used functions */
104static Bool ASTGetRec(ScrnInfoPtr pScrn);
105static void ASTFreeRec(ScrnInfoPtr pScrn);
106static Bool ASTSaveScreen(ScreenPtr pScreen, Bool unblack);
107static Bool ASTCloseScreen(int scrnIndex, ScreenPtr pScreen);
108static void ASTSave(ScrnInfoPtr pScrn);
109static void ASTRestore(ScrnInfoPtr pScrn);
110static void ASTProbeDDC(ScrnInfoPtr pScrn, int index);
111static xf86MonPtr ASTDoDDC(ScrnInfoPtr pScrn, int index);
112static void vFillASTModeInfo (ScrnInfoPtr pScrn);
113static Bool ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
114
115/*
116 * This is intentionally screen-independent.  It indicates the binding
117 * choice made in the first PreInit.
118 */
119_X_EXPORT DriverRec AST = {
120   AST_VERSION,
121   AST_DRIVER_NAME,
122   ASTIdentify,
123   ASTProbe,
124   ASTAvailableOptions,
125   NULL,
126   0
127};
128
129/* Chipsets */
130static SymTabRec ASTChipsets[] = {
131   {PCI_CHIP_AST2000,	"ASPEED Graphics Family"},
132   {PCI_CHIP_AST2100,	"ASPEED Graphics Family"},
133   {-1,			NULL}
134};
135
136static PciChipsets ASTPciChipsets[] = {
137   {PCI_CHIP_AST2000,		PCI_CHIP_AST2000,	RES_SHARED_VGA},
138   {PCI_CHIP_AST2100,		PCI_CHIP_AST2100,	RES_SHARED_VGA},
139   {-1,				-1, 			RES_UNDEFINED }
140};
141
142typedef enum {
143   OPTION_NOACCEL,
144   OPTION_MMIO2D,
145   OPTION_SW_CURSOR,
146   OPTION_HWC_NUM,
147   OPTION_ENG_CAPS,
148   OPTION_DBG_SELECT,
149   OPTION_NO_DDC,
150   OPTION_VGA2_CLONE
151} ASTOpts;
152
153static const OptionInfoRec ASTOptions[] = {
154   {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
155   {OPTION_MMIO2D,	"MMIO2D",	OPTV_BOOLEAN,	{0},	FALSE},
156   {OPTION_SW_CURSOR,	"SWCursor",	OPTV_BOOLEAN,	{0},	FALSE},
157   {OPTION_HWC_NUM,	"HWCNumber",	OPTV_INTEGER,	{0},	FALSE},
158   {OPTION_ENG_CAPS,	"ENGCaps",	OPTV_INTEGER,	{0},	FALSE},
159   {OPTION_DBG_SELECT,	"DBGSelect",	OPTV_INTEGER,	{0},	FALSE},
160   {OPTION_NO_DDC,	"NoDDC",	OPTV_BOOLEAN,	{0}, 	FALSE},
161   {OPTION_VGA2_CLONE,	"VGA2Clone",	OPTV_BOOLEAN,	{0}, 	FALSE},
162   {-1,			NULL,		OPTV_NONE,	{0}, 	FALSE}
163};
164
165#ifdef XFree86LOADER
166
167static MODULESETUPPROTO(astSetup);
168
169static XF86ModuleVersionInfo astVersRec = {
170   AST_DRIVER_NAME,
171   MODULEVENDORSTRING,
172   MODINFOSTRING1,
173   MODINFOSTRING2,
174   XORG_VERSION_CURRENT,
175   AST_MAJOR_VERSION, AST_MINOR_VERSION, AST_PATCH_VERSION,
176   ABI_CLASS_VIDEODRV,
177#ifdef PATCH_ABI_VERSION
178   ABI_VIDEODRV_VERSION_PATCH,
179#else
180   ABI_VIDEODRV_VERSION,
181#endif
182   MOD_CLASS_VIDEODRV,
183   {0, 0, 0, 0}
184};
185
186_X_EXPORT XF86ModuleData astModuleData = { &astVersRec, astSetup, NULL };
187
188static pointer
189astSetup(pointer module, pointer opts, int *errmaj, int *errmin)
190{
191   static Bool setupDone = FALSE;
192
193   /* This module should be loaded only once, but check to be sure.
194    */
195   if (!setupDone) {
196      setupDone = TRUE;
197      xf86AddDriver(&AST, module, 0);
198
199      /*
200       * The return value must be non-NULL on success even though there
201       * is no TearDownProc.
202       */
203      return (pointer) TRUE;
204   } else {
205      if (errmaj)
206	 *errmaj = LDR_ONCEONLY;
207      return NULL;
208   }
209}
210
211#endif	/* XFree86LOADER */
212
213/*
214 * ASTIdentify --
215 *
216 * Returns the string name for the driver based on the chipset. In this
217 * case it will always be an AST, so we can return a static string.
218 *
219 */
220static void
221ASTIdentify(int flags)
222{
223   xf86PrintChipsets(AST_NAME, "Driver for ASPEED Graphics Chipsets",
224		     ASTChipsets);
225}
226
227const OptionInfoRec *
228ASTAvailableOptions(int chipid, int busid)
229{
230
231   return ASTOptions;
232
233}
234
235/*
236 * ASTProbe --
237 *
238 * Look through the PCI bus to find cards that are AST boards.
239 * Setup the dispatch table for the rest of the driver functions.
240 *
241 */
242static Bool
243ASTProbe(DriverPtr drv, int flags)
244{
245    int i, numUsed, numDevSections, *usedChips;
246    Bool foundScreen = FALSE;
247    GDevPtr *devSections;
248
249   /*
250    * Find the config file Device sections that match this
251    * driver, and return if there are none.
252    */
253    if ((numDevSections =
254	xf86MatchDevice(AST_DRIVER_NAME, &devSections)) <= 0) {
255      return FALSE;
256    }
257
258#ifndef XSERVER_LIBPCIACCESS
259   /*
260    * This probing is just checking the PCI data the server already
261    * collected.
262    */
263    if (xf86GetPciVideoInfo() == NULL) {
264	return FALSE;
265    }
266#endif
267
268    numUsed = xf86MatchPciInstances(AST_NAME, PCI_VENDOR_AST,
269				   ASTChipsets, ASTPciChipsets,
270				   devSections, numDevSections,
271				   drv, &usedChips);
272
273    xfree(devSections);
274
275    if (flags & PROBE_DETECT) {
276        if (numUsed > 0)
277	    foundScreen = TRUE;
278    } else {
279        for (i = 0; i < numUsed; i++) {
280	    ScrnInfoPtr pScrn = NULL;
281
282	    /* Allocate new ScrnInfoRec and claim the slot */
283	    if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
284					     ASTPciChipsets, 0, 0, 0, 0, 0)))
285            {
286	        EntityInfoPtr pEnt;
287
288	        pEnt = xf86GetEntityInfo(usedChips[i]);
289
290	        pScrn->driverVersion = AST_VERSION;
291	        pScrn->driverName = AST_DRIVER_NAME;
292	        pScrn->name = AST_NAME;
293
294	        pScrn->Probe = ASTProbe;
295	        pScrn->PreInit = ASTPreInit;
296	        pScrn->ScreenInit = ASTScreenInit;
297	        pScrn->SwitchMode = ASTSwitchMode;
298	        pScrn->AdjustFrame = ASTAdjustFrame;
299	        pScrn->EnterVT = ASTEnterVT;
300	        pScrn->LeaveVT = ASTLeaveVT;
301	        pScrn->FreeScreen = ASTFreeScreen;
302	        pScrn->ValidMode = ASTValidMode;
303
304	        foundScreen = TRUE;
305
306	    } /* end of if */
307        }  /* end of for-loop */
308    } /* end of if flags */
309
310    xfree(usedChips);
311
312    return foundScreen;
313}
314
315/*
316 * ASTPreInit --
317 *
318 * Do initial setup of the board before we know what resolution we will
319 * be running at.
320 *
321 */
322static Bool
323ASTPreInit(ScrnInfoPtr pScrn, int flags)
324{
325   EntityInfoPtr pEnt;
326   vgaHWPtr hwp;
327   int flags24;
328   rgb defaultWeight = { 0, 0, 0 };
329
330   ASTRecPtr pAST;
331
332   ClockRangePtr clockRanges;
333   int i;
334   MessageType from;
335
336   /* Suport one adapter only now */
337   if (pScrn->numEntities != 1)
338       return FALSE;
339
340   pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
341
342   if (flags & PROBE_DETECT) {
343       ASTProbeDDC(pScrn, pEnt->index);
344       return TRUE;
345   }
346
347   if (pEnt->location.type != BUS_PCI)
348       return FALSE;
349
350   if (xf86RegisterResources(pEnt->index, 0, ResExclusive))
351       return FALSE;
352
353   /* The vgahw module should be loaded here when needed */
354   if (!xf86LoadSubModule(pScrn, "vgahw"))
355      return FALSE;
356
357   /* The fb module should be loaded here when needed */
358   if (!xf86LoadSubModule(pScrn, "fb"))
359      return FALSE;
360
361   /* Allocate a vgaHWRec */
362   if (!vgaHWGetHWRec(pScrn))
363       return FALSE;
364   hwp = VGAHWPTR(pScrn);
365
366   /* Color Depth Check */
367   flags24 = Support32bppFb;
368   if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
369      return FALSE;
370   } else {
371      switch (pScrn->depth) {
372      case 8:
373      case 16:
374      case 24:
375	 break;
376      default:
377	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
378		    "Given depth (%d) is not supported by ast driver\n",
379		    pScrn->depth);
380	 return FALSE;
381      }
382   }
383   xf86PrintDepthBpp(pScrn);
384
385   switch (pScrn->bitsPerPixel) {
386   case 8:
387   case 16:
388   case 32:
389      break;
390   default:
391      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
392		 "Given bpp (%d) is not supported by ast driver\n",
393		 pScrn->bitsPerPixel);
394      return FALSE;
395   }
396
397   /* fill pScrn misc. */
398   pScrn->progClock = TRUE;
399   pScrn->rgbBits = 6;
400   pScrn->monitor = pScrn->confScreen->monitor; /* should be initialized before set gamma */
401   pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
402   pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
403
404   /*
405    * If the driver can do gamma correction, it should call xf86SetGamma()
406    * here.
407    */
408   {
409      Gamma zeros = { 0.0, 0.0, 0.0 };
410
411      if (!xf86SetGamma(pScrn, zeros)) {
412         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call xf86SetGamma failed \n");
413	 return FALSE;
414      }
415   }
416
417
418   if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) {
419       return FALSE;
420   }
421
422   if (!xf86SetDefaultVisual(pScrn, -1)) {
423       return FALSE;
424   }
425
426   /* Allocate driverPrivate */
427   if (!ASTGetRec(pScrn)) {
428       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call ASTGetRec failed \n");
429       return FALSE;
430   }
431
432   /* Fill AST Info */
433   pAST = ASTPTR(pScrn);
434   pAST->pEnt    = xf86GetEntityInfo(pScrn->entityList[0]);
435   pAST->PciInfo = xf86GetPciInfoForEntity(pAST->pEnt->index);
436#ifndef XSERVER_LIBPCIACCESS
437   pAST->PciTag  = pciTag(pAST->PciInfo->bus, pAST->PciInfo->device,
438			  pAST->PciInfo->func);
439#endif
440
441   /* Process the options
442    * pScrn->confScreen, pScrn->display, pScrn->monitor, pScrn->numEntities,
443    * and pScrn->entityList should be initialized before
444    */
445   xf86CollectOptions(pScrn, NULL);
446   if (!(pAST->Options = xalloc(sizeof(ASTOptions))))
447   {
448      ASTFreeRec(pScrn);
449      return FALSE;
450   }
451   memcpy(pAST->Options, ASTOptions, sizeof(ASTOptions));
452   xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pAST->Options);
453
454   /*
455    * Set the Chipset and ChipRev, allowing config file entries to
456    * override.
457    */
458   if (pAST->pEnt->device->chipset && *pAST->pEnt->device->chipset) {
459      pScrn->chipset = pAST->pEnt->device->chipset;
460      from = X_CONFIG;
461   } else if (pAST->pEnt->device->chipID >= 0) {
462      pScrn->chipset = (char *)xf86TokenToString(ASTChipsets,
463						 pAST->pEnt->device->chipID);
464      from = X_CONFIG;
465      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
466		 pAST->pEnt->device->chipID);
467   } else {
468      from = X_PROBED;
469      pScrn->chipset = (char *)xf86TokenToString(ASTChipsets,
470						 PCI_DEV_DEVICE_ID(pAST->PciInfo));
471   }
472   if (pAST->pEnt->device->chipRev >= 0) {
473      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
474		 pAST->pEnt->device->chipRev);
475   }
476
477   xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
478	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown ast");
479
480   /* Resource Allocation */
481    pAST->IODBase = pScrn->domainIOBase;
482    /* "Patch" the PIOOffset inside vgaHW in order to force
483     * the vgaHW module to use our relocated i/o ports.
484     */
485    VGAHWPTR(pScrn)->PIOOffset = pAST->PIOOffset = pAST->IODBase + PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) - 0x380;
486
487    pAST->RelocateIO = (IOADDRESS)(PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) + pAST->IODBase);
488
489   if (pAST->pEnt->device->MemBase != 0) {
490      pAST->FBPhysAddr = pAST->pEnt->device->MemBase;
491      from = X_CONFIG;
492   } else {
493      if (PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) != 0) {
494	 pAST->FBPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) & 0xFFF00000;
495	 from = X_PROBED;
496      } else {
497	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
498		    "No valid FB address in PCI config space\n");
499	 ASTFreeRec(pScrn);
500	 return FALSE;
501      }
502   }
503   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer at 0x%lX\n",
504	      (unsigned long) pAST->FBPhysAddr);
505
506   if (pAST->pEnt->device->IOBase != 0) {
507      pAST->MMIOPhysAddr = pAST->pEnt->device->IOBase;
508      from = X_CONFIG;
509   } else {
510      if (PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM)) {
511	 pAST->MMIOPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM) & 0xFFFF0000;
512	 from = X_PROBED;
513      } else {
514	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
515		    "No valid MMIO address in PCI config space\n");
516	 ASTFreeRec(pScrn);
517	 return FALSE;
518      }
519   }
520   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "IO registers at addr 0x%lX\n",
521	      (unsigned long) pAST->MMIOPhysAddr);
522
523   /* Map MMIO */
524   pAST->MMIOMapSize = DEFAULT_MMIO_SIZE;
525   if (!ASTMapMMIO(pScrn)) {
526      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map Memory Map IO Failed \n");
527      return FALSE;
528   }
529
530   /* Init VGA Adapter */
531   if (!xf86IsPrimaryPci(pAST->PciInfo))
532   {
533       InitVGA(pScrn);
534   }
535
536   vASTOpenKey(pScrn);
537   bASTRegInit(pScrn);
538
539   /* Get Chip Type */
540   if (PCI_DEV_REVISION(pAST->PciInfo) >= 0x10)
541       GetChipType(pScrn);
542   else
543       pAST->jChipType = AST2000;
544
545   /* Get DRAM Info */
546   GetDRAMInfo(pScrn);
547
548   /* Map Framebuffer */
549   pScrn->videoRam = GetVRAMInfo(pScrn) / 1024;
550   from = X_DEFAULT;
551
552   if (pAST->pEnt->device->videoRam) {
553      pScrn->videoRam = pAST->pEnt->device->videoRam;
554      from = X_CONFIG;
555   }
556
557   pAST->FbMapSize = pScrn->videoRam * 1024;
558
559#if 0
560   if (!ASTMapMem(pScrn)) {
561      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n");
562      return FALSE;
563   }
564#endif
565
566   pScrn->memPhysBase = (ULONG)pAST->FBPhysAddr;
567   pScrn->fbOffset = 0;
568
569   /* Do DDC
570    * should be done after xf86CollectOptions
571    */
572   pScrn->monitor->DDC = ASTDoDDC(pScrn, pAST->pEnt->index);
573
574   /* Mode Valid */
575   clockRanges = xnfcalloc(sizeof(ClockRange), 1);
576   clockRanges->next = NULL;
577   clockRanges->minClock = 9500;
578   clockRanges->maxClock = GetMaxDCLK(pScrn) * 1000;
579   clockRanges->clockIndex = -1;
580   clockRanges->interlaceAllowed = FALSE;
581   clockRanges->doubleScanAllowed = FALSE;
582
583   /* Add for AST2100, ycchen@061807 */
584   if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200))
585       i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
586			 pScrn->display->modes, clockRanges,
587			 0, 320, 1920, 8 * pScrn->bitsPerPixel,
588			 200, 1200,
589			 pScrn->display->virtualX, pScrn->display->virtualY,
590			 pAST->FbMapSize, LOOKUP_BEST_REFRESH);
591   else
592       i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
593			 pScrn->display->modes, clockRanges,
594			 0, 320, 1600, 8 * pScrn->bitsPerPixel,
595			 200, 1200,
596			 pScrn->display->virtualX, pScrn->display->virtualY,
597			 pAST->FbMapSize, LOOKUP_BEST_REFRESH);
598
599   if (i == -1) {
600      ASTFreeRec(pScrn);
601      return FALSE;
602   }
603
604   xf86PruneDriverModes(pScrn);
605
606   if (!i || !pScrn->modes) {
607      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
608      ASTFreeRec(pScrn);
609      return FALSE;
610   }
611
612   xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
613
614   pScrn->currentMode = pScrn->modes;
615
616   xf86PrintModes(pScrn);
617
618   xf86SetDpi(pScrn, 0, 0);
619
620   /* Accelaration Check */
621   pAST->noAccel = TRUE;
622   pAST->AccelInfoPtr = NULL;
623   pAST->pCMDQPtr = NULL;
624   pAST->CMDQInfo.ulCMDQSize = 0;
625#ifdef	Accel_2D
626   if (!xf86ReturnOptValBool(pAST->Options, OPTION_NOACCEL, FALSE))
627   {
628       if (!xf86LoadSubModule(pScrn, "xaa")) {
629	   ASTFreeRec(pScrn);
630	   return FALSE;
631       }
632
633       pAST->noAccel = FALSE;
634
635       pAST->MMIO2D = TRUE;
636#ifndef	MMIO_2D
637       if (!xf86ReturnOptValBool(pAST->Options, OPTION_MMIO2D, FALSE)) {
638           pAST->CMDQInfo.ulCMDQSize = DEFAULT_CMDQ_SIZE;
639           pAST->MMIO2D = FALSE;
640       }
641#endif
642
643       pAST->ENGCaps = ENG_CAP_ALL;
644       if (!xf86GetOptValInteger(pAST->Options, OPTION_ENG_CAPS, &pAST->ENGCaps)) {
645           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No ENG Capability options found\n");
646       }
647
648       pAST->DBGSelect = 0;
649       if (!xf86GetOptValInteger(pAST->Options, OPTION_DBG_SELECT, &pAST->DBGSelect)) {
650           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DBG Seleclt options found\n");
651       }
652   }
653#endif
654
655   /* HW Cursor Check */
656   pAST->noHWC = TRUE;
657   pAST->HWCInfoPtr = NULL;
658   pAST->pHWCPtr = NULL;
659#ifdef	HWC
660   if (!xf86ReturnOptValBool(pAST->Options, OPTION_SW_CURSOR, FALSE)) {
661      if (!xf86LoadSubModule(pScrn, "ramdac")) {
662	 ASTFreeRec(pScrn);
663	 return FALSE;
664      }
665
666      pAST->noHWC = FALSE;
667      pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM;
668      if (!xf86GetOptValInteger(pAST->Options, OPTION_HWC_NUM, &pAST->HWCInfo.HWC_NUM)) {
669          xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No HWC_NUM options found\n");
670      }
671
672   }
673#endif
674
675   /*  We won't be using the VGA access after the probe */
676   xf86SetOperatingState(resVgaIo, pAST->pEnt->index, ResUnusedOpr);
677   xf86SetOperatingState(resVgaMem, pAST->pEnt->index, ResDisableOpr);
678
679   return TRUE;
680}
681
682
683static Bool
684ASTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
685{
686   ScrnInfoPtr pScrn;
687   ASTRecPtr pAST;
688   vgaHWPtr hwp;
689   VisualPtr visual;
690
691   /* for FB Manager */
692   BoxRec FBMemBox;
693   int    AvailFBSize;
694
695   pScrn = xf86Screens[pScreen->myNum];
696   pAST = ASTPTR(pScrn);
697   hwp = VGAHWPTR(pScrn);
698
699   if (!ASTMapMem(pScrn)) {
700      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n");
701      return FALSE;
702   }
703
704/*   if (!pAST->noAccel) */
705   {
706       /* AvailFBSize = pAST->FbMapSize - pAST->CMDQInfo.ulCMDQSize; */
707       AvailFBSize = pAST->FbMapSize;
708
709       FBMemBox.x1 = 0;
710       FBMemBox.y1 = 0;
711       FBMemBox.x2 = pScrn->displayWidth;
712       FBMemBox.y2 = (AvailFBSize / (pScrn->displayWidth * ((pScrn->bitsPerPixel+1)/8))) - 1;
713
714       if (!xf86InitFBManager(pScreen, &FBMemBox)) {
715          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n");
716          return FALSE;
717       }
718
719   }
720
721   vgaHWGetIOBase(hwp);
722
723   vFillASTModeInfo (pScrn);
724
725   ASTSave(pScrn);
726   if (!ASTModeInit(pScrn, pScrn->currentMode)) {
727      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Mode Init Failed \n");
728      return FALSE;
729   }
730
731   ASTSaveScreen(pScreen, FALSE);
732   ASTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
733
734   miClearVisualTypes();
735
736   /* Re-implemented Direct Color support, -jens */
737   if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
738			 pScrn->rgbBits, pScrn->defaultVisual))
739      return FALSE;
740
741   if (!miSetPixmapDepths())
742   {
743       ASTSaveScreen(pScreen, SCREEN_SAVER_OFF);
744       return FALSE;
745   }
746
747   switch(pScrn->bitsPerPixel) {
748       case 8:
749       case 16:
750       case 32:
751           if (!fbScreenInit(pScreen, pAST->FBVirtualAddr + pScrn->fbOffset,
752  	                     pScrn->virtualX, pScrn->virtualY,
753		             pScrn->xDpi, pScrn->yDpi,
754		             pScrn->displayWidth, pScrn->bitsPerPixel))
755               return FALSE;
756           break;
757       default:
758           return FALSE;
759
760   }
761
762   if (pScrn->bitsPerPixel > 8) {
763      /* Fixup RGB ordering */
764      visual = pScreen->visuals + pScreen->numVisuals;
765      while (--visual >= pScreen->visuals) {
766	 if ((visual->class | DynamicClass) == DirectColor) {
767	    visual->offsetRed = pScrn->offset.red;
768	    visual->offsetGreen = pScrn->offset.green;
769	    visual->offsetBlue = pScrn->offset.blue;
770	    visual->redMask = pScrn->mask.red;
771	    visual->greenMask = pScrn->mask.green;
772	    visual->blueMask = pScrn->mask.blue;
773	 }
774      }
775   }
776
777   fbPictureInit(pScreen, 0, 0);
778
779   xf86SetBlackWhitePixels(pScreen);
780
781#ifdef Accel_2D
782   if (!pAST->noAccel)
783   {
784       if (!ASTAccelInit(pScreen)) {
785           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware acceleration initialization failed\n");
786           pAST->noAccel = TRUE;
787       }
788   }
789#endif /* end of Accel_2D */
790
791   miInitializeBackingStore(pScreen);
792   xf86SetBackingStore(pScreen);
793   xf86SetSilkenMouse(pScreen);
794
795   miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
796
797   if (!pAST->noHWC)
798   {
799       if (!ASTCursorInit(pScreen)) {
800           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware cursor initialization failed\n");
801           pAST->noHWC = TRUE;
802       }
803   }
804
805   if (!miCreateDefColormap(pScreen))
806      return FALSE;
807
808   if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits,
809                    vASTLoadPalette, NULL,
810                    CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) {
811       return FALSE;
812   }
813
814   xf86DPMSInit(pScreen, ASTDisplayPowerManagementSet, 0);
815
816   pScreen->SaveScreen = ASTSaveScreen;
817   pAST->CloseScreen = pScreen->CloseScreen;
818   pScreen->CloseScreen = ASTCloseScreen;
819
820   if (serverGeneration == 1)
821      xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
822
823   return TRUE;
824
825} /* ASTScreenInit */
826
827
828Bool
829ASTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
830{
831   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
832   ASTRecPtr pAST = ASTPTR(pScrn);
833
834#ifdef	HWC
835   if (pAST->pHWCPtr) {
836       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
837       pAST->pHWCPtr = NULL;
838   }
839   ASTHideCursor(pScrn);
840#endif
841
842#ifdef Accel_2D
843   if (pAST->pCMDQPtr) {
844       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
845       pAST->pCMDQPtr = NULL;
846   }
847   vDisable2D(pScrn, pAST);
848#endif
849
850   ASTRestore(pScrn);
851
852   return ASTModeInit(pScrn, mode);
853
854}
855
856void
857ASTAdjustFrame(int scrnIndex, int x, int y, int flags)
858{
859   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
860   ASTRecPtr   pAST  = ASTPTR(pScrn);
861   ULONG base;
862
863   base = y * pAST->VideoModeInfo.ScreenWidth + x * ((pAST->VideoModeInfo.bitsPerPixel + 1) / 8);
864   base = base >> 2;				/* DW unit */
865
866   vSetStartAddressCRT1(pAST, base);
867
868}
869
870/* enter into X Server */
871static Bool
872ASTEnterVT(int scrnIndex, int flags)
873{
874   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
875
876   /* Fixed suspend can't resume issue */
877   if (!bIsVGAEnabled(pScrn))
878   {
879       InitVGA(pScrn);
880       ASTRestore(pScrn);
881   }
882
883   if (!ASTModeInit(pScrn, pScrn->currentMode))
884      return FALSE;
885   ASTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
886
887   return TRUE;
888
889}
890
891/* leave X server */
892static void
893ASTLeaveVT(int scrnIndex, int flags)
894{
895
896   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
897   vgaHWPtr hwp = VGAHWPTR(pScrn);
898   ASTRecPtr pAST = ASTPTR(pScrn);
899
900#ifdef	HWC
901   if (pAST->pHWCPtr) {
902       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
903       pAST->pHWCPtr = NULL;
904   }
905   ASTHideCursor(pScrn);
906#endif
907
908#ifdef Accel_2D
909   if (pAST->pCMDQPtr) {
910       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
911       pAST->pCMDQPtr = NULL;
912   }
913   vDisable2D(pScrn, pAST);
914#endif
915
916   ASTRestore(pScrn);
917   vgaHWLock(hwp);
918
919}
920
921static void
922ASTFreeScreen(int scrnIndex, int flags)
923{
924   ASTFreeRec(xf86Screens[scrnIndex]);
925   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
926      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
927}
928
929
930static ModeStatus
931ASTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
932{
933
934   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
935   ASTRecPtr   pAST  = ASTPTR(pScrn);
936   Bool Flags = MODE_NOMODE;
937
938   if (mode->Flags & V_INTERLACE) {
939      if (verbose) {
940	 xf86DrvMsg(scrnIndex, X_PROBED,
941		    "Removing interlaced mode \"%s\"\n", mode->name);
942      }
943      return MODE_NO_INTERLACE;
944   }
945
946   if ((mode->CrtcHDisplay > MAX_HResolution) || (mode->CrtcVDisplay > MAX_VResolution)) {
947      if (verbose) {
948	 xf86DrvMsg(scrnIndex, X_PROBED,
949		    "Removing the mode \"%s\"\n", mode->name);
950      }
951      return Flags;
952   }
953
954   /* Add for AST2100, ycchen@061807 */
955   if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200))
956   {
957       if ( (mode->CrtcHDisplay == 1920) && (mode->CrtcVDisplay == 1200) )
958           return MODE_OK;
959   }
960
961   switch (mode->CrtcHDisplay)
962   {
963   case 640:
964       if (mode->CrtcVDisplay == 480) Flags=MODE_OK;
965       break;
966   case 800:
967       if (mode->CrtcVDisplay == 600) Flags=MODE_OK;
968       break;
969   case 1024:
970       if (mode->CrtcVDisplay == 768) Flags=MODE_OK;
971       break;
972   case 1280:
973       if (mode->CrtcVDisplay == 1024) Flags=MODE_OK;
974       break;
975   case 1600:
976       if (mode->CrtcVDisplay == 1200) Flags=MODE_OK;
977       break;
978   default:
979       return Flags;
980   }
981
982   return Flags;
983
984}
985
986
987/* Internal used modules */
988/*
989 * ASTGetRec and ASTFreeRec --
990 *
991 * Private data for the driver is stored in the screen structure.
992 * These two functions create and destroy that private data.
993 *
994 */
995static Bool
996ASTGetRec(ScrnInfoPtr pScrn)
997{
998   if (pScrn->driverPrivate)
999      return TRUE;
1000
1001   pScrn->driverPrivate = xnfcalloc(sizeof(ASTRec), 1);
1002   return TRUE;
1003}
1004
1005static void
1006ASTFreeRec(ScrnInfoPtr pScrn)
1007{
1008   if (!pScrn)
1009      return;
1010   if (!pScrn->driverPrivate)
1011      return;
1012   xfree(pScrn->driverPrivate);
1013   pScrn->driverPrivate = 0;
1014}
1015
1016static Bool
1017ASTSaveScreen(ScreenPtr pScreen, Bool unblack)
1018{
1019   /* replacement of vgaHWBlankScreen(pScrn, unblank) without seq reset */
1020   /* return vgaHWSaveScreen(pScreen, unblack); */
1021   ScrnInfoPtr pScrn = NULL;
1022
1023   if (pScreen != NULL)
1024      pScrn = xf86Screens[pScreen->myNum];
1025
1026   if ((pScrn != NULL) && pScrn->vtSema) {
1027     ASTBlankScreen(pScrn, unblack);
1028   }
1029   return (TRUE);
1030}
1031
1032static Bool
1033ASTCloseScreen(int scrnIndex, ScreenPtr pScreen)
1034{
1035   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1036   vgaHWPtr hwp = VGAHWPTR(pScrn);
1037   ASTRecPtr pAST = ASTPTR(pScrn);
1038
1039   if (pScrn->vtSema == TRUE)
1040   {
1041#ifdef	HWC
1042   if (pAST->pHWCPtr) {
1043       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
1044       pAST->pHWCPtr = NULL;
1045   }
1046   ASTHideCursor(pScrn);
1047#endif
1048
1049#ifdef Accel_2D
1050   if (pAST->pCMDQPtr) {
1051       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
1052       pAST->pCMDQPtr = NULL;
1053   }
1054   vDisable2D(pScrn, pAST);
1055#endif
1056
1057      ASTRestore(pScrn);
1058      vgaHWLock(hwp);
1059   }
1060
1061   ASTUnmapMem(pScrn);
1062   vgaHWUnmapMem(pScrn);
1063
1064   if(pAST->AccelInfoPtr) {
1065       XAADestroyInfoRec(pAST->AccelInfoPtr);
1066       pAST->AccelInfoPtr = NULL;
1067   }
1068
1069   if(pAST->HWCInfoPtr) {
1070       xf86DestroyCursorInfoRec(pAST->HWCInfoPtr);
1071       pAST->HWCInfoPtr = NULL;
1072   }
1073
1074   pScrn->vtSema = FALSE;
1075   pScreen->CloseScreen = pAST->CloseScreen;
1076   return (*pScreen->CloseScreen) (scrnIndex, pScreen);
1077}
1078
1079static void
1080ASTSave(ScrnInfoPtr pScrn)
1081{
1082   ASTRecPtr pAST;
1083   vgaRegPtr vgaReg;
1084   ASTRegPtr astReg;
1085   int i, icount=0;
1086
1087   pAST = ASTPTR(pScrn);
1088   vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1089   astReg = &pAST->SavedReg;
1090
1091   /* do save */
1092   if (xf86IsPrimaryPci(pAST->PciInfo)) {
1093       vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
1094   }
1095   else {
1096       vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
1097   }
1098
1099   /* Ext. Save */
1100   vASTOpenKey(pScrn);
1101
1102   /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */
1103   for (i=0x81; i<=0xB6; i++)
1104       GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1105   for (i=0xBC; i<=0xC1; i++)
1106       GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1107   GetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]);
1108
1109}
1110
1111static void
1112ASTRestore(ScrnInfoPtr pScrn)
1113{
1114   ASTRecPtr pAST;
1115   vgaRegPtr vgaReg;
1116   ASTRegPtr astReg;
1117   int i, icount=0;
1118
1119   pAST = ASTPTR(pScrn);
1120   vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1121   astReg = &pAST->SavedReg;
1122
1123   /* do restore */
1124   vgaHWProtect(pScrn, TRUE);
1125   if (xf86IsPrimaryPci(pAST->PciInfo))
1126       vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1127   else
1128       vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
1129   vgaHWProtect(pScrn, FALSE);
1130
1131   /* Ext. restore */
1132   vASTOpenKey(pScrn);
1133
1134   /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */
1135   for (i=0x81; i<=0xB6; i++)
1136       SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1137   for (i=0xBC; i<=0xC1; i++)
1138       SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1139   SetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]);
1140
1141}
1142
1143static void
1144ASTProbeDDC(ScrnInfoPtr pScrn, int index)
1145{
1146   vbeInfoPtr pVbe;
1147
1148   if (xf86LoadSubModule(pScrn, "vbe")) {
1149      pVbe = VBEInit(NULL, index);
1150      ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1151      vbeFree(pVbe);
1152   }
1153}
1154
1155#define SkipDT	0x00
1156#define DT1	0x01
1157#define DT2 	0x02
1158
1159static xf86MonPtr
1160ASTDoDDC(ScrnInfoPtr pScrn, int index)
1161{
1162   vbeInfoPtr pVbe;
1163   xf86MonPtr MonInfo = NULL, MonInfo1 = NULL, MonInfo2 = NULL;
1164   ASTRecPtr pAST = ASTPTR(pScrn);
1165   unsigned long i, j, k;
1166   unsigned char DDC_data[128];
1167   struct monitor_ranges ranges, ranges1, ranges2;
1168   int DTSelect, dclock1=0, h_active1=0, v_active1=0, dclock2=0, h_active2=0, v_active2=0;
1169   struct std_timings stdtiming, *stdtiming1, *stdtiming2;
1170
1171   /* Honour Option "noDDC" */
1172   if (xf86ReturnOptValBool(pAST->Options, OPTION_NO_DDC, FALSE)) {
1173      return MonInfo;
1174   }
1175
1176   if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
1177      MonInfo1 = vbeDoEDID(pVbe, NULL);
1178      MonInfo = MonInfo1;
1179
1180      /* For VGA2 CLONE Support, ycchen@012508 */
1181      if ((xf86ReturnOptValBool(pAST->Options, OPTION_VGA2_CLONE, FALSE)) || pAST->VGA2Clone) {
1182          if (GetVGA2EDID(pScrn, DDC_data) == TRUE) {
1183              xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Get VGA2 EDID Correctly!! \n");
1184              MonInfo2 = xf86InterpretEDID(pScrn->scrnIndex, DDC_data);
1185              if (MonInfo1 == NULL)	/* No DDC1 EDID */
1186                  MonInfo = MonInfo2;
1187              else {			/* Check with VGA1 & VGA2 EDID */
1188                  /* Update establishment timing */
1189                  MonInfo->timings1.t1 = MonInfo1->timings1.t1 & MonInfo2->timings1.t1;
1190                  MonInfo->timings1.t2 = MonInfo1->timings1.t2 & MonInfo2->timings1.t2;
1191                  MonInfo->timings1.t_manu = MonInfo1->timings1.t_manu & MonInfo2->timings1.t_manu;
1192
1193                  /* Update Std. Timing */
1194                  for (i=0; i<8; i++) {
1195	              stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0;
1196                      for (j=0; j<8; j++) {
1197                          if ((MonInfo1->timings2[i].hsize == MonInfo2->timings2[j].hsize) && \
1198                              (MonInfo1->timings2[i].vsize == MonInfo2->timings2[j].vsize) && \
1199                              (MonInfo1->timings2[i].refresh == MonInfo2->timings2[j].refresh)) {
1200                               stdtiming = MonInfo1->timings2[i];
1201                               break;
1202                          }
1203                      }
1204
1205                      MonInfo->timings2[i] = stdtiming;
1206                  } /* Std. Timing */
1207
1208                  /* Get Detailed Timing */
1209                  for (i=0;i<4;i++) {
1210                    if (MonInfo1->det_mon[i].type == 0xFD)
1211                        ranges1 = MonInfo1->det_mon[i].section.ranges;
1212                    else if (MonInfo1->det_mon[i].type == 0xFA)
1213                        stdtiming1 = MonInfo1->det_mon[i].section.std_t;
1214                    else if (MonInfo1->det_mon[i].type == 0x00) {
1215                        if (MonInfo1->det_mon[i].section.d_timings.clock > dclock1)
1216                            dclock1 = MonInfo1->det_mon[i].section.d_timings.clock;
1217                        if (MonInfo1->det_mon[i].section.d_timings.h_active > h_active1)
1218                            h_active1 = MonInfo1->det_mon[i].section.d_timings.h_active;
1219                        if (MonInfo1->det_mon[i].section.d_timings.v_active > v_active1)
1220                            v_active1 = MonInfo1->det_mon[i].section.d_timings.v_active;
1221                    }
1222                    if (MonInfo2->det_mon[i].type == 0xFD)
1223                        ranges2 = MonInfo2->det_mon[i].section.ranges;
1224                    else if (MonInfo1->det_mon[i].type == 0xFA)
1225                        stdtiming2 = MonInfo2->det_mon[i].section.std_t;
1226                    else if (MonInfo2->det_mon[i].type == 0x00) {
1227                        if (MonInfo2->det_mon[i].section.d_timings.clock > dclock2)
1228                            dclock2 = MonInfo2->det_mon[i].section.d_timings.clock;
1229                        if (MonInfo2->det_mon[i].section.d_timings.h_active > h_active2)
1230                            h_active2 = MonInfo2->det_mon[i].section.d_timings.h_active;
1231                        if (MonInfo2->det_mon[i].section.d_timings.v_active > v_active2)
1232                            v_active2 = MonInfo2->det_mon[i].section.d_timings.v_active;
1233                    }
1234                  } /* Get Detailed Timing */
1235
1236                  /* Chk Detailed Timing */
1237                  if ((dclock1 >= dclock2) && (h_active1 >= h_active2) && (v_active1 >= v_active2))
1238                      DTSelect = DT2;
1239                  else if ((dclock2 >= dclock1) && (h_active2 >= h_active1) && (v_active2 >= v_active1))
1240                      DTSelect = DT1;
1241                  else
1242                      DTSelect = SkipDT;
1243
1244                  /* Chk Monitor Descriptor */
1245                  ranges = ranges1;
1246                  ranges.min_h = ranges1.min_h > ranges2.min_h ? ranges1.min_h:ranges2.min_h;
1247                  ranges.min_v = ranges1.min_v > ranges2.min_v ? ranges1.min_v:ranges2.min_v;
1248                  ranges.max_h = ranges1.max_h < ranges2.max_h ? ranges1.max_h:ranges2.max_h;
1249                  ranges.max_v = ranges1.max_v < ranges2.max_v ? ranges1.max_v:ranges2.max_v;
1250                  ranges.max_clock = ranges1.max_clock < ranges2.max_clock ? ranges1.max_clock:ranges2.max_clock;
1251
1252                  /* Update Detailed Timing */
1253                  for (i=0; i<4; i++)
1254                  {
1255                      if (MonInfo->det_mon[i].type == 0xFD) {
1256                          MonInfo->det_mon[i].section.ranges = ranges;
1257                      }
1258                      else if (MonInfo->det_mon[i].type == 0xFA) {
1259                         for (j=0; j<5; j++) {
1260            	             stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0;
1261                             for (k=0; k<5; k++) {
1262                                 if ((stdtiming1[j].hsize == stdtiming2[k].hsize) && \
1263                                     (stdtiming1[j].vsize == stdtiming2[k].vsize) && \
1264                                     (stdtiming1[j].refresh == stdtiming2[k].refresh)) {
1265                                      stdtiming = stdtiming1[j];
1266                                      break;
1267                                 }
1268                             }
1269                             stdtiming1[j] = stdtiming;
1270                         } /* Std. Timing */
1271                      } /* FA */
1272                      else if (MonInfo->det_mon[i].type == 0x00) {
1273                          if (DTSelect == DT2)
1274                              MonInfo->det_mon[i] = MonInfo2->det_mon[i];
1275                          else if (DTSelect == DT1)
1276                              MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1277                          else /* SkipDT */
1278                          {   /* use 1024x768 as default */
1279                              MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1280                              MonInfo->det_mon[i].section.d_timings.clock = 65000000;
1281                              MonInfo->det_mon[i].section.d_timings.h_active = 1024;
1282                              MonInfo->det_mon[i].section.d_timings.h_blanking = 320;
1283                              MonInfo->det_mon[i].section.d_timings.v_active = 768;
1284                              MonInfo->det_mon[i].section.d_timings.v_blanking = 38;
1285                              MonInfo->det_mon[i].section.d_timings.h_sync_off = 24;
1286                              MonInfo->det_mon[i].section.d_timings.h_sync_width = 136;
1287                              MonInfo->det_mon[i].section.d_timings.v_sync_off = 3;
1288                              MonInfo->det_mon[i].section.d_timings.v_sync_width = 6;
1289                          }
1290                      } /* 00 */
1291                      else { /* use Monitor 1 as default */
1292                          MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1293                      }
1294
1295                  } /* Update Detailed Timing */
1296
1297                  /* set feature size */
1298                  if (DTSelect == DT2)  {
1299                      MonInfo->features.hsize = MonInfo2->features.hsize;
1300                      MonInfo->features.vsize = MonInfo2->features.vsize;
1301                  }
1302                  else if (DTSelect == DT1)  {
1303                      MonInfo->features.hsize = MonInfo1->features.hsize;
1304                      MonInfo->features.vsize = MonInfo1->features.vsize;
1305                  }
1306                  else	/* Skip DT */
1307                  {   /* use 1024x768 as default */
1308                      MonInfo->features.hsize = 0x20;
1309                      MonInfo->features.vsize = 0x18;
1310                  }
1311
1312              } /* Check with VGA1 & VGA2 EDID */
1313
1314          } /* GetVGA2EDID */
1315          else {
1316              xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Can't Get VGA2 EDID Correctly!! \n");
1317          }
1318
1319      }
1320
1321      xf86PrintEDID(MonInfo);
1322      xf86SetDDCproperties(pScrn, MonInfo);
1323      vbeFree(pVbe);
1324   } else {
1325      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1326		 "this driver cannot do DDC without VBE\n");
1327   }
1328
1329   return MonInfo;
1330}
1331
1332static void
1333vFillASTModeInfo (ScrnInfoPtr pScrn)
1334{
1335    ASTRecPtr pAST;
1336
1337    pAST = ASTPTR(pScrn);
1338
1339    pAST->VideoModeInfo.ScreenWidth = pScrn->virtualX;
1340    pAST->VideoModeInfo.ScreenHeight = pScrn->virtualY;
1341    pAST->VideoModeInfo.bitsPerPixel = pScrn->bitsPerPixel;
1342    /* Fixed screen pitch incorrect in some specific monitor, ycchen@071707 */
1343    pAST->VideoModeInfo.ScreenPitch = pScrn->displayWidth * ((pScrn->bitsPerPixel + 1) / 8) ;
1344
1345}
1346
1347static Bool
1348ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1349{
1350    vgaHWPtr hwp;
1351    ASTRecPtr pAST;
1352
1353    hwp = VGAHWPTR(pScrn);
1354    pAST = ASTPTR(pScrn);
1355
1356    vgaHWUnlock(hwp);
1357
1358    if (!vgaHWInit(pScrn, mode))
1359      return FALSE;
1360
1361    pScrn->vtSema = TRUE;
1362    pAST->ModePtr = mode;
1363
1364    if (!ASTSetMode(pScrn, mode))
1365      return FALSE;
1366
1367    vgaHWProtect(pScrn, FALSE);
1368
1369    return TRUE;
1370}
1371