/* * Copyright (c) 2005 ASPEED Technology Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the authors not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. The authors makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H #include #endif #include "xf86.h" #include "xf86_OSproc.h" #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 #include "xf86Resources.h" #include "xf86RAC.h" #endif #include "xf86cmap.h" #include "compiler.h" #include "mibstore.h" #include "vgaHW.h" #include "mipointer.h" #include "micmap.h" #include "fb.h" #include "regionstr.h" #include "xf86xv.h" #include #include "vbe.h" #include "xf86PciInfo.h" #include "xf86Pci.h" /* framebuffer offscreen manager */ #include "xf86fbman.h" /* include xaa includes */ #include "xaa.h" #include "xaarop.h" /* H/W cursor support */ #include "xf86Cursor.h" /* Driver specific headers */ #include "ast.h" /* external reference fucntion */ extern Bool ASTMapMem(ScrnInfoPtr pScrn); extern Bool ASTUnmapMem(ScrnInfoPtr pScrn); extern Bool ASTMapMMIO(ScrnInfoPtr pScrn); extern void ASTUnmapMMIO(ScrnInfoPtr pScrn); extern void vASTOpenKey(ScrnInfoPtr pScrn); extern Bool bASTRegInit(ScrnInfoPtr pScrn); extern void GetDRAMInfo(ScrnInfoPtr pScrn); extern ULONG GetVRAMInfo(ScrnInfoPtr pScrn); extern ULONG GetMaxDCLK(ScrnInfoPtr pScrn); extern void GetChipType(ScrnInfoPtr pScrn); extern void vASTLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual); extern void ASTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); extern void vSetStartAddressCRT1(ASTRecPtr pAST, ULONG base); extern Bool ASTSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode); extern Bool GetVGA2EDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer); extern void vInitDRAMReg(ScrnInfoPtr pScrn); extern Bool bIsVGAEnabled(ScrnInfoPtr pScrn); extern void ASTBlankScreen(ScrnInfoPtr pScreen, Bool unblack); extern Bool InitVGA(ScrnInfoPtr pScrn, ULONG Flags); extern Bool GetVGAEDID(ScrnInfoPtr pScrn, unsigned char *pEDIDBuffer); extern Bool bInitAST1180(ScrnInfoPtr pScrn); extern void GetAST1180DRAMInfo(ScrnInfoPtr pScrn); extern void vEnableASTVGAMMIO(ScrnInfoPtr pScrn); extern Bool bInitCMDQInfo(ScrnInfoPtr pScrn, ASTRecPtr pAST); extern Bool bEnableCMDQ(ScrnInfoPtr pScrn, ASTRecPtr pAST); extern void vDisable2D(ScrnInfoPtr pScrn, ASTRecPtr pAST); extern Bool ASTAccelInit(ScreenPtr pScreen); extern Bool ASTCursorInit(ScreenPtr pScreen); extern void ASTDisableHWC(ScrnInfoPtr pScrn); /* Mandatory functions */ static void ASTIdentify(int flags); const OptionInfoRec *ASTAvailableOptions(int chipid, int busid); static Bool ASTProbe(DriverPtr drv, int flags); static Bool ASTPreInit(ScrnInfoPtr pScrn, int flags); static Bool ASTScreenInit(SCREEN_INIT_ARGS_DECL); Bool ASTSwitchMode(SWITCH_MODE_ARGS_DECL); void ASTAdjustFrame(ADJUST_FRAME_ARGS_DECL); static Bool ASTEnterVT(VT_FUNC_ARGS_DECL); static void ASTLeaveVT(VT_FUNC_ARGS_DECL); static void ASTFreeScreen(FREE_SCREEN_ARGS_DECL); static ModeStatus ASTValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags); /* Internally used functions */ static Bool ASTGetRec(ScrnInfoPtr pScrn); static void ASTFreeRec(ScrnInfoPtr pScrn); static Bool ASTSaveScreen(ScreenPtr pScreen, Bool unblack); static Bool ASTCloseScreen(CLOSE_SCREEN_ARGS_DECL); static void ASTSave(ScrnInfoPtr pScrn); static void ASTRestore(ScrnInfoPtr pScrn); static void ASTProbeDDC(ScrnInfoPtr pScrn, int index); static xf86MonPtr ASTDoDDC(ScrnInfoPtr pScrn, int index); static void vFillASTModeInfo (ScrnInfoPtr pScrn); static Bool ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); #ifdef AstVideo /* video function */ static void ASTInitVideo(ScreenPtr pScreen); static int ASTPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer); #endif /* * This is intentionally screen-independent. It indicates the binding * choice made in the first PreInit. */ _X_EXPORT DriverRec AST = { AST_VERSION, AST_DRIVER_NAME, ASTIdentify, ASTProbe, ASTAvailableOptions, NULL, 0 }; /* Chipsets */ static SymTabRec ASTChipsets[] = { {PCI_CHIP_AST2000, "ASPEED Graphics Family"}, {PCI_CHIP_AST2100, "ASPEED Graphics Family"}, {PCI_CHIP_AST1180, "ASPEED AST1180 Graphics"}, {-1, NULL} }; static PciChipsets ASTPciChipsets[] = { {PCI_CHIP_AST2000, PCI_CHIP_AST2000, RES_SHARED_VGA}, {PCI_CHIP_AST2100, PCI_CHIP_AST2100, RES_SHARED_VGA}, {PCI_CHIP_AST1180, PCI_CHIP_AST1180, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; typedef enum { OPTION_NOACCEL, OPTION_MMIO2D, OPTION_SW_CURSOR, OPTION_HWC_NUM, OPTION_ENG_CAPS, OPTION_DBG_SELECT, OPTION_NO_DDC, OPTION_VGA2_CLONE } ASTOpts; static const OptionInfoRec ASTOptions[] = { {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_MMIO2D, "MMIO2D", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_SW_CURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_HWC_NUM, "HWCNumber", OPTV_INTEGER, {0}, FALSE}, {OPTION_ENG_CAPS, "ENGCaps", OPTV_INTEGER, {0}, FALSE}, {OPTION_DBG_SELECT, "DBGSelect", OPTV_INTEGER, {0}, FALSE}, {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_VGA2_CLONE, "VGA2Clone", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; #ifdef XFree86LOADER static MODULESETUPPROTO(astSetup); static XF86ModuleVersionInfo astVersRec = { AST_DRIVER_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, AST_MAJOR_VERSION, AST_MINOR_VERSION, AST_PATCH_VERSION, ABI_CLASS_VIDEODRV, #ifdef PATCH_ABI_VERSION ABI_VIDEODRV_VERSION_PATCH, #else ABI_VIDEODRV_VERSION, #endif MOD_CLASS_VIDEODRV, {0, 0, 0, 0} }; _X_EXPORT XF86ModuleData astModuleData = { &astVersRec, astSetup, NULL }; static pointer astSetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; /* This module should be loaded only once, but check to be sure. */ if (!setupDone) { setupDone = TRUE; xf86AddDriver(&AST, module, 0); /* * The return value must be non-NULL on success even though there * is no TearDownProc. */ return (pointer) TRUE; } else { if (errmaj) *errmaj = LDR_ONCEONLY; return NULL; } } #endif /* XFree86LOADER */ /* * ASTIdentify -- * * Returns the string name for the driver based on the chipset. In this * case it will always be an AST, so we can return a static string. * */ static void ASTIdentify(int flags) { xf86PrintChipsets(AST_NAME, "Driver for ASPEED Graphics Chipsets", ASTChipsets); } const OptionInfoRec * ASTAvailableOptions(int chipid, int busid) { return ASTOptions; } /* * ASTProbe -- * * Look through the PCI bus to find cards that are AST boards. * Setup the dispatch table for the rest of the driver functions. * */ static Bool ASTProbe(DriverPtr drv, int flags) { int i, numUsed, numDevSections, *usedChips; Bool foundScreen = FALSE; GDevPtr *devSections; /* * Find the config file Device sections that match this * driver, and return if there are none. */ if ((numDevSections = xf86MatchDevice(AST_DRIVER_NAME, &devSections)) <= 0) { return FALSE; } #ifndef XSERVER_LIBPCIACCESS /* * This probing is just checking the PCI data the server already * collected. */ if (xf86GetPciVideoInfo() == NULL) { return FALSE; } #endif numUsed = xf86MatchPciInstances(AST_NAME, PCI_VENDOR_AST, ASTChipsets, ASTPciChipsets, devSections, numDevSections, drv, &usedChips); free(devSections); if (flags & PROBE_DETECT) { if (numUsed > 0) foundScreen = TRUE; } else { for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn = NULL; #ifdef XSERVER_LIBPCIACCESS { struct pci_device *pPci = xf86GetPciInfoForEntity(usedChips[i]); if (pci_device_has_kernel_driver(pPci)) { xf86DrvMsg(0, X_ERROR, "ast: The PCI device 0x%x at %2.2d@%2.2d:%2.2d:%1.1d has a kernel module claiming it.\n", pPci->device_id, pPci->bus, pPci->domain, pPci->dev, pPci->func); xf86DrvMsg(0, X_ERROR, "cirrus: This driver cannot operate until it has been unloaded.\n"); return FALSE; } } #endif /* Allocate new ScrnInfoRec and claim the slot */ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], ASTPciChipsets, 0, 0, 0, 0, 0))) { EntityInfoPtr pEnt; pEnt = xf86GetEntityInfo(usedChips[i]); pScrn->driverVersion = AST_VERSION; pScrn->driverName = AST_DRIVER_NAME; pScrn->name = AST_NAME; pScrn->Probe = ASTProbe; pScrn->PreInit = ASTPreInit; pScrn->ScreenInit = ASTScreenInit; pScrn->SwitchMode = ASTSwitchMode; pScrn->AdjustFrame = ASTAdjustFrame; pScrn->EnterVT = ASTEnterVT; pScrn->LeaveVT = ASTLeaveVT; pScrn->FreeScreen = ASTFreeScreen; pScrn->ValidMode = ASTValidMode; foundScreen = TRUE; } /* end of if */ } /* end of for-loop */ } /* end of if flags */ free(usedChips); return foundScreen; } /* * ASTPreInit -- * * Do initial setup of the board before we know what resolution we will * be running at. * */ static Bool ASTPreInit(ScrnInfoPtr pScrn, int flags) { EntityInfoPtr pEnt; int flags24; rgb defaultWeight = { 0, 0, 0 }; #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWPtr hwp; #endif ASTRecPtr pAST; ClockRangePtr clockRanges; int i; MessageType from; int maxPitch, maxHeight; /* Suport one adapter only now */ if (pScrn->numEntities != 1) return FALSE; pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (flags & PROBE_DETECT) { ASTProbeDDC(pScrn, pEnt->index); return TRUE; } if (pEnt->location.type != BUS_PCI) return FALSE; #ifndef XSERVER_LIBPCIACCESS if (xf86RegisterResources(pEnt->index, 0, ResExclusive)) return FALSE; #endif #if !(defined(__sparc__)) && !(defined(__mips__)) /* The vgahw module should be loaded here when needed */ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; #endif /* The fb module should be loaded here when needed */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; #if !(defined(__sparc__)) && !(defined(__mips__)) /* Allocate a vgaHWRec */ if (!vgaHWGetHWRec(pScrn)) return FALSE; hwp = VGAHWPTR(pScrn); vgaHWSetStdFuncs(hwp); #endif /* Color Depth Check */ flags24 = Support32bppFb; if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) { return FALSE; } else { switch (pScrn->depth) { case 8: case 16: case 24: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by ast driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); switch (pScrn->bitsPerPixel) { case 8: case 16: case 32: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given bpp (%d) is not supported by ast driver\n", pScrn->bitsPerPixel); return FALSE; } /* fill pScrn misc. */ pScrn->progClock = TRUE; pScrn->rgbBits = 6; pScrn->monitor = pScrn->confScreen->monitor; /* should be initialized before set gamma */ #ifndef XSERVER_LIBPCIACCESS pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; #endif /* * If the driver can do gamma correction, it should call xf86SetGamma() * here. */ { Gamma zeros = { 0.0, 0.0, 0.0 }; if (!xf86SetGamma(pScrn, zeros)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call xf86SetGamma failed \n"); return FALSE; } } if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) { return FALSE; } if (!xf86SetDefaultVisual(pScrn, -1)) { return FALSE; } /* Allocate driverPrivate */ if (!ASTGetRec(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "call ASTGetRec failed \n"); return FALSE; } /* Fill AST Info */ pAST = ASTPTR(pScrn); pAST->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); pAST->PciInfo = xf86GetPciInfoForEntity(pAST->pEnt->index); #ifndef XSERVER_LIBPCIACCESS pAST->PciTag = pciTag(pAST->PciInfo->bus, pAST->PciInfo->device, pAST->PciInfo->func); #endif /* Process the options * pScrn->confScreen, pScrn->display, pScrn->monitor, pScrn->numEntities, * and pScrn->entityList should be initialized before */ xf86CollectOptions(pScrn, NULL); if (!(pAST->Options = malloc(sizeof(ASTOptions)))) { ASTFreeRec(pScrn); return FALSE; } memcpy(pAST->Options, ASTOptions, sizeof(ASTOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pAST->Options); /* * Set the Chipset and ChipRev, allowing config file entries to * override. */ if (pAST->pEnt->device->chipset && *pAST->pEnt->device->chipset) { pScrn->chipset = pAST->pEnt->device->chipset; from = X_CONFIG; } else if (pAST->pEnt->device->chipID >= 0) { pScrn->chipset = (char *)xf86TokenToString(ASTChipsets, pAST->pEnt->device->chipID); from = X_CONFIG; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", pAST->pEnt->device->chipID); } else { from = X_PROBED; pScrn->chipset = (char *)xf86TokenToString(ASTChipsets, PCI_DEV_DEVICE_ID(pAST->PciInfo)); } if (pAST->pEnt->device->chipRev >= 0) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", pAST->pEnt->device->chipRev); } xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown ast"); /* Resource Allocation */ #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 pAST->IODBase = pScrn->domainIOBase; #else pAST->IODBase = 0; #endif /* "Patch" the PIOOffset inside vgaHW in order to force * the vgaHW module to use our relocated i/o ports. */ #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 VGAHWPTR(pScrn)->PIOOffset = /* ... */ #endif pAST->PIOOffset = pAST->IODBase + PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) - 0x380; pAST->RelocateIO = (IOADDRESS)(PCI_REGION_BASE(pAST->PciInfo, 2, REGION_IO) + pAST->IODBase); if (pAST->pEnt->device->MemBase != 0) { pAST->FBPhysAddr = pAST->pEnt->device->MemBase; from = X_CONFIG; } else { if (PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) != 0) { pAST->FBPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 0, REGION_MEM) & 0xFFF00000; from = X_PROBED; } else { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid FB address in PCI config space\n"); ASTFreeRec(pScrn); return FALSE; } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer at 0x%lX\n", (unsigned long) pAST->FBPhysAddr); if (pAST->pEnt->device->IOBase != 0) { pAST->MMIOPhysAddr = pAST->pEnt->device->IOBase; from = X_CONFIG; } else { if (PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM)) { pAST->MMIOPhysAddr = PCI_REGION_BASE(pAST->PciInfo, 1, REGION_MEM) & 0xFFFF0000; from = X_PROBED; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No valid MMIO address in PCI config space\n"); ASTFreeRec(pScrn); return FALSE; } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "IO registers at addr 0x%lX\n", (unsigned long) pAST->MMIOPhysAddr); /* Map MMIO */ pAST->MMIOMapSize = DEFAULT_MMIO_SIZE; if (!ASTMapMMIO(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map Memory Map IO Failed \n"); return FALSE; } if (PCI_DEV_DEVICE_ID(pAST->PciInfo) == PCI_CHIP_AST1180) { pAST->jChipType = AST1180; /* validate mode */ if ( (pScrn->bitsPerPixel == 8) || (pScrn->depth == 8) ) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given bpp (%d) is not supported by ast driver\n", pScrn->bitsPerPixel); return FALSE; } /* Init AST1180 */ bInitAST1180(pScrn); /* Get AST1180 Information */ GetAST1180DRAMInfo(pScrn); pScrn->videoRam = pAST->ulVRAMSize / 1024; } else { /* Enable VGA MMIO Access */ vEnableASTVGAMMIO(pScrn); /* Init VGA Adapter */ if (!xf86IsPrimaryPci(pAST->PciInfo)) { InitVGA(pScrn, 0); } vASTOpenKey(pScrn); bASTRegInit(pScrn); /* Get Chip Type */ if (PCI_DEV_REVISION(pAST->PciInfo) >= 0x20) pAST->jChipType = AST2300; else if (PCI_DEV_REVISION(pAST->PciInfo) >= 0x10) GetChipType(pScrn); else pAST->jChipType = AST2000; /* Get DRAM Info */ GetDRAMInfo(pScrn); pAST->ulVRAMSize = GetVRAMInfo(pScrn); pScrn->videoRam = pAST->ulVRAMSize / 1024; } /* Map Framebuffer */ from = X_DEFAULT; if (pAST->pEnt->device->videoRam) { pScrn->videoRam = pAST->pEnt->device->videoRam; from = X_CONFIG; } pAST->FbMapSize = pScrn->videoRam * 1024; #if 0 if (!ASTMapMem(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n"); return FALSE; } #endif pScrn->memPhysBase = (ULONG)pAST->FBPhysAddr; pScrn->fbOffset = 0; /* Do DDC * should be done after xf86CollectOptions */ pScrn->monitor->DDC = ASTDoDDC(pScrn, pAST->pEnt->index); /* Mode Valid */ clockRanges = xnfcalloc(sizeof(ClockRange), 1); clockRanges->next = NULL; clockRanges->minClock = 9500; clockRanges->maxClock = GetMaxDCLK(pScrn) * 1000; clockRanges->clockIndex = -1; clockRanges->interlaceAllowed = FALSE; clockRanges->doubleScanAllowed = FALSE; /* Add for AST2100, ycchen@061807 */ if ((pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180)) { maxPitch = 1920; maxHeight = 1200; } else { maxPitch = 1600; maxHeight = 1200; } i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, 0, 320, maxPitch, 8 * pScrn->bitsPerPixel, 200, maxHeight, pScrn->display->virtualX, pScrn->display->virtualY, pAST->FbMapSize, LOOKUP_BEST_REFRESH); /* fixed some monitors can't get propery validate modes using estimated ratio modes */ if (i < 2) /* validate modes are too few */ { i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, 0, 320, maxPitch, 8 * pScrn->bitsPerPixel, 200, maxHeight, pAST->mon_h_active, pAST->mon_v_active, pAST->FbMapSize, LOOKUP_BEST_REFRESH); } if (i == -1) { ASTFreeRec(pScrn); return FALSE; } xf86PruneDriverModes(pScrn); if (!i || !pScrn->modes) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); ASTFreeRec(pScrn); return FALSE; } xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); pScrn->currentMode = pScrn->modes; xf86PrintModes(pScrn); xf86SetDpi(pScrn, 0, 0); /* Accelaration Check */ pAST->noAccel = TRUE; pAST->AccelInfoPtr = NULL; pAST->pCMDQPtr = NULL; pAST->CMDQInfo.ulCMDQSize = 0; #ifdef Accel_2D if (!xf86ReturnOptValBool(pAST->Options, OPTION_NOACCEL, FALSE)) { if (xf86LoadSubModule(pScrn, "xaa")) { pAST->noAccel = FALSE; pAST->MMIO2D = TRUE; #ifndef MMIO_2D if (!xf86ReturnOptValBool(pAST->Options, OPTION_MMIO2D, FALSE)) { pAST->CMDQInfo.ulCMDQSize = DEFAULT_CMDQ_SIZE; pAST->MMIO2D = FALSE; } #endif pAST->ENGCaps = ENG_CAP_ALL; if (!xf86GetOptValInteger(pAST->Options, OPTION_ENG_CAPS, &pAST->ENGCaps)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No ENG Capability options found\n"); } pAST->DBGSelect = 0; if (!xf86GetOptValInteger(pAST->Options, OPTION_DBG_SELECT, &pAST->DBGSelect)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DBG Seleclt options found\n"); } } } #endif /* HW Cursor Check */ pAST->noHWC = TRUE; pAST->HWCInfoPtr = NULL; pAST->pHWCPtr = NULL; #ifdef HWC if (!xf86ReturnOptValBool(pAST->Options, OPTION_SW_CURSOR, FALSE)) { if (!xf86LoadSubModule(pScrn, "ramdac")) { ASTFreeRec(pScrn); return FALSE; } pAST->noHWC = FALSE; pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; if (!xf86GetOptValInteger(pAST->Options, OPTION_HWC_NUM, &pAST->HWCInfo.HWC_NUM)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No HWC_NUM options found\n"); } } #endif #ifndef XSERVER_LIBPCIACCESS /* We won't be using the VGA access after the probe */ xf86SetOperatingState(resVgaIo, pAST->pEnt->index, ResUnusedOpr); xf86SetOperatingState(resVgaMem, pAST->pEnt->index, ResDisableOpr); #endif return TRUE; } static Bool ASTScreenInit(SCREEN_INIT_ARGS_DECL) { ScrnInfoPtr pScrn; ASTRecPtr pAST; VisualPtr visual; /* for FB Manager */ BoxRec FBMemBox; int AvailFBSize; pScrn = xf86ScreenToScrn(pScreen); pAST = ASTPTR(pScrn); if (!ASTMapMem(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Map FB Memory Failed \n"); return FALSE; } /* if (!pAST->noAccel) */ { /* AvailFBSize = pAST->FbMapSize - pAST->CMDQInfo.ulCMDQSize; */ AvailFBSize = pAST->FbMapSize; FBMemBox.x1 = 0; FBMemBox.y1 = 0; FBMemBox.x2 = pScrn->displayWidth; FBMemBox.y2 = (AvailFBSize / (pScrn->displayWidth * ((pScrn->bitsPerPixel+1)/8))) - 1; if (FBMemBox.y2 < 0) FBMemBox.y2 = 32767; if (FBMemBox.y2 < pScrn->virtualY) return FALSE; if (!xf86InitFBManager(pScreen, &FBMemBox)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); return FALSE; } } #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWPtr hwp; hwp = VGAHWPTR(pScrn); vgaHWSetMmioFuncs(hwp, pAST->MMIOVirtualAddr, 0); #endif vFillASTModeInfo (pScrn); ASTSave(pScrn); if (!ASTModeInit(pScrn, pScrn->currentMode)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Mode Init Failed \n"); return FALSE; } ASTSaveScreen(pScreen, FALSE); ASTAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); miClearVisualTypes(); /* Re-implemented Direct Color support, -jens */ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) return FALSE; if (!miSetPixmapDepths()) { ASTSaveScreen(pScreen, SCREEN_SAVER_OFF); return FALSE; } switch(pScrn->bitsPerPixel) { case 8: case 16: case 32: if (!fbScreenInit(pScreen, pAST->FBVirtualAddr + pScrn->fbOffset, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) return FALSE; break; default: return FALSE; } if (pScrn->bitsPerPixel > 8) { /* Fixup RGB ordering */ visual = pScreen->visuals + pScreen->numVisuals; while (--visual >= pScreen->visuals) { if ((visual->class | DynamicClass) == DirectColor) { visual->offsetRed = pScrn->offset.red; visual->offsetGreen = pScrn->offset.green; visual->offsetBlue = pScrn->offset.blue; visual->redMask = pScrn->mask.red; visual->greenMask = pScrn->mask.green; visual->blueMask = pScrn->mask.blue; } } } fbPictureInit(pScreen, 0, 0); xf86SetBlackWhitePixels(pScreen); #ifdef Accel_2D if (!pAST->noAccel) { if (!ASTAccelInit(pScreen)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware acceleration initialization failed\n"); pAST->noAccel = TRUE; } } #endif /* end of Accel_2D */ miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); xf86SetSilkenMouse(pScreen); miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); if (!pAST->noHWC) { if (!ASTCursorInit(pScreen)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Hardware cursor initialization failed\n"); pAST->noHWC = TRUE; } } if (!miCreateDefColormap(pScreen)) return FALSE; if (pAST->jChipType != AST1180) { if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, vASTLoadPalette, NULL, CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { return FALSE; } } xf86DPMSInit(pScreen, ASTDisplayPowerManagementSet, 0); #ifdef AstVideo if ( (pAST->jChipType == AST1180) || (pAST->jChipType == AST2300) ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO,"AST Initial Video()\n"); ASTInitVideo(pScreen); } #endif pScreen->SaveScreen = ASTSaveScreen; pAST->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = ASTCloseScreen; if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); return TRUE; } /* ASTScreenInit */ Bool ASTSwitchMode(SWITCH_MODE_ARGS_DECL) { SCRN_INFO_PTR(arg); ASTRecPtr pAST = ASTPTR(pScrn); /* VideoMode validate */ if (mode->CrtcHDisplay > pScrn->displayWidth) return FALSE; if ((pAST->VideoModeInfo.ScreenPitch * mode->CrtcVDisplay) > pAST->ulVRAMSize) return FALSE; /* VideModeInfo Update */ pAST->VideoModeInfo.ScreenWidth = mode->CrtcHDisplay; pAST->VideoModeInfo.ScreenHeight = mode->CrtcVDisplay; pAST->VideoModeInfo.ScreenPitch = pScrn->displayWidth * ((pScrn->bitsPerPixel + 1) / 8) ; #ifdef HWC if (pAST->pHWCPtr) { xf86FreeOffscreenLinear(pAST->pHWCPtr); /* free HWC Cache */ pAST->pHWCPtr = NULL; } ASTDisableHWC(pScrn); #endif #ifdef Accel_2D if (pAST->pCMDQPtr) { xf86FreeOffscreenLinear(pAST->pCMDQPtr); /* free CMDQ */ pAST->pCMDQPtr = NULL; } vDisable2D(pScrn, pAST); #endif /* Fixed display abnormal on the of the screen if run xvidtune, ycchen@122909 */ /* ASTRestore(pScrn); */ return ASTModeInit(pScrn, mode); } void ASTAdjustFrame(ADJUST_FRAME_ARGS_DECL) { SCRN_INFO_PTR(arg); ASTRecPtr pAST = ASTPTR(pScrn); ULONG base; base = y * pAST->VideoModeInfo.ScreenPitch + x * ((pAST->VideoModeInfo.bitsPerPixel + 1) / 8); /* base = base >> 2; */ /* DW unit */ vSetStartAddressCRT1(pAST, base); } /* enter into X Server */ static Bool ASTEnterVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); ASTRecPtr pAST = ASTPTR(pScrn); /* Fixed suspend can't resume issue */ if (!bIsVGAEnabled(pScrn)) { if (pAST->jChipType == AST1180) bInitAST1180(pScrn); else InitVGA(pScrn, 1); ASTRestore(pScrn); } if (!ASTModeInit(pScrn, pScrn->currentMode)) return FALSE; ASTAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); return TRUE; } /* leave X server */ static void ASTLeaveVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); ASTRecPtr pAST = ASTPTR(pScrn); #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWPtr hwp = VGAHWPTR(pScrn); #endif #ifdef HWC if (pAST->pHWCPtr) { xf86FreeOffscreenLinear(pAST->pHWCPtr); /* free HWC Cache */ pAST->pHWCPtr = NULL; } ASTDisableHWC(pScrn); #endif #ifdef Accel_2D if (pAST->pCMDQPtr) { xf86FreeOffscreenLinear(pAST->pCMDQPtr); /* free CMDQ */ pAST->pCMDQPtr = NULL; } vDisable2D(pScrn, pAST); #endif ASTRestore(pScrn); if (pAST->jChipType == AST1180) ASTBlankScreen(pScrn, 0); #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWLock(hwp); #endif } static void ASTFreeScreen(FREE_SCREEN_ARGS_DECL) { SCRN_INFO_PTR(arg); ASTFreeRec(pScrn); #if !(defined(__sparc__)) && !(defined(__mips__)) if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); #endif } static ModeStatus ASTValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) { SCRN_INFO_PTR(arg); ASTRecPtr pAST = ASTPTR(pScrn); ModeStatus Flags = MODE_NOMODE; UCHAR jReg; ULONG RequestBufferSize; if (mode->Flags & V_INTERLACE) { if (verbose) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Removing interlaced mode \"%s\"\n", mode->name); } return MODE_NO_INTERLACE; } if ((mode->CrtcHDisplay > MAX_HResolution) || (mode->CrtcVDisplay > MAX_VResolution)) { if (verbose) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Removing the mode \"%s\"\n", mode->name); } return Flags; } /* Valid Framebuffer size */ RequestBufferSize = mode->CrtcHDisplay * ((pScrn->bitsPerPixel + 1) / 8) * mode->CrtcVDisplay; if (RequestBufferSize > pAST->ulVRAMSize) return Flags; /* Check BMC scratch for iKVM compatible */ if (pAST->jChipType == AST2000) jReg = 0x80; else if (pAST->jChipType == AST1180) jReg = 0x01; else { GetIndexRegMask(CRTC_PORT, 0xD0, 0xFF, jReg); } if ( !(jReg & 0x80) || (jReg & 0x01) ) { if ( (mode->CrtcHDisplay == 1680) && (mode->CrtcVDisplay == 1050) ) return MODE_OK; if ( (mode->CrtcHDisplay == 1280) && (mode->CrtcVDisplay == 800) ) return MODE_OK; if ( (mode->CrtcHDisplay == 1440) && (mode->CrtcVDisplay == 900) ) return MODE_OK; if ( (pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180) ) { if ( (mode->CrtcHDisplay == 1920) && (mode->CrtcVDisplay == 1080) ) return MODE_OK; } } /* Add for AST2100, ycchen@061807 */ if ( (pAST->jChipType == AST2100) || (pAST->jChipType == AST2200) || (pAST->jChipType == AST2300) || (pAST->jChipType == AST1180) ) { if ( (mode->CrtcHDisplay == 1920) && (mode->CrtcVDisplay == 1200) ) { GetIndexRegMask(CRTC_PORT, 0xD1, 0xFF, jReg); if (jReg & 0x01) return MODE_NOMODE; else return MODE_OK; } } switch (mode->CrtcHDisplay) { case 640: if (mode->CrtcVDisplay == 480) Flags=MODE_OK; break; case 800: if (mode->CrtcVDisplay == 600) Flags=MODE_OK; break; case 1024: if (mode->CrtcVDisplay == 768) Flags=MODE_OK; break; case 1280: if (mode->CrtcVDisplay == 1024) Flags=MODE_OK; break; case 1600: if (mode->CrtcVDisplay == 1200) Flags=MODE_OK; break; default: return Flags; } return Flags; } /* Internal used modules */ /* * ASTGetRec and ASTFreeRec -- * * Private data for the driver is stored in the screen structure. * These two functions create and destroy that private data. * */ static Bool ASTGetRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate) return TRUE; pScrn->driverPrivate = xnfcalloc(sizeof(ASTRec), 1); return TRUE; } static void ASTFreeRec(ScrnInfoPtr pScrn) { if (!pScrn) return; if (!pScrn->driverPrivate) return; free(pScrn->driverPrivate); pScrn->driverPrivate = 0; } static Bool ASTSaveScreen(ScreenPtr pScreen, Bool unblack) { #if !(defined(__sparc__)) && !(defined(__mips__)) /* replacement of vgaHWBlankScreen(pScrn, unblank) without seq reset */ /* return vgaHWSaveScreen(pScreen, unblack); */ ScrnInfoPtr pScrn = NULL; if (pScreen != NULL) pScrn = xf86ScreenToScrn(pScreen); if ((pScrn != NULL) && pScrn->vtSema) { ASTBlankScreen(pScrn, unblack); } return (TRUE); #endif } static Bool ASTCloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); ASTRecPtr pAST = ASTPTR(pScrn); #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWPtr hwp = VGAHWPTR(pScrn); #endif if (pScrn->vtSema == TRUE) { #ifdef HWC if (pAST->pHWCPtr) { xf86FreeOffscreenLinear(pAST->pHWCPtr); /* free HWC Cache */ pAST->pHWCPtr = NULL; } ASTDisableHWC(pScrn); #endif #ifdef Accel_2D if (pAST->pCMDQPtr) { xf86FreeOffscreenLinear(pAST->pCMDQPtr); /* free CMDQ */ pAST->pCMDQPtr = NULL; } vDisable2D(pScrn, pAST); #endif ASTRestore(pScrn); if (pAST->jChipType == AST1180) ASTBlankScreen(pScrn, 0); #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWLock(hwp); #endif } ASTUnmapMem(pScrn); #if !(defined(__sparc__)) && !(defined(__mips__)) vgaHWUnmapMem(pScrn); #endif if(pAST->AccelInfoPtr) { XAADestroyInfoRec(pAST->AccelInfoPtr); pAST->AccelInfoPtr = NULL; } if(pAST->HWCInfoPtr) { xf86DestroyCursorInfoRec(pAST->HWCInfoPtr); pAST->HWCInfoPtr = NULL; } pScrn->vtSema = FALSE; pScreen->CloseScreen = pAST->CloseScreen; return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); } static void ASTSave(ScrnInfoPtr pScrn) { ASTRecPtr pAST; ASTRegPtr astReg; int i, icount=0; ULONG ulData; pAST = ASTPTR(pScrn); astReg = &pAST->SavedReg; if (pAST->jChipType == AST1180) { for (i=0; i<12; i++) { ReadAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL+i*4, ulData); astReg->GFX[i] = ulData; } } else { #if defined(__sparc__) || defined(__mips__) UCHAR jReg; /* Save Misc */ astReg->MISC = GetReg(MISC_PORT_READ); /* Save SR */ for (i=0; i<4; i++) GetIndexReg(SEQ_PORT, (UCHAR) (i), astReg->SEQ[i]); /* Save CR */ for (i=0; i<25; i++) GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->CRTC[i]); /* Save GR */ for (i=0; i<9; i++) GetIndexReg(GR_PORT, (UCHAR) (i), astReg->GR[i]); /* Save AR */ jReg = GetReg(INPUT_STATUS1_READ); for (i=0; i<20; i++) GetIndexReg(AR_PORT_WRITE, (UCHAR) (i), astReg->AR[i]); jReg = GetReg(INPUT_STATUS1_READ); SetReg (AR_PORT_WRITE, 0x20); /* set POS */ #else vgaRegPtr vgaReg; vgaReg = &VGAHWPTR(pScrn)->SavedReg; /* do save */ if (xf86IsPrimaryPci(pAST->PciInfo)) { vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS); } else { vgaHWSave(pScrn, vgaReg, VGA_SR_MODE); } #endif /* Save Ext. */ vASTOpenKey(pScrn); /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */ for (i=0x81; i<=0xB6; i++) GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]); for (i=0xBC; i<=0xC1; i++) GetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]); GetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]); /* Save DAC */ for (i=0; i<256; i++) VGA_GET_PALETTE_INDEX (i, astReg->DAC[i][0], astReg->DAC[i][1], astReg->DAC[i][2]); } } static void ASTRestore(ScrnInfoPtr pScrn) { ASTRecPtr pAST; ASTRegPtr astReg; int i, icount=0; ULONG ulData; pAST = ASTPTR(pScrn); astReg = &pAST->SavedReg; if (pAST->jChipType == AST1180) { for (i=0; i<12; i++) { ulData = astReg->GFX[i]; WriteAST1180SOC(AST1180_GFX_BASE + AST1180_VGA1_CTRL+i*4, ulData); } } else { #if defined(__sparc__) || defined(__mips__) UCHAR jReg; /* Restore Misc */ SetReg(MISC_PORT_WRITE, astReg->MISC); /* Restore SR */ for (i=0; i<4; i++) SetIndexReg(SEQ_PORT, (UCHAR) (i), astReg->SEQ[i]); /* Restore CR */ SetIndexRegMask(CRTC_PORT,0x11, 0x7F, 0x00); for (i=0; i<25; i++) SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->CRTC[i]); /* Restore GR */ for (i=0; i<9; i++) SetIndexReg(GR_PORT, (UCHAR) (i), astReg->GR[i]); /* Restore AR */ jReg = GetReg(INPUT_STATUS1_READ); for (i=0; i<20; i++) { SetReg(AR_PORT_WRITE, (UCHAR) i); SetReg(AR_PORT_WRITE, astReg->AR[i]); } SetReg(AR_PORT_WRITE, 0x14); SetReg(AR_PORT_WRITE, 0x00); jReg = GetReg(INPUT_STATUS1_READ); SetReg (AR_PORT_WRITE, 0x20); /* set POS */ #else vgaRegPtr vgaReg; vgaReg = &VGAHWPTR(pScrn)->SavedReg; /* do restore */ vgaHWProtect(pScrn, TRUE); if (xf86IsPrimaryPci(pAST->PciInfo)) vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS); else vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); vgaHWProtect(pScrn, FALSE); #endif /* Ext. restore */ vASTOpenKey(pScrn); /* fixed Console Switch Refresh Rate Incorrect issue, ycchen@051106 */ for (i=0x81; i<=0xB6; i++) SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]); for (i=0xBC; i<=0xC1; i++) SetIndexReg(CRTC_PORT, (UCHAR) (i), astReg->ExtCRTC[icount++]); SetIndexReg(CRTC_PORT, (UCHAR) (0xBB), astReg->ExtCRTC[icount]); /* Restore DAC */ for (i=0; i<256; i++) VGA_LOAD_PALETTE_INDEX (i, astReg->DAC[i][0], astReg->DAC[i][1], astReg->DAC[i][2]); } } static void ASTProbeDDC(ScrnInfoPtr pScrn, int index) { ASTRecPtr pAST = ASTPTR(pScrn); unsigned char DDC_data[128]; Bool Flags; if (xf86LoadSubModule(pScrn, "ddc")) { if (pAST->jChipType == AST1180) Flags = GetVGA2EDID(pScrn, DDC_data); else Flags = GetVGAEDID(pScrn, DDC_data); if (Flags) { ConfiguredMonitor = xf86InterpretEDID(pScrn->scrnIndex, DDC_data); } else xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[ASTProbeDDC] Can't Get EDID Properly \n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[ASTProbeDDC] Can't Load DDC Sub-Modules or Read EDID Failed \n"); } } #define SkipDT 0x00 #define DT1 0x01 #define DT2 0x02 static xf86MonPtr ASTDoDDC(ScrnInfoPtr pScrn, int index) { xf86MonPtr MonInfo = NULL; ASTRecPtr pAST = ASTPTR(pScrn); unsigned char DDC_data[128]; Bool Flags; xf86MonPtr MonInfo1 = NULL, MonInfo2 = NULL; unsigned long i, j, k; struct monitor_ranges ranges, ranges1, ranges2; int DTSelect, dclock1=0, h_active1=0, v_active1=0, dclock2=0, h_active2=0, v_active2=0; struct std_timings stdtiming, *stdtiming1, *stdtiming2; /* Honour Option "noDDC" */ if (xf86ReturnOptValBool(pAST->Options, OPTION_NO_DDC, FALSE)) { return MonInfo; } if (xf86LoadSubModule(pScrn, "ddc")) { if (pAST->jChipType == AST1180) Flags = GetVGA2EDID(pScrn, DDC_data); else Flags = GetVGAEDID(pScrn, DDC_data); if (Flags) { MonInfo = MonInfo1 = xf86InterpretEDID(pScrn->scrnIndex, DDC_data); } /* For VGA2 CLONE Support, ycchen@012508 */ if ((xf86ReturnOptValBool(pAST->Options, OPTION_VGA2_CLONE, FALSE)) || pAST->VGA2Clone) { if (GetVGA2EDID(pScrn, DDC_data) == TRUE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Get VGA2 EDID Correctly!! \n"); MonInfo2 = xf86InterpretEDID(pScrn->scrnIndex, DDC_data); if (MonInfo1 == NULL) /* No DDC1 EDID */ MonInfo = MonInfo2; else { /* Check with VGA1 & VGA2 EDID */ /* Update establishment timing */ MonInfo->timings1.t1 = MonInfo1->timings1.t1 & MonInfo2->timings1.t1; MonInfo->timings1.t2 = MonInfo1->timings1.t2 & MonInfo2->timings1.t2; MonInfo->timings1.t_manu = MonInfo1->timings1.t_manu & MonInfo2->timings1.t_manu; /* Update Std. Timing */ for (i=0; i<8; i++) { stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0; for (j=0; j<8; j++) { if ((MonInfo1->timings2[i].hsize == MonInfo2->timings2[j].hsize) && \ (MonInfo1->timings2[i].vsize == MonInfo2->timings2[j].vsize) && \ (MonInfo1->timings2[i].refresh == MonInfo2->timings2[j].refresh)) { stdtiming = MonInfo1->timings2[i]; break; } } MonInfo->timings2[i] = stdtiming; } /* Std. Timing */ /* Get Detailed Timing */ for (i=0;i<4;i++) { if (MonInfo1->det_mon[i].type == 0xFD) ranges1 = MonInfo1->det_mon[i].section.ranges; else if (MonInfo1->det_mon[i].type == 0xFA) stdtiming1 = MonInfo1->det_mon[i].section.std_t; else if (MonInfo1->det_mon[i].type == 0x00) { if (MonInfo1->det_mon[i].section.d_timings.clock > dclock1) dclock1 = MonInfo1->det_mon[i].section.d_timings.clock; if (MonInfo1->det_mon[i].section.d_timings.h_active > h_active1) h_active1 = MonInfo1->det_mon[i].section.d_timings.h_active; if (MonInfo1->det_mon[i].section.d_timings.v_active > v_active1) v_active1 = MonInfo1->det_mon[i].section.d_timings.v_active; } if (MonInfo2->det_mon[i].type == 0xFD) ranges2 = MonInfo2->det_mon[i].section.ranges; else if (MonInfo1->det_mon[i].type == 0xFA) stdtiming2 = MonInfo2->det_mon[i].section.std_t; else if (MonInfo2->det_mon[i].type == 0x00) { if (MonInfo2->det_mon[i].section.d_timings.clock > dclock2) dclock2 = MonInfo2->det_mon[i].section.d_timings.clock; if (MonInfo2->det_mon[i].section.d_timings.h_active > h_active2) h_active2 = MonInfo2->det_mon[i].section.d_timings.h_active; if (MonInfo2->det_mon[i].section.d_timings.v_active > v_active2) v_active2 = MonInfo2->det_mon[i].section.d_timings.v_active; } } /* Get Detailed Timing */ /* Chk Detailed Timing */ if ((dclock1 >= dclock2) && (h_active1 >= h_active2) && (v_active1 >= v_active2)) DTSelect = DT2; else if ((dclock2 >= dclock1) && (h_active2 >= h_active1) && (v_active2 >= v_active1)) DTSelect = DT1; else DTSelect = SkipDT; /* Chk Monitor Descriptor */ ranges = ranges1; ranges.min_h = ranges1.min_h > ranges2.min_h ? ranges1.min_h:ranges2.min_h; ranges.min_v = ranges1.min_v > ranges2.min_v ? ranges1.min_v:ranges2.min_v; ranges.max_h = ranges1.max_h < ranges2.max_h ? ranges1.max_h:ranges2.max_h; ranges.max_v = ranges1.max_v < ranges2.max_v ? ranges1.max_v:ranges2.max_v; ranges.max_clock = ranges1.max_clock < ranges2.max_clock ? ranges1.max_clock:ranges2.max_clock; /* Update Detailed Timing */ for (i=0; i<4; i++) { if (MonInfo->det_mon[i].type == 0xFD) { MonInfo->det_mon[i].section.ranges = ranges; } else if (MonInfo->det_mon[i].type == 0xFA) { for (j=0; j<5; j++) { stdtiming.hsize = stdtiming.vsize = stdtiming.refresh = stdtiming.id = 0; for (k=0; k<5; k++) { if ((stdtiming1[j].hsize == stdtiming2[k].hsize) && \ (stdtiming1[j].vsize == stdtiming2[k].vsize) && \ (stdtiming1[j].refresh == stdtiming2[k].refresh)) { stdtiming = stdtiming1[j]; break; } } stdtiming1[j] = stdtiming; } /* Std. Timing */ } /* FA */ else if (MonInfo->det_mon[i].type == 0x00) { if (DTSelect == DT2) MonInfo->det_mon[i] = MonInfo2->det_mon[i]; else if (DTSelect == DT1) MonInfo->det_mon[i] = MonInfo1->det_mon[i]; else /* SkipDT */ { /* use 1024x768 as default */ MonInfo->det_mon[i] = MonInfo1->det_mon[i]; MonInfo->det_mon[i].section.d_timings.clock = 65000000; MonInfo->det_mon[i].section.d_timings.h_active = 1024; MonInfo->det_mon[i].section.d_timings.h_blanking = 320; MonInfo->det_mon[i].section.d_timings.v_active = 768; MonInfo->det_mon[i].section.d_timings.v_blanking = 38; MonInfo->det_mon[i].section.d_timings.h_sync_off = 24; MonInfo->det_mon[i].section.d_timings.h_sync_width = 136; MonInfo->det_mon[i].section.d_timings.v_sync_off = 3; MonInfo->det_mon[i].section.d_timings.v_sync_width = 6; } } /* 00 */ else { /* use Monitor 1 as default */ MonInfo->det_mon[i] = MonInfo1->det_mon[i]; } } /* Update Detailed Timing */ /* set feature size */ if (DTSelect == DT2) { MonInfo->features.hsize = MonInfo2->features.hsize; MonInfo->features.vsize = MonInfo2->features.vsize; } else if (DTSelect == DT1) { MonInfo->features.hsize = MonInfo1->features.hsize; MonInfo->features.vsize = MonInfo1->features.vsize; } else /* Skip DT */ { /* use 1024x768 as default */ MonInfo->features.hsize = 0x20; MonInfo->features.vsize = 0x18; } } /* Check with VGA1 & VGA2 EDID */ } /* GetVGA2EDID */ else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Can't Get VGA2 EDID Correctly!! \n"); } } /* VGA2Clone */ xf86PrintEDID(MonInfo); xf86SetDDCproperties(pScrn, MonInfo); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO,"[ASTDoDDC] Can't Load DDC Sub-Modules or Read EDID Failed \n"); } /* Fill pAST Monitor Info */ if (MonInfo == NULL) { /* default for Non-EDID */ pAST->mon_h_active = 1024; pAST->mon_v_active = 768; } else { /* save MonInfo to Private */ pAST->mon_h_active = MonInfo->det_mon[0].section.d_timings.h_active; pAST->mon_v_active = MonInfo->det_mon[0].section.d_timings.v_active; } return MonInfo; } static void vFillASTModeInfo (ScrnInfoPtr pScrn) { ASTRecPtr pAST; pAST = ASTPTR(pScrn); pAST->VideoModeInfo.ScreenWidth = pScrn->virtualX; pAST->VideoModeInfo.ScreenHeight = pScrn->virtualY; pAST->VideoModeInfo.bitsPerPixel = pScrn->bitsPerPixel; /* Fixed screen pitch incorrect in some specific monitor, ycchen@071707 */ pAST->VideoModeInfo.ScreenPitch = pScrn->displayWidth * ((pScrn->bitsPerPixel + 1) / 8) ; } static Bool ASTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { ASTRecPtr pAST; pAST = ASTPTR(pScrn); pScrn->vtSema = TRUE; pAST->ModePtr = mode; #if defined(__sparc__) || defined(__mips__) if (!ASTSetMode(pScrn, mode)) return FALSE; #else vgaHWPtr hwp; hwp = VGAHWPTR(pScrn); vgaHWUnlock(hwp); if (!vgaHWInit(pScrn, mode)) return FALSE; pScrn->vtSema = TRUE; pAST->ModePtr = mode; if (!ASTSetMode(pScrn, mode)) return FALSE; vgaHWProtect(pScrn, FALSE); #endif return TRUE; } #ifdef AstVideo /* * Video Part by ic_yang */ #include "fourcc.h" #define NUM_ATTRIBUTES 8 #define NUM_IMAGES 8 #define NUM_FORMATS 3 #define IMAGE_MIN_WIDTH 32 #define IMAGE_MIN_HEIGHT 24 #define IMAGE_MAX_WIDTH 1920 #define IMAGE_MAX_HEIGHT 1080 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) static XF86ImageRec ASTImages[NUM_IMAGES] = { XVIMAGE_YUY2, /* If order is changed, ASTOffscreenImages must be adapted */ }; static XF86VideoFormatRec ASTFormats[NUM_FORMATS] = { { 8, PseudoColor}, {16, TrueColor}, {24, TrueColor} }; /* client libraries expect an encoding */ static XF86VideoEncodingRec DummyEncoding = { 0, "XV_IMAGE", 0, 0, /* Will be filled in */ {1, 1} }; static char astxvcolorkey[] = "XV_COLORKEY"; static char astxvbrightness[] = "XV_BRIGHTNESS"; static char astxvcontrast[] = "XV_CONTRAST"; static char astxvsaturation[] = "XV_SATURATION"; static char astxvhue[] = "XV_HUE"; static char astxvgammared[] = "XV_GAMMA_RED"; static char astxvgammagreen[] = "XV_GAMMA_GREEN"; static char astxvgammablue[] = "XV_GAMMA_BLUE"; static XF86AttributeRec ASTAttributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, astxvcolorkey}, {XvSettable | XvGettable, -128, 127, astxvbrightness}, {XvSettable | XvGettable, 0, 255, astxvcontrast}, {XvSettable | XvGettable, -180, 180, astxvsaturation}, {XvSettable | XvGettable, -180, 180, astxvhue}, {XvSettable | XvGettable, 100, 10000, astxvgammared}, {XvSettable | XvGettable, 100, 10000, astxvgammagreen}, {XvSettable | XvGettable, 100, 10000, astxvgammablue}, }; static void ASTStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) { ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data; ASTPtr pAST = ASTPTR(pScrn); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); if(exit) { if(pPriv->fbAreaPtr) { xf86FreeOffscreenArea(pPriv->fbAreaPtr); pPriv->fbAreaPtr = NULL; pPriv->fbSize = 0; } /* clear all flag */ pPriv->videoStatus = 0; } else { #if 0 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { pPriv->videoStatus |= OFF_TIMER; } #endif } } static int ASTSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data; ASTPtr pAST = ASTPTR(pScrn); xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTSetPortAttribute(),attribute=%x\n", attribute); if (attribute == pAST->xvBrightness) { if((value < -128) || (value > 127)) return BadValue; pPriv->brightness = value; } else if (attribute == pAST->xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; } else if (attribute == pAST->xvSaturation) { if ((value < -180) || (value > 180)) return BadValue; pPriv->saturation = value; } else if (attribute == pAST->xvHue) { if ((value < -180) || (value > 180)) return BadValue; pPriv->hue = value; } else if (attribute == pAST->xvColorKey) { pPriv->colorKey = value; REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else if(attribute == pAST->xvGammaRed) { if((value < 100) || (value > 10000)) return BadValue; pPriv->gammaR = value; } else if(attribute == pAST->xvGammaGreen) { if((value < 100) || (value > 10000)) return BadValue; pPriv->gammaG = value; } else if(attribute == pAST->xvGammaBlue) { if((value < 100) || (value > 10000)) return BadValue; pPriv->gammaB = value; } else { return BadMatch; } return Success; } static int ASTGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data; ASTPtr pAST = ASTPTR(pScrn); xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTGetPortAttribute(),attribute=%x\n", attribute); if (attribute == pAST->xvBrightness) { *value = pPriv->brightness; } else if (attribute == pAST->xvContrast) { *value = pPriv->contrast; } else if (attribute == pAST->xvSaturation) { *value = pPriv->saturation; } else if (attribute == pAST->xvHue) { *value = pPriv->hue; } else if(attribute == pAST->xvGammaRed) { *value = pPriv->gammaR; } else if(attribute == pAST->xvGammaGreen) { *value = pPriv->gammaG; } else if(attribute == pAST->xvGammaBlue) { *value = pPriv->gammaB; } else if (attribute == pAST->xvColorKey) { *value = pPriv->colorKey; } else return BadMatch; return Success; } static void ASTQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data) { *p_w = drw_w; *p_h = drw_h; xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTQueryBestSize()\n"); /* TODO: report the HW limitation */ } static int ASTQueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets) { int pitchY, pitchUV; int size, sizeY, sizeUV; xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTQueryImageAttributes()\n"); if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; switch(id) { case PIXEL_FMT_YV12: *w = (*w + 7) & ~7; *h = (*h + 1) & ~1; pitchY = *w; pitchUV = *w >> 1; if(pitches) { pitches[0] = pitchY; pitches[1] = pitches[2] = pitchUV; } sizeY = pitchY * (*h); sizeUV = pitchUV * ((*h) >> 1); if(offsets) { offsets[0] = 0; offsets[1] = sizeY; offsets[2] = sizeY + sizeUV; } size = sizeY + (sizeUV << 1); break; case PIXEL_FMT_NV12: case PIXEL_FMT_NV21: *w = (*w + 7) & ~7; *h = (*h + 1) & ~1; pitchY = *w; pitchUV = *w; if(pitches) { pitches[0] = pitchY; pitches[1] = pitchUV; } sizeY = pitchY * (*h); sizeUV = pitchUV * ((*h) >> 1); if(offsets) { offsets[0] = 0; offsets[1] = sizeY; } size = sizeY + (sizeUV << 1); break; case PIXEL_FMT_YUY2: case PIXEL_FMT_UYVY: case PIXEL_FMT_YVYU: case PIXEL_FMT_RGB6: case PIXEL_FMT_RGB5: default: *w = (*w + 1) & ~1; pitchY = *w << 1; if(pitches) pitches[0] = pitchY; if(offsets) offsets[0] = 0; size = pitchY * (*h); break; } return size; } extern void ASTDisplayVideo(ScrnInfoPtr pScrn, ASTPortPrivPtr pPriv, RegionPtr clipBoxes, int id); static int ASTPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, int id, unsigned char* buf, short width, short height, Bool sync, RegionPtr clipBoxes, pointer data ) { ASTPtr pAST = ASTPTR(pScrn); ASTPortPrivPtr pPriv = (ASTPortPrivPtr)data; int i; int totalSize=0; xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTPutImage()\n"); /* int depth = pAST->CurrentLayout.bitsPerPixel >> 3; */ pPriv->drw_x = drw_x; pPriv->drw_y = drw_y; pPriv->drw_w = drw_w; pPriv->drw_h = drw_h; pPriv->src_x = src_x; pPriv->src_y = src_y; pPriv->src_w = src_w; pPriv->src_h = src_h; pPriv->id = id; pPriv->height = height; switch(id) { case PIXEL_FMT_YV12: case PIXEL_FMT_NV12: case PIXEL_FMT_NV21: pPriv->srcPitch = (width + 7) & ~7; totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */ break; case PIXEL_FMT_YUY2: case PIXEL_FMT_UYVY: case PIXEL_FMT_YVYU: case PIXEL_FMT_RGB6: case PIXEL_FMT_RGB5: default: pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */ totalSize = pPriv->srcPitch * height; } totalSize += 15; totalSize &= ~15; /* allocate memory */ if(totalSize == pPriv->fbSize) { ; } else { int lines, pitch, depth; BoxPtr pBox = NULL; pPriv->fbSize = totalSize; if(pPriv->fbAreaPtr) { xf86FreeOffscreenArea(pPriv->fbAreaPtr); } depth = (pScrn->bitsPerPixel + 7 ) / 8; pitch = pScrn->displayWidth * depth; lines = ((totalSize * 2) / pitch) + 1; xf86DrvMsg(pScrn->scrnIndex, X_INFO,"ASTPutImagelines=%x, pitch=%x, displayWidth=%x\n", lines, pitch, pScrn->displayWidth); pPriv->fbAreaPtr = xf86AllocateOffscreenArea(pScrn->pScreen, pScrn->displayWidth, lines, 0, NULL, NULL, NULL); if(!pPriv->fbAreaPtr) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Allocate video memory fails\n"); return BadAlloc; } pBox = &(pPriv->fbAreaPtr->box); pPriv->bufAddr[0] = (pBox->y1 * pitch) + (pBox->x1 * depth); pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Put Image, pPriv->bufAddr[0]=0x%08X\n", pPriv->bufAddr[0]); } /* copy data */ if(totalSize < 16) { #ifdef NewPath memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); #else /* NewPath */ switch(id) { case PIXEL_FMT_YUY2: case PIXEL_FMT_UYVY: case PIXEL_FMT_YVYU: { BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]); for(i=0; isrcPitch, buf + i*width*2, width*2); break; } default: memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); break; } /* switch */ #endif /* NewPath */ } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Put Image, copy buf\n"); #ifdef NewPath memcpy(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); #else /* NewPath */ switch(id) { case PIXEL_FMT_YUY2: case PIXEL_FMT_UYVY: case PIXEL_FMT_YVYU: { BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]); for(i=0; isrcPitch, buf + i*width*2, width*2); /*for(i=0; isrcPitch+j) = *(buf + width*i + j);*/ break; } default: { BYTE *Base = (BYTE *)(pAST->FBVirtualAddr + pPriv->bufAddr[pPriv->currentBuf]); int j; for(i=0; ipScreen, &pPriv->clip, clipBoxes)) { REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); } else { xf86XVFillKeyHelper(pScrn->pScreen, 0xFFFFFFFF, clipBoxes); } */ pPriv->currentBuf ^= 1; return Success; } static XF86VideoAdaptorPtr ASTSetupImageVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); ASTPtr pAST = ASTPTR(pScrn); XF86VideoAdaptorPtr adapt; ASTPortPrivPtr pPriv; if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(DevUnion) + sizeof(ASTPortPrivRec)))) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask | XvVideoMask; adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; adapt->name = "AST Video"; adapt->nEncodings = 1; adapt->pEncodings = &DummyEncoding; adapt->nFormats = NUM_FORMATS; adapt->pFormats = ASTFormats; adapt->nPorts = 1; adapt->pPortPrivates = (DevUnion*)(&adapt[1]); pPriv = (ASTPortPrivPtr)(&adapt->pPortPrivates[1]); adapt->pPortPrivates->ptr = (pointer)(pPriv); adapt->pAttributes = ASTAttributes; adapt->nAttributes = NUM_ATTRIBUTES; adapt->nImages = NUM_IMAGES; adapt->pImages = ASTImages; adapt->PutVideo = NULL; adapt->PutStill = NULL; adapt->GetVideo = NULL; adapt->GetStill = NULL; adapt->StopVideo = ASTStopVideo; adapt->SetPortAttribute = ASTSetPortAttribute; adapt->GetPortAttribute = ASTGetPortAttribute; adapt->QueryBestSize = ASTQueryBestSize; adapt->PutImage = ASTPutImage; adapt->QueryImageAttributes = ASTQueryImageAttributes; pPriv->currentBuf = 0; pPriv->linear = NULL; pPriv->fbAreaPtr = NULL; pPriv->fbSize = 0; pPriv->videoStatus = 0; pPriv->colorKey = 0x000101fe; pPriv->brightness = 0; pPriv->contrast = 128; pPriv->saturation = 0; pPriv->hue = 0; /* gotta uninit this someplace */ #if defined(REGION_NULL) REGION_NULL(pScreen, &pPriv->clip); #else REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); #endif pAST->adaptor = adapt; pAST->xvBrightness = MAKE_ATOM(astxvbrightness); pAST->xvContrast = MAKE_ATOM(astxvcontrast); pAST->xvColorKey = MAKE_ATOM(astxvcolorkey); pAST->xvSaturation = MAKE_ATOM(astxvsaturation); pAST->xvHue = MAKE_ATOM(astxvhue); pAST->xvGammaRed = MAKE_ATOM(astxvgammared); pAST->xvGammaGreen = MAKE_ATOM(astxvgammagreen); pAST->xvGammaBlue = MAKE_ATOM(astxvgammablue); return adapt; } void ASTInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr ASTAdaptor = NULL; int num_adaptors; ASTAdaptor = ASTSetupImageVideo(pScreen); num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); if(ASTAdaptor) { if(!num_adaptors) { num_adaptors = 1; adaptors = &ASTAdaptor; } else { newAdaptors = malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); if(newAdaptors) { memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); newAdaptors[num_adaptors] = ASTAdaptor; adaptors = newAdaptors; num_adaptors++; } } } if(num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); if(newAdaptors) free(newAdaptors); } #endif /* AstVideo */