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