diff options
Diffstat (limited to 'src/alp_driver.c')
-rw-r--r-- | src/alp_driver.c | 2151 |
1 files changed, 2151 insertions, 0 deletions
diff --git a/src/alp_driver.c b/src/alp_driver.c new file mode 100644 index 0000000..87f8e9b --- /dev/null +++ b/src/alp_driver.c @@ -0,0 +1,2151 @@ +/* + * Driver for CL-GD5480. + * Itai Nahshon. + * + * Support for the CL-GD7548: David Monniaux + * + * This is mainly a cut & paste from the MGA driver. + * Original autors and contributors list include: + * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel, + * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff, + * Guy DESBIEF + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_driver.c,v 1.28 2002/07/24 01:47:27 tsi Exp $ */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" + +/* All drivers need this */ +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* All drivers using the vgahw module need this */ +/* This driver needs to be modified to not use vgaHW for multihead operation */ +#include "vgaHW.h" + +#include "xf86RAC.h" +#include "xf86Resources.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +/* All drivers implementing backing store need this */ +#include "mibstore.h" + +#include "micmap.h" + +/* Needed by the Shadow Framebuffer */ +#include "shadowfb.h" + +/* Note: can HWCUR64 be set even though the hw cursor is disabled for + want of memory ? */ + +/* Framebuffer memory manager */ +#include "xf86fbman.h" + +#include "xf4bpp.h" +#include "xf1bpp.h" +#include "fb.h" + + +#include "xf86DDC.h" +#include "xf86int10.h" + +#include "cir.h" +#define _ALP_PRIVATE_ +#include "alp.h" + +#ifdef XvExtension +#include "xf86xv.h" +#include "Xv.h" +#endif + +#ifdef ALPPROBEI2C +/* For debugging... should go away. */ +static void AlpProbeI2C(int scrnIndex); +#endif + +/* + * Forward definitions for the functions that make up the driver. + */ + +/* Mandatory functions */ + +Bool AlpPreInit(ScrnInfoPtr pScrn, int flags); +Bool AlpScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); +Bool AlpEnterVT(int scrnIndex, int flags); +void AlpLeaveVT(int scrnIndex, int flags); +static Bool AlpCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool AlpSaveScreen(ScreenPtr pScreen, int mode); + +/* Required if the driver supports mode switching */ +Bool AlpSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +/* Required if the driver supports moving the viewport */ +void AlpAdjustFrame(int scrnIndex, int x, int y, int flags); + +/* Optional functions */ +void AlpFreeScreen(int scrnIndex, int flags); +int AlpValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags); +/* Internally used functions */ +static void AlpSave(ScrnInfoPtr pScrn); +static void AlpRestore(ScrnInfoPtr pScrn); +static Bool AlpModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); + +static void AlpProbeLCD(ScrnInfoPtr pScrn); + +static void AlpSetClock(CirPtr pCir, vgaHWPtr hwp, int freq); + +static void AlpOffscreenAccelInit(ScrnInfoPtr pScrn); + +static void AlpDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, int flags); + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +typedef enum { + OPTION_HW_CURSOR, + OPTION_PCI_RETRY, + OPTION_NOACCEL, + OPTION_MMIO, + OPTION_ROTATE, + OPTION_SHADOW_FB, + OPTION_MEMCFG1, + OPTION_MEMCFG2 +} CirOpts; + +static const OptionInfoRec CirOptions[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_MEMCFG1, "MemCFG1", OPTV_INTEGER, {0}, -1 }, + { OPTION_MEMCFG2, "MemCFG2", OPTV_INTEGER, {0}, -1 }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* 1/4bpp 8bpp 15/16bpp 24bpp 32bpp +static int unsupp_MaxClocks[] = { 0, 0, 0, 0, 0 }; */ +static int gd5430_MaxClocks[] = { 85500, 85500, 50000, 28500, 0 }; +static int gd5446_MaxClocks[] = { 135100, 135100, 85500, 85500, 0 }; +static int gd5480_MaxClocks[] = { 135100, 200000, 200000, 135100, 135100 }; +static int gd7548_MaxClocks[] = { 80100, 80100, 80100, 80100, 80100 }; + +/* + * List of symbols from other modules that this module references. This + * list is used to tell the loader that it is OK for symbols here to be + * unresolved providing that it hasn't been told that they haven't been + * told that they are essential via a call to xf86LoaderReqSymbols() or + * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about + * unresolved symbols that are not required. + */ + +static const char *vgahwSymbols[] = { + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWHandleColormaps", + "vgaHWInit", + "vgaHWLock", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWSetMmioFuncs", + "vgaHWSetStdFuncs", + "vgaHWUnlock", + NULL +}; + +static const char *miscfbSymbols[] = { + "xf1bppScreenInit", + "xf4bppScreenInit", + NULL +}; + +static const char *fbSymbols[] = { + "fbScreenInit", + "fbPictureInit", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAInit", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *int10Symbols[] = { + "xf86FreeInt10", + "xf86InitInt10", + NULL +}; + +static const char *shadowSymbols[] = { + "ShadowFBInit", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86DoEDID_DDC2", + "xf86SetDDCproperties", + NULL +}; + +static const char *i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + NULL +}; + +#ifdef XFree86LOADER + +#define ALP_MAJOR_VERSION 1 +#define ALP_MINOR_VERSION 0 +#define ALP_PATCHLEVEL 0 + +static MODULESETUPPROTO(alpSetup); + +static XF86ModuleVersionInfo alpVersRec = +{ + "cirrus_alpine", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + ALP_MAJOR_VERSION, ALP_MINOR_VERSION, ALP_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +/* + * This is the module init data. + * Its name has to be the driver name followed by ModuleData. + */ +XF86ModuleData cirrus_alpineModuleData = { &alpVersRec, alpSetup, NULL }; + +static pointer +alpSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + if (!setupDone) { + setupDone = TRUE; + LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, + miscfbSymbols, ramdacSymbols,int10Symbols, + ddcSymbols, i2cSymbols, shadowSymbols, NULL); + } + return (pointer)1; +} + +#endif /* XFree86LOADER */ + +const OptionInfoRec * +AlpAvailableOptions(int chipid) +{ + return CirOptions; +} + +ScrnInfoPtr +AlpProbe(int entity) +{ + ScrnInfoPtr pScrn = NULL; + + if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets, + NULL,NULL, NULL, NULL, NULL))) { + pScrn->PreInit = AlpPreInit; + pScrn->ScreenInit = AlpScreenInit; + pScrn->SwitchMode = AlpSwitchMode; + pScrn->AdjustFrame = AlpAdjustFrame; + pScrn->EnterVT = AlpEnterVT; + pScrn->LeaveVT = AlpLeaveVT; + pScrn->FreeScreen = AlpFreeScreen; + pScrn->ValidMode = AlpValidMode; + } + + return pScrn; +} + + +static Bool +AlpGetRec(ScrnInfoPtr pScrn) +{ +#ifdef ALP_DEBUG + ErrorF("AlpGetRec\n"); +#endif + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1); + ((CirPtr)pScrn->driverPrivate)->chip.alp = xnfcalloc(sizeof(AlpRec),1); + +#ifdef ALP_DEBUG + ErrorF("AlpGetRec 0x%x\n", CIRPTR(pScrn)); +#endif + return TRUE; +} + +static void +AlpFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + + +/* + * AlpCountRAM -- + * + * Counts amount of installed RAM + * + * XXX Can use options to configure memory on non-primary cards. + */ +static int +AlpCountRam(ScrnInfoPtr pScrn) +{ + CirPtr pCir = CIRPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + MessageType from; + int videoram = 0; + + /* Map the Alp memory and MMIO areas */ + pCir->FbMapSize = 1024*1024; /* XX temp */ + pCir->IoMapSize = 0x4000; /* 16K for moment */ + if (!CirMapMem(pCir, pScrn->scrnIndex)) + return 0; + + /* The 754x supports MMIO for the BitBlt engine but + not for the VGA registers */ + switch (pCir->Chipset) + { + case PCI_CHIP_GD7548: + break; + default: + if (pCir->UseMMIO) + vgaHWSetMmioFuncs(hwp, pCir->IOBase, -0x3C0); + } + + if (pCir->chip.alp->sr0f != (CARD32)-1) { + from = X_CONFIG; + hwp->writeSeq(hwp, 0x0F, pCir->chip.alp->sr0f); + } else { + from = X_PROBED; + pCir->chip.alp->sr0f = hwp->readSeq(hwp, 0x0F); + } + xf86DrvMsg(pScrn->scrnIndex, from, "Memory Config reg 1 is 0x%02X\n", + pCir->chip.alp->sr0f); + + switch (pCir->Chipset) { + case PCI_CHIP_GD5430: +/* case PCI_CHIP_GD5440: */ + switch (pCir->chip.alp->sr0f & 0x18) { + case 0x08: + videoram = 512; + break; + case 0x10: + videoram = 1024; + break; + case 0x18: + videoram = 2048; + break; + } + break; + + case PCI_CHIP_GD5434_4: + case PCI_CHIP_GD5434_8: + case PCI_CHIP_GD5436: + switch (pCir->chip.alp->sr0f & 0x18) { + case 0x10: + videoram = 1024; + break; + case 0x18: + videoram = 2048; + if (pCir->chip.alp->sr0f & 0x80) + videoram = 4096; + break; + } + + case PCI_CHIP_GD5446: + videoram = 1024; + + if (pCir->chip.alp->sr17 != (CARD32)-1) { + from = X_CONFIG; + hwp->writeSeq(hwp, 0x17, pCir->chip.alp->sr17); + } else { + from = X_PROBED; + pCir->chip.alp->sr17 = hwp->readSeq(hwp, 0x17); + } + xf86DrvMsg(pScrn->scrnIndex, from, "Memory Config reg 2 is 0x%02X\n", + pCir->chip.alp->sr17); + + if ((pCir->chip.alp->sr0f & 0x18) == 0x18) { + if (pCir->chip.alp->sr0f & 0x80) { + if (pCir->chip.alp->sr17 & 0x80) + videoram = 2048; + else if (pCir->chip.alp->sr17 & 0x02) + videoram = 3072; + else + videoram = 4096; + } else { + if ((pCir->chip.alp->sr17 & 80) == 0) + videoram = 2048; + } + } + break; + + case PCI_CHIP_GD5480: + if (pCir->chip.alp->sr17 != (CARD32)-1) { + from = X_CONFIG; + hwp->writeSeq(hwp, 0x17, pCir->chip.alp->sr17); + } else { + from = X_PROBED; + pCir->chip.alp->sr17 = hwp->readSeq(hwp, 0x17); + } + xf86DrvMsg(pScrn->scrnIndex, from, "Memory Config reg 2 is 0x%02X\n", + pCir->chip.alp->sr17); + videoram = 1024; + if ((pCir->chip.alp->sr0f & 0x18) == 0x18) { /* 2 or 4 MB */ + videoram = 2048; + if (pCir->chip.alp->sr0f & 0x80) /* Second bank enable */ + videoram = 4096; + } + if (pCir->chip.alp->sr17 & 0x80) + videoram <<= 1; + break; + + case PCI_CHIP_GD7548: + videoram = 1024; /* TODO: actual size */ + break; + } + + /* UNMap the Alp memory and MMIO areas */ + if (!CirUnmapMem(pCir, pScrn->scrnIndex)) + return 0; + vgaHWSetStdFuncs(hwp); + + return videoram; +} + + +/* + * GetAccelPitchValues - + * + * This function returns a list of display width (pitch) values that can + * be used in accelerated mode. + */ +static int * +GetAccelPitchValues(ScrnInfoPtr pScrn) +{ + int *linePitches = NULL; + int i, n = 0; + CirPtr pCir = CIRPTR(pScrn); + + /* XXX ajv - 512, 576, and 1536 may not be supported + line pitches. see sdk pp 4-59 for more + details. Why anyone would want less than 640 is + bizarre. (maybe lots of pixels tall?) */ + + /* The only line pitches the accelerator supports */ +#if 1 + int accelWidths[] = { 640, 768, 800, 960, 1024, 1152, 1280, + 1600, 1920, 2048, 0 }; +#else + int accelWidths[] = { 512, 576, 640, 768, 800, 960, 1024, 1152, + 1280, 1536, 1600, 1920, 2048, 0 }; +#endif + + for (i = 0; accelWidths[i] != 0; i++) { + if (accelWidths[i] % pCir->Rounding == 0) { + n++; + linePitches = xnfrealloc(linePitches, n * sizeof(int)); + linePitches[n - 1] = accelWidths[i]; + } + } + /* Mark the end of the list */ + if (n > 0) { + linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int)); + linePitches[n] = 0; + } + return linePitches; +} + + +/* Mandatory */ +Bool +AlpPreInit(ScrnInfoPtr pScrn, int flags) +{ + CirPtr pCir; + vgaHWPtr hwp; + MessageType from, from1; + int i; + ClockRangePtr clockRanges; + char *s; + xf86Int10InfoPtr pInt = NULL; + + if (flags & PROBE_DETECT) { + cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); + return TRUE; + } + +#ifdef ALP_DEBUG + ErrorF("AlpPreInit\n"); +#endif + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + /* + * Allocate a vgaHWRec + */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + /* Allocate the AlpRec driverPrivate */ + if (!AlpGetRec(pScrn)) + return FALSE; + + pCir = CIRPTR(pScrn); + pCir->pScrn = pScrn; + pCir->PIOReg = hwp->PIOOffset + 0x3CE; + + /* Get the entity, and make sure it is PCI. */ + pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pCir->pEnt->location.type != BUS_PCI) + return FALSE; + + pCir->Chipset = pCir->pEnt->chipset; + /* Find the PCI info for this screen */ + pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index); + pCir->PciTag = pciTag(pCir->PciInfo->bus, + pCir->PciInfo->device, + pCir->PciInfo->func); + + if (xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols,NULL); + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); + pInt = xf86InitInt10(pCir->pEnt->index); + xf86FreeInt10(pInt); + /* + * This is a hack: We restore the PCI base regs as some Colorgraphic + * BIOSes tend to mess them up + */ + pciWriteLong(pCir->PciTag,0x10,pCir->PciInfo->memBase[0]); + pciWriteLong(pCir->PciTag,0x14,pCir->PciInfo->memBase[1]); + + } + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * The first thing we should figure out is the depth, bpp, etc. + * Our default depth is 8, so pass it to the helper function. + * We support both 24bpp and 32bpp layouts, so indicate that. + */ + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb | + SupportConvert32to24 | PreferConvert32to24)) { + return FALSE; + } else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 1: + case 4: + case 8: + case 15: + case 16: + case 24: + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + return FALSE; + } else { + /* XXX check that weight returned is supported */ + ; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) { + return FALSE; + } + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(pCir->Options = xalloc(sizeof(CirOptions)))) + return FALSE; + memcpy(pCir->Options, CirOptions, sizeof(CirOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options); + + if (!xf86IsPrimaryPci(pCir->PciInfo) + && !(pInt || (xf86IsOptionSet(pCir->Options,OPTION_MEMCFG1) + && xf86IsOptionSet(pCir->Options,OPTION_MEMCFG2)))) + return FALSE; + + if (pScrn->depth == 8) + pScrn->rgbBits = 6; + + from = X_DEFAULT; + pCir->HWCursor = FALSE; + if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, &pCir->HWCursor)) + from = X_CONFIG; + + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pCir->HWCursor ? "HW" : "SW"); + if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) { + pCir->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + if(pScrn->bitsPerPixel < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot use accelerations in less than 8 bpp\n"); + pCir->NoAccel = TRUE; + } + + /* + * Set the ChipRev, allowing config file entries to + * override. + */ + if (pCir->pEnt->device->chipRev >= 0) { + pCir->ChipRev = pCir->pEnt->device->chipRev; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pCir->ChipRev); + } else { + pCir->ChipRev = pCir->PciInfo->chipRev; + } + + /* Find the frame buffer base address */ + if (pCir->pEnt->device->MemBase != 0) { + if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->MemBase)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MemBase 0x%08lX doesn't match any PCI base register.\n", + pCir->pEnt->device->MemBase); + return FALSE; + } + pCir->FbAddress = pCir->pEnt->device->MemBase; + from = X_CONFIG; + } else { + if (pCir->PciInfo->memBase[0] != 0) { + /* 5446B and 5480 use mask of 0xfe000000. + 5446A uses 0xff000000. */ + pCir->FbAddress = pCir->PciInfo->memBase[0] & 0xff000000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid FB address in PCI config space\n"); + AlpFreeRec(pScrn); + return FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pCir->FbAddress); + + if (pCir->pEnt->device->IOBase != 0) { + /* Require that the config file value matches one of the PCI values. */ + if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->IOBase)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "IOBase 0x%08lX doesn't match any PCI base register.\n", + pCir->pEnt->device->IOBase); + return FALSE; + } + pCir->IOAddress = pCir->pEnt->device->IOBase; + from = X_CONFIG; + } else { + if (pCir->PciInfo->memBase[1] != 0) { + pCir->IOAddress = pCir->PciInfo->memBase[1] & 0xfffff000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid MMIO address in PCI config space\n"); + /* 5446 rev A do not use a separate MMIO segment */ + /* We do not really need that YET. */ + } + } + + /* User options can override the MMIO default */ +#if 0 + /* Will we ever support MMIO on 5446A or older? */ + if (xf86ReturnOptValBool(pCir->Options, OPTION_MMIO, FALSE)) { + pCir->UseMMIO = TRUE; + from = X_CONFIG; + } +#endif + if (!xf86ReturnOptValBool(pCir->Options, OPTION_MMIO, TRUE)) { + pCir->UseMMIO = FALSE; + from1 = X_CONFIG; + } else if (pCir->IOAddress) { + /* Default to MMIO if we have a separate IOAddress and + not in monochrome mode (IO 0x3Bx is not relocated!) */ + if (pScrn->bitsPerPixel != 1) { + pCir->UseMMIO = TRUE; + from1 = X_PROBED; + } else { + pCir->UseMMIO = FALSE; + from1 = X_PROBED; + } + } else { + pCir->UseMMIO = FALSE; + from1 = X_PROBED; + } + + if (pCir->UseMMIO) { + xf86DrvMsg(pScrn->scrnIndex, from1, "Using MMIO\n"); + xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", + (unsigned long)pCir->IOAddress); + } else + xf86DrvMsg(pScrn->scrnIndex, from1, "Not Using MMIO\n"); + + /* + * XXX Check if this is correct + */ + if (!pCir->UseMMIO) { + pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT | RAC_FB; + xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr); + } else { + xf86SetOperatingState(resVga, pCir->pEnt->index, ResUnusedOpr); + } + + /* Register the PCI-assigned resources. */ + if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); + return FALSE; + } + + if (!xf86LoadSubModule(pScrn, "i2c")) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(i2cSymbols,NULL); + + if (!xf86LoadSubModule(pScrn, "ddc")) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ddcSymbols, NULL); + + if(!AlpI2CInit(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I2C initialization failed\n"); + } + else + xf86SetDDCproperties(pScrn,xf86PrintEDID( + xf86DoEDID_DDC2(pScrn->scrnIndex,pCir->I2CPtr1))); + + /* Probe the possible LCD display */ + AlpProbeLCD(pScrn); + +#ifdef CIRPROBEI2C + CirProbeI2C(pScrn->scrnIndex); +#endif + + /* The gamma fields must be initialised when using the new cmap code */ + if (pScrn->depth > 1) { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) + return FALSE; + } + + /* XXX If UseMMIO == TRUE and for any reason we cannot do MMIO, + abort here */ + + if (xf86GetOptValBool(pCir->Options, + OPTION_SHADOW_FB,&pCir->shadowFB)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", + pCir->shadowFB ? "enabled" : "disabled"); + + if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) { + if(!xf86NameCmp(s, "CW")) { + /* accel is disabled below for shadowFB */ + pCir->shadowFB = TRUE; + pCir->rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise - acceleration disabled\n"); + } else if(!xf86NameCmp(s, "CCW")) { + pCir->shadowFB = TRUE; + pCir->rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" + "counter clockwise - acceleration disabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } + if (pCir->shadowFB && (pScrn->depth < 8)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "shadowFB not supported at this depth.\n"); + pCir->shadowFB = FALSE; + pCir->rotate = 0; + } + + if (pCir->shadowFB && !pCir->NoAccel) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW acceleration not supported with \"shadowFB\".\n"); + pCir->NoAccel = TRUE; + } + + if (pCir->rotate && pCir->HWCursor) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW cursor not supported with \"rotate\".\n"); + pCir->HWCursor = FALSE; + } + + /* XXX We do not know yet how to configure memory on this card. + Use options MemCFG1 and MemCFG2 to set registers SR0F and + SR17 before trying to count ram size. */ + + pCir->chip.alp->sr0f = (CARD32)-1; + pCir->chip.alp->sr17 = (CARD32)-1; + + (void) xf86GetOptValULong(pCir->Options, OPTION_MEMCFG1, (unsigned long *)&pCir->chip.alp->sr0f); + (void) xf86GetOptValULong(pCir->Options, OPTION_MEMCFG2, (unsigned long *)&pCir->chip.alp->sr17); + /* + * If the user has specified the amount of memory in the XF86Config + * file, we respect that setting. + */ + if (pCir->pEnt->device->videoRam != 0) { + pScrn->videoRam = pCir->pEnt->device->videoRam; + pCir->IoMapSize = 0x4000; /* 16K for moment */ + from = X_CONFIG; + } else { + pScrn->videoRam = AlpCountRam(pScrn); + from = X_PROBED; + } + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", pScrn->videoRam); + + pCir->FbMapSize = pScrn->videoRam * 1024; + + /* properties */ + pCir->properties = 0; + + if ((pCir->chip.alp->sr0f & 0x18) > 0x8) + pCir->properties |= HWCUR64; + + switch (pCir->Chipset) { + case PCI_CHIP_GD7548: + pCir->properties |= HWCUR64; + pCir->properties |= ACCEL_AUTOSTART; + break; + case PCI_CHIP_GD5436: + case PCI_CHIP_GD5480: + pCir->properties |= ACCEL_AUTOSTART; + break; + default: + break; + } + + /* We use a programmable clock */ + pScrn->progClock = TRUE; + + /* XXX Set HW cursor use */ + + /* Set the min pixel clock */ + pCir->MinClock = 12000; /* XXX Guess, need to check this */ + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", + pCir->MinClock / 1000); + /* + * If the user has specified ramdac speed in the XF86Config + * file, we respect that setting. + */ + if (pCir->pEnt->device->dacSpeeds[0]) { + ErrorF("Do not specily a Clocks line for Cirrus chips\n"); + return FALSE; + } else { + int speed; + int *p = NULL; + switch (pCir->Chipset) { + case PCI_CHIP_GD5430: + case PCI_CHIP_GD5434_4: + case PCI_CHIP_GD5434_8: + case PCI_CHIP_GD5436: + /* case PCI_CHIP_GD5440: */ + p = gd5430_MaxClocks; + break; + case PCI_CHIP_GD5446: + p = gd5446_MaxClocks; + break; + case PCI_CHIP_GD5480: + p = gd5480_MaxClocks; + break; + case PCI_CHIP_GD7548: + p = gd7548_MaxClocks; + break; + } + if (!p) + return FALSE; + switch(pScrn->bitsPerPixel) { + case 1: + case 4: + speed = p[0]; + break; + case 8: + speed = p[1]; + break; + case 15: + case 16: + speed = p[2]; + break; + case 24: + speed = p[3]; + break; + case 32: + speed = p[4]; + break; + default: + /* Should not get here */ + speed = 0; + break; + } + pCir->MaxClock = speed; + from = X_PROBED; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", + pCir->MaxClock / 1000); + + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = pCir->MinClock; + clockRanges->maxClock = pCir->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = FALSE; /* XXX check this */ + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ + clockRanges->ClockMulFactor = 1; + clockRanges->ClockDivFactor = 1; + clockRanges->PrivFlags = 0; + + switch (pCir->Chipset) + { + case PCI_CHIP_GD7548: + pCir->Rounding = 1; + break; + + default: + pCir->Rounding = 128 >> pCir->BppShift; + } + +#if 0 + if (pCir->Chipset != PCI_CHIP_GD5446 && + pCir->Chipset != PCI_CHIP_GD5480) { + /* XXX Kludge */ + pCir->NoAccel = TRUE; + } +#endif + + /* + * xf86ValidateModes will check that the mode HTotal and VTotal values + * don't exceed the chipset's limit if pScrn->maxHValue and + * pScrn->maxVValue are set. Since our AlpValidMode() already takes + * care of this, we don't worry about setting them here. + */ + + /* Select valid modes from those available */ + if (pCir->NoAccel) { + /* + * XXX Assuming min pitch 256, max 2048 + * XXX Assuming min height 128, max 2048 + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 2048, + pCir->Rounding * pScrn->bitsPerPixel, 128, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, + pCir->FbMapSize, + LOOKUP_BEST_REFRESH); + } else { + /* + * XXX Assuming min height 128, max 2048 + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + GetAccelPitchValues(pScrn), 0, 0, + pCir->Rounding * pScrn->bitsPerPixel, 128, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, + pCir->FbMapSize, + LOOKUP_BEST_REFRESH); + } + if (i == -1) { + AlpFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + AlpFreeRec(pScrn); + return FALSE; + } + + /* + * Set the CRTC parameters for all of the modes based on the type + * of mode, and the chipset's interlace requirements. + * + * Calling this is required if the mode->Crtc* values are used by the + * driver and if the driver doesn't provide code to set them. They + * are not pre-initialised at all. + */ + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch (pScrn->bitsPerPixel) { + case 1: + if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymbols("xf1bppScreenInit",NULL); + break; + case 4: + if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymbols("xf4bppScreenInit",NULL); + break; + case 8: + case 16: + case 24: + case 32: + if (xf86LoadSubModule(pScrn, "fb") == NULL) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(fbSymbols, NULL); + break; + } + + /* Load XAA if needed */ + if (!pCir->NoAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + /* Load ramdac if needed */ + if (pCir->HWCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + if (pCir->shadowFB) { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + AlpFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + return TRUE; +} + +/* + * This function saves the video state. + */ +static void +AlpSave(ScrnInfoPtr pScrn) +{ + CirPtr pCir = CIRPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + +#ifdef ALP_DEBUG + ErrorF("AlpSave\n"); +#endif + vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL); + + pCir->chip.alp->ModeReg.ExtVga[CR1A] = pCir->chip.alp->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A); + pCir->chip.alp->ModeReg.ExtVga[CR1B] = pCir->chip.alp->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B); + pCir->chip.alp->ModeReg.ExtVga[CR1D] = pCir->chip.alp->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D); + pCir->chip.alp->ModeReg.ExtVga[SR07] = pCir->chip.alp->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07); + pCir->chip.alp->ModeReg.ExtVga[SR0E] = pCir->chip.alp->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E); + pCir->chip.alp->ModeReg.ExtVga[SR12] = pCir->chip.alp->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12); + pCir->chip.alp->ModeReg.ExtVga[SR13] = pCir->chip.alp->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13); + pCir->chip.alp->ModeReg.ExtVga[SR17] = pCir->chip.alp->SavedReg.ExtVga[SR17] = hwp->readSeq(hwp, 0x17); + pCir->chip.alp->ModeReg.ExtVga[SR1E] = pCir->chip.alp->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E); + pCir->chip.alp->ModeReg.ExtVga[SR21] = pCir->chip.alp->SavedReg.ExtVga[SR21] = hwp->readSeq(hwp, 0x21); + pCir->chip.alp->ModeReg.ExtVga[SR2D] = pCir->chip.alp->SavedReg.ExtVga[SR2D] = hwp->readSeq(hwp, 0x2D); + pCir->chip.alp->ModeReg.ExtVga[GR17] = pCir->chip.alp->SavedReg.ExtVga[GR17] = hwp->readGr(hwp, 0x17); + pCir->chip.alp->ModeReg.ExtVga[GR18] = pCir->chip.alp->SavedReg.ExtVga[GR18] = hwp->readGr(hwp, 0x18); + /* The first 4 reads are for the pixel mask register. After 4 times that + this register is accessed in succession reading/writing this address + accesses the HDR. */ + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + pCir->chip.alp->ModeReg.ExtVga[HDR] = pCir->chip.alp->SavedReg.ExtVga[HDR] = hwp->readDacMask(hwp); +} + +/* XXX */ +static void +AlpFix1bppColorMap(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); +/* In 1 bpp we have color 0 at LUT 0 and color 1 at LUT 0x3f. + This makes white and black look right (otherwise they were both + black. I'm sure there's a better way to do that, just lazy to + search the docs. */ + + hwp->writeDacWriteAddr(hwp, 0x00); + hwp->writeDacData(hwp, 0x00); hwp->writeDacData(hwp, 0x00); hwp->writeDacData(hwp, 0x00); + hwp->writeDacWriteAddr(hwp, 0x3F); + hwp->writeDacData(hwp, 0x3F); hwp->writeDacData(hwp, 0x3F); hwp->writeDacData(hwp, 0x3F); +} + +static void +alpRestore(vgaHWPtr hwp, AlpRegPtr cirReg) +{ + hwp->writeCrtc(hwp, 0x1A, cirReg->ExtVga[CR1A]); + hwp->writeCrtc(hwp, 0x1B, cirReg->ExtVga[CR1B]); + hwp->writeCrtc(hwp, 0x1D, cirReg->ExtVga[CR1D]); + hwp->writeSeq(hwp, 0x07, cirReg->ExtVga[SR07]); + hwp->writeSeq(hwp, 0x0E, cirReg->ExtVga[SR0E]); + hwp->writeSeq(hwp, 0x12, cirReg->ExtVga[SR12]); + hwp->writeSeq(hwp, 0x13, cirReg->ExtVga[SR13]); + hwp->writeSeq(hwp, 0x17, cirReg->ExtVga[SR17]); + hwp->writeSeq(hwp, 0x1E, cirReg->ExtVga[SR1E]); + hwp->writeSeq(hwp, 0x21, cirReg->ExtVga[SR21]); + hwp->writeSeq(hwp, 0x2D, cirReg->ExtVga[SR2D]); + hwp->writeGr(hwp, 0x17, cirReg->ExtVga[GR17]); + hwp->writeGr(hwp, 0x18, cirReg->ExtVga[GR18]); + /* The first 4 reads are for the pixel mask register. After 4 times that + this register is accessed in succession reading/writing this address + accesses the HDR. */ + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + hwp->readDacMask(hwp); + hwp->writeDacMask(hwp, cirReg->ExtVga[HDR ]); +} + + +/* + * Initialise a new mode. This is currently still using the old + * "initialise struct, restore/write struct to HW" model. That could + * be changed. + * Why?? (EE) + */ + +static Bool +AlpModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp; + vgaRegPtr vgaReg; + CirPtr pCir; + int depthcode; + int width; + Bool HDiv2 = FALSE, VDiv2 = FALSE; + +#ifdef ALP_DEBUG + ErrorF("AlpModeInit %d bpp, %d %d %d %d %d %d %d %d %d\n", + pScrn->bitsPerPixel, + mode->Clock, + mode->HDisplay, + mode->HSyncStart, + mode->HSyncEnd, + mode->HTotal, + mode->VDisplay, + mode->VSyncStart, + mode->VSyncEnd, + mode->VTotal); + + ErrorF("AlpModeInit: depth %d bits\n", pScrn->depth); +#endif + + pCir = CIRPTR(pScrn); + hwp = VGAHWPTR(pScrn); + vgaHWUnlock(hwp); + + pCir->pitch = pScrn->displayWidth * pScrn->bitsPerPixel >> 3; + + depthcode = pScrn->depth; + if (pScrn->bitsPerPixel == 32) + depthcode = 32; + + if ((pCir->Chipset == PCI_CHIP_GD5480 && mode->Clock > 135100) || + (pCir->Chipset == PCI_CHIP_GD5446 && mode->Clock > 85500)) { + /* The actual DAC register value is set later. */ + /* The CRTC is clocked at VCLK / 2, so we must half the */ + /* horizontal timings. */ + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay >>= 1; + mode->CrtcHSyncStart >>= 1; + mode->CrtcHTotal >>= 1; + mode->CrtcHSyncEnd >>= 1; + mode->SynthClock >>= 1; + mode->CrtcHAdjusted = TRUE; + } + depthcode += 64; + HDiv2 = TRUE; + } + + if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) { + /* For non-interlaced vertical timing >= 1024, the vertical timings */ + /* are divided by 2 and VGA CRTC 0x17 bit 2 is set. */ + if (!mode->CrtcVAdjusted) { + mode->CrtcVDisplay >>= 1; + mode->CrtcVSyncStart >>= 1; + mode->CrtcVSyncEnd >>= 1; + mode->CrtcVTotal >>= 1; + mode->CrtcVAdjusted = TRUE; + } + VDiv2 = TRUE; + } + + /* Initialise the ModeReg values */ + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + + /* Turn off HW cursor, gamma correction, overscan color protect. */ + pCir->chip.alp->ModeReg.ExtVga[SR12] = 0; + if ((pCir->properties & HWCUR64) == HWCUR64) + { + pCir->chip.alp->ModeReg.ExtVga[SR12] = 0x4; + switch (pCir->Chipset) + { + case PCI_CHIP_GD7548: + pCir->chip.alp->ModeReg.ExtVga[SR21] |= 0x10; + break; + } + + } + else + pCir->chip.alp->ModeReg.ExtVga[SR12] = 0; + + + if(VDiv2) + hwp->ModeReg.CRTC[0x17] |= 0x04; + +#ifdef ALP_DEBUG + ErrorF("SynthClock = %d\n", mode->SynthClock); +#endif + + /* Disable DCLK pin driver, interrupts. */ + pCir->chip.alp->ModeReg.ExtVga[GR17] |= 0x08; + pCir->chip.alp->ModeReg.ExtVga[GR17] &= ~0x04; + + vgaReg = &hwp->ModeReg; + + pCir->chip.alp->ModeReg.ExtVga[HDR] = 0; + /* Enable linear mode and high-res packed pixel mode */ + pCir->chip.alp->ModeReg.ExtVga[SR07] &= 0xe0; +#ifdef ALP_DEBUG + ErrorF("depthcode = %d\n", depthcode); +#endif + + if (pScrn->bitsPerPixel == 1) { + hwp->IOBase = 0x3B0; + hwp->ModeReg.MiscOutReg &= ~0x01; + } else { + hwp->IOBase = 0x3D0; + hwp->ModeReg.MiscOutReg |= 0x01; + } + + switch (depthcode) { + case 1: + case 4: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x10; + break; + case 8: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x11; + break; + case 64+8: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x17; + break; + case 15: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x17; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC0; + break; + case 64+15: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x19; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC0; + break; + case 16: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x17; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC1; + break; + case 64+16: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x19; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC1; + break; + case 24: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x15; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC5; + break; + case 32: + pCir->chip.alp->ModeReg.ExtVga[SR07] |= 0x19; + pCir->chip.alp->ModeReg.ExtVga[HDR ] = 0xC5; + break; + default: + ErrorF("X11: Internal error: AlpModeInit: Cannot Initialize display to requested mode\n"); +#ifdef ALP_DEBUG + ErrorF("AlpModeInit returning FALSE on depthcode %d\n", depthcode); +#endif + return FALSE; + } + if (HDiv2) + pCir->chip.alp->ModeReg.ExtVga[GR18] |= 0x20; + else + pCir->chip.alp->ModeReg.ExtVga[GR18] &= ~0x20; + + + /* Some extra init stuff */ + switch (pCir->Chipset) + { + case PCI_CHIP_GD7548: + /* Do we use MMIO ? + If we do and we are on a 7548, we need to tell the board + that we want MMIO. */ + if (pCir->UseMMIO) + { + pCir->chip.alp->ModeReg.ExtVga[SR17] = + (pCir->chip.alp->ModeReg.ExtVga[SR17] & ~0x40) | 4; + ErrorF("UseMMIO: SR17=%2X\n", (int) (pCir->chip.alp->ModeReg.ExtVga[SR17])); + } +#ifdef ALP_SETUP + ErrorF("SR2D=%2X\n", (int) (pCir->chip.alp->ModeReg.ExtVga[SR17])); +#endif + pCir->chip.alp->ModeReg.ExtVga[SR2D] |= 0xC0; + break; + } + + /* No support for interlace (yet) */ + pCir->chip.alp->ModeReg.ExtVga[CR1A] = 0x00; + + width = pScrn->displayWidth * pScrn->bitsPerPixel / 8; + if (pScrn->bitsPerPixel == 1) + width <<= 2; + hwp->ModeReg.CRTC[0x13] = width >> 3; + /* Offset extension (see CR13) */ + pCir->chip.alp->ModeReg.ExtVga[CR1B] &= 0xAF; + pCir->chip.alp->ModeReg.ExtVga[CR1B] |= (width >> (3+4)) & 0x10; + pCir->chip.alp->ModeReg.ExtVga[CR1B] |= (width >> (3+3)) & 0x40; + pCir->chip.alp->ModeReg.ExtVga[CR1B] |= 0x22; + + /* Programme the registers */ + vgaHWProtect(pScrn, TRUE); + hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg); + alpRestore(hwp,&pCir->chip.alp->ModeReg); + AlpSetClock(pCir, hwp, mode->SynthClock); + + vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP); + + /* XXX */ + if (pScrn->bitsPerPixel == 1) + AlpFix1bppColorMap(pScrn); + + vgaHWProtect(pScrn, FALSE); + + return TRUE; +} + +/* + * Restore the initial (text) mode. + */ +static void +AlpRestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp; + vgaRegPtr vgaReg; + CirPtr pCir; + AlpRegPtr alpReg; + +#ifdef ALP_DEBUG + ErrorF("AlpRestore\n"); +#endif + + hwp = VGAHWPTR(pScrn); + pCir = CIRPTR(pScrn); + vgaReg = &hwp->SavedReg; + alpReg = &pCir->chip.alp->SavedReg; + + vgaHWProtect(pScrn, TRUE); + + alpRestore(hwp,alpReg); + + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + vgaHWProtect(pScrn, FALSE); +} + +/* Mandatory */ + +/* This gets called at the start of each server generation */ + +Bool +AlpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + CirPtr pCir; + AlpPtr pAlp; + int i, ret; + int init_picture = 0; + VisualPtr visual; + int displayWidth,width,height; + unsigned char * FbBase = NULL; + int cursor_size = 0; + +#ifdef ALP_DEBUG + ErrorF("AlpScreenInit\n"); +#endif + + /* + * First get the ScrnInfoRec + */ + pScrn = xf86Screens[pScreen->myNum]; + + hwp = VGAHWPTR(pScrn); + pCir = CIRPTR(pScrn); + pAlp = ALPPTR(pCir); + + /* Map the VGA memory when the primary video */ + if (!vgaHWMapMem(pScrn)) + return FALSE; + + /* Map the Alp memory and MMIO areas */ + if (!CirMapMem(pCir, pScrn->scrnIndex)) + return FALSE; + + /* The 754x supports MMIO for the BitBlt engine but + not for the VGA registers */ + switch (pCir->Chipset) + { + case PCI_CHIP_GD7548: + break; + default: + if(pCir->UseMMIO) + vgaHWSetMmioFuncs(hwp, pCir->IOBase, -0x3C0); + } + + vgaHWGetIOBase(hwp); + + /* Save the current state */ + AlpSave(pScrn); + + /* Initialise the first mode */ + if (!AlpModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + /* Set the viewport */ + AlpAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + */ + + /* + * Reset the visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + + miSetPixmapDepths (); + + displayWidth = pScrn->displayWidth; + if (pCir->rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } else { + width = pScrn->virtualX; + height = pScrn->virtualY; + } + + if(pCir->shadowFB) { + pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + pCir->ShadowPtr = xalloc(pCir->ShadowPitch * height); + displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FbBase = pCir->ShadowPtr; + } else { + pCir->ShadowPtr = NULL; + FbBase = pCir->FbBase; + } + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + + switch (pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FbBase, + width, height, + pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FbBase, + width, height, + pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 8: + case 16: + case 24: + case 32: + ret = fbScreenInit(pScreen, FbBase, + width,height, + pScrn->xDpi, pScrn->yDpi, + displayWidth,pScrn->bitsPerPixel); + init_picture = 1; + break; + default: + xf86DrvMsg(scrnIndex, X_ERROR, + "X11: Internal error: invalid bpp (%d) in AlpScreenInit\n", + pScrn->bitsPerPixel); + ret = FALSE; + break; + } + if (!ret) + return FALSE; + +#ifdef ALP_DEBUG + ErrorF("AlpScreenInit after depth dependent init\n"); +#endif + + /* Override the default mask/offset settings */ + if (pScrn->bitsPerPixel > 8) { + for (i = 0; i < pScreen->numVisuals; i++) { + visual = &pScreen->visuals[i]; + 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; + } + } + } + + /* must be after RGB ordering fixed */ + if (init_picture) + fbPictureInit (pScreen, 0, 0); + + miInitializeBackingStore(pScreen); + + /* + * Set initial black & white colourmap indices. + */ + xf86SetBlackWhitePixels(pScreen); + + /* + Allocation of off-screen memory to various stuff + (hardware cursor, 8x8 mono pattern...) + Allocation goes top-down in memory, since the cursor + *must* be in the last videoram locations + */ + pCir->offscreen_offset = pScrn->videoRam*1024; + pCir->offscreen_size = pScrn->videoRam * 1024 - pScrn->virtualY * + (BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel)); + +#ifdef ALP_DEBUG + ErrorF("offscreen_offset=%d, offscreen_size=%d\n", + pCir->offscreen_offset, pCir->offscreen_size); +#endif + + /* Initialise cursor functions */ + if (pCir->HWCursor) { /* Initialize HW cursor layer */ + + if ((pCir->properties & HWCUR64) + && (pCir->offscreen_size >= 64*8*2)) { + cursor_size = 64; + pCir->offscreen_size -= 64*8*2; + pCir->offscreen_offset -= 64*8*2; + } else if (pCir->offscreen_size >= 32*4*2) { + cursor_size = 32; + pCir->offscreen_size -= 32*8*2; + pCir->offscreen_offset -= 32*8*2; + } + } + + if (!pCir->NoAccel) { /* Initialize XAA functions */ + AlpOffscreenAccelInit(pScrn); + if (!(pCir->UseMMIO ? AlpXAAInitMMIO(pScreen) : + AlpXAAInit(pScreen))) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not initialize XAA\n"); + } + +#if 1 + pCir->DGAModeInit = AlpModeInit; + if (!CirDGAInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "DGA initialization failed\n"); +#endif + xf86SetSilkenMouse(pScreen); + + /* Initialise cursor functions */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + if (pCir->HWCursor) { + if (!AlpHWCursorInit(pScreen, cursor_size)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); +#ifdef ALP_DEBUG + ErrorF("AlpHWCursorInit() complete\n"); +#endif + } + + if (pCir->shadowFB) { + RefreshAreaFuncPtr refreshArea = cirRefreshArea; + + if(pCir->rotate) { + if (!pCir->PointerMoved) { + pCir->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = cirPointerMoved; + } + + switch(pScrn->bitsPerPixel) { + case 8: refreshArea = cirRefreshArea8; break; + case 16: refreshArea = cirRefreshArea16; break; + case 24: refreshArea = cirRefreshArea24; break; + case 32: refreshArea = cirRefreshArea32; break; + } + } + + ShadowFBInit(pScreen, refreshArea); + } + + /* Initialise default colourmap */ + if (!miCreateDefColormap(pScreen)) + return FALSE; + + if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8) + vgaHWHandleColormaps(pScreen); + + xf86DPMSInit(pScreen, AlpDisplayPowerManagementSet, 0); + + pScrn->memPhysBase = pCir->FbAddress; + pScrn->fbOffset = 0; + +#ifdef XvExtension + { + XF86VideoAdaptorPtr *ptr; + int n; + + n = xf86XVListGenericAdaptors(pScrn,&ptr); + if (n) + xf86XVScreenInit(pScreen, ptr, n); + } +#endif + + /* + * Wrap the CloseScreen vector and set SaveScreen. + */ + pScreen->SaveScreen = AlpSaveScreen; + pCir->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = AlpCloseScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + + /* Done */ + return TRUE; +} + + +/* Usually mandatory */ +Bool +AlpSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return AlpModeInit(xf86Screens[scrnIndex], mode); +} + + +/* + * This function is used to initialize the Start Address - the first + * displayed location in the video memory. + */ +/* Usually mandatory */ +void +AlpAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn; + int Base, tmp; + vgaHWPtr hwp; + + pScrn = xf86Screens[scrnIndex]; + hwp = VGAHWPTR(pScrn); + + Base = ((y * pScrn->displayWidth + x) / 8); + if (pScrn->bitsPerPixel != 1) + Base *= (pScrn->bitsPerPixel/4); + +#ifdef ALP_DEBUG + ErrorF("AlpAdjustFrame %d %d 0x%x %d %x\n", x, y, flags, Base, Base); +#endif + + if ((Base & ~0x000FFFFF) != 0) { + ErrorF("X11: Internal error: AlpAdjustFrame: cannot handle overflow\n"); + return; + } + + hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xff); + hwp->writeCrtc(hwp, 0x0D, Base & 0xff); + tmp = hwp->readCrtc(hwp, 0x1B); + tmp &= 0xF2; + tmp |= (Base >> 16) & 0x01; + tmp |= (Base >> 15) & 0x0C; + hwp->writeCrtc(hwp, 0x1B, tmp); + tmp = hwp->readCrtc(hwp, 0x1D); + tmp &= 0x7F; + tmp |= (Base >> 12) & 0x80; + hwp->writeCrtc(hwp, 0x1D, tmp); +} + +/* + * This is called when VT switching back to the X server. Its job is + * to reinitialise the video mode. + * + * We may wish to unmap video/MMIO memory too. + */ + +/* Mandatory */ +Bool +AlpEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CirPtr pCir = CIRPTR(pScrn); + Bool ret; + +#ifdef ALP_DEBUG + ErrorF("AlpEnterVT\n"); +#endif + + /* Should we re-save the text mode on each VT enter? */ + if (!(ret = AlpModeInit(pScrn, pScrn->currentMode))) + return FALSE; + + if (!pCir->NoAccel) + pCir->InitAccel(pScrn); + + return ret; +} + + +/* + * This is called when VT switching away from the X server. Its job is + * to restore the previous (text) mode. + * + * We may wish to remap video/MMIO memory too. + */ + +/* Mandatory */ +void +AlpLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); +#ifdef ALP_DEBUG + ErrorF("AlpLeaveVT\n"); +#endif + + AlpRestore(pScrn); + vgaHWLock(hwp); +} + + +/* + * This is called at the end of each server generation. It restores the + * original (text) mode. It should also unmap the video memory, and free + * any per-generation data allocated by the driver. It should finish + * by unwrapping and calling the saved CloseScreen function. + */ + +/* Mandatory */ +static Bool +AlpCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + CirPtr pCir = CIRPTR(pScrn); + + if(pScrn->vtSema) { + AlpRestore(pScrn); + vgaHWLock(hwp); + CirUnmapMem(pCir, pScrn->scrnIndex); + } + + if (pCir->AccelInfoRec) + XAADestroyInfoRec(pCir->AccelInfoRec); + pCir->AccelInfoRec = NULL; + if (pCir->CursorInfoRec) + xf86DestroyCursorInfoRec(pCir->CursorInfoRec); + pCir->CursorInfoRec = NULL; + if (pCir->DGAModes) + xfree(pCir->DGAModes); + pCir->DGAnumModes = 0; + pCir->DGAModes = NULL; + + pScrn->vtSema = FALSE; + + pScreen->CloseScreen = pCir->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +/* Free up any persistent data structures */ + +/* Optional */ +void +AlpFreeScreen(int scrnIndex, int flags) +{ +#ifdef ALP_DEBUG + ErrorF("AlpFreeScreen\n"); +#endif + /* + * This only gets called when a screen is being deleted. It does not + * get called routinely at the end of a server generation. + */ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + AlpFreeRec(xf86Screens[scrnIndex]); +} + + +/* Checks if a mode is suitable for the selected chipset. */ + +/* Optional */ +int +AlpValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + int lace; + + lace = 1 + ((mode->Flags & V_INTERLACE) != 0); + + if ((mode->CrtcHDisplay <= 2048) && + (mode->CrtcHSyncStart <= 4096) && + (mode->CrtcHSyncEnd <= 4096) && + (mode->CrtcHTotal <= 4096) && + (mode->CrtcVDisplay <= 2048 * lace) && + (mode->CrtcVSyncStart <= 4096 * lace) && + (mode->CrtcVSyncEnd <= 4096 * lace) && + (mode->CrtcVTotal <= 4096 * lace)) { + return(MODE_OK); + } else { + return(MODE_BAD); + } +} + +/* Do screen blanking */ + +/* Mandatory */ +static Bool +AlpSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + +/* + * Set the clock to the requested frequency. If the MCLK is very close + * to the requested frequency, it sets a flag so that the MCLK can be used + * as VCLK. However this flag is not yet acted upon. + */ +static void +AlpSetClock(CirPtr pCir, vgaHWPtr hwp, int freq) +{ + int num, den, ffreq, usemclk, diff, mclk; + CARD8 tmp; + +#ifdef ALP_DEBUG + ErrorF("AlpSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000); +#endif + + ffreq = freq; + if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den)) + return; + + /* Calculate the MCLK. */ + mclk = 14318 * (hwp->readSeq(hwp, 0x1F) & 0x3F) / 8; /* XXX */ + /* + * Favour MCLK as VLCK if it matches as good as the found clock, + * or if it is within 0.2 MHz of the request clock. A VCLK close + * to MCLK can cause instability. + */ + diff = abs(freq - ffreq); + if (abs(mclk - ffreq) <= diff + 10 || abs(mclk - freq) <= 200) + usemclk = TRUE; + else + usemclk = FALSE; + +#ifdef ALP_DEBUG + ErrorF("AlpSetClock: nom=%x den=%x ffreq=%d.%03dMHz usemclk=%x\n", + num, den, ffreq / 1000, ffreq % 1000, usemclk); +#endif + /* So - how do we use MCLK here for the VCLK ? */ + + /* Set VCLK3. */ + tmp = hwp->readSeq(hwp, 0x0E); + hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | num); + hwp->writeSeq(hwp, 0x1E, den); +} + +/* + * AlpDisplayPowerManagementSet -- + * + * Sets VESA Display Power Management Signaling (DPMS) Mode. + */ +static void +AlpDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, + int flags) +{ + unsigned char sr01, gr0e; + vgaHWPtr hwp; + +#ifdef ALP_DEBUG + ErrorF("AlpDisplayPowerManagementSet\n"); +#endif + + hwp = VGAHWPTR(pScrn); + +#ifdef ALP_DEBUG + ErrorF("AlpDisplayPowerManagementSet: %d\n", PowerManagementMode); +#endif + + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + sr01 = 0x00; + gr0e = 0x00; + break; + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On */ + sr01 = 0x20; + gr0e = 0x02; + break; + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off */ + sr01 = 0x20; + gr0e = 0x04; + break; + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + sr01 = 0x20; + gr0e = 0x06; + break; + default: + return; + } + + sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20; + hwp->writeSeq(hwp, 0x01, sr01); + gr0e |= hwp->readGr(hwp, 0x0E) & ~0x06; + hwp->writeGr(hwp, 0x0E, gr0e); +} + +#ifdef ALPPROBEI2C +static void AlpProbeI2C(int scrnIndex) +{ + int i; + I2CBusPtr b; + + b = xf86I2CFindBus(scrnIndex, "I2C bus 1"); + if (b == NULL) + ErrorF("Could not find I2C bus \"%s\"\n", "I2C bus 1"); + else { + for (i = 2; i < 256; i += 2) + if (xf86I2CProbeAddress(b, i)) + ErrorF("Found device 0x%02x on bus \"%s\"\n", i, b->BusName); + } + b = xf86I2CFindBus(scrnIndex, "I2C bus 2"); + if (b == NULL) + ErrorF("Could not find I2C bus \"%s\"\n", "I2C bus 2"); + else { + for (i = 2; i < 256; i += 2) + if (xf86I2CProbeAddress(b, i)) + ErrorF("Found device 0x%02x on bus \"%s\"\n", i, b->BusName); + } +} +#endif + +static void +AlpProbeLCD(ScrnInfoPtr pScrn) +{ + CirPtr pCir = CIRPTR(pScrn); + AlpPtr pAlp = ALPPTR(pCir); + + vgaHWPtr hwp = VGAHWPTR(pScrn); + CARD8 lcdCrtl; + + static const char* lcd_type_names[] = + { + "none", + "dual-scan monochrome", + "unknown", + "DSTN (dual scan color)", + "TFT (active matrix)" + }; + + + pAlp->lcdType = LCD_NONE; + + switch (pCir->Chipset) { + case PCI_CHIP_GD7548: + switch (hwp->readCrtc(hwp, 0x2C) >> 6) { + case 0: pAlp->lcdType = LCD_DUAL_MONO; break; + case 1: pAlp->lcdType = LCD_UNKNOWN; break; + case 2: pAlp->lcdType = LCD_DSTN; break; + case 3: pAlp->lcdType = LCD_TFT; break; + } + + /* Enable LCD control registers instead of normal CRTC registers */ + lcdCrtl = hwp->readCrtc(hwp, 0x2D); + hwp->writeCrtc(hwp, 0x2D, lcdCrtl | 0x80); + + switch ((hwp->readCrtc(hwp, 0x9) >> 2) & 3) { + case 0: + pAlp->lcdWidth = 640; + pAlp->lcdHeight = 480; + break; + + case 1: + pAlp->lcdWidth = 800; + pAlp->lcdHeight = 600; + break; + + case 2: + pAlp->lcdWidth = 1024; + pAlp->lcdHeight = 768; + break; + + case 3: + pAlp->lcdWidth = 0; + pAlp->lcdHeight = 0; + break; + } + + /* Disable LCD control registers */ + hwp->writeCrtc(hwp, 0x2D, lcdCrtl); + break; + } + + if (pAlp->lcdType != LCD_NONE) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "LCD display: %dx%d %s\n", + pAlp->lcdWidth, pAlp->lcdHeight, + lcd_type_names[pAlp->lcdType]); + } +} + +static void +AlpOffscreenAccelInit(ScrnInfoPtr pScrn) +{ + CirPtr pCir = CIRPTR(pScrn); + AlpPtr pAlp = ALPPTR(pCir); + + if (pCir->offscreen_size >= 8 && pCir->Chipset == PCI_CHIP_GD7548) { + pCir->offscreen_offset -= 8; + pCir->offscreen_size -= 8; + pAlp->monoPattern8x8 = pCir->offscreen_offset; +#ifdef ALP_DEBUG + ErrorF("monoPattern8x8=%d\n", pAlp->monoPattern8x8); +#endif + } else pAlp->monoPattern8x8 = 0; + + { + /* TODO: probably not correct if rotated */ + BoxRec box; + box.x1=0; + box.y1=0; + box.x2=pScrn->virtualX; + box.y2= pCir->offscreen_offset / pCir->pitch; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d lines for offscreen memory\n", + box.y2 - pScrn->virtualY); + } +} |