xenocara/driver/xf86-video-cirrus/src/alp_driver.c

2223 lines
55 KiB
C

/*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* All drivers should typically include these */
#include "xf86.h"
#include "xf86_OSproc.h"
/* All drivers need this */
/* Everything using inb/outb, etc needs "compiler.h" */
#include "compiler.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"
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
#include "xf86RAC.h"
#include "xf86Resources.h"
#endif
/* All drivers initialising the SW cursor need this */
#include "mipointer.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"
#if HAVE_XF4BPP
#include "xf4bpp.h"
#endif
#if HAVE_XF1BPP
#include "xf1bpp.h"
#endif
#include "fb.h"
#include "xf86DDC.h"
#include "xf86int10.h"
#include "cir.h"
#define _ALP_PRIVATE_
#include "alp.h"
#include "xf86xv.h"
#include <X11/extensions/Xv.h>
#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(SCREEN_INIT_ARGS_DECL);
Bool AlpEnterVT(VT_FUNC_ARGS_DECL);
void AlpLeaveVT(VT_FUNC_ARGS_DECL);
static Bool AlpCloseScreen(CLOSE_SCREEN_ARGS_DECL);
static Bool AlpSaveScreen(ScreenPtr pScreen, int mode);
/* Required if the driver supports mode switching */
Bool AlpSwitchMode(SWITCH_MODE_ARGS_DECL);
/* Required if the driver supports moving the viewport */
void AlpAdjustFrame(ADJUST_FRAME_ARGS_DECL);
/* Optional functions */
void AlpFreeScreen(FREE_SCREEN_ARGS_DECL);
ModeStatus AlpValidMode(SCRN_ARG_TYPE arg, 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);
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
static void PC98CIRRUS755xEnable(ScrnInfoPtr pScrn);
static void PC98CIRRUS755xDisable(ScrnInfoPtr pScrn);
#endif
/*
* 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 };
static int gd7555_MaxClocks[] = { 80100, 80100, 80100, 80100, 80100 };
static int gd7556_MaxClocks[] = { 80100, 80100, 80100, 80100, 80100 };
#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,
XORG_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.
*/
_X_EXPORT 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;
}
return (pointer)1;
}
#endif /* XFree86LOADER */
_X_EXPORT const OptionInfoRec *
AlpAvailableOptions(int chipid)
{
return CirOptions;
}
_X_EXPORT 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%lx\n", (intptr_t)CIRPTR(pScrn));
#endif
return TRUE;
}
static void
AlpFreeRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate == NULL)
return;
free(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 */
if (!pCir->IoMapSize)
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",
(unsigned int)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",
(unsigned int)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",
(unsigned int)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;
switch (pCir->chip.alp->sr0f & 0x90) {
case 0x10:
/* TODO: 2 256K X 16 DRAMs (1024) or 4 512K X 8 DRAMs (2048)? */
break;
case 0x90:
videoram <<= 1;
break;
}
break;
case PCI_CHIP_GD7555:
case PCI_CHIP_GD7556:
videoram = 2048; /* for PC-9821 La13 etc. */
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;
int max_pitch;
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
switch (pCir->Chipset) {
case PCI_CHIP_GD5436:
case PCI_CHIP_GD5446:
max_pitch = 0x1ff << 3;
break;
default:
/* FIXME max_pitch for other chipsets? */
max_pitch = (pScrn->bitsPerPixel / 8) * 2048;
break;
}
for (i = 0; accelWidths[i] != 0; i++) {
if ((accelWidths[i] % pCir->Rounding == 0)
&& ((accelWidths[i] * pScrn->bitsPerPixel / 8) <= max_pitch)) {
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;
int depth_flags;
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;
/*
* Allocate a vgaHWRec
*/
if (!vgaHWGetHWRec(pScrn))
return FALSE;
hwp = VGAHWPTR(pScrn);
vgaHWSetStdFuncs(hwp);
vgaHWGetIOBase(hwp);
/* Allocate the AlpRec driverPrivate */
if (!AlpGetRec(pScrn))
return FALSE;
pCir = CIRPTR(pScrn);
pCir->pScrn = pScrn;
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
pCir->PIOReg = hwp->PIOOffset + 0x3CE;
#else
pCir->PIOReg = 0x3CE;
#endif
/* Get the entity, and make sure it is PCI. */
pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pCir->pEnt->location.type != BUS_PCI) {
free(pCir->pEnt);
return FALSE;
}
pCir->Chipset = pCir->pEnt->chipset;
/* Find the PCI info for this screen */
pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index);
pCir->PciTag = pciTag(PCI_DEV_BUS(pCir->PciInfo),
PCI_DEV_DEV(pCir->PciInfo),
PCI_DEV_FUNC(pCir->PciInfo));
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
if (!xf86IsPc98())
#endif
if (xf86LoadSubModule(pScrn, "int10"))
{
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
*/
PCI_WRITE_LONG(pCir->PciInfo, PCI_REGION_BASE(pCir->PciInfo, 0, REGION_MEM), 0x10);
PCI_WRITE_LONG(pCir->PciInfo, PCI_REGION_BASE(pCir->PciInfo, 1, REGION_MEM), 0x14);
}
/* Set pScrn->monitor */
pScrn->monitor = pScrn->confScreen->monitor;
/* 32bpp only works on 5480 and 7548 */
depth_flags = Support24bppFb;
if (pCir->Chipset == PCI_CHIP_GD5480 || pCir->Chipset ==PCI_CHIP_GD7548)
depth_flags |= Support32bppFb |
SupportConvert32to24 |
PreferConvert32to24;
/*
* The first thing we should figure out is the depth, bpp, etc.
* We support both 24bpp and 32bpp layouts, so indicate that.
*/
if (!xf86SetDepthBpp(pScrn, 0, 0, 24, depth_flags)) {
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 = malloc(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;
switch (pCir->Chipset) {
case PCI_CHIP_GD7555:
case PCI_CHIP_GD7556:
pCir->HWCursor = TRUE;
break;
default:
break;
}
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 = PCI_DEV_REVISION(pCir->PciInfo);
}
/* 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 (PCI_REGION_BASE(pCir->PciInfo, 0, REGION_MEM) != 0) {
/* 5446B and 5480 use mask of 0xfe000000.
5446A uses 0xff000000. */
pCir->FbAddress = PCI_REGION_BASE(pCir->PciInfo, 0, REGION_MEM) & 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 (PCI_REGION_BASE(pCir->PciInfo, 1, REGION_MEM) != 0) {
pCir->IOAddress = PCI_REGION_BASE(pCir->PciInfo, 1, REGION_MEM) & 0xfffff000;
pCir->IoMapSize = PCI_REGION_SIZE(pCir->PciInfo, 1);
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");
#ifndef XSERVER_LIBPCIACCESS
/*
* 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;
}
#endif
if (!xf86LoadSubModule(pScrn, "i2c")) {
AlpFreeRec(pScrn);
return FALSE;
}
if (!xf86LoadSubModule(pScrn, "ddc")) {
AlpFreeRec(pScrn);
return FALSE;
}
if(!AlpI2CInit(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"I2C initialization failed\n");
}
else
xf86SetDDCproperties(pScrn,xf86PrintEDID(
xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),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_GD5440: */
p = gd5430_MaxClocks;
break;
case PCI_CHIP_GD5436:
case PCI_CHIP_GD5446:
p = gd5446_MaxClocks;
break;
case PCI_CHIP_GD5480:
p = gd5480_MaxClocks;
break;
case PCI_CHIP_GD7548:
p = gd7548_MaxClocks;
break;
case PCI_CHIP_GD7555:
p = gd7555_MaxClocks;
break;
case PCI_CHIP_GD7556:
p = gd7556_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) {
#ifdef HAVE_XF1BPP
case 1:
if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) {
AlpFreeRec(pScrn);
return FALSE;
}
break;
#endif
#ifdef HAVE_XF4BPP
case 4:
if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) {
AlpFreeRec(pScrn);
return FALSE;
}
break;
#endif
case 8:
case 16:
case 24:
case 32:
if (xf86LoadSubModule(pScrn, "fb") == NULL) {
AlpFreeRec(pScrn);
return FALSE;
}
break;
}
/* Load XAA if needed */
if (!pCir->NoAccel) {
#ifdef USE_EXA
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loading EXA module...\n");
if (xf86LoadSubModule(pScrn, "exa")) {
pCir->ExaDriver = exaDriverAlloc();
if (!pCir->ExaDriver) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Could no allocate EXA_DRIVER.\n");
pCir->UseEXA = FALSE;
}
pCir->UseEXA = TRUE;
}
#endif
#ifdef HAVE_XAA_H
if (!xf86LoadSubModule(pScrn, "xaa"))
#else
if (!pCir->UseEXA)
#endif
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Falling back to shadowfb\n");
pCir->NoAccel = TRUE;
pCir->shadowFB = TRUE;
}
}
/* Load ramdac if needed */
if (pCir->HWCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
AlpFreeRec(pScrn);
return FALSE;
}
}
if (pCir->shadowFB) {
if (!xf86LoadSubModule(pScrn, "shadowfb")) {
AlpFreeRec(pScrn);
return FALSE;
}
}
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;
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;
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);
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
if (xf86IsPc98())
PC98CIRRUS755xEnable(pScrn);
#endif
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(SCREEN_INIT_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
vgaHWPtr hwp;
CirPtr pCir;
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
hwp = VGAHWPTR(pScrn);
pCir = CIRPTR(pScrn);
/* 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;
/* Make things beautiful */
AlpSaveScreen(pScreen, SCREEN_SAVER_ON);
/* Set the viewport */
AlpAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
/*
* 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 = malloc(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) {
#ifdef HAVE_XF1BPP
case 1:
ret = xf1bppScreenInit(pScreen, FbBase,
width, height,
pScrn->xDpi, pScrn->yDpi,
displayWidth);
break;
#endif
#ifdef HAVE_XF4BPP
case 4:
ret = xf4bppScreenInit(pScreen, FbBase,
width, height,
pScrn->xDpi, pScrn->yDpi,
displayWidth);
break;
#endif
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(pScrn->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);
/*
* 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);
#ifdef HAVE_XAA_H
if (!(pCir->UseMMIO ? AlpXAAInitMMIO(pScreen) :
AlpXAAInit(pScreen)))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Could not initialize XAA\n");
#endif
#ifdef USE_EXA
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Filling in EXA memory info\n");
pCir->ExaDriver->offScreenBase = pCir->offscreen_offset;
pCir->ExaDriver->memorySize = pCir->FbMapSize;
if (AlpEXAInit(pScreen))
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"EXA Acceleration enabled\n");
else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"EXA Acceleration Init failed\n");
pCir->NoAccel = TRUE;
}
#endif
}
#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;
{
XF86VideoAdaptorPtr *ptr;
int n;
n = xf86XVListGenericAdaptors(pScrn,&ptr);
if (n)
xf86XVScreenInit(pScreen, ptr, n);
}
/*
* 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(SWITCH_MODE_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
return AlpModeInit(pScrn, mode);
}
/*
* This function is used to initialize the Start Address - the first
* displayed location in the video memory.
*/
/* Usually mandatory */
void
AlpAdjustFrame(ADJUST_FRAME_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
int Base, tmp;
vgaHWPtr hwp;
hwp = VGAHWPTR(pScrn);
Base = ((y * pScrn->displayWidth + x) / 8);
if (pScrn->bitsPerPixel != 1)
Base *= (pScrn->bitsPerPixel/4);
#ifdef ALP_DEBUG
ErrorF("AlpAdjustFrame %d %d %d %x\n", x, y, 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(VT_FUNC_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
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(VT_FUNC_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
vgaHWPtr hwp = VGAHWPTR(pScrn);
#ifdef ALP_DEBUG
ErrorF("AlpLeaveVT\n");
#endif
AlpRestore(pScrn);
vgaHWLock(hwp);
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
if (xf86IsPc98())
PC98CIRRUS755xDisable(pScrn);
#endif
}
/*
* 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(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
vgaHWPtr hwp = VGAHWPTR(pScrn);
CirPtr pCir = CIRPTR(pScrn);
if(pScrn->vtSema) {
AlpRestore(pScrn);
vgaHWLock(hwp);
CirUnmapMem(pCir, pScrn->scrnIndex);
}
#ifdef HAVE_XAA_H
if (pCir->AccelInfoRec)
XAADestroyInfoRec(pCir->AccelInfoRec);
pCir->AccelInfoRec = NULL;
#endif
if (pCir->CursorInfoRec)
xf86DestroyCursorInfoRec(pCir->CursorInfoRec);
pCir->CursorInfoRec = NULL;
if (pCir->DGAModes)
free(pCir->DGAModes);
pCir->DGAnumModes = 0;
pCir->DGAModes = NULL;
pScrn->vtSema = FALSE;
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
if (xf86IsPc98())
PC98CIRRUS755xDisable(pScrn);
#endif
pScreen->CloseScreen = pCir->CloseScreen;
return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
}
/* Free up any persistent data structures */
/* Optional */
void
AlpFreeScreen(FREE_SCREEN_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
#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(pScrn);
AlpFreeRec(pScrn);
}
/* Checks if a mode is suitable for the selected chipset. */
/* Optional */
ModeStatus
AlpValidMode(SCRN_ARG_TYPE arg, 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;
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;
#ifdef ALP_DEBUG
ErrorF("AlpSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n",
num, den, ffreq / 1000, ffreq % 1000);
#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);
}
}
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
static void
PC98CIRRUS755xEnable(ScrnInfoPtr pScrn) /* enter_aile() */
{
unsigned int index,data;
vgaHWPtr hwp = VGAHWPTR(pScrn);
outb(0xfac, 0x02);
outb(0x68, 0x0e);
outb(0x6a, 0x07);
outb(0x6a, 0x8f);
outb(0x6a, 0x06);
outw(VGA_SEQ_INDEX, 0x1206); /* unlock cirrus special */
index = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
data = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
outb(index, 0x3c);
outb(data, inb(data) & 0xef);
outb(index, 0x1a);
outb(data, inb(data) & 0xf3);
}
static void
PC98CIRRUS755xDisable(ScrnInfoPtr pScrn) /* leave_aile() */
{
unsigned int index,data;
vgaHWPtr hwp = VGAHWPTR(pScrn);
outw(VGA_SEQ_INDEX, 0x1206); /* unlock cirrus special */
index = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
data = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
outb(index, 0x3c);
outb(data, 0x71);
outb(index, 0x1a);
outb(data, inb(data) | 0x0c);
outb(0xfac,0x00);
outb(0x68, 0x0f);
outb(0x6a, 0x07);
outb(0x6a, 0x8e);
outb(0x6a, 0x21);
outb(0x6a, 0x69);
outb(0x6a, 0x06);
}
#endif