ast_driver.c revision 6c78137b
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, ULONG Flags);
82extern Bool GetVGAEDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer);
83extern Bool bInitAST1180(ScrnInfoPtr pScrn);
84extern void GetAST1180DRAMInfo(ScrnInfoPtr pScrn);
85
86extern Bool bInitCMDQInfo(ScrnInfoPtr pScrn, ASTRecPtr pAST);
87extern Bool bEnableCMDQ(ScrnInfoPtr pScrn, ASTRecPtr pAST);
88extern void vDisable2D(ScrnInfoPtr pScrn, ASTRecPtr pAST);
89
90extern Bool ASTAccelInit(ScreenPtr pScreen);
91
92extern Bool ASTCursorInit(ScreenPtr pScreen);
93extern void ASTDisableHWC(ScrnInfoPtr pScrn);
94
95/* Mandatory functions */
96static void ASTIdentify(int flags);
97const OptionInfoRec *ASTAvailableOptions(int chipid, int busid);
98static Bool ASTProbe(DriverPtr drv, int flags);
99static Bool ASTPreInit(ScrnInfoPtr pScrn, int flags);
100static Bool ASTScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
101Bool ASTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
102void ASTAdjustFrame(int scrnIndex, int x, int y, int flags);
103static Bool ASTEnterVT(int scrnIndex, int flags);
104static void ASTLeaveVT(int scrnIndex, int flags);
105static void ASTFreeScreen(int scrnIndex, int flags);
106static ModeStatus ASTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags);
107
108/* Internally used functions */
109static Bool ASTGetRec(ScrnInfoPtr pScrn);
110static void ASTFreeRec(ScrnInfoPtr pScrn);
111static Bool ASTSaveScreen(ScreenPtr pScreen, Bool unblack);
112static Bool ASTCloseScreen(int scrnIndex, ScreenPtr pScreen);
113static void ASTSave(ScrnInfoPtr pScrn);
114static void ASTRestore(ScrnInfoPtr pScrn);
115static void ASTProbeDDC(ScrnInfoPtr pScrn, int index);
116static xf86MonPtr ASTDoDDC(ScrnInfoPtr pScrn, int index);
117static void vFillASTModeInfo (ScrnInfoPtr pScrn);
118static Bool ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
119
120#ifdef AstVideo
121/* video function */
122static void ASTInitVideo(ScreenPtr pScreen);
123static int  ASTPutImage( ScrnInfoPtr,
124        short, short, short, short, short, short, short, short,
125        int, unsigned char*, short, short, Bool, RegionPtr, pointer,
126	DrawablePtr);
127#endif
128
129/*
130 * This is intentionally screen-independent.  It indicates the binding
131 * choice made in the first PreInit.
132 */
133_X_EXPORT DriverRec AST = {
134   AST_VERSION,
135   AST_DRIVER_NAME,
136   ASTIdentify,
137   ASTProbe,
138   ASTAvailableOptions,
139   NULL,
140   0
141};
142
143/* Chipsets */
144static SymTabRec ASTChipsets[] = {
145   {PCI_CHIP_AST2000,	"ASPEED Graphics Family"},
146   {PCI_CHIP_AST2100,	"ASPEED Graphics Family"},
147   {PCI_CHIP_AST1180,	"ASPEED AST1180 Graphics"},
148   {-1,			NULL}
149};
150
151static PciChipsets ASTPciChipsets[] = {
152   {PCI_CHIP_AST2000,		PCI_CHIP_AST2000,	RES_SHARED_VGA},
153   {PCI_CHIP_AST2100,		PCI_CHIP_AST2100,	RES_SHARED_VGA},
154   {PCI_CHIP_AST1180,		PCI_CHIP_AST1180,	RES_SHARED_VGA},
155   {-1,				-1, 			RES_UNDEFINED }
156};
157
158typedef enum {
159   OPTION_NOACCEL,
160   OPTION_MMIO2D,
161   OPTION_SW_CURSOR,
162   OPTION_HWC_NUM,
163   OPTION_ENG_CAPS,
164   OPTION_DBG_SELECT,
165   OPTION_NO_DDC,
166   OPTION_VGA2_CLONE
167} ASTOpts;
168
169static const OptionInfoRec ASTOptions[] = {
170   {OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN,	{0},	FALSE},
171   {OPTION_MMIO2D,	"MMIO2D",	OPTV_BOOLEAN,	{0},	FALSE},
172   {OPTION_SW_CURSOR,	"SWCursor",	OPTV_BOOLEAN,	{0},	FALSE},
173   {OPTION_HWC_NUM,	"HWCNumber",	OPTV_INTEGER,	{0},	FALSE},
174   {OPTION_ENG_CAPS,	"ENGCaps",	OPTV_INTEGER,	{0},	FALSE},
175   {OPTION_DBG_SELECT,	"DBGSelect",	OPTV_INTEGER,	{0},	FALSE},
176   {OPTION_NO_DDC,	"NoDDC",	OPTV_BOOLEAN,	{0}, 	FALSE},
177   {OPTION_VGA2_CLONE,	"VGA2Clone",	OPTV_BOOLEAN,	{0}, 	FALSE},
178   {-1,			NULL,		OPTV_NONE,	{0}, 	FALSE}
179};
180
181#ifdef XFree86LOADER
182
183static MODULESETUPPROTO(astSetup);
184
185static XF86ModuleVersionInfo astVersRec = {
186   AST_DRIVER_NAME,
187   MODULEVENDORSTRING,
188   MODINFOSTRING1,
189   MODINFOSTRING2,
190   XORG_VERSION_CURRENT,
191   AST_MAJOR_VERSION, AST_MINOR_VERSION, AST_PATCH_VERSION,
192   ABI_CLASS_VIDEODRV,
193#ifdef PATCH_ABI_VERSION
194   ABI_VIDEODRV_VERSION_PATCH,
195#else
196   ABI_VIDEODRV_VERSION,
197#endif
198   MOD_CLASS_VIDEODRV,
199   {0, 0, 0, 0}
200};
201
202_X_EXPORT XF86ModuleData astModuleData = { &astVersRec, astSetup, NULL };
203
204static pointer
205astSetup(pointer module, pointer opts, int *errmaj, int *errmin)
206{
207   static Bool setupDone = FALSE;
208
209   /* This module should be loaded only once, but check to be sure.
210    */
211   if (!setupDone) {
212      setupDone = TRUE;
213      xf86AddDriver(&AST, module, 0);
214
215      /*
216       * The return value must be non-NULL on success even though there
217       * is no TearDownProc.
218       */
219      return (pointer) TRUE;
220   } else {
221      if (errmaj)
222	 *errmaj = LDR_ONCEONLY;
223      return NULL;
224   }
225}
226
227#endif	/* XFree86LOADER */
228
229/*
230 * ASTIdentify --
231 *
232 * Returns the string name for the driver based on the chipset. In this
233 * case it will always be an AST, so we can return a static string.
234 *
235 */
236static void
237ASTIdentify(int flags)
238{
239   xf86PrintChipsets(AST_NAME, "Driver for ASPEED Graphics Chipsets",
240		     ASTChipsets);
241}
242
243const OptionInfoRec *
244ASTAvailableOptions(int chipid, int busid)
245{
246
247   return ASTOptions;
248
249}
250
251/*
252 * ASTProbe --
253 *
254 * Look through the PCI bus to find cards that are AST boards.
255 * Setup the dispatch table for the rest of the driver functions.
256 *
257 */
258static Bool
259ASTProbe(DriverPtr drv, int flags)
260{
261    int i, numUsed, numDevSections, *usedChips;
262    Bool foundScreen = FALSE;
263    GDevPtr *devSections;
264
265   /*
266    * Find the config file Device sections that match this
267    * driver, and return if there are none.
268    */
269    if ((numDevSections =
270	xf86MatchDevice(AST_DRIVER_NAME, &devSections)) <= 0) {
271      return FALSE;
272    }
273
274#ifndef XSERVER_LIBPCIACCESS
275   /*
276    * This probing is just checking the PCI data the server already
277    * collected.
278    */
279    if (xf86GetPciVideoInfo() == NULL) {
280	return FALSE;
281    }
282#endif
283
284    numUsed = xf86MatchPciInstances(AST_NAME, PCI_VENDOR_AST,
285				   ASTChipsets, ASTPciChipsets,
286				   devSections, numDevSections,
287				   drv, &usedChips);
288
289    free(devSections);
290
291    if (flags & PROBE_DETECT) {
292        if (numUsed > 0)
293	    foundScreen = TRUE;
294    } else {
295        for (i = 0; i < numUsed; i++) {
296	    ScrnInfoPtr pScrn = NULL;
297
298	    /* Allocate new ScrnInfoRec and claim the slot */
299	    if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
300					     ASTPciChipsets, 0, 0, 0, 0, 0)))
301            {
302	        EntityInfoPtr pEnt;
303
304	        pEnt = xf86GetEntityInfo(usedChips[i]);
305
306	        pScrn->driverVersion = AST_VERSION;
307	        pScrn->driverName = AST_DRIVER_NAME;
308	        pScrn->name = AST_NAME;
309
310	        pScrn->Probe = ASTProbe;
311	        pScrn->PreInit = ASTPreInit;
312	        pScrn->ScreenInit = ASTScreenInit;
313	        pScrn->SwitchMode = ASTSwitchMode;
314	        pScrn->AdjustFrame = ASTAdjustFrame;
315	        pScrn->EnterVT = ASTEnterVT;
316	        pScrn->LeaveVT = ASTLeaveVT;
317	        pScrn->FreeScreen = ASTFreeScreen;
318	        pScrn->ValidMode = ASTValidMode;
319
320	        foundScreen = TRUE;
321
322	    } /* end of if */
323        }  /* end of for-loop */
324    } /* end of if flags */
325
326    free(usedChips);
327
328    return foundScreen;
329}
330
331/*
332 * ASTPreInit --
333 *
334 * Do initial setup of the board before we know what resolution we will
335 * be running at.
336 *
337 */
338static Bool
339ASTPreInit(ScrnInfoPtr pScrn, int flags)
340{
341   EntityInfoPtr pEnt;
342   vgaHWPtr hwp;
343   int flags24;
344   rgb defaultWeight = { 0, 0, 0 };
345
346   ASTRecPtr pAST;
347
348   ClockRangePtr clockRanges;
349   int i;
350   MessageType from;
351   int maxPitch, maxHeight;
352
353   /* Suport one adapter only now */
354   if (pScrn->numEntities != 1)
355       return FALSE;
356
357   pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
358
359   if (flags & PROBE_DETECT) {
360       ASTProbeDDC(pScrn, pEnt->index);
361       return TRUE;
362   }
363
364   if (pEnt->location.type != BUS_PCI)
365       return FALSE;
366
367#ifndef XSERVER_LIBPCIACCESS
368   if (xf86RegisterResources(pEnt->index, 0, ResExclusive))
369       return FALSE;
370#endif
371
372   /* The vgahw module should be loaded here when needed */
373   if (!xf86LoadSubModule(pScrn, "vgahw"))
374      return FALSE;
375
376   /* The fb module should be loaded here when needed */
377   if (!xf86LoadSubModule(pScrn, "fb"))
378      return FALSE;
379
380   /* Allocate a vgaHWRec */
381   if (!vgaHWGetHWRec(pScrn))
382       return FALSE;
383   hwp = VGAHWPTR(pScrn);
384
385   /* Color Depth Check */
386   flags24 = Support32bppFb;
387   if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
388      return FALSE;
389   } else {
390      switch (pScrn->depth) {
391      case 8:
392      case 16:
393      case 24:
394	 break;
395      default:
396	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
397		    "Given depth (%d) is not supported by ast driver\n",
398		    pScrn->depth);
399	 return FALSE;
400      }
401   }
402   xf86PrintDepthBpp(pScrn);
403
404   switch (pScrn->bitsPerPixel) {
405   case 8:
406   case 16:
407   case 32:
408      break;
409   default:
410      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
411		 "Given bpp (%d) is not supported by ast driver\n",
412		 pScrn->bitsPerPixel);
413      return FALSE;
414   }
415
416   /* fill pScrn misc. */
417   pScrn->progClock = TRUE;
418   pScrn->rgbBits = 6;
419   pScrn->monitor = pScrn->confScreen->monitor; /* should be initialized before set gamma */
420#ifndef XSERVER_LIBPCIACCESS
421   pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
422   pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
423#endif
424
425   /*
426    * If the driver can do gamma correction, it should call xf86SetGamma()
427    * here.
428    */
429   {
430      Gamma zeros = { 0.0, 0.0, 0.0 };
431
432      if (!xf86SetGamma(pScrn, zeros)) {
433         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call xf86SetGamma failed \n");
434	 return FALSE;
435      }
436   }
437
438
439   if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) {
440       return FALSE;
441   }
442
443   if (!xf86SetDefaultVisual(pScrn, -1)) {
444       return FALSE;
445   }
446
447   /* Allocate driverPrivate */
448   if (!ASTGetRec(pScrn)) {
449       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call ASTGetRec failed \n");
450       return FALSE;
451   }
452
453   /* Fill AST Info */
454   pAST = ASTPTR(pScrn);
455   pAST->pEnt    = xf86GetEntityInfo(pScrn->entityList[0]);
456   pAST->PciInfo = xf86GetPciInfoForEntity(pAST->pEnt->index);
457#ifndef XSERVER_LIBPCIACCESS
458   pAST->PciTag  = pciTag(pAST->PciInfo->bus, pAST->PciInfo->device,
459			  pAST->PciInfo->func);
460#endif
461
462   /* Process the options
463    * pScrn->confScreen, pScrn->display, pScrn->monitor, pScrn->numEntities,
464    * and pScrn->entityList should be initialized before
465    */
466   xf86CollectOptions(pScrn, NULL);
467   if (!(pAST->Options = malloc(sizeof(ASTOptions))))
468   {
469      ASTFreeRec(pScrn);
470      return FALSE;
471   }
472   memcpy(pAST->Options, ASTOptions, sizeof(ASTOptions));
473   xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pAST->Options);
474
475   /*
476    * Set the Chipset and ChipRev, allowing config file entries to
477    * override.
478    */
479   if (pAST->pEnt->device->chipset && *pAST->pEnt->device->chipset) {
480      pScrn->chipset = pAST->pEnt->device->chipset;
481      from = X_CONFIG;
482   } else if (pAST->pEnt->device->chipID >= 0) {
483      pScrn->chipset = (char *)xf86TokenToString(ASTChipsets,
484						 pAST->pEnt->device->chipID);
485      from = X_CONFIG;
486      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
487		 pAST->pEnt->device->chipID);
488   } else {
489      from = X_PROBED;
490      pScrn->chipset = (char *)xf86TokenToString(ASTChipsets,
491						 PCI_DEV_DEVICE_ID(pAST->PciInfo));
492   }
493   if (pAST->pEnt->device->chipRev >= 0) {
494      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
495		 pAST->pEnt->device->chipRev);
496   }
497
498   xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
499	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown ast");
500
501   /* Resource Allocation */
502    pAST->IODBase = pScrn->domainIOBase;
503    /* "Patch" the PIOOffset inside vgaHW in order to force
504     * the vgaHW module to use our relocated i/o ports.
505     */
506    VGAHWPTR(pScrn)->PIOOffset = pAST->PIOOffset = pAST->IODBase + PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) - 0x380;
507
508    pAST->RelocateIO = (IOADDRESS)(PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) + pAST->IODBase);
509
510   if (pAST->pEnt->device->MemBase != 0) {
511      pAST->FBPhysAddr = pAST->pEnt->device->MemBase;
512      from = X_CONFIG;
513   } else {
514      if (PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) != 0) {
515	 pAST->FBPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) & 0xFFF00000;
516	 from = X_PROBED;
517      } else {
518	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
519		    "No valid FB address in PCI config space\n");
520	 ASTFreeRec(pScrn);
521	 return FALSE;
522      }
523   }
524   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer at 0x%lX\n",
525	      (unsigned long) pAST->FBPhysAddr);
526
527   if (pAST->pEnt->device->IOBase != 0) {
528      pAST->MMIOPhysAddr = pAST->pEnt->device->IOBase;
529      from = X_CONFIG;
530   } else {
531      if (PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM)) {
532	 pAST->MMIOPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM) & 0xFFFF0000;
533	 from = X_PROBED;
534      } else {
535	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
536		    "No valid MMIO address in PCI config space\n");
537	 ASTFreeRec(pScrn);
538	 return FALSE;
539      }
540   }
541   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "IO registers at addr 0x%lX\n",
542	      (unsigned long) pAST->MMIOPhysAddr);
543
544   /* Map MMIO */
545   pAST->MMIOMapSize = DEFAULT_MMIO_SIZE;
546   if (!ASTMapMMIO(pScrn)) {
547      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map Memory Map IO Failed \n");
548      return FALSE;
549   }
550
551   if (PCI_DEV_DEVICE_ID(pAST->PciInfo) == PCI_CHIP_AST1180)
552   {
553       pAST->jChipType = AST1180;
554
555       /* validate mode */
556       if ( (pScrn->bitsPerPixel == 8) || (pScrn->depth == 8) )
557       {
558           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
559		      "Given bpp (%d) is not supported by ast driver\n",
560		      pScrn->bitsPerPixel);
561           return FALSE;
562       }
563
564       /* Init AST1180 */
565       bInitAST1180(pScrn);
566
567       /* Get AST1180 Information */
568       GetAST1180DRAMInfo(pScrn);
569       pScrn->videoRam = pAST->ulVRAMSize / 1024;
570
571   }
572   else
573   {
574       /* Init VGA Adapter */
575       if (!xf86IsPrimaryPci(pAST->PciInfo))
576       {
577           InitVGA(pScrn, 0);
578       }
579
580       vASTOpenKey(pScrn);
581       bASTRegInit(pScrn);
582
583       /* Get Chip Type */
584       if (PCI_DEV_REVISION(pAST->PciInfo) >= 0x20)
585           pAST->jChipType = AST2300;
586       else if (PCI_DEV_REVISION(pAST->PciInfo) >= 0x10)
587           GetChipType(pScrn);
588       else
589           pAST->jChipType = AST2000;
590
591       /* Get DRAM Info */
592       GetDRAMInfo(pScrn);
593       pAST->ulVRAMSize = GetVRAMInfo(pScrn);
594       pScrn->videoRam  = pAST->ulVRAMSize / 1024;
595   }
596
597   /* Map Framebuffer */
598   from = X_DEFAULT;
599   if (pAST->pEnt->device->videoRam) {
600      pScrn->videoRam = pAST->pEnt->device->videoRam;
601      from = X_CONFIG;
602   }
603
604   pAST->FbMapSize = pScrn->videoRam * 1024;
605
606#if 0
607   if (!ASTMapMem(pScrn)) {
608      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n");
609      return FALSE;
610   }
611#endif
612
613   pScrn->memPhysBase = (ULONG)pAST->FBPhysAddr;
614   pScrn->fbOffset = 0;
615
616   /* Do DDC
617    * should be done after xf86CollectOptions
618    */
619   pScrn->monitor->DDC = ASTDoDDC(pScrn, pAST->pEnt->index);
620
621   /* Mode Valid */
622   clockRanges = xnfcalloc(sizeof(ClockRange), 1);
623   clockRanges->next = NULL;
624   clockRanges->minClock = 9500;
625   clockRanges->maxClock = GetMaxDCLK(pScrn) * 1000;
626   clockRanges->clockIndex = -1;
627   clockRanges->interlaceAllowed = FALSE;
628   clockRanges->doubleScanAllowed = FALSE;
629
630   /* Add for AST2100, ycchen@061807 */
631   if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180))
632   {
633       maxPitch  = 1920;
634       maxHeight = 1200;
635   }
636   else
637   {
638       maxPitch  = 1600;
639       maxHeight = 1200;
640   }
641
642   i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
643			 pScrn->display->modes, clockRanges,
644			 0, 320, maxPitch, 8 * pScrn->bitsPerPixel,
645			 200, maxHeight,
646			 pScrn->display->virtualX, pScrn->display->virtualY,
647			 pAST->FbMapSize, LOOKUP_BEST_REFRESH);
648
649   /* fixed some monitors can't get propery validate modes using estimated ratio modes */
650   if (i < 2)		/* validate modes are too few */
651   {
652       i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
653			     pScrn->display->modes, clockRanges,
654			     0, 320, maxPitch, 8 * pScrn->bitsPerPixel,
655			     200, maxHeight,
656			     pAST->mon_h_active, pAST->mon_v_active,
657			     pAST->FbMapSize, LOOKUP_BEST_REFRESH);
658   }
659
660   if (i == -1) {
661      ASTFreeRec(pScrn);
662      return FALSE;
663   }
664
665   xf86PruneDriverModes(pScrn);
666
667   if (!i || !pScrn->modes) {
668      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
669      ASTFreeRec(pScrn);
670      return FALSE;
671   }
672
673   xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
674
675   pScrn->currentMode = pScrn->modes;
676
677   xf86PrintModes(pScrn);
678
679   xf86SetDpi(pScrn, 0, 0);
680
681   /* Accelaration Check */
682   pAST->noAccel = TRUE;
683   pAST->AccelInfoPtr = NULL;
684   pAST->pCMDQPtr = NULL;
685   pAST->CMDQInfo.ulCMDQSize = 0;
686#ifdef	Accel_2D
687   if (!xf86ReturnOptValBool(pAST->Options, OPTION_NOACCEL, FALSE))
688   {
689       if (!xf86LoadSubModule(pScrn, "xaa")) {
690	   ASTFreeRec(pScrn);
691	   return FALSE;
692       }
693
694       pAST->noAccel = FALSE;
695
696       pAST->MMIO2D = TRUE;
697#ifndef	MMIO_2D
698       if (!xf86ReturnOptValBool(pAST->Options, OPTION_MMIO2D, FALSE)) {
699           pAST->CMDQInfo.ulCMDQSize = DEFAULT_CMDQ_SIZE;
700           pAST->MMIO2D = FALSE;
701       }
702#endif
703
704       pAST->ENGCaps = ENG_CAP_ALL;
705       if (!xf86GetOptValInteger(pAST->Options, OPTION_ENG_CAPS, &pAST->ENGCaps)) {
706           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No ENG Capability options found\n");
707       }
708
709       pAST->DBGSelect = 0;
710       if (!xf86GetOptValInteger(pAST->Options, OPTION_DBG_SELECT, &pAST->DBGSelect)) {
711           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DBG Seleclt options found\n");
712       }
713   }
714#endif
715
716   /* HW Cursor Check */
717   pAST->noHWC = TRUE;
718   pAST->HWCInfoPtr = NULL;
719   pAST->pHWCPtr = NULL;
720#ifdef	HWC
721   if (!xf86ReturnOptValBool(pAST->Options, OPTION_SW_CURSOR, FALSE)) {
722      if (!xf86LoadSubModule(pScrn, "ramdac")) {
723	 ASTFreeRec(pScrn);
724	 return FALSE;
725      }
726
727      pAST->noHWC = FALSE;
728      pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM;
729      if (!xf86GetOptValInteger(pAST->Options, OPTION_HWC_NUM, &pAST->HWCInfo.HWC_NUM)) {
730          xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No HWC_NUM options found\n");
731      }
732
733   }
734#endif
735
736#ifndef XSERVER_LIBPCIACCESS
737   /*  We won't be using the VGA access after the probe */
738   xf86SetOperatingState(resVgaIo, pAST->pEnt->index, ResUnusedOpr);
739   xf86SetOperatingState(resVgaMem, pAST->pEnt->index, ResDisableOpr);
740#endif
741
742   return TRUE;
743}
744
745
746static Bool
747ASTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
748{
749   ScrnInfoPtr pScrn;
750   ASTRecPtr pAST;
751   vgaHWPtr hwp;
752   VisualPtr visual;
753
754   /* for FB Manager */
755   BoxRec FBMemBox;
756   int    AvailFBSize;
757
758   pScrn = xf86Screens[pScreen->myNum];
759   pAST = ASTPTR(pScrn);
760   hwp = VGAHWPTR(pScrn);
761
762   if (!ASTMapMem(pScrn)) {
763      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n");
764      return FALSE;
765   }
766
767/*   if (!pAST->noAccel) */
768   {
769       /* AvailFBSize = pAST->FbMapSize - pAST->CMDQInfo.ulCMDQSize; */
770       AvailFBSize = pAST->FbMapSize;
771
772       FBMemBox.x1 = 0;
773       FBMemBox.y1 = 0;
774       FBMemBox.x2 = pScrn->displayWidth;
775       FBMemBox.y2 = (AvailFBSize / (pScrn->displayWidth * ((pScrn->bitsPerPixel+1)/8))) - 1;
776
777       if (FBMemBox.y2 < 0)
778           FBMemBox.y2 = 32767;
779       if (FBMemBox.y2 < pScrn->virtualY)
780           return FALSE;
781
782       if (!xf86InitFBManager(pScreen, &FBMemBox)) {
783          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n");
784          return FALSE;
785       }
786
787   }
788
789   vgaHWGetIOBase(hwp);
790
791   vFillASTModeInfo (pScrn);
792
793   ASTSave(pScrn);
794   if (!ASTModeInit(pScrn, pScrn->currentMode)) {
795      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Mode Init Failed \n");
796      return FALSE;
797   }
798
799   ASTSaveScreen(pScreen, FALSE);
800   ASTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
801
802   miClearVisualTypes();
803
804   /* Re-implemented Direct Color support, -jens */
805   if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
806			 pScrn->rgbBits, pScrn->defaultVisual))
807      return FALSE;
808
809   if (!miSetPixmapDepths())
810   {
811       ASTSaveScreen(pScreen, SCREEN_SAVER_OFF);
812       return FALSE;
813   }
814
815   switch(pScrn->bitsPerPixel) {
816       case 8:
817       case 16:
818       case 32:
819           if (!fbScreenInit(pScreen, pAST->FBVirtualAddr + pScrn->fbOffset,
820  	                     pScrn->virtualX, pScrn->virtualY,
821		             pScrn->xDpi, pScrn->yDpi,
822		             pScrn->displayWidth, pScrn->bitsPerPixel))
823               return FALSE;
824           break;
825       default:
826           return FALSE;
827
828   }
829
830   if (pScrn->bitsPerPixel > 8) {
831      /* Fixup RGB ordering */
832      visual = pScreen->visuals + pScreen->numVisuals;
833      while (--visual >= pScreen->visuals) {
834	 if ((visual->class | DynamicClass) == DirectColor) {
835	    visual->offsetRed = pScrn->offset.red;
836	    visual->offsetGreen = pScrn->offset.green;
837	    visual->offsetBlue = pScrn->offset.blue;
838	    visual->redMask = pScrn->mask.red;
839	    visual->greenMask = pScrn->mask.green;
840	    visual->blueMask = pScrn->mask.blue;
841	 }
842      }
843   }
844
845   fbPictureInit(pScreen, 0, 0);
846
847   xf86SetBlackWhitePixels(pScreen);
848
849#ifdef Accel_2D
850   if (!pAST->noAccel)
851   {
852       if (!ASTAccelInit(pScreen)) {
853           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware acceleration initialization failed\n");
854           pAST->noAccel = TRUE;
855       }
856   }
857#endif /* end of Accel_2D */
858
859   miInitializeBackingStore(pScreen);
860   xf86SetBackingStore(pScreen);
861   xf86SetSilkenMouse(pScreen);
862
863   miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
864
865   if (!pAST->noHWC)
866   {
867       if (!ASTCursorInit(pScreen)) {
868           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware cursor initialization failed\n");
869           pAST->noHWC = TRUE;
870       }
871   }
872
873   if (!miCreateDefColormap(pScreen))
874      return FALSE;
875
876   if (pAST->jChipType != AST1180)
877   {
878       if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits,
879                               vASTLoadPalette, NULL,
880                               CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) {
881           return FALSE;
882       }
883   }
884
885   xf86DPMSInit(pScreen, ASTDisplayPowerManagementSet, 0);
886
887#ifdef AstVideo
888   if ( (pAST->jChipType == AST1180) || (pAST->jChipType == AST2300) )
889   {
890       xf86DrvMsg(pScrn->scrnIndex, X_INFO,"AST Initial Video()\n");
891       ASTInitVideo(pScreen);
892   }
893#endif
894
895   pScreen->SaveScreen = ASTSaveScreen;
896   pAST->CloseScreen = pScreen->CloseScreen;
897   pScreen->CloseScreen = ASTCloseScreen;
898
899   if (serverGeneration == 1)
900      xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
901
902   return TRUE;
903
904} /* ASTScreenInit */
905
906
907Bool
908ASTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
909{
910   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
911   ASTRecPtr pAST = ASTPTR(pScrn);
912
913   /* VideoMode validate */
914   if (mode->CrtcHDisplay > pScrn->displayWidth)
915       return FALSE;
916   if ((pAST->VideoModeInfo.ScreenPitch * mode->CrtcVDisplay) > pAST->ulVRAMSize)
917       return FALSE;
918
919   /* VideModeInfo Update */
920   pAST->VideoModeInfo.ScreenWidth  = mode->CrtcHDisplay;
921   pAST->VideoModeInfo.ScreenHeight = mode->CrtcVDisplay;
922   pAST->VideoModeInfo.ScreenPitch  = pScrn->displayWidth * ((pScrn->bitsPerPixel + 1) / 8) ;
923
924#ifdef	HWC
925   if (pAST->pHWCPtr) {
926       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
927       pAST->pHWCPtr = NULL;
928   }
929   ASTDisableHWC(pScrn);
930#endif
931
932#ifdef Accel_2D
933   if (pAST->pCMDQPtr) {
934       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
935       pAST->pCMDQPtr = NULL;
936   }
937   vDisable2D(pScrn, pAST);
938#endif
939
940   /* Fixed display abnormal on the of the screen if run xvidtune, ycchen@122909 */
941   /* ASTRestore(pScrn); */
942
943   return ASTModeInit(pScrn, mode);
944
945}
946
947void
948ASTAdjustFrame(int scrnIndex, int x, int y, int flags)
949{
950   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
951   ASTRecPtr   pAST  = ASTPTR(pScrn);
952   ULONG base;
953
954   base = y * pAST->VideoModeInfo.ScreenPitch + x * ((pAST->VideoModeInfo.bitsPerPixel + 1) / 8);
955   /* base = base >> 2; */			/* DW unit */
956
957   vSetStartAddressCRT1(pAST, base);
958
959}
960
961/* enter into X Server */
962static Bool
963ASTEnterVT(int scrnIndex, int flags)
964{
965   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
966   ASTRecPtr pAST = ASTPTR(pScrn);
967
968   /* Fixed suspend can't resume issue */
969   if (!bIsVGAEnabled(pScrn))
970   {
971       if (pAST->jChipType == AST1180)
972           bInitAST1180(pScrn);
973       else
974           InitVGA(pScrn, 1);
975       ASTRestore(pScrn);
976   }
977
978   if (!ASTModeInit(pScrn, pScrn->currentMode))
979      return FALSE;
980   ASTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
981
982   return TRUE;
983
984}
985
986/* leave X server */
987static void
988ASTLeaveVT(int scrnIndex, int flags)
989{
990
991   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
992   ASTRecPtr pAST = ASTPTR(pScrn);
993   vgaHWPtr hwp = VGAHWPTR(pScrn);
994
995#ifdef	HWC
996   if (pAST->pHWCPtr) {
997       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
998       pAST->pHWCPtr = NULL;
999   }
1000   ASTDisableHWC(pScrn);
1001#endif
1002
1003#ifdef Accel_2D
1004   if (pAST->pCMDQPtr) {
1005       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
1006       pAST->pCMDQPtr = NULL;
1007   }
1008   vDisable2D(pScrn, pAST);
1009#endif
1010
1011   ASTRestore(pScrn);
1012
1013   if (pAST->jChipType == AST1180)
1014       ASTBlankScreen(pScrn, 0);
1015
1016   vgaHWLock(hwp);
1017
1018}
1019
1020static void
1021ASTFreeScreen(int scrnIndex, int flags)
1022{
1023   ASTFreeRec(xf86Screens[scrnIndex]);
1024   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1025      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1026}
1027
1028static ModeStatus
1029ASTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1030{
1031
1032   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1033   ASTRecPtr   pAST  = ASTPTR(pScrn);
1034   ModeStatus Flags = MODE_NOMODE;
1035   UCHAR jReg;
1036   ULONG RequestBufferSize;
1037
1038   if (mode->Flags & V_INTERLACE) {
1039      if (verbose) {
1040	 xf86DrvMsg(scrnIndex, X_PROBED,
1041		    "Removing interlaced mode \"%s\"\n", mode->name);
1042      }
1043      return MODE_NO_INTERLACE;
1044   }
1045
1046   if ((mode->CrtcHDisplay > MAX_HResolution) || (mode->CrtcVDisplay > MAX_VResolution)) {
1047      if (verbose) {
1048	 xf86DrvMsg(scrnIndex, X_PROBED,
1049		    "Removing the mode \"%s\"\n", mode->name);
1050      }
1051      return Flags;
1052   }
1053
1054   /* Valid Framebuffer size */
1055   RequestBufferSize = mode->CrtcHDisplay * ((pScrn->bitsPerPixel + 1) / 8) * mode->CrtcVDisplay;
1056   if (RequestBufferSize > pAST->ulVRAMSize)
1057      return Flags;
1058
1059   /* Check BMC scratch for iKVM compatible */
1060   if (pAST->jChipType == AST2000)
1061       jReg = 0x80;
1062   else if (pAST->jChipType == AST1180)
1063       jReg = 0x01;
1064   else
1065   {
1066       GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg);
1067   }
1068
1069   if ( !(jReg & 0x80) || (jReg & 0x01) )
1070   {
1071      if ( (mode->CrtcHDisplay == 1680) && (mode->CrtcVDisplay == 1050) )
1072          return MODE_OK;
1073      if ( (mode->CrtcHDisplay == 1280) && (mode->CrtcVDisplay == 800) )
1074          return MODE_OK;
1075      if ( (mode->CrtcHDisplay == 1440) && (mode->CrtcVDisplay == 900) )
1076          return MODE_OK;
1077
1078      if ( (pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180) )
1079      {
1080          if ( (mode->CrtcHDisplay == 1920) && (mode->CrtcVDisplay == 1080) )
1081              return MODE_OK;
1082      }
1083   }
1084
1085   /* Add for AST2100, ycchen@061807 */
1086   if ( (pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180) )
1087   {
1088       if ( (mode->CrtcHDisplay == 1920) && (mode->CrtcVDisplay == 1200) )
1089           return MODE_OK;
1090   }
1091
1092   switch (mode->CrtcHDisplay)
1093   {
1094   case 640:
1095       if (mode->CrtcVDisplay == 480) Flags=MODE_OK;
1096       break;
1097   case 800:
1098       if (mode->CrtcVDisplay == 600) Flags=MODE_OK;
1099       break;
1100   case 1024:
1101       if (mode->CrtcVDisplay == 768) Flags=MODE_OK;
1102       break;
1103   case 1280:
1104       if (mode->CrtcVDisplay == 1024) Flags=MODE_OK;
1105       break;
1106   case 1600:
1107       if (mode->CrtcVDisplay == 1200) Flags=MODE_OK;
1108       break;
1109   default:
1110       return Flags;
1111   }
1112
1113   return Flags;
1114}
1115
1116/* Internal used modules */
1117/*
1118 * ASTGetRec and ASTFreeRec --
1119 *
1120 * Private data for the driver is stored in the screen structure.
1121 * These two functions create and destroy that private data.
1122 *
1123 */
1124static Bool
1125ASTGetRec(ScrnInfoPtr pScrn)
1126{
1127   if (pScrn->driverPrivate)
1128      return TRUE;
1129
1130   pScrn->driverPrivate = xnfcalloc(sizeof(ASTRec), 1);
1131   return TRUE;
1132}
1133
1134static void
1135ASTFreeRec(ScrnInfoPtr pScrn)
1136{
1137   if (!pScrn)
1138      return;
1139   if (!pScrn->driverPrivate)
1140      return;
1141   free(pScrn->driverPrivate);
1142   pScrn->driverPrivate = 0;
1143}
1144
1145static Bool
1146ASTSaveScreen(ScreenPtr pScreen, Bool unblack)
1147{
1148   /* replacement of vgaHWBlankScreen(pScrn, unblank) without seq reset */
1149   /* return vgaHWSaveScreen(pScreen, unblack); */
1150   ScrnInfoPtr pScrn = NULL;
1151
1152   if (pScreen != NULL)
1153      pScrn = xf86Screens[pScreen->myNum];
1154
1155   if ((pScrn != NULL) && pScrn->vtSema) {
1156     ASTBlankScreen(pScrn, unblack);
1157   }
1158   return (TRUE);
1159}
1160
1161static Bool
1162ASTCloseScreen(int scrnIndex, ScreenPtr pScreen)
1163{
1164   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1165   vgaHWPtr hwp = VGAHWPTR(pScrn);
1166   ASTRecPtr pAST = ASTPTR(pScrn);
1167
1168   if (pScrn->vtSema == TRUE)
1169   {
1170#ifdef	HWC
1171   if (pAST->pHWCPtr) {
1172       xf86FreeOffscreenLinear(pAST->pHWCPtr);		/* free HWC Cache */
1173       pAST->pHWCPtr = NULL;
1174   }
1175       ASTDisableHWC(pScrn);
1176#endif
1177
1178#ifdef Accel_2D
1179   if (pAST->pCMDQPtr) {
1180       xf86FreeOffscreenLinear(pAST->pCMDQPtr);		/* free CMDQ */
1181       pAST->pCMDQPtr = NULL;
1182   }
1183   vDisable2D(pScrn, pAST);
1184#endif
1185
1186      ASTRestore(pScrn);
1187
1188      if (pAST->jChipType == AST1180)
1189          ASTBlankScreen(pScrn, 0);
1190
1191      vgaHWLock(hwp);
1192   }
1193
1194   ASTUnmapMem(pScrn);
1195   vgaHWUnmapMem(pScrn);
1196
1197   if(pAST->AccelInfoPtr) {
1198       XAADestroyInfoRec(pAST->AccelInfoPtr);
1199       pAST->AccelInfoPtr = NULL;
1200   }
1201
1202   if(pAST->HWCInfoPtr) {
1203       xf86DestroyCursorInfoRec(pAST->HWCInfoPtr);
1204       pAST->HWCInfoPtr = NULL;
1205   }
1206
1207   pScrn->vtSema = FALSE;
1208   pScreen->CloseScreen = pAST->CloseScreen;
1209   return (*pScreen->CloseScreen) (scrnIndex, pScreen);
1210}
1211
1212static void
1213ASTSave(ScrnInfoPtr pScrn)
1214{
1215   ASTRecPtr pAST;
1216   vgaRegPtr vgaReg;
1217   ASTRegPtr astReg;
1218   int i, icount=0;
1219   ULONG ulData;
1220
1221   pAST = ASTPTR(pScrn);
1222   vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1223   astReg = &pAST->SavedReg;
1224
1225   /* do save */
1226   if (xf86IsPrimaryPci(pAST->PciInfo)) {
1227       vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
1228   }
1229   else {
1230       vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
1231   }
1232
1233   /* Ext. Save */
1234   if (pAST->jChipType == AST1180)
1235   {
1236       for (i=0; i<12; i++)
1237       {
1238           ReadAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL+i*4, ulData);
1239           astReg->GFX[i] = ulData;
1240       }
1241   }
1242   else
1243   {
1244       vASTOpenKey(pScrn);
1245
1246       /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */
1247       for (i=0x81; i<=0xB6; i++)
1248           GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1249       for (i=0xBC; i<=0xC1; i++)
1250           GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1251       GetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]);
1252   }
1253
1254}
1255
1256static void
1257ASTRestore(ScrnInfoPtr pScrn)
1258{
1259   ASTRecPtr pAST;
1260   vgaRegPtr vgaReg;
1261   ASTRegPtr astReg;
1262   int i, icount=0;
1263   ULONG ulData;
1264
1265   pAST = ASTPTR(pScrn);
1266   vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1267   astReg = &pAST->SavedReg;
1268
1269   /* do restore */
1270   vgaHWProtect(pScrn, TRUE);
1271   if (xf86IsPrimaryPci(pAST->PciInfo))
1272       vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1273   else
1274       vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
1275   vgaHWProtect(pScrn, FALSE);
1276
1277   if (pAST->jChipType == AST1180)
1278   {
1279       for (i=0; i<12; i++)
1280       {
1281           ulData = astReg->GFX[i];
1282           WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL+i*4, ulData);
1283       }
1284   }
1285   else
1286   {
1287      /* Ext. restore */
1288      vASTOpenKey(pScrn);
1289
1290      /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */
1291      for (i=0x81; i<=0xB6; i++)
1292          SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1293      for (i=0xBC; i<=0xC1; i++)
1294          SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]);
1295      SetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]);
1296   }
1297
1298}
1299
1300static void
1301ASTProbeDDC(ScrnInfoPtr pScrn, int index)
1302{
1303   vbeInfoPtr pVbe;
1304   ASTRecPtr pAST = ASTPTR(pScrn);
1305   unsigned char DDC_data[128];
1306   Bool Flags;
1307
1308   if ( (pAST->jChipType == AST1180) || (!xf86IsPrimaryPci(pAST->PciInfo)) )
1309   {
1310       if (pAST->jChipType == AST1180)
1311           Flags = GetVGA2EDID(pScrn, DDC_data);
1312       else
1313           Flags = GetVGAEDID(pScrn, DDC_data);
1314
1315       if (Flags)
1316       {
1317           ConfiguredMonitor = xf86InterpretEDID(pScrn->scrnIndex, DDC_data);
1318       }
1319       else
1320           xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[ASTProbeDDC] Can't Get EDID Properly \n");
1321   }
1322   else
1323   {
1324       if (xf86LoadSubModule(pScrn, "vbe")) {
1325          pVbe = VBEInit(NULL, index);
1326          ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1327          vbeFree(pVbe);
1328       }
1329   }
1330}
1331
1332#define SkipDT	0x00
1333#define DT1	0x01
1334#define DT2 	0x02
1335
1336static xf86MonPtr
1337ASTDoDDC(ScrnInfoPtr pScrn, int index)
1338{
1339   vbeInfoPtr pVbe;
1340   xf86MonPtr MonInfo = NULL, MonInfo1 = NULL, MonInfo2 = NULL;
1341   ASTRecPtr pAST = ASTPTR(pScrn);
1342   unsigned long i, j, k;
1343   unsigned char DDC_data[128];
1344   struct monitor_ranges ranges, ranges1, ranges2;
1345   int DTSelect, dclock1=0, h_active1=0, v_active1=0, dclock2=0, h_active2=0, v_active2=0;
1346   struct std_timings stdtiming, *stdtiming1, *stdtiming2;
1347   Bool Flags;
1348
1349   /* Honour Option "noDDC" */
1350   if (xf86ReturnOptValBool(pAST->Options, OPTION_NO_DDC, FALSE)) {
1351      return MonInfo;
1352   }
1353
1354   if ( (pAST->jChipType == AST1180) || (!xf86IsPrimaryPci(pAST->PciInfo)) )
1355   {
1356
1357        if (pAST->jChipType == AST1180)
1358            Flags = GetVGA2EDID(pScrn, DDC_data);
1359        else
1360            Flags = GetVGAEDID(pScrn, DDC_data);
1361
1362        if (Flags)
1363        {
1364            MonInfo = xf86InterpretEDID(pScrn->scrnIndex, DDC_data);
1365            xf86PrintEDID(MonInfo);
1366            xf86SetDDCproperties(pScrn, MonInfo);
1367        }
1368        else
1369            xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[ASTDoDDC] Can't Get EDID Properly \n");
1370
1371   }
1372   else
1373   {
1374
1375       if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
1376          MonInfo1 = vbeDoEDID(pVbe, NULL);
1377          MonInfo = MonInfo1;
1378
1379          /* For VGA2 CLONE Support, ycchen@012508 */
1380          if ((xf86ReturnOptValBool(pAST->Options, OPTION_VGA2_CLONE, FALSE)) || pAST->VGA2Clone) {
1381              if (GetVGA2EDID(pScrn, DDC_data) == TRUE) {
1382                  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Get VGA2 EDID Correctly!! \n");
1383                  MonInfo2 = xf86InterpretEDID(pScrn->scrnIndex, DDC_data);
1384                  if (MonInfo1 == NULL)	/* No DDC1 EDID */
1385                      MonInfo = MonInfo2;
1386                  else {			/* Check with VGA1 & VGA2 EDID */
1387                      /* Update establishment timing */
1388                      MonInfo->timings1.t1 = MonInfo1->timings1.t1 & MonInfo2->timings1.t1;
1389                      MonInfo->timings1.t2 = MonInfo1->timings1.t2 & MonInfo2->timings1.t2;
1390                      MonInfo->timings1.t_manu = MonInfo1->timings1.t_manu & MonInfo2->timings1.t_manu;
1391
1392                      /* Update Std. Timing */
1393                      for (i=0; i<8; i++) {
1394	                  stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0;
1395                          for (j=0; j<8; j++) {
1396                              if ((MonInfo1->timings2[i].hsize == MonInfo2->timings2[j].hsize) && \
1397                                  (MonInfo1->timings2[i].vsize == MonInfo2->timings2[j].vsize) && \
1398                                  (MonInfo1->timings2[i].refresh == MonInfo2->timings2[j].refresh)) {
1399                                   stdtiming = MonInfo1->timings2[i];
1400                                   break;
1401                              }
1402                          }
1403
1404                          MonInfo->timings2[i] = stdtiming;
1405                      } /* Std. Timing */
1406
1407                      /* Get Detailed Timing */
1408                      for (i=0;i<4;i++) {
1409                        if (MonInfo1->det_mon[i].type == 0xFD)
1410                            ranges1 = MonInfo1->det_mon[i].section.ranges;
1411                        else if (MonInfo1->det_mon[i].type == 0xFA)
1412                            stdtiming1 = MonInfo1->det_mon[i].section.std_t;
1413                        else if (MonInfo1->det_mon[i].type == 0x00) {
1414                            if (MonInfo1->det_mon[i].section.d_timings.clock > dclock1)
1415                                dclock1 = MonInfo1->det_mon[i].section.d_timings.clock;
1416                            if (MonInfo1->det_mon[i].section.d_timings.h_active > h_active1)
1417                                h_active1 = MonInfo1->det_mon[i].section.d_timings.h_active;
1418                            if (MonInfo1->det_mon[i].section.d_timings.v_active > v_active1)
1419                                v_active1 = MonInfo1->det_mon[i].section.d_timings.v_active;
1420                        }
1421                        if (MonInfo2->det_mon[i].type == 0xFD)
1422                            ranges2 = MonInfo2->det_mon[i].section.ranges;
1423                        else if (MonInfo1->det_mon[i].type == 0xFA)
1424                            stdtiming2 = MonInfo2->det_mon[i].section.std_t;
1425                        else if (MonInfo2->det_mon[i].type == 0x00) {
1426                             if (MonInfo2->det_mon[i].section.d_timings.clock > dclock2)
1427                                dclock2 = MonInfo2->det_mon[i].section.d_timings.clock;
1428                             if (MonInfo2->det_mon[i].section.d_timings.h_active > h_active2)
1429                                h_active2 = MonInfo2->det_mon[i].section.d_timings.h_active;
1430                             if (MonInfo2->det_mon[i].section.d_timings.v_active > v_active2)
1431                                v_active2 = MonInfo2->det_mon[i].section.d_timings.v_active;
1432                        }
1433                      } /* Get Detailed Timing */
1434
1435                      /* Chk Detailed Timing */
1436                      if ((dclock1 >= dclock2) && (h_active1 >= h_active2) && (v_active1 >= v_active2))
1437                          DTSelect = DT2;
1438                      else if ((dclock2 >= dclock1) && (h_active2 >= h_active1) && (v_active2 >= v_active1))
1439                          DTSelect = DT1;
1440                      else
1441                          DTSelect = SkipDT;
1442
1443                      /* Chk Monitor Descriptor */
1444                      ranges = ranges1;
1445                      ranges.min_h = ranges1.min_h > ranges2.min_h ? ranges1.min_h:ranges2.min_h;
1446                      ranges.min_v = ranges1.min_v > ranges2.min_v ? ranges1.min_v:ranges2.min_v;
1447                      ranges.max_h = ranges1.max_h < ranges2.max_h ? ranges1.max_h:ranges2.max_h;
1448                      ranges.max_v = ranges1.max_v < ranges2.max_v ? ranges1.max_v:ranges2.max_v;
1449                      ranges.max_clock = ranges1.max_clock < ranges2.max_clock ? ranges1.max_clock:ranges2.max_clock;
1450
1451                      /* Update Detailed Timing */
1452                      for (i=0; i<4; i++)
1453                      {
1454                          if (MonInfo->det_mon[i].type == 0xFD) {
1455                              MonInfo->det_mon[i].section.ranges = ranges;
1456                          }
1457                          else if (MonInfo->det_mon[i].type == 0xFA) {
1458                             for (j=0; j<5; j++) {
1459            	                 stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0;
1460                                 for (k=0; k<5; k++) {
1461                                     if ((stdtiming1[j].hsize == stdtiming2[k].hsize) && \
1462                                         (stdtiming1[j].vsize == stdtiming2[k].vsize) && \
1463                                         (stdtiming1[j].refresh == stdtiming2[k].refresh)) {
1464                                          stdtiming = stdtiming1[j];
1465                                          break;
1466                                     }
1467                                 }
1468                                 stdtiming1[j] = stdtiming;
1469                             } /* Std. Timing */
1470                          } /* FA */
1471                          else if (MonInfo->det_mon[i].type == 0x00) {
1472                              if (DTSelect == DT2)
1473                                  MonInfo->det_mon[i] = MonInfo2->det_mon[i];
1474                              else if (DTSelect == DT1)
1475                                  MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1476                              else /* SkipDT */
1477                              {   /* use 1024x768 as default */
1478                                  MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1479                                  MonInfo->det_mon[i].section.d_timings.clock = 65000000;
1480                                  MonInfo->det_mon[i].section.d_timings.h_active = 1024;
1481                                  MonInfo->det_mon[i].section.d_timings.h_blanking = 320;
1482                                  MonInfo->det_mon[i].section.d_timings.v_active = 768;
1483                                  MonInfo->det_mon[i].section.d_timings.v_blanking = 38;
1484                                  MonInfo->det_mon[i].section.d_timings.h_sync_off = 24;
1485                                  MonInfo->det_mon[i].section.d_timings.h_sync_width = 136;
1486                                  MonInfo->det_mon[i].section.d_timings.v_sync_off = 3;
1487                                  MonInfo->det_mon[i].section.d_timings.v_sync_width = 6;
1488                              }
1489                          } /* 00 */
1490                          else { /* use Monitor 1 as default */
1491                              MonInfo->det_mon[i] = MonInfo1->det_mon[i];
1492                          }
1493
1494                      } /* Update Detailed Timing */
1495
1496                      /* set feature size */
1497                      if (DTSelect == DT2)  {
1498                          MonInfo->features.hsize = MonInfo2->features.hsize;
1499                          MonInfo->features.vsize = MonInfo2->features.vsize;
1500                      }
1501                      else if (DTSelect == DT1)  {
1502                          MonInfo->features.hsize = MonInfo1->features.hsize;
1503                          MonInfo->features.vsize = MonInfo1->features.vsize;
1504                      }
1505                      else	/* Skip DT */
1506                      {   /* use 1024x768 as default */
1507                          MonInfo->features.hsize = 0x20;
1508                          MonInfo->features.vsize = 0x18;
1509                      }
1510
1511                  } /* Check with VGA1 & VGA2 EDID */
1512
1513              } /* GetVGA2EDID */
1514              else {
1515                  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Can't Get VGA2 EDID Correctly!! \n");
1516              }
1517
1518          }
1519
1520          /* save MonInfo to Private */
1521          pAST->mon_h_active = MonInfo->det_mon[0].section.d_timings.h_active;
1522          pAST->mon_v_active = MonInfo->det_mon[0].section.d_timings.v_active;
1523
1524          xf86PrintEDID(MonInfo);
1525          xf86SetDDCproperties(pScrn, MonInfo);
1526          vbeFree(pVbe);
1527       } else {
1528          xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1529		     "this driver cannot do DDC without VBE\n");
1530       }
1531
1532   } /* AST1180 */
1533
1534   return MonInfo;
1535}
1536
1537static void
1538vFillASTModeInfo (ScrnInfoPtr pScrn)
1539{
1540    ASTRecPtr pAST;
1541
1542    pAST = ASTPTR(pScrn);
1543
1544    pAST->VideoModeInfo.ScreenWidth = pScrn->virtualX;
1545    pAST->VideoModeInfo.ScreenHeight = pScrn->virtualY;
1546    pAST->VideoModeInfo.bitsPerPixel = pScrn->bitsPerPixel;
1547    /* Fixed screen pitch incorrect in some specific monitor, ycchen@071707 */
1548    pAST->VideoModeInfo.ScreenPitch = pScrn->displayWidth * ((pScrn->bitsPerPixel + 1) / 8) ;
1549
1550}
1551
1552static Bool
1553ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1554{
1555    vgaHWPtr hwp;
1556    ASTRecPtr pAST;
1557
1558    hwp = VGAHWPTR(pScrn);
1559    pAST = ASTPTR(pScrn);
1560
1561    vgaHWUnlock(hwp);
1562
1563    if (!vgaHWInit(pScrn, mode))
1564      return FALSE;
1565
1566    pScrn->vtSema = TRUE;
1567    pAST->ModePtr = mode;
1568
1569    if (!ASTSetMode(pScrn, mode))
1570      return FALSE;
1571
1572    vgaHWProtect(pScrn, FALSE);
1573
1574    return TRUE;
1575}
1576
1577#ifdef AstVideo
1578/*
1579 * Video Part by ic_yang
1580 */
1581#include "fourcc.h"
1582
1583#define NUM_ATTRIBUTES  	8
1584#define NUM_IMAGES 		8
1585#define NUM_FORMATS     	3
1586
1587#define IMAGE_MIN_WIDTH         32
1588#define IMAGE_MIN_HEIGHT        24
1589#define IMAGE_MAX_WIDTH         1920
1590#define IMAGE_MAX_HEIGHT        1080
1591
1592#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
1593
1594static XF86ImageRec ASTImages[NUM_IMAGES] =
1595{
1596    XVIMAGE_YUY2, /* If order is changed, ASTOffscreenImages must be adapted */
1597};
1598
1599static XF86VideoFormatRec ASTFormats[NUM_FORMATS] =
1600{
1601   { 8, PseudoColor},
1602   {16, TrueColor},
1603   {24, TrueColor}
1604};
1605
1606/* client libraries expect an encoding */
1607static XF86VideoEncodingRec DummyEncoding =
1608{
1609   0,
1610   "XV_IMAGE",
1611   0, 0,                /* Will be filled in */
1612   {1, 1}
1613};
1614
1615static char astxvcolorkey[] 				= "XV_COLORKEY";
1616static char astxvbrightness[] 				= "XV_BRIGHTNESS";
1617static char astxvcontrast[] 				= "XV_CONTRAST";
1618static char astxvsaturation[] 				= "XV_SATURATION";
1619static char astxvhue[] 				        = "XV_HUE";
1620static char astxvgammared[] 				= "XV_GAMMA_RED";
1621static char astxvgammagreen[] 				= "XV_GAMMA_GREEN";
1622static char astxvgammablue[] 				= "XV_GAMMA_BLUE";
1623
1624static XF86AttributeRec ASTAttributes[NUM_ATTRIBUTES] =
1625{
1626   {XvSettable | XvGettable, 0, (1 << 24) - 1, astxvcolorkey},
1627   {XvSettable | XvGettable, -128, 127, astxvbrightness},
1628   {XvSettable | XvGettable, 0, 255, astxvcontrast},
1629   {XvSettable | XvGettable, -180, 180, astxvsaturation},
1630   {XvSettable | XvGettable, -180, 180, astxvhue},
1631   {XvSettable | XvGettable, 100, 10000, astxvgammared},
1632   {XvSettable | XvGettable, 100, 10000, astxvgammagreen},
1633   {XvSettable | XvGettable, 100, 10000, astxvgammablue},
1634};
1635
1636static void ASTStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
1637{
1638    ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data;
1639    ASTPtr pAST = ASTPTR(pScrn);
1640
1641    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1642
1643    if(exit)
1644    {
1645        if(pPriv->fbAreaPtr)
1646        {
1647            xf86FreeOffscreenArea(pPriv->fbAreaPtr);
1648            pPriv->fbAreaPtr = NULL;
1649            pPriv->fbSize = 0;
1650        }
1651        /* clear all flag */
1652        pPriv->videoStatus = 0;
1653    }
1654    else
1655    {
1656#if 0
1657        if(pPriv->videoStatus & CLIENT_VIDEO_ON)
1658        {
1659            pPriv->videoStatus |= OFF_TIMER;
1660
1661        }
1662#endif
1663    }
1664}
1665
1666static int ASTSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data)
1667{
1668    ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data;
1669    ASTPtr pAST = ASTPTR(pScrn);
1670
1671    xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTSetPortAttribute(),attribute=%x\n", attribute);
1672
1673    if (attribute == pAST->xvBrightness)
1674    {
1675        if((value < -128) || (value > 127))
1676         return BadValue;
1677
1678        pPriv->brightness = value;
1679    }
1680    else if (attribute == pAST->xvContrast)
1681    {
1682        if ((value < 0) || (value > 255))
1683         return BadValue;
1684
1685        pPriv->contrast = value;
1686    }
1687    else if (attribute == pAST->xvSaturation)
1688    {
1689        if ((value < -180) || (value > 180))
1690         return BadValue;
1691
1692        pPriv->saturation = value;
1693    }
1694    else if (attribute == pAST->xvHue)
1695    {
1696        if ((value < -180) || (value > 180))
1697         return BadValue;
1698
1699        pPriv->hue = value;
1700    }
1701    else if (attribute == pAST->xvColorKey)
1702    {
1703          pPriv->colorKey = value;
1704          REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1705    }
1706    else if(attribute == pAST->xvGammaRed)
1707    {
1708        if((value < 100) || (value > 10000))
1709            return BadValue;
1710        pPriv->gammaR = value;
1711    }
1712    else if(attribute == pAST->xvGammaGreen)
1713    {
1714        if((value < 100) || (value > 10000))
1715            return BadValue;
1716        pPriv->gammaG = value;
1717    }
1718    else if(attribute == pAST->xvGammaBlue)
1719    {
1720        if((value < 100) || (value > 10000))
1721            return BadValue;
1722        pPriv->gammaB = value;
1723    }
1724    else
1725    {
1726        return BadMatch;
1727    }
1728
1729    return Success;
1730}
1731
1732static int ASTGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data)
1733{
1734    ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data;
1735    ASTPtr pAST = ASTPTR(pScrn);
1736
1737    xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTGetPortAttribute(),attribute=%x\n", attribute);
1738
1739    if (attribute == pAST->xvBrightness)
1740    {
1741        *value = pPriv->brightness;
1742    }
1743    else if (attribute == pAST->xvContrast)
1744    {
1745        *value = pPriv->contrast;
1746    }
1747    else if (attribute == pAST->xvSaturation)
1748    {
1749        *value = pPriv->saturation;
1750    }
1751    else if (attribute == pAST->xvHue)
1752    {
1753        *value = pPriv->hue;
1754    }
1755    else if(attribute == pAST->xvGammaRed)
1756    {
1757        *value = pPriv->gammaR;
1758
1759    }
1760    else if(attribute == pAST->xvGammaGreen)
1761    {
1762        *value = pPriv->gammaG;
1763    }
1764    else if(attribute == pAST->xvGammaBlue)
1765    {
1766        *value = pPriv->gammaB;
1767    }
1768    else if (attribute == pAST->xvColorKey)
1769    {
1770        *value = pPriv->colorKey;
1771    }
1772    else
1773        return BadMatch;
1774
1775    return Success;
1776}
1777
1778static void ASTQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
1779                                short vid_w, short vid_h,
1780                                short drw_w, short drw_h,
1781                                unsigned int *p_w, unsigned int *p_h,
1782                                pointer data)
1783{
1784    *p_w = drw_w;
1785    *p_h = drw_h;
1786    xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTQueryBestSize()\n");
1787  /* TODO: report the HW limitation */
1788}
1789
1790static int ASTQueryImageAttributes(ScrnInfoPtr pScrn, int id,
1791                                    unsigned short *w, unsigned short *h,
1792                                    int *pitches, int *offsets)
1793{
1794    int pitchY, pitchUV;
1795    int size, sizeY, sizeUV;
1796
1797    xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTQueryImageAttributes()\n");
1798
1799    if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH;
1800    if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT;
1801
1802    switch(id) {
1803    case PIXEL_FMT_YV12:
1804        *w = (*w + 7) & ~7;
1805        *h = (*h + 1) & ~1;
1806        pitchY = *w;
1807        pitchUV = *w >> 1;
1808        if(pitches) {
1809          pitches[0] = pitchY;
1810          pitches[1] = pitches[2] = pitchUV;
1811        }
1812        sizeY = pitchY * (*h);
1813        sizeUV = pitchUV * ((*h) >> 1);
1814        if(offsets) {
1815          offsets[0] = 0;
1816          offsets[1] = sizeY;
1817          offsets[2] = sizeY + sizeUV;
1818        }
1819        size = sizeY + (sizeUV << 1);
1820        break;
1821    case PIXEL_FMT_NV12:
1822    case PIXEL_FMT_NV21:
1823        *w = (*w + 7) & ~7;
1824        *h = (*h + 1) & ~1;
1825		pitchY = *w;
1826    	pitchUV = *w;
1827    	if(pitches) {
1828      	    pitches[0] = pitchY;
1829            pitches[1] = pitchUV;
1830        }
1831    	sizeY = pitchY * (*h);
1832    	sizeUV = pitchUV * ((*h) >> 1);
1833    	if(offsets) {
1834          offsets[0] = 0;
1835          offsets[1] = sizeY;
1836        }
1837        size = sizeY + (sizeUV << 1);
1838        break;
1839    case PIXEL_FMT_YUY2:
1840    case PIXEL_FMT_UYVY:
1841    case PIXEL_FMT_YVYU:
1842    case PIXEL_FMT_RGB6:
1843    case PIXEL_FMT_RGB5:
1844    default:
1845        *w = (*w + 1) & ~1;
1846        pitchY = *w << 1;
1847        if(pitches) pitches[0] = pitchY;
1848        if(offsets) offsets[0] = 0;
1849        size = pitchY * (*h);
1850        break;
1851    }
1852
1853    return size;
1854}
1855
1856extern void ASTDisplayVideo(ScrnInfoPtr pScrn, ASTPortPrivPtr pPriv, RegionPtr clipBoxes, int id);
1857
1858static int ASTPutImage(ScrnInfoPtr pScrn,
1859                          short src_x, short src_y,
1860                          short drw_x, short drw_y,
1861                          short src_w, short src_h,
1862                          short drw_w, short drw_h,
1863                          int id, unsigned char* buf,
1864                          short width, short height,
1865                          Bool sync,
1866                          RegionPtr clipBoxes, pointer data,
1867			  DrawablePtr pDraw
1868)
1869{
1870    ASTPtr pAST = ASTPTR(pScrn);
1871    ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data;
1872    int i;
1873    int totalSize=0;
1874
1875    xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTPutImage()\n");
1876    /*   int depth = pAST->CurrentLayout.bitsPerPixel >> 3; */
1877
1878    pPriv->drw_x = drw_x;
1879    pPriv->drw_y = drw_y;
1880    pPriv->drw_w = drw_w;
1881    pPriv->drw_h = drw_h;
1882    pPriv->src_x = src_x;
1883    pPriv->src_y = src_y;
1884    pPriv->src_w = src_w;
1885    pPriv->src_h = src_h;
1886    pPriv->id = id;
1887    pPriv->height = height;
1888
1889    switch(id)
1890    {
1891    case PIXEL_FMT_YV12:
1892    case PIXEL_FMT_NV12:
1893    case PIXEL_FMT_NV21:
1894        pPriv->srcPitch = (width + 7) & ~7;
1895        totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */
1896    break;
1897    case PIXEL_FMT_YUY2:
1898    case PIXEL_FMT_UYVY:
1899    case PIXEL_FMT_YVYU:
1900    case PIXEL_FMT_RGB6:
1901    case PIXEL_FMT_RGB5:
1902    default:
1903        pPriv->srcPitch = ((width << 1) + 3) & ~3;	/* Verified */
1904        totalSize = pPriv->srcPitch * height;
1905    }
1906
1907    totalSize += 15;
1908    totalSize &= ~15;
1909    /* allocate memory */
1910
1911    if(totalSize == pPriv->fbSize)
1912    {
1913        ;
1914    }
1915    else
1916    {
1917        int lines, pitch, depth;
1918        BoxPtr pBox = NULL;
1919
1920        pPriv->fbSize = totalSize;
1921
1922        if(pPriv->fbAreaPtr)
1923        {
1924             xf86FreeOffscreenArea(pPriv->fbAreaPtr);
1925        }
1926
1927        depth = (pScrn->bitsPerPixel + 7 ) / 8;
1928        pitch = pScrn->displayWidth * depth;
1929        lines = ((totalSize * 2) / pitch) + 1;
1930        xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTPutImagelines=%x, pitch=%x, displayWidth=%x\n", lines, pitch, pScrn->displayWidth);
1931
1932
1933        pPriv->fbAreaPtr = xf86AllocateOffscreenArea(pScrn->pScreen,
1934                                 pScrn->displayWidth,
1935                                lines, 0, NULL, NULL, NULL);
1936
1937        if(!pPriv->fbAreaPtr)
1938        {
1939            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Allocate video memory fails\n");
1940            return BadAlloc;
1941        }
1942
1943        pBox = &(pPriv->fbAreaPtr->box);
1944        pPriv->bufAddr[0] = (pBox->y1 * pitch) + (pBox->x1 * depth);
1945        pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize;
1946        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Put Image, pPriv->bufAddr[0]=0x%08X\n", pPriv->bufAddr[0]);
1947
1948    }
1949
1950    /* copy data */
1951    if(totalSize < 16)
1952    {
1953      #ifdef NewPath
1954        memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
1955      #else /* NewPath */
1956        switch(id)
1957        {
1958        case PIXEL_FMT_YUY2:
1959        case PIXEL_FMT_UYVY:
1960        case PIXEL_FMT_YVYU:
1961        {
1962             BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]);
1963             for(i=0; i<height; i++)
1964                  memcpy( Base + i * pPriv->srcPitch, buf + i*width*2, width*2);
1965             break;
1966        }
1967        default:
1968            memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
1969            break;
1970        } /* switch */
1971      #endif /* NewPath */
1972    }
1973    else
1974    {
1975        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Put Image, copy buf\n");
1976
1977      #ifdef NewPath
1978       	memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
1979      #else     /* NewPath */
1980        switch(id)
1981        {
1982        case PIXEL_FMT_YUY2:
1983        case PIXEL_FMT_UYVY:
1984        case PIXEL_FMT_YVYU:
1985        {
1986            BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]);
1987            for(i=0; i<height; i++)
1988                  memcpy( Base + i * pPriv->srcPitch, buf + i*width*2, width*2);
1989
1990            /*for(i=0; i<height; i++)
1991                for(j=0; j<width*2; j++)
1992                    *(Base+i*pPriv->srcPitch+j) = *(buf + width*i + j);*/
1993            break;
1994        }
1995        default:
1996        {    BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]);
1997            int j;
1998            for(i=0; i<height; i++)
1999                for(j=0; j<width; j++)
2000                   *(Base + width*i + j) = *(buf + width * i + j);
2001        break;
2002        }
2003        } /* end of switch */
2004      #endif    /* NewPath */
2005    }
2006
2007    ASTDisplayVideo(pScrn, pPriv, clipBoxes, id);
2008
2009    /* update cliplist
2010    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))
2011    {
2012        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
2013    }
2014    else
2015    {
2016        xf86XVFillKeyHelper(pScrn->pScreen, 0xFFFFFFFF, clipBoxes);
2017    }
2018    */
2019    pPriv->currentBuf ^= 1;
2020
2021    return Success;
2022}
2023
2024static XF86VideoAdaptorPtr ASTSetupImageVideo(ScreenPtr pScreen)
2025{
2026    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2027    ASTPtr pAST = ASTPTR(pScrn);
2028    XF86VideoAdaptorPtr adapt;
2029    ASTPortPrivPtr pPriv;
2030
2031
2032    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
2033                            sizeof(DevUnion) +
2034                            sizeof(ASTPortPrivRec))))
2035        return NULL;
2036
2037    adapt->type = XvWindowMask | XvInputMask | XvImageMask | XvVideoMask;
2038    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
2039    adapt->name = "AST Video";
2040
2041    adapt->nEncodings = 1;
2042    adapt->pEncodings = &DummyEncoding;
2043
2044    adapt->nFormats = NUM_FORMATS;
2045    adapt->pFormats = ASTFormats;
2046    adapt->nPorts = 1;
2047    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
2048
2049    pPriv = (ASTPortPrivPtr)(&adapt->pPortPrivates[1]);
2050
2051    adapt->pPortPrivates->ptr = (pointer)(pPriv);
2052    adapt->pAttributes = ASTAttributes;
2053    adapt->nAttributes = NUM_ATTRIBUTES;
2054	adapt->nImages = NUM_IMAGES;
2055    adapt->pImages = ASTImages;
2056
2057    adapt->PutVideo = NULL;
2058
2059    adapt->PutStill = NULL;
2060    adapt->GetVideo = NULL;
2061    adapt->GetStill = NULL;
2062    adapt->StopVideo = ASTStopVideo;
2063    adapt->SetPortAttribute = ASTSetPortAttribute;
2064    adapt->GetPortAttribute = ASTGetPortAttribute;
2065    adapt->QueryBestSize = ASTQueryBestSize;
2066    adapt->PutImage = ASTPutImage;
2067    adapt->QueryImageAttributes = ASTQueryImageAttributes;
2068
2069
2070    pPriv->currentBuf   = 0;
2071    pPriv->linear       = NULL;
2072    pPriv->fbAreaPtr    = NULL;
2073    pPriv->fbSize = 0;
2074	pPriv->videoStatus  = 0;
2075
2076    pPriv->colorKey     = 0x000101fe;
2077    pPriv->brightness   = 0;
2078    pPriv->contrast     = 128;
2079    pPriv->saturation   = 0;
2080    pPriv->hue          = 0;
2081
2082    /* gotta uninit this someplace */
2083#if defined(REGION_NULL)
2084    REGION_NULL(pScreen, &pPriv->clip);
2085#else
2086    REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
2087#endif
2088
2089	pAST->adaptor = adapt;
2090
2091	pAST->xvBrightness = MAKE_ATOM(astxvbrightness);
2092	pAST->xvContrast   = MAKE_ATOM(astxvcontrast);
2093	pAST->xvColorKey   = MAKE_ATOM(astxvcolorkey);
2094	pAST->xvSaturation = MAKE_ATOM(astxvsaturation);
2095	pAST->xvHue 	   = MAKE_ATOM(astxvhue);
2096	pAST->xvGammaRed   = MAKE_ATOM(astxvgammared);
2097    pAST->xvGammaGreen = MAKE_ATOM(astxvgammagreen);
2098    pAST->xvGammaBlue  = MAKE_ATOM(astxvgammablue);
2099
2100    return adapt;
2101}
2102
2103void ASTInitVideo(ScreenPtr pScreen)
2104{
2105    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2106    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
2107    XF86VideoAdaptorPtr ASTAdaptor = NULL;
2108    int num_adaptors;
2109
2110    ASTAdaptor = ASTSetupImageVideo(pScreen);
2111
2112    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
2113
2114    if(ASTAdaptor)
2115    {
2116        if(!num_adaptors)
2117        {
2118            num_adaptors = 1;
2119            adaptors = &ASTAdaptor;
2120        }
2121        else
2122        {
2123            newAdaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
2124            if(newAdaptors)
2125            {
2126                memcpy(newAdaptors, adaptors, num_adaptors *
2127                                        sizeof(XF86VideoAdaptorPtr));
2128                newAdaptors[num_adaptors] = ASTAdaptor;
2129                adaptors = newAdaptors;
2130                num_adaptors++;
2131            }
2132        }
2133    }
2134
2135    if(num_adaptors)
2136        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
2137
2138    if(newAdaptors)
2139        free(newAdaptors);
2140
2141}
2142#endif /* AstVideo */
2143