summaryrefslogtreecommitdiff
path: root/src
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
commit3b2090ec858107463451f90a4889f2c4cfc21254 (patch)
treecb8cbf8f4df61be320bb147553e74b0d93062c77 /src
Initial revisionXORG-STABLE
Diffstat (limited to 'src')
-rw-r--r--src/i740.h157
-rw-r--r--src/i740_accel.c396
-rw-r--r--src/i740_cursor.c220
-rw-r--r--src/i740_dga.c252
-rw-r--r--src/i740_dga.h26
-rw-r--r--src/i740_driver.c1921
-rw-r--r--src/i740_i2c.c105
-rw-r--r--src/i740_io.c93
-rw-r--r--src/i740_macros.h61
-rw-r--r--src/i740_reg.h327
-rw-r--r--src/i740_video.c1323
11 files changed, 4881 insertions, 0 deletions
diff --git a/src/i740.h b/src/i740.h
new file mode 100644
index 0000000..63f78f2
--- /dev/null
+++ b/src/i740.h
@@ -0,0 +1,157 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740.h,v 1.7 2002/10/23 16:08:36 tsi Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#ifndef _I740_H_
+#define _I740_H_
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+#include "i740_reg.h"
+#include "i740_macros.h"
+
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+/* Globals */
+/* Memory mapped register access macros */
+#define INREG8(addr) *(volatile CARD8 *)(pI740->MMIOBase + (addr))
+#define INREG16(addr) *(volatile CARD16 *)(pI740->MMIOBase + (addr))
+#define INREG(addr) *(volatile CARD32 *)(pI740->MMIOBase + (addr))
+#define OUTREG8(addr, val) *(volatile CARD8 *)(pI740->MMIOBase + (addr)) = (val)
+#define OUTREG16(addr, val) *(volatile CARD16 *)(pI740->MMIOBase + (addr)) = (val)
+#define OUTREG(addr, val) *(volatile CARD32 *)(pI740->MMIOBase + (addr)) = (val)
+
+typedef struct _I740Rec *I740Ptr;
+
+typedef void (*I740WriteIndexedByteFunc)(I740Ptr pI740, int addr,
+ unsigned char index, char value);
+typedef char (*I740ReadIndexedByteFunc)(I740Ptr pI740, int addr,
+ unsigned char index);
+typedef void (*I740WriteByteFunc)(I740Ptr pI740, int addr, unsigned char value);
+typedef char (*I740ReadByteFunc)(I740Ptr pI740, int addr);
+
+typedef struct {
+ unsigned char DisplayControl;
+ unsigned char PixelPipeCfg0;
+ unsigned char PixelPipeCfg1;
+ unsigned char PixelPipeCfg2;
+ unsigned char VideoClk2_M;
+ unsigned char VideoClk2_N;
+ unsigned char VideoClk2_MN_MSBs;
+ unsigned char VideoClk2_DivisorSel;
+ unsigned char PLLControl;
+ unsigned char AddressMapping;
+ unsigned char IOControl;
+ unsigned char BitBLTControl;
+ unsigned char ExtVertTotal;
+ unsigned char ExtVertDispEnd;
+ unsigned char ExtVertSyncStart;
+ unsigned char ExtVertBlankStart;
+ unsigned char ExtHorizTotal;
+ unsigned char ExtHorizBlank;
+ unsigned char ExtOffset;
+ unsigned char InterlaceControl;
+ unsigned int LMI_FIFO_Watermark;
+} I740RegRec, *I740RegPtr;
+
+typedef struct _I740Rec {
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+ long FbMapSize;
+ int cpp;
+ int MaxClock;
+ int CursorStart;
+ int Chipset;
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+ EntityInfoPtr pEnt;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ int HasSGRAM;
+ I740RegRec SavedReg;
+ I740RegRec ModeReg;
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ FBAreaPtr CursorData;
+ CloseScreenProcPtr CloseScreen;
+ GFX2DOPREG_BLTER_FULL_LOAD bltcmd;
+ Bool usePIO;
+ I740WriteIndexedByteFunc writeControl;
+ I740ReadIndexedByteFunc readControl;
+ I740WriteByteFunc writeStandard;
+ I740ReadByteFunc readStandard;
+ OptionInfoPtr Options;
+
+ /*DGA*/
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+ BoxRec FbMemBox;
+ /*-*/
+
+ /*I2C*/
+ I2CBusPtr rc_i2c;
+ /*-*/
+
+ /*-*/ /*Overlay*/
+ XF86VideoAdaptorPtr adaptor;
+ unsigned long OverlayStart;
+ unsigned long OverlayPhysical;
+ int colorKey;
+ ScreenBlockHandlerProcPtr BlockHandler;
+ int ov_offset_x,ov_offset_y;
+ /*-*/
+
+ Bool usevgacompat;
+} I740Rec;
+
+#define I740PTR(p) ((I740Ptr)((p)->driverPrivate))
+
+extern Bool I740CursorInit(ScreenPtr pScreen);
+extern Bool I740AccelInit(ScreenPtr pScreen);
+void I740SetPIOAccess(I740Ptr pI740);
+void I740SetMMIOAccess(I740Ptr pI740);
+void I740InitVideo(ScreenPtr pScreen);
+
+Bool I740SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+void I740AdjustFrame(int scrnIndex, int x, int y, int flags);
+
+
+#define minb(p) MMIO_IN8(pI740->MMIOBase, (p))
+#define moutb(p,v) MMIO_OUT8(pI740->MMIOBase, (p),(v))
+
+#endif
diff --git a/src/i740_accel.c b/src/i740_accel.c
new file mode 100644
index 0000000..78c9644
--- /dev/null
+++ b/src/i740_accel.c
@@ -0,0 +1,396 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_accel.c,v 1.7 2002/10/21 13:32:58 alanh Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "xaa.h"
+#include "vgaHW.h"
+
+#include "xf86xv.h"
+#include "i740.h"
+
+static unsigned int i740Rop[16] = {
+ 0x00, /* GXclear */
+ 0x88, /* GXand */
+ 0x44, /* GXandReverse */
+ 0xCC, /* GXcopy */
+ 0x22, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x66, /* GXxor */
+ 0xEE, /* GXor */
+ 0x11, /* GXnor */
+ 0x99, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xDD, /* GXorReverse */
+ 0x33, /* GXcopyInvert */
+ 0xBB, /* GXorInverted */
+ 0x77, /* GXnand */
+ 0xFF /* GXset */
+};
+
+static unsigned int i740PatternRop[16] = {
+ 0x00, /* GXclear */
+ 0xA0, /* GXand */
+ 0x50, /* GXandReverse */
+ 0xF0, /* GXcopy */
+ 0x0A, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x5A, /* GXxor */
+ 0xFA, /* GXor */
+ 0x05, /* GXnor */
+ 0xA5, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xF5, /* GXorReverse */
+ 0x0F, /* GXcopyInvert */
+ 0xAF, /* GXorInverted */
+ 0x5F, /* GXnand */
+ 0xFF /* GXset */
+};
+
+static void I740SyncPIO(ScrnInfoPtr pScrn);
+static void I740SyncMMIO(ScrnInfoPtr pScrn);
+static void I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+static void I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+static void I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
+ int ydir, int rop,
+ unsigned int planemask,
+ int transparency_color);
+static void I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h);
+static void I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int x, int y, int w, int h);
+#if 0
+static void I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int bg, int fg, int rop,
+ unsigned int planemask);
+static void I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int skipleft);
+#endif
+/*
+ * The following function sets up the supported acceleration. Call it
+ * from the FbInit() function in the SVGA driver, or before ScreenInit
+ * in a monolithic server.
+ */
+Bool
+I740AccelInit(ScreenPtr pScreen) {
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ pI740->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr) return FALSE;
+
+ if (pScrn->bitsPerPixel == 32) {
+ infoPtr->Flags = 0; /* Disables all acceleration */
+ return TRUE;;
+ }
+
+ infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
+
+ /* Sync */
+ if (pI740->usePIO)
+ infoPtr->Sync = I740SyncPIO;
+ else
+ infoPtr->Sync = I740SyncMMIO;
+
+ infoPtr->CachePixelGranularity=8/pI740->cpp;
+
+ /* Solid filled rectangles */
+ infoPtr->SolidFillFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidFill = I740SetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = I740SubsequentSolidFillRect;
+
+ /* Screen to screen copy */
+ infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
+ infoPtr->SetupForScreenToScreenCopy = I740SetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy = I740SubsequentScreenToScreenCopy;
+
+ /* 8x8 pattern fills */
+ infoPtr->SetupForMono8x8PatternFill = I740SetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect = I740SubsequentMono8x8PatternFillRect;
+ infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST;
+
+ /* CPU to screen color expansion */
+ /* Currently XAA is limited to only DWORD padding. The 3.3 driver
+ * uses NO_PAD scanlines b/c of problems with using the chip in
+ * DWORD mode. Once other padding modes are available in XAA this
+ * Code can be turned back on.
+ */
+#if 0
+#ifndef ALLOW_PCI_COLOR_EXP
+ if (pI740->Chipset != PCI_CHIP_I740_PCI) {
+#endif
+ /*
+ * Currently, we are not properly able to read the bitblt engine
+ * busy bit on the PCI i740 card. When we are able to do so, we
+ * can re-enable color expansion.
+ */
+ infoPtr->CPUToScreenColorExpandFillFlags =
+ NO_PLANEMASK |
+#ifdef USE_DWORD_COLOR_EXP
+ SCANLINE_PAD_DWORD |
+#endif
+ CPU_TRANSFER_PAD_QWORD |
+ SYNC_AFTER_COLOR_EXPAND |
+ BIT_ORDER_IN_BYTE_MSBFIRST;
+ infoPtr->ColorExpandBase = (unsigned char *)(pI740->MMIOBase + BLTDATA);
+ infoPtr->ColorExpandRange = 0x10000;
+ infoPtr->SetupForCPUToScreenColorExpandFill = I740SetupForCPUToScreenColorExpandFill;
+ infoPtr->SubsequentCPUToScreenColorExpandFill = I740SubsequentCPUToScreenColorExpandFill;
+#ifndef ALLOW_PCI_COLOR_EXP
+ }
+#endif
+#endif
+ return XAAInit(pScreen, infoPtr);
+}
+
+static void
+I740SyncPIO(ScrnInfoPtr pScrn) {
+ WAIT_ENGINE_IDLE_PIO();
+}
+
+static void
+I740SyncMMIO(ScrnInfoPtr pScrn) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ WAIT_ENGINE_IDLE_MMIO();
+}
+
+static void
+I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+
+ pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
+ (pScrn->displayWidth * pI740->cpp);
+ pI740->bltcmd.BR01 = color;
+ pI740->bltcmd.BR04 = SOLID_PAT_SELECT | PAT_IS_MONO | i740PatternRop[rop];
+}
+
+static void
+I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ WAIT_LP_FIFO(12);
+ OUTREG(LP_FIFO, 0x6000000A);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR00);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR01);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR04);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
+}
+
+static void
+I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int transparency_color)
+{
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ pI740->bltcmd.BR00 = (((pScrn->displayWidth * pI740->cpp) << 16) |
+ (pScrn->displayWidth * pI740->cpp));
+
+ pI740->bltcmd.BR04 = SRC_IS_IN_COLOR | SRC_USE_SRC_ADDR | i740Rop[rop];
+ if (xdir == -1)
+ pI740->bltcmd.BR04 |= BLT_RIGHT_TO_LEFT;
+ else
+ pI740->bltcmd.BR04 |= BLT_LEFT_TO_RIGHT;
+
+ if (ydir == -1)
+ pI740->bltcmd.BR04 |= BLT_BOT_TO_TOP;
+ else
+ pI740->bltcmd.BR04 |= BLT_TOP_TO_BOT;
+
+ pI740->bltcmd.BR01 = 0x00000000;
+
+}
+
+static void
+I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ if (pI740->bltcmd.BR04 & BLT_BOT_TO_TOP) {
+ pI740->bltcmd.BR06 = (y1 + h - 1) *
+ pScrn->displayWidth * pI740->cpp;
+ pI740->bltcmd.BR07 = (y2 + h - 1) *
+ pScrn->displayWidth * pI740->cpp;
+ } else {
+ pI740->bltcmd.BR06 = y1 * pScrn->displayWidth * pI740->cpp;
+ pI740->bltcmd.BR07 = y2 * pScrn->displayWidth * pI740->cpp;
+ }
+
+ if (pI740->bltcmd.BR04 & BLT_RIGHT_TO_LEFT) {
+ pI740->bltcmd.BR06 += (x1 + w - 1) * pI740->cpp + pI740->cpp - 1;
+ pI740->bltcmd.BR07 += (x2 + w - 1) * pI740->cpp + pI740->cpp - 1;
+ } else {
+ pI740->bltcmd.BR06 += x1 * pI740->cpp;
+ pI740->bltcmd.BR07 += x2 * pI740->cpp;
+ }
+
+ WAIT_LP_FIFO(12);
+ OUTREG(LP_FIFO, 0x6000000A);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR00);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR01);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR04);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR06);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR07);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
+}
+
+static void
+I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) |
+ (pScrn->displayWidth * pI740->cpp);
+
+ pI740->bltcmd.BR01 = bg;
+ pI740->bltcmd.BR02 = fg;
+
+ pI740->bltcmd.BR04 = PAT_IS_MONO | i740PatternRop[rop];
+ if (bg == -1) pI740->bltcmd.BR04 |= MONO_PAT_TRANSP;
+
+ pI740->bltcmd.BR05 = (pattx + patty * pScrn->displayWidth) * pI740->cpp;
+}
+
+static void
+I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
+ int x, int y, int w, int h) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ WAIT_LP_FIFO(12);
+ OUTREG(LP_FIFO, 0x6000000A);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR00);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR01);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR02);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR04 | ((y<<20) & PAT_VERT_ALIGN));
+ OUTREG(LP_FIFO, pI740->bltcmd.BR05);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
+}
+#if 0
+static void
+I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int bg, int fg,
+ int rop, unsigned int planemask) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ pI740->bltcmd.BR00 = (pScrn->displayWidth * pI740->cpp) << 16;
+ pI740->bltcmd.BR01 = bg;
+ pI740->bltcmd.BR02 = fg;
+#ifdef USE_DWORD_COLOR_EXP
+ pI740->bltcmd.BR03 = MONO_DWORD_ALIGN | MONO_USE_COLEXP;
+#else
+ pI740->bltcmd.BR03 = MONO_BIT_ALIGN | MONO_USE_COLEXP;
+#endif
+ pI740->bltcmd.BR04 = SRC_IS_MONO | SRC_USE_BLTDATA | i740Rop[rop];
+ if (bg == -1) pI740->bltcmd.BR04 |= MONO_SRC_TRANSP;
+}
+
+static void
+I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int skipleft) {
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ pI740->AccelInfoRec->Sync(pScrn);
+ OUTREG(LP_FIFO, 0x6000000A);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR00);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR01);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR02);
+ OUTREG(LP_FIFO, pI740->bltcmd.BR03 | (skipleft & MONO_SRC_LEFT_CLIP));
+ OUTREG(LP_FIFO, pI740->bltcmd.BR04);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp);
+ OUTREG(LP_FIFO, 0x00000000);
+ OUTREG(LP_FIFO, 0x00000000);
+#ifdef USE_DWORD_COLOR_EXP
+ /*
+ * This extra wait is necessary to keep the bitblt engine from
+ * locking up, but I am not sure why it is needed. If we take it
+ * out, "x11perf -copyplane10" will lock the bitblt engine. When
+ * the bitblt engine is locked, it is waiting for mono data to be
+ * written to the BLTDATA region, which seems to imply that some of
+ * the data that was written was lost. This might be fixed by
+ * BLT_SKEW changes. Update: The engine still locks up with this
+ * extra wait. More investigation (and time) is needed.
+ */
+ WAIT_BLT_IDLE();
+#endif
+ OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp));
+}
+#endif
diff --git a/src/i740_cursor.c b/src/i740_cursor.c
new file mode 100644
index 0000000..6f62660
--- /dev/null
+++ b/src/i740_cursor.c
@@ -0,0 +1,220 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_cursor.c,v 1.5 2002/10/21 13:32:58 alanh Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86fbman.h"
+
+#include "vgaHW.h"
+#include "xf86xv.h"
+#include "i740.h"
+
+static void I740LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void I740ShowCursor(ScrnInfoPtr pScrn);
+static void I740HideCursor(ScrnInfoPtr pScrn);
+static void I740SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static void I740SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
+static Bool I740UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
+
+Bool
+I740CursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ I740Ptr pI740;
+ xf86CursorInfoPtr infoPtr;
+ FBAreaPtr fbarea;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI740 = I740PTR(pScrn);
+ pI740->CursorInfoRec = infoPtr = xf86CreateCursorInfoRec();
+ if (!infoPtr) return FALSE;
+
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+ HARDWARE_CURSOR_INVERT_MASK |
+ HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
+
+ infoPtr->SetCursorColors = I740SetCursorColors;
+ infoPtr->SetCursorPosition = I740SetCursorPosition;
+ infoPtr->LoadCursorImage = I740LoadCursorImage;
+ infoPtr->HideCursor = I740HideCursor;
+ infoPtr->ShowCursor = I740ShowCursor;
+ infoPtr->UseHWCursor = I740UseHWCursor;
+
+/*
+ * Allocate a region the full width and tall enough
+ * that at least 6K of video memory is consumed.
+ * Then use a 1 kilobyte piece that is 4K byte aligned
+ * within that region. KAO.
+ */
+ fbarea = xf86AllocateOffscreenArea(pScreen,
+ pScrn->displayWidth,
+ ((6*1024)/(pScrn->displayWidth*pI740->cpp))+1,
+ 0,0,0,0);
+ if (fbarea == NULL) {
+ pI740->CursorStart=0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Hardware cursor disabled due to failure allocating offscreen memory.\n");
+ }
+ else {
+ pI740->CursorStart = ((((fbarea->box.x1 + pScrn->displayWidth * fbarea->box.y1) * pI740->cpp)+4096)&0xfff000);
+ }
+ /*
+ * Perhaps move the cursor to the beginning of the frame buffer
+ * so that it never fails?
+ */
+ if (pI740->CursorStart>4*1024*1024) {
+ pI740->CursorStart=0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling hardware cursor due to large framebuffer\n");
+ }
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+static Bool
+I740UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) {
+ ScrnInfoPtr pScrn;
+ I740Ptr pI740;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI740 = I740PTR(pScrn);
+ if (pScrn->currentMode->Flags&V_DBLSCAN)
+ return FALSE;
+ if (!pI740->CursorStart) return FALSE;
+ return TRUE;
+}
+
+static void
+I740LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) {
+ I740Ptr pI740;
+ int x, y;
+ CARD8 *pcurs;
+
+ pI740 = I740PTR(pScrn);
+ pcurs = (CARD8 *)(pI740->FbBase + pI740->CursorStart);
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64 / 4; x++) {
+ *pcurs++ = *src++;
+ }
+ }
+}
+
+static void
+I740SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) {
+ I740Ptr pI740;
+ int flag;
+
+ pI740 = I740PTR(pScrn);
+ if (x >= 0) flag = CURSOR_X_POS;
+ else {
+ flag = CURSOR_X_NEG;
+ x=-x;
+ }
+ pI740->writeControl(pI740, XRX, CURSOR_X_LO, x&0xFF);
+ pI740->writeControl(pI740, XRX, CURSOR_X_HI, (((x >> 8) & 0x07) | flag));
+
+ if (y >= 0) flag = CURSOR_Y_POS;
+ else {
+ flag = CURSOR_Y_NEG;
+ y=-y;
+ }
+ pI740->writeControl(pI740, XRX, CURSOR_Y_LO, y&0xFF);
+ pI740->writeControl(pI740, XRX, CURSOR_Y_HI, (((y >> 8) & 0x07) | flag));
+}
+
+static void
+I740ShowCursor(ScrnInfoPtr pScrn) {
+ I740Ptr pI740;
+ unsigned char tmp;
+
+ pI740 = I740PTR(pScrn);
+ pI740->writeControl(pI740, XRX, CURSOR_BASEADDR_LO,
+ (pI740->CursorStart & 0x0000F000) >> 8);
+ pI740->writeControl(pI740, XRX, CURSOR_BASEADDR_HI,
+ (pI740->CursorStart & 0x003F0000) >> 16);
+ pI740->writeControl(pI740, XRX, CURSOR_CONTROL,
+ CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C);
+
+ tmp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ tmp |= HW_CURSOR_ENABLE;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I740HideCursor(ScrnInfoPtr pScrn) {
+ unsigned char tmp;
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ tmp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ tmp &= ~HW_CURSOR_ENABLE;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I740SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) {
+ int tmp;
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+ tmp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ tmp |= EXTENDED_PALETTE;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, tmp);
+
+ pI740->writeStandard(pI740, DACMASK, 0xFF);
+ pI740->writeStandard(pI740, DACWX, 0x04);
+
+ pI740->writeStandard(pI740, DACDATA, (bg & 0x00FF0000) >> 16);
+ pI740->writeStandard(pI740, DACDATA, (bg & 0x0000FF00) >> 8);
+ pI740->writeStandard(pI740, DACDATA, (bg & 0x000000FF));
+
+ pI740->writeStandard(pI740, DACDATA, (fg & 0x00FF0000) >> 16);
+ pI740->writeStandard(pI740, DACDATA, (fg & 0x0000FF00) >> 8);
+ pI740->writeStandard(pI740, DACDATA, (fg & 0x000000FF));
+
+ tmp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ tmp &= ~EXTENDED_PALETTE;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, tmp);
+}
+
+
+
diff --git a/src/i740_dga.c b/src/i740_dga.c
new file mode 100644
index 0000000..0edc0b9
--- /dev/null
+++ b/src/i740_dga.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2001 by Patrick LERDA
+ *
+ * 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 Patrick LERDA not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Patrick LERDA makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PATRICK LERDA 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: Patrick LERDA
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_dga.c,v 1.2 2003/02/12 21:46:42 tsi Exp $ */
+
+
+#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 "xf86xv.h"
+#include "i740.h"
+#include "dgaproc.h"
+#include "i740_dga.h"
+
+static Bool I740_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *);
+static Bool I740_SetMode(ScrnInfoPtr, DGAModePtr);
+static void I740_Sync(ScrnInfoPtr);
+static int I740_GetViewport(ScrnInfoPtr);
+static void I740_SetViewport(ScrnInfoPtr, int, int, int);
+static void I740_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void I740_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+#if 0
+static void I740_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long);
+#endif
+
+static DGAFunctionRec I740DGAFuncs = {
+ I740_OpenFramebuffer,
+ NULL,
+ I740_SetMode,
+ I740_SetViewport,
+ I740_GetViewport,
+ I740_Sync,
+ I740_FillRect,
+ I740_BlitRect,
+#if 0
+ I740_BlitTransRect
+#else
+ NULL
+#endif
+};
+
+Bool I740DGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I740Ptr pI740 = I740PTR(pScrn);
+ DGAModePtr modes = NULL, newmodes = NULL, currentMode;
+ DisplayModePtr pMode, firstMode;
+ int Bpp = pScrn->bitsPerPixel >> 3;
+ int num = 0;
+
+ 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++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if(pI740->AccelInfoRec)
+ currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ 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 = (Bpp == 3) ? 2 : 1;
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ currentMode->offset = 0;
+ currentMode->address = pI740->FbBase;
+
+ currentMode->bytesPerScanline =
+ ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+ currentMode->imageWidth = pI740->FbMemBox.x2;
+ currentMode->imageHeight = pI740->FbMemBox.y2;
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ 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;
+ }
+
+ pI740->numDGAModes = num;
+ pI740->DGAModes = modes;
+
+ return DGAInit(pScreen, &I740DGAFuncs, modes, num);
+}
+
+static DisplayModePtr I740SavedDGAModes[MAXSCREENS];
+
+static Bool I740_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ int index = pScrn->pScreen->myNum;
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ if(!pMode) { /* restore the original mode */
+ if(pI740->DGAactive) {
+ pScrn->currentMode = I740SavedDGAModes[index];
+ I740SwitchMode(index, pScrn->currentMode, 0);
+ I740AdjustFrame(index, 0, 0, 0);
+ pI740->DGAactive = FALSE;
+ }
+ } else {
+ if(!pI740->DGAactive) {
+ I740SavedDGAModes[index] = pScrn->currentMode;
+ pI740->DGAactive = TRUE;
+ }
+
+ I740SwitchMode(index, pMode->mode, 0);
+ }
+
+ return TRUE;
+}
+
+static int I740_GetViewport(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ return pI740->DGAViewportStatus;
+}
+
+static void I740_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ I740AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+
+ /* wait for retrace */
+ while((hwp->readST01(hwp) & 0x08));
+ while(!(hwp->readST01(hwp) & 0x08));
+
+ pI740->DGAViewportStatus = 0;
+}
+
+static void I740_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ if(pI740->AccelInfoRec) {
+ (*pI740->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pI740->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ SET_SYNC_FLAG(pI740->AccelInfoRec);
+ }
+}
+
+static void I740_Sync(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ if(pI740->AccelInfoRec) {
+ (*pI740->AccelInfoRec->Sync)(pScrn);
+ }
+}
+
+static void I740_BlitRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty
+ ){
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ if(pI740->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pI740->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pI740->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h);
+ SET_SYNC_FLAG(pI740->AccelInfoRec);
+ }
+}
+
+#if 0
+static void I740_BlitTransRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+ )
+{
+ /* this one should be separate since the XAA function would
+ prohibit usage of ~0 as the key */
+}
+#endif
+
+static Bool I740_OpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+ ){
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)pI740->LinearAddr;
+ *size = pI740->FbMapSize;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
diff --git a/src/i740_dga.h b/src/i740_dga.h
new file mode 100644
index 0000000..ea00de2
--- /dev/null
+++ b/src/i740_dga.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2001 by Patrick LERDA
+ *
+ * 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 Patrick LERDA not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Patrick LERDA makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PATRICK LERDA 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: Patrick LERDA
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_dga.h,v 1.1 2002/10/21 13:32:58 alanh Exp $ */
+
+Bool I740DGAInit(ScreenPtr pScreen);
diff --git a/src/i740_driver.c b/src/i740_driver.c
new file mode 100644
index 0000000..51e8b61
--- /dev/null
+++ b/src/i740_driver.c
@@ -0,0 +1,1921 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_driver.c,v 1.41 2003/02/17 16:59:02 dawes Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+/*
+ * This server does not support these XFree86 4.0 features yet
+ * DDC1 & DDC2 (requires I2C)
+ * shadowFb (if requested or acceleration is off)
+ * Overlay planes
+ * DGA
+ */
+
+/*
+ * These are X and server generic header files.
+ */
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+
+/* If the driver uses port I/O directly, it needs: */
+
+#include "compiler.h"
+
+/* Drivers using the mi implementation of backing store need: */
+
+#include "mibstore.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"
+
+/* Drivers using the mi SW cursor need: */
+
+#include "mipointer.h"
+
+/* Drivers using the mi colourmap code need: */
+
+#include "micmap.h"
+
+#define USE_FB
+
+#ifdef USE_FB
+#include "fb.h"
+#else
+/* Drivers using cfb need: */
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+
+/* Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: */
+
+#include "cfb16.h"
+#include "cfb24.h"
+#include "cfb32.h"
+#endif
+
+/* The driver's own header file: */
+
+
+#include "miscstruct.h"
+
+#include "xf86xv.h"
+#include "Xv.h"
+
+#include "vbe.h"
+#include "i740_dga.h"
+#include "i740.h"
+
+
+/* Required Functions: */
+static const OptionInfoRec * I740AvailableOptions(int chipid, int busid);
+
+/* Print a driver identifying message. */
+static void I740Identify(int flags);
+
+/* Identify if there is any hardware present that I know how to drive. */
+static Bool I740Probe(DriverPtr drv, int flags);
+
+/* Process the config file and see if we have a valid configuration */
+static Bool I740PreInit(ScrnInfoPtr pScrn, int flags);
+
+/* Initialize a screen */
+static Bool I740ScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
+
+/* Enter from a virtual terminal */
+static Bool I740EnterVT(int scrnIndex, int flags);
+
+/* Leave to a virtual terminal */
+static void I740LeaveVT(int scrnIndex, int flags);
+
+/* Close down each screen we initialized */
+static Bool I740CloseScreen(int scrnIndex, ScreenPtr pScreen);
+
+/* Change screensaver state */
+static Bool I740SaveScreen(ScreenPtr pScreen, int mode);
+
+/* Cleanup server private data */
+static void I740FreeScreen(int scrnIndex, int flags);
+
+/* Check if a mode is valid on the hardware */
+static int I740ValidMode(int scrnIndex, DisplayModePtr mode, Bool
+ verbose, int flags);
+
+/* Switch to various Display Power Management System levels */
+static void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagermentMode, int flags);
+
+static void I740ProbeDDC(ScrnInfoPtr pScrn, int index);
+
+static Bool I740MapMem(ScrnInfoPtr pScrn);
+static Bool I740UnmapMem(ScrnInfoPtr pScrn);
+
+
+#define VERSION 4000
+#define I740_NAME "I740"
+#define I740_DRIVER_NAME "i740"
+#define I740_MAJOR_VERSION 1
+#define I740_MINOR_VERSION 0
+#define I740_PATCHLEVEL 0
+
+DriverRec I740 = {
+ VERSION,
+ I740_DRIVER_NAME,
+ I740Identify,
+ I740Probe,
+ I740AvailableOptions,
+ NULL,
+ 0
+};
+
+/* Chipsets */
+static SymTabRec I740Chipsets[] = {
+ { PCI_CHIP_I740_AGP, "i740 (agp)"},
+ { PCI_CHIP_I740_PCI, "i740 (pci)"},
+ { -1, NULL }
+};
+
+static PciChipsets I740PciChipsets[] = {
+ { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA },
+ { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_SDRAM,
+ OPTION_SGRAM,
+ OPTION_SLOW_RAM,
+ OPTION_DAC_6BIT,
+ OPTION_USE_PIO,
+ OPTION_VGACOMPAT
+} I740Opts;
+
+static const OptionInfoRec I740Options[] = {
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE},
+ { -1, NULL, OPTV_NONE, {0}, FALSE}
+};
+
+static const char *vgahwSymbols[] = {
+ "vgaHWGetHWRec",
+ "vgaHWSave", /* Added */
+ "vgaHWRestore", /* Added */
+ "vgaHWProtect",
+ "vgaHWInit",
+ "vgaHWMapMem",
+ "vgaHWSetMmioFuncs",
+ "vgaHWGetIOBase",
+ "vgaHWLock",
+ "vgaHWUnlock",
+ "vgaHWFreeHWRec",
+ "vgaHWSaveScreen",
+ "vgaHWHandleColormaps",
+ 0
+};
+
+static const char *fbSymbols[] = {
+#ifdef USE_FB
+ "fbScreenInit",
+ "fbPictureInit",
+#else
+ "cfbScreenInit",
+ "cfb16ScreenInit",
+ "cfb24ScreenInit",
+ "cfb32ScreenInit",
+#endif
+ "cfb8_32ScreenInit",
+ "cfb24_32ScreenInit",
+ NULL
+};
+
+static const char *xf8_32bppSymbols[] = {
+ "xf86Overlay8Plus32Init",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAADestroyInfoRec",
+ "XAACreateInfoRec",
+ "XAAInit",
+ "XAAStippleScanlineFuncLSBFirst",
+ "XAAOverlayFBfuncs",
+ "XAACachePlanarMonoStipple",
+ "XAAScreenIndex",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86InitCursor",
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ NULL
+};
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ NULL
+};
+
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(i740Setup);
+
+static XF86ModuleVersionInfo i740VersRec =
+{
+ "i740",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0};
+
+static pointer
+i740Setup(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(&I740, module, 0);
+
+ /*
+ * Modules that this driver always requires may be loaded here
+ * by calling LoadSubModule().
+ */
+
+ /*
+ * Tell the loader about symbols from other modules that this module
+ * might refer to.
+ */
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
+ xf8_32bppSymbols, ramdacSymbols, vbeSymbols,
+ ddcSymbols, i2cSymbols, NULL /* shadowSymbols */,
+ NULL /* fbdevsymbols */, NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer)1;
+ } else {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif
+
+/*
+ * I740GetRec and I740FreeRec --
+ *
+ * Private data for the driver is stored in the screen structure.
+ * These two functions create and destroy that private data.
+ *
+ */
+static Bool
+I740GetRec(ScrnInfoPtr pScrn) {
+ if (pScrn->driverPrivate) return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1);
+ return TRUE;
+}
+
+static void
+I740FreeRec(ScrnInfoPtr pScrn) {
+ if (!pScrn) return;
+ if (!pScrn->driverPrivate) return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate=0;
+}
+
+static const OptionInfoRec *
+I740AvailableOptions(int chipid, int busid)
+{
+ return I740Options;
+}
+
+/*
+ * I740Identify --
+ *
+ * Returns the string name for the driver based on the chipset. In this
+ * case it will always be an I740, so we can return a static string.
+ *
+ */
+static void
+I740Identify(int flags) {
+ xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets);
+}
+
+/*
+ * I740Probe --
+ *
+ * Look through the PCI bus to find cards that are I740 boards.
+ * Setup the dispatch table for the rest of the driver functions.
+ *
+ */
+static Bool
+I740Probe(DriverPtr drv, int flags) {
+ int i, numUsed, numDevSections, *usedChips;
+ GDevPtr *devSections;
+ Bool foundScreen = FALSE;
+
+ /*
+ Find the config file Device sections that match this
+ driver, and return if there are none.
+ */
+ if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) {
+ return FALSE;
+ }
+
+ /*
+ Since these Probing is just checking the PCI data the server already
+ collected.
+ */
+ if (!xf86GetPciVideoInfo()) return FALSE;
+
+ /* Look for Intel based chips */
+ numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL,
+ I740Chipsets, I740PciChipsets,
+ devSections, numDevSections,
+ drv, &usedChips);
+
+ if (numUsed > 0) {
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i=0; i<numUsed; i++) {
+ ScrnInfoPtr pScrn = NULL;
+ /* Allocate new ScrnInfoRec and claim the slot */
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ I740PciChipsets, 0, 0, 0, 0, 0))) {
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = I740_DRIVER_NAME;
+ pScrn->name = I740_NAME;
+ pScrn->Probe = I740Probe;
+ pScrn->PreInit = I740PreInit;
+ pScrn->ScreenInit = I740ScreenInit;
+ pScrn->SwitchMode = I740SwitchMode;
+ pScrn->AdjustFrame = I740AdjustFrame;
+ pScrn->EnterVT = I740EnterVT;
+ pScrn->LeaveVT = I740LeaveVT;
+ pScrn->FreeScreen = I740FreeScreen;
+ pScrn->ValidMode = I740ValidMode;
+ foundScreen = TRUE;
+
+ }
+ }
+ }
+
+
+ /* Look for Real3D based chips */
+ numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D,
+ I740Chipsets, I740PciChipsets,
+ devSections, numDevSections,
+ drv, &usedChips);
+
+ if (numUsed > 0) {
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i=0; i<numUsed; i++) {
+ ScrnInfoPtr pScrn = NULL;
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ I740PciChipsets, 0, 0, 0, 0, 0))) {
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = I740_DRIVER_NAME;
+ pScrn->name = I740_NAME;
+ pScrn->Probe = I740Probe;
+ pScrn->PreInit = I740PreInit;
+ pScrn->ScreenInit = I740ScreenInit;
+ pScrn->SwitchMode = I740SwitchMode;
+ pScrn->AdjustFrame = I740AdjustFrame;
+ pScrn->EnterVT = I740EnterVT;
+ pScrn->LeaveVT = I740LeaveVT;
+ pScrn->FreeScreen = I740FreeScreen;
+ pScrn->ValidMode = I740ValidMode;
+ foundScreen = TRUE;
+ }
+ }
+ }
+
+ xfree(devSections);
+ xfree(usedChips);
+
+ return foundScreen;
+}
+
+static void
+I740ProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+/*
+ * I740PreInit --
+ *
+ * Do initial setup of the board before we know what resolution we will
+ * be running at.
+ *
+ */
+static Bool
+I740PreInit(ScrnInfoPtr pScrn, int flags) {
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+ ClockRangePtr clockRanges;
+ int i;
+ MessageType from;
+ int temp;
+#ifndef USE_FB
+ char *mod=0, *reqSym=0;
+#endif
+ int flags24;
+ rgb defaultWeight = {0, 0, 0};
+
+ if (pScrn->numEntities != 1) return FALSE;
+
+ /* Allocate driverPrivate */
+ if (!I740GetRec(pScrn)) {
+ return FALSE;
+ }
+
+ pI740 = I740PTR(pScrn);
+
+ pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pI740->pEnt->location.type != BUS_PCI) return FALSE;
+
+ /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/
+ if (flags & PROBE_DETECT) {
+ I740ProbeDDC(pScrn, pI740->pEnt->index);
+ return TRUE;
+ }
+
+ /* 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;
+
+ pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index);
+ pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device,
+ pI740->PciInfo->func);
+
+ if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone))
+ return FALSE;
+ if (pI740->usePIO)
+ pScrn->racIoFlags = RAC_FB | RAC_COLORMAP;
+ else
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+
+ flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, flags24)) {
+ return FALSE;
+ } else {
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by i740 driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+ /*xf86PrintDepthBpp(pScrn);*/
+
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
+ return FALSE;
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ } else {
+ /* We don't currently support DirectColor at > 8bpp */
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* We use a programamble clock */
+ pScrn->progClock = TRUE;
+
+ hwp = VGAHWPTR(pScrn);
+ pI740->cpp = pScrn->bitsPerPixel/8;
+
+ /* Process the options */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(pI740->Options = xalloc(sizeof(I740Options))))
+ return FALSE;
+ memcpy(pI740->Options, I740Options, sizeof(I740Options));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options);
+
+ /* 6-BIT dac isn't reasonable for modes with > 8bpp */
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) &&
+ pScrn->bitsPerPixel>8) {
+ OptionInfoPtr ptr;
+ ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT);
+ ptr->found=FALSE;
+ }
+
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE))
+ pScrn->rgbBits=8;
+ else
+ pScrn->rgbBits=6;
+
+ /* We have to use PIO to probe, because we haven't mappend yet */
+ I740SetPIOAccess(pI740);
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) {
+ pScrn->chipset = pI740->pEnt->device->chipset;
+ from = X_CONFIG;
+ } else if (pI740->pEnt->device->chipID >= 0) {
+ pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pI740->pEnt->device->chipID);
+ } else {
+ from = X_PROBED;
+ pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->PciInfo->chipType);
+ }
+ if (pI740->pEnt->device->chipRev >= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pI740->pEnt->device->chipRev);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740");
+
+ if (pI740->pEnt->device->MemBase != 0) {
+ pI740->LinearAddr = pI740->pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else {
+ if (pI740->PciInfo->memBase[1] != 0) {
+ pI740->LinearAddr = pI740->PciInfo->memBase[0]&0xFF000000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid FB address in PCI config space\n");
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ pI740->LinearAddr);
+
+ if (pI740->pEnt->device->IOBase != 0) {
+ pI740->MMIOAddr = pI740->pEnt->device->IOBase;
+ from = X_CONFIG;
+ } else {
+ if (pI740->PciInfo->memBase[1]) {
+ pI740->MMIOAddr = pI740->PciInfo->memBase[1]&0xFFF80000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid MMIO address in PCI config space\n");
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
+ pI740->MMIOAddr);
+
+ /* Calculate memory */
+ if (pI740->pEnt->device->videoRam) {
+ pScrn->videoRam = pI740->pEnt->device->videoRam;
+ from = X_CONFIG;
+ } else {
+ if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM)
+ pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1);
+ else
+ pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0);
+ pScrn->videoRam = (pScrn->videoRam&0x0F)*1024;
+ from = X_PROBED;
+ }
+
+ temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO);
+ pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE));
+ if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
+ if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "It is nonsensical to set both SDRAM and SGRAM options\n");
+ return FALSE;
+ }
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) {
+ pI740->HasSGRAM = FALSE;
+ } else {
+ pI740->HasSGRAM = TRUE;
+ }
+ } else {
+ if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "It is nonsensical to set both SDRAM and SGRAM options\n");
+ return FALSE;
+ }
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) {
+ pI740->HasSGRAM = TRUE;
+ } else {
+ pI740->HasSGRAM = FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n",
+ pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM");
+ pI740->FbMapSize = pScrn->videoRam*1024;
+
+ /*
+ * If the driver can do gamma correction, it should call xf86SetGamma()
+ * here.
+ */
+
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ pI740->MaxClock = 0;
+ if (pI740->pEnt->device->dacSpeeds[0]) {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8];
+ break;
+ case 16:
+ pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16];
+ break;
+ case 24:
+ pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24];
+ break;
+ case 32:
+ pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32];
+ break;
+ }
+ if (!pI740->MaxClock)
+ pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0];
+ from = X_CONFIG;
+ } else {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pI740->MaxClock = 203000;
+ break;
+ case 16:
+ pI740->MaxClock = 163000;
+ break;
+ case 24:
+ if (pI740->HasSGRAM)
+ pI740->MaxClock = 136000;
+ else
+ pI740->MaxClock = 128000;
+ break;
+ case 32:
+ pI740->MaxClock = 86000;
+ }
+ }
+ clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next=NULL;
+ clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
+ clockRanges->maxClock=pI740->MaxClock;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = FALSE; /*PL*/
+ clockRanges->doubleScanAllowed = TRUE; /*PL*/
+
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ 0, 320, 1600,
+ 8, 200, 1200,
+ pScrn->display->virtualX, pScrn->display->virtualY,
+ pI740->FbMapSize, LOOKUP_BEST_REFRESH);
+
+ if (i==-1) {
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (!i || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ pScrn->currentMode = pScrn->modes;
+
+ xf86PrintModes(pScrn);
+
+ xf86SetDpi(pScrn, 0, 0);
+
+#ifdef USE_FB
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymbols("fbScreenInit","fbPictureInit", NULL);
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ mod = "cfb";
+ reqSym = "cfbScreenInit";
+ break;
+ case 16:
+ mod = "cfb16";
+ reqSym = "cfb16ScreenInit";
+ break;
+ case 24:
+ mod = "cfb24";
+ reqSym = "cfb24ScreenInit";
+ break;
+ case 32:
+ mod = "cfb32";
+ reqSym = "cfb32ScreenInit";
+ break;
+ }
+ if (mod && !xf86LoadSubModule(pScrn, mod)) {
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymbols(reqSym, NULL);
+#endif
+
+ if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+ if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ I740FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ /* We wont be using the VGA access after the probe */
+ if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) {
+ resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB},
+ {ResShrIoBlock,0x3C0,0x3DF},
+ _END };
+ resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF},
+ {ResShrMemBlock,0xB8000,0xBFFFF},
+ {ResShrMemBlock,0xB0000,0xB7FFF},
+ _END };
+
+ pI740->usePIO=FALSE;
+ I740SetMMIOAccess(pI740);
+ xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr);
+ xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr);
+ } else {
+ pI740->usePIO=TRUE;
+ }
+
+ if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT))
+ pI740->usevgacompat=TRUE;
+ else
+ pI740->usevgacompat=FALSE;
+
+
+#if 0 /*DDC2*/
+ { /*PL*/
+
+ if (xf86LoadSubModule(pScrn, "ddc")) {
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+ if ( xf86LoadSubModule(pScrn, "i2c") ) {
+ xf86LoaderReqSymLists(i2cSymbols,NULL);
+
+ if (I740MapMem(pScrn))
+ {
+ if (I740_I2CInit(pScrn))
+ {
+ xf86MonPtr MonInfo;
+
+ if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pI740->rc_i2c))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n",
+ MonInfo);
+ xf86PrintEDID( MonInfo );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor "
+ "info\n\n");
+ xf86SetDDCproperties(pScrn,MonInfo);
+ }
+
+ //xf86SetDDCproperties(pScrn,xf86PrintEDID( xf86DoEDID_DDC2(pScrn->scrnIndex,pI740->rc_i2c)));
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
+
+ I740UnmapMem(pScrn);
+ }
+ }
+ }
+ }
+#endif /*DDC2*/
+
+ { /* Overlay */
+ pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) |
+ (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
+
+ pI740->colorKey &= ((1 << pScrn->depth) - 1);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey);
+ }
+
+
+ return TRUE;
+}
+
+static Bool I740MapMem(ScrnInfoPtr pScrn)
+{
+ int mmioFlags;
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
+
+ pI740->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+ pI740->PciTag,
+ pI740->MMIOAddr,
+ 0x80000);
+ if (!pI740->MMIOBase) return FALSE;
+
+ pI740->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pI740->PciTag,
+ pI740->LinearAddr,
+ pI740->FbMapSize);
+ if (!pI740->FbBase) return FALSE;
+
+ return TRUE;
+}
+
+static Bool I740UnmapMem(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->MMIOBase, 0x80000);
+ pI740->MMIOBase=0;
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->FbBase, pI740->FbMapSize);
+ pI740->FbBase = 0;
+ return TRUE;
+}
+
+/*
+ * I740Save --
+ *
+ * This function saves the video state. It reads all of the SVGA registers
+ * into the vgaI740Rec data structure. There is in general no need to
+ * mask out bits here - just read the registers.
+ */
+static void
+DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, Bool saveFonts)
+{
+ I740Ptr pI740;
+ vgaHWPtr hwp;
+
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+ if (saveFonts)
+ vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS);
+ else
+ vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
+
+ /*
+ * The port I/O code necessary to read in the extended registers
+ * into the fields of the vgaI740Rec structure goes here.
+ */
+
+ i740Reg->IOControl = pI740->readControl(pI740, XRX, IO_CTNL);
+ i740Reg->AddressMapping = pI740->readControl(pI740, XRX, ADDRESS_MAPPING);
+ i740Reg->BitBLTControl = pI740->readControl(pI740, XRX, BITBLT_CNTL);
+ i740Reg->VideoClk2_M = pI740->readControl(pI740, XRX, VCLK2_VCO_M);
+ i740Reg->VideoClk2_N = pI740->readControl(pI740, XRX, VCLK2_VCO_N);
+ i740Reg->VideoClk2_MN_MSBs = pI740->readControl(pI740, XRX, VCLK2_VCO_MN_MSBS);
+ i740Reg->VideoClk2_DivisorSel = pI740->readControl(pI740, XRX, VCLK2_VCO_DIV_SEL);
+ i740Reg->PLLControl = pI740->readControl(pI740, XRX, PLL_CNTL);
+
+ i740Reg->ExtVertTotal=hwp->readCrtc(hwp, EXT_VERT_TOTAL);
+ i740Reg->ExtVertDispEnd=hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
+ i740Reg->ExtVertSyncStart=hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
+ i740Reg->ExtVertBlankStart=hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
+ i740Reg->ExtHorizTotal=hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
+ i740Reg->ExtHorizBlank=hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
+ i740Reg->ExtOffset=hwp->readCrtc(hwp, EXT_OFFSET);
+ i740Reg->InterlaceControl=hwp->readCrtc(hwp, INTERLACE_CNTL);
+
+ i740Reg->PixelPipeCfg0 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ i740Reg->PixelPipeCfg1 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1);
+ i740Reg->PixelPipeCfg2 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2);
+ i740Reg->DisplayControl = pI740->readControl(pI740, XRX, DISPLAY_CNTL);
+
+ i740Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
+}
+
+static void
+I740Save(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+
+ hwp = VGAHWPTR(pScrn);
+ pI740 = I740PTR(pScrn);
+ DoSave(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE);
+}
+
+static void
+DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg,
+ Bool restoreFonts) {
+ I740Ptr pI740;
+ vgaHWPtr hwp;
+ unsigned char temp;
+ unsigned int itemp;
+
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ vgaHWProtect(pScrn, TRUE);
+#if 0
+ temp=hwp->readCrtc(hwp, VERT_SYNC_END);
+ hwp->writeCrtc(hwp, VERT_SYNC_END, temp&0x7F);
+#endif
+
+ temp = pI740->readControl(pI740, MRX, ACQ_CNTL_2);
+ if ((temp & FRAME_CAP_MODE) == SINGLE_CAP_MODE) {
+ temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1);
+ temp |= BLANK_DISP_OVERLAY; /* Disable the overlay */
+ pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp);
+ } else {
+ temp &= ~FRAME_CAP_MODE;
+ pI740->writeControl(pI740, MRX, ACQ_CNTL_2, temp);
+ }
+ usleep(50000);
+
+ /* Turn off DRAM Refresh */
+ pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+ usleep(1000); /* Wait 1 ms */
+
+ /* Write the M, N and P values */
+ pI740->writeControl(pI740, XRX, VCLK2_VCO_M, i740Reg->VideoClk2_M);
+ pI740->writeControl(pI740, XRX, VCLK2_VCO_N, i740Reg->VideoClk2_N);
+ pI740->writeControl(pI740, XRX, VCLK2_VCO_MN_MSBS, i740Reg->VideoClk2_MN_MSBs);
+ pI740->writeControl(pI740, XRX, VCLK2_VCO_DIV_SEL, i740Reg->VideoClk2_DivisorSel);
+
+ /*
+ * Turn on 8 bit dac mode, if requested. This is needed to make
+ * sure that vgaHWRestore writes the values into the DAC properly.
+ * The problem occurs if 8 bit dac mode is requested and the HW is
+ * in 6 bit dac mode. If this happens, all the values are
+ * automatically shifted left twice by the HW and incorrect colors
+ * will be displayed on the screen. The only time this can happen
+ * is at server startup time and when switching back from a VT.
+ */
+ temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ temp &= 0x7F; /* Save all but the 8 bit dac mode bit */
+ temp |= (i740Reg->PixelPipeCfg0 & DAC_8_BIT);
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp);
+
+ /*
+ * Code to restore any SVGA registers that have been saved/modified
+ * goes here. Note that it is allowable, and often correct, to
+ * only modify certain bits in a register by a read/modify/write cycle.
+ *
+ * A special case - when using an external clock-setting program,
+ * this function must not change bits associated with the clock
+ * selection. This condition can be checked by the condition:
+ *
+ * if (restore->std.NoClock >= 0)
+ * restore clock-select bits.
+ */
+ if (restoreFonts)
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
+ else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
+
+ hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i740Reg->ExtVertTotal);
+ hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i740Reg->ExtVertDispEnd);
+ hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i740Reg->ExtVertSyncStart);
+ hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i740Reg->ExtVertBlankStart);
+ hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i740Reg->ExtHorizTotal);
+ hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i740Reg->ExtHorizBlank);
+ hwp->writeCrtc(hwp, EXT_OFFSET, i740Reg->ExtOffset);
+
+ temp=hwp->readCrtc(hwp, INTERLACE_CNTL);
+ temp &= ~INTERLACE_ENABLE;
+ temp |= i740Reg->InterlaceControl;
+ hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
+
+ temp=pI740->readControl(pI740, XRX, ADDRESS_MAPPING);
+ temp &= 0xE0; /* Save reserved bits 7:5 */
+ temp |= i740Reg->AddressMapping;
+ pI740->writeControl(pI740, XRX, ADDRESS_MAPPING, temp);
+
+ temp=pI740->readControl(pI740, XRX, BITBLT_CNTL);
+ temp &= ~COLEXP_MODE;
+ temp |= i740Reg->BitBLTControl;
+ pI740->writeControl(pI740, XRX, BITBLT_CNTL, temp);
+
+ temp=pI740->readControl(pI740, XRX, DISPLAY_CNTL);
+ temp &= ~(VGA_WRAP_MODE | GUI_MODE);
+ temp |= i740Reg->DisplayControl;
+ pI740->writeControl(pI740, XRX, DISPLAY_CNTL, temp);
+
+ temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
+ temp &= 0x64; /* Save reserved bits 6:5,2 */
+ temp |= i740Reg->PixelPipeCfg0;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp);
+
+ temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2);
+ temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
+ temp |= i740Reg->PixelPipeCfg2;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_2, temp);
+
+ temp=pI740->readControl(pI740, XRX, PLL_CNTL);
+ temp = i740Reg->PLLControl; /* To fix the 2.3X BIOS problem */
+ pI740->writeControl(pI740, XRX, PLL_CNTL, temp);
+
+ temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1);
+ temp &= ~DISPLAY_COLOR_MODE;
+ temp |= i740Reg->PixelPipeCfg1;
+ pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_1, temp);
+
+ itemp = INREG(FWATER_BLC);
+ itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+ itemp |= i740Reg->LMI_FIFO_Watermark;
+ OUTREG(FWATER_BLC, itemp);
+
+ /* Turn on DRAM Refresh */
+ pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+ temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1);
+ temp &= ~BLANK_DISP_OVERLAY; /* Re-enable the overlay */
+ pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp);
+
+ if (!(vgaReg->Attribute[0x10] & 0x1)) {
+ usleep(50000);
+ if (restoreFonts)
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
+ else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+ temp=pI740->readControl(pI740, XRX, IO_CTNL);
+ temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+ temp |= i740Reg->IOControl;
+ pI740->writeControl(pI740, XRX, IO_CTNL, temp);
+#if 0
+ temp=hwp->readCrtc(hwp, VERT_SYNC_END);
+ hwp->writeCrtc(hwp, VERT_SYNC_END, temp|0x80);
+#endif
+}
+
+static void
+I740Restore(ScrnInfoPtr pScrn) {
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+
+ hwp = VGAHWPTR(pScrn);
+ pI740 = I740PTR(pScrn);
+
+ DoRestore(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE);
+}
+
+/*
+ * I740CalcFIFO --
+ *
+ * Calculate burst length and FIFO watermark.
+ */
+
+static unsigned int
+I740CalcFIFO(ScrnInfoPtr pScrn, double freq)
+{
+ unsigned int wm = 0x18120000;
+ I740Ptr pI740;
+
+ pI740 = I740PTR(pScrn);
+
+ /*
+ * Would like to calculate these values automatically, but a generic
+ * algorithm does not seem possible. Note: These FIFO water mark
+ * values were tested on several cards and seem to eliminate the
+ * all of the snow and vertical banding, but fine adjustments will
+ * probably be required for other cards.
+ */
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ if (pI740->HasSGRAM) {
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ } else {
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ }
+ break;
+ case 16:
+ if (pI740->HasSGRAM) {
+ if (freq > 140) wm = 0x2C1D0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24160000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ } else {
+ if (freq > 160) wm = 0x28200000;
+ else if (freq > 140) wm = 0x2A1E0000;
+ else if (freq > 130) wm = 0x2B1A0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24180000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ }
+ break;
+ case 24:
+ if (pI740->HasSGRAM) {
+ if (freq > 130) wm = 0x31200000;
+ else if (freq > 120) wm = 0x2E200000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ } else {
+ if (freq > 120) wm = 0x311F0000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ }
+ break;
+ case 32:
+ if (pI740->HasSGRAM) {
+ if (freq > 80) wm = 0x2A200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ } else {
+ if (freq > 80) wm = 0x29200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ }
+ break;
+ }
+
+ return wm;
+}
+
+/*
+ * I740CalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+
+#define MAX_VCO_FREQ 450.0
+#define TARGET_MAX_N 30
+#define REF_FREQ 66.66666666667
+
+#define CALC_VCLK(m,n,p,d) \
+ (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQ
+
+static void
+I740CalcVCLK(ScrnInfoPtr pScrn, double freq)
+{
+ I740Ptr pI740;
+ I740RegPtr i740Reg;
+ int m, n, p, d;
+ double f_out;
+ double f_err;
+ double f_vco;
+ int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
+ double f_target = freq;
+ double err_max = 0.005;
+ double err_target = 0.001;
+ double err_best = 999999.0;
+
+ pI740 = I740PTR(pScrn);
+ i740Reg = &pI740->ModeReg;
+
+ p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2);
+ d_best = d = 0;
+
+ f_vco = f_target * (1 << p);
+
+ n = 2;
+ do {
+ n++;
+ m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
+ if (m < 3) m = 3;
+ f_out = CALC_VCLK(m,n,p,d);
+ f_err = 1.0 - (f_target/f_out);
+ if (fabs(f_err) < err_max) {
+ m_best = m;
+ n_best = n;
+ err_best = f_err;
+ }
+ } while ((fabs(f_err) >= err_target) &&
+ ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
+
+ if (fabs(f_err) < err_target) {
+ m_best = m;
+ n_best = n;
+ }
+
+ i740Reg->VideoClk2_M = (m_best-2) & 0xFF;
+ i740Reg->VideoClk2_N = (n_best-2) & 0xFF;
+ i740Reg->VideoClk2_MN_MSBs = ((((n_best-2) >> 4) & VCO_N_MSBS) |
+ (((m_best-2) >> 8) & VCO_M_MSBS));
+ i740Reg->VideoClk2_DivisorSel = ((p_best << 4) |
+ (d_best ? 4 : 0) |
+ REF_DIV_1);
+}
+
+static Bool
+I740SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) {
+ I740Ptr pI740;
+ I740RegPtr i740Reg;
+ vgaRegPtr pVga;
+ double dclk = mode->Clock/1000.0;
+
+ pI740 = I740PTR(pScrn);
+ i740Reg = &pI740->ModeReg;
+ pVga = &VGAHWPTR(pScrn)->ModeReg;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
+ i740Reg->ExtOffset = pScrn->displayWidth >> 11;
+ i740Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
+ i740Reg->BitBLTControl = COLEXP_8BPP;
+ break;
+ case 16:
+ if (pScrn->weight.green == 5) {
+ i740Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
+ } else {
+ i740Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
+ }
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
+ i740Reg->ExtOffset = pScrn->displayWidth >> 10;
+ i740Reg->BitBLTControl = COLEXP_16BPP;
+ break;
+ case 24:
+ pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
+ i740Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
+ i740Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
+ i740Reg->BitBLTControl = COLEXP_24BPP;
+ break;
+ case 32:
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 1;
+ i740Reg->ExtOffset = pScrn->displayWidth >> 9;
+ i740Reg->PixelPipeCfg1 = DISPLAY_32BPP_MODE;
+ i740Reg->BitBLTControl = COLEXP_RESERVED; /* Not implemented on i740 */
+ break;
+ default:
+ break;
+ }
+
+ /* Turn on 8 bit dac if requested */
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE))
+ i740Reg->PixelPipeCfg0 = DAC_6_BIT;
+ else
+ i740Reg->PixelPipeCfg0 = DAC_8_BIT;
+
+ i740Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE /*| OVERLAY_GAMMA_ENABLE*/;
+
+ /* Turn on Extended VGA Interpretation */
+ i740Reg->IOControl = EXTENDED_CRTC_CNTL;
+
+ /* Turn on linear and page mapping */
+ i740Reg->AddressMapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+
+ /* Turn on GUI mode */
+ i740Reg->DisplayControl = HIRES_MODE;
+
+ /* Set the MCLK freq */
+ if (xf86ReturnOptValBool(pI740->Options, OPTION_SLOW_RAM, FALSE))
+ i740Reg->PLLControl = PLL_MEMCLK__66667KHZ; /* 66 MHz */
+ else
+ i740Reg->PLLControl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+ /* Calculate the extended CRTC regs */
+ i740Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
+ i740Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
+ i740Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
+ i740Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
+ i740Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
+ /*
+ * the KGA fix in vgaHW.c results in the first
+ * scanline and the first character clock (8 pixels)
+ * of each scanline thereafter on display with an i740
+ * to be blank. Restoring CRTC 3, 5, & 22 to their
+ * "theoretical" values corrects the problem. KAO.
+ */
+ i740Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0) << 6;
+ vgaHWVBlankKGA(mode, pVga, 8, 0);
+
+ /* Turn on interlaced mode if necessary */
+ if (mode->Flags & V_INTERLACE)
+ i740Reg->InterlaceControl = INTERLACE_ENABLE;
+ else
+ i740Reg->InterlaceControl = INTERLACE_DISABLE;
+
+ /*
+ * Set the overscan color to 0.
+ * NOTE: This only affects >8bpp mode.
+ */
+ pVga->Attribute[0x11] = 0;
+
+ /*
+ * Calculate the VCLK that most closely matches the requested dot
+ * clock.
+ */
+ I740CalcVCLK(pScrn, dclk);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ pVga->MiscOutReg |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ i740Reg->LMI_FIFO_Watermark = I740CalcFIFO(pScrn, dclk);
+
+ /*-Overlay-*/
+ pI740->ov_offset_x=((mode->CrtcHTotal-mode->CrtcHDisplay) & ~7)-9;
+ pI740->ov_offset_y=mode->CrtcVTotal-mode->CrtcVSyncEnd-2;
+ /*-*/
+
+ return TRUE;
+}
+
+static Bool
+I740ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode_src)
+{
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+ struct _DisplayModeRec mode_dst;
+ DisplayModePtr mode=&mode_dst;
+
+ *mode=*mode_src;
+
+ hwp = VGAHWPTR(pScrn);
+ pI740 = I740PTR(pScrn);
+
+ vgaHWUnlock(hwp);
+
+
+ if(pI740->usevgacompat)
+ { /* Try to get the same visual aspect as a S3 board */
+ mode->CrtcHSyncStart+=16;
+ mode->CrtcHSyncEnd +=16;
+ }
+
+ if (!vgaHWInit(pScrn, mode)) return FALSE;
+
+ pScrn->vtSema = TRUE;
+
+ if (!I740SetMode(pScrn, mode)) return FALSE;
+
+ DoRestore(pScrn, &hwp->ModeReg, &pI740->ModeReg, FALSE);
+
+ return TRUE;
+}
+
+static void I740LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ I740Ptr pI740;
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ for (i=0; i<numColors; i++)
+ {
+ index=indices[i/2];
+ r=colors[index].red;
+ b=colors[index].blue;
+ g=colors[index].green;
+
+ hwp->writeDacWriteAddr(hwp, index<<2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+
+ i++;
+ hwp->writeDacWriteAddr(hwp, index<<2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+}
+
+static void I740LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ I740Ptr pI740;
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ for (i=0; i<numColors; i++) {
+ index=indices[i/2];
+ r=colors[index].red;
+ b=colors[index].blue;
+ index=indices[i];
+ g=colors[index].green;
+ hwp->writeDacWriteAddr(hwp, index<<2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ i++;
+ index=indices[i];
+ g=colors[index].green;
+ hwp->writeDacWriteAddr(hwp, index<<2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+}
+
+static void
+I740LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual) {
+ I740Ptr pI740;
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ for (i=0; i<numColors; i++) {
+ index=indices[i];
+ r=colors[index].red;
+ b=colors[index].blue;
+ index=indices[i];
+ g=colors[index].green;
+ hwp->writeDacWriteAddr(hwp, index);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+}
+
+static Bool
+I740ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+ VisualPtr visual;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ if (!I740MapMem(pScrn)) return FALSE;
+ pScrn->memPhysBase = pI740->LinearAddr;
+ pScrn->fbOffset = 0;
+
+ if (!pI740->usePIO)
+ vgaHWSetMmioFuncs(hwp, pI740->MMIOBase, 0);
+ vgaHWGetIOBase(hwp);
+ if (!vgaHWMapMem(pScrn)) return FALSE;
+
+ I740Save(pScrn);
+ if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE;
+
+ I740SaveScreen(pScreen, SCREEN_SAVER_ON);
+ I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ miClearVisualTypes();
+
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+#ifdef USE_FB
+ if (!miSetPixmapDepths ()) return FALSE;
+#endif
+
+ switch (pScrn->bitsPerPixel) {
+#ifdef USE_FB
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ if (!fbScreenInit(pScreen, pI740->FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth,pScrn->bitsPerPixel))
+ return FALSE;
+ break;
+#else
+ case 8:
+ if (!cfbScreenInit(pScreen, pI740->FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 16:
+ if (!cfb16ScreenInit(pScreen, pI740->FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 24:
+ if (!cfb24ScreenInit(pScreen, pI740->FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ break;
+ case 32:
+ if (!cfb32ScreenInit(pScreen, pI740->FbBase,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth))
+ return FALSE;
+ break;
+#endif
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in I740ScrnInit\n",
+ pScrn->bitsPerPixel);
+ return FALSE;
+ }
+#ifdef USE_FB
+ fbPictureInit(pScreen,0,0);
+#endif
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel>8) {
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!miCreateDefColormap(pScreen)) return FALSE;
+
+ if (pScrn->bitsPerPixel==16)
+ {
+ if (pScrn->weight.green == 5)
+ {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+ else
+ {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+
+ xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0);
+
+#if 0 /*def XvExtension*/
+ {
+ XF86VideoAdaptorPtr *ptr;
+ int n;
+
+ n = xf86XVListGenericAdaptors(pScrn,&ptr);
+ if (n) {
+ xf86XVScreenInit(pScreen, ptr, n);
+ }
+ }
+#endif
+
+ memset(&(pI740->FbMemBox), 0, sizeof(BoxRec));
+ pI740->FbMemBox.x1=0;
+ pI740->FbMemBox.x2=pScrn->displayWidth;
+ pI740->FbMemBox.y1=0;
+ pI740->FbMemBox.y2=pI740->FbMapSize/(pScrn->displayWidth*pI740->cpp);
+
+ I740DGAInit(pScreen);
+
+ if (!xf86InitFBManager(pScreen, &pI740->FbMemBox)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n");
+ return FALSE;
+ }
+
+ if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) {
+ if (!I740AccelInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware acceleration initialization failed\n");
+ }
+ }
+
+ if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!I740CursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ pScreen->SaveScreen = I740SaveScreen;
+ pI740->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = I740CloseScreen;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+#ifdef XvExtension
+ { /* Overlay */
+ I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024;
+ }
+#endif /*XvExtension*/
+
+ return TRUE;
+}
+
+Bool
+I740SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) {
+ ScrnInfoPtr pScrn;
+
+ pScrn=xf86Screens[scrnIndex];
+ return I740ModeInit(pScrn, mode);
+}
+
+void
+I740AdjustFrame(int scrnIndex, int x, int y, int flags) {
+ ScrnInfoPtr pScrn;
+ I740Ptr pI740;
+ int Base;
+ vgaHWPtr hwp;
+
+ pScrn = xf86Screens[scrnIndex];
+ pI740 = I740PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ Base = (y * pScrn->displayWidth + x) >> 2;
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ Base *= 2;
+ break;
+ case 24:
+ /*
+ * The last bit does not seem to have any effect on the start
+ * address register in 24bpp mode, so...
+ */
+ Base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ Base *= 3;
+ break;
+ case 32:
+ Base *= 4;
+ break;
+ }
+
+ hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF);
+ hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8);
+ hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22);
+ hwp->writeCrtc(hwp, EXT_START_ADDR,
+ ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE));
+}
+
+static Bool
+I740EnterVT(int scrnIndex, int flags) {
+ ScrnInfoPtr pScrn;
+
+ pScrn = xf86Screens[scrnIndex];
+ if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return TRUE;
+}
+
+static void
+I740LeaveVT(int scrnIndex, int flags) {
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+
+ pScrn = xf86Screens[scrnIndex];
+ hwp=VGAHWPTR(pScrn);
+ I740Restore(pScrn);
+ vgaHWLock(hwp);
+}
+
+static Bool
+I740CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ I740Ptr pI740;
+
+ pScrn = xf86Screens[scrnIndex];
+ hwp = VGAHWPTR(pScrn);
+ pI740 = I740PTR(pScrn);
+
+ if (pScrn->vtSema) {
+ I740Restore(pScrn);
+ vgaHWLock(hwp);
+ }
+
+ I740UnmapMem(pScrn);
+ vgaHWUnmapMem(pScrn);
+ if (pI740->AccelInfoRec)
+ XAADestroyInfoRec(pI740->AccelInfoRec);
+ pI740->AccelInfoRec=0;
+ if (pI740->CursorInfoRec)
+ xf86DestroyCursorInfoRec(pI740->CursorInfoRec);
+ pI740->CursorInfoRec=0;
+ pScrn->vtSema=FALSE;
+
+ pScreen->CloseScreen = pI740->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+static void
+I740FreeScreen(int scrnIndex, int flags) {
+ I740FreeRec(xf86Screens[scrnIndex]);
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+}
+
+static int
+I740ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) {
+ if (mode->Flags & V_INTERLACE) {
+ if (verbose) {
+ xf86DrvMsg(scrnIndex, X_PROBED,
+ "Removing interlaced mode \"%s\"\n",
+ mode->name);
+ }
+ return MODE_BAD;
+ }
+ return MODE_OK;
+}
+
+static Bool
+I740SaveScreen(ScreenPtr pScreen, int mode)
+{
+#if 0
+ Bool unblack = xf86IsUnblank(mode);
+ if (unblack) outw(SRX, 0x0300);
+ else outw(SRX, 0x0100);
+#endif
+ return vgaHWSaveScreen(pScreen, mode);
+}
+
+static void
+I740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags) {
+ I740Ptr pI740;
+ unsigned char SEQ01=0;
+ int DPMSSyncSelect=0;
+
+ pI740 = I740PTR(pScrn);
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ }
+
+ /* Turn the screen on/off */
+ SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20;
+ pI740->writeControl(pI740, SRX, 0x01, SEQ01);
+
+ /* Set the DPMS mode */
+ pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+}
diff --git a/src/i740_i2c.c b/src/i740_i2c.c
new file mode 100644
index 0000000..174a578
--- /dev/null
+++ b/src/i740_i2c.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2001 by Patrick LERDA
+ *
+ * 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 Patrick LERDA not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Patrick LERDA makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PATRICK LERDA 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: Patrick LERDA
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_i2c.c,v 1.1 2002/10/21 13:32:58 alanh Exp $ */
+
+/* not working at this time */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+
+#include "vgaHW.h"
+
+#include "xf86xv.h"
+#include "i740.h"
+
+
+static void i740_I2CPutBits(I2CBusPtr b, int clk, int dat)
+{
+ I740Ptr pI740=I740PTR(xf86Screens[b->scrnIndex]);
+ unsigned char val;
+
+ val=pI740->readControl(pI740, XRX, 0x1C);
+
+ if(clk) val&=~0x40; else val|=0x40; if(dat) val&=~0x08; else val|=0x08;
+
+ /*if ( clk && dat) val&=0xBF; else if( clk && !dat) val&=0xF7; else if(!clk && dat) val|=0x40; else val|=0x08;*/
+
+ val|=0x90;
+
+ pI740->writeControl(pI740, XRX, 0x1C, val);
+
+ ErrorF("i740_I2CPutBits: clk=%d dat=%d [<1c>=0x%02x] [<63>=0x%02x] clk=%d dat=%d\n", clk, dat,val,pI740->readControl(pI740, XRX, 0x63),
+ !!(pI740->readControl(pI740, XRX, 0x63) & 0x02), !!(pI740->readControl(pI740, XRX, 0x63) & 0x01) );
+}
+
+static void i740_I2CGetBits(I2CBusPtr b, int *clk, int *dat)
+{
+ I740Ptr pI740=I740PTR(xf86Screens[b->scrnIndex]);
+ unsigned char val;
+
+ {
+ val=pI740->readControl(pI740, XRX, 0x1C);
+ val|=0x90;
+ pI740->writeControl(pI740, XRX, 0x1C, val);
+ }
+
+ {
+ val=pI740->readControl(pI740, XRX, 0x63);
+ *clk=!!(val & 0x02);
+ *dat=!!(val & 0x01);
+ }
+
+ ErrorF("i740_I2CGetBits: clk=%d dat=%d [<1c>=0x%02x] [<63>=0x%02x]\n", *clk, *dat,pI740->readControl(pI740, XRX, 0x1c) & 0xff,pI740->readControl(pI740, XRX, 0x63));
+}
+
+Bool I740_I2CInit(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740=I740PTR(pScrn);
+ I2CBusPtr I2CPtr;
+
+ { unsigned char val; val=pI740->readControl(pI740, XRX, 0x63); val&=0xFC; pI740->writeControl(pI740, XRX, 0x63, val); }
+ { unsigned char val; val=pI740->readControl(pI740, XRX, 0x1C); val|=0x90; pI740->writeControl(pI740, XRX, 0x1C, val); }
+ { unsigned char val; val=pI740->readControl(pI740, XRX, 0x63); val&=0xFC; pI740->writeControl(pI740, XRX, 0x63, val); }
+
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+
+ pI740->rc_i2c = I2CPtr;
+
+ I2CPtr->BusName = "I2C bus";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = i740_I2CPutBits;
+ I2CPtr->I2CGetBits = i740_I2CGetBits;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/i740_io.c b/src/i740_io.c
new file mode 100644
index 0000000..0195862
--- /dev/null
+++ b/src/i740_io.c
@@ -0,0 +1,93 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_io.c,v 1.5 2002/10/21 13:32:58 alanh Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "vgaHW.h"
+
+#include "xf86xv.h"
+#include "i740.h"
+
+static void I740WriteControlPIO(I740Ptr pI740, int addr, unsigned char index, char val) {
+ outb(addr, index);
+ outb(addr+1, val);
+}
+
+static char I740ReadControlPIO(I740Ptr pI740, int addr, unsigned char index) {
+ outb(addr, index);
+ return inb(addr+1);
+}
+
+static void I740WriteStandardPIO(I740Ptr pI740, int addr, unsigned char val) {
+ outb(addr, val);
+}
+
+static char I740ReadStandardPIO(I740Ptr pI740, int addr) {
+ return inb(addr);
+}
+
+void I740SetPIOAccess(I740Ptr pI740) {
+ pI740->writeControl=I740WriteControlPIO;
+ pI740->readControl=I740ReadControlPIO;
+ pI740->writeStandard=I740WriteStandardPIO;
+ pI740->readStandard=I740ReadStandardPIO;
+}
+
+static void I740WriteControlMMIO(I740Ptr pI740, int addr, unsigned char index, char val) {
+ moutb(addr, index);
+ moutb(addr+1, val);
+}
+
+static char I740ReadControlMMIO(I740Ptr pI740, int addr, unsigned char index) {
+ moutb(addr, index);
+ return minb(addr+1);
+}
+
+static void I740WriteStandardMMIO(I740Ptr pI740, int addr, unsigned char val) {
+ moutb(addr, val);
+}
+
+static char I740ReadStandardMMIO(I740Ptr pI740, int addr) {
+ return minb(addr);
+}
+
+void I740SetMMIOAccess(I740Ptr pI740) {
+ pI740->writeControl=I740WriteControlMMIO;
+ pI740->readControl=I740ReadControlMMIO;
+ pI740->writeStandard=I740WriteStandardMMIO;
+ pI740->readStandard=I740ReadStandardMMIO;
+}
+
diff --git a/src/i740_macros.h b/src/i740_macros.h
new file mode 100644
index 0000000..797b89f
--- /dev/null
+++ b/src/i740_macros.h
@@ -0,0 +1,61 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_macros.h,v 1.4 2002/10/21 13:32:58 alanh Exp $ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ */
+
+#include "xf86fbman.h"
+
+
+#define WAIT_ENGINE_IDLE_PIO() { \
+ outb(XRX, BITBLT_CNTL); \
+ while (inb(XRX+1) & BITBLT_STATUS) \
+ outb(XRX, BITBLT_CNTL); \
+ }
+
+#define WAIT_ENGINE_IDLE_MMIO() { \
+ moutb(XRX, BITBLT_CNTL); \
+ while (minb(XRX+1) & BITBLT_STATUS) \
+ moutb(XRX, BITBLT_CNTL); \
+ }
+
+#define WAIT_BLT_IDLE() { \
+ while (INREG(BITBLT_CONTROL) & BLTR_STATUS); \
+ }
+
+#define WAIT_LP_FIFO(n) { \
+ while (INREG8(LP_FIFO_COUNT) > 15-(n)); \
+ }
+
+#define WAIT_HP_FIFO(n) { \
+ while (INREG8(HP_FIFO_COUNT) > 15-(n)); \
+ }
diff --git a/src/i740_reg.h b/src/i740_reg.h
new file mode 100644
index 0000000..0366d7e
--- /dev/null
+++ b/src/i740_reg.h
@@ -0,0 +1,327 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_reg.h,v 1.2 2000/02/23 04:47:14 martin Exp $ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ */
+
+/* I/O register offsets */
+#define SRX 0x3C4
+#define GRX 0x3CE
+#define ARX 0x3C0
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6
+#define DACSTATE 0x3C7
+#define DACRX 0x3C7
+#define DACWX 0x3C8
+#define DACDATA 0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C
+#define START_ADDR_LO 0x0D
+#define VERT_SYNC_END 0x11
+#define EXT_VERT_TOTAL 0x30
+#define EXT_VERT_DISPLAY 0x31
+#define EXT_VERT_SYNC_START 0x32
+#define EXT_VERT_BLANK_START 0x33
+#define EXT_HORIZ_TOTAL 0x35
+#define EXT_HORIZ_BLANK 0x39
+#define EXT_START_ADDR 0x40
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41
+#define EXT_START_ADDR_HI 0x42
+#define INTERLACE_CNTL 0x70
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R 0x3CC
+#define MSR_W 0x3C2
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0
+#define CGA_BASE 0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL 0x09
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+#define ADDRESS_MAPPING 0x0A
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define BITBLT_CNTL 0x20
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define CHIP_RESET 0x02
+#define BITBLT_STATUS 0x01
+
+#define DISPLAY_CNTL 0x40
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+#define DRAM_ROW_TYPE 0x50
+#define DRAM_ROW_0 0x07
+#define DRAM_ROW_0_SDRAM 0x00
+#define DRAM_ROW_0_EMPTY 0x07
+#define DRAM_ROW_1 0x38
+#define DRAM_ROW_1_SDRAM 0x00
+#define DRAM_ROW_1_EMPTY 0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY 0x10
+#define DRAM_RAS_TIMING 0x08
+#define DRAM_RAS_PRECHARGE 0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL 0x53
+#define DRAM_REFRESH_RATE 0x03
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x01
+#define DRAM_REFRESH_FAST_TEST 0x02
+#define DRAM_REFRESH_RESERVED 0x03
+#define DRAM_TIMING 0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+#define CURSOR_CONTROL 0xA0
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_128_2C 0x02
+#define CURSOR_MODE_128_1C 0x03
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO 0xA4
+#define CURSOR_X_HI 0xA5
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0xA6
+#define CURSOR_Y_HI 0xA7
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define VCLK2_VCO_M 0xC8
+#define VCLK2_VCO_N 0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS 0x30
+#define VCO_M_MSBS 0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+#define REF_CLK_DIV_BY_5 0x02
+#define REF_DIV_4 0x00
+#define REF_DIV_1 0x01
+
+#define PLL_CNTL 0xCE
+#define PLL_MEMCLK_SEL 0x03
+#define PLL_MEMCLK__66667KHZ 0x00
+#define PLL_MEMCLK__75000KHZ 0x01
+#define PLL_MEMCLK__88889KHZ 0x02
+#define PLL_MEMCLK_100000KHZ 0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1 0x02
+#define ACQ_CNTL_2 0x03
+#define FRAME_CAP_MODE 0x01
+#define CONT_CAP_MODE 0x00
+#define SINGLE_CAP_MODE 0x01
+#define ACQ_CNTL_3 0x04
+#define COL_KEY_CNTL_1 0x3C
+#define BLANK_DISP_OVERLAY 0x20
+
+/* FIFOs */
+#define LP_FIFO 0x1000
+#define HP_FIFO 0x2000
+#define INSTPNT 0x3040
+#define LP_FIFO_COUNT 0x3040
+#define HP_FIFO_COUNT 0x3041
+
+/* FIFO Commands */
+#define CLIENT 0xE0000000
+#define CLIENT_2D 0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS 0x3038
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+/* Interrupt Control Registers */
+#define IER 0x3030
+#define IIR 0x3032
+#define IMR 0x3034
+#define ISR 0x3036
+#define VMIINTB_EVENT 0x2000
+#define GPIO4_INT 0x1000
+#define DISP_FLIP_EVENT 0x0800
+#define DVD_PORT_DMA 0x0400
+#define DISP_VBLANK 0x0200
+#define FIFO_EMPTY_DMA_DONE 0x0100
+#define INST_PARSER_ERROR 0x0080
+#define USER_DEFINED 0x0040
+#define BREAKPOINT 0x0020
+#define DISP_HORIZ_COUNT 0x0010
+#define DISP_VSYNC 0x0008
+#define CAPTURE_HORIZ_COUNT 0x0004
+#define CAPTURE_VSYNC 0x0002
+#define THREE_D_PIPE_FLUSHED 0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC 0x00006000
+#define LMI_BURST_LENGTH 0x7F000000
+#define LMI_FIFO_WATERMARK 0x003F0000
+#define AGP_BURST_LENGTH 0x00007F00
+#define AGP_FIFO_WATERMARK 0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH 0x00040000
+#define DST_PITCH 0x1FFF0000
+#define SRC_PITCH 0x00001FFF
+#define COLEXP_BG_COLOR 0x00040004
+#define COLEXP_FG_COLOR 0x00040008
+#define MONO_SRC_CNTL 0x0004000C
+#define MONO_USE_COLEXP 0x00000000
+#define MONO_USE_SRCEXP 0x08000000
+#define MONO_DATA_ALIGN 0x07000000
+#define MONO_BIT_ALIGN 0x01000000
+#define MONO_BYTE_ALIGN 0x02000000
+#define MONO_WORD_ALIGN 0x03000000
+#define MONO_DWORD_ALIGN 0x04000000
+#define MONO_QWORD_ALIGN 0x05000000
+#define MONO_SRC_INIT_DSCRD 0x003F0000
+#define MONO_SRC_RIGHT_CLIP 0x00003F00
+#define MONO_SRC_LEFT_CLIP 0x0000003F
+#define BITBLT_CONTROL 0x00040010
+#define BLTR_STATUS 0x80000000
+#define DYN_DEPTH 0x03000000
+#define DYN_DEPTH_8BPP 0x00000000
+#define DYN_DEPTH_16BPP 0x01000000
+#define DYN_DEPTH_24BPP 0x02000000
+#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */
+#define DYN_DEPTH_ENABLE 0x00800000
+#define PAT_VERT_ALIGN 0x00700000
+#define SOLID_PAT_SELECT 0x00080000
+#define PAT_IS_IN_COLOR 0x00000000
+#define PAT_IS_MONO 0x00040000
+#define MONO_PAT_TRANSP 0x00020000
+#define COLOR_TRANSP_ROP 0x00000000
+#define COLOR_TRANSP_DST 0x00008000
+#define COLOR_TRANSP_EQ 0x00000000
+#define COLOR_TRANSP_NOT_EQ 0x00010000
+#define COLOR_TRANSP_ENABLE 0x00004000
+#define MONO_SRC_TRANSP 0x00002000
+#define SRC_IS_IN_COLOR 0x00000000
+#define SRC_IS_MONO 0x00001000
+#define SRC_USE_SRC_ADDR 0x00000000
+#define SRC_USE_BLTDATA 0x00000400
+#define BLT_TOP_TO_BOT 0x00000000
+#define BLT_BOT_TO_TOP 0x00000200
+#define BLT_LEFT_TO_RIGHT 0x00000000
+#define BLT_RIGHT_TO_LEFT 0x00000100
+#define BLT_ROP 0x000000FF
+#define BLT_PAT_ADDR 0x00040014
+#define BLT_SRC_ADDR 0x00040018
+#define BLT_DST_ADDR 0x0004001C
+#define BLT_DST_H_W 0x00040020
+#define BLT_DST_HEIGHT 0x1FFF0000
+#define BLT_DST_WIDTH 0x00001FFF
+#define SRCEXP_BG_COLOR 0x00040024
+#define SRCEXP_FG_COLOR 0x00040028
+#define BLTDATA 0x00050000
+
+typedef struct {
+ unsigned int cmd;
+ unsigned int BR00;
+ unsigned int BR01;
+ unsigned int BR02;
+ unsigned int BR03;
+ unsigned int BR04;
+ unsigned int BR05;
+ unsigned int BR06;
+ unsigned int BR07;
+ unsigned int BR09;
+ unsigned int BR0A;
+ unsigned int BR08;
+} GFX2DOPREG_BLTER_FULL_LOAD;
diff --git a/src/i740_video.c b/src/i740_video.c
new file mode 100644
index 0000000..7ce7dfb
--- /dev/null
+++ b/src/i740_video.c
@@ -0,0 +1,1323 @@
+/*
+ * Copyright 2001 by Patrick LERDA
+ * Portions Copyright by Stephen Blackheath
+ *
+ * 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 Patrick LERDA not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Patrick LERDA makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PATRICK LERDA 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: Patrick LERDA
+ * with modifications by Stephen Blackheath (Aug 2002)
+ *
+ * REVISION HISTORY:
+ * December 2001 - Patrick LERDA's original (http://sourceforge.net/projects/i740fb).
+ * 27 August 2002 - Patrick's version would run for an hour or two on my machine,
+ * then the screen would go blank (no signal to monitor) and for some reason I
+ * sometimes couldn't even log in through the network. I had to re-boot my machine.
+ * This version fixes that and makes a few other unnecessary tweaks. I am not
+ * certain, but I think the problem is that Patrick's code was reading a value from
+ * XRX register 0xD0, and or'ing with 0x10. When I removed this from the main
+ * loop, it became reliable. I suspect the hardware (whether just my cheap
+ * clone board only I'm not sure) was sometimes returning bogus values, which were
+ * then programmed back in - but I never checked this. This register is related to
+ * powering on or off certain subsystems of the i740 chip, so that might explain
+ * the blank screen. - Stephen Blackheath
+ * 3 September 2002 - Added software scaling in the situation where the screen size is
+ * smaller than the original video size, since scaling down is not supported by
+ * the hardware. The implementation of this is not quite complete.
+ * 12 September 2002 - Better software scaling with some averaging, giving a nicer
+ * picture.
+ * 13 January 2003 - Fixed a minor bug where the video would occasionally stop updating,
+ * which was worked around just by re-sizing the window.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_video.c,v 1.3 2003/01/17 22:22:52 tsi Exp $ */
+
+/*
+ * i740_video.c: i740 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
+ */
+
+#ifdef XvExtension
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "xf86xv.h"
+#include "Xv.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#include "vgaHW.h"
+#include "i740.h"
+
+
+#define FOURCC_RV15 0x35315652
+#define FOURCC_RV16 0x36315652
+
+/*-*/
+#define i740_wc(fb,z,r,v) (pI740->writeControl(pI740,(z),(r),(v)))
+#define i740_rc(fb,z,r) (pI740->readControl(pI740,(z),(r)))
+/*-*/
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+
+
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvColorKey;
+
+
+
+#define IMAGE_MAX_PHY_WIDTH 1024 /*720*/
+#define IMAGE_MAX_PHY_HEIGHT 1024 /*576*/
+
+
+#define IMAGE_MAX_LOG_WIDTH 1024 /*720*/
+#define IMAGE_MAX_LOG_HEIGHT 1024 /*576*/
+
+
+typedef struct {
+ CARD32 YBuf0offset;
+ CARD32 YBuf1offset;
+
+ unsigned char currentBuf;
+
+ int brightness;
+ int contrast;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ FBLinearPtr linear;
+
+} I740PortPrivRec, *I740PortPrivPtr;
+
+typedef struct {
+ CARD32 OBUF_0Y;
+ CARD32 OBUF_1Y;
+ CARD32 OBUF_0U;
+ CARD32 OBUF_0V;
+ CARD32 OBUF_1U;
+ CARD32 OBUF_1V;
+ CARD32 OV0STRIDE;
+ CARD32 YRGB_VPH;
+ CARD32 UV_VPH;
+ CARD32 HORZ_PH;
+ CARD32 INIT_PH;
+ CARD32 DWINPOS;
+ CARD32 DWINSZ;
+ CARD32 SWID;
+ CARD32 SWIDQW;
+ CARD32 SHEIGHT;
+ CARD32 YRGBSCALE;
+ CARD32 UVSCALE;
+ CARD32 OV0CLRC0;
+ CARD32 OV0CLRC1;
+ CARD32 DCLRKV;
+ CARD32 DCLRKM;
+ CARD32 SCLRKVH;
+ CARD32 SCLRKVL;
+ CARD32 SCLRKM;
+ CARD32 OV0CONF;
+ CARD32 OV0CMD;
+} I740OverlayRegRec, *I740OverlayRegPtr;
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (I740PortPrivPtr)((I740PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+
+
+/*-----------------------------------------------------------------------------------------*/
+__inline__ static void i740fb_overlay_off(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ /* 0x3C = COL_KEY_CNTL_1 */
+ i740_wc(fb_p, MRX, 0x3C, (i740_rc(fb_p, MRX, 0x3C) | 0x02));
+ usleep(50000);
+ /*i740_wc(fb_p, XRX, 0xD0, (i740_rc(fb_p, XRX, 0xD0) & ~0x10));
+ usleep(50000);*/
+ i740_wc(fb_p, XRX, 0xD0, 0x2F);
+}
+
+__inline__ static void i740fb_overlay_set(ScrnInfoPtr pScrn, I740PortPrivPtr pPriv, unsigned long mem1,unsigned long mem2,
+ unsigned long isrc_w,unsigned long isrc_h, /* source image size */
+ unsigned long idst_w,unsigned long idst_h, /* destination image size */
+ unsigned long ddst_x,unsigned long ddst_y, /* destination image pos to display */
+ unsigned long ddst_w,unsigned long ddst_h, /* destination image size to display allows trunc... */
+ unsigned long pitch,int flip,
+ unsigned char vd_mod)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ const int f_dbl=pScrn->currentMode->Flags & V_DBLSCAN;
+
+ if(f_dbl) { idst_h*=2; ddst_y*=2; ddst_h*=2; }
+
+ ddst_x+=pI740->ov_offset_x;
+ ddst_y+=pI740->ov_offset_y;
+
+ /* Program the i740 overlay to use the new image dimensions. */
+
+ i740_wc(fb_p, MRX, 0x24, mem1>>16);
+ i740_wc(fb_p, MRX, 0x23, mem1>> 8);
+ i740_wc(fb_p, MRX, 0x22, mem1>> 0);
+
+ i740_wc(fb_p, MRX, 0x27, mem2>>16);
+ i740_wc(fb_p, MRX, 0x26, mem2>> 8);
+ i740_wc(fb_p, MRX, 0x25, mem2>> 0);
+
+ i740_wc(fb_p, MRX, 0x28, (( pitch >>3)-1) );
+
+ { unsigned short v=ddst_x; i740_wc(fb_p, MRX, 0x2B, v>> 8); i740_wc(fb_p, MRX, 0x2A, v>> 0); }
+ { unsigned short v=ddst_x+ddst_w-1; i740_wc(fb_p, MRX, 0x2D, v>> 8); i740_wc(fb_p, MRX, 0x2C, v>> 0); }
+ { unsigned short v=ddst_y; i740_wc(fb_p, MRX, 0x2F, v>> 8); i740_wc(fb_p, MRX, 0x2E, v>> 0); }
+ { unsigned short v=ddst_y+ddst_h-1; i740_wc(fb_p, MRX, 0x31, v>> 8); i740_wc(fb_p, MRX, 0x30, v>> 0); }
+
+ i740_wc(fb_p, MRX, 0x32, (isrc_w<<8)/(idst_w));
+ i740_wc(fb_p, MRX, 0x33, (isrc_h<<8)/(idst_h));
+
+ i740_wc(fb_p, MRX, 0x50, 0);
+ i740_wc(fb_p, MRX, 0x51, 0);
+
+ i740_wc(fb_p, MRX, 0x1E, ( idst_w > isrc_w ? 0x04 : 0x00 ) | ( idst_h > isrc_h ? 0x08 : 0x00 ));
+ i740_wc(fb_p, MRX, 0x1F, ( idst_w > isrc_w ? 0x20 : 0x00 ) | ( (idst_h > isrc_h) && (pitch <= 720*2) ? 0xC0 : 0x00 ) | (vd_mod & 0x1F));
+
+ /*i740_wc(fb_p, MRX, 0x20, 0);*/
+
+ i740_wc(fb_p, MRX, 0x19, 0x00);
+
+ /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
+ i740_wc(fb_p, XRX, 0xD0, 0x3F);
+ /* 0x3C = COL_KEY_CNTL_1 */
+ i740_wc(fb_p, MRX, 0x3C, 0x05 | 0x02);
+
+ /*i740_wc(fb_p, MRX, 0x20, (flip ? 0x14 : 0x04));*/
+ /*i740_wc(fb_p, MRX, 0x20, 0);*/
+ /*i740_wc(fb_p, XRX, 0xD0, i740_rc(fb_p, XRX, 0xD0) | 0x10 );*/
+ /*i740_wc(fb_p, MRX, 0x19, 0x00);*/
+ i740_wc(fb_p, MRX, 0x20, (flip ? 0x34 : 0x24)); /*SB*/
+}
+
+__inline__ static void i740fb_colorkey(ScrnInfoPtr pScrn,unsigned long key)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ unsigned char r,g,b,rm,gm,bm;
+
+ /*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"colorkey=%04x depth=%d\n",key,pScrn->depth);*/
+
+ switch(pScrn->depth)
+ {
+ case 4: r=0x00; g=0x00; b=key; rm=0xFF; gm=0xFF; bm=0xF0; break;
+ case 8: r=0x00; g=0x00; b=key; rm=0xFF; gm=0xFF; bm=0x00; break;
+ case 15: r=(key&0x7C00)>>7; g=(key&0x03E0)>>2; b=(key&0x001F)<<3; rm=0x07; gm=0x07; bm=0x07; break;
+ case 16: r=(key&0xF800)>>8; g=(key&0x07E0)>>3; b=(key&0x001F)<<3; rm=0x07; gm=0x03; bm=0x07; break;
+ default: /*24*/ r=(key&0xFF00)>>8; g=(key&0xFF00)>>3; b=(key&0xFF00)<<3; rm=0x00; gm=0x00; bm=0x00; break;
+ }
+
+ i740_wc(fb_p, MRX, 0x3D, r);
+ i740_wc(fb_p, MRX, 0x3E, g);
+ i740_wc(fb_p, MRX, 0x3F, b);
+
+ i740_wc(fb_p, MRX, 0x40, rm);
+ i740_wc(fb_p, MRX, 0x41, gm);
+ i740_wc(fb_p, MRX, 0x42, bm);
+}
+
+/*-----------------------------------------------------------------------------------------*/
+
+
+
+static void I740ResetVideo(ScrnInfoPtr pScrn)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740ResetVideo entered\n"); /* ### */
+
+ /*
+ * Enable destination color keying
+ */
+
+ i740fb_colorkey(pScrn,pPriv->colorKey);
+}
+
+
+
+
+static Bool RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* I740ClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (x1, y1
+ inclusive, x2, y2 exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+static void I740ClipVideo(
+ BoxPtr dst,
+ INT32 *x1,
+ INT32 *x2,
+ INT32 *y1,
+ INT32 *y2,
+ BoxPtr extents, /* extents of the clip region */
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ int diff;
+
+ hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
+
+ *x1 <<= 16; *x2 <<= 16;
+ *y1 <<= 16; *y2 <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *x1 += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *x2 -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *y1 += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *y2 -= diff * vscale;
+ }
+
+ if(*x1 < 0) {
+ diff = (- *x1 + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *x1 += diff * hscale;
+ }
+ delta = *x2 - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *x2 -= diff * hscale;
+ }
+ if(*y1 < 0) {
+ diff = (- *y1 + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *y1 += diff * vscale;
+ }
+ delta = *y2 - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *y2 -= diff * vscale;
+ }
+}
+
+static void I740StopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+ I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740StopVideo entered %p %d\n", (void*)data, (int)exit);*/ /* ### */
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(exit)
+ {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON)
+ i740fb_overlay_off(pScrn);
+
+ if(pPriv->linear)
+ {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ else
+ {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON)
+ {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+
+}
+
+static int I740SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data)
+{
+ I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740OverlayRegPtr overlay = (I740OverlayRegPtr) (pI740->FbBase + pI740->OverlayStart);
+
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetPortAttribute entered %d\n", (int) value);*/ /* ### */
+
+ if(attribute == xvBrightness)
+ {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
+ /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
+ }
+ else
+ if(attribute == xvContrast)
+ {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
+ /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
+ }
+ else
+ if(attribute == xvColorKey)
+ {
+ pPriv->colorKey = value;
+
+ i740fb_colorkey(pScrn,pPriv->colorKey);
+
+ /*//OVERLAY_UPDATE(pI740->OverlayPhysical);*/
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ }
+ else
+ return BadMatch;
+
+ return Success;
+}
+
+static int I740GetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvContrast) {
+ *value = pPriv->contrast;
+ } else
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else return BadMatch;
+
+ return Success;
+}
+
+static void I740QueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
+ if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h); /* ### */
+ fprintf(stderr, "fprintf - I740QueryBestSize entered %d %d %d %d\n", (int) vid_w, (int) vid_h, (int) drw_w, (int) drw_h); /* ### */
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+static void I740CopyMungedData(ScrnInfoPtr pScrn,
+ unsigned char *src1, unsigned char *src2, unsigned char *src3,
+ int srcPitch,
+ int srcPitch2,
+ int dstPitch,
+ int h,
+ int w,
+ long scalex,
+ long scaley)
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
+ CARD32 *dst;
+ int i, j;
+
+ if (pPriv->currentBuf == 0)
+ dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf0offset);
+ else
+ dst = (CARD32 *)(pI740->FbBase + pPriv->YBuf1offset);
+
+ dstPitch >>= 2;
+ w >>= 1;
+
+ /* If the space on the screen is smaller than the source image, then we use
+ * software scaling to make it smaller. */
+ if (scalex > 0x10000 || scaley > 0x10000) {
+ int dsth = ((long) h * 0x10000L + scaley - 1) / scaley;
+ long halfx = scalex/2;
+ long dstj = 0;
+ for(j = 0; j < dsth; j++) {
+ int dstj_rnd = dstj >> 16;
+ unsigned char* src1_ = src1 + (dstj_rnd * srcPitch);
+ unsigned char* src2_ = src2 + ((dstj_rnd/2) * srcPitch2);
+ unsigned char* src3_ = src3 + ((dstj_rnd/2) * srcPitch2);
+ int dstw = ((long) w * 0x10000L + halfx - 1) / scalex;
+ long srci = 0;
+ for(i = 0; i < dstw; i++) {
+ long srci_rnd = srci >> 16;
+ long srci2_rnd = (srci + halfx) >> 16;
+ dst[i] =
+ (((src1_[srci_rnd << 1] | (src1_[(srci_rnd << 1) + 1] << 16) |
+ (src3_[srci_rnd] << 8) | (src2_[srci_rnd] << 24))) >> 1 & 0x7F7F7F7FL)
+ +
+ (((src1_[srci2_rnd << 1] | (src1_[(srci2_rnd << 1) + 1] << 16) |
+ (src3_[srci2_rnd] << 8) | (src2_[srci2_rnd] << 24))) >> 1 & 0x7F7F7F7FL);
+ srci += scalex;
+ }
+ dst += dstPitch;
+ dstj += scaley;
+ }
+ }
+ else {
+ for(j = 0; j < h; j++) {
+ for(i = 0; i < w; i++) {
+ dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
+ (src3[i] << 8) | (src2[i] << 24);
+ }
+ dst += dstPitch;
+ src1 += srcPitch;
+ if(j & 1) {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
+ }
+}
+
+
+__inline__ static void I740CopyPackedData(ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch,
+ int top,
+ int left,
+ int h,
+ int w
+ )
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
+ unsigned char *src, *dst;
+
+ src = buf + (top*srcPitch) + (left<<1);
+
+ if (pPriv->currentBuf == 0)
+ dst = pI740->FbBase + pPriv->YBuf0offset;
+ else
+ dst = pI740->FbBase + pPriv->YBuf1offset;
+
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+
+__inline__ static void I740DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
+ int dstPitch, /* of chroma for 4:2:0 */
+ int x1, int y1, int x2, int y2,
+ BoxPtr dstBox,
+ short src_w, short src_h, short drw_w, short drw_h,
+ unsigned char vd_mod
+ )
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = pI740->adaptor->pPortPrivates[0].ptr;
+
+ i740fb_overlay_set(pScrn,pPriv,pPriv->YBuf0offset,pPriv->YBuf1offset,
+ src_w,src_h, /* source image size */
+ drw_w,drw_h, /* destination image size */
+ dstBox->x1,dstBox->y1, /* destination image pos to display */
+ dstBox->x2 - dstBox->x1,dstBox->y2 - dstBox->y1, /* destination image size to display allows trunc... */
+ dstPitch,(pPriv->currentBuf != 0),
+ vd_mod);
+
+ i740fb_colorkey(pScrn,pPriv->colorKey); /* needed to reset properly the i740 board after switching from framebuffer */
+}
+
+static FBLinearPtr I740AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+{
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear)
+ {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory resized to %d - %p\n", (int) size, linear); /* ### */
+ return linear;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory free %p - %d < %d\n", linear, (int) linear->size, (int) size); /* ### */
+ xf86FreeOffscreenLinear(linear);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
+
+ if(!new_linear)
+ {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
+
+ if(max_size < size) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory can't purge %d < %d\n", (int) max_size, (int) size); /* ### */
+ return NULL;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory purged %d\n", (int) max_size); /* ### */
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
+ NULL, NULL, NULL);
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateMemory allocated %d - %p\n", (int) size, new_linear); /* ### */
+
+ return new_linear;
+}
+
+static int I740PutImage(ScrnInfoPtr pScrn,
+ short src_x, short src_y, short drw_x, short drw_y,
+ short src_w, short src_h, short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool sync, RegionPtr clipBoxes, pointer data
+ )
+{
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = (I740PortPrivPtr)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch, srcPitch2=0;
+ int top, left, npixels, nlines, size;
+ BoxRec dstBox;
+ int offset2=0, offset3=0;
+
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740PutImage entered %d %d\n", (int) width, (int) height, id);*/ /* ### */
+
+ /* Clip */
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2)) {
+ return Success;
+ }
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ switch(id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ offset2 = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ offset3 = (srcPitch2 * (height >> 1)) + offset2;
+ dstPitch = ((width << 1) + 15) & ~15;
+ size = dstPitch * height;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 7) & ~7;
+ size = dstPitch * height;
+ break;
+ }
+
+ {
+ FBLinearPtr new_linear = I740AllocateMemory(pScrn, pPriv->linear, size);
+ if (new_linear != pPriv->linear) {
+ pPriv->linear = new_linear;
+ }
+ }
+ if(!pPriv->linear)
+ return BadAlloc;
+
+ /* fixup pointers */
+ pPriv->YBuf0offset = pPriv->linear->offset*pI740->cpp;
+ pPriv->YBuf1offset = (pPriv->linear->offset*pI740->cpp) + size;
+
+
+#if 0 /*???*/
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pPriv->currentBuf);
+#endif
+
+ /* buffer swap */
+ pPriv->currentBuf ^= 1;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ {
+ CARD32 tmp;
+
+ top &= ~1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ offset2 += tmp;
+ offset3 += tmp;
+
+ if(id == FOURCC_I420)
+ {
+ tmp = offset2;
+ offset2 = offset3;
+ offset3 = tmp;
+ }
+
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+
+ /* If the screen image size is smaller than the video image size, then
+ * we use software scaling to make it smaller. The hardware takes care
+ * of scaling up - see i740fb_overlay_set.
+ */
+ {
+ long scalex = 0x10000, scaley = 0x10000;
+ if (drw_w < src_w)
+ scalex = (0x10000L * (long) src_w) / (long) drw_w;
+ if (drw_h < src_h)
+ scaley = (0x10000L * (long) src_h) / (long) drw_h;
+
+ I740CopyMungedData(pScrn, buf + (top * srcPitch) + left,
+ buf + offset2, buf + offset3,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels, scalex, scaley);
+ }
+ }
+ break;
+
+ case FOURCC_UYVY: case FOURCC_YUY2: default:
+ {
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ /* Add software scaling as above. */
+ I740CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ }
+ break;
+ }
+
+ /* update cliplist */
+ if(!RegionsEqual(&pPriv->clip, clipBoxes))
+ {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
+ }
+
+ {
+ unsigned char vd_mod;
+
+ switch(id)
+ {
+ case FOURCC_RV15: vd_mod=0x09; break;
+ case FOURCC_RV16: vd_mod=0x08; break;
+ default: vd_mod=0x00; break;
+ }
+
+ I740DisplayVideo(pScrn, id, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h,
+ vd_mod);
+ }
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ return Success;
+}
+
+
+static int I740QueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets )
+{
+ int size,tmp;
+
+ if(*w > IMAGE_MAX_PHY_WIDTH) *w = IMAGE_MAX_PHY_WIDTH;
+ if(*h > IMAGE_MAX_PHY_HEIGHT) *h = IMAGE_MAX_PHY_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static void I740BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ I740Ptr pI740 = I740PTR(pScrn);
+ I740PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler entered\n"); */ /* ### */
+
+ pScreen->BlockHandler = pI740->BlockHandler;
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ pScreen->BlockHandler = I740BlockHandler;
+
+ if(pPriv->videoStatus & TIMER_MASK)
+ {
+ UpdateCurrentTime();
+ if(pPriv->videoStatus & OFF_TIMER)
+ {
+ if(pPriv->offTime < currentTime.milliseconds)
+ {
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: OFF_TIMER expired\n");*/ /* ### */
+ /* Turn off the overlay */
+ i740fb_overlay_off(pScrn);
+
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ }
+ else
+ { /* FREE_TIMER */
+ if(pPriv->freeTime < currentTime.milliseconds)
+ {
+ if(pPriv->linear)
+ {
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740BlockHandler: FREE_TIMER expired\n");*/ /* ### */
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ * Offscreen Images
+ ***************************************************************************/
+
+typedef struct {
+ FBLinearPtr linear;
+ Bool isOn;
+} OffscreenPrivRec, * OffscreenPrivPtr;
+
+static int I740AllocateSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h,
+ XF86SurfacePtr surface
+){
+ FBLinearPtr linear;
+ int pitch, size;
+ OffscreenPrivPtr pPriv;
+ I740Ptr pI740 = I740PTR(pScrn);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740AllocateSurface entered %d %d\n", (int) w, (int) h); /* ### */
+
+ if((w > IMAGE_MAX_LOG_WIDTH) || (h > IMAGE_MAX_LOG_HEIGHT))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ size = pitch * h;
+
+ if(!(linear = I740AllocateMemory(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if(!(surface->pitches = xalloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+
+ pPriv->linear = linear;
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = linear->offset*pI740->cpp;
+ surface->devPrivate.ptr = (pointer)pPriv;
+
+ /*//memset(pI740->FbBase + surface->offsets[0],0,size);*/
+
+ return Success;
+}
+
+static int I740StopSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn)
+ {
+ /*//i740fb_overlay_off(pScrn);*/
+
+ pPriv->isOn = FALSE;
+ }
+
+ return Success;
+}
+
+
+static int I740FreeSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn)
+ {
+ I740StopSurface(surface);
+ }
+
+ xf86FreeOffscreenLinear(pPriv->linear);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int I740GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value)
+{
+ return I740GetPortAttribute(pScrn, attribute, value, 0);
+}
+
+static int I740SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
+{
+ return I740SetPortAttribute(pScrn, attribute, value, 0);
+}
+
+
+static int I740DisplaySurface(XF86SurfacePtr surface, short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ RegionPtr clipBoxes)
+{
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+ ScrnInfoPtr pScrn = surface->pScrn;
+ I740PortPrivPtr pI740Priv = GET_PORT_PRIVATE(pScrn);
+
+ INT32 x1, y1, x2, y2;
+ BoxRec dstBox;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740DisplaySurface entered\n"); /* ### */
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"I740DisplaySurface-----------------------------------\n");*/
+ /*//fprintf(stderr, "I740DisplaySurface-----------------------------------\n");*/
+
+
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ I740ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
+ surface->width, surface->height);
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ /* fixup pointers */
+ pI740Priv->YBuf0offset = surface->offsets[0];
+ pI740Priv->YBuf1offset = pI740Priv->YBuf0offset;
+
+#if 0 /*???*/
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pI740Priv->currentBuf) {
+ if(loops == 200000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
+ break;
+ }
+ loops++;
+ }
+#endif
+
+ /* buffer swap */
+ if (pI740Priv->currentBuf == 0)
+ pI740Priv->currentBuf = 1;
+ else
+ pI740Priv->currentBuf = 0;
+
+ I740ResetVideo(pScrn);
+
+ I740DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+ surface->pitches[0], x1, y1, x2, y2, &dstBox,
+ src_w, src_h, drw_w, drw_h,
+ 0x00);
+
+ XAAFillSolidRects(pScrn, pI740Priv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if(pI740Priv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, & pI740Priv->clip);
+ UpdateCurrentTime();
+ pI740Priv->videoStatus = FREE_TIMER;
+ pI740Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ pScrn->pScreen->BlockHandler = I740BlockHandler;
+ }
+
+ return Success;
+}
+
+/*-------------------------------------------------------------------------------------------*/
+#define NUM_IMAGES (sizeof(i740vid_Images)/sizeof(XF86ImageRec))
+static XF86ImageRec i740vid_Images[] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_UYVY,
+ XVIMAGE_YV12, /* converted to YUV2 while copying */
+ XVIMAGE_I420, /* converted to YUV2 while copying */
+ {
+ FOURCC_RV15,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','5',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 15, 0x001F, 0x03E0, 0x7C00,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ FOURCC_RV16,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','6',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 16, 0x001F, 0x07E0, 0xF800,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+};
+
+#define NUM_ATTRIBUTES (sizeof(i740vid_Attributes)/sizeof(XF86AttributeRec))
+
+static XF86AttributeRec i740vid_Attributes[] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+
+static void I740InitOffscreenImages(ScreenPtr pScreen)
+{
+ XF86OffscreenImagePtr offscreenImages;
+ {
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitOffscreenImages entered\n"); /* ### */
+ }
+
+ /* need to free this someplace */
+ if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
+ {
+ return;
+ }
+
+ offscreenImages[0].image = &i740vid_Images[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = I740AllocateSurface;
+ offscreenImages[0].free_surface = I740FreeSurface;
+ offscreenImages[0].display = I740DisplaySurface;
+ offscreenImages[0].stop = I740StopSurface;
+ offscreenImages[0].setAttribute = I740SetSurfaceAttribute;
+ offscreenImages[0].getAttribute = I740GetSurfaceAttribute;
+ offscreenImages[0].max_width = IMAGE_MAX_LOG_WIDTH;
+ offscreenImages[0].max_height = IMAGE_MAX_LOG_HEIGHT;
+ offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
+ offscreenImages[0].attributes = i740vid_Attributes;
+
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
+
+
+
+static XF86VideoAdaptorPtr I740SetupImageVideo(ScreenPtr pScreen)
+{
+ /* client libraries expect an encoding */
+ static XF86VideoEncodingRec DummyEncoding[1] =
+ {
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_PHY_WIDTH, IMAGE_MAX_PHY_HEIGHT,
+ {1, 1}
+ }
+ };
+
+#define NUM_FORMATS (sizeof(i740vid_Formats)/sizeof(XF86VideoFormatRec))
+ static XF86VideoFormatRec i740vid_Formats[] =
+ {
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {8, PseudoColor}
+ };
+
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I740Ptr pI740 = I740PTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ I740PortPrivPtr pPriv;
+
+ /*xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740SetupImageVideo entered\n");*/ /* ### */
+ {
+ const int n=sizeof(XF86VideoAdaptorRec)+sizeof(I740PortPrivRec)+sizeof(DevUnion);
+
+ if(!(adapt = xcalloc(1, n)))
+ return NULL;
+
+ /*//memset(adapt,0,n);*/
+ }
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "I740 Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = i740vid_Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ pPriv = (I740PortPrivPtr)((unsigned char *)(&adapt[1])+sizeof(sizeof(DevUnion)));
+
+ adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
+ adapt->pAttributes = i740vid_Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pImages = i740vid_Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = I740StopVideo;
+ adapt->SetPortAttribute = I740SetPortAttribute;
+ adapt->GetPortAttribute = I740GetPortAttribute;
+ adapt->QueryBestSize = I740QueryBestSize;
+ adapt->PutImage = I740PutImage;
+ adapt->QueryImageAttributes = I740QueryImageAttributes;
+
+ pPriv->colorKey = pI740->colorKey & ((1 << pScrn->depth) - 1);
+ pPriv->videoStatus = 0;
+ pPriv->brightness = 0;
+ pPriv->contrast = 64;
+ pPriv->linear = NULL;
+ pPriv->currentBuf = 0;
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+
+ pI740->adaptor = adapt;
+
+ pI740->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = I740BlockHandler;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ I740ResetVideo(pScrn);
+
+ return adapt;
+}
+
+void I740InitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "I740InitVideo entered\n"); /* ### */
+
+#if 0 /*disable!*/
+ {
+ XF86VideoAdaptorPtr *ptr;
+ int n;
+
+ n = xf86XVListGenericAdaptors(pScrn,&ptr);
+ if (n) {
+ xf86XVScreenInit(pScreen, ptr, n);
+ }
+
+ return;
+ }
+#endif
+
+ {
+ newAdaptor = I740SetupImageVideo(pScreen);
+ I740InitOffscreenImages(pScreen);
+ }
+
+ {
+ XF86VideoAdaptorPtr *adaptors_oldptrs, *adaptors_newptrs = NULL;
+ int num_adaptors;
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors_oldptrs);
+
+ if(newAdaptor)
+ {
+ if(!num_adaptors)
+ {
+ xf86XVScreenInit(pScreen, &newAdaptor, 1);
+ }
+ else
+ {
+ if((adaptors_newptrs = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr))))
+ {
+ memcpy(adaptors_newptrs, adaptors_oldptrs, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+ adaptors_newptrs[num_adaptors] = newAdaptor;
+
+ /*//xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"num--- %d [%d] %08x %08x\n",num_adaptors,num_adaptors * sizeof(XF86VideoAdaptorPtr),*/
+ /*// adaptors_newptrs[0],adaptors_newptrs[1]);*/
+
+
+ xf86XVScreenInit(pScreen, adaptors_newptrs, num_adaptors+1);
+ xfree(adaptors_newptrs);
+ }
+ }
+ }
+
+ }
+}
+#endif /*XvExtension*/