summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit97c9ec2c1201ec09c359f92817033281045c537e (patch)
tree1c5fd291eed7533af96fab9525fcb7cc75eb2884
downloadxorg-driver-xf86-video-cirrus-97c9ec2c1201ec09c359f92817033281045c537e.tar.gz
Initial revisionXORG-STABLE
-rw-r--r--README.multihead70
-rw-r--r--man/cirrus.man30
-rw-r--r--src/CirrusClk.c146
-rw-r--r--src/alp.h87
-rw-r--r--src/alp_driver.c2151
-rw-r--r--src/alp_hwcurs.c258
-rw-r--r--src/alp_i2c.c126
-rw-r--r--src/alp_xaa.c686
-rw-r--r--src/alp_xaam.c271
-rw-r--r--src/cir.h97
-rw-r--r--src/cir_dga.c256
-rw-r--r--src/cir_driver.c409
-rw-r--r--src/cir_shadow.c251
-rw-r--r--src/lg.h110
-rw-r--r--src/lg_driver.c1877
-rw-r--r--src/lg_hwcurs.c384
-rw-r--r--src/lg_i2c.c96
-rw-r--r--src/lg_xaa.c298
-rw-r--r--src/lg_xaa.h180
19 files changed, 7783 insertions, 0 deletions
diff --git a/README.multihead b/README.multihead
new file mode 100644
index 0000000..efe62d4
--- /dev/null
+++ b/README.multihead
@@ -0,0 +1,70 @@
+WARNING:
+On exit XFree86 restores the old mode but it
+does not disable the secondary card. As a result
+the second card (which has some randonm CRTC timing)
+may produce synch pulses which are wrong for your
+monitor.
+
+If your monitor does not tolerate bad timing I would
+recommend that you don't try Multi-head yet, or at
+least, turn it off *before* leaving X.
+
+
+3.9Nl notice: There is a problem with releasing
+of LBX colormap privates which may cause a seg.
+fault when the server exits. I got a patch from
+Mark Vojkovich which fixes it.
+
+If you have a CL-GD5480 or CL-GD5446 ver. B you
+should be able to try Multi-Head with that
+card as a secondary. The primary card should not
+have any special feature. Some MainBoards may
+not do it right too. I tried it with a 5465 (AGP)
+as a primary and 5446B (PCI) secondary on an
+ABIT LX6 upgraded to the latest bios.
+
+Version A of the 5446 cannot be pure MMIO (The driver
+requires that it is the primary display adapter).
+You can distinguish between the rel A and rel B by
+running "scanpci -v". Version 1 does not report a
+valid BASE1 address.
+
+The bios upgrade lets me chose if the primary
+display adapter is on PCI on AGP (I chose
+the AGP card as primary). Warning - this setup
+will *NOT* work with XFree86 3.3.2.
+
+The only problem that I found so far is with
+memory configuration initialization. My bios
+does not initialize the secondary display adapter.
+This results in a currupted display.
+
+Here are the options:
+1. warm booting from Windows 98 may work. I have
+not tried that.
+
+2. Take out the other card and leave the 5446
+(or 5480) as the primary card. Start the server
+and watch it's output. Look for lines like:
+ (--) CIRRUS(0): Memory Config reg 1 is 0x1B
+ (--) CIRRUS(0): Memory Config reg 2 is 0x21
+Remember these values. Now edit XF86Config
+and add to the proper device section the lines:
+ Option "MemCFG1" "0x1B"
+ Option "MemCFG2" "0x21"
+These values are the contents of registers SR0F
+and SR17. (notice: the 5480 driver does not use
+and will not print MemCFG2).
+
+Now you can reinstall the other card (which
+must me set as the the primary display adaptor).
+
+A note about configuring multi-head:
+There should be a separate section for each
+adapter (device), Monitor and Screen. A "ServerLayout"
+section is optional (and recommended). To make it
+easier for XFree86 to relate device sections to
+actual cards, use a BusId line in each device
+section. XFree86 3.9N works properly if the config
+file is for Multi-head but it finds only one
+display adapter.
diff --git a/man/cirrus.man b/man/cirrus.man
new file mode 100644
index 0000000..5035b02
--- /dev/null
+++ b/man/cirrus.man
@@ -0,0 +1,30 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cirrus.man,v 1.2 2001/01/27 18:20:47 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH CIRRUS __drivermansuffix__ __vendorversion__
+.SH NAME
+cirrus \- Cirrus Logic video driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qcirrus\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B cirrus
+is an XFree86 driver for Cirrus Logic video chips.
+THIS MAN PAGE NEEDS TO BE FILLED IN.
+.SH SUPPORTED HARDWARE
+The
+.B cirrus
+driver supports...
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: ...
diff --git a/src/CirrusClk.c b/src/CirrusClk.c
new file mode 100644
index 0000000..c548f1f
--- /dev/null
+++ b/src/CirrusClk.c
@@ -0,0 +1,146 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/CirrusClk.c,v 1.9 1999/12/26 18:24:14 robin Exp $ */
+
+/*
+ * Programming of the built-in Cirrus clock generator.
+ * Harm Hanemaayer <hhanemaa@cs.ruu.nl>
+ *
+ * VCO stability criterion code added by Koen Gadeyne (koen.gadeyne@barco.com)
+ * Max clock specification added by Harm Hanemaayer (H.Hanemaayer@inter.nl.net)
+ *
+ * Minor changes and cleanup Itai Nahshon.
+ *
+ * Made this completly chipset independent, and moved chipset dependent parts
+ * into the specific sub-drivers. Derek Fawcus <derek@spider.com>
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+#include "cir.h"
+
+/* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */
+#define CLOCK_FACTOR 28636
+
+/* Stability constraints for internal VCO -- MAX_VCO also determines
+ * the maximum Video pixel clock
+ */
+#define MIN_VCO CLOCK_FACTOR
+#define MAX_VCO 111000
+
+/* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */
+#define VCOVAL(n, d) \
+ ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) )
+
+#define CLOCKVAL(n, d) \
+ (VCOVAL(n, d) >> ((d) & 1))
+
+typedef struct {
+ unsigned char numer;
+ unsigned char denom;
+} cirrusClockRec;
+
+static cirrusClockRec cirrusClockTab[] = {
+ { 0x2C, 0x33 }, /* 12.599 */
+ { 0x4A, 0x2B }, /* 25.227 */
+ { 0x5B, 0x2F }, /* 28.325 */
+ { 0x45, 0x30 }, /* 41.164 */
+ { 0x7E, 0x33 }, /* 36.082 */
+ { 0x42, 0x1F }, /* 31.500 */
+ { 0x51, 0x3A }, /* 39.992 */
+ { 0x55, 0x36 }, /* 45.076 */
+ { 0x65, 0x3A }, /* 49.867 */
+ { 0x76, 0x34 }, /* 64.983 */
+ { 0x7E, 0x32 }, /* 72.163 */
+ { 0x6E, 0x2A }, /* 75.000 */
+ { 0x5F, 0x22 }, /* 80.013 */
+ { 0x7D, 0x2A }, /* 85.226 */
+ { 0x58, 0x1C }, /* 89.998 */
+ { 0x49, 0x16 }, /* 95.019 */
+ { 0x46, 0x14 }, /* 100.226 */
+ { 0x53, 0x16 }, /* 108.035 */
+ { 0x5C, 0x18 }, /* 110.248 */
+
+ { 0x6D, 0x1A }, /* 120.050 */
+ { 0x58, 0x14 }, /* 125.998 */
+ { 0x6D, 0x18 }, /* 130.055 */
+ { 0x42, 0x0E }, /* 134.998 */
+
+ { 0x69, 0x14 }, /* 150.341 */
+ { 0x5E, 0x10 }, /* 168.239 */
+ { 0x5C, 0x0E }, /* 188.182 */
+ { 0x67, 0x0E }, /* 210.682 */
+ { 0x60, 0x0C }, /* 229.091 */
+};
+
+#define NU_FIXED_CLOCKS (sizeof(cirrusClockTab)/sizeof(cirrusClockTab[0]))
+
+
+/*
+ * This function returns the 7-bit numerator and 6-bit denominator/post-scalar
+ * value that corresponds to the closest clock found.
+ * If a frequency close to one of the tested clock values is found,
+ * use the tested clock since others can be unstable.
+ */
+
+Bool
+CirrusFindClock(int *rfreq, int max_clock, int *num_out, int *den_out)
+{
+ int n, i;
+ int num = 0, den = 0;
+ int freq, ffreq = 0, mindiff = 0;
+
+ freq = *rfreq;
+ /* Prefer a tested value if it matches within 0.1%. */
+ for (i = 0; i < NU_FIXED_CLOCKS; i++) {
+ int diff;
+ diff = abs(CLOCKVAL(cirrusClockTab[i].numer,
+ cirrusClockTab[i].denom) - freq);
+ if (diff < freq / 1000) {
+ num = cirrusClockTab[i].numer;
+ den = cirrusClockTab[i].denom;
+ ffreq = CLOCKVAL(num, den);
+ goto foundclock;
+ }
+ }
+
+ /*
+ * If max_clock is greater than the MAX_VCO default, ignore
+ * MAX_VCO. On the other hand, if MAX_VCO is higher than max_clock,
+ * make use of the higher MAX_VCO value.
+ */
+ if (MAX_VCO > max_clock)
+ max_clock = MAX_VCO;
+
+ mindiff = freq;
+ for (n = 0x10; n < 0x7f; n++) {
+ int d;
+ for (d = 0x14; d < 0x3f; d++) {
+ int c, diff;
+
+ /* Avoid combinations that can be unstable. */
+ if ((VCOVAL(n, d) < MIN_VCO) || (VCOVAL(n, d) > max_clock))
+ continue;
+ c = CLOCKVAL(n, d);
+ diff = abs(c - freq);
+ if (diff < mindiff) {
+ mindiff = diff;
+ num = n;
+ den = d;
+ ffreq = c;
+ }
+ }
+ }
+
+ if (0 == num || 0 == den)
+ return FALSE;
+
+foundclock:
+ *num_out = num;
+ *den_out = den;
+ *rfreq = ffreq;
+
+ return TRUE;
+}
diff --git a/src/alp.h b/src/alp.h
new file mode 100644
index 0000000..01c5301
--- /dev/null
+++ b/src/alp.h
@@ -0,0 +1,87 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp.h,v 1.8 2001/10/01 13:44:05 eich Exp $ */
+
+/* (c) Itai Nahshon */
+
+#ifndef ALP_H
+#define ALP_H
+
+extern ScrnInfoPtr AlpProbe(int entity);
+extern const OptionInfoRec * AlpAvailableOptions(int chipid);
+
+# ifdef _ALP_PRIVATE_
+/* Saved registers that are not part of the core VGA */
+/* CRTC >= 0x19; Sequencer >= 0x05; Graphics >= 0x09; Attribute >= 0x15 */
+
+enum {
+ /* CR regs */
+ CR1A,
+ CR1B,
+ CR1D,
+ /* SR regs */
+ SR07,
+ SR0E,
+ SR12,
+ SR13,
+ SR17,
+ SR1E,
+ SR21,
+ SR2D,
+ /* GR regs */
+ GR17,
+ GR18,
+ /* HDR */
+ HDR,
+ /* Must be last! */
+ CIR_NSAVED
+};
+
+typedef enum {LCD_NONE, LCD_DUAL_MONO, LCD_UNKNOWN, LCD_DSTN, LCD_TFT} LCDType;
+
+typedef struct {
+ unsigned char ExtVga[CIR_NSAVED];
+} AlpRegRec, *AlpRegPtr;
+
+extern Bool AlpHWCursorInit(ScreenPtr pScreen, int size);
+extern Bool AlpXAAInit(ScreenPtr pScreen);
+extern Bool AlpXAAInitMMIO(ScreenPtr pScreen);
+extern Bool AlpDGAInit(ScreenPtr pScreen);
+extern Bool AlpI2CInit(ScrnInfoPtr pScrn);
+
+/* Card-specific driver information */
+#define ALPPTR(p) ((AlpPtr)((p)->chip.alp))
+
+typedef struct alpRec {
+ unsigned char * HWCursorBits;
+ unsigned char * CursorBits;
+
+ AlpRegRec SavedReg;
+ AlpRegRec ModeReg;
+ LCDType lcdType;
+ int lcdWidth, lcdHeight;
+ int CursorWidth;
+ int CursorHeight;
+ int waitMsk;
+ int scanlineDest;
+ int scanlineCount;
+ int scanlineWidth;
+
+ int SubsequentColorExpandScanlineDest;
+ int SubsequentColorExpandScanlineByteWidth;
+ int SubsequentColorExpandScanlineDWordWidth;
+
+ /* Offset into framebuffer of a 8-byte scratch area for fills */
+ CARD32 monoPattern8x8;
+
+ Bool autoStart;
+
+ /* MMIO Base for BitBLT operation. This is
+ IOBase for 5446 and 7548, IOBase+0x100 for 5480 */
+ unsigned char * BLTBase;
+ CARD32 transRop;
+/* XXX For XF86Config based mem configuration */
+ CARD32 sr0f, sr17;
+} AlpRec, *AlpPtr;
+
+# endif /* _ALP_PRIVATE_ */
+#endif /* ALP_H */
+
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);
+ }
+}
diff --git a/src/alp_hwcurs.c b/src/alp_hwcurs.c
new file mode 100644
index 0000000..a4f0581
--- /dev/null
+++ b/src/alp_hwcurs.c
@@ -0,0 +1,258 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_hwcurs.c,v 1.5 2001/05/07 21:59:06 tsi Exp $ */
+
+/* (c) Itai Nahshon */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _ALP_PRIVATE_
+#include "alp.h"
+
+#define CURSORWIDTH pAlp->CursorWidth
+#define CURSORHEIGHT pAlp->CursorHeight
+#define CURSORSIZE (CURSORWIDTH*CURSORHEIGHT/8)
+#define MAXCURSORSIZE (64*64>>3)
+
+static void
+AlpSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ const AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetCursorColors\n");
+#endif
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]|0x02);
+ hwp->writeDacWriteAddr(hwp, 0x00);
+ hwp->writeDacData(hwp, 0x3f & (bg >> 18));
+ hwp->writeDacData(hwp, 0x3f & (bg >> 10));
+ hwp->writeDacData(hwp, 0x3f & (bg >> 2));
+ hwp->writeDacWriteAddr(hwp, 0x0F);
+ hwp->writeDacData(hwp, 0x3F & (fg >> 18));
+ hwp->writeDacData(hwp, 0x3F & (fg >> 10));
+ hwp->writeDacData(hwp, 0x3F & (fg >> 2));
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
+}
+
+static void
+AlpLoadSkewedCursor(CirPtr pCir, int x, int y) {
+
+ const AlpPtr pAlp = ALPPTR(pCir);
+
+ unsigned char *memx = pAlp->HWCursorBits;
+ unsigned char *CursorBits = pAlp->CursorBits;
+
+ unsigned char mem[2*MAXCURSORSIZE];
+ unsigned char *p1, *p2;
+ int i, j, m, a, b;
+ Bool cur64 = (CURSORWIDTH == 64);
+ int shift = (cur64? 1 : 0);
+
+ if (x > 0) x = 0; else x = -x;
+ if (y > 0) y = 0; else y = -y;
+
+
+ a = ((y*CURSORWIDTH<<shift)+x)>>3;
+ b = x & 7;
+
+ /* Copy the skewed mask bits */
+ p1 = mem;
+ p2 = CursorBits + a;
+ for (i = 0; i < (CURSORSIZE << shift)-a-1; i++) {
+ *p1++ = (p2[0] << b) | (p2[1] >> (8-b));
+ p2++;
+ }
+ /* last mask byte */
+ *p1++ = (p2[0] << b);
+
+ /* Clear to end (bottom) of mask. */
+ for (i = i+1; i < (CURSORSIZE << shift); i++)
+ *p1++ = 0;
+
+ if (!cur64) {
+ /* Now copy the cursor bits */
+ /* p1 is already right */
+ p2 = CursorBits+CURSORSIZE+a;
+ for (i = 0; i < CURSORSIZE-a-1; i++) {
+ *p1++ = (p2[0] << b) | (p2[1] >> (8-b));
+ p2++;
+ }
+ /* last cursor byte */
+ *p1++ = (p2[0] << b);
+ }
+
+ /* Clear to end (bottom) of cursor. */
+ for (i = i+1; i < CURSORSIZE; i++)
+ *p1++ = 0;
+
+ /* Clear the right unused area of the mask
+ and cyrsor bits. */
+ p2 = mem + CURSORWIDTH/8 - (x>>3) - 1;
+ for (i = 0; i < 2*CURSORHEIGHT; i++) {
+ m = (-1)<<(x&7);
+ p1 = p2;
+ p2 += CURSORWIDTH/8;
+ for (j = x>>3; j >= 0; j--) {
+ *p1 &= m;
+ m = 0;
+ p1++;
+ }
+ }
+ memcpy(memx, mem, 2*CURSORSIZE);
+}
+
+
+static void
+AlpSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+ const AlpPtr pAlp = ALPPTR(pCir);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+#if 0
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetCursorPosition %d %d\n", x, y);
+#endif
+#endif
+
+ if (x < 0 || y < 0) {
+ if (x+CURSORWIDTH <= 0 || y+CURSORHEIGHT <= 0) {
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12] & ~0x01);
+ return;
+ }
+ AlpLoadSkewedCursor(pCir, x, y);
+ pCir->CursorIsSkewed = TRUE;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ } else if (pCir->CursorIsSkewed) {
+ memcpy(pAlp->HWCursorBits, pAlp->CursorBits, 2*CURSORSIZE);
+ pCir->CursorIsSkewed = FALSE;
+ }
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
+ hwp->writeSeq(hwp, ((x << 5)|0x10)&0xff, x >> 3);
+ hwp->writeSeq(hwp, ((y << 5)|0x11)&0xff, y >> 3);
+}
+
+static void
+AlpLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
+{
+ const AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpLoadCursorImage\n");
+#endif
+
+ pAlp->CursorBits = bits;
+ memcpy(pAlp->HWCursorBits, bits, 2*CURSORSIZE);
+ /* this should work for both 64 and 32 bit cursors */
+ pAlp->ModeReg.ExtVga[SR13] = 0x3f;
+ hwp->writeSeq(hwp, 0x13, pAlp->ModeReg.ExtVga[SR13]);
+}
+
+static void
+AlpHideCursor(ScrnInfoPtr pScrn)
+{
+ AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpHideCursor\n");
+#endif
+ pAlp->ModeReg.ExtVga[SR12] &= ~0x01;
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
+}
+
+static void
+AlpShowCursor(ScrnInfoPtr pScrn)
+{
+ AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpShowCursor\n");
+#endif
+ pAlp->ModeReg.ExtVga[SR12] |= 0x01;
+ hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
+}
+
+static Bool
+AlpUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+#ifdef ALP_DEBUG
+ ErrorF("AlpUseHWCursor\n");
+#endif
+ if (pScrn->bitsPerPixel < 8)
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+AlpHWCursorInit(ScreenPtr pScreen, int size)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ const CirPtr pCir = CIRPTR(pScrn);
+ const AlpPtr pAlp = ALPPTR(pCir);
+
+ xf86CursorInfoPtr infoPtr;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpHWCursorInit\n");
+#endif
+ if (!size) return FALSE;
+
+ infoPtr = xf86CreateCursorInfoRec();
+ if (!infoPtr) return FALSE;
+
+ pCir->CursorInfoRec = infoPtr;
+ pCir->CursorIsSkewed = FALSE;
+ pAlp->CursorBits = NULL;
+
+ if (size == 64)
+ CURSORWIDTH = CURSORHEIGHT = 64;
+ else
+ CURSORWIDTH = CURSORHEIGHT = 32;
+
+ pAlp->HWCursorBits = pCir->FbBase + 1024*pScrn->videoRam - 2*CURSORSIZE;
+
+ infoPtr->MaxWidth = CURSORWIDTH;
+ infoPtr->MaxHeight = CURSORHEIGHT;
+ if (CURSORWIDTH == 64)
+ infoPtr->Flags =
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+#endif
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+ HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
+ else
+ infoPtr->Flags =
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+#endif
+ HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
+
+ infoPtr->SetCursorColors = AlpSetCursorColors;
+ infoPtr->SetCursorPosition = AlpSetCursorPosition;
+ infoPtr->LoadCursorImage = AlpLoadCursorImage;
+ infoPtr->HideCursor = AlpHideCursor;
+ infoPtr->ShowCursor = AlpShowCursor;
+ infoPtr->UseHWCursor = AlpUseHWCursor;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpHWCursorInit before xf86InitCursor\n");
+#endif
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Hardware cursor: %ix%i\n",
+ CURSORWIDTH,CURSORHEIGHT);
+ return(xf86InitCursor(pScreen, infoPtr));
+}
+
+
diff --git a/src/alp_i2c.c b/src/alp_i2c.c
new file mode 100644
index 0000000..78d5406
--- /dev/null
+++ b/src/alp_i2c.c
@@ -0,0 +1,126 @@
+/* (c) Itai Nahshon */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_i2c.c,v 1.3 2000/12/06 15:35:15 eich Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _ALP_PRIVATE_
+#include "alp.h"
+
+/*
+ * Switch between internal I2C bus and external (DDC) bus.
+ * There is one I2C port controlled bu SR08 and the programmable
+ * outputs control a multiplexer.
+ */
+static Bool
+AlpI2CSwitchToBus(I2CBusPtr b)
+{
+ CirPtr pCir = ((CirPtr)b->DriverPrivate.ptr);
+ vgaHWPtr hwp = VGAHWPTR(pCir->pScrn);
+ CARD8 reg = hwp->readGr(hwp, 0x17);
+ if (b == pCir->I2CPtr1) {
+ if ((reg & 0x60) == 0)
+ return TRUE;
+ reg &= ~0x60;
+ }
+ else if(b == pCir->I2CPtr2) {
+ if ((reg & 0x60) != 0)
+ return TRUE;
+ reg |= 0x60;
+ } else return FALSE;
+
+ /* ErrorF("AlpI2CSwitchToBus: \"%s\"\n", b->BusName); */
+ hwp->writeGr(hwp, 0x17, reg);
+ return TRUE;
+}
+
+static void
+AlpI2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ unsigned int reg = 0xfc;
+ CirPtr pCir = ((CirPtr)b->DriverPrivate.ptr);
+ vgaHWPtr hwp = VGAHWPTR(pCir->pScrn);
+
+ if (!AlpI2CSwitchToBus(b))
+ return;
+
+ if (clock) reg |= 1;
+ if (data) reg |= 2;
+ hwp->writeSeq(hwp, 0x08, reg);
+ /* ErrorF("AlpI2CPutBits: %d %d\n", clock, data); */
+}
+
+static void
+AlpI2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ unsigned int reg;
+ CirPtr pCir = ((CirPtr)b->DriverPrivate.ptr);
+ vgaHWPtr hwp = VGAHWPTR(pCir->pScrn);
+
+ if (!AlpI2CSwitchToBus(b))
+ return;
+
+ reg = hwp->readSeq(hwp, 0x08);
+ *clock = (reg & 0x04) != 0;
+ *data = (reg & 0x80) != 0;
+ /* ErrorF("AlpI2CGetBits: %d %d\n", *clock, *data); */
+}
+
+Bool
+AlpI2CInit(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ I2CBusPtr I2CPtr;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpI2CInit\n");
+#endif
+
+ switch(pCir->Chipset) {
+ case PCI_CHIP_GD5446:
+ case PCI_CHIP_GD5480:
+ break;
+ default:
+ return FALSE;
+ }
+
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if (!I2CPtr) return FALSE;
+
+ pCir->I2CPtr1 = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus 1";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = AlpI2CPutBits;
+ I2CPtr->I2CGetBits = AlpI2CGetBits;
+ I2CPtr->DriverPrivate.ptr = pCir;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if (!I2CPtr) return FALSE;
+
+ pCir->I2CPtr2 = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus 2";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = AlpI2CPutBits;
+ I2CPtr->I2CGetBits = AlpI2CGetBits;
+ I2CPtr->DriverPrivate.ptr = pCir;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/alp_xaa.c b/src/alp_xaa.c
new file mode 100644
index 0000000..417f816
--- /dev/null
+++ b/src/alp_xaa.c
@@ -0,0 +1,686 @@
+/* (c) Itai Nahshon */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_xaa.c,v 1.8 2002/01/25 21:56:00 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _ALP_PRIVATE_
+#include "alp.h"
+
+#define WAIT outb(pCir->PIOReg, 0x31); \
+ while(inb(pCir->PIOReg + 1) & pCir->chip.alp->waitMsk){};
+#define WAIT_1 outb(pCir->PIOReg, 0x31); \
+ while(inb(pCir->PIOReg + 1) & 0x1){};
+
+static const CARD16 translated_rop[] =
+{
+ /* GXclear */ 0x0032U,
+ /* GXand */ 0x0532U,
+ /* GXandreverse */ 0x0932U,
+ /* GXcopy */ 0x0D32U,
+ /* GXandinversted */ 0x5032U,
+ /* GXnoop */ 0x0632U,
+ /* GXxor */ 0x5932U,
+ /* GXor */ 0x6D32U,
+ /* GXnor */ 0x9032U,
+ /* GXequiv */ 0x9532U,
+ /* GXinvert */ 0x0B32U,
+ /* GXorReverse */ 0xAD32U,
+ /* GXcopyInverted */ 0xD032U,
+ /* GXorInverted */ 0xD632U,
+ /* GXnand */ 0xDA32U,
+ /* GXset */ 0x0E32U
+};
+
+#if 1
+#define SetupForRop(rop) outw(pCir->PIOReg, translated_rop[rop])
+#else
+#define SetupForRop(rop) outw(pCir->PIOReg, 0x0D32)
+#endif
+
+static void AlpSync(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSync\n");
+#endif
+ WAIT_1;
+ return;
+}
+
+static void
+AlpSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask,
+ int trans_color)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForScreenToScreenCopy xdir=%d ydir=%d rop=%x planemask=%x trans_color=%x\n",
+ xdir, ydir, rop, planemask, trans_color);
+#endif
+ WAIT;
+ SetupForRop(rop);
+ /* Set dest pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+ /* Set source pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x26);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x27);
+}
+
+static void
+AlpSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
+ int y2, int w, int h)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int source, dest;
+ int hh, ww;
+ int decrement = 0;
+ int pitch = pCir->pitch;
+
+ ww = (w * pScrn->bitsPerPixel / 8) - 1;
+ hh = h - 1;
+ dest = y2 * pitch + x2 * pScrn->bitsPerPixel / 8;
+ source = y1 * pitch + x1 * pScrn->bitsPerPixel / 8;
+ if (dest > source) {
+ decrement = 1 << 8;
+ dest += hh * pitch + ww;
+ source += hh * pitch + ww;
+ }
+
+ WAIT;
+
+ outw(pCir->PIOReg, decrement | 0x30);
+
+ /* Width */
+ outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+ outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+ /* Height */
+ outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+ outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+
+
+ /* source */
+ outw(pCir->PIOReg, ((source << 8) & 0xff00) | 0x2C);
+ outw(pCir->PIOReg, ((source) & 0xff00) | 0x2D);
+ outw(pCir->PIOReg, ((source >> 8) & 0x3f00)| 0x2E);
+
+ /* dest */
+ outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+ outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+ outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+ if (!pCir->chip.alp->autoStart)
+ outw(pCir->PIOReg, 0x0231);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentScreenToScreenCopy x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n",
+ x1, y1, x2, y2, w, h);
+ ErrorF("AlpSubsequentScreenToScreenCopy s=%d d=%d ww=%d hh=%d\n",
+ source, dest, ww, hh);
+#endif
+
+}
+
+static void
+AlpSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForSolidFill color=%x rop=%x planemask=%x\n",
+ color, rop, planemask);
+#endif
+ WAIT;
+
+ SetupForRop(rop);
+
+ switch (pCir -> Chipset)
+ {
+ case PCI_CHIP_GD7548:
+ /* The GD7548 does not (apparently) support solid filling
+ directly, it always need an actual source.
+ We therefore use it as a pattern fill with a solid
+ pattern */
+ {
+ int source = pAlp->monoPattern8x8;
+ /* source = 8x8 solid mono pattern */
+ outw(pCir->PIOReg, ((source << 8) & 0xff00) | 0x2C);
+ outw(pCir->PIOReg, ((source) & 0xff00) | 0x2D);
+ outw(pCir->PIOReg, ((source >> 8) & 0x3f00) | 0x2E);
+ /* memset() may not be the fastest */
+ memset(pCir->FbBase + pAlp->monoPattern8x8, 0xFF, 8);
+ write_mem_barrier();
+ break;
+ }
+ default:
+ /* GR33 = 0x04 => does not exist on GD7548 */
+ outw(pCir->PIOReg, 0x0433);
+ }
+
+ /* GR30 = color expansion, pattern copy */
+ /* Choses 8bpp / 16bpp color expansion */
+ outw(pCir->PIOReg, 0xC030 |((pScrn->bitsPerPixel - 8) << 9));
+
+ outw(pCir->PIOReg, ((color << 8) & 0xff00) | 0x01);
+ outw(pCir->PIOReg, ((color) & 0xff00) | 0x11);
+ outw(pCir->PIOReg, ((color >> 8) & 0xff00) | 0x13);
+ outw(pCir->PIOReg, 0x15);
+
+ /* Set dest pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+}
+
+static void
+AlpSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int dest;
+ int hh, ww;
+ int pitch = pCir->pitch;
+
+ ww = (w * pScrn->bitsPerPixel / 8) - 1;
+ hh = h - 1;
+ dest = y * pitch + x * pScrn->bitsPerPixel / 8;
+
+ WAIT;
+
+ /* Width */
+ outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+ outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+ /* Height */
+ outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+ outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+
+ /* dest */
+ outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+ outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+ outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+ if (!pCir->chip.alp->autoStart)
+ outw(pCir->PIOReg, 0x0231);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentSolidFillRect x=%d y=%d w=%d h=%d\n",
+ x, y, w, h);
+#endif
+
+}
+
+static void
+AlpSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int patx, int paty,
+ int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupFor8x8PatternFill pattern=%8x%8x"
+ "fg=%x bg=%x rop=%x planemask=%x\n",
+ patx, paty, fg, bg, rop, planemask);
+#endif
+ WAIT;
+
+ SetupForRop(rop);
+
+ {
+ int source = pAlp->monoPattern8x8;
+ /* source = 8x8 solid mono pattern */
+ outw(pCir->PIOReg, ((source << 8) & 0xff00) | 0x2C);
+ outw(pCir->PIOReg, ((source) & 0xff00) | 0x2D);
+ outw(pCir->PIOReg, ((source >> 8) & 0x3f00) | 0x2E);
+ }
+
+ /* GR30 = color expansion, pattern copy */
+ /* Choses 8bpp / 16bpp color expansion */
+ if (bg == -1)
+ { /* transparency requested */
+ outw(pCir->PIOReg, 0xC830 |((pScrn->bitsPerPixel - 8) << 9));
+
+ bg = ~fg;
+ /* transparent color compare */
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x34);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x35);
+
+ /* transparent color mask = 0 (all bits matters) */
+ outw(pCir->PIOReg, 0x38);
+ outw(pCir->PIOReg, 0x39);
+ }
+ else
+ {
+ outw(pCir->PIOReg, 0xC030 |((pScrn->bitsPerPixel - 8) << 9));
+ }
+
+ outw(pCir->PIOReg, ((fg << 8) & 0xff00) | 0x01);
+ outw(pCir->PIOReg, ((fg) & 0xff00) | 0x11);
+
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x00);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x10);
+
+ /* Set dest pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+}
+
+static void
+AlpSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ int dest;
+ int hh, ww;
+ int pitch = pCir->pitch;
+
+ ww = (w * pScrn->bitsPerPixel / 8) - 1;
+ hh = h - 1;
+ dest = y * pitch + x * pScrn->bitsPerPixel / 8;
+
+ WAIT;
+ /* memcpy() may not be the fastest */
+ memcpy(pCir->FbBase + pAlp->monoPattern8x8, &patx, 4);
+ memcpy(pCir->FbBase + pAlp->monoPattern8x8 + 4, &paty, 4);
+ write_mem_barrier();
+
+ /* Width */
+ outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+ outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+ /* Height */
+ outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+ outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+
+ /* dest */
+ outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+ outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+ outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+ if (!pCir->chip.alp->autoStart)
+ outw(pCir->PIOReg, 0x0231);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequent8x8PatternFill x=%d y=%d w=%d h=%d\n",
+ x, y, w, h);
+#endif
+
+}
+
+#if 0
+/* XF86 does not support byte-padded scanlines */
+
+static void
+AlpSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForCPUToScreenColorExpandFill "
+ "fg=%x bg=%x rop=%x planemask=%x\n",
+ fg, bg, rop, planemask);
+#endif
+ WAIT;
+
+ SetupForRop(rop);
+
+ /* GR30 = color expansion, CPU->display copy */
+ /* Choses 8bpp / 16bpp color expansion */
+ if (bg == -1)
+ { /* transparency requested */
+ outw(pCir->PIOReg, 0x8C30 |((pScrn->bitsPerPixel - 8) << 9));
+
+ bg = ~fg;
+ /* transparent color compare */
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x34);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x35);
+
+ /* transparent color mask = 0 (all bits matters) */
+ outw(pCir->PIOReg, 0x38);
+ outw(pCir->PIOReg, 0x39);
+ }
+ else
+ {
+ outw(pCir->PIOReg, 0x8430 |((pScrn->bitsPerPixel - 8) << 9));
+ }
+
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x00);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x10);
+
+ outw(pCir->PIOReg, ((fg << 8) & 0xff00) | 0x01);
+ outw(pCir->PIOReg, ((fg) & 0xff00) | 0x11);
+
+ /* Set dest pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+}
+
+static void
+AlpSubsequentCPUToScreenColorExpandFill(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int skipleft)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int dest;
+ int hh, ww;
+ int pitch = pCir->pitch;
+
+ ww = (((w+7) & ~7) * pScrn->bitsPerPixel / 8) - 1;
+ hh = h - 1;
+ dest = y * pitch + x * pScrn->bitsPerPixel / 8;
+
+ WAIT;
+
+ /* Width */
+ outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+ outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+ /* Height */
+ outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+ outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+
+ /* source = CPU ; description of bit 2 of GR30 in the 7548 manual
+ says that if we do color expansion we must zero the source
+ adress registers (GR2C, GR2D, GR2E) */
+ outw(pCir->PIOReg, 0x2C);
+ outw(pCir->PIOReg, 0x2D);
+ outw(pCir->PIOReg, 0x2E);
+
+ /* dest */
+ outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+ outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+ outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+ if (!pCir->chip.alp->autoStart)
+ outw(pCir->PIOReg, 0x0231);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentCPUToScreenColorExpandFill x=%d y=%d w=%d h=%d\n",
+ x, y, w, h);
+#endif
+}
+#endif
+
+#if 1
+static void
+AlpSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int planemask)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForCPUToScreenColorExpandFill "
+ "fg=%x bg=%x rop=%x planemask=%x, bpp=%d\n",
+ fg, bg, rop, planemask, pScrn->bitsPerPixel);
+#endif
+ WAIT;
+
+ SetupForRop(rop);
+
+ /* GR30 = color expansion, CPU->display copy */
+ /* Choses 8bpp / 16bpp color expansion */
+ if (bg == -1)
+ { /* transparency requested */
+ if (pScrn->bitsPerPixel > 8) /* 16 bpp */
+ {
+ outw(pCir->PIOReg, 0x9C30);
+
+ bg = ~fg;
+ /* transparent color compare */
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x34);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x35);
+ } else /* 8 bpp */
+ {
+ outw(pCir->PIOReg, 0x8C30);
+
+ bg = ~fg;
+ /* transparent color compare */
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x34);
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x35);
+ }
+
+ /* transparent color mask = 0 (all bits matters) */
+ outw(pCir->PIOReg, 0x38);
+ outw(pCir->PIOReg, 0x39);
+ }
+ else
+ {
+ outw(pCir->PIOReg, 0x8430 |((pScrn->bitsPerPixel - 8) << 9));
+ }
+
+ outw(pCir->PIOReg, ((bg << 8) & 0xff00) | 0x00);
+ outw(pCir->PIOReg, ((bg) & 0xff00) | 0x10);
+
+ outw(pCir->PIOReg, ((fg << 8) & 0xff00) | 0x01);
+ outw(pCir->PIOReg, ((fg) & 0xff00) | 0x11);
+
+ /* Set dest pitch */
+ outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+ outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+}
+
+static void
+AlpSubsequentScanlineCPUToScreenColorExpandFill(
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int skipleft)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+
+ int pitch = pCir->pitch;
+
+ pAlp->SubsequentColorExpandScanlineByteWidth =
+ (w * pScrn->bitsPerPixel / 8) - 1;
+ pAlp->SubsequentColorExpandScanlineDWordWidth =
+ (w + 31) >> 5;
+ pAlp->SubsequentColorExpandScanlineDest =
+ y * pitch + x * pScrn->bitsPerPixel / 8;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentScanlineCPUToScreenColorExpandFill x=%d y=%d w=%d h=%d skipleft=%d\n",
+ x, y, w, h, skipleft);
+#endif
+}
+
+static void
+AlpSubsequentColorExpandScanline(
+ ScrnInfoPtr pScrn,
+ int bufno)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ int dest=pAlp->SubsequentColorExpandScanlineDest;
+ int ww=pAlp->SubsequentColorExpandScanlineByteWidth;
+ int width=pAlp->SubsequentColorExpandScanlineDWordWidth;
+ CARD32* from;
+ volatile CARD32 *to;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentColorExpandScanline\n");
+#endif
+
+ pAlp->SubsequentColorExpandScanlineDest += pCir->pitch;
+
+ to = (CARD32*) pCir->FbBase;
+ from = (CARD32*) (pCir->ScanlineColorExpandBuffers[bufno]);
+ WAIT_1;
+
+ /* Width */
+ outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+ outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+
+ /* Height = 1 */
+ outw(pCir->PIOReg, 0x22);
+ outw(pCir->PIOReg, 0x23);
+
+ /* source = CPU ; description of bit 2 of GR30 in the 7548 manual
+ says that if we do color expansion we must zero the source
+ adress registers (GR2C, GR2D, GR2E) */
+ outw(pCir->PIOReg, 0x2C);
+ outw(pCir->PIOReg, 0x2D);
+ outw(pCir->PIOReg, 0x2E);
+
+ /* dest */
+ outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+ outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+ write_mem_barrier();
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentColorExpandScanline (2)\n");
+#endif
+
+ outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+ if (!pCir->chip.alp->autoStart)
+ outw(pCir->PIOReg, 0x0231);
+
+ {
+ int i;
+ for (i=0; i<width; i++)
+ *to=*(from++);
+ write_mem_barrier();
+ }
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentColorExpandScanline (3)\n");
+#endif
+}
+#endif
+
+static void
+AlpAccelEngineInit(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+
+ outw(pCir->PIOReg, 0x200E); /* enable writes to gr33 */
+ /* Setup things for autostart */
+ if (pCir->properties & ACCEL_AUTOSTART) {
+ outw(pCir->PIOReg, 0x8031); /* enable autostart */
+ pCir->chip.alp->waitMsk = 0x10;
+ pCir->chip.alp->autoStart = TRUE;
+ } else {
+ pCir->chip.alp->waitMsk = 0x1;
+ pCir->chip.alp->autoStart = FALSE;
+ }
+}
+
+Bool
+AlpXAAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CirPtr pCir = CIRPTR(pScrn);
+ AlpPtr pAlp = ALPPTR(pCir);
+ XAAInfoRecPtr XAAPtr;
+
+ pCir->InitAccel = AlpAccelEngineInit;
+#ifdef ALP_DEBUG
+ ErrorF("AlpXAAInit\n");
+#endif
+
+ XAAPtr = XAACreateInfoRec();
+ if (!XAAPtr) return FALSE;
+
+ /* Pixmap cache */
+ XAAPtr->Flags |= LINEAR_FRAMEBUFFER;
+ XAAPtr->Sync = AlpSync;
+
+ XAAPtr->SetupForScreenToScreenCopy = AlpSetupForScreenToScreenCopy;
+ XAAPtr->SubsequentScreenToScreenCopy = AlpSubsequentScreenToScreenCopy;
+ XAAPtr->ScreenToScreenCopyFlags =
+ NO_TRANSPARENCY | NO_PLANEMASK;
+
+ XAAPtr->SetupForSolidFill = AlpSetupForSolidFill;
+ XAAPtr->SubsequentSolidFillRect = AlpSubsequentSolidFillRect;
+ XAAPtr->SubsequentSolidFillTrap = NULL;
+ XAAPtr->SolidFillFlags = NO_PLANEMASK;
+
+ if (pCir->Chipset == PCI_CHIP_GD7548) {
+ if (pAlp->monoPattern8x8) {
+ XAAPtr->SetupForMono8x8PatternFill
+ = AlpSetupForMono8x8PatternFill;
+ XAAPtr->SubsequentMono8x8PatternFillRect
+ = AlpSubsequentMono8x8PatternFillRect;
+ XAAPtr->SubsequentMono8x8PatternFillTrap = NULL;
+ XAAPtr->Mono8x8PatternFillFlags =
+ NO_PLANEMASK |
+ HARDWARE_PATTERN_PROGRAMMED_BITS | BIT_ORDER_IN_BYTE_MSBFIRST;
+ }
+#if 1
+ /* kludge: since XF86 does not support byte-padded
+ mono bitmaps (only dword-padded), use the
+ scanline version */
+ XAAPtr->SetupForScanlineCPUToScreenColorExpandFill =
+ AlpSetupForScanlineCPUToScreenColorExpandFill;
+ XAAPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ AlpSubsequentScanlineCPUToScreenColorExpandFill;
+ XAAPtr->SubsequentColorExpandScanline =
+ AlpSubsequentColorExpandScanline;
+ {
+ const int NumScanlineColorExpandBuffers = 2;
+ int i;
+ int buffer_size = (pCir->pScrn->virtualX + 31) & ~31;
+#ifdef ALP_DEBUG
+ ErrorF("Computing buffers for %d pixel lines\n",
+ pCir->pScrn->virtualX);
+#endif
+ XAAPtr->NumScanlineColorExpandBuffers =
+ NumScanlineColorExpandBuffers;
+ XAAPtr->ScanlineColorExpandBuffers =
+ pCir->ScanlineColorExpandBuffers = (unsigned char **)
+ (malloc(sizeof(unsigned char *) *
+ NumScanlineColorExpandBuffers));
+ /* TODO: are those mallocs to be freed ? */
+
+ for(i=0; i<NumScanlineColorExpandBuffers; i++)
+ pCir->ScanlineColorExpandBuffers[i] = (unsigned char *)
+ malloc(buffer_size);
+ }
+ XAAPtr->ScanlineCPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | BIT_ORDER_IN_BYTE_MSBFIRST |
+ SCANLINE_PAD_DWORD | ROP_NEEDS_SOURCE;
+#endif
+#if 0
+ /* Currently disabled: XF86 sends DWORD-padded data,
+ not byte-padded */
+ XAAPtr->SetupForCPUToScreenColorExpandFill =
+ AlpSetupForCPUToScreenColorExpandFill;
+ XAAPtr->SubsequentCPUToScreenColorExpandFill =
+ AlpSubsequentCPUToScreenColorExpandFill;
+ XAAPtr->ColorExpandBase = pCir->FbBase + 4;
+ XAAPtr->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK | BIT_ORDER_IN_BYTE_MSBFIRST |
+ SCANLINE_PAD_DWORD | ROP_NEEDS_SOURCE |
+ CPU_TRANSFER_PAD_DWORD | CPU_TRANSFER_BASE_FIXED;
+#endif
+ }
+
+ AlpAccelEngineInit(pScrn);
+
+ pCir->AccelInfoRec = XAAPtr;
+
+ if (!XAAInit(pScreen, XAAPtr))
+ return FALSE;
+
+ return TRUE;
+}
+
diff --git a/src/alp_xaam.c b/src/alp_xaam.c
new file mode 100644
index 0000000..2f25092
--- /dev/null
+++ b/src/alp_xaam.c
@@ -0,0 +1,271 @@
+/* (c) Itai Nahshon */
+/* #define DEBUG */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_xaam.c,v 1.8 2002/07/10 02:36:50 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _ALP_PRIVATE_
+#include "alp.h"
+
+#ifdef DEBUG
+#define minb(p) \
+ (ErrorF("minb(%X)\n", p),\
+ MMIO_IN8(pCir->chip.alp->BLTBase, (p)))
+#define moutb(p,v) \
+ (ErrorF("moutb(%X, %X)\n", p,v),\
+ MMIO_OUT8(pCir->chip.alp->BLTBase, (p),(v)))
+#define vga_minb(p) \
+ (ErrorF("minb(%X)\n", p),\
+ MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p))))
+#define vga_moutb(p,v) \
+ { ErrorF("moutb(%X, %X)\n", p,v);\
+ MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v));}
+#define minl(p) \
+ (ErrorF("minl(%X)\n", p),\
+ MMIO_IN32(pCir->chip.alp->BLTBase, (p)))
+#define moutl(p,v) \
+ (ErrorF("moutl(%X, %X)\n", p,v),\
+ MMIO_OUT32(pCir->chip.alp->BLTBase, (p),(v)))
+#else
+#define minb(p) MMIO_IN8(pCir->chip.alp->BLTBase, (p))
+#define moutb(p,v) MMIO_OUT8(pCir->chip.alp->BLTBase, (p),(v))
+#define vga_minb(p) MMIO_IN8(hwp->MMIIOBase, (hwp->MMIOOffset + (p)))
+#define vga_moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
+#define minl(p) MMIO_IN32(pCir->chip.alp->BLTBase, (p))
+#define moutl(p,v) MMIO_OUT32(pCir->chip.alp->BLTBase, (p),(v))
+#endif
+
+static const CARD8 translated_rop[] =
+{
+ /* GXclear */ 0x00U,
+ /* GXand */ 0x05U,
+ /* GXandreverse */ 0x09U,
+ /* GXcopy */ 0x0DU,
+ /* GXandinversted */ 0x50U,
+ /* GXnoop */ 0x06U,
+ /* GXxor */ 0x59U,
+ /* GXor */ 0x6DU,
+ /* GXnor */ 0x90U,
+ /* GXequiv */ 0x95U,
+ /* GXinvert */ 0x0BU,
+ /* GXorReverse */ 0xADU,
+ /* GXcopyInverted */ 0xD0U,
+ /* GXorInverted */ 0xD6U,
+ /* GXnand */ 0xDAU,
+ /* GXset */ 0x0EU
+};
+
+#define WAIT while(minl(0x40) & pCir->chip.alp->waitMsk){};
+#define WAIT_1 while((minl(0x40)) & 0x1){};
+
+static void AlpSync(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+#ifdef ALP_DEBUG
+ ErrorF("AlpSync mm\n");
+#endif
+ WAIT_1;
+ return;
+}
+
+static void
+AlpSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int trans_color)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int pitch = pCir->pitch;
+
+ WAIT;
+
+ pCir->chip.alp->transRop = translated_rop[rop] << 16;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForScreenToScreenCopy xdir=%d ydir=%d rop=%x planemask=%x trans_color=%x\n",
+ xdir, ydir, rop, planemask, trans_color);
+#endif
+ moutl(0x0C, (pitch << 16) | pitch);
+
+}
+
+static void
+AlpSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
+ int y2, int w, int h)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int source, dest;
+ int hh, ww;
+ int decrement = 0;
+ int pitch = pCir->pitch;
+
+ ww = ((w * pScrn->bitsPerPixel / 8) - 1) & 0x1fff;
+ hh = (h - 1) & 0x1fff;
+ dest = y2 * pitch + x2 * pScrn->bitsPerPixel / 8;
+ source = y1 * pitch + x1 * pScrn->bitsPerPixel / 8;
+ if (dest > source) {
+ decrement = 1;
+ dest += hh * pitch + ww;
+ source += hh * pitch + ww;
+ }
+
+ WAIT;
+
+ /* Width / Height */
+ moutl(0x08, (hh << 16) | ww);
+ /* source */
+ moutl(0x14, source & 0x3fffff);
+ moutl(0x18, pCir->chip.alp->transRop | decrement);
+
+ /* dest */
+ write_mem_barrier();
+ moutl(0x10, dest & 0x3fffff);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentScreenToScreenCopy x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n",
+ x1, y1, x2, y2, w, h);
+ ErrorF("AlpSubsequentScreenToScreenCopy s=%d d=%d ww=%d hh=%d\n",
+ source, dest, ww, hh);
+#endif
+ if (!pCir->chip.alp->autoStart) {
+ CARD32 val = minl(0x40);
+ moutl(0x40,val | 0x02);
+ }
+ write_mem_barrier();
+}
+
+
+static void
+AlpSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int pitch = pCir->pitch;
+
+ WAIT;
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSetupForSolidFill color=%x rop=%x planemask=%x\n",
+ color, rop, planemask);
+#endif
+
+ moutl(0x04, color & 0xffffff);
+
+ /* Set dest pitch */
+ moutl(0x0C, pitch & 0x1fff);
+ moutl(0x18, (((pScrn->bitsPerPixel - 8) << 1))
+ | translated_rop[rop] << 16
+ | 0x040000C0);
+}
+
+static void
+AlpSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ int dest;
+ int hh, ww;
+ CirPtr pCir = CIRPTR(pScrn);
+ int pitch = pCir->pitch;
+
+ ww = ((w * pScrn->bitsPerPixel / 8) - 1) & 0x1fff;
+ hh = (h - 1) & 0x7ff;
+ dest = y * pitch + x * pScrn->bitsPerPixel / 8;
+
+ WAIT;
+
+ /* Width / Height */
+ write_mem_barrier();
+ moutl(0x08, (hh << 16) | ww);
+
+#ifdef ALP_DEBUG
+ ErrorF("AlpSubsequentSolidFillRect x=%d y=%d w=%d h=%d\n",
+ x, y, w, h);
+#endif
+ /* dest */
+ moutl(0x10, (dest & 0x3fffff));
+
+ if (!pCir->chip.alp->autoStart) {
+ CARD32 val = minl(0x40);
+ moutl(0x40, val | 0x02);
+ }
+ write_mem_barrier();
+}
+
+static void
+AlpAccelEngineInit(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CirPtr pCir = CIRPTR(pScrn);
+
+ if (pCir->Chipset != PCI_CHIP_GD7548) {
+ vga_moutb(0x3CE, 0x0E); /* enable writes to gr33 */
+ vga_moutb(0x3CF, 0x20); /* enable writes to gr33 */
+ }
+ if (pCir->properties & ACCEL_AUTOSTART) {
+ moutl(0x40, 0x80); /* enable autostart */
+ pCir->chip.alp->waitMsk = 0x10;
+ pCir->chip.alp->autoStart = TRUE;
+ } else {
+ pCir->chip.alp->waitMsk = 0x1;
+ pCir->chip.alp->autoStart = FALSE;
+ }
+}
+
+Bool
+AlpXAAInitMMIO(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CirPtr pCir = CIRPTR(pScrn);
+ XAAInfoRecPtr XAAPtr;
+
+ pCir->InitAccel = AlpAccelEngineInit;
+#ifdef ALP_DEBUG
+ ErrorF("AlpXAAInitMM\n");
+#endif
+
+ XAAPtr = XAACreateInfoRec();
+ if (!XAAPtr) return FALSE;
+
+ XAAPtr->Flags |= LINEAR_FRAMEBUFFER;
+ XAAPtr->Sync = AlpSync;
+
+ XAAPtr->SetupForScreenToScreenCopy = AlpSetupForScreenToScreenCopy;
+ XAAPtr->SubsequentScreenToScreenCopy = AlpSubsequentScreenToScreenCopy;
+ XAAPtr->ScreenToScreenCopyFlags =
+ (NO_TRANSPARENCY | NO_PLANEMASK);
+
+ XAAPtr->SetupForSolidFill = AlpSetupForSolidFill;
+ XAAPtr->SubsequentSolidFillRect = AlpSubsequentSolidFillRect;
+ XAAPtr->SubsequentSolidFillTrap = NULL;
+ XAAPtr->SolidFillFlags = NO_PLANEMASK;
+
+ switch (pCir->Chipset) {
+ case PCI_CHIP_GD5480:
+ case PCI_CHIP_GD5446:
+ pCir->chip.alp->BLTBase = pCir->IOBase + 0x100;
+ break;
+ default:
+ pCir->chip.alp->BLTBase = pCir->IOBase;
+ break;
+ }
+
+ AlpAccelEngineInit(pScrn);
+
+ pCir->AccelInfoRec = XAAPtr;
+
+ if (!XAAInit(pScreen, XAAPtr))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+
+
diff --git a/src/cir.h b/src/cir.h
new file mode 100644
index 0000000..536f7aa
--- /dev/null
+++ b/src/cir.h
@@ -0,0 +1,97 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir.h,v 1.21 2002/01/25 21:56:01 tsi Exp $ */
+
+/* (c) Itai Nahshon */
+
+#ifndef CIR_H
+#define CIR_H
+
+#include "xf86Cursor.h"
+#include "xaa.h"
+#include "xf86i2c.h"
+
+/* Card-specific driver information */
+#define CIRPTR(p) ((CirPtr)((p)->driverPrivate))
+struct lgRec;
+struct alpRec;
+
+typedef struct {
+ ScrnInfoPtr pScrn;
+ CARD32 properties;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ IOADDRESS PIOReg;
+ union {
+ struct lgRec *lg;
+ struct alpRec *alp;
+ } chip;
+ EntityInfoPtr pEnt;
+ int Chipset;
+ int ChipRev;
+ int Rounding;
+ int BppShift;
+ Bool HasFBitBlt;
+ CARD32 IOAddress;
+ CARD32 FbAddress;
+ unsigned char * IOBase;
+ unsigned char * FbBase;
+ long FbMapSize;
+ long IoMapSize;
+ int MinClock;
+ int MaxClock;
+ Bool NoAccel;
+ Bool HWCursor;
+ Bool UseMMIO;
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ int DGAnumModes;
+ DGAModePtr DGAModes;
+ Bool DGAactive;
+ Bool (*DGAModeInit)(ScrnInfoPtr, DisplayModePtr);
+ int DGAViewportStatus;
+ I2CBusPtr I2CPtr1;
+ I2CBusPtr I2CPtr2;
+ CloseScreenProcPtr CloseScreen;
+
+ Bool CursorIsSkewed;
+ Bool shadowFB;
+ int rotate;
+ int ShadowPitch;
+ unsigned char * ShadowPtr;
+ void (*PointerMoved)(int index, int x, int y);
+ int pitch;
+
+ unsigned char ** ScanlineColorExpandBuffers;
+ void (*InitAccel)(ScrnInfoPtr);
+ int offscreen_size;
+ int offscreen_offset;
+ OptionInfoPtr Options;
+} CirRec, *CirPtr;
+
+/* CirrusClk.c */
+extern Bool
+CirrusFindClock(int *rfreq, int max_clock, int *num_out, int *den_out);
+
+/* cir_driver.c */
+extern SymTabRec CIRChipsets[];
+extern PciChipsets CIRPciChipsets[];
+
+extern Bool CirMapMem(CirPtr pCir, int scrnIndex);
+extern Bool CirUnmapMem(CirPtr pCir, int scrnIndex);
+extern void cirProbeDDC(ScrnInfoPtr pScrn, int index);
+
+/* cir_dga.c */
+extern Bool CirDGAInit(ScreenPtr pScreen);
+
+/* in cir_shadow.c */
+void cirPointerMoved(int index, int x, int y);
+void cirRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void cirRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void cirRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void cirRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+void cirRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+/* properties */
+#define HWCUR64 0x1
+#define ACCEL_AUTOSTART 0x2
+
+#endif /* CIR_H */
diff --git a/src/cir_dga.c b/src/cir_dga.c
new file mode 100644
index 0000000..7677160
--- /dev/null
+++ b/src/cir_dga.c
@@ -0,0 +1,256 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_dga.c,v 1.7 2001/10/01 13:44:05 eich Exp $ */
+/*
+ * Copyright 2000 by Egbert Eich
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * EGBERT EICH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ * by: Egbert Eich
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "vgaHW.h"
+#include "cir.h"
+#include "dgaproc.h"
+
+static Bool Cir_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool Cir_SetMode(ScrnInfoPtr, DGAModePtr);
+static void Cir_Sync(ScrnInfoPtr);
+static int Cir_GetViewport(ScrnInfoPtr);
+static void Cir_SetViewport(ScrnInfoPtr, int, int, int);
+static void Cir_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void Cir_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+/*
+static void Cir_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+*/
+
+static
+DGAFunctionRec CirDGAFuncs = {
+ Cir_OpenFramebuffer,
+ NULL, /* Cir_CloseFramebuffer */
+ Cir_SetMode,
+ Cir_SetViewport,
+ Cir_GetViewport,
+ Cir_Sync,
+ Cir_FillRect,
+ Cir_BlitRect,
+ NULL /* Cir_BlitTransRect */
+};
+
+
+
+
+Bool
+CirDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CirPtr pCir = CIRPTR(pScrn);
+ DGAModePtr modes = NULL, newmodes = NULL, currentMode;
+ DisplayModePtr pMode, firstMode;
+ int Bpp = pScrn->bitsPerPixel >> 3;
+ int num = 0;
+ int imlines = (pScrn->videoRam * 1024) /
+ (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+
+
+ if (!pCir->DGAnumModes) {
+ pMode = firstMode = pScrn->modes;
+ while (pMode) {
+ newmodes = xrealloc(modes, (num + 1) * sizeof (DGAModeRec));
+ if (!newmodes) {
+ xfree(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+ currentMode = modes + num;
+ num++;
+ (void)memset(currentMode, 1, sizeof(DGAModeRec));
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_PIXMAP_AVAILABLE
+ | ((!pCir->NoAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
+ if (pMode->Flags & V_DBLSCAN)
+ currentMode->flags |= DGA_DOUBLESCAN;
+ if(pMode->Flags & V_INTERLACE)
+ currentMode->flags |= DGA_INTERLACED;
+ currentMode->byteOrder = pScrn->imageByteOrder;
+ currentMode->depth = pScrn->depth;
+ currentMode->bitsPerPixel = pScrn->bitsPerPixel;
+ currentMode->red_mask = pScrn->mask.red;
+ currentMode->green_mask = pScrn->mask.green;
+ currentMode->blue_mask = pScrn->mask.blue;
+ currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ currentMode->xViewportStep = 1; /* The granularity of x and y pos. */
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = 0 /*DGA_FLIP_RETRACE*/;
+ currentMode->offset = 0;
+ currentMode->address = pCir->FbBase;
+ currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+ currentMode->pixmapWidth = currentMode->imageWidth
+ = pScrn->displayWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight = imlines;
+ currentMode->maxViewportX = currentMode->imageWidth -
+ currentMode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = currentMode->imageHeight -
+ currentMode->viewportHeight;
+
+ pMode = pMode->next;
+ if(pMode == firstMode)
+ break;
+ }
+ pCir->DGAnumModes = num;
+ pCir->DGAModes = modes;
+ }
+ return DGAInit(pScreen, &CirDGAFuncs, pCir->DGAModes, pCir->DGAnumModes);
+}
+
+static Bool
+Cir_OpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+){
+ CirPtr pCir = CIRPTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)(long)pCir->FbAddress;
+ *size = pCir->FbMapSize;
+ *offset = 0; /* Always */
+ *flags = 0; /* Root permissions OS-dependent */
+
+ return TRUE;
+}
+
+
+static Bool
+Cir_SetMode(
+ ScrnInfoPtr pScrn,
+ DGAModePtr pMode
+){
+ CirPtr pCir = CIRPTR(pScrn);
+ static int OldDisplayWidth[MAXSCREENS];
+ int index = pScrn->pScreen->myNum;
+ Bool ret = FALSE;
+
+ if(!pMode) { /* restore the original mode */
+ /* put the ScreenParameters back */
+ pScrn->displayWidth = OldDisplayWidth[index];
+ ret = pCir->DGAModeInit(xf86Screens[index], pScrn->currentMode);
+ pCir->DGAactive = FALSE;
+ } else {
+ if(!pCir->DGAactive) { /* save the old parameters */
+ OldDisplayWidth[index] = pScrn->displayWidth;
+
+ pCir->DGAactive = TRUE;
+ }
+ pScrn->displayWidth = pMode->bytesPerScanline /
+ (pMode->bitsPerPixel >> 3);
+
+ ret = pCir->DGAModeInit(xf86Screens[index], pMode->mode);
+ }
+ return ret;
+}
+
+static void
+Cir_SetViewport(
+ ScrnInfoPtr pScrn,
+ int x, int y,
+ int flags
+){
+ CirPtr pCir = CIRPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+
+ while((hwp->readST01(hwp) & 0x08));
+ while(!(hwp->readST01(hwp) & 0x08));
+
+ pCir->DGAViewportStatus = 0; /* AdjustFrame loops until finished */
+}
+
+static int
+Cir_GetViewport(
+ ScrnInfoPtr pScrn
+){
+ CirPtr pCir = CIRPTR(pScrn);
+
+ return pCir->DGAViewportStatus;
+}
+
+
+
+static void
+Cir_Sync(
+ ScrnInfoPtr pScrn
+){
+ CirPtr pCir = CIRPTR(pScrn);
+
+ if(pCir->AccelInfoRec) {
+ (*pCir->AccelInfoRec->Sync)(pScrn);
+ }
+}
+
+static void
+Cir_FillRect (
+ ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ unsigned long color
+){
+ CirPtr pCir = CIRPTR(pScrn);
+
+ if(pCir->AccelInfoRec) {
+ (*pCir->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pCir->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ SET_SYNC_FLAG(pCir->AccelInfoRec);
+ }
+}
+
+static void
+Cir_BlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+){
+ CirPtr pCir = CIRPTR(pScrn);
+
+ if(pCir->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pCir->AccelInfoRec->SetupForScreenToScreenCopy)(
+ pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pCir->AccelInfoRec->SubsequentScreenToScreenCopy)(
+ pScrn, srcx, srcy, dstx, dsty, w, h);
+ SET_SYNC_FLAG(pCir->AccelInfoRec);
+ }
+}
diff --git a/src/cir_driver.c b/src/cir_driver.c
new file mode 100644
index 0000000..b8c2c49
--- /dev/null
+++ b/src/cir_driver.c
@@ -0,0 +1,409 @@
+/*
+ * 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/cir_driver.c,v 1.68 2001/06/13 23:34:09 dawes Exp $ */
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "xf86Resources.h"
+
+/* All drivers need this */
+#include "xf86_ansic.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"
+
+#include "cir.h"
+#include "alp.h"
+#include "lg.h"
+
+#include "vbe.h"
+
+/*
+ * Forward definitions for the functions that make up the driver.
+ */
+
+/* Mandatory functions */
+
+static const OptionInfoRec * CIRAvailableOptions(int chipid, int busid);
+static void CIRIdentify(int flags);
+static Bool CIRProbe(DriverPtr drv, int flags);
+
+static Bool lg_loaded = FALSE;
+static Bool alp_loaded = FALSE;
+
+#define VERSION 4000
+#define CIR_NAME "CIRRUS"
+#define CIR_DRIVER_NAME "cirrus"
+#define CIR_MAJOR_VERSION 1
+#define CIR_MINOR_VERSION 0
+#define CIR_PATCHLEVEL 0
+
+/*
+ * This contains the functions needed by the server after loading the
+ * driver module. It must be supplied, and gets added the driver list by
+ * the Module Setup funtion in the dynamic case. In the static case a
+ * reference to this is compiled in, and this requires that the name of
+ * this DriverRec be an upper-case version of the driver name.
+ */
+
+DriverRec CIRRUS = {
+ VERSION,
+ CIR_DRIVER_NAME,
+ CIRIdentify,
+ CIRProbe,
+ CIRAvailableOptions,
+ NULL,
+ 0
+};
+
+/* Supported chipsets */
+SymTabRec CIRChipsets[] = {
+ { PCI_CHIP_GD5430, "CLGD5430" },
+ { PCI_CHIP_GD5434_4, "CLGD5434-4" },
+ { PCI_CHIP_GD5434_8, "CLGD5434-8" },
+ { PCI_CHIP_GD5436, "CLGD5436" },
+/* { PCI_CHIP_GD5440, "CLGD5440" }, */
+ { PCI_CHIP_GD5446, "CLGD5446" },
+ { PCI_CHIP_GD5480, "CLGD5480" },
+ { PCI_CHIP_GD5462, "CL-GD5462" },
+ { PCI_CHIP_GD5464, "CL-GD5464" },
+ { PCI_CHIP_GD5464BD, "CL-GD5464BD" },
+ { PCI_CHIP_GD5465, "CL-GD5465" },
+ { PCI_CHIP_GD7548, "CL-GD7548" },
+ {-1, NULL }
+};
+
+/* List of PCI chipset names */
+PciChipsets CIRPciChipsets[] = {
+ { PCI_CHIP_GD5430, PCI_CHIP_GD5430, RES_SHARED_VGA },
+ { PCI_CHIP_GD5434_4,PCI_CHIP_GD5434_4, RES_SHARED_VGA },
+ { PCI_CHIP_GD5434_8,PCI_CHIP_GD5434_8, RES_SHARED_VGA },
+ { PCI_CHIP_GD5436, PCI_CHIP_GD5436, RES_SHARED_VGA },
+/* { PCI_CHIP_GD5440, PCI_CHIP_GD5440, RES_SHARED_VGA }, */
+ { PCI_CHIP_GD5446, PCI_CHIP_GD5446, RES_SHARED_VGA },
+ { PCI_CHIP_GD5480, PCI_CHIP_GD5480, RES_SHARED_VGA },
+ { PCI_CHIP_GD5462, PCI_CHIP_GD5462, RES_SHARED_VGA },
+ { PCI_CHIP_GD5464, PCI_CHIP_GD5464, RES_SHARED_VGA },
+ { PCI_CHIP_GD5464BD,PCI_CHIP_GD5464BD, RES_SHARED_VGA },
+ { PCI_CHIP_GD5465, PCI_CHIP_GD5465, RES_SHARED_VGA },
+ { PCI_CHIP_GD7548, PCI_CHIP_GD7548, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED}
+};
+
+/*
+ * 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 *alpSymbols[] = {
+ "AlpAvailableOptions",
+ "AlpProbe",
+ NULL
+};
+static const char *lgSymbols[] = {
+ "LgAvailableOptions",
+ "LgProbe",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(cirSetup);
+
+static XF86ModuleVersionInfo cirVersRec =
+{
+ "cirrus",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ CIR_MAJOR_VERSION, CIR_MINOR_VERSION, CIR_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV, /* This is a video driver */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+/*
+ * This is the module init data.
+ * Its name has to be the driver name followed by ModuleData.
+ */
+XF86ModuleData cirrusModuleData = { &cirVersRec, cirSetup, NULL };
+
+static pointer
+cirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ /* This module should be loaded only once, but check to be sure. */
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&CIRRUS, module, 0);
+
+ LoaderRefSymLists(alpSymbols, lgSymbols, vbeSymbols, NULL);
+ return (pointer)1;
+ }
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+}
+
+#endif /* XFree86LOADER */
+
+/* Mandatory */
+static void
+CIRIdentify(int flags)
+{
+ xf86PrintChipsets(CIR_NAME, "driver for Cirrus chipsets", CIRChipsets);
+}
+
+static const OptionInfoRec *
+CIRAvailableOptions(int chipid, int busid)
+{
+ int chip = chipid & 0xffff;
+
+ switch (chip)
+ {
+ case PCI_CHIP_GD5462:
+ case PCI_CHIP_GD5464:
+ case PCI_CHIP_GD5464BD:
+ case PCI_CHIP_GD5465:
+ if (lg_loaded)
+ return LgAvailableOptions(chipid);
+ else
+ return NULL;
+
+ default:
+ if (alp_loaded)
+ return AlpAvailableOptions(chipid);
+ else
+ return NULL;
+ }
+}
+
+static Bool
+CIRProbe(DriverPtr drv, int flags)
+{
+ int i;
+ GDevPtr *devSections;
+ pciVideoPtr pPci;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+ ScrnInfoPtr (*subProbe)(int entity);
+ ScrnInfoPtr pScrn;
+
+#ifdef CIR_DEBUG
+ ErrorF("CirProbe\n");
+#endif
+
+ /*
+ * For PROBE_DETECT, make sure both sub-modules are loaded before
+ * calling xf86MatchPciInstances(), because the AvailableOptions()
+ * functions may be called before xf86MatchPciInstances() returns.
+ */
+
+ if (flags & PROBE_DETECT) {
+ if (!lg_loaded) {
+ if (xf86LoadDrvSubModule(drv, "cirrus_laguna")) {
+ xf86LoaderReqSymLists(lgSymbols, NULL);
+ lg_loaded = TRUE;
+ }
+ }
+ if (!alp_loaded) {
+ if (xf86LoadDrvSubModule(drv, "cirrus_alpine")) {
+ xf86LoaderReqSymLists(alpSymbols, NULL);
+ alp_loaded = TRUE;
+ }
+ }
+ }
+
+ if ((numDevSections = xf86MatchDevice(CIR_DRIVER_NAME,
+ &devSections)) <= 0) {
+ return FALSE;
+ }
+
+ if (xf86GetPciVideoInfo() == NULL) {
+ /*
+ * We won't let anything in the config file override finding no
+ * PCI video cards at all. This seems reasonable now, but we'll see.
+ */
+ return FALSE;
+ }
+
+ numUsed = xf86MatchPciInstances(CIR_NAME, PCI_VENDOR_CIRRUS,
+ CIRChipsets, CIRPciChipsets, devSections,
+ numDevSections, drv, &usedChips);
+ /* Free it since we don't need that list after this */
+ xfree(devSections);
+ if (numUsed <= 0)
+ return FALSE;
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ /* The Laguna family of chips is so different from the Alpine
+ family that we won't share even the highest-level of
+ functions. But, the Laguna chips /are/ Cirrus chips, so
+ they should be handled in this driver (as opposed to their
+ own driver). */
+ pPci = xf86GetPciInfoForEntity(usedChips[i]);
+ if (pPci->chipType == PCI_CHIP_GD5462 ||
+ pPci->chipType == PCI_CHIP_GD5464 ||
+ pPci->chipType == PCI_CHIP_GD5464BD ||
+ pPci->chipType == PCI_CHIP_GD5465) {
+
+ if (!lg_loaded) {
+ if (!xf86LoadDrvSubModule(drv, "cirrus_laguna"))
+ continue;
+ xf86LoaderReqSymLists(lgSymbols, NULL);
+ lg_loaded = TRUE;
+ }
+ subProbe = LgProbe;
+ } else {
+ if (!alp_loaded) {
+ if (!xf86LoadDrvSubModule(drv, "cirrus_alpine"))
+ continue;
+ xf86LoaderReqSymLists(alpSymbols, NULL);
+ alp_loaded = TRUE;
+ }
+ subProbe = AlpProbe;
+ }
+ pScrn = NULL;
+
+ if ((pScrn = subProbe(usedChips[i]))) {
+ foundScreen = TRUE;
+ /* Fill in what we can of the ScrnInfoRec */
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = CIR_DRIVER_NAME;
+ pScrn->name = CIR_NAME;
+ pScrn->Probe = NULL;
+ }
+ }
+ xfree(usedChips);
+
+ return foundScreen;
+}
+
+/*
+ * Map the framebuffer and MMIO memory.
+ */
+
+Bool
+CirMapMem(CirPtr pCir, int scrnIndex)
+{
+ int mmioFlags;
+
+#ifdef CIR_DEBUG
+ ErrorF("CirMapMem\n");
+#endif
+
+ /*
+ * Map the frame buffer.
+ */
+ if (pCir->FbMapSize) {
+
+ pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
+ pCir->PciTag, pCir->FbAddress,
+ pCir->FbMapSize);
+ if (pCir->FbBase == NULL)
+ return FALSE;
+ }
+
+#ifdef CIR_DEBUG
+ ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase);
+#endif
+
+ /*
+ * Map IO registers to virtual address space
+ */
+ if (pCir->IOAddress == 0) {
+ pCir->IOBase = NULL; /* Until we are ready to use MMIO */
+ } else {
+ mmioFlags = VIDMEM_MMIO;
+ /*
+ * For Alpha, we need to map SPARSE memory, since we need
+ * byte/short access. Common-level will automatically use
+ * sparse mapping for MMIO.
+ */
+ pCir->IOBase =
+ xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag,
+ pCir->IOAddress, pCir->IoMapSize);
+ if (pCir->IOBase == NULL)
+ return FALSE;
+ }
+
+#ifdef CIR_DEBUG
+ ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n",
+ pCir->IOBase, pCir->IoMapSize, pCir->IOAddress);
+ ErrorF("MMIO[GR31] = %2X\n", (int)
+ ((volatile unsigned char*) pCir->IOBase)[0x40]);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Unmap the framebuffer and MMIO memory.
+ */
+
+Bool
+CirUnmapMem(CirPtr pCir, int scrnIndex)
+{
+#ifdef CIR_DEBUG
+ ErrorF("CirUnmapMem\n");
+#endif
+
+ if (pCir->IOBase != NULL) {
+ /*
+ * Unmap IO registers to virtual address space
+ */
+ xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize);
+ pCir->IOBase = NULL;
+ }
+
+ xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize);
+ pCir->FbBase = NULL;
+ return TRUE;
+}
+
+void
+cirProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ xf86LoaderReqSymLists(vbeSymbols,NULL);
+ pVbe = VBEInit(NULL,index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
diff --git a/src/cir_shadow.c b/src/cir_shadow.c
new file mode 100644
index 0000000..184dee8
--- /dev/null
+++ b/src/cir_shadow.c
@@ -0,0 +1,251 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_shadow.c,v 1.1 2000/02/08 13:13:14 eich Exp $ */
+
+/*
+ Copyright (c) 1999,2000 The XFree86 Project Inc.
+ based on code written by Mark Vojkovich <markv@valinux.com>
+*/
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "shadowfb.h"
+#include "servermd.h"
+#include "cir.h"
+#include "alp.h"
+
+void
+cirRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int width, height, Bpp, FBPitch;
+ unsigned char *src, *dst;
+
+ Bpp = pScrn->bitsPerPixel >> 3;
+ FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+
+ while(num--) {
+ width = (pbox->x2 - pbox->x1) * Bpp;
+ height = pbox->y2 - pbox->y1;
+ src = pCir->ShadowPtr + (pbox->y1 * pCir->ShadowPitch) +
+ (pbox->x1 * Bpp);
+ dst = pCir->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
+
+ while(height--) {
+ memcpy(dst, src, width);
+ dst += FBPitch;
+ src += pCir->ShadowPitch;
+ }
+
+ pbox++;
+ }
+}
+
+void
+cirPointerMoved(int index, int x, int y)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ CirPtr pCir = CIRPTR(pScrn);
+ int newX, newY;
+
+ if(pCir->rotate == 1) {
+ newX = pScrn->pScreen->height - y - 1;
+ newY = x;
+ } else {
+ newX = y;
+ newY = pScrn->pScreen->width - x - 1;
+ }
+
+ (*pCir->PointerMoved)(index, newX, newY);
+}
+
+void
+cirRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pCir->rotate * pCir->ShadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* in dwords */
+
+ if(pCir->rotate == 1) {
+ dstPtr = pCir->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = pCir->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[srcPitch * 3] << 24);
+ src += srcPitch * 4;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+void
+cirRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD16 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pCir->rotate * pCir->ShadowPitch >> 1;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~1;
+ y2 = (pbox->y2 + 1) & ~1;
+ height = (y2 - y1) >> 1; /* in dwords */
+
+ if(pCir->rotate == 1) {
+ dstPtr = (CARD16*)pCir->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = (CARD16*)pCir->ShadowPtr +
+ ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD16*)pCir->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = (CARD16*)pCir->ShadowPtr +
+ (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 16);
+ src += srcPitch * 2;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+/* this one could be faster */
+void
+cirRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
+ srcPitch = -pCir->rotate * pCir->ShadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* blocks of 3 dwords */
+
+ if(pCir->rotate == 1) {
+ dstPtr = pCir->FbBase +
+ (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
+ srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
+ } else {
+ dstPtr = pCir->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
+ srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
+ (src[srcPitch] << 24);
+ dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[(srcPitch * 2) + 1] << 24);
+ dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
+ (src[(srcPitch * 3) + 1] << 16) |
+ (src[(srcPitch * 3) + 2] << 24);
+ dst += 3;
+ src += srcPitch * 4;
+ }
+ srcPtr += pCir->rotate * 3;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+void
+cirRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ int count, width, height, dstPitch, srcPitch;
+ CARD32 *dstPtr, *srcPtr, *src, *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pCir->rotate * pCir->ShadowPitch >> 2;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ height = pbox->y2 - pbox->y1;
+
+ if(pCir->rotate == 1) {
+ dstPtr = (CARD32*)pCir->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
+ srcPtr = (CARD32*)pCir->ShadowPtr +
+ ((1 - pbox->y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD32*)pCir->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
+ srcPtr = (CARD32*)pCir->ShadowPtr +
+ (pbox->y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = *src;
+ src += srcPitch;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+
diff --git a/src/lg.h b/src/lg.h
new file mode 100644
index 0000000..9d91053
--- /dev/null
+++ b/src/lg.h
@@ -0,0 +1,110 @@
+/*
+ * Common strutures and function for CL-GD546x -- The Laguna family
+ *
+ * lg.h
+ *
+ * (c) 1998 Corin Anderson.
+ * corina@the4cs.com
+ * Tukwila, WA
+ *
+ * Inspired by cir.h
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg.h,v 1.12 2001/05/04 19:05:36 dawes Exp $ */
+
+#ifndef LG_H
+#define LG_H
+#define LG_DEBUG
+
+extern ScrnInfoPtr LgProbe(int entity);
+extern const OptionInfoRec * LgAvailableOptions(int chipid);
+
+# ifdef _LG_PRIVATE_
+
+/* Saved registers that are not part of the core VGA */
+/* CRTC >= 0x19; Sequencer >= 0x05; Graphics >= 0x09; Attribute >= 0x15 */
+ /* CR regs */
+enum {
+ /* CR regs */
+ CR1A,
+ CR1B,
+ CR1D,
+ CR1E,
+ /* SR regs */
+ SR07,
+ SR0E,
+ SR12,
+ SR13,
+ SR1E,
+ /* Must be last! */
+ LG_LAST_REG
+};
+
+#undef FORMAT
+
+typedef struct {
+ unsigned char ExtVga[LG_LAST_REG];
+
+ /* Laguna regs */
+ CARD8 TILE, BCLK;
+ CARD16 FORMAT, DTTC, TileCtrl, CONTROL;
+ CARD32 VSC;
+} LgRegRec, *LgRegPtr;
+
+typedef struct {
+ int tilesPerLine; /* Number of tiles per line */
+ int pitch; /* Display pitch, in bytes */
+ int width; /* Tile width. 0 = 128 byte 1 = 256 byte */
+} LgLineDataRec, *LgLineDataPtr;
+
+
+/* lg_driver.c */
+extern LgLineDataRec LgLineData[];
+
+/* lg_xaa.c */
+extern Bool LgXAAInit(ScreenPtr pScreen);
+
+/* lg_hwcurs.c */
+extern Bool LgHWCursorInit(ScreenPtr pScreen);
+extern void LgHideCursor(ScrnInfoPtr pScrn);
+extern void LgShowCursor(ScrnInfoPtr pScrn);
+
+/* lg_i2c.c */
+extern Bool LgI2CInit(ScrnInfoPtr pScrn);
+
+#define memrb(off) MMIO_IN8(pCir->IOBase,off)
+#define memrw(off) MMIO_IN16(pCir->IOBase,off)
+#define memrl(off) MMIO_IN32(pCir->IOBase,off)
+#define memwb(off,val) MMIO_OUT8(pCir->IOBase,off,val)
+#define memww(off,val) MMIO_OUT16(pCir->IOBase,off,val)
+#define memwl(off,val) MMIO_OUT32(pCir->IOBase,off,val)
+
+/* Card-specific driver information */
+#define LGPTR(p) ((LgPtr)((p)->chip.lg))
+
+typedef struct lgRec {
+ CARD32 HWCursorAddr;
+ int HWCursorImageX;
+ int HWCursorImageY;
+ int HWCursorTileWidth;
+ int HWCursorTileHeight;
+
+ int lineDataIndex;
+
+ int memInterleave;
+
+ LgRegRec SavedReg;
+ LgRegRec ModeReg;
+
+ CARD32 oldBitmask;
+ Bool blitTransparent;
+ int blitYDir;
+} LgRec, *LgPtr;
+
+# endif /* _LG_PRIVATE_ */
+#endif /* LG_H */
+
+
+
+
+
diff --git a/src/lg_driver.c b/src/lg_driver.c
new file mode 100644
index 0000000..2f63143
--- /dev/null
+++ b/src/lg_driver.c
@@ -0,0 +1,1877 @@
+/*
+ * Driver for CL-GD546x -- The Laguna family
+ *
+ * lg_driver.c
+ *
+ * (c) 1998 Corin Anderson.
+ * corina@the4cs.com
+ * Tukwila, WA
+ *
+ * This driver is derived from the cir_driver.c module.
+ * Original authors and contributors list include:
+ * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel,
+ * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff,
+ * Guy DESBIEF, Itai Nahshon.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_driver.c,v 1.43 2002/07/24 01:47:27 tsi Exp $ */
+
+#define EXPERIMENTAL
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+/* All drivers need this */
+#include "xf86_ansic.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"
+
+#include "xf86int10.h"
+
+#include "fb.h"
+
+#include "xf86DDC.h"
+
+#undef LG_DEBUG
+
+#include "cir.h"
+#define _LG_PRIVATE_
+#include "lg.h"
+
+#ifdef XvExtension
+#include "xf86xv.h"
+#include "Xv.h"
+#endif
+
+/*
+ * Forward definitions for the functions that make up the driver.
+ */
+
+/* Mandatory functions */
+Bool LgPreInit(ScrnInfoPtr pScrn, int flags);
+Bool LgScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
+Bool LgEnterVT(int scrnIndex, int flags);
+void LgLeaveVT(int scrnIndex, int flags);
+static Bool LgCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool LgSaveScreen(ScreenPtr pScreen, Bool mode);
+
+/* Required if the driver supports mode switching */
+Bool LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+/* Required if the driver supports moving the viewport */
+void LgAdjustFrame(int scrnIndex, int x, int y, int flags);
+
+/* Optional functions */
+void LgFreeScreen(int scrnIndex, int flags);
+int LgValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags);
+
+/* Internally used functions */
+static void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg);
+static int LgFindLineData(int displayWidth, int bpp);
+static CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq);
+static void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base);
+
+static void LgDisplayPowerManagementSet(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;
+
+/*
+ * This contains the functions needed by the server after loading the
+ * driver module. It must be supplied, and gets added the driver list by
+ * the Module Setup funtion in the dynamic case. In the static case a
+ * reference to this is compiled in, and this requires that the name of
+ * this DriverRec be an upper-case version of the driver name.
+ */
+
+typedef enum {
+ OPTION_HW_CURSOR,
+ OPTION_PCI_RETRY,
+ OPTION_ROTATE,
+ OPTION_SHADOW_FB,
+ OPTION_NOACCEL
+} LgOpts;
+
+static const OptionInfoRec LgOptions[] = {
+ { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
+ /* fifo_conservative/aggressive; fast/med/slow_dram; ... */
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+
+/* 1/4bpp 8bpp 15/16bpp 24bpp 32bpp */
+static int gd5462_MaxClocks[] = { 170000, 170000, 135100, 135100, 85500 };
+static int gd5464_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
+static int gd5465_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 };
+
+LgLineDataRec LgLineData[] = {
+ { 5, 640, 0}, /* We're rather use skinny tiles, so put all of */
+ { 8, 1024, 0}, /* them at the head of the table */
+ {10, 1280, 0},
+ {13, 1664, 0},
+ {16, 2048, 0},
+ {20, 2560, 0},
+ {10, 2560, 1},
+ {26, 3328, 0},
+ { 5, 1280, 1},
+ { 8, 2048, 1},
+ {13, 3328, 1},
+ {16, 4096, 1},
+ {20, 5120, 1},
+ {26, 6656, 1},
+ {-1, -1, -1} /* Sentinal to indicate end of table */
+};
+
+static int LgLinePitches[4][11] = {
+ /* 8 */ { 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 },
+ /* 16 */ { 320, 512, 640, 832, 1024, 1280, 1664, 2048, 2560, 3328, 0 },
+ /* 24 */ { 213, 341, 426, 554, 682, 853, 1109, 1365, 1706, 2218, 0 },
+ /* 32 */ { 160, 256, 320, 416, 512, 640, 832, 1024, 1280, 1664, 0 }
+};
+
+/*
+ * 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",
+ "vgaHWUnlock",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbScreenInit",
+ "fbPictureInit",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+#define LGuseI2C 1
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+#if LGuseI2C
+ "xf86DoEDID_DDC2",
+#endif
+ "xf86SetDDCproperties",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86FreeInt10",
+ "xf86InitInt10",
+ NULL
+};
+
+static const char *shadowSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+
+#ifdef XFree86LOADER
+
+#define LG_MAJOR_VERSION 1
+#define LG_MINOR_VERSION 0
+#define LG_PATCHLEVEL 0
+
+static MODULESETUPPROTO(lgSetup);
+
+static XF86ModuleVersionInfo lgVersRec =
+{
+ "cirrus_laguna",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_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_lagunaModuleData = { &lgVersRec, lgSetup, NULL };
+
+static pointer
+lgSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
+ ramdacSymbols, ddcSymbols, i2cSymbols,
+ int10Symbols, NULL);
+ }
+ return (pointer)1;
+}
+
+#endif /* XFree86LOADER */
+
+const OptionInfoRec *
+LgAvailableOptions(int chipid)
+{
+ return LgOptions;
+}
+
+ScrnInfoPtr
+LgProbe(int entity)
+{
+ ScrnInfoPtr pScrn = NULL;
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets,
+ NULL, NULL, NULL, NULL, NULL))) {
+ pScrn->PreInit = LgPreInit;
+ pScrn->ScreenInit = LgScreenInit;
+ pScrn->SwitchMode = LgSwitchMode;
+ pScrn->AdjustFrame = LgAdjustFrame;
+ pScrn->EnterVT = LgEnterVT;
+ pScrn->LeaveVT = LgLeaveVT;
+ pScrn->FreeScreen = LgFreeScreen;
+ pScrn->ValidMode = LgValidMode;
+ }
+ return pScrn;
+}
+
+
+static Bool
+LgGetRec(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir;
+
+ if (pScrn->driverPrivate != NULL)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1);
+ ((CirPtr)pScrn->driverPrivate)->chip.lg = xnfcalloc(sizeof(LgRec),1);
+
+ /* Initialize it */
+ pCir = CIRPTR(pScrn);
+ pCir->chip.lg->oldBitmask = 0x00000000;
+
+ return TRUE;
+}
+
+static void
+LgFreeRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate == NULL)
+ return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+
+
+/*
+ * LgCountRAM --
+ *
+ * Counts amount of installed RAM
+ */
+
+/* XXX We need to get rid of this PIO (MArk) */
+static int
+LgCountRam(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD8 SR14;
+
+ vgaHWProtect(pScrn, TRUE);
+
+ /* The ROM BIOS scratchpad registers contain,
+ among other things, the amount of installed
+ RDRAM on the laguna chip. */
+ SR14 = hwp->readSeq(hwp, 0x14);
+
+ ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n",
+ hwp->readSeq(hwp, 9), hwp->readSeq(hwp, 10),
+ SR14, hwp->readSeq(hwp, 0x15));
+
+ vgaHWProtect(pScrn, FALSE);
+
+ return 1024 * ((SR14&0x7) + 1);
+
+ /* !!! This function seems to be incorrect... */
+}
+
+static xf86MonPtr
+LgDoDDC(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ xf86MonPtr MonInfo = NULL;
+
+ /* Map the CIR memory and MMIO areas */
+ if (!CirMapMem(pCir, pScrn->scrnIndex))
+ return FALSE;
+
+ {
+ ErrorF("RIF Control %#04x, RAC Control %#04x\n",
+ memrw(0x200), memrw(0x201));
+ }
+#if LGuseI2C
+ if (!LgI2CInit(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed\n");
+
+ goto unmap_out;
+ }
+
+ /* Read and output monitor info using DDC2 over I2C bus */
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pCir->I2CPtr1);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n", MonInfo);
+ xf86PrintEDID(MonInfo);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n\n");
+#endif /* LGuseI2C */
+
+ xf86SetDDCproperties(pScrn, MonInfo);
+
+unmap_out:
+ CirUnmapMem(pCir, pScrn->scrnIndex);
+
+ return MonInfo;
+}
+
+/* Mandatory */
+Bool
+LgPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ CirPtr pCir;
+ vgaHWPtr hwp;
+ MessageType from;
+ int i;
+ ClockRangePtr clockRanges;
+ int fbPCIReg, ioPCIReg;
+ char *s;
+
+ if (flags & PROBE_DETECT) {
+ cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
+ return TRUE;
+ }
+
+#ifdef LG_DEBUG
+ ErrorF("LgPreInit\n");
+#endif
+
+ /* Check the number of entities, and fail if it isn't one. */
+ if (pScrn->numEntities != 1)
+ return FALSE;
+
+ /* The vgahw module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+
+ /*
+ * Allocate a vgaHWRec
+ */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+
+ hwp = VGAHWPTR(pScrn);
+ vgaHWGetIOBase(hwp);
+
+ /* Allocate the LgRec driverPrivate */
+ if (!LgGetRec(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")) {
+ xf86Int10InfoPtr int10InfoPtr;
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+
+ int10InfoPtr = xf86InitInt10(pCir->pEnt->index);
+
+ if (int10InfoPtr)
+ xf86FreeInt10(int10InfoPtr);
+ }
+
+ /* 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;
+ }
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ case 32:
+ /* 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};
+
+ /* !!! I think we can force 5-6-5 weight for 16bpp here for
+ the 5462. */
+
+ 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(LgOptions))))
+ return FALSE;
+ memcpy(pCir->Options, LgOptions, sizeof(LgOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options);
+
+ 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 in less than 8 bpp\n");
+ return FALSE;
+ }
+ /*
+ * 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;
+ }
+
+ /* Cirrus swapped the FB and IO registers in the 5465 (by design). */
+ if (PCI_CHIP_GD5465 == pCir->Chipset) {
+ fbPCIReg = 0;
+ ioPCIReg = 1;
+ } else {
+ fbPCIReg = 1;
+ ioPCIReg = 0;
+ }
+
+ /* Find the frame buffer base address */
+ if (pCir->pEnt->device->MemBase != 0) {
+ /* Require that the config file value matches one of the PCI values. */
+ 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[fbPCIReg] != 0) {
+ pCir->FbAddress = pCir->PciInfo->memBase[fbPCIReg] & 0xff000000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid FB address in PCI config space\n");
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pCir->FbAddress);
+
+ /* Find the MMIO base address */
+ 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[ioPCIReg] != 0) {
+ pCir->IOAddress = pCir->PciInfo->memBase[ioPCIReg] & 0xfffff000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid MMIO address in PCI config space\n");
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
+ (unsigned long)pCir->IOAddress);
+
+ /*
+ * 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;
+ from = X_CONFIG;
+ } else {
+ pScrn->videoRam = LgCountRam(pScrn);
+ from = X_PROBED;
+ }
+ if (2048 == pScrn->videoRam) {
+ /* Two-way interleaving */
+ pCir->chip.lg->memInterleave = 0x40;
+ } else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) {
+ /* Four-way interleaving */
+ pCir->chip.lg->memInterleave = 0x80;
+ } else {
+ /* One-way interleaving */
+ pCir->chip.lg->memInterleave = 0x00;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
+ pScrn->videoRam);
+
+ pCir->FbMapSize = pScrn->videoRam * 1024;
+ pCir->IoMapSize = 0x4000; /* 16K for moment, will increase */
+
+ pScrn->racIoFlags = RAC_COLORMAP
+#ifndef EXPERIMENTAL
+ | RAC_VIEWPORT
+#endif
+;
+ xf86SetOperatingState(resVgaMem, 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, "ddc")) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+
+#if LGuseI2C
+ if (!xf86LoadSubModule(pScrn, "i2c")) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(i2cSymbols, NULL);
+#endif
+
+ /* Read and print the monitor DDC information */
+ pScrn->monitor->DDC = LgDoDDC(pScrn);
+
+ /* 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;
+ }
+ 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 && !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;
+ }
+
+ /* 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 specify a Clocks line for Cirrus chips\n");
+ return FALSE;
+ } else {
+ int speed;
+ int *p;
+ switch (pCir->Chipset) {
+ case PCI_CHIP_GD5462:
+ p = gd5462_MaxClocks;
+ break;
+ case PCI_CHIP_GD5464:
+ case PCI_CHIP_GD5464BD:
+ p = gd5464_MaxClocks;
+ break;
+ case PCI_CHIP_GD5465:
+ p = gd5465_MaxClocks;
+ break;
+ default:
+ ErrorF("???\n");
+ return FALSE;
+ }
+ switch (pScrn->bitsPerPixel) {
+ 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;
+
+ /* Depending upon what sized tiles used, either 128 or 256. */
+ /* Aw, heck. Just say 128. */
+ pCir->Rounding = 128 >> pCir->BppShift;
+
+ /*
+ * 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 CIRValidMode() already takes
+ * care of this, we don't worry about setting them here.
+ */
+
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
+ clockRanges,
+ LgLinePitches[pScrn->bitsPerPixel / 8 - 1],
+ 0, 0, 128 * 8,
+ 0, 0, /* Any virtual height is allowed. */
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pCir->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+
+ pCir->chip.lg->lineDataIndex = LgFindLineData(pScrn->displayWidth,
+ pScrn->bitsPerPixel);
+
+ if (i == -1) {
+ LgFreeRec(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");
+ LgFreeRec(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 8:
+ case 16:
+ case 24:
+ case 32:
+ if (xf86LoadSubModule(pScrn, "fb") == NULL) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+ break;
+ }
+
+ /* Load XAA if needed */
+ if (!pCir->NoAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+ /* Load ramdac if needed */
+ if (pCir->HWCursor) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ if (pCir->shadowFB) {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ LgFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(shadowSymbols, NULL);
+ }
+
+ return TRUE;
+}
+
+/*
+ * This function saves the video state.
+ */
+static void
+LgSave(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+#ifdef LG_DEBUG
+ ErrorF("LgSave\n");
+#endif
+
+ vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL);
+
+ pCir->chip.lg->ModeReg.ExtVga[CR1A] = pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A);
+ pCir->chip.lg->ModeReg.ExtVga[CR1B] = pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B);
+ pCir->chip.lg->ModeReg.ExtVga[CR1D] = pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D);
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] = pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E);
+ pCir->chip.lg->ModeReg.ExtVga[SR07] = pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07);
+ pCir->chip.lg->ModeReg.ExtVga[SR0E] = pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E);
+ pCir->chip.lg->ModeReg.ExtVga[SR12] = pCir->chip.lg->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12);
+ pCir->chip.lg->ModeReg.ExtVga[SR13] = pCir->chip.lg->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13);
+ pCir->chip.lg->ModeReg.ExtVga[SR1E] = pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E);
+
+ pCir->chip.lg->ModeReg.FORMAT = pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0);
+
+ pCir->chip.lg->ModeReg.VSC = pCir->chip.lg->SavedReg.VSC = memrl(0x3FC);
+
+ pCir->chip.lg->ModeReg.DTTC = pCir->chip.lg->SavedReg.DTTC = memrw(0xEA);
+
+ if (pCir->Chipset == PCI_CHIP_GD5465) {
+ pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4);
+ }
+
+ pCir->chip.lg->ModeReg.TILE = pCir->chip.lg->SavedReg.TILE = memrb(0x407);
+
+ if (pCir->Chipset == PCI_CHIP_GD5465)
+ pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0);
+ else
+ pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x8C);
+
+ pCir->chip.lg->ModeReg.CONTROL = pCir->chip.lg->SavedReg.CONTROL = memrw(0x402);
+}
+
+/*
+ * Initialise a new mode. This is currently still using the old
+ * "initialise struct, restore/write struct to HW" model. That could
+ * be changed.
+ */
+
+static Bool
+LgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp;
+ vgaRegPtr vgaReg;
+ CirPtr pCir;
+ int width;
+ Bool VDiv2 = FALSE;
+ CARD16 clockData;
+ LgLineDataPtr lineData;
+
+#ifdef LG_DEBUG
+ ErrorF("LgModeInit %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("LgModeInit: depth %d bits\n", pScrn->depth);
+#endif
+
+ pCir = CIRPTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ vgaHWUnlock(hwp);
+
+ 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;
+
+ if (VDiv2)
+ hwp->ModeReg.CRTC[0x17] |= 0x04;
+
+#ifdef LG_DEBUG
+ ErrorF("SynthClock = %d\n", mode->SynthClock);
+#endif
+ vgaReg = &hwp->ModeReg;
+
+ hwp->IOBase = 0x3D0;
+ hwp->ModeReg.MiscOutReg |= 0x01;
+#if 0 /* Mono address */
+ hwp->IOBase = 0x3B0;
+ hwp->ModeReg.MiscOutReg &= ~0x01;
+#endif
+
+
+ /* ??? Should these be both ...End or ...Start, not one of each? */
+ pCir->chip.lg->ModeReg.ExtVga[CR1A] = (((mode->CrtcVSyncStart + 1) & 0x300 ) >> 2)
+ | (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2);
+
+ width = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
+ if (pScrn->bitsPerPixel == 1)
+ width <<= 2;
+ hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3;
+ /* Offset extension (see CR13) */
+ pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF;
+ pCir->chip.lg->ModeReg.ExtVga[CR1B] |= (((width + 7) >> 3) & 0x100)?0x10:0x00;
+ pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22;
+ pCir->chip.lg->ModeReg.ExtVga[CR1D] = (((width + 7) >> 3) & 0x200)?0x01:0x00;
+
+ /* Set the 28th bit to enable extended modes. */
+ pCir->chip.lg->ModeReg.VSC = 0x10000000;
+
+ /* Overflow register (sure are a lot of overflow bits around...) */
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHTotal>>3 & 0x0100)?1:0)<<7;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHDisplay>>3 & 0x0100)?1:0)<<6;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<5;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<4;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVTotal & 0x0400)?1:0)<<3;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVDisplay & 0x0400)?1:0)<<2;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<1;
+ pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<0;
+
+ lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
+
+ pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F;
+
+ if (8 == pScrn->bitsPerPixel) {
+ pCir->chip.lg->ModeReg.FORMAT = 0x0000;
+
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
+ | (lineData->width << 6);
+ pCir->chip.lg->ModeReg.CONTROL = 0x0000 | (lineData->width << 11);
+
+
+ /* There is an optimal FIFO threshold value (lower 5 bits of DTTC)
+ for every resolution and color depth combination. We'll hit
+ the highlights here, and get close for anything that's not
+ covered. */
+ if (mode->CrtcHDisplay <= 640) {
+ /* BAD numbers: 0x1E */
+ /* GOOD numbers: 0x14 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
+ } else if (mode->CrtcHDisplay <= 800) {
+ /* BAD numbers: 0x16 */
+ /* GOOD numbers: 0x13 0x14 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014);
+ } else if (mode->CrtcHDisplay <= 1024) {
+ /* BAD numbers: */
+ /* GOOD numbers: 0x15 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
+ } else if (mode->CrtcHDisplay <= 1280) {
+ /* BAD numbers: */
+ /* GOOD numbers: 0x16 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0016);
+ } else {
+ /* BAD numbers: */
+ /* GOOD numbers: */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
+ }
+ } else if (16 == pScrn->bitsPerPixel) {
+ /* !!! Assume 5-6-5 RGB mode (for now...) */
+ pCir->chip.lg->ModeReg.FORMAT = 0x1400;
+
+ if (pScrn->depth == 15)
+ pCir->chip.lg->ModeReg.FORMAT = 0x1600;
+
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
+ | (lineData->width << 6);
+ pCir->chip.lg->ModeReg.CONTROL = 0x2000 | (lineData->width << 11);
+
+ if (mode->CrtcHDisplay <= 640) {
+ /* BAD numbers: 0x12 */
+ /* GOOD numbers: 0x10 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
+ } else if (mode->CrtcHDisplay <= 800) {
+ /* BAD numbers: 0x13 */
+ /* GOOD numbers: 0x11 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
+ } else if (mode->CrtcHDisplay <= 1024) {
+ /* BAD numbers: 0x14 */
+ /* GOOD numbers: 0x12 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0012);
+ } else if (mode->CrtcHDisplay <= 1280) {
+ /* BAD numbers: 0x08 0x10 */
+ /* Borderline numbers: 0x12 */
+ /* GOOD numbers: 0x15 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015);
+ } else {
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
+ }
+ } else if (24 == pScrn->bitsPerPixel) {
+ pCir->chip.lg->ModeReg.FORMAT = 0x2400;
+
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
+ | (lineData->width << 6);
+ pCir->chip.lg->ModeReg.CONTROL = 0x4000 | (lineData->width << 11);
+
+ if (mode->CrtcHDisplay <= 640) {
+ /* BAD numbers: */
+ /* GOOD numbers: 0x10 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010);
+ } else if (mode->CrtcHDisplay <= 800) {
+ /* BAD numbers: */
+ /* GOOD numbers: 0x11 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011);
+ } else if (mode->CrtcHDisplay <= 1024) {
+ /* BAD numbers: 0x12 0x13 */
+ /* Borderline numbers: 0x15 */
+ /* GOOD numbers: 0x17 */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
+ } else if (mode->CrtcHDisplay <= 1280) {
+ /* BAD numbers: */
+ /* GOOD numbers: 0x1E */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001E);
+ } else {
+ /* BAD numbers: */
+ /* GOOD numbers: */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0020);
+ }
+ } else if (32 == pScrn->bitsPerPixel) {
+ pCir->chip.lg->ModeReg.FORMAT = 0x3400;
+
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080
+ | (lineData->width << 6);
+ pCir->chip.lg->ModeReg.CONTROL = 0x6000 | (lineData->width << 11);
+
+ if (mode->CrtcHDisplay <= 640) {
+ /* GOOD numbers: 0x0E */
+ /* BAD numbers: */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x000E);
+ } else if (mode->CrtcHDisplay <= 800) {
+ /* GOOD numbers: 0x17 */
+ /* BAD numbers: */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017);
+ } else if (mode->CrtcHDisplay <= 1024) {
+ /* GOOD numbers: 0x1D */
+ /* OKAY numbers: 0x15 0x14 0x16 0x18 0x19 */
+ /* BAD numbers: 0x0E 0x12 0x13 0x0D */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001D);
+ } else if (mode->CrtcHDisplay <= 1280) {
+ /* GOOD numbers: */
+ /* BAD numbers: */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0022); /* 10 */
+ } else {
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0024);
+ }
+ } else {
+ /* ??? What could it be? Use some sane numbers. */
+ }
+
+ /* Setup the appropriate memory interleaving */
+ pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8);
+ pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0;
+
+ if (PCI_CHIP_GD5465 == pCir->Chipset) {
+ /* The tile control information in the DTTC is also mirrored
+ elsewhere. */
+ pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->ModeReg.DTTC & 0xFFC0;
+
+ /* The 5465's DTTC records _fetches_ per line, not
+ tiles per line. Fetchs are 128-byte fetches. */
+ if (pCir->chip.lg->ModeReg.DTTC & 0x0040) {
+ /* Using 256-byte wide tiles. Double the fetches
+ per line field. */
+ pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xC0FF)
+ | ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1);
+ }
+ }
+
+ /* Program the registers */
+ vgaHWProtect(pScrn, TRUE);
+ hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg);
+
+ clockData = LgSetClock(pCir, hwp, mode->SynthClock);
+ pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF;
+ pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF;
+
+ /* Write those registers out to the card. */
+ LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg);
+
+ /* Programme the registers */
+ vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP);
+
+ vgaHWProtect(pScrn, FALSE);
+
+ return TRUE;
+}
+
+static int LgFindLineData(int displayWidth, int bpp)
+{
+ /* Find the smallest tile-line-pitch such that the total byte pitch
+ is greater than or equal to displayWidth*Bpp. */
+ int i;
+
+ /* Some pitch sizes are duplicates in the table. BUT, the invariant is
+ that the _first_ time a pitch occurs in the table is always _before_
+ all other pitches greater than it. Said in another way... if all
+ duplicate entries from the table were removed, then the resulting pitch
+ values are strictly increasing. */
+
+ for (i = 0; LgLineData[i].pitch > 0; i++)
+ if (LgLineData[i].pitch >= displayWidth*bpp>>3)
+ return i;
+
+ /* Um, uh oh! */
+ return -1;
+}
+
+
+
+
+static void
+LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg)
+{
+ CirPtr pCir;
+ vgaHWPtr hwp;
+ CARD8 cr1D;
+
+ pCir = CIRPTR(pScrn);
+
+ /* First, VGAish registers. */
+ hwp = VGAHWPTR(pScrn);
+ hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]);
+ hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]);
+ cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | (lgReg->ExtVga[CR1D] & 0x01);
+ hwp->writeCrtc(hwp, 0x1D, cr1D);
+ hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]);
+
+ hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]);
+ hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]);
+ hwp->writeSeq(hwp, 0x12, lgReg->ExtVga[SR12]);
+ hwp->writeSeq(hwp, 0x13, lgReg->ExtVga[SR13]);
+ hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]);
+ memww(0xC0, lgReg->FORMAT);
+
+ /* Vendor Specific Control is touchy. Only bit 28 is of concern. */
+ memwl(0x3FC, ((memrl(0x3FC) & ~(1<<28)) | (lgReg->VSC & (1<<28))));
+
+ memww(0xEA, lgReg->DTTC);
+
+ if (pCir->Chipset == PCI_CHIP_GD5465) {
+ memww(0x2C4, lgReg->TileCtrl);
+ }
+
+ memwb(0x407, lgReg->TILE);
+
+ if (pCir->Chipset == PCI_CHIP_GD5465)
+ memwb(0x2C0, lgReg->BCLK);
+ else
+ memwb(0x8C, lgReg->BCLK);
+
+ memww(0x402, lgReg->CONTROL);
+}
+
+/*
+ * Restore the initial (text) mode.
+ */
+static void
+LgRestore(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ vgaRegPtr vgaReg;
+ CirPtr pCir;
+ LgRegPtr lgReg;
+
+#ifdef LG_DEBUG
+ ErrorF("LgRestore pScrn = 0x%08X\n", pScrn);
+#endif
+
+ pCir = CIRPTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ vgaReg = &hwp->SavedReg;
+ lgReg = &pCir->chip.lg->SavedReg;
+
+ vgaHWProtect(pScrn, TRUE);
+
+ LgRestoreLgRegs(pScrn, lgReg);
+
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
+ vgaHWProtect(pScrn, FALSE);
+}
+
+/* Mandatory */
+
+/* This gets called at the start of each server generation */
+
+Bool
+LgScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ /* The vgaHW references will disappear one day */
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ CirPtr pCir;
+ int i, ret;
+ VisualPtr visual;
+ int displayWidth,width,height;
+ unsigned char * FbBase = NULL;
+
+#ifdef LG_DEBUG
+ ErrorF("LgScreenInit\n");
+#endif
+
+ /*
+ * First get the ScrnInfoRec
+ */
+ pScrn = xf86Screens[pScreen->myNum];
+
+ hwp = VGAHWPTR(pScrn);
+
+ hwp->MapSize = 0x10000; /* Standard 64k VGA window */
+
+ pCir = CIRPTR(pScrn);
+
+ /* Map the VGA memory and get the VGA IO base */
+ if (!vgaHWMapMem(pScrn))
+ return FALSE;
+
+ /* Map the CIR memory and MMIO areas */
+ if (!CirMapMem(pCir, pScrn->scrnIndex))
+ return FALSE;
+#ifdef EXPERIMENTAL
+ lg_vgaHWSetMmioFunc(hwp, pCir->IOBase);
+#endif
+ vgaHWGetIOBase(hwp);
+
+ /* Save the current state */
+ LgSave(pScrn);
+
+ /* Initialise the first mode */
+ if (!LgModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+
+ /* Set the viewport */
+ LgAdjustFrame(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 ();
+
+#ifdef LG_DEBUG
+ ErrorF("LgScreenInit after miSetVisualTypes\n");
+#endif
+ 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 8:
+ case 16:
+ case 24:
+ case 32:
+ ret = fbScreenInit(pScreen, FbBase,
+ width,height,
+ pScrn->xDpi, pScrn->yDpi,
+ displayWidth,pScrn->bitsPerPixel);
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "X11: Internal error: invalid bpp (%d) in LgScreenInit\n",
+ pScrn->bitsPerPixel);
+ ret = FALSE;
+ break;
+ }
+ if (!ret)
+ return FALSE;
+
+#ifdef LG_DEBUG
+ ErrorF("LgScreenInit 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 */
+
+ fbPictureInit(pScreen, 0, 0);
+
+ miInitializeBackingStore(pScreen);
+
+ /*
+ * Set initial black & white colourmap indices.
+ */
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (!pCir->NoAccel) { /* Initialize XAA functions */
+ if (!LgXAAInit(pScreen))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialize XAA\n");
+ }
+#if 1
+ pCir->DGAModeInit = LgModeInit;
+ if (!CirDGAInit(pScreen))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "DGA initialization failed\n");
+#endif
+ xf86SetSilkenMouse(pScreen);
+
+ /* Initialise cursor functions */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (pCir->HWCursor) { /* Initialize HW cursor layer */
+ if (!LgHWCursorInit(pScreen))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+
+ /* Initialise default colourmap */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8)
+ vgaHWHandleColormaps(pScreen);
+
+ xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 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 = LgSaveScreen;
+ pCir->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = LgCloseScreen;
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ /* Done */
+ return TRUE;
+}
+
+
+/* Usually mandatory */
+Bool
+LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return LgModeInit(xf86Screens[scrnIndex], mode);
+}
+
+#define ROUND_DOWN(x, mod) (((x) / (mod)) * (mod))
+#define ROUND_UP(x, mod) ((((x) + (mod) - 1) / (mod)) * (mod))
+
+/*
+ * This function is used to initialize the Start Address - the first
+ * displayed location in the video memory.
+ */
+/* Usually mandatory */
+void
+LgAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ int Base, tmp;
+ CirPtr pCir = CIRPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int cursorX, cursorY;
+ int middleX, middleY;
+ const LgLineDataPtr lineData = &LgLineData[pCir->chip.lg->lineDataIndex];
+ const int viewportXRes =
+ (PCI_CHIP_GD5465 == pCir->Chipset) ? (24==pScrn->bitsPerPixel?24:1) :
+ (lineData->width?256:128) /
+ (24==pScrn->bitsPerPixel?1:(pScrn->bitsPerPixel>>3));
+ const int viewportYRes =
+ (PCI_CHIP_GD5465 == pCir->Chipset) ? 1 : (24==pScrn->bitsPerPixel?3:1);
+
+ /* Where's the pointer? */
+ miPointerPosition(&cursorX, &cursorY);
+
+ /* Where's the middle of the screen? We want to eventually know
+ which side of the screen the pointer is on. */
+ middleX = (pScrn->frameX1 + pScrn->frameX0) / 2;
+ middleY = (pScrn->frameY1 + pScrn->frameY0) / 2;
+
+ if (cursorX < middleX) {
+ /* Pointer is on left side of screen. Round the frame value down. */
+ pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes);
+ } else {
+ /* Pointer is on right side of screen. Round the frame value
+ up. A side effect of this rounding up is that we might expose
+ a part of the screen that's actually on the far /left/ of the
+ frame buffer. That's because, although the virtual desktop might
+ be an integral number of tiles, the display might not. We'll
+ just live with this artifact. */
+ pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes);
+ }
+ pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
+
+ if (cursorY < middleY) {
+ pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes);
+ } else {
+ pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes);
+ }
+ pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
+
+
+ if (x != pScrn->frameX0 || y != pScrn->frameY0) {
+ /* !!! */
+ /* We moved the frame from where xf86SetViewport() placed it.
+ If we're using a SW cursor, that's okay -- the pointer exists in
+ the framebuffer, and those bits are still all aligned. But
+ if we're using a HW cursor, then we need to re-align the pointer.
+ Call SetCursorPosition() with the appropriate new pointer
+ values, adjusted to be wrt the new frame. */
+
+ x = pScrn->frameX0;
+ y = pScrn->frameY0;
+ }
+
+ /* ??? Will this work for 1bpp? */
+ Base = (y * lineData->pitch + (x*pScrn->bitsPerPixel/8)) / 4;
+
+ if ((Base & ~0x000FFFFF) != 0) {
+ /* ??? */
+ ErrorF("X11: Internal error: LgAdjustFrame: cannot handle overflow\n");
+ return;
+ }
+
+ hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF);
+ hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
+ tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2;
+ tmp |= (Base >> 16) & 0x01;
+ tmp |= (Base >> 15) & 0x0C;
+ hwp->writeCrtc(hwp, 0x1B, tmp);
+ tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7;
+ tmp |= (Base >> 16) & 0x18;
+ 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
+LgEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ CirPtr pCir = CIRPTR(pScrn);
+#ifdef LG_DEBUG
+ ErrorF("LgEnterVT\n");
+#endif
+
+ /* XXX Shouldn't this be in LeaveVT? */
+ /* Disable HW cursor */
+ if (pCir->HWCursor)
+ LgHideCursor(pScrn);
+
+ /* Should we re-save the text mode on each VT enter? */
+ return LgModeInit(pScrn, pScrn->currentMode);
+}
+
+
+/*
+ * 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
+LgLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CirPtr pCir = CIRPTR(pScrn);
+#ifdef LG_DEBUG
+ ErrorF("LgLeaveVT\n");
+#endif
+
+ /* XXX Shouldn't this be in EnterVT? */
+ /* Enable HW cursor */
+ if (pCir->HWCursor)
+ LgShowCursor(pScrn);
+
+ LgRestore(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
+LgCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CirPtr pCir = CIRPTR(pScrn);
+
+ if(pScrn->vtSema) {
+ LgRestore(pScrn);
+ if (pCir->HWCursor)
+ LgHideCursor(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
+LgFreeScreen(int scrnIndex, int flags)
+{
+#ifdef LG_DEBUG
+ ErrorF("LgFreeScreen\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]);
+ LgFreeRec(xf86Screens[scrnIndex]);
+}
+
+
+/* Checks if a mode is suitable for the selected chipset. */
+
+/* Optional */
+int
+LgValidMode(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);
+ }
+ return(MODE_BAD);
+}
+
+
+/* Do screen blanking */
+
+/* Mandatory */
+static Bool
+LgSaveScreen(ScreenPtr pScreen, int mode)
+{
+ CirPtr pCir = CIRPTR(xf86Screens[pScreen->myNum]);
+ ScrnInfoPtr pScrn = NULL;
+ Bool unblank;
+
+ unblank = xf86IsUnblank(mode);
+
+ if (pScreen != NULL)
+ pScrn = xf86Screens[pScreen->myNum];
+
+ if (pScrn != NULL && pScrn->vtSema) {
+ if (unblank)
+ /* Power up the palette DAC */
+ memwb(0xB0,memrb(0xB0) & 0x7F);
+ else
+ /* Power down the palette DAC */
+ memwb(0xB0,memrb(0xB0) | 0x80);
+ }
+
+ return vgaHWSaveScreen(pScreen, mode);
+}
+
+static CARD16
+LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq)
+{
+ int ffreq, num, den;
+ CARD8 tmp;
+
+ ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000);
+
+ ffreq = freq;
+ if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den))
+ return 0;
+
+ ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n",
+ num, den, ffreq / 1000, ffreq % 1000);
+
+ /* Set VCLK3. */
+ /* The numerator and denominator registers are switched
+ around in the Laguna chips. */
+ tmp = hwp->readSeq(hwp, 0x0E);
+ hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den);
+ hwp->writeSeq(hwp, 0x1E, num);
+
+ return (den << 8) | num;
+}
+
+/*
+ * CIRDisplayPowerManagementSet --
+ *
+ * Sets VESA Display Power Management Signaling (DPMS) Mode.
+ */
+static void
+LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ unsigned char sr01, cr1a;
+ vgaHWPtr hwp;
+
+#ifdef LG_DEBUG
+ ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode);
+#endif
+
+ hwp = VGAHWPTR(pScrn);
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ sr01 = 0x00;
+ cr1a = 0x00;
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ sr01 = 0x20;
+ cr1a = 0x08;
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ sr01 = 0x20;
+ cr1a = 0x04;
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ sr01 = 0x20;
+ cr1a = 0x0c;
+ break;
+ default:
+ return;
+ }
+
+ sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20;
+ hwp->writeSeq(hwp, 0x01, sr01);
+ cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C;
+ hwp->writeCrtc(hwp, 0x1A, cr1a);
+}
+
+#define minb(p) MMIO_IN8(hwp->MMIOBase, (p))
+#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v))
+
+static void
+mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
+{
+ moutb(index << 2, value);
+}
+
+static CARD8
+mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
+{
+ return minb(index << 2);
+}
+
+static void
+lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base)
+{
+ hwp->writeCrtc = mmioWriteCrtc;
+ hwp->readCrtc = mmioReadCrtc;
+ hwp->MMIOBase = base;
+ hwp->MMIOOffset = 0;
+}
diff --git a/src/lg_hwcurs.c b/src/lg_hwcurs.c
new file mode 100644
index 0000000..7e30bdb
--- /dev/null
+++ b/src/lg_hwcurs.c
@@ -0,0 +1,384 @@
+/*
+ * Hardware cursor support for CL-GD546x -- The Laugna family
+ *
+ * lg_hwcurs.c
+ *
+ * (c) 1998 Corin Anderson.
+ * corina@the4cs.com
+ * Tukwila, WA
+ *
+ * Much of this code is inspired by the HW cursor code from XFree86
+ * 3.3.3.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_hwcurs.c,v 1.5 2001/05/07 21:59:06 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _LG_PRIVATE_
+#include "lg.h"
+#include "lg_xaa.h" /* For BitBLT engine macros */
+
+/*
+#define LG_CURSOR_DEBUG
+*/
+
+#define CURSORWIDTH 64
+#define CURSORHEIGHT 64
+#define CURSORSIZE (CURSORWIDTH*CURSORHEIGHT/8)
+
+/* Some registers used for the HW cursor. */
+enum {
+ PALETTE_READ_ADDR = 0x00A4,
+ PALETTE_WRITE_ADDR = 0x00A8,
+ PALETTE_DATA = 0x00AC,
+
+ PALETTE_STATE = 0x00B0,
+ CURSOR_X_POS = 0x00E0,
+ CURSOR_Y_POS = 0x00E2,
+ CURSOR_PRESET = 0x00E4,
+ CURSOR_CONTROL = 0x00E6,
+ CURSOR_ADDR = 0x00E8
+};
+
+
+static void
+LgFindCursorTile(ScrnInfoPtr pScrn, int *x, int *y, int *width, int *height,
+ CARD32 *curAddr);
+
+
+/*
+ * Set the FG and BG colors of the HW cursor.
+ */
+static void LgSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgSetCursorColors\n");
+#endif
+
+ /* Enable access to cursor colors in palette */
+ memwb(PALETTE_STATE, (memrb(PALETTE_STATE) | (1<<3)));
+
+ /* Slam in the color */
+
+ memwb(PALETTE_WRITE_ADDR, 0x00);
+ memwb(PALETTE_DATA, (bg >> 16));
+ memwb(PALETTE_DATA, (bg >> 8));
+ memwb(PALETTE_DATA, (bg >> 0));
+ memwb(PALETTE_WRITE_ADDR, 0x0F);
+ memwb(PALETTE_DATA, (fg >> 16));
+ memwb(PALETTE_DATA, (fg >> 8));
+ memwb(PALETTE_DATA, (fg >> 0));
+
+ /* Disable access to cursor colors */
+ memwb(PALETTE_STATE, (memrb(PALETTE_STATE) & ~(1<<3)));
+}
+
+
+/*
+ * Set the (x,y) position of the pointer.
+ *
+ * Note: (x,y) are /frame/ relative, not /framebuffer/ relative.
+ * That is, if the virtual desktop has been panned all the way to
+ * the right, and the pointer is to be in the upper-right hand corner
+ * of the viewable screen, the pointer coords are (0,0) (even though
+ * the pointer is on, say (550,0) wrt the frame buffer). This is, of
+ * course, a /good/ thing -- we don't want to have to deal with where
+ * the virtual display is, etc, in the cursor code.
+ *
+ */
+static void LgSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+
+#if 0
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgSetCursorPosition %d %d\n", x, y);
+#endif
+#endif
+
+ if (x < 0 || y < 0) {
+ CARD16 oldPreset = memrw(CURSOR_PRESET);
+ CARD16 newPreset = 0x8080 & oldPreset; /* Reserved bits */
+
+ if (x < 0) {
+ newPreset |= ((-x & 0x7F) << 8);
+ x = 0;
+ }
+
+ if (y < 0) {
+ newPreset |= ((-y & 0x7F) << 0);
+ y = 0;
+ }
+
+ memww(CURSOR_PRESET, newPreset);
+ pCir->CursorIsSkewed = TRUE;
+ } else if (pCir->CursorIsSkewed) {
+ /* Reset the hotspot location. */
+ memww(CURSOR_PRESET, memrw(CURSOR_PRESET & 0x8080));
+ pCir->CursorIsSkewed = FALSE;
+ }
+
+ /* Commit the new position to the card. */
+ memww(CURSOR_X_POS, x);
+ memww(CURSOR_Y_POS, y);
+}
+
+
+/*
+ * Load the cursor image to the card. The cursor image is given in
+ * bits. The format is: ???
+ */
+static void LgLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+ const LgPtr pLg = LGPTR(pCir);
+
+ volatile CARD32 *pXCursorBits = (CARD32 *)bits;
+
+ int l, w;
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgLoadCursorImage\n");
+#endif
+
+ /* All ("all") we have to do is a simple CPU-to-screen copy of the
+ cursor image to the frame buffer. */
+
+ while (!LgREADY()) {}
+ ;
+
+ /* Wait until there's ample room in the chip's queue */
+ while (memrb(QFREE) < 10) {}
+ ;
+
+ LgSETMODE(HOST2SCR); /* Host-to-screen blit */
+ LgSETROP(0x00CC); /* Source copy */
+
+ /* First, copy our transparent cursor image to the next 1/2 tile boundry */
+ /* Destination */
+ LgSETMDSTXY(pLg->HWCursorImageX+pLg->HWCursorTileWidth, pLg->HWCursorImageY);
+
+ /* Set the source pitch. 0 means that, worst case, the source is
+ alligned only on a byte boundry */
+ LgSETMPHASE1(0);
+
+ LgSETMEXTENTSNOMONOQW(pLg->HWCursorTileWidth, pLg->HWCursorTileHeight);
+
+ for (l = 0; l < CURSORHEIGHT; l++) {
+ /* Plane 0 */
+ for (w = 0; w < CURSORWIDTH >> 5; w++)
+ memwl(HOSTDATA, 0x00000000);
+ /* Plane 1 */
+ for (w = 0; w < CURSORWIDTH >> 5; w++)
+ memwl(HOSTDATA, 0x00000000);
+ }
+
+ /* Now, copy the real cursor image */
+
+ /* Set the destination */
+ LgSETMDSTXY(pLg->HWCursorImageX, pLg->HWCursorImageY);
+
+ /* Set the source pitch. 0 means that, worst case, the source is
+ alligned only on a byte boundry */
+ LgSETMPHASE1(0);
+
+ /* Always copy an entire cursor image to the card. */
+ LgSETMEXTENTSNOMONOQW(pLg->HWCursorTileWidth, pLg->HWCursorTileHeight);
+
+ for (l = 0; l < CURSORHEIGHT; l++) {
+ /* Plane 0 */
+ for (w = 0; w < CURSORWIDTH >> 5; w++)
+ memwl(HOSTDATA, *pXCursorBits++);
+ /* Plane 1 */
+ for (w = 0; w < CURSORWIDTH >> 5; w++)
+ memwl(HOSTDATA, *pXCursorBits++);
+ }
+
+ while (!LgREADY())
+ ;
+}
+
+
+
+/*
+ * LgFindCursorTile() finds the tile of display memory that will be
+ * used to load the pointer image into. The tile chosen will be the
+ * last tile in the last line of the frame buffer.
+ */
+static void
+LgFindCursorTile(ScrnInfoPtr pScrn, int *x, int *y, int *width, int *height,
+ CARD32 *curAddr)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ LgPtr pLg = LGPTR(pCir);
+
+ int videoRam = pScrn->videoRam; /* in K */
+ int tileHeight = LgLineData[pLg->lineDataIndex].width?8:16;
+ int tileWidth = LgLineData[pLg->lineDataIndex].width?256:128;
+ int tilesPerLine = LgLineData[pLg->lineDataIndex].tilesPerLine;
+ int filledOutTileLines, leftoverMem;
+ int yTile, xTile;
+ int tileNumber;
+
+ filledOutTileLines = videoRam / (tilesPerLine * 2); /* tiles are 2K */
+ leftoverMem = videoRam - filledOutTileLines*tilesPerLine*2;
+
+ if (leftoverMem > 0) {
+ yTile = filledOutTileLines;
+ } else {
+ /* There is no incomplete row of tiles. Then just use the last
+ tile in the last line */
+ yTile = filledOutTileLines - 1;
+ }
+ xTile = 0; /* Always use the first tile in the determined tile row */
+
+ /* The (x,y) coords of the pointer image. */
+ if (x)
+ *x = xTile * tileWidth;
+ if (y)
+ *y = yTile * tileHeight;
+
+ if (width)
+ *width = tileWidth;
+ if (height)
+ *height = tileHeight / 2;
+
+ /* Now, compute the linear address of the cursor image. This process
+ is unpleasant because the memory is tiled, and we essetially have
+ to undo the tiling computation. */
+ if (curAddr) {
+ unsigned int nIL; /* Interleaving */
+ nIL = pLg->memInterleave==0x00? 1 : (pLg->memInterleave==0x40 ? 2 : 4);
+
+ if (PCI_CHIP_GD5465 == pCir->Chipset) {
+ /* The Where's The Cursor formula changed for the 5465. It's really
+ kinda wierd now. */
+ unsigned long page, bank;
+ unsigned int nX, nY;
+
+ nX = xTile * tileWidth;
+ nY = yTile * tileHeight;
+
+ page = (nY / (tileHeight * nIL)) * tilesPerLine + nX / tileWidth;
+ bank = (nX/tileWidth + nY/tileHeight) % nIL + page/(512*nIL);
+ page = page & 0x1FF;
+ *curAddr = bank*1024*1024L + page*2048 + (nY%tileHeight)*tileWidth;
+ } else {
+ tileNumber = (tilesPerLine*nIL) * (yTile/nIL) + yTile % nIL;
+ *curAddr = tileNumber * 2048;
+ }
+ }
+}
+
+
+
+
+/*
+ * Hide/disable the HW cursor.
+ */
+void LgHideCursor(ScrnInfoPtr pScrn)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+
+ /* To hide the cursor, we kick it off into the corner, and then set the
+ cursor image to be a transparent bitmap. That way, if X continues
+ to move the cursor while it is hidden, there is no way that the user
+ can move the cursor back on screen!
+
+ We don't just clear the cursor enable bit because doesn't work in some
+ cases (like when switching back to text mode).
+ */
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgHideCursor\n");
+#endif
+
+ memww(CURSOR_CONTROL, (memrw(CURSOR_CONTROL) & 0xFFFE));
+}
+
+void LgShowCursor(ScrnInfoPtr pScrn)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+ const LgPtr pLg = LGPTR(pCir);
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgShowCursor\n");
+#endif
+
+ memww(CURSOR_CONTROL,(memrw(CURSOR_CONTROL) | (1<<0)));
+ memww(CURSOR_ADDR,(pLg->HWCursorAddr & 0x7FFC));
+}
+
+
+/*
+ * Can the HW cursor be used?
+ */
+static Bool LgUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgUseHWCursor\n");
+#endif
+
+ if(pScrn->bitsPerPixel < 8)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Initialize all the fun HW cursor code.
+ */
+Bool LgHWCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CirPtr pCir = CIRPTR(pScrn);
+ xf86CursorInfoPtr infoPtr;
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgHWCursorInit\n");
+#endif
+
+ infoPtr = xf86CreateCursorInfoRec();
+ if(!infoPtr) return FALSE;
+
+ pCir->CursorInfoRec = infoPtr;
+ LgFindCursorTile(pScrn, &pCir->chip.lg->HWCursorImageX, &pCir->chip.lg->HWCursorImageY,
+ &pCir->chip.lg->HWCursorTileWidth, &pCir->chip.lg->HWCursorTileHeight,
+ &pCir->chip.lg->HWCursorAddr);
+ /* Keep only bits 22:10 of the address. */
+ pCir->chip.lg->HWCursorAddr = (pCir->chip.lg->HWCursorAddr >> 8) & 0x7FFC;
+
+ pCir->CursorIsSkewed = FALSE;
+
+ infoPtr->MaxWidth = CURSORWIDTH;
+ infoPtr->MaxHeight = CURSORHEIGHT;
+ infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
+ | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
+ | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
+ infoPtr->SetCursorColors = LgSetCursorColors;
+ infoPtr->SetCursorPosition = LgSetCursorPosition;
+ infoPtr->LoadCursorImage = LgLoadCursorImage;
+ infoPtr->HideCursor = LgHideCursor;
+ infoPtr->ShowCursor = LgShowCursor;
+ infoPtr->UseHWCursor = LgUseHWCursor;
+
+#ifdef LG_CURSOR_DEBUG
+ ErrorF("LgHWCursorInit before xf86InitCursor\n");
+#endif
+
+ return(xf86InitCursor(pScreen, infoPtr));
+}
diff --git a/src/lg_i2c.c b/src/lg_i2c.c
new file mode 100644
index 0000000..6cb3e3d
--- /dev/null
+++ b/src/lg_i2c.c
@@ -0,0 +1,96 @@
+/* (c) Itai Nahshon */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_i2c.c,v 1.4 2000/12/06 15:35:17 eich Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _LG_PRIVATE_
+#include "lg.h"
+
+static void
+LgI2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ unsigned int regval, regno;
+ CirPtr pCir = ((CirPtr)b->DriverPrivate.ptr);
+ if (b == pCir->I2CPtr1)
+ regno = 0x280;
+ else if (b == pCir->I2CPtr2)
+ regno = 0x282;
+ else
+ return;
+
+ regval = 0xff7e;
+ if (clock) regval |= 0x0080;
+ if (data) regval |= 0x0001;
+ memww(regno, regval);
+ /* ErrorF("LgI2CPutBits: %d %d\n", clock, data); */
+}
+
+static void
+LgI2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ unsigned int regval, regno;
+ CirPtr pCir = ((CirPtr)b->DriverPrivate.ptr);
+ if (b == pCir->I2CPtr1)
+ regno = 0x280;
+ else if (b == pCir->I2CPtr2)
+ regno = 0x282;
+ else
+ return;
+
+ regval = memrw(regno);
+ *clock = (regval & 0x8000) != 0;
+ *data = (regval & 0x0100) != 0;
+ /* ErrorF("LgI2CGetBits: %d %d\n", *clock, *data); */
+}
+
+Bool
+LgI2CInit(ScrnInfoPtr pScrn)
+{
+ CirPtr pCir = CIRPTR(pScrn);
+ I2CBusPtr I2CPtr;
+
+#ifdef LG_DEBUG
+ ErrorF("LgI2CInit\n");
+#endif
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if (!I2CPtr) return FALSE;
+
+ pCir->I2CPtr1 = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus 1";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = LgI2CPutBits;
+ I2CPtr->I2CGetBits = LgI2CGetBits;
+ I2CPtr->DriverPrivate.ptr = pCir;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if (!I2CPtr) return FALSE;
+
+ pCir->I2CPtr2 = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus 2";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = LgI2CPutBits;
+ I2CPtr->I2CGetBits = LgI2CGetBits;
+ I2CPtr->DriverPrivate.ptr = pCir;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
+
diff --git a/src/lg_xaa.c b/src/lg_xaa.c
new file mode 100644
index 0000000..9488721
--- /dev/null
+++ b/src/lg_xaa.c
@@ -0,0 +1,298 @@
+/*
+ * XAA acceleration for CL-GD546x -- The Laugna family
+ *
+ * lg_xaa.c
+ *
+ * (c) 1998 Corin Anderson.
+ * corina@the4cs.com
+ * Tukwila, WA
+ *
+ * Much of this code is inspired by the XAA acceleration from XFree86
+ * 3.3.3, laguna_acl.c
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_xaa.c,v 1.5 2001/02/15 17:39:28 eich Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _LG_PRIVATE_
+#include "lg.h"
+#include "lg_xaa.h"
+
+/* Laguna raster operations, source is OP1 and destination is OP0. */
+/* The order in this array is important! */
+static int lgRop[16] = {
+ /* Lg Op X name */
+
+ 0x00, /* 0 GXclear */
+ 0x88, /* S.D GXand */
+ 0x44, /* S.~D GXandReverse */
+ 0xCC, /* S GXcopy */
+ 0x22, /* ~S.D GXandInverted */
+ 0xAA, /* D GXnoop */
+ 0x66, /* S~=D GXxor */
+ 0xEE, /* S+D GXor */
+ 0x77, /* ~S.~D GXnor */
+ 0x99, /* S=D GXequiv */
+ 0x55, /* ~D GXinvert */
+ 0xDD, /* S+~D GXorReverse */
+ 0x33, /* ~S GXcopyInverted */
+ 0xBB, /* ~S+D GXorInverted */
+ 0x11, /* ~S+~D GXnand */
+ 0xFF /* 1 GXset */
+};
+
+#if 0
+/* Laguna raster operations, source is OP2 and destination is OP0. */
+static int lgPatRop[16] = {
+ /* Lg Op X name */
+
+ 0x00, /* 0 GXclear */
+ 0xA0, /* S.D GXand */
+ 0x50, /* S.~D GXandReverse */
+ 0xF0, /* S GXcopy */
+ 0x0A, /* ~S.D GXandInverted */
+ 0xAA, /* D GXnoop */
+ 0x5A, /* S~=D GXxor */
+ 0xFA, /* S+D GXor */
+ 0x05, /* ~S.~D GXnor */
+ 0xA5, /* S=D GXequiv */
+ 0x55, /* ~D GXinvert */
+ 0xF5, /* S+~D GXorReverse */
+ 0x0F, /* ~S GXcopyInverted */
+ 0xAF, /* ~S+D GXorInverted */
+ 0x5F, /* ~S+~D GXnand */
+ 0xFF /* 1 GXset */
+};
+#endif
+
+
+static void LgSetBitmask(CirPtr pCir, const CARD32 m);
+static void LgWaitQAvail(CirPtr pCir, int n);
+static CARD32 LgExpandColor(CARD32 color, int bpp);
+static void LgSync(ScrnInfoPtr pScrn);
+static void LgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+
+static void LgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+static void LgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask,
+ int transparency_color);
+static void LgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h);
+
+
+/**************************************************** LgXAAInit *****/
+
+Bool
+LgXAAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ CirPtr pCir = CIRPTR(pScrn);
+ XAAInfoRecPtr XAAPtr;
+
+ XAAPtr = XAACreateInfoRec();
+ if (!XAAPtr)
+ return FALSE;
+
+ /*
+ * Solid color fills.
+ */
+ XAAPtr->SetupForSolidFill = LgSetupForSolidFill;
+ XAAPtr->SubsequentSolidFillRect = LgSubsequentSolidFillRect;
+ XAAPtr->SubsequentSolidFillTrap = NULL;
+ XAAPtr->SolidFillFlags = 0;
+
+ /*
+ * Screen-to-screen copies.
+ */
+ XAAPtr->SetupForScreenToScreenCopy = LgSetupForScreenToScreenCopy;
+ XAAPtr->SubsequentScreenToScreenCopy = LgSubsequentScreenToScreenCopy;
+ /* Maybe ONLY_LEFT_TO_RIGHT_BITBLT or ONLY_TWO_BITBLT_DIRECTIONS? */
+ XAAPtr->ScreenToScreenCopyFlags = ONLY_LEFT_TO_RIGHT_BITBLT;
+
+ /*
+ * Miscellany.
+ */
+ XAAPtr->Sync = LgSync;
+
+ pCir->AccelInfoRec = XAAPtr;
+
+ if (!XAAInit(pScreen, XAAPtr))
+ return FALSE;
+
+ return TRUE;
+}
+
+/******************************************** Lg XAA helper functions ***/
+
+/*
+ * The bitmask is usually all 1's, so it's silly to spend a DWORD write
+ * to program the register with the same value each time. Bitmask is
+ * about the only register whose value is worth shadowing, so we special-
+ * case it.
+ */
+static void
+LgSetBitmask(CirPtr pCir, const CARD32 m)
+{
+ const LgPtr pLg = LGPTR(pCir);
+
+ if (m != pLg->oldBitmask) {
+ LgSETBITMASK(m);
+ pLg->oldBitmask = m;
+ }
+}
+
+/*
+ * Return from the function only when there's room somewhere for the
+ * upcoming register writes. That means that either PCI retry is enabled
+ * (i.e., we let the PCI bus buffer the register writes), or we wait for
+ * room in the Laguna's command queue explicitly.
+ */
+static void
+LgWaitQAvail(CirPtr pCir, int n)
+{
+ if (!0/*lgUsePCIRetry*/) {
+ CARD8 qfree;
+
+ /* Wait until n entries are open in the command queue */
+ do
+ qfree = *(volatile CARD8 *)(pCir->IOBase + QFREE);
+ while (qfree < n);
+ }
+}
+
+
+/* We might want to make this a macro at some point. */
+static CARD32
+LgExpandColor(CARD32 color, int bpp)
+{
+ if (8 == bpp)
+ color = ((color&0xFF) << 8) | (color&0xFF);
+
+ if (8 == bpp || 16 == bpp)
+ color = ((color&0xFFFF) << 16) | (color&0xFFFF);
+
+ return color;
+}
+
+
+/*************************************************** Lg XAA functions ***/
+
+
+static void
+LgSync(ScrnInfoPtr pScrn)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+#if 0
+ LgPtr pLg = LGPTR(pScrn);
+#endif
+
+ while (!LgREADY())
+ ;
+}
+
+static void
+LgSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+
+ const CirPtr pCir = CIRPTR(pScrn);
+
+ color = LgExpandColor(color, pScrn->bitsPerPixel);
+
+ LgWaitQAvail(pCir, 4);
+
+ LgSETBACKGROUND(color);
+ LgSETROP(lgRop[rop]);
+ LgSETMODE(SCR2SCR | COLORFILL);
+ LgSetBitmask(pCir, planemask);
+}
+
+static void
+LgSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+
+ /* Wait for room in the command queue. */
+ LgWaitQAvail(pCir, 2);
+
+ LgSETDSTXY(x, y);
+ LgSETEXTENTS(w, h);
+}
+
+static void
+LgSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
+ int rop, unsigned int planemask, int transparency_color)
+{
+ int bltmode = 0;
+ const CirPtr pCir = CIRPTR(pScrn);
+ const LgPtr pLg = LGPTR(pCir);
+
+ pLg->blitTransparent = (transparency_color != -1);
+ pLg->blitYDir = ydir;
+
+ LgWaitQAvail(pCir, 4);
+
+ /* We set the rop up here because the LgSETROP macro conveniently
+ (really -- it is convenient!) clears the transparency bits
+ in DRAWDEF. We'll set those bits appropriatly later. */
+ LgSETROP(lgRop[rop]);
+
+ if (ydir < 0)
+ bltmode |= BLITUP;
+ if (pLg->blitTransparent) {
+ /* Gotta extend the transparency_color to the full 32-bit
+ size of the register. */
+ transparency_color = LgExpandColor(transparency_color,
+ pScrn->bitsPerPixel);
+
+ bltmode |= COLORTRANS;
+ LgSETBACKGROUND(transparency_color);
+ LgSETTRANSPARENCY(TRANSEQ);
+ } else {
+ LgSETTRANSPARENCY(TRANSNONE);
+ }
+
+ LgSETMODE(SCR2SCR | COLORSRC | bltmode);
+ LgSetBitmask(pCir, planemask);
+}
+
+static void
+LgSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h)
+{
+ const CirPtr pCir = CIRPTR(pScrn);
+ const LgPtr pLg = LGPTR(pCir);
+
+ /*
+ * We have set the flag indicating that xdir must be one,
+ * so we can assume that here.
+ */
+ if (pLg->blitYDir == -1) {
+ y1 += h - 1;
+ y2 += h - 1;
+ }
+
+ if (pLg->blitTransparent) {
+ /* We're doing a transparent blit. We'll need to point
+ OP2 to the color compare mask. */
+ LgWaitQAvail(pCir, 4);
+ LgSETTRANSMASK(x1, y1);
+ } else {
+ LgWaitQAvail(pCir, 3);
+ }
+ LgSETSRCXY(x1, y1);
+ LgSETDSTXY(x2, y2);
+ LgSETEXTENTS(w, h);
+}
+
diff --git a/src/lg_xaa.h b/src/lg_xaa.h
new file mode 100644
index 0000000..7359a49
--- /dev/null
+++ b/src/lg_xaa.h
@@ -0,0 +1,180 @@
+#ifndef __LG_XAA_H
+#define __LG_XAA_H
+
+/*
+ * XAA acceleration for CL-GD546x -- The Laugna family
+ *
+ * lg_xaa.h
+ *
+ * (c) 1996,1998 Corin Anderson.
+ * corina@the4cs.com
+ * Tukwila, WA
+ *
+ * This header file draws much from the file cir_blitLG.h in version 3.3.3
+ * of XFree86.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_xaa.h,v 1.3 2000/02/08 13:13:15 eich Exp $ */
+
+/* This header file defines the necessary structures, contstants, and
+ variables for using the bitBLT engine on a Laguna family graphics
+ accelerator. */
+
+
+enum { /* Offsets into MMIO space for bitBLT regs */
+ STATUS = 0x0400,
+ OP0_opRDRAM = 0x0520,
+ OP1_opRDRAM = 0x0540,
+ OP2_opRDRAM = 0x0560,
+ OP0_opMRDRAM = 0x0524,
+ OP1_opMRDRAM = 0x0544,
+ OP2_opMRDRAM = 0x0564,
+ OP0_opSRAM = 0x0528,
+ OP1_opSRAM = 0x0548,
+ OP2_opSRAM = 0x0568,
+ OP1_opMSRAM = 0x054A,
+ OP2_opMSRAM = 0x056A,
+ DRAWDEF = 0x0584,
+ BLTDEF = 0x0586,
+ BLTEXT_EX = 0x0700,
+ MBLTEXT_EX = 0x0720,
+ MONOQW = 0x0588,
+ QFREE = 0x0404,
+ PATOFF = 0x052A,
+ HOSTDATA = 0x0800,
+ OP_opBGCOLOR = 0x05E4,
+ OP_opFGCOLOR = 0x05E0,
+ bltCONTROL = 0x0402,
+ BITMASK = 0x05E8
+};
+
+enum { HOSTDATASIZE = 2048 }; /* The HOSTDATA port is 2048 BYTES */
+
+enum { /* OR these together to form a bitBLT mode */
+ HOST2SCR = 0x1120, /* CPU/Screen transfer modes */
+ SCR2HOST = 0x2010,
+ HOST2PAT = 0x1102,
+ HOST2SRAM2 = 0x6020, /* CPU to SRAM2 transfer */
+
+ SCR2SCR = 0x1110, /* Screen/Screen transfers */
+ COLORSRC = 0x0000, /* Source is color data */
+ MONOSRC = 0x0040, /* Source is mono data (color expansion) */
+ COLORTRANS = 0x0001, /* Transparent screen/screen transfer */
+ MONOTRANS = 0x0005, /* Transparent screen/screen color expansion */
+ COLORFILL = 0x0070, /* Solid color fill mode */
+ SRAM1SCR2SCR = 0x1180, /* Pattern fill, source from SRAM1 */
+
+ PAT2SCR = 0x1109, /* Pattern/Screen transfers */
+ COLORPAT = 0x0000, /* Pattern is color data */
+ MONOPAT = 0x0004, /* Pattern is mono data (color expansion) */
+ SRAM2PAT2SCR = 0x1108, /* SRAM2 is pattern source */
+
+ PATeqSRC = 0x0800, /* The Pattern and Source operands are the same */
+ /* Advice from Corey: don't ever try to use
+ this option! 8) There's a documented bug
+ with it on the '62, and, well, I have
+ empirical evidence that either the bug's
+ still around, even in the '64 and the '65.
+ It's a performance option, anyway, so not
+ using it should be okay. */
+
+
+ BLITUP = 0x8000 /* The blit is proceeding from bottom to top */
+};
+
+enum { /* Select transparency compare */
+ TRANSBG = 0x0100,
+ TRANSFG = 0x0300,
+ TRANSEQ = 0x0100,
+ TRANSNE = 0x0300,
+ TRANSNONE = 0x0000
+};
+
+#define LgREADY() ((memrb(STATUS) & 0x07) == 0x00)
+
+#define LgSETROP(rop) memww(DRAWDEF,rop);
+
+#define LgSETTRANSPARENCY(trans) \
+ memww(DRAWDEF,(trans) | (memrw(DRAWDEF) & 0x00FF));
+
+#define LgSETMODE(mode) memww(BLTDEF,mode);
+
+#define LgSETDSTXY(X, Y) memwl(OP0_opRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETSRCXY(X, Y) memwl(OP1_opRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETPATXY(X, Y) memwl(OP2_opRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETTRANSMASK(X, Y) LgSETPATXY(X, Y)
+
+#define LgSETSRAMDST(offset) memww(OP0_opSRAM, offset);
+
+/* was this a bug? it read OP2_opSRAM */
+#define LgSETSRAM1OFFSET(offset) memww(OP1_opSRAM, offset);
+
+#define LgSETSRAM2OFFSET(offset) memww(OP2_opSRAM, offset);
+
+#define LgSETMSRAM1OFFSET(offset) memww(OP1_opMSRAM, offset);
+
+#define LgSETMSRAM2OFFSET(offset) memww(OP2_opMSRAM, offset);
+
+#define LgSETMDSTXY(X, Y) memwl(OP0_opMRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETMSRCXY(X, Y) memwl(OP1_opMRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETMPATXY(X, Y) memwl(OP2_opMRDRAM, (((Y) << 16) | (X)));
+
+#define LgSETMTRANSMASK(X, Y) LgSETMPATXY(X, Y)
+
+#define LgSETPHASE0(phase) memwl( OP0_opRDRAM, phase);
+
+#define LgSETPHASE1(phase) memwl(OP1_opRDRAM, phase);
+
+#define LgSETPHASE2(phase) memwl( OP2_opRDRAM, phase);
+
+#define LgSETMPHASE0(phase) memwl(OP0_opMRDRAM, phase);
+
+#define LgSETMPHASE1(phase) memwl(OP1_opMRDRAM, phase);
+
+#define LgSETEXTENTS(width, height) \
+ memwl(BLTEXT_EX, (((height) << 16)|(width)));
+
+#if 0
+#define LgSETMEXTENTS(width, height) \
+ memwl(MBLTEXT_EX, (((height) << 16)|(width)));
+#else
+/* For monochrome (byte) blits, we need to set how many QWORDs of data
+ encompass the X extent. Write this piece of data into MONOQW. */
+#define LgSETMEXTENTS(width, height) \
+ { \
+ memww(MONOQW, ((width + 7) >> 3)); \
+ memwl(MBLTEXT_EX, (((height) << 16)|(width))); \
+ }
+
+#define LgSETMEXTENTSNOMONOQW(width, height) \
+ memwl(MBLTEXT_EX, (((height) << 16)|(width)));
+
+/*
+ memww(MBLTEXT_EX, height);
+ memww(MBLTEXT_EX + 2, width);
+ */
+#endif
+
+#define LgHOSTDATAWRITE(data) memwl(HOSTDATA, data);
+
+#define LgHOSTDATAREAD() (memrl(HOSTDATA))
+
+#define LgSETBACKGROUND(color) memwl(OP_opBGCOLOR, color);
+
+#define LgSETFOREGROUND(color) memwl(OP_opFGCOLOR, color);
+
+#define LgSETPATOFF(xoff, yoff) memww(PATOFF, (((yoff) << 8) | (xoff)));
+
+#define LgSETSWIZZLE() memww(bltCONTROL, memrw(bltCONTROL | 0x0400));
+
+#define LgCLEARSWIZZLE() memww(bltCONTROL, memrw(bltCONTROL & ~0x0400));
+
+#define LgSETBITMASK(m) memwl(BITMASK, m);
+
+
+
+#endif /* __LG_XAA_H */