summaryrefslogtreecommitdiff
path: root/src/legacy/i810
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-06-20 12:52:10 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-06-25 13:18:01 +0100
commit797d173a9af12055ba2609293182b616dd673ef4 (patch)
tree0bc73734fa5e5bb1e57715d448bc7a6da88aba5a /src/legacy/i810
parentcd61531a78b9a2cbdd6019199c43258f83e6e2ce (diff)
i810: Move into a legacy directory.
The driver is still built but is no longer under active development so move it and supporting files to a new directory. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/legacy/i810')
-rw-r--r--src/legacy/i810/Makefile.am33
-rw-r--r--src/legacy/i810/i810.h335
-rw-r--r--src/legacy/i810/i810_accel.c617
-rw-r--r--src/legacy/i810/i810_common.h323
-rw-r--r--src/legacy/i810/i810_cursor.c266
-rw-r--r--src/legacy/i810/i810_dga.c258
-rw-r--r--src/legacy/i810/i810_dri.c1544
-rw-r--r--src/legacy/i810/i810_dri.h131
-rw-r--r--src/legacy/i810/i810_driver.c2121
-rw-r--r--src/legacy/i810/i810_hwmc.c419
-rw-r--r--src/legacy/i810/i810_io.c133
-rw-r--r--src/legacy/i810/i810_memory.c428
-rw-r--r--src/legacy/i810/i810_reg.h3194
-rw-r--r--src/legacy/i810/i810_ring.h90
-rw-r--r--src/legacy/i810/i810_video.c1423
-rw-r--r--src/legacy/i810/i810_wmark.c313
-rw-r--r--src/legacy/i810/xvmc/I810XvMC.c4509
-rw-r--r--src/legacy/i810/xvmc/I810XvMC.h366
-rw-r--r--src/legacy/i810/xvmc/Makefile.am11
19 files changed, 16514 insertions, 0 deletions
diff --git a/src/legacy/i810/Makefile.am b/src/legacy/i810/Makefile.am
new file mode 100644
index 00000000..aab7f512
--- /dev/null
+++ b/src/legacy/i810/Makefile.am
@@ -0,0 +1,33 @@
+SUBDIRS = xvmc
+
+noinst_LTLIBRARIES = liblegacy-i810.la
+
+AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ @PCIACCESS_CFLAGS@ -I$(top_srcdir)/src
+
+liblegacy_i810_la_SOURCES = \
+ i810_accel.c \
+ i810_common.h \
+ i810_cursor.c \
+ i810_dga.c \
+ i810_driver.c \
+ i810.h \
+ i810_io.c \
+ i810_memory.c \
+ i810_reg.h \
+ i810_ring.h \
+ i810_video.c \
+ i810_wmark.c
+
+if DRI
+liblegacy_i810_la_SOURCES +=\
+ i810_dri.c \
+ i810_dri.h \
+ $(NULL)
+endif
+
+if XVMC
+liblegacy_i810_la_SOURCES += \
+ i810_hwmc.h \
+ i810_hwmc.c \
+ $(NULL)
+endif
diff --git a/src/legacy/i810/i810.h b/src/legacy/i810/i810.h
new file mode 100644
index 00000000..b39cfff3
--- /dev/null
+++ b/src/legacy/i810/i810.h
@@ -0,0 +1,335 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright © 2002 David Dawes
+
+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.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@xfree86.org>
+ *
+ */
+
+#ifndef _I810_H_
+#define _I810_H_
+
+#include <stdint.h>
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "i810_reg.h"
+#include "xaa.h"
+#include "xf86Cursor.h"
+#include "xf86xv.h"
+#include "vbe.h"
+#include "vgaHW.h"
+
+#include "xorg-server.h"
+#include <pciaccess.h>
+
+#ifdef XF86DRI
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "dri.h"
+#include "GL/glxint.h"
+#include "i810_dri.h"
+#endif
+
+#include "i810_common.h"
+#include "i810_ring.h"
+
+#include "intel_driver.h"
+
+/* HWMC Surfaces */
+#define I810_MAX_SURFACES 7
+#define I810_MAX_SUBPICTURES 2
+#define I810_TOTAL_SURFACES 9
+
+/* Globals */
+
+typedef struct _I810Rec *I810Ptr;
+
+typedef void (*I810WriteIndexedByteFunc)(I810Ptr pI810, IOADDRESS addr,
+ uint8_t index, uint8_t value);
+typedef uint8_t(*I810ReadIndexedByteFunc)(I810Ptr pI810, IOADDRESS addr,
+ uint8_t index);
+typedef void (*I810WriteByteFunc)(I810Ptr pI810, IOADDRESS addr,
+ uint8_t value);
+typedef uint8_t(*I810ReadByteFunc)(I810Ptr pI810, IOADDRESS addr);
+
+extern void I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned start,
+ unsigned pitch, unsigned size);
+
+typedef struct {
+ unsigned long Start;
+ unsigned long End;
+ unsigned long Size;
+} I810MemRange;
+
+typedef struct {
+ int tail_mask;
+ I810MemRange mem;
+ unsigned char *virtual_start;
+ int head;
+ int tail;
+ int space;
+} I810RingBuffer;
+
+typedef struct {
+ unsigned char DisplayControl;
+ unsigned char PixelPipeCfg0;
+ unsigned char PixelPipeCfg1;
+ unsigned char PixelPipeCfg2;
+ unsigned short VideoClk2_M;
+ unsigned short VideoClk2_N;
+ unsigned char VideoClk2_DivisorSel;
+ 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;
+
+ unsigned int LprbTail;
+ unsigned int LprbHead;
+ unsigned int LprbStart;
+ unsigned int LprbLen;
+
+ unsigned int Fence[8];
+
+ unsigned short OverlayActiveStart;
+ unsigned short OverlayActiveEnd;
+
+} I810RegRec, *I810RegPtr;
+
+typedef struct _I810Rec {
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+ long FbMapSize;
+ long DepthOffset;
+ long BackOffset;
+ int cpp;
+ int MaxClock;
+
+ unsigned int bufferOffset; /* for I810SelectBuffer */
+ Bool DoneFrontAlloc;
+ BoxRec FbMemBox;
+ I810MemRange FrontBuffer;
+ I810MemRange BackBuffer;
+ I810MemRange DepthBuffer;
+ I810MemRange TexMem;
+ I810MemRange Scratch;
+ I810MemRange BufferMem;
+ I810MemRange ContextMem;
+ I810MemRange MC;
+
+ int auxPitch;
+ int auxPitchBits;
+
+ Bool CursorIsARGB;
+ int CursorOffset;
+ unsigned long CursorPhysical;
+ unsigned long CursorStart;
+ int CursorARGBOffset;
+ unsigned long CursorARGBPhysical;
+ unsigned long CursorARGBStart;
+ unsigned long OverlayPhysical;
+ unsigned long OverlayStart;
+ int colorKey;
+ unsigned int surfaceAllocation[I810_TOTAL_SURFACES];
+ int numSurfaces;
+
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+
+ int Chipset;
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+ IOADDRESS ioBase;
+ EntityInfoPtr pEnt;
+ struct pci_device *PciInfo;
+
+ I810RingBuffer *LpRing;
+ unsigned int BR[20];
+
+ int LmFreqSel;
+
+ int VramKey;
+ unsigned long VramOffset;
+ int DcacheKey;
+ unsigned long DcacheOffset;
+ int HwcursKey;
+ unsigned long HwcursOffset;
+ int ARGBHwcursKey;
+ unsigned long ARGBHwcursOffset;
+
+ int GttBound;
+
+ I810MemRange DcacheMem;
+ I810MemRange SysMem;
+
+ I810MemRange SavedDcacheMem;
+ I810MemRange SavedSysMem;
+
+ unsigned char **ScanlineColorExpandBuffers;
+ int NumScanlineColorExpandBuffers;
+ int nextColorExpandBuf;
+
+ I810RegRec SavedReg;
+ I810RegRec ModeReg;
+
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ CloseScreenProcPtr CloseScreen;
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+ I810WriteIndexedByteFunc writeControl;
+ I810ReadIndexedByteFunc readControl;
+ I810WriteByteFunc writeStandard;
+ I810ReadByteFunc readStandard;
+
+ Bool directRenderingDisabled; /* DRI disabled in PreInit */
+ Bool directRenderingEnabled; /* false if XF86DRI not defined. */
+
+#ifdef XF86DRI
+ int LockHeld;
+ DRIInfoPtr pDRIInfo;
+ int drmSubFD;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ I810ConfigPrivPtr pVisualConfigsPriv;
+ unsigned long dcacheHandle;
+ unsigned long backHandle;
+ unsigned long zHandle;
+ unsigned long cursorHandle;
+ unsigned long cursorARGBHandle;
+ unsigned long xvmcHandle;
+ unsigned long sysmemHandle;
+ Bool agpAcquired;
+ drm_handle_t buffer_map;
+ drm_handle_t ring_map;
+ drm_handle_t overlay_map;
+ drm_handle_t mc_map;
+ drm_handle_t xvmcContext;
+#endif
+ Bool agpAcquired2d;
+
+ XF86VideoAdaptorPtr adaptor;
+ OptionInfoPtr Options;
+
+ int configured_device;
+
+ Bool showCache;
+ Bool noAccel;
+ Bool allowPageFlip;
+ Bool have3DWindows;
+ int drmMinor;
+} I810Rec;
+
+#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
+
+#define I810_SELECT_FRONT 0
+#define I810_SELECT_BACK 1
+#define I810_SELECT_DEPTH 2
+
+#ifdef XF86DRI
+extern Bool I810DRIScreenInit(ScreenPtr pScreen);
+extern void I810DRICloseScreen(ScreenPtr pScreen);
+extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen);
+extern Bool I810DRILeave(ScrnInfoPtr pScrn);
+extern Bool I810DRIEnter(ScrnInfoPtr pScrn);
+#endif
+extern Bool I810InitDma(ScrnInfoPtr pScrn);
+extern Bool I810CleanupDma(ScrnInfoPtr pScrn);
+
+#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
+#define I810REGPTR(p) (&(I810PTR(p)->ModeReg))
+
+extern Bool I810CursorInit(ScreenPtr pScreen);
+extern Bool I810AccelInit(ScreenPtr pScreen);
+extern void I810SetPIOAccess(I810Ptr pI810);
+extern void I810SetMMIOAccess(I810Ptr pI810);
+extern unsigned int I810CalcWatermark(ScrnInfoPtr pScrn, double freq,
+ Bool dcache);
+extern void I810PrintErrorState(ScrnInfoPtr pScrn);
+extern int I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
+extern void I810Sync(ScrnInfoPtr pScrn);
+extern unsigned long I810LocalToPhysical(ScrnInfoPtr pScrn,
+ unsigned long local);
+extern int I810AllocLow(I810MemRange * result, I810MemRange * pool,
+ int size);
+extern int I810AllocHigh(I810MemRange * result, I810MemRange * pool,
+ int size);
+extern Bool I810AllocateFront(ScrnInfoPtr pScrn);
+
+extern int I810AllocateGARTMemory(ScrnInfoPtr pScrn);
+extern void I810FreeGARTMemory(ScrnInfoPtr pScrn);
+
+extern Bool I810BindGARTMemory(ScrnInfoPtr pScrn);
+extern Bool I810UnbindGARTMemory(ScrnInfoPtr pScrn);
+
+extern int I810CheckAvailableMemory(ScrnInfoPtr pScrn);
+
+extern Bool I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+extern void I810AdjustFrame(int scrnIndex, int x, int y, int flags);
+
+extern void I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
+ int ydir, int rop,
+ unsigned int planemask,
+ int trans_color);
+extern void I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
+ int srcY, int dstX, int dstY,
+ int w, int h);
+extern void I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+extern void I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+
+extern void I810SelectBuffer(ScrnInfoPtr pScrn, int buffer);
+
+extern void I810RefreshRing(ScrnInfoPtr pScrn);
+extern void I810EmitFlush(ScrnInfoPtr pScrn);
+extern void I810EmitInvarientState(ScrnInfoPtr pScrn);
+
+extern Bool I810DGAInit(ScreenPtr pScreen);
+
+extern void I810InitVideo(ScreenPtr pScreen);
+extern void I810InitMC(ScreenPtr pScreen);
+
+extern const OptionInfoRec *I810AvailableOptions(int chipid, int busid);
+
+#endif /* _I810_H_ */
diff --git a/src/legacy/i810/i810_accel.c b/src/legacy/i810/i810_accel.c
new file mode 100644
index 00000000..ae4a6544
--- /dev/null
+++ b/src/legacy/i810/i810_accel.c
@@ -0,0 +1,617 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xaarop.h"
+#include "i810.h"
+
+static void I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int x, int y, int w, int h);
+
+static void I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int mask);
+
+static void I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
+ pScrn, int x,
+ int y, int w,
+ int h,
+ int skipleft);
+
+static void I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
+
+/* 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
+I810AccelInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810AccelInit\n");
+
+ pI810->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ pI810->bufferOffset = 0;
+ infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
+ infoPtr->Flags |= PIXMAP_CACHE;
+
+ /* Sync
+ */
+ infoPtr->Sync = I810Sync;
+
+ /* Solid filled rectangles
+ */
+ {
+ infoPtr->SolidFillFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidFill = I810SetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = I810SubsequentSolidFillRect;
+ }
+
+ /* Screen to screen copy
+ * - the transparency op hangs the blit engine, disable for now.
+ */
+ {
+ infoPtr->ScreenToScreenCopyFlags = (0
+ | NO_PLANEMASK
+ | NO_TRANSPARENCY | 0);
+
+ infoPtr->SetupForScreenToScreenCopy = I810SetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy =
+ I810SubsequentScreenToScreenCopy;
+ }
+
+ /* 8x8 pattern fills
+ */
+ {
+ infoPtr->SetupForMono8x8PatternFill = I810SetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ I810SubsequentMono8x8PatternFillRect;
+
+ infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+ NO_PLANEMASK | 0);
+ }
+
+ /* 8x8 color fills - not considered useful for XAA.
+ */
+
+ /* Scanline color expansion - Use the same scheme as the 3.3 driver.
+ *
+ */
+ if (pI810->Scratch.Size != 0) {
+ int i;
+ int width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ int nr_buffers = pI810->Scratch.Size / width;
+ unsigned char *ptr = pI810->FbBase + pI810->Scratch.Start;
+
+ pI810->NumScanlineColorExpandBuffers = nr_buffers;
+ pI810->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(nr_buffers, sizeof(unsigned char *));
+
+ for (i = 0; i < nr_buffers; i++, ptr += width)
+ pI810->ScanlineColorExpandBuffers[i] = ptr;
+
+ infoPtr->ScanlineCPUToScreenColorExpandFillFlags = (NO_PLANEMASK |
+ ROP_NEEDS_SOURCE |
+ BIT_ORDER_IN_BYTE_MSBFIRST
+ | 0);
+
+ infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(1, sizeof(unsigned char *));
+ infoPtr->NumScanlineColorExpandBuffers = 1;
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI810->ScanlineColorExpandBuffers[0];
+ pI810->nextColorExpandBuf = 0;
+
+ infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
+ I810SetupForScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ I810SubsequentScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentColorExpandScanline =
+ I810SubsequentColorExpandScanline;
+ }
+
+ /* Possible todo: Image writes w/ non-GXCOPY rop.
+ */
+
+ I810SelectBuffer(pScrn, I810_SELECT_FRONT);
+
+ return XAAInit(pScreen, infoPtr);
+}
+
+int
+I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RingBuffer *ring = pI810->LpRing;
+ int iters = 0;
+ int start = 0;
+ int now = 0;
+ int last_head = 0;
+ int first = 0;
+
+ /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
+ * call it crashed.
+ */
+ if (timeout_millis == 0)
+ timeout_millis = 2000;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
+ ErrorF("I810WaitLpRing %d\n", n);
+ first = GetTimeInMillis();
+ }
+
+ while (ring->space < n) {
+ ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail + 8);
+
+ if (ring->space < 0)
+ ring->space += ring->mem.Size;
+
+ iters++;
+ now = GetTimeInMillis();
+ if (start == 0 || now < start || ring->head != last_head) {
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ if (now > start)
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+ start = now;
+ last_head = ring->head;
+ } else if (now - start > timeout_millis) {
+ ErrorF("Error in I810WaitLpRing(), now is %d, start is %d\n", now,
+ start);
+ I810PrintErrorState(pScrn);
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ pI810->AccelInfoRec = NULL; /* Stops recursive behavior */
+ FatalError("lockup\n");
+ }
+
+ DELAY(10000);
+ }
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
+ now = GetTimeInMillis();
+ if (now - first) {
+ ErrorF("Elapsed %d ms\n", now - first);
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+ }
+ }
+
+ return iters;
+}
+
+void
+I810Sync(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
+ ErrorF("I810Sync\n");
+
+#ifdef XF86DRI
+ /* VT switching tries to do this.
+ */
+ if (!pI810->LockHeld && pI810->directRenderingEnabled) {
+ return;
+ }
+#endif
+
+ /* Send a flush instruction and then wait till the ring is empty.
+ * This is stronger than waiting for the blitter to finish as it also
+ * flushes the internal graphics caches.
+ */
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ I810WaitLpRing(pScrn, pI810->LpRing->mem.Size - 8, 0);
+
+ pI810->LpRing->space = pI810->LpRing->mem.Size - 8;
+ pI810->nextColorExpandBuf = 0;
+}
+
+void
+I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForFillRectSolid color: %x rop: %x mask: %x\n",
+ color, rop, planemask);
+
+ /* Color blit, p166 */
+ pI810->BR[13] = (BR13_SOLID_PATTERN |
+ (XAAGetPatternROP(rop) << 16) |
+ (pScrn->displayWidth * pI810->cpp));
+ pI810->BR[16] = color;
+}
+
+void
+I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
+
+ {
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+ OUT_RING(pI810->BR[13]);
+ OUT_RING((h << 16) | (w * pI810->cpp));
+ OUT_RING(pI810->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI810->cpp);
+
+ OUT_RING(pI810->BR[16]);
+ OUT_RING(0); /* pad to quadword */
+
+ ADVANCE_LP_RING();
+ }
+}
+
+void
+I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int transparency_color)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForScreenToScreenCopy %d %d %x %x %d\n",
+ xdir, ydir, rop, planemask, transparency_color);
+
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+
+ if (ydir == -1)
+ pI810->BR[13] = (-pI810->BR[13]) & 0xFFFF;
+ if (xdir == -1)
+ pI810->BR[13] |= BR13_RIGHT_TO_LEFT;
+
+ pI810->BR[13] |= XAAGetCopyROP(rop) << 16;
+
+ pI810->BR[18] = 0;
+}
+
+void
+I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int src, dst;
+ int w_back = w;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF( "I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
+ x1,y1,x2,y2,w,h);
+ /*
+ * This works around a bug in the i810 drawing engine.
+ * This was developed empirically so it may not catch all
+ * cases.
+ */
+#define I810_MWIDTH 8
+
+ if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3
+ && (y2 - y1) >= 0 && (x2 - x1) <= (w + I810_MWIDTH)
+ && (w > I810_MWIDTH))
+ w = I810_MWIDTH;
+ do {
+
+ if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) {
+ src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ } else {
+ src = y1 * pScrn->displayWidth * pI810->cpp;
+ dst = y2 * pScrn->displayWidth * pI810->cpp;
+ }
+
+ if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) {
+ src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ } else {
+ src += x1 * pI810->cpp;
+ dst += x2 * pI810->cpp;
+ }
+
+
+ /* SRC_COPY_BLT, p169 */
+ {
+ BEGIN_LP_RING(6);
+ OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+ OUT_RING( pI810->BR[13]);
+
+ OUT_RING( (h << 16) | (w * pI810->cpp));
+ OUT_RING( pI810->bufferOffset + dst);
+
+ OUT_RING( pI810->BR[13] & 0xFFFF);
+ OUT_RING( pI810->bufferOffset + src);
+ ADVANCE_LP_RING();
+ }
+ w_back -= w;
+ if (w_back <= 0)
+ break;
+ x2 += w;
+ x1 += w;
+ if (w_back > I810_MWIDTH)
+ w = I810_MWIDTH;
+ else
+ w = w_back;
+ } while (1);
+}
+
+static void
+I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupFor8x8PatternColorExpand\n");
+
+ /* FULL_MONO_PAT_BLT, p176 */
+ pI810->BR[0] = (BR00_BITBLT_CLIENT | BR00_OP_MONO_PAT_BLT | 0x9);
+ pI810->BR[18] = bg;
+ pI810->BR[19] = fg;
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+ pI810->BR[13] |= XAAGetPatternROP(rop) << 16;
+ if (bg == -1)
+ pI810->BR[13] |= BR13_MONO_PATN_TRANS;
+}
+
+static void
+I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
+ int x, int y, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int addr =
+ pI810->bufferOffset + (y * pScrn->displayWidth + x) * pI810->cpp;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810Subsequent8x8PatternColorExpand\n");
+
+ {
+ BEGIN_LP_RING(12);
+ OUT_RING(pI810->BR[0] | ((y << 5) & BR00_PAT_VERT_ALIGN));
+ OUT_RING(pI810->BR[13]);
+ OUT_RING((h << 16) | (w * pI810->cpp));
+ OUT_RING(addr);
+ OUT_RING(pI810->BR[13] & 0xFFFF); /* src pitch */
+ OUT_RING(addr); /* src addr */
+ OUT_RING(0); /* transparency color */
+ OUT_RING(pI810->BR[18]); /* bg */
+ OUT_RING(pI810->BR[19]); /* fg */
+ OUT_RING(pattx); /* pattern data */
+ OUT_RING(patty);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I810GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
+
+ if (pI810->nextColorExpandBuf == pI810->NumScanlineColorExpandBuffers)
+ I810Sync(pScrn);
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI810->ScanlineColorExpandBuffers[pI810->nextColorExpandBuf];
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("using color expand buffer %d\n", pI810->nextColorExpandBuf);
+
+ pI810->nextColorExpandBuf++;
+}
+
+static void
+I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
+ fg, bg, rop, planemask);
+
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+ pI810->BR[13] |= XAAGetCopyROP(rop) << 16;
+ pI810->BR[13] |= (1 << 27);
+ if (bg == -1)
+ pI810->BR[13] |= BR13_MONO_TRANSPCY;
+
+ pI810->BR[18] = bg;
+ pI810->BR[19] = fg;
+
+ I810GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h, int skipleft)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentScanlineCPUToScreenColorExpandFill "
+ "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+ pI810->BR[0] = BR00_BITBLT_CLIENT | BR00_OP_MONO_SRC_COPY_BLT | 0x06;
+ pI810->BR[9] = (pI810->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI810->cpp);
+ pI810->BR[14] = ((1 << 16) | (w * pI810->cpp));
+ pI810->BR[11] = ((w + 31) / 32) - 1;
+}
+
+static void
+I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pI810->BR[12] = (pI810->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI810->FbBase);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentColorExpandScanline %d (addr %x)\n",
+ bufno, pI810->BR[12]);
+
+ {
+ BEGIN_LP_RING(8);
+ OUT_RING(pI810->BR[0]);
+ OUT_RING(pI810->BR[13]);
+ OUT_RING(pI810->BR[14]);
+ OUT_RING(pI810->BR[9]);
+ OUT_RING(pI810->BR[11]);
+ OUT_RING(pI810->BR[12]); /* srcaddr */
+ OUT_RING(pI810->BR[18]);
+ OUT_RING(pI810->BR[19]);
+ ADVANCE_LP_RING();
+ }
+
+ /* Advance to next scanline.
+ */
+ pI810->BR[9] += pScrn->displayWidth * pI810->cpp;
+ I810GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+void
+I810EmitFlush(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+}
+
+void
+I810SelectBuffer(ScrnInfoPtr pScrn, int buffer)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ switch (buffer) {
+ case I810_SELECT_BACK:
+ pI810->bufferOffset = pI810->BackBuffer.Start;
+ break;
+ case I810_SELECT_DEPTH:
+ pI810->bufferOffset = pI810->DepthBuffer.Start;
+ break;
+ default:
+ case I810_SELECT_FRONT:
+ pI810->bufferOffset = pI810->FrontBuffer.Start;
+ break;
+ }
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SelectBuffer %d --> offset %x\n",
+ buffer, pI810->bufferOffset);
+}
+
+void
+I810RefreshRing(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pI810->LpRing->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ pI810->LpRing->tail = INREG(LP_RING + RING_TAIL);
+ pI810->LpRing->space = pI810->LpRing->head - (pI810->LpRing->tail + 8);
+ if (pI810->LpRing->space < 0)
+ pI810->LpRing->space += pI810->LpRing->mem.Size;
+
+ if (pI810->AccelInfoRec)
+ pI810->AccelInfoRec->NeedToSync = TRUE;
+}
+
+/* Emit on gaining VT?
+ */
+void
+I810EmitInvarientState(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ BEGIN_LP_RING(10);
+
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0);
+
+ OUT_RING(GFX_OP_COLOR_CHROMA_KEY);
+ OUT_RING(CC1_UPDATE_KILL_WRITE |
+ CC1_DISABLE_KILL_WRITE |
+ CC1_UPDATE_COLOR_IDX |
+ CC1_UPDATE_CHROMA_LOW | CC1_UPDATE_CHROMA_HI | 0);
+ OUT_RING(0);
+ OUT_RING(0);
+
+/* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */
+/* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */
+
+ ADVANCE_LP_RING();
+}
+
diff --git a/src/legacy/i810/i810_common.h b/src/legacy/i810/i810_common.h
new file mode 100644
index 00000000..ea28f4ab
--- /dev/null
+++ b/src/legacy/i810/i810_common.h
@@ -0,0 +1,323 @@
+/* i810_common.h -- common header definitions for I810 2D/3D/DRM suite
+ *
+ * Copyright 2002 Tungsten Graphics, 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, sublicense,
+ * 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 NONINFRINGEMENT. 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.
+ *
+ * Converted to common header format:
+ * Jens Owen <jens@tungstengraphics.com>
+ *
+ *
+ */
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (i810_drm.h)
+ */
+
+#ifndef _I810_COMMON_H_
+#define _I810_COMMON_H_
+
+/* Provide substitutes for gcc's __FUNCTION__ on other compilers */
+#if !defined(__GNUC__) && !defined(__FUNCTION__)
+# if defined(__STDC__) && (__STDC_VERSION__>=199901L) /* C99 */
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ ""
+# endif
+#endif
+
+#define PFX __FILE__,__LINE__,__FUNCTION__
+#define FUNCTION_NAME __FUNCTION__
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * KB(1024))
+
+/* Using usleep() makes things noticably slow. */
+#if 0
+#define DELAY(x) usleep(x)
+#else
+#define DELAY(x) do {;} while (0)
+#endif
+
+#define PrintErrorState I810PrintErrorState
+#define WaitRingFunc I810WaitLpRing
+#define RecPtr pI810
+
+static inline void memset_volatile(volatile void *b, int c, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ ((volatile char *)b)[i] = c;
+}
+
+static inline void memcpy_volatile(volatile void *dst, const void *src,
+ size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ ((volatile char *)dst)[i] = ((volatile char *)src)[i];
+}
+
+/* Memory mapped register access macros */
+#define INREG8(addr) *(volatile uint8_t *)(RecPtr->MMIOBase + (addr))
+#define INREG16(addr) *(volatile uint16_t *)(RecPtr->MMIOBase + (addr))
+#define INREG(addr) *(volatile uint32_t *)(RecPtr->MMIOBase + (addr))
+#define INGTT(addr) *(volatile uint32_t *)(RecPtr->GTTBase + (addr))
+#define POSTING_READ(addr) (void)INREG(addr)
+
+#define OUTREG8(addr, val) do { \
+ *(volatile uint8_t *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG8(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(val), FUNCTION_NAME); \
+ } \
+} while (0)
+
+#define OUTREG16(addr, val) do { \
+ *(volatile uint16_t *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG16(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(val), FUNCTION_NAME); \
+ } \
+} while (0)
+
+#define OUTREG(addr, val) do { \
+ *(volatile uint32_t *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(val), FUNCTION_NAME); \
+ } \
+} while (0)
+
+/* To remove all debugging, make sure I810_DEBUG is defined as a
+ * preprocessor symbol, and equal to zero.
+ */
+#if 1
+#define I810_DEBUG 0
+#endif
+#ifndef I810_DEBUG
+#warning "Debugging enabled - expect reduced performance"
+extern int I810_DEBUG;
+#endif
+
+#define DEBUG_VERBOSE_ACCEL 0x1
+#define DEBUG_VERBOSE_SYNC 0x2
+#define DEBUG_VERBOSE_VGA 0x4
+#define DEBUG_VERBOSE_RING 0x8
+#define DEBUG_VERBOSE_OUTREG 0x10
+#define DEBUG_VERBOSE_MEMORY 0x20
+#define DEBUG_VERBOSE_CURSOR 0x40
+#define DEBUG_ALWAYS_SYNC 0x80
+#define DEBUG_VERBOSE_DRI 0x100
+#define DEBUG_VERBOSE_BIOS 0x200
+
+/* Size of the mmio region.
+ */
+#define I810_REG_SIZE 0x80000
+
+#define GTT_PAGE_SIZE KB(4)
+#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y))
+#define ROUND_TO_PAGE(x) ROUND_TO((x), GTT_PAGE_SIZE)
+#define ROUND_TO_MB(x) ROUND_TO((x), MB(1))
+#define PRIMARY_RINGBUFFER_SIZE KB(128)
+#define MIN_SCRATCH_BUFFER_SIZE KB(16)
+#define MAX_SCRATCH_BUFFER_SIZE KB(64)
+#define HWCURSOR_SIZE GTT_PAGE_SIZE
+#define HWCURSOR_SIZE_ARGB GTT_PAGE_SIZE * 4
+
+/* Use a 64x64 HW cursor */
+#define I810_CURSOR_X 64
+#define I810_CURSOR_Y I810_CURSOR_X
+
+#define PIPE_NAME(n) ('A' + (n))
+
+extern struct pci_device *
+intel_host_bridge (void);
+
+/**
+ * Hints to CreatePixmap to tell the driver how the pixmap is going to be
+ * used.
+ *
+ * Compare to CREATE_PIXMAP_USAGE_* in the server.
+ */
+enum {
+ INTEL_CREATE_PIXMAP_TILING_X = 0x10000000,
+ INTEL_CREATE_PIXMAP_TILING_Y,
+ INTEL_CREATE_PIXMAP_TILING_NONE,
+};
+
+#ifndef _I810_DEFINES_
+#define _I810_DEFINES_
+#define I810_USE_BATCH 1
+
+#define I810_DMA_BUF_ORDER 12
+#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
+#define I810_DMA_BUF_NR 256
+
+#define I810_NR_SAREA_CLIPRECTS 8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I810_NR_TEX_REGIONS 64
+#define I810_LOG_MIN_TEX_REGION_SIZE 16
+
+/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1 1
+#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1 3
+#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1 5
+#define I810_DESTREG_DR2 6
+#define I810_DESTREG_DR3 7
+#define I810_DESTREG_DR4 8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1 1
+#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1 3
+#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1 1
+#define I810_TEXREG_MI2 2
+#define I810_TEXREG_MI3 3
+#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_I810_INIT 0x00
+#define DRM_I810_VERTEX 0x01
+#define DRM_I810_CLEAR 0x02
+#define DRM_I810_FLUSH 0x03
+#define DRM_I810_GETAGE 0x04
+#define DRM_I810_GETBUF 0x05
+#define DRM_I810_SWAP 0x06
+#define DRM_I810_COPY 0x07
+#define DRM_I810_DOCOPY 0x08
+#define DRM_I810_OV0INFO 0x09
+#define DRM_I810_FSTATUS 0x0a
+#define DRM_I810_OV0FLIP 0x0b
+#define DRM_I810_MC 0x0c
+#define DRM_I810_RSTATUS 0x0d
+#define DRM_I810_FLIP 0x0e
+
+#endif
+
+typedef enum _drmI810Initfunc {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02,
+ I810_INIT_DMA_1_4 = 0x03
+} drmI810Initfunc;
+
+typedef struct {
+ drmI810Initfunc func;
+ unsigned int mmio_offset;
+ unsigned int buffers_offset;
+ int sarea_priv_offset;
+ unsigned int ring_start;
+ unsigned int ring_end;
+ unsigned int ring_size;
+ unsigned int front_offset;
+ unsigned int back_offset;
+ unsigned int depth_offset;
+ unsigned int overlay_offset;
+ unsigned int overlay_physical;
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
+} drmI810Init;
+
+typedef struct {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drmI810DMA;
+
+/* Flags for clear ioctl
+ */
+#define I810_FRONT 0x1
+#define I810_BACK 0x2
+#define I810_DEPTH 0x4
+
+typedef struct {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drmI810Clear;
+
+typedef struct {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+} drmI810Vertex;
+
+/* Flags for vertex ioctl
+ */
+#define PR_TRIANGLES (0x0<<18)
+#define PR_TRISTRIP_0 (0x1<<18)
+#define PR_TRISTRIP_1 (0x2<<18)
+#define PR_TRIFAN (0x3<<18)
+#define PR_POLYGON (0x4<<18)
+#define PR_LINES (0x5<<18)
+#define PR_LINESTRIP (0x6<<18)
+#define PR_RECTS (0x7<<18)
+#define PR_MASK (0x7<<18)
+
+#endif
diff --git a/src/legacy/i810/i810_cursor.c b/src/legacy/i810/i810_cursor.c
new file mode 100644
index 00000000..898a1364
--- /dev/null
+++ b/src/legacy/i810/i810_cursor.c
@@ -0,0 +1,266 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+
+#include "xf86fbman.h"
+
+#include "i810.h"
+
+static Bool I810UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
+static void I810LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
+static void I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void I810ShowCursor(ScrnInfoPtr pScrn);
+static void I810HideCursor(ScrnInfoPtr pScrn);
+static void I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
+static void I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static Bool I810UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
+
+Bool
+I810CursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ I810Ptr pI810;
+ xf86CursorInfoPtr infoPtr;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI810 = I810PTR(pScrn);
+ pI810->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 | 0);
+
+ infoPtr->SetCursorColors = I810SetCursorColors;
+ infoPtr->SetCursorPosition = I810SetCursorPosition;
+ infoPtr->LoadCursorImage = I810LoadCursorImage;
+ infoPtr->HideCursor = I810HideCursor;
+ infoPtr->ShowCursor = I810ShowCursor;
+ infoPtr->UseHWCursor = I810UseHWCursor;
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = FALSE;
+
+ if (!pI810->CursorARGBPhysical) {
+ infoPtr->UseHWCursorARGB = I810UseHWCursorARGB;
+ infoPtr->LoadCursorARGB = I810LoadCursorARGB;
+ }
+#endif
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+static Bool I810UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (!pI810->CursorARGBPhysical)
+ return FALSE;
+
+ if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void I810LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ uint32_t *pcurs = (uint32_t *) (pI810->FbBase + pI810->CursorStart);
+ uint32_t *image = (uint32_t *) pCurs->bits->argb;
+ int x, y, w, h;
+
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = TRUE;
+#endif
+
+ w = pCurs->bits->width;
+ h = pCurs->bits->height;
+
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ *pcurs++ = *image++;
+ for (; x < 64; x++)
+ *pcurs++ = 0;
+ }
+
+ for (; y < 64; y++)
+ for (x = 0; x < 64; x++)
+ *pcurs++ = 0;
+}
+#endif
+
+static Bool
+I810UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (!pI810->CursorPhysical)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static void
+I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ uint8_t *pcurs = (uint8_t *) (pI810->FbBase + pI810->CursorStart);
+ int x, y;
+
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = FALSE;
+#endif
+
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64 / 4; x++) {
+ *pcurs++ = *src++;
+ }
+ }
+}
+
+static void
+I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int flag;
+
+ x += pI810->CursorOffset;
+
+ if (x >= 0)
+ flag = CURSOR_X_POS;
+ else {
+ flag = CURSOR_X_NEG;
+ x = -x;
+ }
+
+ OUTREG8(CURSOR_X_LO, x & 0xFF);
+ OUTREG8(CURSOR_X_HI, (((x >> 8) & 0x07) | flag));
+
+ if (y >= 0)
+ flag = CURSOR_Y_POS;
+ else {
+ flag = CURSOR_Y_NEG;
+ y = -y;
+ }
+ OUTREG8(CURSOR_Y_LO, y & 0xFF);
+ OUTREG8(CURSOR_Y_HI, (((y >> 8) & 0x07) | flag));
+
+ if (pI810->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical);
+ else
+ OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical);
+}
+
+static void
+I810ShowCursor(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ unsigned char tmp;
+
+ if (pI810->CursorIsARGB) {
+ OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical);
+ OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_ARGB_AX);
+ } else {
+ OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical);
+ OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C);
+ }
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp |= HW_CURSOR_ENABLE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I810HideCursor(ScrnInfoPtr pScrn)
+{
+ unsigned char tmp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp &= ~HW_CURSOR_ENABLE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ int tmp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+#ifdef ARGB_CURSOR
+ if (pI810->CursorIsARGB)
+ return;
+#endif
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp |= EXTENDED_PALETTE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+
+ pI810->writeStandard(pI810, DACMASK, 0xFF);
+ pI810->writeStandard(pI810, DACWX, 0x04);
+
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x00FF0000) >> 16);
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x0000FF00) >> 8);
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x000000FF));
+
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x00FF0000) >> 16);
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x0000FF00) >> 8);
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x000000FF));
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp &= ~EXTENDED_PALETTE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
diff --git a/src/legacy/i810/i810_dga.c b/src/legacy/i810/i810_dga.c
new file mode 100644
index 00000000..d9ddda04
--- /dev/null
+++ b/src/legacy/i810/i810_dga.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "i810.h"
+#include "i810_reg.h"
+#include "dgaproc.h"
+#include "vgaHW.h"
+
+static Bool I810_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool I810_SetMode(ScrnInfoPtr, DGAModePtr);
+static void I810_Sync(ScrnInfoPtr);
+static int I810_GetViewport(ScrnInfoPtr);
+static void I810_SetViewport(ScrnInfoPtr, int, int, int);
+static void I810_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void I810_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+
+#if 0
+static void I810_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+#endif
+
+static
+DGAFunctionRec I810DGAFuncs = {
+ I810_OpenFramebuffer,
+ NULL,
+ I810_SetMode,
+ I810_SetViewport,
+ I810_GetViewport,
+ I810_Sync,
+ I810_FillRect,
+ I810_BlitRect,
+#if 0
+ I810_BlitTransRect
+#else
+ NULL
+#endif
+};
+
+Bool
+I810DGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(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 = realloc(modes, (num + 1) * sizeof(DGAModeRec));
+
+ if (!newmodes) {
+ free(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+
+ currentMode = modes + num;
+ num++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if (!pI810->noAccel)
+ 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 = pI810->FbBase;
+
+ currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+ currentMode->imageWidth = pI810->FbMemBox.x2;
+ currentMode->imageHeight = pI810->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;
+ }
+
+ pI810->numDGAModes = num;
+ pI810->DGAModes = modes;
+
+ return DGAInit(pScreen, &I810DGAFuncs, modes, num);
+}
+
+static DisplayModePtr I810SavedDGAModes[MAXSCREENS];
+
+static Bool
+I810_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ int index = pScrn->pScreen->myNum;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (!pMode) { /* restore the original mode */
+ if (pI810->DGAactive) {
+ pScrn->currentMode = I810SavedDGAModes[index];
+ pScrn->SwitchMode(index, pScrn->currentMode, 0);
+ pScrn->AdjustFrame(index, 0, 0, 0);
+ pI810->DGAactive = FALSE;
+ }
+ } else {
+ if (!pI810->DGAactive) {
+ I810SavedDGAModes[index] = pScrn->currentMode;
+ pI810->DGAactive = TRUE;
+ }
+
+ pScrn->SwitchMode(index, pMode->mode, 0);
+ }
+
+ return TRUE;
+}
+
+static int
+I810_GetViewport(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ return pI810->DGAViewportStatus;
+}
+
+static void
+I810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+
+ /* wait for retrace */
+ while ((hwp->readST01(hwp) & 0x08)) ;
+ while (!(hwp->readST01(hwp) & 0x08)) ;
+
+ pI810->DGAViewportStatus = 0;
+}
+
+static void
+I810_FillRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h, unsigned long color)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->AccelInfoRec) {
+ (*pI810->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
+ (*pI810->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
+ SET_SYNC_FLAG(pI810->AccelInfoRec);
+ }
+}
+
+static void
+I810_Sync(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->AccelInfoRec) {
+ (*pI810->AccelInfoRec->Sync) (pScrn);
+ }
+}
+
+static void
+I810_BlitRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pI810->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
+ GXcopy, ~0, -1);
+ (*pI810->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+ SET_SYNC_FLAG(pI810->AccelInfoRec);
+ }
+}
+
+#if 0
+static void
+I810_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
+I810_OpenFramebuffer(ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem, int *size, int *offset, int *flags)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char *)pI810->LinearAddr;
+ *size = pI810->FbMapSize;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
diff --git a/src/legacy/i810/i810_dri.c b/src/legacy/i810/i810_dri.c
new file mode 100644
index 00000000..ecb94af1
--- /dev/null
+++ b/src/legacy/i810/i810_dri.c
@@ -0,0 +1,1544 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Priv.h"
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+#include "windowstr.h"
+#include "shadow.h"
+#include "shadowfb.h"
+
+#include "GL/glxtokens.h"
+
+#include "i810.h"
+#include "i810_dri.h"
+
+static char I810KernelDriverName[] = "i810";
+static char I810ClientDriverName[] = "i810";
+
+static Bool I810InitVisualConfigs(ScreenPtr pScreen);
+static Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore);
+static void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType readContextType,
+ void *readContextStore,
+ DRIContextType writeContextType,
+ void *writeContextStore);
+static void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
+static void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index);
+
+
+static void I810EnablePageFlip(ScreenPtr pScreen);
+static void I810DisablePageFlip(ScreenPtr pScreen);
+static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void I810DRITransitionTo3d(ScreenPtr pScreen);
+static void I810DRITransitionTo2d(ScreenPtr pScreen);
+
+static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+extern void GlxSetVisualConfigs(int nconfigs,
+ __GLXvisualConfig * configs,
+ void **configprivs);
+
+static int i810_pitches[] = {
+ 512,
+ 1024,
+ 2048,
+ 4096,
+ 0
+};
+
+static int i810_pitch_flags[] = {
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x3,
+ 0
+};
+
+static unsigned int i810_drm_version = 0;
+
+Bool
+I810CleanupDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ drmI810Init info;
+
+ memset(&info, 0, sizeof(drmI810Init));
+ info.func = I810_CLEANUP_DMA;
+
+ if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
+ &info, sizeof(drmI810Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[dri] I810 Dma Cleanup Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+I810InitDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RingBuffer *ring = pI810->LpRing;
+ I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
+ drmI810Init info;
+
+ memset(&info, 0, sizeof(drmI810Init));
+
+ info.ring_start = ring->mem.Start;
+ info.ring_end = ring->mem.End;
+ info.ring_size = ring->mem.Size;
+ info.mmio_offset = (unsigned int)pI810DRI->regs;
+ info.buffers_offset = (unsigned int)pI810->buffer_map;
+ info.sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ info.front_offset = 0;
+ info.back_offset = pI810->BackBuffer.Start;
+ info.depth_offset = pI810->DepthBuffer.Start;
+ info.overlay_offset = pI810->OverlayStart;
+ info.overlay_physical = pI810->OverlayPhysical;
+ info.w = pScrn->virtualX;
+ info.h = pScrn->virtualY;
+ info.pitch = pI810->auxPitch;
+ info.pitch_bits = pI810->auxPitchBits;
+
+ /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility
+ * we created a new v1.4 that supports a new init function. Eventually the
+ * old init function will go away. If you change the drm interface, make a
+ * new init type too so that we can detect the new client.
+ */
+ switch(i810_drm_version) {
+ case ((1<<16) | 0):
+ case ((1<<16) | 1):
+ case ((1<<16) | 2):
+ case ((1<<16) | 3):
+ /* Use OLD drm < 1.4 init */
+ info.func = I810_INIT_DMA;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n");
+ break;
+ default:
+ case ((1<<16) | 4):
+ /* DRM version 1.3 or greater init */
+ info.func = I810_INIT_DMA_1_4;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n");
+ break;
+ }
+
+ if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
+ &info, sizeof(drmI810Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] I810 Dma Initialization failed.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I810InitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = NULL;
+ I810ConfigPrivPtr pI810Configs = NULL;
+ I810ConfigPrivPtr *pI810ConfigPtrs = NULL;
+ int accum, stencil, db, depth;
+ int i;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 24:
+ case 32:
+ break;
+ case 16:
+ numConfigs = 8;
+
+ pConfigs =
+ (__GLXvisualConfig *) calloc(sizeof(__GLXvisualConfig),
+ numConfigs);
+ if (!pConfigs)
+ return FALSE;
+
+ pI810Configs =
+ (I810ConfigPrivPtr) calloc(sizeof(I810ConfigPrivRec),
+ numConfigs);
+ if (!pI810Configs) {
+ free(pConfigs);
+ return FALSE;
+ }
+
+ pI810ConfigPtrs =
+ (I810ConfigPrivPtr *) calloc(sizeof(I810ConfigPrivPtr),
+ numConfigs);
+ if (!pI810ConfigPtrs) {
+ free(pConfigs);
+ free(pI810Configs);
+ return FALSE;
+ }
+
+ for (i = 0; i < numConfigs; i++)
+ pI810ConfigPtrs[i] = &pI810Configs[i];
+
+ i = 0;
+ depth = 1;
+ for (accum = 0; accum <= 1; accum++) {
+ for (stencil = 0; stencil <= 1; stencil++) {
+ for (db = 1; db >= 0; db--) {
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0;
+ if (accum) {
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ if (depth)
+ pConfigs[i].depthSize = 16;
+ else
+ pConfigs[i].depthSize = 0;
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (stencil || accum)
+ pConfigs[i].visualRating = GLX_SLOW_CONFIG;
+ else
+ pConfigs[i].visualRating = GLX_NONE;
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ assert(i == numConfigs);
+ break;
+ }
+ pI810->numVisualConfigs = numConfigs;
+ pI810->pVisualConfigs = pConfigs;
+ pI810->pVisualConfigsPriv = pI810Configs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI810ConfigPtrs);
+ return TRUE;
+}
+
+static unsigned int
+mylog2(unsigned int n)
+{
+ unsigned int log2 = 1;
+
+ while (n > 1)
+ n >>= 1, log2++;
+ return log2;
+}
+
+Bool
+I810DRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ I810DRIPtr pI810DRI;
+ unsigned long tom;
+ drm_handle_t agpHandle;
+ drm_handle_t dcacheHandle;
+ int sysmem_size = 0;
+ int back_size = 0;
+ unsigned int pitch_idx = 0;
+ int bufs;
+ int width = pScrn->displayWidth * pI810->cpp;
+ int i;
+
+ /* Hardware 3D rendering only implemented for 16bpp */
+ /* And it only works for 5:6:5 (Mark) */
+ if (pScrn->depth != 16)
+ return FALSE;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module. */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* adjust width first */
+#define Elements(x) sizeof(x)/sizeof(*x)
+ for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
+ if (width <= i810_pitches[pitch_idx])
+ break;
+
+ if (pitch_idx == Elements(i810_pitches)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] Couldn't find depth/back buffer pitch");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ } else {
+ /* for tiled memory to work, the buffer needs to have the
+ * number of lines as a multiple of 16 (the tile size),
+ * - airlied */
+ int lines = (pScrn->virtualY + 15) / 16 * 16;
+ back_size = i810_pitches[pitch_idx] * lines;
+ back_size = ((back_size + 4096 - 1) / 4096) * 4096;
+ }
+
+ pScrn->displayWidth = i810_pitches[pitch_idx] / pI810->cpp;
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
+ "[dri] Disabling DRI.\n", major, minor, patch,
+ DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (!pDRIInfo) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRICreateInfoRec failed. Disabling DRI.\n");
+ return FALSE;
+ }
+
+/* pDRIInfo->wrap.ValidateTree = 0; */
+/* pDRIInfo->wrap.PostValidateTree = 0; */
+
+ pI810->pDRIInfo = pDRIInfo;
+ pI810->LockHeld = 0;
+
+ pDRIInfo->drmDriverName = I810KernelDriverName;
+ pDRIInfo->clientDriverName = I810ClientDriverName;
+ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+ pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
+ } else {
+ pDRIInfo->busIdString = malloc(64);
+ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
+ pI810->PciInfo->dev, pI810->PciInfo->func
+ );
+ }
+ pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
+ pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
+ pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
+ pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr;
+ pDRIInfo->frameBufferSize = (((pScrn->displayWidth *
+ pScrn->virtualY * pI810->cpp) +
+ 4096 - 1) / 4096) * 4096;
+
+ pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp;
+ pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES;
+
+ if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES)
+ pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
+ else
+ pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES;
+
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] Data does not fit in SAREA\n");
+ return FALSE;
+ }
+ pDRIInfo->SAREASize = SAREA_MAX;
+
+ if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) {
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = NULL;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pI810DRI;
+ pDRIInfo->devPrivateSize = sizeof(I810DRIRec);
+ pDRIInfo->contextSize = sizeof(I810DRIContextRec);
+
+ pDRIInfo->CreateContext = I810CreateContext;
+ pDRIInfo->DestroyContext = I810DestroyContext;
+ pDRIInfo->SwapContext = I810DRISwapContext;
+ pDRIInfo->InitBuffers = I810DRIInitBuffers;
+ pDRIInfo->MoveBuffers = I810DRIMoveBuffers;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+ pDRIInfo->TransitionTo2d = I810DRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = I810DRITransitionTo3d;
+ pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d;
+ pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ /* This adds the framebuffer as a drm map *before* we have asked agp
+ * to allocate it. Scary stuff, hold on...
+ */
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ free(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = NULL;
+ return FALSE;
+ }
+
+ /* Check the i810 DRM versioning */
+ {
+ drmVersionPtr version;
+
+ /* Check the DRM lib version.
+ * drmGetLibVersion was not supported in version 1.0, so check for
+ * symbol first to avoid possible crash or hang.
+ */
+ if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
+ version = drmGetLibVersion(pI810->drmSubFD);
+ } else
+ {
+ /* drmlib version 1.0.0 didn't have the drmGetLibVersion
+ * entry point. Fake it by allocating a version record
+ * via drmGetVersion and changing it to version 1.0.0
+ */
+ version = drmGetVersion(pI810->drmSubFD);
+ version->version_major = 1;
+ version->version_minor = 0;
+ version->version_patchlevel = 0;
+ }
+
+#define REQ_MAJ 1
+#define REQ_MIN 1
+ if (version) {
+ if (version->version_major != REQ_MAJ ||
+ version->version_minor < REQ_MIN) {
+ /* incompatible drm library version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor, version->version_patchlevel,
+ REQ_MAJ, REQ_MIN);
+ drmFreeVersion(version);
+ I810DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Check the i810 DRM version */
+ version = drmGetVersion(pI810->drmSubFD);
+ if (version) {
+ i810_drm_version = (version->version_major<<16) |
+ version->version_minor;
+ if (version->version_major != 1 || version->version_minor < 2) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor, version->version_patchlevel);
+ I810DRICloseScreen(pScreen);
+ drmFreeVersion(version);
+ return FALSE;
+ }
+ pI810->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+ }
+
+ pI810DRI->regsSize = I810_REG_SIZE;
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
+ pI810DRI->regsSize, DRM_REGISTERS, 0,
+ (drmAddress) &pI810DRI->regs) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
+ (int)pI810DRI->regs);
+
+ pI810->backHandle = DRM_AGP_NO_HANDLE;
+ pI810->zHandle = DRM_AGP_NO_HANDLE;
+ pI810->cursorHandle = DRM_AGP_NO_HANDLE;
+ pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
+ pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
+
+ /* Agp Support - Need this just to get the framebuffer.
+ */
+ if (drmAgpAcquire(pI810->drmSubFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pI810->agpAcquired = TRUE;
+
+ if (drmAgpEnable(pI810->drmSubFD, 0) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
+ memset(&pI810->BackBuffer, 0, sizeof(I810MemRange));
+ memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange));
+ pI810->CursorPhysical = 0;
+ pI810->CursorARGBPhysical = 0;
+
+ /* Dcache - half the speed of normal ram, but has use as a Z buffer
+ * under the DRI.
+ */
+
+ drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL,
+ (drmAddress) &dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n",
+ (int)dcacheHandle);
+
+ sysmem_size = pScrn->videoRam * 1024;
+ if (dcacheHandle != DRM_AGP_NO_HANDLE) {
+ if (back_size > 4 * 1024 * 1024) {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[dri] Backsize is larger then 4 meg\n");
+ sysmem_size = sysmem_size - 2 * back_size;
+ drmAgpFree(pI810->drmSubFD, dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
+ } else {
+ sysmem_size = sysmem_size - back_size;
+ }
+ } else {
+ sysmem_size = sysmem_size - 2 * back_size;
+ }
+
+ /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */
+ if (pI810->numSurfaces && (pI810->numSurfaces == 6)) {
+ if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) {
+ sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "User requested more memory then fits in the agp aperture\n"
+ "Truncating to %d bytes of memory\n", sysmem_size);
+ }
+ }
+ if (pI810->numSurfaces && (pI810->numSurfaces == 7)) {
+ if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) {
+ sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "User requested more memory then fits in the agp aperture\n"
+ "Truncating to %d bytes of memory\n", sysmem_size);
+ }
+ }
+
+ if (sysmem_size > pI810->FbMapSize) {
+ sysmem_size = pI810->FbMapSize;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] User requested more memory then fits in the agp"
+ " aperture\n\tTruncating to %d bytes of memory\n",
+ sysmem_size);
+ }
+
+ sysmem_size -= 4096; /* remove 4k for the hw cursor */
+ sysmem_size -= 16384; /* remove 16k for the ARGB hw cursor */
+
+ pI810->SysMem.Start = 0;
+ pI810->SysMem.Size = sysmem_size;
+ pI810->SysMem.End = sysmem_size;
+ tom = sysmem_size;
+
+ pI810->SavedSysMem = pI810->SysMem;
+
+ if (dcacheHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) {
+ memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Found 4096K Z buffer memory\n");
+ pI810->DcacheMem.Start = pI810->DepthOffset;
+ pI810->DcacheMem.Size = 1024 * 4096;
+ pI810->DcacheMem.End =
+ pI810->DcacheMem.Start + pI810->DcacheMem.Size;
+ if (!I810AllocLow
+ (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Depth buffer allocation failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: dcache bind failed\n");
+ drmAgpFree(pI810->drmSubFD, dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: no dcache memory found\n");
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
+ (drmAddress) &agpHandle);
+ pI810->backHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound backbuffer memory\n");
+
+ pI810->BackBuffer.Start = pI810->BackOffset;
+ pI810->BackBuffer.Size = back_size;
+ pI810->BackBuffer.End = (pI810->BackBuffer.Start +
+ pI810->BackBuffer.Size);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to bind backbuffer. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ if (dcacheHandle == DRM_AGP_NO_HANDLE) {
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
+ (drmAddress) &agpHandle);
+
+ pI810->zHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound depthbuffer memory\n");
+ pI810->DepthBuffer.Start = pI810->DepthOffset;
+ pI810->DepthBuffer.Size = back_size;
+ pI810->DepthBuffer.End = (pI810->DepthBuffer.Start +
+ pI810->DepthBuffer.Size);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to bind depthbuffer. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ }
+
+ /* Now allocate and bind the agp space. This memory will include the
+ * regular framebuffer as well as texture memory.
+ */
+ drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL,
+ (drmAddress)&agpHandle);
+ pI810->sysmemHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound System Texture Memory\n");
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled
+ regions and required surface pitches. (Numbers are adjusted if the
+ AGP region is only 32MB
+ For numSurfaces == 6
+ 44 - 48MB = 4MB Fence, 8 Tiles wide
+ 43 - 44MB = 1MB Fence, 8 Tiles wide
+ 42 - 43MB = 1MB Fence, 4 Tiles wide
+ 41 - 42MB = 1MB Fence, 4 Tiles wide
+ For numSurfaces == 7
+ 44 - 48MB = 4MB Fence, 8 Tiles wide
+ 43 - 44MB = 1MB Fence, 8 Tiles wide
+ 42.5 - 43MB = 0.5MB Fence, 8 Tiles wide
+ 42 - 42.5MB = 0.5MB Fence, 4 Tiles wide
+ 40 - 42MB = 2MB Fence, 4 Tiles wide
+ */
+ if (pI810->numSurfaces) {
+ if (pI810->numSurfaces == 6) {
+ pI810->MC.Size = 7 * 1024 * 1024;
+ pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024;
+
+ }
+ if (pI810->numSurfaces == 7) {
+ pI810->MC.Size = 8 * 1024 * 1024;
+ pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
+ }
+ drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL,
+ (drmAddress) &agpHandle);
+
+ pI810->xvmcHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "GART: Allocated 7MB for HWMC\n");
+ pI810->MC.End = pI810->MC.Start + pI810->MC.Size;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n");
+ pI810->MC.Start = 0;
+ pI810->MC.Size = 0;
+ pI810->MC.End = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n");
+ pI810->MC.Start = 0;
+ pI810->MC.Size = 0;
+ pI810->MC.End = 0;
+ }
+ pI810->xvmcContext = 0;
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, 4096, 2,
+ (unsigned long *)&pI810->CursorPhysical,
+ (drmAddress) &agpHandle);
+
+ pI810->cursorHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ tom = sysmem_size;
+
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Allocated 4K for mouse cursor image\n");
+ pI810->CursorStart = tom;
+ tom += 4096;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: cursor bind failed\n");
+ pI810->CursorPhysical = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: cursor alloc failed\n");
+ pI810->CursorPhysical = 0;
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, 16384, 2,
+ (unsigned long *)&pI810->CursorARGBPhysical,
+ (drmAddress) &agpHandle);
+
+ pI810->cursorARGBHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ int r;
+
+ if ((r = drmAgpBind(pI810->drmSubFD, agpHandle, tom)) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Allocated 16K for ARGB mouse cursor image\n");
+ pI810->CursorARGBStart = tom;
+ tom += 16384;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: ARGB cursor bind failed\n");
+ pI810->CursorARGBPhysical = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: ARGB cursor alloc failed\n");
+ pI810->CursorARGBPhysical = 0;
+ }
+
+ /* Steal some of the excess cursor space for the overlay regs.
+ */
+ pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
+ pI810->OverlayStart = pI810->CursorStart + 1024;
+
+ I810SetTiledMemory(pScrn, 1,
+ pI810->DepthBuffer.Start,
+ i810_pitches[pitch_idx], 8 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 2,
+ pI810->BackBuffer.Start,
+ i810_pitches[pitch_idx], 8 * 1024 * 1024);
+
+ /* These are for HWMC surfaces */
+ if (pI810->numSurfaces == 6) {
+ I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 4,
+ pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 5,
+ pI810->MC.Start + 1024 * 1024 * 2,
+ 1024, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 6,
+ pI810->MC.Start + 1024 * 1024 * 3,
+ 1024, 4 * 1024 * 1024);
+ }
+ if (pI810->numSurfaces == 7) {
+ I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 4,
+ pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024);
+
+ I810SetTiledMemory(pScrn, 5,
+ pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024,
+ 1024, 512 * 1024);
+
+ I810SetTiledMemory(pScrn, 6,
+ pI810->MC.Start + 3 * 1024 * 1024,
+ 1024, 1 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 7,
+ pI810->MC.Start + 4 * 1024 * 1024,
+ 1024, 4 * 1024 * 1024);
+
+ }
+
+ pI810->auxPitch = i810_pitches[pitch_idx];
+ pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
+ pI810->SavedDcacheMem = pI810->DcacheMem;
+ pI810DRI->backbufferSize = pI810->BackBuffer.Size;
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
+ pI810->BackBuffer.Size, DRM_AGP, 0,
+ (drmAddress) &pI810DRI->backbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
+ pI810->DepthBuffer.Size, DRM_AGP, 0,
+ (drmAddress) &pI810DRI->depthbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Allocate FrontBuffer etc. */
+ if (!I810AllocateFront(pScrn)) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Allocate buffer memory */
+ I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem),
+ I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n",
+ pI810->BufferMem.Start);
+
+ if (pI810->BufferMem.Start == 0 ||
+ pI810->BufferMem.End - pI810->BufferMem.Start >
+ I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] Not enough memory for dma buffers. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
+ pI810->BufferMem.Size, DRM_AGP, 0,
+ (drmAddress) &pI810->buffer_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ pI810DRI->agp_buffers = pI810->buffer_map;
+ pI810DRI->agp_buf_size = pI810->BufferMem.Size;
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
+ pI810->LpRing->mem.Size, DRM_AGP, 0,
+ (drmAddress) &pI810->ring_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Use the rest of memory for textures. */
+ pI810DRI->textureSize = pI810->SysMem.Size;
+
+ i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
+
+ if (i < I810_LOG_MIN_TEX_REGION_SIZE)
+ i = I810_LOG_MIN_TEX_REGION_SIZE;
+
+ pI810DRI->logTextureGranularity = i;
+ pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */
+
+ if (pI810DRI->textureSize < 512 * 1024) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Less then 512k memory left for textures. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize);
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
+ pI810->TexMem.Size, DRM_AGP, 0,
+ (drmAddress) &pI810DRI->textures) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(textures) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ if ((bufs = drmAddBufs(pI810->drmSubFD,
+ I810_DMA_BUF_NR,
+ I810_DMA_BUF_SZ,
+ DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding %d %d byte DMA buffers. Disabling DRI.\n",
+ I810_DMA_BUF_NR, I810_DMA_BUF_SZ);
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ);
+
+ I810InitDma(pScrn);
+
+ /* Okay now initialize the dma engine */
+
+ if (!pI810DRI->irq) {
+ pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD,
+ ((pI810->PciInfo->domain << 8) |
+ pI810->PciInfo->bus),
+ pI810->PciInfo->dev,
+ pI810->PciInfo->func
+ );
+ if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding irq handler, there is a device "
+ "already using that irq\n Consider rearranging your "
+ "PCI cards. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq);
+
+ pI810DRI->deviceID = DEVICE_ID(pI810->PciInfo);
+ pI810DRI->width = pScrn->virtualX;
+ pI810DRI->height = pScrn->virtualY;
+ pI810DRI->mem = pScrn->videoRam * 1024;
+ pI810DRI->cpp = pI810->cpp;
+
+ pI810DRI->fbOffset = pI810->FrontBuffer.Start;
+ pI810DRI->fbStride = pI810->auxPitch;
+
+ pI810DRI->bitsPerPixel = pScrn->bitsPerPixel;
+
+ pI810DRI->textureOffset = pI810->TexMem.Start;
+
+ pI810DRI->backOffset = pI810->BackBuffer.Start;
+ pI810DRI->depthOffset = pI810->DepthBuffer.Start;
+
+ pI810DRI->ringOffset = pI810->LpRing->mem.Start;
+ pI810DRI->ringSize = pI810->LpRing->mem.Size;
+
+ pI810DRI->auxPitch = pI810->auxPitch;
+ pI810DRI->auxPitchBits = pI810->auxPitchBits;
+ pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ if (!(I810InitVisualConfigs(pScreen))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810InitVisualConfigs failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] visual configs initialized.\n");
+ pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+
+ return TRUE;
+}
+
+void
+I810DRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
+
+ if (pI810DRI->irq) {
+ drmCtlUninstHandler(pI810->drmSubFD);
+ pI810DRI->irq = 0;
+ }
+
+ I810CleanupDma(pScrn);
+
+ if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
+ if (pI810->backHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->backHandle);
+ if (pI810->zHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->zHandle);
+ if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
+ if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
+ if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
+
+ if (pI810->agpAcquired == TRUE)
+ drmAgpRelease(pI810->drmSubFD);
+
+ pI810->backHandle = DRM_AGP_NO_HANDLE;
+ pI810->zHandle = DRM_AGP_NO_HANDLE;
+ pI810->cursorHandle = DRM_AGP_NO_HANDLE;
+ pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
+ pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
+
+ DRICloseScreen(pScreen);
+
+ if (pI810->pDRIInfo) {
+ if (pI810->pDRIInfo->devPrivate) {
+ free(pI810->pDRIInfo->devPrivate);
+ pI810->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = NULL;
+ }
+ if (pI810->pVisualConfigs)
+ free(pI810->pVisualConfigs);
+ if (pI810->pVisualConfigsPriv)
+ free(pI810->pVisualConfigsPriv);
+}
+
+static Bool
+I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+I810DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr info = I810PTR(pScrn);
+
+ memset(sPriv, 0, sizeof(sPriv));
+
+ /* Have shadow run only while there is 3d active.
+ */
+ if (info->allowPageFlip && info->drmMinor >= 3) {
+ ShadowFBInit( pScreen, I810DRIRefreshArea );
+ }
+ else
+ info->allowPageFlip = 0;
+ return DRIFinishScreenInit(pScreen);
+}
+
+void
+I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (syncType == DRI_3D_SYNC &&
+ oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (in)\n");
+
+ if (!pScrn->vtSema)
+ return;
+ pI810->LockHeld = 1;
+ I810RefreshRing(pScrn);
+ } else if (syncType == DRI_2D_SYNC &&
+ oldContextType == DRI_NO_CONTEXT &&
+ newContextType == DRI_2D_CONTEXT) {
+ pI810->LockHeld = 0;
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (out)\n");
+ } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (other)\n");
+}
+
+static void
+I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ BoxPtr pbox = REGION_RECTS(prgn);
+ int nbox = REGION_NUM_RECTS(prgn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRIInitBuffers\n");
+
+ I810SetupForSolidFill(pScrn, 0, GXcopy, -1);
+ while (nbox--) {
+ I810SelectBuffer(pScrn, I810_SELECT_BACK);
+ I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ /* Clear the depth buffer - uses 0xffff rather than 0.
+ */
+ pbox = REGION_RECTS(prgn);
+ nbox = REGION_NUM_RECTS(prgn);
+ I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
+ I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
+ while (nbox--) {
+ I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+ I810SelectBuffer(pScrn, I810_SELECT_FRONT);
+
+ if (pI810->AccelInfoRec)
+ pI810->AccelInfoRec->NeedToSync = TRUE;
+}
+
+/* This routine is a modified form of XAADoBitBlt with the calls to
+ * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
+ * instead of destination. My origin is upside down so the ydir cases
+ * are reversed.
+ *
+ * KW: can you believe that this is called even when a 2d window moves?
+ */
+static void
+I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index)
+{
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ BoxPtr pboxTmp, pboxNext, pboxBase;
+ DDXPointPtr pptTmp, pptNew2 = NULL;
+ int xdir, ydir;
+
+ int screenwidth = pScrn->virtualX;
+ int screenheight = pScrn->virtualY;
+
+ BoxPtr pbox = REGION_RECTS(prgnSrc);
+ int nbox = REGION_NUM_RECTS(prgnSrc);
+
+ BoxPtr pboxNew1 = NULL;
+ BoxPtr pboxNew2 = NULL;
+ DDXPointPtr pptNew1 = NULL;
+ DDXPointPtr pptSrc = &ptOldOrg;
+
+ int dx = pParent->drawable.x - ptOldOrg.x;
+ int dy = pParent->drawable.y - ptOldOrg.y;
+
+ /* If the copy will overlap in Y, reverse the order */
+ if (dy > 0) {
+ ydir = -1;
+
+ if (nbox > 1) {
+ /* Keep ordering in each band, reverse order of bands */
+ pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
+ if (!pboxNew1)
+ return;
+ pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
+ if (!pptNew1) {
+ free(pboxNew1);
+ return;
+ }
+ pboxBase = pboxNext = pbox + nbox - 1;
+ while (pboxBase >= pbox) {
+ while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
+ pboxNext--;
+ pboxTmp = pboxNext + 1;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+ while (pboxTmp <= pboxBase) {
+ *pboxNew1++ = *pboxTmp++;
+ *pptNew1++ = *pptTmp++;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew1 -= nbox;
+ pbox = pboxNew1;
+ pptNew1 -= nbox;
+ pptSrc = pptNew1;
+ }
+ } else {
+ /* No changes required */
+ ydir = 1;
+ }
+
+ /* If the regions will overlap in X, reverse the order */
+ if (dx > 0) {
+ xdir = -1;
+
+ if (nbox > 1) {
+ /*reverse orderof rects in each band */
+ pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
+ pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
+ if (!pboxNew2 || !pptNew2) {
+ if (pptNew2)
+ free(pptNew2);
+ if (pboxNew2)
+ free(pboxNew2);
+ if (pboxNew1) {
+ free(pptNew1);
+ free(pboxNew1);
+ }
+ return;
+ }
+ pboxBase = pboxNext = pbox;
+ while (pboxBase < pbox + nbox) {
+ while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1))
+ pboxNext++;
+ pboxTmp = pboxNext;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+ while (pboxTmp != pboxBase) {
+ *pboxNew2++ = *--pboxTmp;
+ *pptNew2++ = *--pptTmp;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew2 -= nbox;
+ pbox = pboxNew2;
+ pptNew2 -= nbox;
+ pptSrc = pptNew2;
+ }
+ } else {
+ /* No changes are needed */
+ xdir = 1;
+ }
+
+ /* SelectBuffer isn't really a good concept for the i810.
+ */
+ I810EmitFlush(pScrn);
+ I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
+ for (; nbox--; pbox++) {
+
+ int x1 = pbox->x1;
+ int y1 = pbox->y1;
+ int destx = x1 + dx;
+ int desty = y1 + dy;
+ int w = pbox->x2 - x1 + 1;
+ int h = pbox->y2 - y1 + 1;
+
+ if (destx < 0)
+ x1 -= destx, w += destx, destx = 0;
+ if (desty < 0)
+ y1 -= desty, h += desty, desty = 0;
+ if (destx + w > screenwidth)
+ w = screenwidth - destx;
+ if (desty + h > screenheight)
+ h = screenheight - desty;
+ if (w <= 0)
+ continue;
+ if (h <= 0)
+ continue;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n",
+ x1, y1, w, h, dx, dy);
+
+ I810SelectBuffer(pScrn, I810_SELECT_BACK);
+ I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+ I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
+ I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+ }
+ I810SelectBuffer(pScrn, I810_SELECT_FRONT);
+ I810EmitFlush(pScrn);
+
+ if (pboxNew2) {
+ free(pptNew2);
+ free(pboxNew2);
+ }
+ if (pboxNew1) {
+ free(pptNew1);
+ free(pboxNew1);
+ }
+
+ if (pI810->AccelInfoRec)
+ pI810->AccelInfoRec->NeedToSync = TRUE;
+}
+
+
+/* Use the miext/shadow module to maintain a list of dirty rectangles.
+ * These are blitted to the back buffer to keep both buffers clean
+ * during page-flipping when the 3d application isn't fullscreen.
+ *
+ * Unlike most use of the shadow code, both buffers are in video memory.
+ *
+ * An alternative to this would be to organize for all on-screen drawing
+ * operations to be duplicated for the two buffers. That might be
+ * faster, but seems like a lot more work...
+ */
+
+
+/* This should be done *before* XAA syncs or fires its buffer.
+ * Otherwise will have to fire it again???
+ */
+static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+ unsigned int br13;
+ int cpp=2;
+
+
+ /* Don't want to do this when no 3d is active and pages are
+ * right-way-round
+ */
+ if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+ return;
+
+ br13 = (pI810->auxPitch) | (0xcc << 16);
+
+ for (i = 0 ; i < num ; i++, pbox++) {
+ unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1;
+ unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1;
+ unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch);
+
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+ OUT_RING(br13);
+ OUT_RING( (h<<16) | (w*cpp) );
+ OUT_RING(pI810->BackBuffer.Start + dst);
+ OUT_RING(br13 & 0xffff);
+ OUT_RING(dst);
+
+ ADVANCE_LP_RING();
+ }
+
+}
+
+static void I810EnablePageFlip(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+ int cpp=2;
+ pSAREAPriv->pf_enabled = pI810->allowPageFlip;
+ pSAREAPriv->pf_active = 0;
+
+ if (pI810->allowPageFlip) {
+ unsigned int br13 = pI810->auxPitch | (0xcc << 16);
+
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+ OUT_RING(br13);
+ OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp));
+ OUT_RING(pI810->BackBuffer.Start);
+ OUT_RING(br13 & 0xFFFF);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ pSAREAPriv->pf_active = 1;
+ }
+
+}
+
+static void I810DisablePageFlip(ScreenPtr pScreen)
+{
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ pSAREAPriv->pf_active=0;
+}
+
+static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen)
+{
+ /* Tell the clients not to pageflip. How?
+ * -- Field in sarea, plus bumping the window counters.
+ * -- DRM needs to cope with Front-to-Back swapbuffers.
+ */
+ I810DisablePageFlip(pScreen);
+}
+
+static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen)
+{
+ /* Let the remaining 3d app start page flipping again */
+ I810EnablePageFlip(pScreen);
+}
+
+static void I810DRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ I810EnablePageFlip(pScreen);
+ pI810->have3DWindows = 1;
+}
+
+static void I810DRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ /* Try flipping back to the front page if necessary */
+ if (pSAREAPriv->pf_current_page == 1)
+ drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP);
+
+ /* Shut down shadowing if we've made it back to the front page */
+ if (pSAREAPriv->pf_current_page == 0) {
+ I810DisablePageFlip(pScreen);
+ }
+ pI810->have3DWindows = 0;
+}
+
+Bool
+I810DRILeave(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->directRenderingEnabled) {
+ if (pI810->dcacheHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->backHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->zHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->sysmemHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->xvmcHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->cursorHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->cursorARGBHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->agpAcquired == TRUE)
+ drmAgpRelease(pI810->drmSubFD);
+ pI810->agpAcquired = FALSE;
+ }
+ return TRUE;
+}
+
+Bool
+I810DRIEnter(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->directRenderingEnabled) {
+
+ if (pI810->agpAcquired == FALSE)
+ drmAgpAcquire(pI810->drmSubFD);
+ pI810->agpAcquired = TRUE;
+ if (pI810->dcacheHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
+ pI810->DepthOffset) != 0)
+ return FALSE;
+ if (pI810->backHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
+ pI810->BackOffset) != 0)
+ return FALSE;
+ if (pI810->zHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
+ pI810->DepthOffset) != 0)
+ return FALSE;
+ if (pI810->sysmemHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0)
+ return FALSE;
+ if (pI810->xvmcHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
+ pI810->MC.Start) != 0)
+ return FALSE;
+ if (pI810->cursorHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
+ pI810->CursorStart) != 0)
+ return FALSE;
+ if (pI810->cursorARGBHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle,
+ pI810->CursorARGBStart) != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/legacy/i810/i810_dri.h b/src/legacy/i810/i810_dri.h
new file mode 100644
index 00000000..16b6f087
--- /dev/null
+++ b/src/legacy/i810/i810_dri.h
@@ -0,0 +1,131 @@
+
+#ifndef _I810_DRI_
+#define _I810_DRI_
+
+#include "xf86drm.h"
+#include "i810_common.h"
+
+#define I810_MAX_DRAWABLES 256
+
+#define I810_MAJOR_VERSION 1
+#define I810_MINOR_VERSION 7
+#define I810_PATCHLEVEL 4
+
+typedef struct {
+ drm_handle_t regs;
+ drmSize regsSize;
+
+ drmSize backbufferSize;
+ drm_handle_t backbuffer;
+
+ drmSize depthbufferSize;
+ drm_handle_t depthbuffer;
+
+ drm_handle_t textures;
+ int textureSize;
+
+ drm_handle_t agp_buffers;
+ drmSize agp_buf_size;
+
+ int deviceID;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+ int bitsPerPixel;
+ int fbOffset;
+ int fbStride;
+
+ int backOffset;
+ int depthOffset;
+
+ int auxPitch;
+ int auxPitchBits;
+
+ int logTextureGranularity;
+ int textureOffset;
+
+ /* For non-dma direct rendering.
+ */
+ int ringOffset;
+ int ringSize;
+
+ drmBufMapPtr drmBufs;
+ int irq;
+ unsigned int sarea_priv_offset;
+
+} I810DRIRec, *I810DRIPtr;
+
+/* WARNING: Do not change the SAREA structure without changing the kernel
+ * as well */
+
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_CTX 0x4
+#define I810_UPLOAD_BUFFERS 0x8
+#define I810_UPLOAD_TEX0 0x10
+#define I810_UPLOAD_TEX1 0x20
+#define I810_UPLOAD_CLIPRECTS 0x40
+
+typedef struct {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} I810TexRegionRec, *I810TexRegionPtr;
+
+typedef struct {
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+
+ /* Maintain an LRU of contiguous regions of texture space. If
+ * you think you own a region of texture memory, and it has an
+ * age different to the one you set, then you are mistaken and
+ * it has been stolen by another client. If global texAge
+ * hasn't changed, there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained
+ * texture information of other clients - by maintaining them
+ * in the same lru which is used to age their own textures,
+ * clients have an approximate lru for the whole of global
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+ * them all in LRU order.
+ */
+
+ drmTextureRegion texList[I810_NR_TEX_REGIONS + 1];
+
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+
+ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+ int last_quiescent; /* */
+
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active; /* is pageflipping active right now? */
+ int pf_current_page; /* which buffer is being displayed? */
+
+
+} I810SAREARec, *I810SAREAPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I810ConfigPrivRec, *I810ConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I810DRIContextRec, *I810DRIContextPtr;
+
+#endif
diff --git a/src/legacy/i810/i810_driver.c b/src/legacy/i810/i810_driver.c
new file mode 100644
index 00000000..3fc9d044
--- /dev/null
+++ b/src/legacy/i810/i810_driver.c
@@ -0,0 +1,2121 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ */
+
+/*
+ * This server does not support these XFree86 4.0 features yet
+ * shadowFb (if requested or acceleration is off)
+ * Overlay planes
+ * DGA
+ */
+
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * These are X and server generic header files.
+ */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86cmap.h"
+
+#include "compiler.h"
+#include "mibstore.h"
+#include "vgaHW.h"
+#include "mipointer.h"
+#include "micmap.h"
+
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "vbe.h"
+
+#include "i810.h"
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+#include "../legacy.h"
+
+static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
+static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool I810EnterVT(int scrnIndex, int flags);
+static void I810LeaveVT(int scrnIndex, int flags);
+static Bool I810CloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank);
+static void I810FreeScreen(int scrnIndex, int flags);
+static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagermentMode,
+ int flags);
+static ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flags);
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_COLOR_KEY,
+ OPTION_CACHE_LINES,
+ OPTION_DAC_6BIT,
+ OPTION_DRI,
+ OPTION_NO_DDC,
+ OPTION_SHOW_CACHE,
+ OPTION_XVMC_SURFACES,
+ OPTION_PAGEFLIP
+} I810Opts;
+
+static const OptionInfoRec I810Options[] = {
+ {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+/* *INDENT-ON* */
+
+#ifndef I810_DEBUG
+int I810_DEBUG = (0
+/* | DEBUG_ALWAYS_SYNC */
+/* | DEBUG_VERBOSE_ACCEL */
+/* | DEBUG_VERBOSE_SYNC */
+/* | DEBUG_VERBOSE_VGA */
+/* | DEBUG_VERBOSE_RING */
+/* | DEBUG_VERBOSE_OUTREG */
+/* | DEBUG_VERBOSE_MEMORY */
+/* | DEBUG_VERBOSE_CURSOR */
+ );
+#endif
+
+#ifdef XF86DRI
+static int i810_pitches[] = {
+ 512,
+ 1024,
+ 2048,
+ 4096,
+ 0
+};
+#endif
+
+int I830EntityIndex = -1;
+
+/*
+ * I810GetRec and I810FreeRec --
+ *
+ * Private data for the driver is stored in the screen structure.
+ * These two functions create and destroy that private data.
+ *
+ */
+static Bool
+I810GetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1);
+ return TRUE;
+}
+
+static void
+I810FreeRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn)
+ return;
+ if (!pScrn->driverPrivate)
+ return;
+ free(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+struct pci_device *
+intel_host_bridge (void)
+{
+ static const struct pci_slot_match bridge_match = {
+ 0, 0, 0, PCI_MATCH_ANY, 0
+ };
+ struct pci_device_iterator *slot_iterator;
+ struct pci_device *bridge;
+
+ slot_iterator = pci_slot_match_iterator_create (&bridge_match);
+ bridge = pci_device_next (slot_iterator);
+ pci_iterator_destroy (slot_iterator);
+ return bridge;
+}
+
+static void
+I810ProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+static xf86MonPtr
+I810DoDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ xf86MonPtr MonInfo = NULL;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ /* Honour Option "noDDC" */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) {
+ return MonInfo;
+ }
+
+ if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
+ MonInfo = vbeDoEDID(pVbe, NULL);
+ xf86PrintEDID(MonInfo);
+ xf86SetDDCproperties(pScrn, MonInfo);
+ vbeFree(pVbe);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "this driver cannot do DDC without VBE\n");
+ }
+
+ return MonInfo;
+}
+
+/*
+ * I810PreInit --
+ *
+ * Do initial setup of the board before we know what resolution we will
+ * be running at.
+ *
+ */
+static Bool
+I810PreInit(ScrnInfoPtr pScrn, int flags)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+ ClockRangePtr clockRanges;
+ int i;
+ MessageType from;
+ int flags24;
+ rgb defaultWeight = { 0, 0, 0 };
+ int mem;
+ Bool enable;
+ struct intel_chipset chipset;
+
+ if (pScrn->numEntities != 1)
+ return FALSE;
+
+ /* Allocate driverPrivate */
+ if (!I810GetRec(pScrn))
+ return FALSE;
+
+ pI810 = I810PTR(pScrn);
+
+ pI810->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pI810->pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ if (flags & PROBE_DETECT) {
+ I810ProbeDDC(pScrn, pI810->pEnt->index);
+ return TRUE;
+ }
+
+ /* The vgahw module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ /* Allocate a vgaHWRec */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+ hwp = VGAHWPTR(pScrn);
+ pI810->ioBase = hwp->PIOOffset;
+
+ pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
+ if (!xf86SetDepthBpp(pScrn, 16, 0, 16, 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 i810 driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given bpp (%d) is not supported by i810 driver\n",
+ pScrn->bitsPerPixel);
+ return FALSE;
+ }
+
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
+ return FALSE;
+
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return FALSE;
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ pI810->cpp = pScrn->bitsPerPixel / 8;
+
+ /* Process the options */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(pI810->Options = malloc(sizeof(I810Options))))
+ return FALSE;
+ memcpy(pI810->Options, I810Options, sizeof(I810Options));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options);
+
+ pScrn->rgbBits = 8;
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
+ pScrn->rgbBits = 6;
+
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE))
+ pI810->showCache = TRUE;
+ else
+ pI810->showCache = FALSE;
+
+ /* 6-BIT dac isn't reasonable for modes with > 8bpp */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) &&
+ pScrn->bitsPerPixel > 8) {
+ OptionInfoPtr ptr;
+
+ ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT);
+ ptr->found = FALSE;
+ }
+
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
+ pI810->noAccel = TRUE;
+
+ if (!pI810->noAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+#ifdef XF86DRI
+ pI810->directRenderingDisabled =
+ !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
+
+ if (!pI810->directRenderingDisabled) {
+ if (pI810->noAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
+ "needs 2D acceleration.\n");
+ pI810->directRenderingDisabled=TRUE;
+ } else if (pScrn->depth!=16) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
+ "runs only at 16-bit depth.\n");
+ pI810->directRenderingDisabled=TRUE;
+ }
+ }
+#endif
+
+ /* Get DDC info from monitor */
+ /* after xf86ProcessOptions,
+ * because it is controlled by options [no]vbe and [no]ddc
+ */
+ I810DoDDC(pScrn, pI810->pEnt->index);
+
+ /* We have to use PIO to probe, because we haven't mapped yet */
+ I810SetPIOAccess(pI810);
+
+ intel_detect_chipset(pScrn, pI810->PciInfo, &chipset);
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pI810->pEnt->device->chipset && *pI810->pEnt->device->chipset) {
+ pScrn->chipset = pI810->pEnt->device->chipset;
+ from = X_CONFIG;
+ } else if (pI810->pEnt->device->chipID >= 0) {
+ pScrn->chipset = (char *)xf86TokenToString(intel_chipsets,
+ pI810->pEnt->device->chipID);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pI810->pEnt->device->chipID);
+ } else {
+ from = X_PROBED;
+ pScrn->chipset = (char *)xf86TokenToString(intel_chipsets,
+ DEVICE_ID(pI810->PciInfo));
+ }
+ if (pI810->pEnt->device->chipRev >= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pI810->pEnt->device->chipRev);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
+ (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
+
+ pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr;
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pI810->LinearAddr);
+
+ pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr;
+ xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
+ (unsigned long)pI810->MMIOAddr);
+
+ /* AGP GART support is required. Don't proceed any further if it isn't
+ * present.
+ */
+ if (!xf86AgpGARTSupported()) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "AGP GART support is not available. Make sure your kernel has\n"
+ "\tagpgart support or that the agpgart kernel module is loaded.\n");
+ return FALSE;
+ }
+
+ /* Find out memory bus frequency.
+ */
+ {
+ uint32_t whtcfg_pamr_drp;
+
+ pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP);
+
+ /* Need this for choosing watermarks.
+ */
+ if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133)
+ pI810->LmFreqSel = 133;
+ else
+ pI810->LmFreqSel = 100;
+ }
+
+ /* Default to 4MB framebuffer, which is sufficient for all
+ * supported 2d resolutions. If the user has specified a different
+ * size in the XF86Config, use that amount instead.
+ *
+ * Changed to 8 Meg so we can have acceleration by default (Mark).
+ */
+ mem = I810CheckAvailableMemory(pScrn);
+ if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */
+ pScrn->videoRam = 8192;
+ else if (mem < 196608)
+ pScrn->videoRam = 16384; /* < 192 MB */
+ else
+ pScrn->videoRam = 24576;
+
+ from = X_DEFAULT;
+
+ if (pI810->pEnt->device->videoRam) {
+ pScrn->videoRam = pI810->pEnt->device->videoRam;
+ from = X_CONFIG;
+ }
+
+ if (mem > 0 && mem < pScrn->videoRam) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
+ " but the\n\t maximum AGP memory available is %dk.\n",
+ pScrn->videoRam, mem);
+ from = X_PROBED;
+ if (mem > (6 * 1024)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Reducing video memory to 4MB\n");
+ pScrn->videoRam = 4096;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
+ " is available. Cannot proceed.\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam);
+
+ /* Calculate Fixed Offsets depending on graphics aperture size */
+ {
+ struct pci_device *bridge = intel_host_bridge ();
+ uint32_t smram_miscc;
+
+ pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC);
+
+ if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
+ pI810->FbMapSize = 0x1000000;
+ pI810->DepthOffset = 0x1000000;
+ pI810->BackOffset = 0x1800000;
+ } else {
+ pI810->FbMapSize = 0x3000000;
+ pI810->DepthOffset = 0x3000000;
+ pI810->BackOffset = 0x3800000;
+ }
+ }
+
+ /*
+ * 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;
+ }
+ }
+
+ pI810->MaxClock = 0;
+ if (pI810->pEnt->device->dacSpeeds[0]) {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8];
+ break;
+ case 16:
+ pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16];
+ break;
+ case 24:
+ pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24];
+ break;
+ case 32: /* not supported */
+ pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32];
+ break;
+ }
+ if (!pI810->MaxClock)
+ pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0];
+ } else {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pI810->MaxClock = 203000;
+ break;
+ case 16:
+ pI810->MaxClock = 163000;
+ break;
+ case 24:
+ pI810->MaxClock = 136000;
+ break;
+ case 32: /* not supported */
+ pI810->MaxClock = 86000;
+ }
+ }
+ clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next = NULL;
+ /* 9.4MHz appears to be the smallest that works. */
+ clockRanges->minClock = 9500;
+ clockRanges->maxClock = pI810->MaxClock;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = FALSE;
+
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+#ifndef XF86DRI
+ 0, 320, 1600, 64 * pScrn->bitsPerPixel,
+#else
+ i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel,
+#endif
+ 200, 1200,
+ pScrn->display->virtualX, pScrn->display->virtualY,
+ pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
+
+ if (i == -1) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (!i || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ pScrn->currentMode = pScrn->modes;
+
+ xf86PrintModes(pScrn);
+
+ xf86SetDpi(pScrn, 0, 0);
+
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+
+ if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+ if (xf86GetOptValInteger
+ (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "video overlay key set to 0x%x\n", pI810->colorKey);
+ } else {
+ pI810->colorKey = (1 << pScrn->offset.red) |
+ (1 << pScrn->offset.green) |
+ (((pScrn->mask.blue >> pScrn->offset.blue) -
+ 1) << pScrn->offset.blue);
+ }
+
+ pI810->allowPageFlip=FALSE;
+ enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
+
+#ifdef XF86DRI
+ if (!pI810->directRenderingDisabled) {
+ pI810->allowPageFlip = enable;
+ if (pI810->allowPageFlip == TRUE)
+ {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ pI810->allowPageFlip = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't load shadowfb module:\n");
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
+ enable ? "enabled" : "disabled");
+
+ }
+#endif
+
+ if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
+ &(pI810->numSurfaces))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
+ pI810->numSurfaces);
+ if (pI810->numSurfaces > 7) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using 7 XvMC Surfaces (Maximum Allowed).\n");
+ pI810->numSurfaces = 7;
+ }
+ if (pI810->numSurfaces < 6) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using 6 XvMC Surfaces (Minimum Allowed).\n");
+ pI810->numSurfaces = 6;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
+ pI810->numSurfaces = 0;
+ }
+
+#ifdef XF86DRI
+ /* Load the dri module if requested. */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
+ xf86LoadSubModule(pScrn, "dri");
+ }
+#endif
+
+ /* We won't be using the VGA access after the probe */
+ I810SetMMIOAccess(pI810);
+ return TRUE;
+}
+
+static Bool
+I810MapMMIO(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ struct pci_device *const device = pI810->PciInfo;
+ int err;
+
+ err = pci_device_map_range (device,
+ pI810->MMIOAddr,
+ I810_REG_SIZE,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ (void **) &pI810->MMIOBase);
+ if (err)
+ {
+ xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+ "Unable to map mmio BAR. %s (%d)\n",
+ strerror (err), err);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+I810MapMem(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ struct pci_device *const device = pI810->PciInfo;
+ int err;
+
+ if (!I810MapMMIO(pScrn))
+ return FALSE;
+
+ err = pci_device_map_range (device,
+ pI810->LinearAddr,
+ pI810->FbMapSize,
+ PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
+ (void **) &pI810->FbBase);
+ if (err)
+ {
+ xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+ "Unable to map frame buffer BAR. %s (%d)\n",
+ strerror (err), err);
+ return FALSE;
+ }
+
+ pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
+
+ return TRUE;
+}
+
+static void
+I810UnmapMMIO(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE);
+ pI810->MMIOBase = NULL;
+}
+
+static Bool
+I810UnmapMem(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize);
+ pI810->FbBase = NULL;
+ I810UnmapMMIO(pScrn);
+ return TRUE;
+}
+
+/* Famous last words
+ */
+void
+I810PrintErrorState(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+ (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR));
+
+ ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR),
+ (unsigned long) INREG(IPEHR));
+
+ ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+ (unsigned long) INREG(LP_RING + RING_TAIL),
+ (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+ (unsigned long) INREG(LP_RING + RING_LEN),
+ (unsigned long) INREG(LP_RING + RING_START));
+
+ ErrorF("eir: %x esr: %x emr: %x\n",
+ INREG16(EIR), INREG16(ESR), INREG16(EMR));
+
+ ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
+
+ ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE),
+ (unsigned long) INREG(INST_PS));
+
+ ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
+ INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
+}
+
+/*
+ * I810Save --
+ *
+ * This function saves the video state. It reads all of the SVGA registers
+ * into the vgaI810Rec data structure. There is in general no need to
+ * mask out bits here - just read the registers.
+ */
+static void
+DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
+ Bool saveFonts)
+{
+ I810Ptr pI810;
+ vgaHWPtr hwp;
+ int i;
+
+ pI810 = I810PTR(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 | VGA_SR_CMAP);
+ else
+ vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
+
+ /*
+ * The port I/O code necessary to read in the extended registers
+ * into the fields of the vgaI810Rec structure goes here.
+ */
+ i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL);
+ i810Reg->AddressMapping = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
+ i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
+ i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
+ i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
+ i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
+
+ i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL);
+ i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
+ i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
+ i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
+ i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
+ i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
+ i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET);
+ i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL);
+
+ i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
+ i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
+ i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
+ i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
+ i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
+
+ for (i = 0; i < 8; i++)
+ i810Reg->Fence[i] = INREG(FENCE + i * 4);
+
+ i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
+ i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
+ i810Reg->LprbStart = INREG(LP_RING + RING_START);
+ i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
+
+ if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
+ i810Reg->LprbLen & RING_VALID) {
+ I810PrintErrorState(pScrn);
+ FatalError("Active ring not flushed\n");
+ }
+}
+
+static void
+I810Save(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+ uint32_t temp;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+ DoSave(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
+
+ temp = INREG(MEMMODE);
+ temp |= 4;
+ OUTREG(MEMMODE, temp);
+}
+
+static void
+i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode)
+{
+ int i;
+
+ ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg);
+
+ ErrorF("SEQ: ");
+ for (i = 0; i < vgaReg->numSequencer; i++) {
+ if ((i & 7) == 0)
+ ErrorF("\n");
+ ErrorF(" %d: %x", i, vgaReg->Sequencer[i]);
+ }
+ ErrorF("\n");
+
+ ErrorF("CRTC: ");
+ for (i = 0; i < vgaReg->numCRTC; i++) {
+ if ((i & 3) == 0)
+ ErrorF("\n");
+ ErrorF(" %d: %x", i, vgaReg->CRTC[i]);
+ }
+ ErrorF("\n");
+
+ ErrorF("GFX: ");
+ for (i = 0; i < vgaReg->numGraphics; i++) {
+ if ((i & 7) == 0)
+ ErrorF("\n");
+ ErrorF(" %d: %x", i, vgaReg->Graphics[i]);
+ }
+ ErrorF("\n");
+
+ ErrorF("ATTR: ");
+ for (i = 0; i < vgaReg->numAttribute; i++) {
+ if ((i & 7) == 0)
+ ErrorF("\n");
+ ErrorF(" %d: %x", i, vgaReg->Attribute[i]);
+ }
+ ErrorF("\n");
+
+ ErrorF(" DisplayControl: %x\n", mode->DisplayControl);
+ ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
+ ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
+ ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
+ ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M);
+ ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N);
+ ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
+ ErrorF(" AddressMapping: %x\n", mode->AddressMapping);
+ ErrorF(" IOControl: %x\n", mode->IOControl);
+ ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl);
+ ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal);
+ ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
+ ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
+ ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
+ ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal);
+ ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank);
+ ErrorF(" ExtOffset: %x\n", mode->ExtOffset);
+ ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl);
+ ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
+ ErrorF(" LprbTail: %x\n", mode->LprbTail);
+ ErrorF(" LprbHead: %x\n", mode->LprbHead);
+ ErrorF(" LprbStart: %x\n", mode->LprbStart);
+ ErrorF(" LprbLen: %x\n", mode->LprbLen);
+}
+
+static void
+DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
+ Bool restoreFonts)
+{
+ I810Ptr pI810;
+ vgaHWPtr hwp;
+ unsigned char temp;
+ unsigned int itemp;
+ int i;
+
+ pI810 = I810PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
+ ErrorF("Setting mode in I810Restore:\n");
+ i810PrintMode(vgaReg, i810Reg);
+ }
+
+ vgaHWProtect(pScrn, TRUE);
+
+ usleep(50000);
+
+ /* Turn off DRAM Refresh */
+ temp = INREG8(DRAM_ROW_CNTL_HI);
+ temp &= ~DRAM_REFRESH_RATE;
+ temp |= DRAM_REFRESH_DISABLE;
+ OUTREG8(DRAM_ROW_CNTL_HI, temp);
+
+ usleep(1000); /* Wait 1 ms */
+
+ /* Write the M, N and P values */
+ OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M);
+ OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N);
+ OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->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 = INREG8(PIXPIPE_CONFIG_0);
+ temp &= 0x7F; /* Save all but the 8 bit dac mode bit */
+ temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
+ OUTREG8(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 (i810Reg->std.NoClock >= 0)
+ * restore clock-select bits.
+ */
+ if (restoreFonts)
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
+ else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
+
+ hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
+ hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
+ hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
+ hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
+ hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
+ hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
+ hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);
+
+ temp = hwp->readCrtc(hwp, INTERLACE_CNTL);
+ temp &= ~INTERLACE_ENABLE;
+ temp |= i810Reg->InterlaceControl;
+ hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
+
+ temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
+ temp &= 0xE0; /* Save reserved bits 7:5 */
+ temp |= i810Reg->AddressMapping;
+ pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp);
+
+ /* Setting the OVRACT Register for video overlay */
+ {
+ uint32_t LCD_TV_Control = INREG(LCD_TV_C);
+ uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL);
+ uint32_t ActiveStart, ActiveEnd;
+
+ if((LCD_TV_Control & LCD_TV_ENABLE)
+ && !(LCD_TV_Control & LCD_TV_VGAMOD)
+ && TV_HTotal) {
+ ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
+ ActiveEnd = (TV_HTotal & 0x3ff) - 31;
+ } else {
+ ActiveStart = i810Reg->OverlayActiveStart;
+ ActiveEnd = i810Reg->OverlayActiveEnd;
+ }
+ OUTREG(LCD_TV_OVRACT,
+ (ActiveEnd << 16) | ActiveStart);
+ }
+
+ /* Turn on DRAM Refresh */
+ temp = INREG8(DRAM_ROW_CNTL_HI);
+ temp &= ~DRAM_REFRESH_RATE;
+ temp |= DRAM_REFRESH_60HZ;
+ OUTREG8(DRAM_ROW_CNTL_HI, temp);
+
+ temp = INREG8(BITBLT_CNTL);
+ temp &= ~COLEXP_MODE;
+ temp |= i810Reg->BitBLTControl;
+ OUTREG8(BITBLT_CNTL, temp);
+
+ temp = INREG8(DISPLAY_CNTL);
+ temp &= ~(VGA_WRAP_MODE | GUI_MODE);
+ temp |= i810Reg->DisplayControl;
+ OUTREG8(DISPLAY_CNTL, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_0);
+ temp &= 0x64; /* Save reserved bits 6:5,2 */
+ temp |= i810Reg->PixelPipeCfg0;
+ OUTREG8(PIXPIPE_CONFIG_0, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_2);
+ temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
+ temp |= i810Reg->PixelPipeCfg2;
+ OUTREG8(PIXPIPE_CONFIG_2, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_1);
+ temp &= ~DISPLAY_COLOR_MODE;
+ temp &= 0xEF; /* Restore the CRT control bit */
+ temp |= i810Reg->PixelPipeCfg1;
+ OUTREG8(PIXPIPE_CONFIG_1, temp);
+
+ OUTREG16(EIR, 0);
+
+ itemp = INREG(FWATER_BLC);
+ itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
+ MM_BURST_LENGTH | MM_FIFO_WATERMARK);
+ itemp |= i810Reg->LMI_FIFO_Watermark;
+ OUTREG(FWATER_BLC, itemp);
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
+ }
+
+ /* First disable the ring buffer (Need to wait for empty first?, if so
+ * should probably do it before entering this section)
+ */
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~RING_VALID_MASK;
+ OUTREG(LP_RING + RING_LEN, itemp);
+
+ /* Set up the low priority ring buffer.
+ */
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ pI810->LpRing->head = 0;
+ pI810->LpRing->tail = 0;
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= i810Reg->LprbStart;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= i810Reg->LprbLen;
+ OUTREG(LP_RING + RING_LEN, itemp);
+
+ if (!(vgaReg->Attribute[0x10] & 0x1)) {
+ usleep(50000);
+ if (restoreFonts)
+ vgaHWRestore(pScrn, vgaReg,
+ VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
+ else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+
+ temp = hwp->readCrtc(hwp, IO_CTNL);
+ temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+ temp |= i810Reg->IOControl;
+ hwp->writeCrtc(hwp, IO_CTNL, temp);
+}
+
+static void
+I810SetRingRegs(ScrnInfoPtr pScrn)
+{
+ unsigned int itemp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= pI810->LpRing->mem.Start;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
+ OUTREG(LP_RING + RING_LEN, itemp);
+}
+
+static void
+I810Restore(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+
+ DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
+}
+
+/*
+ * I810CalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+
+#define MAX_VCO_FREQ 600.0
+#define TARGET_MAX_N 30
+#define REF_FREQ 24.0
+
+#define CALC_VCLK(m,n,p) \
+ (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
+
+static void
+I810CalcVCLK(ScrnInfoPtr pScrn, double freq)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ int m, n, p;
+ double f_out;
+ double f_err;
+ double f_vco;
+ int m_best = 0, n_best = 0, p_best = 0;
+ double f_target = freq;
+ double err_max = 0.005;
+ double err_target = 0.001;
+ double err_best = 999999.0;
+
+ p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);
+ /* Make sure p is within range. */
+ if (p_best > 5) {
+ p_best = p = 5;
+ }
+
+ 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);
+ 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;
+ }
+
+ i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;
+ i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;
+ i810Reg->VideoClk2_DivisorSel = (p_best << 4);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
+ "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
+ i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
+ i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
+}
+
+static Bool
+I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
+ double dclk = mode->Clock / 1000.0;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
+ i810Reg->ExtOffset = pScrn->displayWidth >> 11;
+ i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_8BPP;
+ break;
+ case 16:
+ if (pScrn->weight.green == 5) {
+ i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
+ } else {
+ i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
+ }
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
+ i810Reg->ExtOffset = pScrn->displayWidth >> 10;
+ i810Reg->BitBLTControl = COLEXP_16BPP;
+
+ /* Enable Palette Programming for Direct Color visuals. -jens */
+ i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
+ break;
+ case 24:
+ pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
+ i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
+
+ i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_24BPP;
+
+ /* Enable Palette Programming for Direct Color visuals. -jens */
+ i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
+ break;
+ default:
+ break;
+ }
+
+ /* Turn on 8 bit dac if requested */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
+ i810Reg->PixelPipeCfg0 = DAC_6_BIT;
+ else
+ i810Reg->PixelPipeCfg0 = DAC_8_BIT;
+
+ /* Do not delay CRT Blank: needed for video overlay */
+ i810Reg->PixelPipeCfg1 |= 0x10;
+
+ /* Turn on Extended VGA Interpretation */
+ i810Reg->IOControl = EXTENDED_CRTC_CNTL;
+
+ /* Turn on linear and page mapping */
+ i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
+
+ /* Turn on GUI mode */
+ i810Reg->DisplayControl = HIRES_MODE;
+
+ /* Calculate the extended CRTC regs */
+ i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
+ i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
+ i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
+ i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
+ i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
+ i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
+
+ /*
+ * 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 i810
+ * to be blank. Restoring CRTC 3, 5, & 22 to their
+ * "theoretical" values corrects the problem. KAO.
+ */
+ pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
+ pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
+ | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
+ pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
+
+ i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
+ vgaHWVBlankKGA(mode, pVga, 8, 0);
+
+ /*
+ * The following workarounds are needed to get video overlay working
+ * at 1024x768 and 1280x1024 display resolutions.
+ */
+ if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
+ i810Reg->ExtVertBlankStart = 2;
+ }
+ if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
+ i810Reg->ExtVertBlankStart = 3;
+ }
+
+ /* OVRACT Register */
+ i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
+ i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
+
+ /* Turn on interlaced mode if necessary */
+ if (mode->Flags & V_INTERLACE) {
+ i810Reg->InterlaceControl = INTERLACE_ENABLE;
+ i810Reg->ExtVertDispEnd *= 2;
+ } else
+ i810Reg->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.
+ */
+ I810CalcVCLK(pScrn, dclk);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ pVga->MiscOutReg |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);
+
+ /* Setup the ring buffer */
+ i810Reg->LprbTail = 0;
+ i810Reg->LprbHead = 0;
+ i810Reg->LprbStart = pI810->LpRing->mem.Start;
+
+ if (i810Reg->LprbStart)
+ i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |
+ RING_NO_REPORT | RING_VALID);
+ else
+ i810Reg->LprbLen = RING_INVALID;
+
+ return TRUE;
+}
+
+static Bool
+I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+
+ vgaHWUnlock(hwp);
+
+ if (!vgaHWInit(pScrn, mode))
+ return FALSE;
+
+ pScrn->vtSema = TRUE;
+
+ if (!I810SetMode(pScrn, mode))
+ return FALSE;
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+#endif
+
+ DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+#endif
+
+ return TRUE;
+}
+
+static void
+I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ vgaHWPtr hwp;
+ int i, j, index;
+ unsigned char r, g, b;
+
+ hwp = VGAHWPTR(pScrn);
+
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ r = colors[index].red;
+ g = colors[index].green;
+ b = colors[index].blue;
+ for (j = 0; j < 8; j++) {
+ hwp->writeDacWriteAddr(hwp, (index << 3) + j);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+ }
+}
+
+static void
+I810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ hwp = VGAHWPTR(pScrn);
+
+ /* Load all four entries in each of the 64 color ranges. -jens */
+ 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);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
+ 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);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+
+ hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+}
+
+static void
+I810LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ hwp = VGAHWPTR(pScrn);
+
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ r = colors[index].red;
+ g = colors[index].green;
+ b = colors[index].blue;
+ hwp->writeDacWriteAddr(hwp, index);
+ hwp->writeDacData(hwp, r);
+ hwp->writeDacData(hwp, g);
+ hwp->writeDacData(hwp, b);
+ }
+}
+
+Bool
+I810AllocateFront(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int cache_lines = -1;
+
+ if (pI810->DoneFrontAlloc)
+ return TRUE;
+
+ memset(&(pI810->FbMemBox), 0, sizeof(BoxRec));
+ /* Alloc FrontBuffer/Ring/Accel memory */
+ pI810->FbMemBox.x1 = 0;
+ pI810->FbMemBox.x2 = pScrn->displayWidth;
+ pI810->FbMemBox.y1 = 0;
+ pI810->FbMemBox.y2 = pScrn->virtualY;
+
+ xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines);
+
+ if (cache_lines < 0) {
+ /* make sure there is enough for two DVD sized YUV buffers */
+ cache_lines = (pScrn->depth == 24) ? 256 : 384;
+ if (pScrn->displayWidth <= 1024)
+ cache_lines *= 2;
+ }
+ /* Make sure there's enough space for cache_lines.
+ *
+ * Had a bug here where maxCacheLines was computed to be less than 0.
+ * Not sure why 256 was initially subtracted from videoRam in the
+ * maxCacheLines calculation, but that was causing a problem
+ * for configurations that have exactly enough Ram for the framebuffer.
+ * Common code should catch the case where there isn't enough space for
+ * framebuffer, we'll just check for no space for cache_lines. -jens
+ *
+ */
+ {
+ int maxCacheLines;
+
+ maxCacheLines = (pScrn->videoRam * 1024 /
+ (pScrn->bitsPerPixel / 8) /
+ pScrn->displayWidth) - pScrn->virtualY;
+ if (maxCacheLines < 0)
+ maxCacheLines = 0;
+ if (cache_lines > maxCacheLines)
+ cache_lines = maxCacheLines;
+ }
+ pI810->FbMemBox.y2 += cache_lines;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Adding %i scanlines for pixmap caching\n", cache_lines);
+
+ /* Reserve room for the framebuffer and pixcache. Put at the top
+ * of memory so we can have nice alignment for the tiled regions at
+ * the start of memory.
+ */
+
+ if (!I810AllocLow(&(pI810->FrontBuffer),
+ &(pI810->SysMem),
+ ((pI810->FbMemBox.x2 *
+ pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095)) {
+ xf86DrvMsg(pScrn->scrnIndex,
+ X_WARNING, "Framebuffer allocation failed\n");
+ return FALSE;
+ }
+
+ memset(pI810->LpRing, 0, sizeof(I810RingBuffer));
+ if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) {
+ pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1;
+ pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
+ pI810->LpRing->head = 0;
+ pI810->LpRing->tail = 0;
+ pI810->LpRing->space = 0;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Ring buffer allocation failed\n");
+ return (FALSE);
+ }
+
+ if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) ||
+ I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Scratch memory allocation failed\n");
+ return (FALSE);
+ }
+
+ pI810->DoneFrontAlloc = TRUE;
+ return TRUE;
+}
+
+static Bool
+I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+ VisualPtr visual;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI810 = I810PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ pI810->LpRing = calloc(sizeof(I810RingBuffer),1);
+ if (!pI810->LpRing) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Could not allocate lpring data structure.\n");
+ return FALSE;
+ }
+
+ miClearVisualTypes();
+
+ /* Re-implemented Direct Color support, -jens */
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths())
+ return FALSE;
+
+ {
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ i810Reg->Fence[i] = 0;
+ }
+
+ /* Have to init the DRM earlier than in other drivers to get agp
+ * memory. Wonder if this is going to be a problem...
+ */
+
+#ifdef XF86DRI
+ /*
+ * Setup DRI after visuals have been established, but before fbScreenInit
+ * is called. fbScreenInit will eventually call into the drivers
+ * InitGLXVisuals call back.
+ */
+ /*
+ * pI810->directRenderingDisabled is set once in PreInit. Reinitialise
+ * pI810->directRenderingEnabled based on it each generation.
+ */
+ pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
+
+ if (pI810->directRenderingEnabled==TRUE)
+ pI810->directRenderingEnabled = I810DRIScreenInit(pScreen);
+
+#else
+ pI810->directRenderingEnabled = FALSE;
+ if (!I810AllocateGARTMemory(pScrn))
+ return FALSE;
+ if (!I810AllocateFront(pScrn))
+ return FALSE;
+#endif
+
+ if (!I810MapMem(pScrn))
+ return FALSE;
+
+ pScrn->memPhysBase = (unsigned long)pI810->LinearAddr;
+ pScrn->fbOffset = 0;
+
+ vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0);
+ vgaHWGetIOBase(hwp);
+ if (!vgaHWMapMem(pScrn))
+ return FALSE;
+
+ I810Save(pScrn);
+ if (!I810ModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+
+ I810SaveScreen(pScreen, FALSE);
+ I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ if (!fbScreenInit(pScreen, pI810->FbBase + pScrn->fbOffset,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel))
+ return FALSE;
+
+ if (pScrn->bitsPerPixel > 8) {
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ fbPictureInit(pScreen, NULL, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+#ifdef XF86DRI
+ if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) {
+ pI810->directRenderingEnabled = FALSE;
+ I810DRICloseScreen(pScreen);
+ }
+
+ if (!pI810->directRenderingEnabled) {
+ pI810->DoneFrontAlloc = FALSE;
+ if (!I810AllocateGARTMemory(pScrn))
+ return FALSE;
+ if (!I810AllocateFront(pScrn))
+ return FALSE;
+ }
+#endif
+
+#ifdef XFreeXDGA
+ I810DGAInit(pScreen);
+#endif
+
+ if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to init memory manager\n");
+ return FALSE;
+ }
+
+ if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) {
+ if (pI810->LpRing->mem.Size != 0) {
+ I810SetRingRegs(pScrn);
+
+ if (!I810AccelInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware acceleration initialization failed\n");
+ } else /* PK added 16.02.2004 */
+ I810EmitFlush(pScrn);
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!I810CursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ /* Use driver specific palette load routines for Direct Color support. -jens */
+ if (pScrn->bitsPerPixel == 16) {
+ if (pScrn->depth == 15) {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, NULL,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ } else {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, NULL,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+ } else {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, NULL,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+
+ xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0);
+
+ I810InitVideo(pScreen);
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ /* Now that mi, fb, drm and others have done their thing,
+ * complete the DRI setup.
+ */
+ pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
+ }
+#ifdef XvMCExtension
+ if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
+ /* Initialize the hardware motion compensation code */
+ I810InitMC(pScreen);
+ }
+#endif
+#endif
+
+ if (pI810->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
+ }
+
+ pScreen->SaveScreen = I810SaveScreen;
+ pI810->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = I810CloseScreen;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ return TRUE;
+}
+
+Bool
+I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+#if 0
+ I810Ptr pI810 = I810PTR(pScrn);
+#endif
+ if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags);
+
+#if 0
+/*
+ * This has been added to prevent lockups on mode switch by modeling
+ * it after I810Leave()/I810Enter() but the call to I810DRILeave()
+ * was missing so it caused the opposite.
+ * The version below works but it is doubtful it does any good.
+ * If lockups on mode switch are still seen revisit this code. (EE)
+ */
+
+# ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+# endif
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+
+# ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (!I810DRILeave(pScrn))
+ return FALSE;
+ if (!I810DRIEnter(pScrn))
+ return FALSE;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+# endif
+#endif
+ return I810ModeInit(pScrn, mode);
+}
+
+void
+I810AdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I810Ptr pI810 = I810PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int Base;
+
+#if 1
+ if (pI810->showCache) {
+ int lastline = pI810->FbMapSize /
+ ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
+ lastline -= pScrn->currentMode->VDisplay;
+ if (y > 0)
+ y += pScrn->currentMode->VDisplay;
+ if (y > lastline) y = lastline;
+ }
+#endif
+ Base = (y * pScrn->displayWidth + x) >> 2;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags);
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ Base *= 2;
+ break;
+ case 24:
+ /* KW: Need to do 16-pixel alignment for i810, otherwise you
+ * get bad watermark problems. Need to fixup the mouse
+ * pointer positioning to take this into account.
+ */
+ pI810->CursorOffset = (Base & 0x3) * 4;
+ Base &= ~0x3;
+ 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));
+}
+
+/* These functions are usually called with the lock **not held**.
+ */
+static Bool
+I810EnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+#ifdef XF86DRI
+ I810Ptr pI810 = I810PTR(pScrn);
+#endif
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("\n\nENTER VT\n");
+
+ if (!I810BindGARTMemory(pScrn)) {
+ return FALSE;
+ }
+#ifdef XF86DRI
+ if (!I810DRIEnter(pScrn)) {
+ return FALSE;
+ }
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+#endif
+
+ if (!I810ModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+ I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return TRUE;
+}
+
+static void
+I810LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("\n\n\nLeave VT\n");
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+#endif
+
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+
+ if (!I810UnbindGARTMemory(pScrn))
+ return;
+#ifdef XF86DRI
+ if (!I810DRILeave(pScrn))
+ return;
+#endif
+
+ vgaHWLock(hwp);
+}
+
+static Bool
+I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ I810Ptr pI810 = I810PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
+
+ if (pScrn->vtSema == TRUE) {
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+ vgaHWLock(hwp);
+ }
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ I810DRICloseScreen(pScreen);
+ pI810->directRenderingEnabled = FALSE;
+ }
+#endif
+
+ if (pScrn->vtSema == TRUE) {
+ I810UnbindGARTMemory(pScrn);
+ I810Restore(pScrn);
+ vgaHWLock(hwp);
+ }
+
+ I810UnmapMem(pScrn);
+ vgaHWUnmapMem(pScrn);
+
+ if (pI810->ScanlineColorExpandBuffers) {
+ free(pI810->ScanlineColorExpandBuffers);
+ pI810->ScanlineColorExpandBuffers = NULL;
+ }
+
+ if (infoPtr) {
+ if (infoPtr->ScanlineColorExpandBuffers)
+ free(infoPtr->ScanlineColorExpandBuffers);
+ XAADestroyInfoRec(infoPtr);
+ pI810->AccelInfoRec = NULL;
+ }
+
+ if (pI810->CursorInfoRec) {
+ xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
+ pI810->CursorInfoRec = NULL;
+ }
+
+ /* Free all allocated video ram.
+ */
+ pI810->SysMem = pI810->SavedSysMem;
+ pI810->DcacheMem = pI810->SavedDcacheMem;
+ pI810->DoneFrontAlloc = FALSE;
+
+ /* Need to actually close the gart fd, or the unbound memory will just sit
+ * around. Will prevent the Xserver from recycling.
+ */
+ xf86GARTCloseScreen(scrnIndex);
+
+ free(pI810->LpRing);
+ pI810->LpRing = NULL;
+
+ pScrn->vtSema = FALSE;
+ pScreen->CloseScreen = pI810->CloseScreen;
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static void
+I810FreeScreen(int scrnIndex, int flags)
+{
+ I810FreeRec(xf86Screens[scrnIndex]);
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+}
+
+static ModeStatus
+I810ValidMode(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
+I810SaveScreen(ScreenPtr pScreen, Bool unblack)
+{
+ return vgaHWSaveScreen(pScreen, unblack);
+}
+
+static void
+I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ I810Ptr pI810;
+ unsigned char SEQ01 = 0;
+ int DPMSSyncSelect = 0;
+
+ pI810 = I810PTR(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 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20;
+ pI810->writeControl(pI810, SRX, 0x01, SEQ01);
+
+ /* Set the DPMS mode */
+ OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
+}
+
+const OptionInfoRec *
+lg_i810_available_options(int chipid, int busid)
+{
+ return I810Options;
+}
+
+
+void lg_i810_init(ScrnInfoPtr scrn)
+{
+ scrn->PreInit = I810PreInit;
+ scrn->ScreenInit = I810ScreenInit;
+ scrn->SwitchMode = I810SwitchMode;
+ scrn->AdjustFrame = I810AdjustFrame;
+ scrn->EnterVT = I810EnterVT;
+ scrn->LeaveVT = I810LeaveVT;
+ scrn->FreeScreen = I810FreeScreen;
+ scrn->ValidMode = I810ValidMode;
+}
diff --git a/src/legacy/i810/i810_hwmc.c b/src/legacy/i810/i810_hwmc.c
new file mode 100644
index 00000000..724e1bea
--- /dev/null
+++ b/src/legacy/i810/i810_hwmc.c
@@ -0,0 +1,419 @@
+/***************************************************************************
+
+Copyright 2000 Intel Corporation. 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 INTEL, 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.
+
+**************************************************************************/
+
+/*
+ * i810_hwmc.c: i810 HWMC Driver
+ *
+ * Authors:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i810.h"
+#include "i810_dri.h"
+
+#include "xf86xv.h"
+#include "xf86xvmc.h"
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/XvMC.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv );
+void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
+
+int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
+
+int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
+
+
+typedef struct {
+ drm_context_t drmcontext;
+ unsigned int fbBase;
+ unsigned int OverlayOffset;
+ unsigned int OverlaySize;
+ unsigned int SurfacesOffset;
+ unsigned int SurfacesSize;
+ char busIdString[10];
+ char pad[2];
+} I810XvMCCreateContextRec;
+
+
+static int yv12_subpicture_index_list[2] =
+{
+ FOURCC_IA44,
+ FOURCC_AI44
+};
+
+static XF86MCImageIDList yv12_subpicture_list =
+{
+ 2,
+ yv12_subpicture_index_list
+};
+
+static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_2,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_1,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoPtr ppSI[2] =
+{
+ (XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface,
+ (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
+};
+
+/* List of subpicture types that we support */
+static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
+static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
+
+static XF86ImagePtr i810_subpicture_list[2] =
+{
+ (XF86ImagePtr)&ia44_subpicture,
+ (XF86ImagePtr)&ai44_subpicture
+};
+
+/* Fill in the device dependent adaptor record.
+ * This is named "I810 Video Overlay" because this code falls under the
+ * XV extenstion, the name must match or it won't be used.
+ *
+ * Surface and Subpicture - see above
+ * Function pointers to functions below
+ */
+static XF86MCAdaptorRec pAdapt =
+{
+ "I810 Video Overlay", /* name */
+ 2, /* num_surfaces */
+ ppSI, /* surfaces */
+ 2, /* num_subpictures */
+ i810_subpicture_list, /* subpictures */
+ (xf86XvMCCreateContextProcPtr)I810XvMCCreateContext,
+ (xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext,
+ (xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface,
+ (xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface,
+ (xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture,
+ (xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture
+};
+
+static XF86MCAdaptorPtr ppAdapt[1] =
+{
+ (XF86MCAdaptorPtr)&pAdapt
+};
+
+/**************************************************************************
+ *
+ * I810InitMC
+ *
+ * Initialize the hardware motion compenstation extention for this
+ * hardware. The initialization routines want the address of the pointers
+ * to the structures, not the address of the structures. This means we
+ * allocate (or create static?) the pointer memory and pass that
+ * address. This seems a little convoluted.
+ *
+ * We need to allocate memory for the device depended adaptor record.
+ * This is what holds the pointers to all our device functions.
+ *
+ * We need to map the overlay registers into the drm.
+ *
+ * We need to map the surfaces into the drm.
+ *
+ * Inputs:
+ * Screen pointer
+ *
+ * Outputs:
+ * None, this calls the device independent screen initialization
+ * function.
+ *
+ * Revisions:
+ *
+ **************************************************************************/
+void I810InitMC(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ /* Clear the Surface Allocation */
+ for(i=0; i<I810_MAX_SURFACES; i++) {
+ pI810->surfaceAllocation[i] = 0;
+ }
+
+ /* Cursor is at a page boundary, Overlay regs are not, don't forget */
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->CursorStart,
+ 4096, DRM_AGP, 0, (drmAddress) &pI810->overlay_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
+ return;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->MC.Start,
+ pI810->MC.Size, DRM_AGP, 0, (drmAddress) &pI810->mc_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n");
+ return;
+ }
+ xf86XvMCScreenInit(pScreen, 1, ppAdapt);
+}
+
+/**************************************************************************
+ *
+ * I810XvMCCreateContext
+ *
+ * Some info about the private data:
+ *
+ * Set *num_priv to the number of 32bit words that make up the size of
+ * of the data that priv will point to.
+ *
+ * *priv = (long *) calloc (elements, sizeof(element))
+ * *num_priv = (elements * sizeof(element)) >> 2;
+ *
+ **************************************************************************/
+
+int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ DRIInfoPtr pDRIInfo = pI810->pDRIInfo;
+ I810XvMCCreateContextRec *contextRec;
+
+
+ if(!pI810->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
+ return BadAlloc;
+ }
+
+ /* Context Already in use! */
+ if(pI810->xvmcContext) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
+ return BadAlloc;
+ }
+
+ *priv = calloc(1,sizeof(I810XvMCCreateContextRec));
+ contextRec = (I810XvMCCreateContextRec *)*priv;
+
+ if(!*priv) {
+ *num_priv = 0;
+ return BadAlloc;
+ }
+
+ *num_priv = sizeof(I810XvMCCreateContextRec) >> 2;
+ if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I810XvMCCreateContext: Unable to create DRMContext!\n");
+ free(*priv);
+ return BadAlloc;
+ }
+
+ drmAuthMagic(pI810->drmSubFD, pContext->flags);
+
+ pI810->xvmcContext = contextRec->drmcontext;
+ contextRec->fbBase = pScrn->memPhysBase;
+
+ /* Overlay Regs are at 1024 offset into the Cursor Space */
+ contextRec->OverlayOffset = pI810->CursorStart;
+ contextRec->OverlaySize = 4096;
+
+ contextRec->SurfacesOffset = pI810->MC.Start;
+ contextRec->SurfacesSize = pI810->MC.Size;
+ strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9);
+
+ return Success;
+}
+
+
+int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ *priv = (long *)calloc(2,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I810XvMCCreateSurface: Unable to allocate memory!\n");
+ *num_priv = 0;
+ return BadAlloc;
+ }
+ *num_priv = 2;
+
+ /* Surface Arrangement is different based on 6 or 7 Surfaces */
+ if(pI810->numSurfaces == 6) {
+ for(i=0; i<pI810->numSurfaces; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSurf->surface_id;
+ /* Y data starts at 2MB offset, each surface is 576k */
+ (*priv)[0] = (2*1024*1024 + 576*1024 * i);
+ /* UV data starts at 0 offset, each set is 288k */
+ (*priv)[1] = (576*512 * i);
+ return Success;
+ }
+ }
+ }
+ if(pI810->numSurfaces == 7) {
+ for(i=0; i<pI810->numSurfaces; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSurf->surface_id;
+ /* Y data starts at 2.5MB offset, each surface is 576k */
+ (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
+ /* UV data starts at 0 offset, each set is 288k */
+ (*priv)[1] = (576*512 * i);
+ return Success;
+ }
+ }
+ }
+ (*priv)[0] = 0;
+ (*priv)[1] = 0;
+ return BadAlloc;
+}
+
+int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
+ int *num_priv, long **priv )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ *priv = (long *)calloc(1,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I810XvMCCreateSubpicture: Unable to allocate memory!\n");
+ *num_priv = 0;
+ return BadAlloc;
+ }
+ *num_priv = 1;
+
+ if(pI810->numSurfaces == 6) {
+ for(i=6; i<8; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSubp->subpicture_id;
+ /* Subpictures are after the Y surfaces in memory */
+ (*priv)[0] = (2*1024*1024 + 576*1024 * i);
+ return Success;
+ }
+ }
+ }
+ if(pI810->numSurfaces == 7) {
+ for(i=7; i<9; i++) {
+ if(!pI810->surfaceAllocation[i]) {
+ pI810->surfaceAllocation[i] = pSubp->subpicture_id;
+ /* Subpictures are after the Y surfaces in memory */
+ (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
+ return Success;
+ }
+ }
+ }
+
+ (*priv)[0] = 0;
+ return BadAlloc;
+}
+
+void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext);
+ pI810->xvmcContext = 0;
+}
+
+void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ for(i=0; i<I810_MAX_SURFACES; i++) {
+ if(pI810->surfaceAllocation[i] == pSurf->surface_id) {
+ pI810->surfaceAllocation[i] = 0;
+ return;
+ }
+ }
+ return;
+}
+
+void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ for(i=pI810->numSurfaces; i<I810_MAX_SURFACES + I810_MAX_SUBPICTURES; i++) {
+ if(pI810->surfaceAllocation[i] == pSubp->subpicture_id) {
+ pI810->surfaceAllocation[i] = 0;
+ return;
+ }
+ }
+ return;
+}
+
+
+
+
+
+
diff --git a/src/legacy/i810/i810_io.c b/src/legacy/i810/i810_io.c
new file mode 100644
index 00000000..a6cf3058
--- /dev/null
+++ b/src/legacy/i810/i810_io.c
@@ -0,0 +1,133 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+
+#ifdef BUILD_FOR_I830
+#include "i830.h"
+#define pI810 pI830
+#define I810Ptr I830Ptr
+#define I810WriteControlPIO I830WriteControlPIO
+#define I810ReadControlPIO I830ReadControlPIO
+#define I810WriteStandardPIO I830WriteStandardPIO
+#define I810ReadStandardPIO I830ReadStandardPIO
+#define I810SetPIOAccess I830SetPIOAccess
+#define I810WriteControlMMIO I830WriteControlMMIO
+#define I810ReadControlMMIO I830ReadControlMMIO
+#define I810WriteStandardMMIO I830WriteStandardMMIO
+#define I810ReadStandardMMIO I830ReadStandardMMIO
+#define I810SetMMIOAccess I830SetMMIOAccess
+#else
+#include "i810.h"
+#endif
+
+#define minb(p) *(volatile uint8_t *)(pI810->MMIOBase + (p))
+#define moutb(p,v) *(volatile uint8_t *)(pI810->MMIOBase + (p)) = (v)
+
+static void
+I810WriteControlPIO(I810Ptr pI810, IOADDRESS addr, uint8_t index, uint8_t val)
+{
+ addr += pI810->ioBase;
+ outb(addr, index);
+ outb(addr + 1, val);
+}
+
+static uint8_t
+I810ReadControlPIO(I810Ptr pI810, IOADDRESS addr, uint8_t index)
+{
+ addr += pI810->ioBase;
+ outb(addr, index);
+ return inb(addr + 1);
+}
+
+static void
+I810WriteStandardPIO(I810Ptr pI810, IOADDRESS addr, uint8_t val)
+{
+ outb(pI810->ioBase + addr, val);
+}
+
+static uint8_t
+I810ReadStandardPIO(I810Ptr pI810, IOADDRESS addr)
+{
+ return inb(pI810->ioBase + addr);
+}
+
+void
+I810SetPIOAccess(I810Ptr pI810)
+{
+ pI810->writeControl = I810WriteControlPIO;
+ pI810->readControl = I810ReadControlPIO;
+ pI810->writeStandard = I810WriteStandardPIO;
+ pI810->readStandard = I810ReadStandardPIO;
+}
+
+static void
+I810WriteControlMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t index, uint8_t val)
+{
+ moutb(addr, index);
+ moutb(addr + 1, val);
+}
+
+static uint8_t
+I810ReadControlMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t index)
+{
+ moutb(addr, index);
+ return minb(addr + 1);
+}
+
+static void
+I810WriteStandardMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t val)
+{
+ moutb(addr, val);
+}
+
+static uint8_t
+I810ReadStandardMMIO(I810Ptr pI810, IOADDRESS addr)
+{
+ return minb(addr);
+}
+
+void
+I810SetMMIOAccess(I810Ptr pI810)
+{
+ pI810->writeControl = I810WriteControlMMIO;
+ pI810->readControl = I810ReadControlMMIO;
+ pI810->writeStandard = I810WriteStandardMMIO;
+ pI810->readStandard = I810ReadStandardMMIO;
+}
diff --git a/src/legacy/i810/i810_memory.c b/src/legacy/i810/i810_memory.c
new file mode 100644
index 00000000..f57ddbe2
--- /dev/null
+++ b/src/legacy/i810/i810_memory.c
@@ -0,0 +1,428 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "i810.h"
+#include "i810_reg.h"
+
+int
+I810AllocLow(I810MemRange * result, I810MemRange * pool, int size)
+{
+ if (size > (long)pool->Size)
+ return 0;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->Start = pool->Start;
+ result->End = pool->Start += size;
+
+ return 1;
+}
+
+int
+I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size)
+{
+ if (size > (long)pool->Size)
+ return 0;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->End = pool->End;
+ result->Start = pool->End -= size;
+
+ return 1;
+}
+
+int
+I810AllocateGARTMemory(ScrnInfoPtr pScrn)
+{
+ unsigned long size = pScrn->videoRam * 1024;
+ I810Ptr pI810 = I810PTR(pScrn);
+ int key;
+ long tom = 0;
+ unsigned long physical;
+
+ if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "AGP GART support is either not available or cannot be used.\n"
+ "\tMake sure your kernel has agpgart support or has the\n"
+ "\tagpgart module loaded.\n");
+ return FALSE;
+ }
+
+ /* This allows the 2d only Xserver to regen */
+ pI810->agpAcquired2d = TRUE;
+
+ /*
+ * I810/I815
+ *
+ * Treat the gart like video memory - we assume we own all that is
+ * there, so ignore EBUSY errors. Don't try to remove it on
+ * failure, either, as other X server may be using it.
+ */
+
+ if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL)) == -1)
+ return FALSE;
+
+ pI810->VramOffset = 0;
+ pI810->VramKey = key;
+
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, 0))
+ return FALSE;
+
+ pI810->SysMem.Start = 0;
+ pI810->SysMem.Size = size;
+ pI810->SysMem.End = size;
+ pI810->SavedSysMem = pI810->SysMem;
+
+ tom = pI810->SysMem.End;
+
+ pI810->DcacheMem.Start = 0;
+ pI810->DcacheMem.End = 0;
+ pI810->DcacheMem.Size = 0;
+ pI810->CursorPhysical = 0;
+ pI810->CursorARGBPhysical = 0;
+
+ /*
+ * Dcache - half the speed of normal ram, so not really useful for
+ * a 2d server. Don't bother reporting its presence. This is
+ * mapped in addition to the requested amount of system ram.
+ */
+
+ size = 1024 * 4096;
+
+ /*
+ * Keep it 512K aligned for the sake of tiled regions.
+ */
+
+ tom += 0x7ffff;
+ tom &= ~0x7ffff;
+
+ if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
+ pI810->DcacheOffset = tom;
+ pI810->DcacheKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for DCACHE failed\n", size);
+ pI810->DcacheKey = -1;
+ } else {
+ pI810->DcacheMem.Start = tom;
+ pI810->DcacheMem.Size = size;
+ pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size;
+ tom = pI810->DcacheMem.End;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for %ld bytes of DCACHE\n",
+ size);
+ pI810->DcacheKey = -1;
+ }
+
+ /*
+ * Mouse cursor -- The i810 (crazy) needs a physical address in
+ * system memory from which to upload the cursor. We get this from
+ * the agpgart module using a special memory type.
+ */
+
+ /*
+ * 4k for the cursor is excessive, I'm going to steal 3k for
+ * overlay registers later
+ */
+
+ size = 4096;
+
+ if ((key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for HW cursor\n");
+ pI810->HwcursKey = -1;
+ pI810->CursorStart = 0;
+ } else {
+ pI810->HwcursOffset = tom;
+ pI810->HwcursKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for HW cursor failed\n", size);
+ pI810->HwcursKey = -1;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocated of %ld bytes for HW cursor\n", size);
+ pI810->CursorPhysical = physical;
+ pI810->CursorStart = tom;
+ tom += size;
+ }
+ }
+
+ /*
+ * 16k for the ARGB cursor
+ */
+
+ size = 16384;
+
+ if ((key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for ARGB HW cursor\n");
+ pI810->ARGBHwcursKey = -1;
+ pI810->CursorARGBStart = 0;
+ } else {
+ pI810->ARGBHwcursOffset = tom;
+ pI810->ARGBHwcursKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for ARGB HW cursor failed\n", size);
+ pI810->ARGBHwcursKey = -1;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocated of %ld bytes for ARGB HW cursor\n", size);
+ pI810->CursorARGBPhysical = physical;
+ pI810->CursorARGBStart = tom;
+ tom += size;
+ }
+ }
+
+ /*
+ * Overlay register buffer -- Just like the cursor, the i810 needs a
+ * physical address in system memory from which to upload the overlay
+ * registers.
+ */
+
+ if (pI810->CursorStart != 0) {
+ pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
+ pI810->OverlayStart = pI810->CursorStart + 1024;
+ }
+
+ pI810->GttBound = 1;
+
+ return TRUE;
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+void
+I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned int start,
+ unsigned int pitch, unsigned int size)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ uint32_t val;
+ uint32_t fence_mask = 0;
+
+ if (nr < 0 || nr > 7) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s - fence %d out of range\n",
+ "I810SetTiledMemory", nr);
+ return;
+ }
+
+ i810Reg->Fence[nr] = 0;
+
+ fence_mask = ~FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s %d: start (%x) is not 512k aligned\n",
+ "I810SetTiledMemory", nr, start);
+ return;
+ }
+
+ if (start % size) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s %d: start (%x) is not size (%x) aligned\n",
+ "I810SetTiledMemory", nr, start, size);
+ return;
+ }
+
+ if (pitch & 127) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s %d: pitch (%x) not a multiple of 128 bytes\n",
+ "I810SetTiledMemory", nr, pitch);
+ return;
+ }
+
+ val = (start | FENCE_X_MAJOR | FENCE_VALID);
+
+ switch (size) {
+ case KB(512):
+ val |= FENCE_SIZE_512K;
+ break;
+ case MB(1):
+ val |= FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= FENCE_SIZE_32M;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
+ size);
+ return;
+ }
+
+ switch (pitch / 128) {
+ case 1:
+ val |= FENCE_PITCH_1;
+ break;
+ case 2:
+ val |= FENCE_PITCH_2;
+ break;
+ case 4:
+ val |= FENCE_PITCH_4;
+ break;
+ case 8:
+ val |= FENCE_PITCH_8;
+ break;
+ case 16:
+ val |= FENCE_PITCH_16;
+ break;
+ case 32:
+ val |= FENCE_PITCH_32;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
+ size);
+ return;
+ }
+
+ i810Reg->Fence[nr] = val;
+}
+
+Bool
+I810BindGARTMemory(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled
+ && !pI810->GttBound) {
+ if (!xf86AcquireGART(pScrn->scrnIndex))
+ return FALSE;
+
+ if (pI810->VramKey != -1
+ && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->VramKey,
+ pI810->VramOffset))
+ return FALSE;
+
+ if (pI810->DcacheKey != -1
+ && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey,
+ pI810->DcacheOffset))
+ return FALSE;
+
+ if (pI810->HwcursKey != -1
+ && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey,
+ pI810->HwcursOffset))
+ return FALSE;
+
+ if (pI810->ARGBHwcursKey != -1
+ && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey,
+ pI810->ARGBHwcursOffset))
+ return FALSE;
+
+ pI810->GttBound = 1;
+ }
+
+ return TRUE;
+}
+
+Bool
+I810UnbindGARTMemory(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled
+ && pI810->GttBound) {
+ if (pI810->VramKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->VramKey))
+ return FALSE;
+
+ if (pI810->DcacheKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey))
+ return FALSE;
+
+ if (pI810->HwcursKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey))
+ return FALSE;
+
+ if (pI810->ARGBHwcursKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey))
+ return FALSE;
+
+ if (!xf86ReleaseGART(pScrn->scrnIndex))
+ return FALSE;
+
+ pI810->GttBound = 0;
+ }
+
+ return TRUE;
+}
+
+int
+I810CheckAvailableMemory(ScrnInfoPtr pScrn)
+{
+ AgpInfoPtr agpinf;
+ int maxPages;
+
+ if (!xf86AgpGARTSupported() ||
+ !xf86AcquireGART(pScrn->scrnIndex) ||
+ (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL ||
+ !xf86ReleaseGART(pScrn->scrnIndex))
+ return -1;
+
+ maxPages = agpinf->totalPages - agpinf->usedPages;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %dk available\n",
+ "I810CheckAvailableMemory", maxPages * 4);
+
+ return maxPages * 4;
+}
diff --git a/src/legacy/i810/i810_reg.h b/src/legacy/i810/i810_reg.h
new file mode 100644
index 00000000..2b679346
--- /dev/null
+++ b/src/legacy/i810/i810_reg.h
@@ -0,0 +1,3194 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+/** @file
+ * Register names and fields for Intel graphics.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ * based on the i740 driver by
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ *
+ */
+
+#ifndef _I810_REG_H
+#define _I810_REG_H
+
+/* I/O register offsets
+ */
+#define SRX 0x3C4 /* p208 */
+#define GRX 0x3CE /* p213 */
+#define ARX 0x3C0 /* p224 */
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6 /* p232 */
+#define DACSTATE 0x3C7 /* p232 */
+#define DACRX 0x3C7 /* p233 */
+#define DACWX 0x3C8 /* p233 */
+#define DACDATA 0x3C9 /* p233 */
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C /* p246 */
+#define START_ADDR_LO 0x0D /* p247 */
+#define VERT_SYNC_END 0x11 /* p249 */
+#define EXT_VERT_TOTAL 0x30 /* p257 */
+#define EXT_VERT_DISPLAY 0x31 /* p258 */
+#define EXT_VERT_SYNC_START 0x32 /* p259 */
+#define EXT_VERT_BLANK_START 0x33 /* p260 */
+#define EXT_HORIZ_TOTAL 0x35 /* p261 */
+#define EXT_HORIZ_BLANK 0x39 /* p261 */
+#define EXT_START_ADDR 0x40 /* p262 */
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41 /* p263 */
+#define EXT_START_ADDR_HI 0x42 /* p263 */
+#define INTERLACE_CNTL 0x70 /* p264 */
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register
+ */
+#define MSR_R 0x3CC /* p207 */
+#define MSR_W 0x3C2 /* p207 */
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0 /* p207 */
+#define CGA_BASE 0x3D0 /* p207 */
+
+/* CR80 - IO Control, p264
+ */
+#define IO_CTNL 0x80
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+/* GR10 - Address mapping, p221
+ */
+#define ADDRESS_MAPPING 0x10
+#define PAGE_TO_LOCAL_MEM_ENABLE 0x10
+#define GTT_MEM_MAP_ENABLE 0x08
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define HOTKEY_VBIOS_SWITCH_BLOCK 0x80
+#define HOTKEY_SWITCH 0x20
+#define HOTKEY_TOGGLE 0x10
+
+/* Blitter control, p378
+ */
+#define BITBLT_CNTL 0x7000c
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define BITBLT_STATUS 0x01
+
+#define CHDECMISC 0x10111
+#define DCC 0x10200
+#define C0DRB0 0x10200
+#define C0DRB1 0x10202
+#define C0DRB2 0x10204
+#define C0DRB3 0x10206
+#define C0DRA01 0x10208
+#define C0DRA23 0x1020a
+#define C1DRB0 0x10600
+#define C1DRB1 0x10602
+#define C1DRB2 0x10604
+#define C1DRB3 0x10606
+#define C1DRA01 0x10608
+#define C1DRA23 0x1060a
+
+/* p375.
+ */
+#define DISPLAY_CNTL 0x70008
+#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
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_0 0x70009
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_1 0x7000a
+#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
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_2 0x7000b
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+
+/* p380
+ */
+#define DISPLAY_BASE 0x70020
+#define DISPLAY_BASE_MASK 0x03fffffc
+
+
+/* Cursor control registers, pp383-384
+ */
+/* Desktop (845G, 865G) */
+#define CURSOR_CONTROL 0x70080
+#define CURSOR_ENABLE 0x80000000
+#define CURSOR_GAMMA_ENABLE 0x40000000
+#define CURSOR_STRIDE_MASK 0x30000000
+#define CURSOR_FORMAT_SHIFT 24
+#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT)
+
+/* Mobile and i810 */
+#define CURSOR_A_CONTROL CURSOR_CONTROL
+#define CURSOR_ORIGIN_SCREEN 0x00 /* i810 only */
+#define CURSOR_ORIGIN_DISPLAY 0x1 /* i810 only */
+#define CURSOR_MODE 0x27
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01 /* i810 only */
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_64_32B_AX 0x07
+#define CURSOR_MODE_64_ARGB_AX (0x20 | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_PIPE_SELECT (1 << 28)
+#define MCURSOR_PIPE_A 0x00
+#define MCURSOR_PIPE_B (1 << 28)
+#define MCURSOR_GAMMA_ENABLE (1 << 26)
+#define MCURSOR_MEM_TYPE_LOCAL (1 << 25)
+
+
+#define CURSOR_BASEADDR 0x70084
+#define CURSOR_A_BASE CURSOR_BASEADDR
+#define CURSOR_BASEADDR_MASK 0x1FFFFF00
+#define CURSOR_A_POSITION 0x70088
+#define CURSOR_POS_SIGN 0x8000
+#define CURSOR_POS_MASK 0x007FF
+#define CURSOR_X_SHIFT 0
+#define CURSOR_Y_SHIFT 16
+#define CURSOR_X_LO 0x70088
+#define CURSOR_X_HI 0x70089
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0x7008A
+#define CURSOR_Y_HI 0x7008B
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define CURSOR_A_PALETTE0 0x70090
+#define CURSOR_A_PALETTE1 0x70094
+#define CURSOR_A_PALETTE2 0x70098
+#define CURSOR_A_PALETTE3 0x7009C
+
+#define CURSOR_SIZE 0x700A0
+#define CURSOR_SIZE_MASK 0x3FF
+#define CURSOR_SIZE_HSHIFT 0
+#define CURSOR_SIZE_VSHIFT 12
+
+#define CURSOR_B_CONTROL 0x700C0
+#define CURSOR_B_BASE 0x700C4
+#define CURSOR_B_POSITION 0x700C8
+#define CURSOR_B_PALETTE0 0x700D0
+#define CURSOR_B_PALETTE1 0x700D4
+#define CURSOR_B_PALETTE2 0x700D8
+#define CURSOR_B_PALETTE3 0x700DC
+
+
+/* Similar registers exist in Device 0 on the i810 (pp55-65), but I'm
+ * not sure they refer to local (graphics) memory.
+ *
+ * These details are for the local memory control registers,
+ * (pp301-310). The test machines are not equiped with local memory,
+ * so nothing is tested. Only a single row seems to be supported.
+ */
+#define DRAM_ROW_TYPE 0x3000
+#define DRAM_ROW_0 0x01
+#define DRAM_ROW_0_SDRAM 0x01
+#define DRAM_ROW_0_EMPTY 0x00
+#define DRAM_ROW_CNTL_LO 0x3001
+#define DRAM_PAGE_MODE_CTRL 0x10
+#define DRAM_RAS_TO_CAS_OVRIDE 0x08
+#define DRAM_CAS_LATENCY 0x04
+#define DRAM_RAS_TIMING 0x02
+#define DRAM_RAS_PRECHARGE 0x01
+#define DRAM_ROW_CNTL_HI 0x3002
+#define DRAM_REFRESH_RATE 0x18
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x08
+#define DRAM_REFRESH_FAST_TEST 0x10
+#define DRAM_REFRESH_RESERVED 0x18
+#define DRAM_SMS 0x07
+#define DRAM_SMS_NORMAL 0x00
+#define DRAM_SMS_NOP_ENABLE 0x01
+#define DRAM_SMS_ABPCE 0x02
+#define DRAM_SMS_MRCE 0x03
+#define DRAM_SMS_CBRCE 0x04
+
+/* p307
+ */
+#define DPMS_SYNC_SELECT 0x5002
+#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 GPIOA 0x5010
+#define GPIOB 0x5014
+#define GPIOC 0x5018
+#define GPIOD 0x501c
+#define GPIOE 0x5020
+#define GPIOF 0x5024
+#define GPIOG 0x5028
+#define GPIOH 0x502c
+# define GPIO_CLOCK_DIR_MASK (1 << 0)
+# define GPIO_CLOCK_DIR_IN (0 << 1)
+# define GPIO_CLOCK_DIR_OUT (1 << 1)
+# define GPIO_CLOCK_VAL_MASK (1 << 2)
+# define GPIO_CLOCK_VAL_OUT (1 << 3)
+# define GPIO_CLOCK_VAL_IN (1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
+# define GPIO_DATA_DIR_MASK (1 << 8)
+# define GPIO_DATA_DIR_IN (0 << 9)
+# define GPIO_DATA_DIR_OUT (1 << 9)
+# define GPIO_DATA_VAL_MASK (1 << 10)
+# define GPIO_DATA_VAL_OUT (1 << 11)
+# define GPIO_DATA_VAL_IN (1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
+
+/* GMBus registers for hardware-assisted (non-bitbanging) I2C access */
+#define GMBUS0 0x5100
+#define GMBUS1 0x5104
+#define GMBUS2 0x5108
+#define GMBUS3 0x510c
+#define GMBUS4 0x5110
+#define GMBUS5 0x5120
+
+/* p317, 319
+ */
+#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */
+#define VCLK2_VCO_N 0x600a
+#define VCLK2_VCO_DIV_SEL 0x6012
+
+#define VCLK_DIVISOR_VGA0 0x6000
+#define VCLK_DIVISOR_VGA1 0x6004
+#define VCLK_POST_DIV 0x6010
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA1_PD_P2_DIV_4 (1 << 15)
+/** Overrides the p2 post divisor field */
+# define VGA1_PD_P1_DIV_2 (1 << 13)
+# define VGA1_PD_P1_SHIFT 8
+/** P1 value is 2 greater than this field */
+# define VGA1_PD_P1_MASK (0x1f << 8)
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA0_PD_P2_DIV_4 (1 << 7)
+/** Overrides the p2 post divisor field */
+# define VGA0_PD_P1_DIV_2 (1 << 5)
+# define VGA0_PD_P1_SHIFT 0
+/** P1 value is 2 greater than this field */
+# define VGA0_PD_P1_MASK (0x1f << 0)
+
+#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
+
+
+/* Instruction Parser Mode Register
+ * - p281
+ * - 2 new bits.
+ */
+#define INST_PM 0x20c0
+#define AGP_SYNC_PACKET_FLUSH_ENABLE 0x20 /* reserved */
+#define SYNC_PACKET_FLUSH_ENABLE 0x10
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+
+#define MEMMODE 0x20dc
+
+
+/* Instruction parser error register. p279
+ */
+#define IPEIR 0x2088
+#define IPEHR 0x208C
+
+#define INST_DONE 0x2090
+# define IDCT_DONE (1 << 30)
+# define IQ_DONE (1 << 29)
+# define PR_DONE (1 << 28)
+# define VLD_DONE (1 << 27)
+# define IP_DONE (1 << 26)
+# define FBC_DONE (1 << 25)
+# define BINNER_DONE (1 << 24)
+# define SF_DONE (1 << 23)
+# define SE_DONE (1 << 22)
+# define WM_DONE (1 << 21)
+# define IZ_DONE (1 << 20)
+# define PERSPECTIVE_INTERP_DONE (1 << 19)
+# define DISPATCHER_DONE (1 << 18)
+# define PROJECTION_DONE (1 << 17)
+# define DEPENDENT_ADDRESS_DONE (1 << 16)
+# define QUAD_CACHE_DONE (1 << 15)
+# define TEXTURE_FETCH_DONE (1 << 14)
+# define TEXTURE_DECOMPRESS_DONE (1 << 13)
+# define SAMPLER_CACHE_DONE (1 << 12)
+# define FILTER_DONE (1 << 11)
+# define BYPASS_FIFO_DONE (1 << 10)
+# define PS_DONE (1 << 9)
+# define CC_DONE (1 << 8)
+# define MAP_FILTER_DONE (1 << 7)
+# define MAP_L2_IDLE (1 << 6)
+# define RING_2_ENABLE (1 << 2)
+# define RING_1_ENABLE (1 << 1)
+# define RING_0_ENABLE (1 << 0)
+
+#define SCPD0 0x209c /* debug */
+#define INST_PS 0x20c4
+#define IPEIR_I965 0x2064 /* i965 */
+#define IPEHR_I965 0x2068 /* i965 */
+#define INST_DONE_I965 0x206c
+# define I965_SF_DONE (1 << 23)
+# define I965_SE_DONE (1 << 22)
+# define I965_WM_DONE (1 << 21)
+# define I965_TEXTURE_FETCH_DONE (1 << 14)
+# define I965_SAMPLER_CACHE_DONE (1 << 12)
+# define I965_FILTER_DONE (1 << 11)
+# define I965_PS_DONE (1 << 9)
+# define I965_CC_DONE (1 << 8)
+# define I965_MAP_FILTER_DONE (1 << 7)
+# define I965_MAP_L2_IDLE (1 << 6)
+# define I965_CP_DONE (1 << 1)
+# define I965_RING_0_ENABLE (1 << 0)
+#define INST_PS_I965 0x2070
+
+/* Current active ring head address:
+ */
+#define ACTHD_I965 0x2074
+#define ACTHD 0x20C8
+
+/* Current primary/secondary DMA fetch addresses:
+ */
+#define DMA_FADD_P 0x2078
+#define DMA_FADD_S 0x20d4
+#define INST_DONE_1 0x207c
+
+#define CACHE_MODE_0 0x2120
+#define CACHE_MODE_1 0x2124
+#define MI_MODE 0x209c
+#define MI_DISPLAY_POWER_DOWN 0x20e0
+#define MI_ARB_STATE 0x20e4
+#define MI_RDRET_STATE 0x20fc
+
+/* Start addresses for each of the primary rings:
+ */
+#define PR0_STR 0x20f0
+#define PR1_STR 0x20f4
+#define PR2_STR 0x20f8
+
+#define WIZ_CTL 0x7c00
+#define WIZ_CTL_SINGLE_SUBSPAN (1<<6)
+#define WIZ_CTL_IGNORE_STALLS (1<<5)
+
+#define SVG_WORK_CTL 0x7408
+
+#define TS_CTL 0x7e00
+#define TS_MUX_ERR_CODE (0<<8)
+#define TS_MUX_URB_0 (1<<8)
+#define TS_MUX_DISPATCH_ID_0 (10<<8)
+#define TS_MUX_ERR_CODE_VALID (15<<8)
+#define TS_MUX_TID_0 (16<<8)
+#define TS_MUX_EUID_0 (18<<8)
+#define TS_MUX_FFID_0 (22<<8)
+#define TS_MUX_EOT (26<<8)
+#define TS_MUX_SIDEBAND_0 (27<<8)
+#define TS_SNAP_ALL_CHILD (1<<2)
+#define TS_SNAP_ALL_ROOT (1<<1)
+#define TS_SNAP_ENABLE (1<<0)
+
+#define TS_DEBUG_DATA 0x7e0c
+
+#define TD_CTL 0x8000
+#define TD_CTL2 0x8004
+
+
+#define ECOSKPD 0x21d0
+#define EXCC 0x2028
+
+/* I965 debug regs:
+ */
+#define IA_VERTICES_COUNT_QW 0x2310
+#define IA_PRIMITIVES_COUNT_QW 0x2318
+#define VS_INVOCATION_COUNT_QW 0x2320
+#define GS_INVOCATION_COUNT_QW 0x2328
+#define GS_PRIMITIVES_COUNT_QW 0x2330
+#define CL_INVOCATION_COUNT_QW 0x2338
+#define CL_PRIMITIVES_COUNT_QW 0x2340
+#define PS_INVOCATION_COUNT_QW 0x2348
+#define PS_DEPTH_COUNT_QW 0x2350
+#define TIMESTAMP_QW 0x2358
+#define CLKCMP_QW 0x2360
+
+
+
+
+
+
+/* General error reporting regs, p296
+ */
+#define EIR 0x20B0
+#define EMR 0x20B4
+#define ESR 0x20B8
+# define ERR_VERTEX_MAX (1 << 5) /* lpt/cst */
+# define ERR_PGTBL_ERROR (1 << 4)
+# define ERR_DISPLAY_OVERLAY_UNDERRUN (1 << 3)
+# define ERR_MAIN_MEMORY_REFRESH (1 << 1)
+# define ERR_INSTRUCTION_ERROR (1 << 0)
+
+
+/* Interrupt Control Registers
+ * - new bits for i810
+ * - new register hwstam (mask)
+ */
+#define HWS_PGA 0x2080
+#define PWRCTXA 0x2088 /* 965GM+ only */
+#define PWRCTX_EN (1<<0)
+#define HWSTAM 0x2098 /* p290 */
+#define IER 0x20a0 /* p291 */
+#define IIR 0x20a4 /* p292 */
+#define IMR 0x20a8 /* p293 */
+#define ISR 0x20ac /* p294 */
+#define HW_ERROR 0x8000
+#define SYNC_STATUS_TOGGLE 0x1000
+#define DPY_0_FLIP_PENDING 0x0800
+#define DPY_1_FLIP_PENDING 0x0400 /* not implemented on i810 */
+#define OVL_0_FLIP_PENDING 0x0200
+#define OVL_1_FLIP_PENDING 0x0100 /* not implemented on i810 */
+#define DPY_0_VBLANK 0x0080
+#define DPY_0_EVENT 0x0040
+#define DPY_1_VBLANK 0x0020 /* not implemented on i810 */
+#define DPY_1_EVENT 0x0010 /* not implemented on i810 */
+#define HOST_PORT_EVENT 0x0008 /* */
+#define CAPTURE_EVENT 0x0004 /* */
+#define USER_DEFINED 0x0002
+#define BREAKPOINT 0x0001
+
+
+#define INTR_RESERVED (0x6000 | \
+ DPY_1_FLIP_PENDING | \
+ OVL_1_FLIP_PENDING | \
+ DPY_1_VBLANK | \
+ DPY_1_EVENT | \
+ HOST_PORT_EVENT | \
+ CAPTURE_EVENT )
+
+/* FIFO Watermark and Burst Length Control Register
+ *
+ * - different offset and contents on i810 (p299) (fewer bits per field)
+ * - some overlay fields added
+ * - what does it all mean?
+ */
+#define FWATER_BLC 0x20d8
+#define FWATER_BLC2 0x20dc
+#define MM_BURST_LENGTH 0x00700000
+#define MM_FIFO_WATERMARK 0x0001F000
+#define LM_BURST_LENGTH 0x00000700
+#define LM_FIFO_WATERMARK 0x0000001F
+
+
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define FENCE_NEW 0x3000
+#define FENCE_NEW_NR 16
+
+#define FENCE_LINEAR 0
+#define FENCE_XMAJOR 1
+#define FENCE_YMAJOR 2
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define I965_FENCE_X_MAJOR 0x00000000
+#define I965_FENCE_Y_MAJOR 0x00000002
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_PITCH_64 0x00000060
+#define FENCE_VALID 0x00000001
+
+
+/* Registers to control page table, p274
+ */
+#define PGETBL_CTL 0x2020
+#define PGETBL_ADDR_MASK 0xFFFFF000
+#define PGETBL_ENABLE_MASK 0x00000001
+#define PGETBL_ENABLED 0x00000001
+/** Added in 965G, this field has the actual size of the global GTT */
+#define PGETBL_SIZE_MASK 0x0000000e
+#define PGETBL_SIZE_512KB (0 << 1)
+#define PGETBL_SIZE_256KB (1 << 1)
+#define PGETBL_SIZE_128KB (2 << 1)
+#define PGETBL_SIZE_1MB (3 << 1)
+#define PGETBL_SIZE_2MB (4 << 1)
+#define PGETBL_SIZE_1_5MB (5 << 1)
+#define G33_PGETBL_SIZE_MASK (3 << 8)
+#define G33_PGETBL_SIZE_1M (1 << 8)
+#define G33_PGETBL_SIZE_2M (2 << 8)
+
+#define I830_PTE_BASE 0x10000
+#define PTE_ADDRESS_MASK 0xfffff000
+#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */
+#define PTE_MAPPING_TYPE_UNCACHED (0 << 1)
+#define PTE_MAPPING_TYPE_DCACHE (1 << 1) /* i830 only */
+#define PTE_MAPPING_TYPE_CACHED (3 << 1)
+#define PTE_MAPPING_TYPE_MASK (3 << 1)
+#define PTE_VALID (1 << 0)
+
+/** @defgroup PGE_ERR
+ * @{
+ */
+/** Page table debug register for i845 */
+#define PGE_ERR 0x2024
+#define PGE_ERR_ADDR_MASK 0xFFFFF000
+#define PGE_ERR_ID_MASK 0x00000038
+#define PGE_ERR_CAPTURE 0x00000000
+#define PGE_ERR_OVERLAY 0x00000008
+#define PGE_ERR_DISPLAY 0x00000010
+#define PGE_ERR_HOST 0x00000018
+#define PGE_ERR_RENDER 0x00000020
+#define PGE_ERR_BLITTER 0x00000028
+#define PGE_ERR_MAPPING 0x00000030
+#define PGE_ERR_CMD_PARSER 0x00000038
+#define PGE_ERR_TYPE_MASK 0x00000007
+#define PGE_ERR_INV_TABLE 0x00000000
+#define PGE_ERR_INV_PTE 0x00000001
+#define PGE_ERR_MIXED_TYPES 0x00000002
+#define PGE_ERR_PAGE_MISS 0x00000003
+#define PGE_ERR_ILLEGAL_TRX 0x00000004
+#define PGE_ERR_LOCAL_MEM 0x00000005
+#define PGE_ERR_TILED 0x00000006
+/** @} */
+
+/** @defgroup PGTBL_ER
+ * @{
+ */
+/** Page table debug register for i945 */
+# define PGTBL_ER 0x2024
+# define PGTBL_ERR_MT_TILING (1 << 27)
+# define PGTBL_ERR_MT_GTT_PTE (1 << 26)
+# define PGTBL_ERR_LC_TILING (1 << 25)
+# define PGTBL_ERR_LC_GTT_PTE (1 << 24)
+# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE (1 << 23)
+# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE (1 << 22)
+# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE (1 << 21)
+# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE (1 << 20)
+# define PGTBL_ERR_CS_GTT (1 << 19)
+# define PGTBL_ERR_OVERLAY_TILING (1 << 18)
+# define PGTBL_ERR_OVERLAY_GTT_PTE (1 << 16)
+# define PGTBL_ERR_DISPC_TILING (1 << 14)
+# define PGTBL_ERR_DISPC_GTT_PTE (1 << 12)
+# define PGTBL_ERR_DISPB_TILING (1 << 10)
+# define PGTBL_ERR_DISPB_GTT_PTE (1 << 8)
+# define PGTBL_ERR_DISPA_TILING (1 << 6)
+# define PGTBL_ERR_DISPA_GTT_PTE (1 << 4)
+# define PGTBL_ERR_HOST_PTE_DATA (1 << 1)
+# define PGTBL_ERR_HOST_GTT_PTE (1 << 0)
+/** @} */
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING 0x2030
+#define HP_RING 0x2040
+
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x000FFFF8
+#define I830_TAIL_MASK 0x001FFFF8
+
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define I830_HEAD_MASK 0x001FFFFC
+
+#define RING_START 0x08
+#define START_ADDR 0x03FFFFF8
+#define I830_RING_START_MASK 0xFFFFF000
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x001FF000
+#define I830_RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+
+
+/* BitBlt Instructions
+ *
+ * There are many more masks & ranges yet to add.
+ */
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR00_OP_FULL_BLT 0x11400000
+#define BR00_OP_MONO_SRC_BLT 0x11800000
+#define BR00_OP_MONO_SRC_COPY_BLT 0x11000000
+#define BR00_OP_MONO_PAT_BLT 0x11C00000
+#define BR00_OP_MONO_SRC_COPY_IMMEDIATE_BLT (0x61 << 22)
+#define BR00_OP_TEXT_IMMEDIATE_BLT 0xc000000
+
+
+#define BR00_TPCY_DISABLE 0x00000000
+#define BR00_TPCY_ENABLE 0x00000010
+
+#define BR00_TPCY_ROP 0x00000000
+#define BR00_TPCY_NO_ROP 0x00000020
+#define BR00_TPCY_EQ 0x00000000
+#define BR00_TPCY_NOT_EQ 0x00000040
+
+#define BR00_PAT_MSB_FIRST 0x00000000 /* ? */
+
+#define BR00_PAT_VERT_ALIGN 0x000000e0
+
+#define BR00_LENGTH 0x0000000F
+
+#define BR09_DEST_ADDR 0x03FFFFFF
+
+#define BR11_SOURCE_PITCH 0x00003FFF
+
+#define BR12_SOURCE_ADDR 0x03FFFFFF
+
+#define BR13_SOLID_PATTERN 0x80000000
+#define BR13_RIGHT_TO_LEFT 0x40000000
+#define BR13_LEFT_TO_RIGHT 0x00000000
+#define BR13_MONO_TRANSPCY 0x20000000
+#define BR13_MONO_PATN_TRANS 0x10000000
+#define BR13_USE_DYN_DEPTH 0x04000000
+#define BR13_DYN_8BPP 0x00000000
+#define BR13_DYN_16BPP 0x01000000
+#define BR13_DYN_24BPP 0x02000000
+#define BR13_ROP_MASK 0x00FF0000
+#define BR13_DEST_PITCH 0x0000FFFF
+#define BR13_PITCH_SIGN_BIT 0x00008000
+
+#define BR14_DEST_HEIGHT 0xFFFF0000
+#define BR14_DEST_WIDTH 0x0000FFFF
+
+#define BR15_PATTERN_ADDR 0x03FFFFFF
+
+#define BR16_SOLID_PAT_COLOR 0x00FFFFFF
+#define BR16_BACKGND_PAT_CLR 0x00FFFFFF
+
+#define BR17_FGND_PAT_CLR 0x00FFFFFF
+
+#define BR18_SRC_BGND_CLR 0x00FFFFFF
+#define BR19_SRC_FGND_CLR 0x00FFFFFF
+
+
+/* Instruction parser instructions
+ */
+
+#define INST_PARSER_CLIENT 0x00000000
+#define INST_OP_FLUSH 0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+
+#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+
+
+/* Registers in the i810 host-pci bridge pci config space which affect
+ * the i810 graphics operations.
+ */
+#define SMRAM_MISCC 0x70
+#define GMS 0x000000c0
+#define GMS_DISABLE 0x00000000
+#define GMS_ENABLE_BARE 0x00000040
+#define GMS_ENABLE_512K 0x00000080
+#define GMS_ENABLE_1M 0x000000c0
+#define USMM 0x00000030
+#define USMM_DISABLE 0x00000000
+#define USMM_TSEG_ZERO 0x00000010
+#define USMM_TSEG_512K 0x00000020
+#define USMM_TSEG_1M 0x00000030
+#define GFX_MEM_WIN_SIZE 0x00010000
+#define GFX_MEM_WIN_32M 0x00010000
+#define GFX_MEM_WIN_64M 0x00000000
+
+/* Overkill? I don't know. Need to figure out top of mem to make the
+ * SMRAM calculations come out. Linux seems to have problems
+ * detecting it all on its own, so this seems a reasonable double
+ * check to any user supplied 'mem=...' boot param.
+ *
+ * ... unfortunately this reg doesn't work according to spec on the
+ * test hardware.
+ */
+#define WHTCFG_PAMR_DRP 0x50
+#define SYS_DRAM_ROW_0_SHIFT 16
+#define SYS_DRAM_ROW_1_SHIFT 20
+#define DRAM_MASK 0x0f
+#define DRAM_VALUE_0 0
+#define DRAM_VALUE_1 8
+/* No 2 value defined */
+#define DRAM_VALUE_3 16
+#define DRAM_VALUE_4 16
+#define DRAM_VALUE_5 24
+#define DRAM_VALUE_6 32
+#define DRAM_VALUE_7 32
+#define DRAM_VALUE_8 48
+#define DRAM_VALUE_9 64
+#define DRAM_VALUE_A 64
+#define DRAM_VALUE_B 96
+#define DRAM_VALUE_C 128
+#define DRAM_VALUE_D 128
+#define DRAM_VALUE_E 192
+#define DRAM_VALUE_F 256 /* nice one, geezer */
+#define LM_FREQ_MASK 0x10
+#define LM_FREQ_133 0x10
+#define LM_FREQ_100 0x00
+
+
+
+
+/* These are 3d state registers, but the state is invarient, so we let
+ * the X server handle it:
+ */
+
+
+
+/* GFXRENDERSTATE_COLOR_CHROMA_KEY, p135
+ */
+#define GFX_OP_COLOR_CHROMA_KEY ((0x3<<29)|(0x1d<<24)|(0x2<<16)|0x1)
+#define CC1_UPDATE_KILL_WRITE (1<<28)
+#define CC1_ENABLE_KILL_WRITE (1<<27)
+#define CC1_DISABLE_KILL_WRITE 0
+#define CC1_UPDATE_COLOR_IDX (1<<26)
+#define CC1_UPDATE_CHROMA_LOW (1<<25)
+#define CC1_UPDATE_CHROMA_HI (1<<24)
+#define CC1_CHROMA_LOW_MASK ((1<<24)-1)
+#define CC2_COLOR_IDX_SHIFT 24
+#define CC2_COLOR_IDX_MASK (0xff<<24)
+#define CC2_CHROMA_HI_MASK ((1<<24)-1)
+
+
+#define GFX_CMD_CONTEXT_SEL ((0<<29)|(0x5<<23))
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_UPDATE_USE (1<<16)
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_LOAD_CTX0 0
+#define CS_LOAD_CTX1 (1<<8)
+#define CS_USE_CTX0 0
+#define CS_USE_CTX1 (1<<0)
+
+/* I810 LCD/TV registers */
+#define LCD_TV_HTOTAL 0x60000
+#define LCD_TV_C 0x60018
+#define LCD_TV_OVRACT 0x6001C
+
+#define LCD_TV_ENABLE (1 << 31)
+#define LCD_TV_VGAMOD (1 << 28)
+
+/* I830 CRTC registers */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+#define VSYNCSHIFT_A 0x60028
+
+#define HTOTAL_B 0x61000
+#define HBLANK_B 0x61004
+#define HSYNC_B 0x61008
+#define VTOTAL_B 0x6100c
+#define VBLANK_B 0x61010
+#define VSYNC_B 0x61014
+#define PIPEBSRC 0x6101c
+#define BCLRPAT_B 0x61020
+#define VSYNCSHIFT_B 0x61028
+
+#define PP_STATUS 0x61200
+# define PP_ON (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY (1 << 30)
+# define PP_SEQUENCE_NONE (0 << 28)
+# define PP_SEQUENCE_ON (1 << 28)
+# define PP_SEQUENCE_OFF (2 << 28)
+# define PP_SEQUENCE_MASK 0x30000000
+
+#define PP_CONTROL 0x61204
+# define POWER_DOWN_ON_RESET (1 << 1)
+# define POWER_TARGET_ON (1 << 0)
+
+#define PP_ON_DELAYS 0x61208
+#define PP_OFF_DELAYS 0x6120c
+#define PP_DIVISOR 0x61210
+
+#define PFIT_CONTROL 0x61230
+# define PFIT_ENABLE (1 << 31)
+/* Pre-965 */
+# define VERT_INTERP_DISABLE (0 << 10)
+# define VERT_INTERP_BILINEAR (1 << 10)
+# define VERT_INTERP_MASK (3 << 10)
+# define VERT_AUTO_SCALE (1 << 9)
+# define HORIZ_INTERP_DISABLE (0 << 6)
+# define HORIZ_INTERP_BILINEAR (1 << 6)
+# define HORIZ_INTERP_MASK (3 << 6)
+# define HORIZ_AUTO_SCALE (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
+/* 965+ */
+# define PFIT_PIPE_MASK (3 << 29)
+# define PFIT_PIPE_SHIFT 29
+# define PFIT_SCALING_MODE_MASK (7 << 26)
+# define PFIT_SCALING_AUTO (0 << 26)
+# define PFIT_SCALING_PROGRAMMED (1 << 26)
+# define PFIT_SCALING_PILLAR (2 << 26)
+# define PFIT_SCALING_LETTER (3 << 26)
+# define PFIT_FILTER_SELECT_MASK (3 << 24)
+# define PFIT_FILTER_FUZZY (0 << 24)
+# define PFIT_FILTER_CRISP (1 << 24)
+# define PFIT_FILTER_MEDIAN (2 << 24)
+
+#define PFIT_PGM_RATIOS 0x61234
+/* Pre-965 */
+# define PFIT_VERT_SCALE_SHIFT 20
+# define PFIT_VERT_SCALE_MASK 0xfff00000
+# define PFIT_HORIZ_SCALE_SHIFT 4
+# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+/* 965+ */
+# define PFIT_VERT_SCALE_SHIFT_965 16
+# define PFIT_VERT_SCALE_MASK_965 0x1fff0000
+# define PFIT_HORIZ_SCALE_SHIFT_965 0
+# define PFIT_HORIZ_SCALE_MASK_965 0x00001fff
+
+#define DPLL_A 0x06014
+#define DPLL_B 0x06018
+# define DPLL_VCO_ENABLE (1 << 31)
+# define DPLL_DVO_HIGH_SPEED (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE (1 << 29)
+# define DPLL_VGA_MODE_DIS (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
+# define DPLL_MODE_MASK (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */
+/**
+ * The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
+# define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15
+/* IGDNG */
+# define DPLL_FPA0_P1_POST_DIV_SHIFT 16
+
+# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
+# define PLL_REF_INPUT_DREFCLK (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
+# define PLL_REF_INPUT_SUPER_SSC (1 << 13) /* IGDNG: 120M SSC */
+# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+# define PLL_REF_INPUT_MASK (3 << 13)
+# define PLL_REF_INPUT_DMICLK (5 << 13) /* IGDNG: DMI refclk */
+# define PLL_LOAD_PULSE_PHASE_SHIFT 9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
+/* IGDNG */
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9)
+# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1)<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT)
+# define DPLL_FPA1_P1_POST_DIV_SHIFT 0
+# define DPLL_FPA1_P1_POST_DIV_MASK 0xff
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK 0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES 4
+# define SDVO_MULTIPLIER_SHIFT_VGA 0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD 0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD 0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT 24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
+/** @} */
+
+#define DPLL_TEST 0x606c
+# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
+# define DPLLB_TEST_N_BYPASS (1 << 19)
+# define DPLLB_TEST_M_BYPASS (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
+# define DPLLA_TEST_N_BYPASS (1 << 3)
+# define DPLLA_TEST_M_BYPASS (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
+
+#define D_STATE 0x6104
+#define DSPCLK_GATE_D 0x6200
+# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
+# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
+# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
+# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */
+# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */
+# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */
+# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */
+# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */
+# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */
+# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */
+# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */
+# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */
+# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */
+# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */
+# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */
+# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */
+# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */
+# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */
+# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */
+# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11)
+# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10)
+# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9)
+# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8)
+# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */
+# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */
+# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
+# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
+# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
+/**
+ * This bit must be set on the 830 to prevent hangs when turning off the
+ * overlay scaler.
+ */
+# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3)
+# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2)
+# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1)
+# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
+# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
+
+#define RENCLK_GATE_D1 0x6204
+# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */
+# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */
+# define PC_FE_CLOCK_GATE_DISABLE (1 << 11)
+# define PC_BE_CLOCK_GATE_DISABLE (1 << 10)
+# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9)
+# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8)
+# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7)
+# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6)
+# define MAG_CLOCK_GATE_DISABLE (1 << 5)
+/** This bit must be unset on 855,865 */
+# define MECI_CLOCK_GATE_DISABLE (1 << 4)
+# define DCMP_CLOCK_GATE_DISABLE (1 << 3)
+# define MEC_CLOCK_GATE_DISABLE (1 << 2)
+# define MECO_CLOCK_GATE_DISABLE (1 << 1)
+/** This bit must be set on 855,865. */
+# define SV_CLOCK_GATE_DISABLE (1 << 0)
+# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16)
+# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15)
+# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14)
+# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13)
+# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12)
+# define I915_WM_CLOCK_GATE_DISABLE (1 << 11)
+# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10)
+# define I915_PI_CLOCK_GATE_DISABLE (1 << 9)
+# define I915_DI_CLOCK_GATE_DISABLE (1 << 8)
+# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7)
+# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6)
+# define I915_SC_CLOCK_GATE_DISABLE (1 << 5)
+# define I915_FL_CLOCK_GATE_DISABLE (1 << 4)
+# define I915_DM_CLOCK_GATE_DISABLE (1 << 3)
+# define I915_PS_CLOCK_GATE_DISABLE (1 << 2)
+# define I915_CC_CLOCK_GATE_DISABLE (1 << 1)
+# define I915_BY_CLOCK_GATE_DISABLE (1 << 0)
+
+# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30)
+/** This bit must always be set on 965G/965GM */
+# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29)
+# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28)
+# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27)
+# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26)
+# define I965_GW_CLOCK_GATE_DISABLE (1 << 25)
+# define I965_TD_CLOCK_GATE_DISABLE (1 << 24)
+/** This bit must always be set on 965G */
+# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23)
+# define I965_IC_CLOCK_GATE_DISABLE (1 << 22)
+# define I965_EU_CLOCK_GATE_DISABLE (1 << 21)
+# define I965_IF_CLOCK_GATE_DISABLE (1 << 20)
+# define I965_TC_CLOCK_GATE_DISABLE (1 << 19)
+# define I965_SO_CLOCK_GATE_DISABLE (1 << 17)
+# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16)
+# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15)
+# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14)
+# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13)
+# define I965_EM_CLOCK_GATE_DISABLE (1 << 12)
+# define I965_UC_CLOCK_GATE_DISABLE (1 << 11)
+# define I965_SI_CLOCK_GATE_DISABLE (1 << 6)
+# define I965_MT_CLOCK_GATE_DISABLE (1 << 5)
+# define I965_PL_CLOCK_GATE_DISABLE (1 << 4)
+# define I965_DG_CLOCK_GATE_DISABLE (1 << 3)
+# define I965_QC_CLOCK_GATE_DISABLE (1 << 2)
+# define I965_FT_CLOCK_GATE_DISABLE (1 << 1)
+# define I965_DM_CLOCK_GATE_DISABLE (1 << 0)
+
+#define RENCLK_GATE_D2 0x6208
+#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9)
+#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7)
+#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6)
+#define RAMCLK_GATE_D 0x6210 /* CRL only */
+#define DEUC 0x6214 /* CRL only */
+
+/*
+ * This is a PCI config space register to manipulate backlight brightness
+ * It is used when the BLM_LEGACY_MODE is turned on. When enabled, the first
+ * byte of this config register sets brightness within the range from
+ * 0 to 0xff
+ */
+#define LEGACY_BACKLIGHT_BRIGHTNESS 0xf4
+
+#define BLC_PWM_CTL 0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
+#define BACKLIGHT_MODULATION_FREQ_SHIFT2 (16)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
+#define BACKLIGHT_MODULATION_FREQ_MASK2 (0xffff << 16)
+#define BLM_LEGACY_MODE (1 << 16)
+
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+
+/* On 965+ backlight control is in another register */
+#define BLC_PWM_CTL2 0x61250
+#define BLM_LEGACY_MODE2 (1 << 30)
+
+#define BLM_CTL 0x61260
+#define BLM_THRESHOLD_0 0x61270
+#define BLM_THRESHOLD_1 0x61274
+#define BLM_THRESHOLD_2 0x61278
+#define BLM_THRESHOLD_3 0x6127c
+#define BLM_THRESHOLD_4 0x61280
+#define BLM_THRESHOLD_5 0x61284
+
+#define BLM_ACCUMULATOR_0 0x61290
+#define BLM_ACCUMULATOR_1 0x61294
+#define BLM_ACCUMULATOR_2 0x61298
+#define BLM_ACCUMULATOR_3 0x6129c
+#define BLM_ACCUMULATOR_4 0x612a0
+#define BLM_ACCUMULATOR_5 0x612a4
+
+#define FPA0 0x06040
+#define FPA1 0x06044
+#define FPB0 0x06048
+#define FPB1 0x0604c
+# define FP_N_DIV_MASK 0x003f0000
+# define FP_N_IGD_DIV_MASK 0x00ff0000
+# define FP_N_DIV_SHIFT 16
+# define FP_M1_DIV_MASK 0x00003f00
+# define FP_M1_DIV_SHIFT 8
+# define FP_M2_DIV_MASK 0x0000003f
+# define FP_M2_IGD_DIV_MASK 0x000000ff
+# define FP_M2_DIV_SHIFT 0
+
+#define PORT_HOTPLUG_EN 0x61110
+# define HDMIB_HOTPLUG_INT_EN (1 << 29)
+# define HDMIC_HOTPLUG_INT_EN (1 << 28)
+# define HDMID_HOTPLUG_INT_EN (1 << 27)
+# define SDVOB_HOTPLUG_INT_EN (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN (1 << 25)
+# define TV_HOTPLUG_INT_EN (1 << 18)
+# define CRT_HOTPLUG_INT_EN (1 << 9)
+# define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
+/* must use period 64 on GM45 according to docs */
+# define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
+# define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
+# define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
+# define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
+# define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
+# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
+# define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
+# define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
+# define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
+# define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
+
+#define PORT_HOTPLUG_STAT 0x61114
+# define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
+# define HDMIC_HOTPLUG_INT_STATUS (1 << 28)
+# define HDMID_HOTPLUG_INT_STATUS (1 << 27)
+# define CRT_HOTPLUG_INT_STATUS (1 << 11)
+# define TV_HOTPLUG_INT_STATUS (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
+
+#define SDVOB 0x61140
+#define SDVOC 0x61160
+#define SDVO_ENABLE (1 << 31)
+#define SDVO_PIPE_B_SELECT (1 << 30)
+#define SDVO_STALL_SELECT (1 << 29)
+#define SDVO_INTERRUPT_ENABLE (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT 23
+#define SDVO_PHASE_SELECT_MASK (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
+#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_ENCODING_SDVO (0x0 << 10)
+#define SDVO_ENCODING_HDMI (0x2 << 10)
+/** Requird for HDMI operation */
+#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
+#define SDVO_COLOR_NOT_FULL_RANGE (1 << 8)
+#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVO_AUDIO_ENABLE (1 << 6)
+/** New with 965, default is to be set */
+#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4)
+/** New with 965, default is to be set */
+#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3)
+/** 915/945 only, read-only bit */
+#define SDVOB_PCIE_CONCURRENCY (1 << 3)
+#define SDVO_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK (1 << 17)
+
+#define UDIB_SVB_SHB_CODES 0x61144
+#define UDIB_SHA_BLANK_CODES 0x61148
+#define UDIB_START_END_FILL_CODES 0x6114c
+
+
+#define SDVOUDI 0x61150
+
+#define I830_HTOTAL_MASK 0xfff0000
+#define I830_HACTIVE_MASK 0x7ff
+
+#define I830_HBLANKEND_MASK 0xfff0000
+#define I830_HBLANKSTART_MASK 0xfff
+
+#define I830_HSYNCEND_MASK 0xfff0000
+#define I830_HSYNCSTART_MASK 0xfff
+
+#define I830_VTOTAL_MASK 0xfff0000
+#define I830_VACTIVE_MASK 0x7ff
+
+#define I830_VBLANKEND_MASK 0xfff0000
+#define I830_VBLANKSTART_MASK 0xfff
+
+#define I830_VSYNCEND_MASK 0xfff0000
+#define I830_VSYNCSTART_MASK 0xfff
+
+#define I830_PIPEA_HORZ_MASK 0x7ff0000
+#define I830_PIPEA_VERT_MASK 0x7ff
+
+#define ADPA 0x61100
+#define ADPA_DAC_ENABLE (1<<31)
+#define ADPA_DAC_DISABLE 0
+#define ADPA_PIPE_SELECT_MASK (1<<30)
+#define ADPA_PIPE_A_SELECT 0
+#define ADPA_PIPE_B_SELECT (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY 0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW 0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW 0
+
+
+#define DVOA 0x61120
+#define DVOB 0x61140
+#define DVOC 0x61160
+#define DVO_ENABLE (1 << 31)
+#define DVO_PIPE_B_SELECT (1 << 30)
+#define DVO_PIPE_STALL_UNUSED (0 << 28)
+#define DVO_PIPE_STALL (1 << 28)
+#define DVO_PIPE_STALL_TV (2 << 28)
+#define DVO_PIPE_STALL_MASK (3 << 28)
+#define DVO_USE_VGA_SYNC (1 << 15)
+#define DVO_DATA_ORDER_I740 (0 << 14)
+#define DVO_DATA_ORDER_FP (1 << 14)
+#define DVO_VSYNC_DISABLE (1 << 11)
+#define DVO_HSYNC_DISABLE (1 << 10)
+#define DVO_VSYNC_TRISTATE (1 << 9)
+#define DVO_HSYNC_TRISTATE (1 << 8)
+#define DVO_BORDER_ENABLE (1 << 7)
+#define DVO_DATA_ORDER_GBRG (1 << 6)
+#define DVO_DATA_ORDER_RGGB (0 << 6)
+#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
+#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
+#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
+#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
+#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
+#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
+#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
+#define DVO_PRESERVE_MASK (0x7<<24)
+
+#define DVOA_SRCDIM 0x61124
+#define DVOB_SRCDIM 0x61144
+#define DVOC_SRCDIM 0x61164
+#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
+#define DVO_SRCDIM_VERTICAL_SHIFT 0
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS 0x61180
+/**
+ * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN (1 << 31)
+/** Selects pipe B for LVDS data. Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT (1 << 30)
+
+/* on 965, dithering is enabled in this register, not PFIT_CONTROL */
+# define LVDS_DITHER_ENABLE (1 << 25)
+
+/*
+ * Selects between .0 and .1 formats:
+ *
+ * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0
+ * 1 = 1x24.1 or 2x24.1
+ */
+# define LVDS_DATA_FORMAT_DOT_ONE (1 << 24)
+
+/* Using LE instead of HS on second channel control signal */
+# define LVDS_LE_CONTROL_ENABLE (1 << 23)
+
+/* Using LF instead of VS on second channel control signal */
+# define LVDS_LF_CONTROL_ENABLE (1 << 22)
+
+/* invert vsync signal polarity */
+# define LVDS_VSYNC_POLARITY_INVERT (1 << 21)
+
+/* invert hsync signal polarity */
+# define LVDS_HSYNC_POLARITY_INVERT (1 << 20)
+
+/* invert display enable signal polarity */
+# define LVDS_DE_POLARITY_INVERT (1 << 19)
+
+/*
+ * Control signals for second channel, ignored in single channel modes
+ */
+
+/* send DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_DE_HS_VS (0 << 17)
+
+# define LVDS_SECOND_CHANNEL_RESERVED (1 << 17)
+
+/* Send zeros instead of DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_ZEROS (2 << 17)
+
+/* Set DE=0, HS=LE, VS=LF on second channel */
+# define LVDS_SECOND_CHANNEL_HS_VS (3 << 17)
+
+/*
+ * Send duplicate data for channel reserved bits, otherwise send zeros
+ */
+# define LVDS_CHANNEL_DUP_RESERVED (1 << 16)
+
+/*
+ * Enable border for unscaled (or aspect-scaled) display
+ */
+# define LVDS_BORDER_ENABLE (1 << 15)
+
+/*
+ * Tri-state the LVDS buffers when powered down, otherwise
+ * they are set to 0V
+ */
+# define LVDS_POWER_DOWN_TRI_STATE (1 << 10)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK (3 << 6)
+# define LVDS_A3_POWER_DOWN (0 << 6)
+# define LVDS_A3_POWER_UP (3 << 6)
+/**
+ * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK (3 << 4)
+# define LVDS_CLKB_POWER_DOWN (0 << 4)
+# define LVDS_CLKB_POWER_UP (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode. The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK (3 << 2)
+# define LVDS_B0B3_POWER_DOWN (0 << 2)
+# define LVDS_B0B3_POWER_UP (3 << 2)
+
+/** @} */
+
+#define DP_B 0x64100
+#define DPB_AUX_CH_CTL 0x64110
+#define DPB_AUX_CH_DATA1 0x64114
+#define DPB_AUX_CH_DATA2 0x64118
+#define DPB_AUX_CH_DATA3 0x6411c
+#define DPB_AUX_CH_DATA4 0x64120
+#define DPB_AUX_CH_DATA5 0x64124
+
+#define DP_C 0x64200
+#define DPC_AUX_CH_CTL 0x64210
+#define DPC_AUX_CH_DATA1 0x64214
+#define DPC_AUX_CH_DATA2 0x64218
+#define DPC_AUX_CH_DATA3 0x6421c
+#define DPC_AUX_CH_DATA4 0x64220
+#define DPC_AUX_CH_DATA5 0x64224
+
+#define DP_D 0x64300
+#define DPD_AUX_CH_CTL 0x64310
+#define DPD_AUX_CH_DATA1 0x64314
+#define DPD_AUX_CH_DATA2 0x64318
+#define DPD_AUX_CH_DATA3 0x6431c
+#define DPD_AUX_CH_DATA4 0x64320
+#define DPD_AUX_CH_DATA5 0x64324
+
+/*
+ * Two channel clock control. Turn this on if you need clkb for two channel mode
+ * Overridden by global LVDS power sequencing
+ */
+
+/* clkb off */
+# define LVDS_CLKB_POWER_DOWN (0 << 4)
+
+/* powered up, but clkb forced to 0 */
+# define LVDS_CLKB_POWER_PARTIAL (1 << 4)
+
+/* clock B running */
+# define LVDS_CLKB_POWER_UP (3 << 4)
+
+/*
+ * Two channel mode B0-B2 control. Sets state when power is on.
+ * Set to POWER_DOWN in single channel mode, other settings enable
+ * two channel mode. The CLKB power control controls whether that clock
+ * is enabled during two channel mode.
+ *
+ */
+/* Everything is off, including B3 and CLKB */
+# define LVDS_B_POWER_DOWN (0 << 2)
+
+/* B0, B1, B2 and data lines forced to 0. timing is active */
+# define LVDS_B_POWER_PARTIAL (1 << 2)
+
+/* data lines active (both timing and colour) */
+# define LVDS_B_POWER_UP (3 << 2)
+
+/** @defgroup TV_CTL
+ * @{
+ */
+#define TV_CTL 0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE (1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT (1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE (0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO (1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT (2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28)
+# define TV_TRILEVEL_SYNC (1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC (1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X (0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X (1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE (2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X (3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE (1 << 17)
+/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */
+# define TV_PAL_BURST (1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK (7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX (1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX (1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf)
+# define TV_FUSE_STATE_MASK (3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED (0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED (2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL (0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1 (1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2 (2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3 (3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4 (4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5 (5 << 0)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
+# define TV_TEST_MODE_MASK (7 << 0)
+/** @} */
+
+/** @defgroup TV_DAC
+ * @{
+ */
+#define TV_DAC 0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG (1 << 31)
+# define TVDAC_SENSE_MASK (7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE (1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE (1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE (1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN (1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL (1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL (1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL (1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE (1 << 7)
+/** Sets the slew rate. Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST (1 << 6)
+# define DAC_A_1_3_V (0 << 4)
+# define DAC_A_1_1_V (1 << 4)
+# define DAC_A_0_7_V (2 << 4)
+# define DAC_A_MASK (3 << 4)
+# define DAC_B_1_3_V (0 << 2)
+# define DAC_B_1_1_V (1 << 2)
+# define DAC_B_0_7_V (2 << 2)
+# define DAC_B_MASK (3 << 2)
+# define DAC_C_1_3_V (0 << 0)
+# define DAC_C_1_1_V (1 << 0)
+# define DAC_C_0_7_V (2 << 0)
+# define DAC_C_MASK (3 << 0)
+/** @} */
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y 0x68010
+# define TV_RY_MASK 0x07ff0000
+# define TV_RY_SHIFT 16
+# define TV_GY_MASK 0x00000fff
+# define TV_GY_SHIFT 0
+
+#define TV_CSC_Y2 0x68014
+# define TV_BY_MASK 0x07ff0000
+# define TV_BY_SHIFT 16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK 0x000003ff
+# define TV_AY_SHIFT 0
+
+#define TV_CSC_U 0x68018
+# define TV_RU_MASK 0x07ff0000
+# define TV_RU_SHIFT 16
+# define TV_GU_MASK 0x000007ff
+# define TV_GU_SHIFT 0
+
+#define TV_CSC_U2 0x6801c
+# define TV_BU_MASK 0x07ff0000
+# define TV_BU_SHIFT 16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK 0x000003ff
+# define TV_AU_SHIFT 0
+
+#define TV_CSC_V 0x68020
+# define TV_RV_MASK 0x0fff0000
+# define TV_RV_SHIFT 16
+# define TV_GV_MASK 0x000007ff
+# define TV_GV_SHIFT 0
+
+#define TV_CSC_V2 0x68024
+# define TV_BV_MASK 0x07ff0000
+# define TV_BV_SHIFT 16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK 0x000007ff
+# define TV_AV_SHIFT 0
+
+/** @defgroup TV_CSC_KNOBS
+ * @{
+ */
+#define TV_CLR_KNOBS 0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK 0xff000000
+# define TV_BRIGHTNESS_SHIFT 24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK 0x00ff0000
+# define TV_CONTRAST_SHIFT 16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK 0x0000ff00
+# define TV_SATURATION_SHIFT 8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK 0x000000ff
+# define TV_HUE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CLR_LEVEL
+ * @{
+ */
+#define TV_CLR_LEVEL 0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK 0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT 16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK 0x000001ff
+# define TV_BLANK_LEVEL_SHIFT 0
+/* @} */
+
+/** @defgroup TV_H_CTL_1
+ * @{
+ */
+#define TV_H_CTL_1 0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK 0x1fff0000
+# define TV_HSYNC_END_SHIFT 16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK 0x00001fff
+# define TV_HTOTAL_SHIFT 0
+/** @} */
+
+/** @defgroup TV_H_CTL_2
+ * @{
+ */
+#define TV_H_CTL_2 0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA (1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT 16
+# define TV_HBURST_START_MASK 0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT 0
+# define TV_HBURST_LEN_MASK 0x0001fff
+/** @} */
+
+/** @defgroup TV_H_CTL_3
+ * @{
+ */
+#define TV_H_CTL_3 0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT 16
+# define TV_HBLANK_END_MASK 0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT 0
+# define TV_HBLANK_START_MASK 0x0001fff
+/** @} */
+
+/** @defgroup TV_V_CTL_1
+ * @{
+ */
+#define TV_V_CTL_1 0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT 16
+# define TV_NBR_END_MASK 0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT 8
+# define TV_VI_END_F1_MASK 0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT 0
+# define TV_VI_END_F2_MASK 0x0000003f
+/** @} */
+
+/** @defgroup TV_V_CTL_2
+ * @{
+ */
+#define TV_V_CTL_2 0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK 0x07ff0000
+# define TV_VSYNC_LEN_SHIFT 16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK 0x00007f00
+# define TV_VSYNC_START_F1_SHIFT 8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK 0x0000007f
+# define TV_VSYNC_START_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_3
+ * @{
+ */
+#define TV_V_CTL_3 0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA (1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK 0x007f0000
+# define TV_VEQ_LEN_SHIFT 16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK 0x0007f00
+# define TV_VEQ_START_F1_SHIFT 8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK 0x000007f
+# define TV_VEQ_START_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_4
+ * @{
+ */
+#define TV_V_CTL_4 0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK 0x003f0000
+# define TV_VBURST_START_F1_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK 0x000000ff
+# define TV_VBURST_END_F1_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_5
+ * @{
+ */
+#define TV_V_CTL_5 0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK 0x003f0000
+# define TV_VBURST_START_F2_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK 0x000000ff
+# define TV_VBURST_END_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_6
+ * @{
+ */
+#define TV_V_CTL_6 0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK 0x003f0000
+# define TV_VBURST_START_F3_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK 0x000000ff
+# define TV_VBURST_END_F3_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_7
+ * @{
+ */
+#define TV_V_CTL_7 0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK 0x003f0000
+# define TV_VBURST_START_F4_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK 0x000000ff
+# define TV_VBURST_END_F4_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_1
+ * @{
+ */
+#define TV_SC_CTL_1 0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN (1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN (1 << 30)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN (1 << 29)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2 (0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4 (1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8 (2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER (3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK 0x00ff0000
+# define TV_BURST_LEVEL_SHIFT 16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK 0x00000fff
+# define TV_SCDDA1_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_2
+ * @{
+ */
+#define TV_SC_CTL_2 0x68064
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK 0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT 16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK 0x00007fff
+# define TV_SCDDA2_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_3
+ * @{
+ */
+#define TV_SC_CTL_3 0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK 0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT 16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK 0x00007fff
+# define TV_SCDDA3_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_WIN_POS
+ * @{
+ */
+#define TV_WIN_POS 0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK 0x1fff0000
+# define TV_XPOS_SHIFT 16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK 0x00000fff
+# define TV_YPOS_SHIFT 0
+/** @} */
+
+/** @defgroup TV_WIN_SIZE
+ * @{
+ */
+#define TV_WIN_SIZE 0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK 0x1fff0000
+# define TV_XSIZE_SHIFT 16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK 0x00000fff
+# define TV_YSIZE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_1
+ * @{
+ */
+#define TV_FILTER_CTL_1 0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE (1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS (1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT (1 << 28)
+# define TV_VADAPT_MODE_MASK (3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST (0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE (1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST (3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate. TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK 0x00003fff
+# define TV_HSCALE_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_2
+ * @{
+ */
+#define TV_FILTER_CTL_2 0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK 0x00038000
+# define TV_VSCALE_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK 0x00007fff
+# define TV_VSCALE_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_3
+ * @{
+ */
+#define TV_FILTER_CTL_3 0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK 0x00038000
+# define TV_VSCALE_IP_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK 0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CC_CONTROL
+ * @{
+ */
+#define TV_CC_CONTROL 0x68090
+# define TV_CC_ENABLE (1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK (1 << 27)
+# define TV_CC_FID_SHIFT 27
+/** Sets the horizontal position of the CC data. Usually 135. */
+# define TV_CC_HOFF_MASK 0x03ff0000
+# define TV_CC_HOFF_SHIFT 16
+/** Sets the vertical position of the CC data. Usually 21 */
+# define TV_CC_LINE_MASK 0x0000003f
+# define TV_CC_LINE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CC_DATA
+ * @{
+ */
+#define TV_CC_DATA 0x68094
+# define TV_CC_RDY (1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK 0x007f0000
+# define TV_CC_DATA_2_SHIFT 16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK 0x0000007f
+# define TV_CC_DATA_1_SHIFT 0
+/** @}
+ */
+
+/** @{ */
+#define TV_H_LUMA_0 0x68100
+#define TV_H_LUMA_59 0x681ec
+#define TV_H_CHROMA_0 0x68200
+#define TV_H_CHROMA_59 0x682ec
+#define TV_V_LUMA_0 0x68300
+#define TV_V_LUMA_42 0x683a8
+#define TV_V_CHROMA_0 0x68400
+#define TV_V_CHROMA_42 0x684a8
+/** @} */
+
+#define PIPEA_DSL 0x70000
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (1<<30)
+#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPEACONF_SINGLE_WIDE 0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED (1<<25)
+#define PIPEACONF_PALETTE 0
+#define PIPEACONF_GAMMA (1<<24)
+/* IGDNG: gamma */
+#define PIPECONF_PALETTE_8BIT (0<<24)
+#define PIPECONF_PALETTE_10BIT (1<<24)
+#define PIPECONF_PALETTE_12BIT (2<<24)
+#define PIPECONF_FORCE_BORDER (1<<25)
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+/* IGDNG */
+#define PIPECONF_MSA_TIMING_DELAY (0<<18) /* for eDP */
+#define PIPECONF_NO_DYNAMIC_RATE_CHANGE (0 << 16)
+#define PIPECONF_NO_ROTATION (0<<14)
+#define PIPECONF_FULL_COLOR_RANGE (0<<13)
+#define PIPECONF_CE_COLOR_RANGE (1<<13)
+#define PIPECONF_COLOR_SPACE_RGB (0<<11)
+#define PIPECONF_COLOR_SPACE_YUV601 (1<<11)
+#define PIPECONF_COLOR_SPACE_YUV709 (2<<11)
+#define PIPECONF_CONNECT_DEFAULT (0<<9)
+#define PIPECONF_8BPP (0<<5)
+#define PIPECONF_10BPP (1<<5)
+#define PIPECONF_6BPP (2<<5)
+#define PIPECONF_12BPP (3<<5)
+#define PIPECONF_ENABLE_DITHER (1<<4)
+#define PIPECONF_DITHER_SPATIAL (0<<2)
+#define PIPECONF_DITHER_ST1 (1<<2)
+#define PIPECONF_DITHER_ST2 (2<<2)
+#define PIPECONF_DITHER_TEMPORAL (3<<2)
+
+#define PIPEAGCMAXRED 0x70010
+#define PIPEAGCMAXGREEN 0x70014
+#define PIPEAGCMAXBLUE 0x70018
+#define PIPEASTAT 0x70024
+# define FIFO_UNDERRUN (1 << 31)
+# define CRC_ERROR_ENABLE (1 << 29)
+# define CRC_DONE_ENABLE (1 << 28)
+# define GMBUS_EVENT_ENABLE (1 << 27)
+# define VSYNC_INT_ENABLE (1 << 25)
+# define DLINE_COMPARE_ENABLE (1 << 24)
+# define DPST_EVENT_ENABLE (1 << 23)
+# define LBLC_EVENT_ENABLE (1 << 22)
+# define OFIELD_INT_ENABLE (1 << 21)
+# define EFIELD_INT_ENABLE (1 << 20)
+# define SVBLANK_INT_ENABLE (1 << 18)
+# define VBLANK_INT_ENABLE (1 << 17)
+# define OREG_UPDATE_ENABLE (1 << 16)
+# define CRC_ERROR_INT_STATUS (1 << 13)
+# define CRC_DONE_INT_STATUS (1 << 12)
+# define GMBUS_INT_STATUS (1 << 11)
+# define VSYNC_INT_STATUS (1 << 9)
+# define DLINE_COMPARE_STATUS (1 << 8)
+# define DPST_EVENT_STATUS (1 << 7)
+# define LBLC_EVENT_STATUS (1 << 6)
+# define OFIELD_INT_STATUS (1 << 5)
+# define EFIELD_INT_STATUS (1 << 4)
+# define SVBLANK_INT_STATUS (1 << 2)
+# define VBLANK_INT_STATUS (1 << 1)
+# define OREG_UPDATE_STATUS (1 << 0)
+
+
+#define DSPARB 0x70030
+#define DSPARB_CSTART_SHIFT 7
+#define DSPARB_BSTART_SHIFT 0
+#define DSPARB_BEND_SHIFT 9 /* on 855 */
+#define DSPARB_AEND_SHIFT 0
+#define DSPFW1 0x70034
+#define DSPFW2 0x70038
+#define DSPFW3 0x7003c
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ * do {
+ * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT;
+ * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> PIPE_FRAME_LOW_SHIFT);
+ * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT);
+ * } while (high1 != high2);
+ * frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH 0x70040
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT 0
+#define PIPEAFRAMEPIXEL 0x70044
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_PIXEL_SHIFT 0
+
+/*
+ * Computing GMCH M and N values.
+ *
+ * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
+ *
+ * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
+ *
+ * The GMCH value is used internally
+ */
+#define PIPEA_GMCH_DATA_M 0x70050
+
+/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
+#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25)
+#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25
+
+#define PIPE_GMCH_DATA_M_MASK (0xffffff)
+
+#define PIPEA_GMCH_DATA_N 0x70054
+#define PIPE_GMCH_DATA_N_MASK (0xffffff)
+
+/*
+ * Computing Link M and N values.
+ *
+ * Link M / N = pixel_clock / ls_clk
+ *
+ * (the DP spec calls pixel_clock the 'strm_clk')
+ *
+ * The Link value is transmitted in the Main Stream
+ * Attributes and VB-ID.
+ */
+
+#define PIPEA_DP_LINK_M 0x70060
+#define PIPEA_DP_LINK_M_MASK (0xffffff)
+
+#define PIPEA_DP_LINK_N 0x70064
+#define PIPEA_DP_LINK_N_MASK (0xffffff)
+
+#define PIPEB_DSL 0x71000
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE (1<<31)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_DOUBLE_WIDE (1<<30)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_GAMMA (1<<24)
+#define PIPEBCONF_PALETTE 0
+
+#define PIPEBGCMAXRED 0x71010
+#define PIPEBGCMAXGREEN 0x71014
+#define PIPEBGCMAXBLUE 0x71018
+#define PIPEBSTAT 0x71024
+#define PIPEBFRAMEHIGH 0x71040
+#define PIPEBFRAMEPIXEL 0x71044
+
+#define PIPEB_GMCH_DATA_M 0x71050
+#define PIPEB_GMCH_DATA_N 0x71054
+#define PIPEB_DP_LINK_M 0x71060
+#define PIPEB_DP_LINK_N 0x71064
+
+#define DSPACNTR 0x70180
+#define DSPBCNTR 0x71180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#define DISPLAY_PLANE_TILED (1<<10)
+#define DISPPLANE_GAMMA_ENABLE (1<<30)
+#define DISPPLANE_GAMMA_DISABLE 0
+#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#define DISPPLANE_8BPP (0x2<<26)
+#define DISPPLANE_15_16BPP (0x4<<26)
+#define DISPPLANE_16BPP (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) /* IGDNG: BGRX */
+#define DISPPLANE_32BPP (0x7<<26) /* IGDNG: not support */
+/* IGDNG */
+#define DISPPLANE_32BPP_10 (0x8<<26) /* 2:10:10:10 */
+#define DISPPLANE_32BPP_BGRX (0xa<<26)
+#define DISPPLANE_64BPP (0xc<<26)
+#define DISPPLANE_32BPP_RGBX (0xe<<26)
+#define DISPPLANE_STEREO_ENABLE (1<<25)
+#define DISPPLANE_STEREO_DISABLE 0
+#define DISPPLANE_SEL_PIPE_MASK (1<<24)
+#define DISPPLANE_SEL_PIPE_A 0 /* IGDNG: don't use */
+#define DISPPLANE_SEL_PIPE_B (1<<24)
+#define DISPPLANE_NORMAL_RANGE (0<<25)
+#define DISPPLANE_EXT_RANGE (1<<25)
+/* IGDNG */
+#define DISPPLANE_CSC_BYPASS (0<<24)
+#define DISPPLANE_CSC_PASSTHROUGH (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE 0
+#define DISPPLANE_LINE_DOUBLE (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE 0
+#define DISPPLANE_STEREO_POLARITY_FIRST 0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE 0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
+/* IGDNG */
+#define DISPPLANE_X_TILE (1<<10)
+#define DISPPLANE_LINEAR (0<<10)
+
+#define DSPABASE 0x70184
+/* IGDNG */
+#define DSPALINOFF 0x70184
+#define DSPASTRIDE 0x70188
+
+#define DSPBBASE 0x71184
+/* IGDNG */
+#define DSPBLINOFF 0x71184
+#define DSPBADDR DSPBBASE
+#define DSPBSTRIDE 0x71188
+
+#define DSPAKEYVAL 0x70194
+#define DSPAKEYMASK 0x70198
+
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+
+#define DSPASURF 0x7019C
+#define DSPATILEOFF 0x701A4
+
+#define DSPBSURF 0x7119C
+#define DSPBTILEOFF 0x711A4
+
+#define VGACNTRL 0x71400
+# define VGA_DISP_DISABLE (1 << 31)
+# define VGA_2X_MODE (1 << 30)
+# define VGA_PIPE_B_SELECT (1 << 29)
+
+/* Various masks for reserved bits, etc. */
+#define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \
+ (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \
+ (1<<2)|(1<<1)|1|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)))
+#define I830_FWATER2_MASK ~(0)
+
+#define DV0A_RESERVED ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1)
+#define DV0B_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1)
+#define VGA0_N_DIVISOR_MASK ((1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define VGA0_M1_DIVISOR_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define VGA0_M2_DIVISOR_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define VGA0_M1M2N_RESERVED ~(VGA0_N_DIVISOR_MASK|VGA0_M1_DIVISOR_MASK|VGA0_M2_DIVISOR_MASK)
+#define VGA0_POSTDIV_MASK ((1<<7)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define VGA1_POSTDIV_MASK ((1<<15)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define VGA_POSTDIV_RESERVED ~(VGA0_POSTDIV_MASK|VGA1_POSTDIV_MASK|(1<<7)|(1<<15))
+#define DPLLA_POSTDIV_MASK ((1<<23)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define DPLLA_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<22)|(1<<15)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define ADPA_RESERVED ((1<<2)|(1<<1)|1|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define SUPER_WORD 32
+#define BURST_A_MASK ((1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define BURST_B_MASK ((1<<26)|(1<<25)|(1<<24))
+#define WATER_A_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define WATER_B_MASK ((1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define WATER_RESERVED ((1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<7)|(1<<6))
+#define PIPEACONF_RESERVED ((1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff)
+#define PIPEBCONF_RESERVED ((1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff)
+#define DSPACNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0xffff)
+#define DSPBCNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0x7ffe)
+
+#define I830_GMCH_CTRL 0x52
+
+#define I830_GMCH_ENABLED 0x4
+#define I830_GMCH_MEM_MASK 0x1
+#define I830_GMCH_MEM_64M 0x1
+#define I830_GMCH_MEM_128M 0
+
+#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_DISABLED 0x00
+#define I830_GMCH_GMS_LOCAL 0x10
+#define I830_GMCH_GMS_STOLEN_512 0x20
+#define I830_GMCH_GMS_STOLEN_1024 0x30
+#define I830_GMCH_GMS_STOLEN_8192 0x40
+
+#define I830_RDRAM_CHANNEL_TYPE 0x03010
+#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
+#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+
+#define I855_GMCH_GMS_MASK (0xF << 4)
+#define I855_GMCH_GMS_DISABLED 0x00
+#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+#define I915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
+#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
+#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
+#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
+#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
+
+
+#define I915_GCFGC 0xf0
+#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK (7 << 4)
+
+#define I855_HPLLCC 0xc0
+#define I855_CLOCK_CONTROL_MASK (3 << 0)
+#define I855_CLOCK_133_200 (0 << 0)
+#define I855_CLOCK_100_200 (1 << 0)
+#define I855_CLOCK_100_133 (2 << 0)
+#define I855_CLOCK_166_250 (3 << 0)
+
+/* BLT commands */
+#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3))
+#define COLOR_BLT_WRITE_ALPHA (1<<21)
+#define COLOR_BLT_WRITE_RGB (1<<20)
+
+#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4))
+#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB (1<<20)
+#define XY_COLOR_BLT_TILED (1<<11)
+
+#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1)
+
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
+
+#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4)
+#define SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define SRC_COPY_BLT_WRITE_RGB (1<<20)
+
+#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22))
+
+#define XY_MONO_PAT_BLT_CMD ((0x2<<29)|(0x52<<22)|0x7)
+#define XY_MONO_PAT_VERT_SEED ((1<<10)|(1<<9)|(1<<8))
+#define XY_MONO_PAT_HORT_SEED ((1<<14)|(1<<13)|(1<<12))
+#define XY_MONO_PAT_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_PAT_BLT_WRITE_RGB (1<<20)
+
+#define XY_MONO_SRC_BLT_CMD ((0x2<<29)|(0x54<<22)|(0x6))
+#define XY_MONO_SRC_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_SRC_BLT_WRITE_RGB (1<<20)
+
+#define STATE3D_FOG_MODE ((3<<29)|(0x1d<<24)|(0x89<<16)|2)
+#define FOG_MODE_VERTEX (1<<31)
+
+#define DISABLE_TEX_TRANSFORM (1<<28)
+#define TEXTURE_SET(x) (x<<29)
+
+#define STATE3D_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16))
+#define DISABLE_VIEWPORT_TRANSFORM (1<<31)
+#define DISABLE_PERSPECTIVE_DIVIDE (1<<29)
+
+#define MI_SET_CONTEXT (0x18<<23)
+#define CTXT_NO_RESTORE (1)
+#define CTXT_PALETTE_SAVE_DISABLE (1<<3)
+#define CTXT_PALETTE_RESTORE_DISABLE (1<<2)
+
+/* Dword 0 */
+#define MI_VERTEX_BUFFER (0x17<<23)
+#define MI_VERTEX_BUFFER_IDX(x) (x<<20)
+#define MI_VERTEX_BUFFER_PITCH(x) (x<<13)
+#define MI_VERTEX_BUFFER_WIDTH(x) (x<<6)
+/* Dword 1 */
+#define MI_VERTEX_BUFFER_DISABLE (1)
+
+/* Overlay Flip */
+#define MI_OVERLAY_FLIP (0x11<<23)
+#define MI_OVERLAY_FLIP_CONTINUE (0<<21)
+#define MI_OVERLAY_FLIP_ON (1<<21)
+#define MI_OVERLAY_FLIP_OFF (2<<21)
+
+/* Wait for Events */
+#define MI_WAIT_FOR_EVENT (0x03<<23)
+#define MI_WAIT_FOR_PIPEB_SVBLANK (1<<18)
+#define MI_WAIT_FOR_PIPEA_SVBLANK (1<<17)
+#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16)
+#define MI_WAIT_FOR_PIPEB_VBLANK (1<<7)
+#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW (1<<5)
+#define MI_WAIT_FOR_PIPEA_VBLANK (1<<3)
+#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW (1<<1)
+
+/* Set the scan line for MI_WAIT_FOR_PIPE?_SCAN_LINE_WINDOW */
+#define MI_LOAD_SCAN_LINES_INCL (0x12<<23)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA (0)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB (0x1<<20)
+
+/* Flush */
+#define MI_FLUSH (0x04<<23)
+#define MI_WRITE_DIRTY_STATE (1<<4)
+#define MI_END_SCENE (1<<3)
+#define MI_GLOBAL_SNAPSHOT_COUNT_RESET (1<<3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2)
+#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1)
+#define MI_INVALIDATE_MAP_CACHE (1<<0)
+/* broadwater flush bits */
+#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3)
+
+/* Noop */
+#define MI_NOOP 0x00
+#define MI_NOOP_WRITE_ID (1<<22)
+#define MI_NOOP_ID_MASK (1<<22 - 1)
+
+#define STATE3D_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x01<<16))
+
+/* Batch */
+#define MI_BATCH_BUFFER ((0x30 << 23) | 1)
+#define MI_BATCH_BUFFER_START (0x31 << 23)
+#define MI_BATCH_BUFFER_END (0xA << 23)
+#define MI_BATCH_NON_SECURE (1)
+#define MI_BATCH_NON_SECURE_I965 (1 << 8)
+
+/* STATE3D_FOG_MODE stuff */
+#define ENABLE_FOG_SOURCE (1<<27)
+#define ENABLE_FOG_CONST (1<<24)
+#define ENABLE_FOG_DENSITY (1<<23)
+
+#define MAX_DISPLAY_PIPES 2
+
+typedef enum {
+ CrtIndex = 0,
+ TvIndex,
+ DfpIndex,
+ LfpIndex,
+ Crt2Index,
+ Tv2Index,
+ Dfp2Index,
+ Lfp2Index,
+ NumDisplayTypes
+} DisplayType;
+
+/* What's connected to the pipes (as reported by the BIOS) */
+#define PIPE_ACTIVE_MASK 0xff
+#define PIPE_CRT_ACTIVE (1 << CrtIndex)
+#define PIPE_TV_ACTIVE (1 << TvIndex)
+#define PIPE_DFP_ACTIVE (1 << DfpIndex)
+#define PIPE_LCD_ACTIVE (1 << LfpIndex)
+#define PIPE_CRT2_ACTIVE (1 << Crt2Index)
+#define PIPE_TV2_ACTIVE (1 << Tv2Index)
+#define PIPE_DFP2_ACTIVE (1 << Dfp2Index)
+#define PIPE_LCD2_ACTIVE (1 << Lfp2Index)
+
+#define PIPE_SIZED_DISP_MASK (PIPE_DFP_ACTIVE | \
+ PIPE_LCD_ACTIVE | \
+ PIPE_DFP2_ACTIVE)
+
+#define PIPE_A_SHIFT 0
+#define PIPE_B_SHIFT 8
+#define PIPE_SHIFT(n) ((n) == 0 ? \
+ PIPE_A_SHIFT : PIPE_B_SHIFT)
+
+/*
+ * Some BIOS scratch area registers. The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+
+#define SWF0 0x71410
+#define SWF1 0x71414
+#define SWF2 0x71418
+#define SWF3 0x7141c
+#define SWF4 0x71420
+#define SWF5 0x71424
+#define SWF6 0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00 0x70410
+#define SWF01 0x70414
+#define SWF02 0x70418
+#define SWF03 0x7041c
+#define SWF04 0x70420
+#define SWF05 0x70424
+#define SWF06 0x70428
+
+#define SWF10 SWF0
+#define SWF11 SWF1
+#define SWF12 SWF2
+#define SWF13 SWF3
+#define SWF14 SWF4
+#define SWF15 SWF5
+#define SWF16 SWF6
+
+#define SWF30 0x72414
+#define SWF31 0x72418
+#define SWF32 0x7241c
+
+/*
+ * Overlay registers. These are overlay registers accessed via MMIO.
+ * Those loaded via the overlay register page are defined in i830_video.c.
+ */
+#define OVADD 0x30000
+
+#define DOVSTA 0x30008
+#define OC_BUF (0x3<<20)
+
+#define OGAMC5 0x30010
+#define OGAMC4 0x30014
+#define OGAMC3 0x30018
+#define OGAMC2 0x3001c
+#define OGAMC1 0x30020
+#define OGAMC0 0x30024
+
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A 0x0a000
+#define PALETTE_B 0x0a800
+
+/* Framebuffer compression */
+#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
+#define FBC_LL_BASE 0x03204 /* 4k page aligned */
+#define FBC_CONTROL 0x03208
+#define FBC_CTL_EN (1<<31)
+#define FBC_CTL_PERIODIC (1<<30)
+#define FBC_CTL_INTERVAL_SHIFT (16)
+#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define FBC_CTL_STRIDE_SHIFT (5)
+#define FBC_CTL_FENCENO (1<<0)
+#define FBC_COMMAND 0x0320c
+#define FBC_CMD_COMPRESS (1<<0)
+#define FBC_STATUS 0x03210
+#define FBC_STAT_COMPRESSING (1<<31)
+#define FBC_STAT_COMPRESSED (1<<30)
+#define FBC_STAT_MODIFIED (1<<29)
+#define FBC_STAT_CURRENT_LINE (1<<0)
+#define FBC_CONTROL2 0x03214
+#define FBC_CTL_FENCE_DBL (0<<4)
+#define FBC_CTL_IDLE_IMM (0<<2)
+#define FBC_CTL_IDLE_FULL (1<<2)
+#define FBC_CTL_IDLE_LINE (2<<2)
+#define FBC_CTL_IDLE_DEBUG (3<<2)
+#define FBC_CTL_CPU_FENCE (1<<1)
+#define FBC_CTL_PLANEA (0<<0)
+#define FBC_CTL_PLANEB (1<<0)
+#define FBC_FENCE_OFF 0x0321b
+#define FBC_MOD_NUM 0x03220
+#define FBC_TAG_DEBUG 0x03300
+
+#define FBC_LL_SIZE (1536)
+#define FBC_LL_PAD (32)
+
+/* Framebuffer compression version 2 */
+#define DPFC_CB_BASE 0x3200
+#define DPFC_CONTROL 0x3208
+#define DPFC_CTL_EN (1<<31)
+#define DPFC_CTL_PLANEA (0<<30)
+#define DPFC_CTL_PLANEB (1<<30)
+#define DPFC_CTL_FENCE_EN (1<<29)
+#define DPFC_CTL_LIMIT_1X (0<<6)
+#define DPFC_CTL_LIMIT_2X (1<<6)
+#define DPFC_CTL_LIMIT_4X (2<<6)
+#define DPFC_RECOMP_CTL 0x320c
+#define DPFC_RECOMP_STALL_EN (1<<27)
+#define DPFC_RECOMP_STALL_WM_SHIFT (16)
+#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000)
+#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0)
+#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f)
+#define DPFC_STATUS 0x3210
+#define DPFC_INVAL_SEG_SHIFT (16)
+#define DPFC_INVAL_SEG_MASK (0x07ff0000)
+#define DPFC_COMP_SEG_SHIFT (0)
+#define DPFC_COMP_SEG_MASK (0x000003ff)
+#define DPFC_STATUS2 0x3214
+#define DPFC_FENCE_YOFF 0x3218
+
+#define PEG_BAND_GAP_DATA 0x14d68
+
+#define MCHBAR_RENDER_STANDBY 0x111B8
+#define RENDER_STANDBY_ENABLE (1 << 30)
+
+/* IGDNG */
+
+/* warmup time in us */
+#define WARMUP_PCH_REF_CLK_SSC_MOD 1
+#define WARMUP_PCH_FDI_RECEIVER_PLL 25
+#define WARMUP_PCH_DPLL 50
+#define WARMUP_CPU_DP_PLL 20
+#define WARMUP_CPU_FDI_TRANSMITTER_PLL 10
+#define WARMUP_DMI_LATENCY 20
+#define FDI_TRAIN_PATTERN_1_TIME 0.5
+#define FDI_TRAIN_PATTERN_2_TIME 1.5
+#define FDI_ONE_IDLE_PATTERN_TIME 31
+
+#define CPU_VGACNTRL 0x41000
+
+#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
+#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
+#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2)
+#define DIGITAL_PORTA_NO_DETECT (0 << 0)
+#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1)
+#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0)
+
+/* refresh rate hardware control */
+#define RR_HW_CTL 0x45300
+#define RR_HW_LOW_POWER_FRAMES_MASK 0xff
+#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
+
+#define FDI_PLL_BIOS_0 0x46000
+#define FDI_PLL_BIOS_1 0x46004
+#define FDI_PLL_BIOS_2 0x46008
+#define DISPLAY_PORT_PLL_BIOS_0 0x4600c
+#define DISPLAY_PORT_PLL_BIOS_1 0x46010
+#define DISPLAY_PORT_PLL_BIOS_2 0x46014
+
+#define FDI_PLL_FREQ_CTL 0x46030
+#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
+#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
+#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff
+
+#define PIPEA_DATA_M1 0x60030
+#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
+#define TU_SIZE_MASK 0x7e000000
+#define PIPEA_DATA_M1_OFFSET 0
+#define PIPEA_DATA_N1 0x60034
+#define PIPEA_DATA_N1_OFFSET 0
+
+#define PIPEA_DATA_M2 0x60038
+#define PIPEA_DATA_M2_OFFSET 0
+#define PIPEA_DATA_N2 0x6003c
+#define PIPEA_DATA_N2_OFFSET 0
+
+#define PIPEA_LINK_M1 0x60040
+#define PIPEA_LINK_M1_OFFSET 0
+#define PIPEA_LINK_N1 0x60044
+#define PIPEA_LINK_N1_OFFSET 0
+
+#define PIPEA_LINK_M2 0x60048
+#define PIPEA_LINK_M2_OFFSET 0
+#define PIPEA_LINK_N2 0x6004c
+#define PIPEA_LINK_N2_OFFSET 0
+
+/* PIPEB timing regs are same start from 0x61000 */
+
+#define PIPEB_DATA_M1 0x61030
+#define PIPEB_DATA_M1_OFFSET 0
+#define PIPEB_DATA_N1 0x61034
+#define PIPEB_DATA_N1_OFFSET 0
+
+#define PIPEB_DATA_M2 0x61038
+#define PIPEB_DATA_M2_OFFSET 0
+#define PIPEB_DATA_N2 0x6103c
+#define PIPEB_DATA_N2_OFFSET 0
+
+#define PIPEB_LINK_M1 0x61040
+#define PIPEB_LINK_M1_OFFSET 0
+#define PIPEB_LINK_N1 0x61044
+#define PIPEB_LINK_N1_OFFSET 0
+
+#define PIPEB_LINK_M2 0x61048
+#define PIPEB_LINK_M2_OFFSET 0
+#define PIPEB_LINK_N2 0x6104c
+#define PIPEB_LINK_N2_OFFSET 0
+
+/* PIPECONF for pipe A/B addr is same */
+
+/* cusor A is only connected to pipe A,
+ cursor B is connected to pipe B. Otherwise no change. */
+
+/* Plane A/B, DSPACNTR/DSPBCNTR addr not changed */
+
+/* CPU panel fitter */
+#define PFA_CTL_1 0x68080
+#define PFB_CTL_1 0x68880
+#define PF_ENABLE (1<<31)
+
+#define PFA_WIN_POS 0x68070
+#define PFB_WIN_POS 0x68870
+#define PFA_WIN_SIZE 0x68074
+#define PFB_WIN_SIZE 0x68874
+
+/* legacy palette */
+#define LGC_PALETTE_A 0x4a000
+#define LGC_PALETTE_B 0x4a800
+
+/* interrupts */
+#define DE_MASTER_IRQ_CONTROL (1 << 31)
+#define DE_SPRITEB_FLIP_DONE (1 << 29)
+#define DE_SPRITEA_FLIP_DONE (1 << 28)
+#define DE_PLANEB_FLIP_DONE (1 << 27)
+#define DE_PLANEA_FLIP_DONE (1 << 26)
+#define DE_PCU_EVENT (1 << 25)
+#define DE_GTT_FAULT (1 << 24)
+#define DE_POISON (1 << 23)
+#define DE_PERFORM_COUNTER (1 << 22)
+#define DE_PCH_EVENT (1 << 21)
+#define DE_AUX_CHANNEL_A (1 << 20)
+#define DE_DP_A_HOTPLUG (1 << 19)
+#define DE_GSE (1 << 18)
+#define DE_PIPEB_VBLANK (1 << 15)
+#define DE_PIPEB_EVEN_FIELD (1 << 14)
+#define DE_PIPEB_ODD_FIELD (1 << 13)
+#define DE_PIPEB_LINE_COMPARE (1 << 12)
+#define DE_PIPEB_VSYNC (1 << 11)
+#define DE_PIPEB_FIFO_UNDERRUN (1 << 8)
+#define DE_PIPEA_VBLANK (1 << 7)
+#define DE_PIPEA_EVEN_FIELD (1 << 6)
+#define DE_PIPEA_ODD_FIELD (1 << 5)
+#define DE_PIPEA_LINE_COMPARE (1 << 4)
+#define DE_PIPEA_VSYNC (1 << 3)
+#define DE_PIPEA_FIFO_UNDERRUN (1 << 0)
+
+#define DEISR 0x44000
+#define DEIMR 0x44004
+#define DEIIR 0x44008
+#define DEIER 0x4400c
+
+/* GT interrupt */
+#define GT_SYNC_STATUS (1 << 2)
+#define GT_USER_INTERRUPT (1 << 0)
+
+#define GTISR 0x44010
+#define GTIMR 0x44014
+#define GTIIR 0x44018
+#define GTIER 0x4401c
+
+/* PCH */
+
+/* south display engine interrupt */
+#define SDE_CRT_HOTPLUG (1 << 11)
+#define SDE_PORTD_HOTPLUG (1 << 10)
+#define SDE_PORTC_HOTPLUG (1 << 9)
+#define SDE_PORTB_HOTPLUG (1 << 8)
+#define SDE_SDVOB_HOTPLUG (1 << 6)
+
+#define SDEISR 0xc4000
+#define SDEIMR 0xc4004
+#define SDEIIR 0xc4008
+#define SDEIER 0xc400c
+
+/* digital port hotplug */
+#define PCH_PORT_HOTPLUG 0xc4030
+#define PORTD_HOTPLUG_ENABLE (1 << 20)
+#define PORTD_PULSE_DURATION_2ms (0)
+#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
+#define PORTD_PULSE_DURATION_6ms (2 << 18)
+#define PORTD_PULSE_DURATION_100ms (3 << 18)
+#define PORTD_HOTPLUG_NO_DETECT (0)
+#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
+#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
+#define PORTC_HOTPLUG_ENABLE (1 << 12)
+#define PORTC_PULSE_DURATION_2ms (0)
+#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
+#define PORTC_PULSE_DURATION_6ms (2 << 10)
+#define PORTC_PULSE_DURATION_100ms (3 << 10)
+#define PORTC_HOTPLUG_NO_DETECT (0)
+#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
+#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
+#define PORTB_HOTPLUG_ENABLE (1 << 4)
+#define PORTB_PULSE_DURATION_2ms (0)
+#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
+#define PORTB_PULSE_DURATION_6ms (2 << 2)
+#define PORTB_PULSE_DURATION_100ms (3 << 2)
+#define PORTB_HOTPLUG_NO_DETECT (0)
+#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
+#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
+
+#define PCH_GPIOA 0xc5010
+#define PCH_GPIOB 0xc5014
+#define PCH_GPIOC 0xc5018
+#define PCH_GPIOD 0xc501c
+#define PCH_GPIOE 0xc5020
+#define PCH_GPIOF 0xc5024
+#define PCH_GMBUS0 0xc5100
+#define PCH_GMBUS1 0xc5104
+#define PCH_GMBUS2 0xc5108
+#define PCH_GMBUS3 0xc510c
+#define PCH_GMBUS4 0xc5110
+#define PCH_GMBUS5 0xc5120
+
+#define PCH_DPLL_A 0xc6014
+#define PCH_DPLL_B 0xc6018
+
+#define PCH_FPA0 0xc6040
+#define PCH_FPA1 0xc6044
+#define PCH_FPB0 0xc6048
+#define PCH_FPB1 0xc604c
+
+#define PCH_DPLL_TEST 0xc606c
+
+#define PCH_DREF_CONTROL 0xC6200
+#define DREF_CONTROL_MASK 0x7fc3
+#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13)
+#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13)
+#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3<<13)
+#define DREF_SSC_SOURCE_DISABLE (0<<11)
+#define DREF_SSC_SOURCE_ENABLE (2<<11)
+#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
+#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
+#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
+#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
+#define DREF_SSC4_DOWNSPREAD (0<<6)
+#define DREF_SSC4_CENTERSPREAD (1<<6)
+#define DREF_SSC1_DISABLE (0<<1)
+#define DREF_SSC1_ENABLE (1<<1)
+#define DREF_SSC4_DISABLE (0)
+#define DREF_SSC4_ENABLE (1)
+
+#define PCH_RAWCLK_FREQ 0xc6204
+#define FDL_TP1_TIMER_SHIFT 12
+#define FDL_TP1_TIMER_MASK (3<<12)
+#define FDL_TP2_TIMER_SHIFT 10
+#define FDL_TP2_TIMER_MASK (3<<10)
+#define RAWCLK_FREQ_MASK 0x3ff
+
+#define PCH_DPLL_TMR_CFG 0xc6208
+
+#define PCH_SSC4_PARMS 0xc6210
+#define PCH_SSC4_AUX_PARMS 0xc6214
+
+/* transcoder */
+
+#define TRANS_HTOTAL_A 0xe0000
+#define TRANS_HTOTAL_SHIFT 16
+#define TRANS_HACTIVE_SHIFT 0
+#define TRANS_HBLANK_A 0xe0004
+#define TRANS_HBLANK_END_SHIFT 16
+#define TRANS_HBLANK_START_SHIFT 0
+#define TRANS_HSYNC_A 0xe0008
+#define TRANS_HSYNC_END_SHIFT 16
+#define TRANS_HSYNC_START_SHIFT 0
+#define TRANS_VTOTAL_A 0xe000c
+#define TRANS_VTOTAL_SHIFT 16
+#define TRANS_VACTIVE_SHIFT 0
+#define TRANS_VBLANK_A 0xe0010
+#define TRANS_VBLANK_END_SHIFT 16
+#define TRANS_VBLANK_START_SHIFT 0
+#define TRANS_VSYNC_A 0xe0014
+#define TRANS_VSYNC_END_SHIFT 16
+#define TRANS_VSYNC_START_SHIFT 0
+
+#define TRANSA_DATA_M1 0xe0030
+#define TRANSA_DATA_N1 0xe0034
+#define TRANSA_DATA_M2 0xe0038
+#define TRANSA_DATA_N2 0xe003c
+#define TRANSA_DP_LINK_M1 0xe0040
+#define TRANSA_DP_LINK_N1 0xe0044
+#define TRANSA_DP_LINK_M2 0xe0048
+#define TRANSA_DP_LINK_N2 0xe004c
+
+#define TRANS_HTOTAL_B 0xe1000
+#define TRANS_HBLANK_B 0xe1004
+#define TRANS_HSYNC_B 0xe1008
+#define TRANS_VTOTAL_B 0xe100c
+#define TRANS_VBLANK_B 0xe1010
+#define TRANS_VSYNC_B 0xe1014
+
+#define TRANSB_DATA_M1 0xe1030
+#define TRANSB_DATA_N1 0xe1034
+#define TRANSB_DATA_M2 0xe1038
+#define TRANSB_DATA_N2 0xe103c
+#define TRANSB_DP_LINK_M1 0xe1040
+#define TRANSB_DP_LINK_N1 0xe1044
+#define TRANSB_DP_LINK_M2 0xe1048
+#define TRANSB_DP_LINK_N2 0xe104c
+
+#define TRANSACONF 0xf0008
+#define TRANSBCONF 0xf1008
+#define TRANS_DISABLE (0<<31)
+#define TRANS_ENABLE (1<<31)
+#define TRANS_STATE_MASK (1<<30)
+#define TRANS_STATE_DISABLE (0<<30)
+#define TRANS_STATE_ENABLE (1<<30)
+#define TRANS_FSYNC_DELAY_HB1 (0<<27)
+#define TRANS_FSYNC_DELAY_HB2 (1<<27)
+#define TRANS_FSYNC_DELAY_HB3 (2<<27)
+#define TRANS_FSYNC_DELAY_HB4 (3<<27)
+#define TRANS_DP_AUDIO_ONLY (1<<26)
+#define TRANS_DP_VIDEO_AUDIO (0<<26)
+#define TRANS_PROGRESSIVE (0<<21)
+#define TRANS_8BPC (0<<5)
+#define TRANS_10BPC (1<<5)
+#define TRANS_6BPC (2<<5)
+#define TRANS_12BPC (3<<5)
+
+#define FDI_RXA_CHICKEN 0xc200c
+#define FDI_RXB_CHICKEN 0xc2010
+#define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1)
+
+/* CPU: FDI_TX */
+#define FDI_TXA_CTL 0x60100
+#define FDI_TXB_CTL 0x61100
+#define FDI_TX_DISABLE (0<<31)
+#define FDI_TX_ENABLE (1<<31)
+#define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
+#define FDI_LINK_TRAIN_PATTERN_2 (1<<28)
+#define FDI_LINK_TRAIN_PATTERN_IDLE (2<<28)
+#define FDI_LINK_TRAIN_NONE (3<<28)
+#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3<<25)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3<<22)
+#define FDI_DP_PORT_WIDTH_X1 (0<<19)
+#define FDI_DP_PORT_WIDTH_X2 (1<<19)
+#define FDI_DP_PORT_WIDTH_X3 (2<<19)
+#define FDI_DP_PORT_WIDTH_X4 (3<<19)
+#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
+/* IGDNG: hardwired to 1 */
+#define FDI_TX_PLL_ENABLE (1<<14)
+/* both Tx and Rx */
+#define FDI_SCRAMBLING_ENABLE (0<<7)
+#define FDI_SCRAMBLING_DISABLE (1<<7)
+
+/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
+#define FDI_RXA_CTL 0xf000c
+#define FDI_RXB_CTL 0xf100c
+#define FDI_RX_ENABLE (1<<31)
+#define FDI_RX_DISABLE (0<<31)
+/* train, dp width same as FDI_TX */
+#define FDI_DP_PORT_WIDTH_X8 (7<<19)
+#define FDI_8BPC (0<<16)
+#define FDI_10BPC (1<<16)
+#define FDI_6BPC (2<<16)
+#define FDI_12BPC (3<<16)
+#define FDI_LINK_REVERSE_OVERWRITE (1<<15)
+#define FDI_DMI_LINK_REVERSE_MASK (1<<14)
+#define FDI_RX_PLL_ENABLE (1<<13)
+#define FDI_FS_ERR_CORRECT_ENABLE (1<<11)
+#define FDI_FE_ERR_CORRECT_ENABLE (1<<10)
+#define FDI_FS_ERR_REPORT_ENABLE (1<<9)
+#define FDI_FE_ERR_REPORT_ENABLE (1<<8)
+#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
+#define FDI_SEL_RAWCLK (0<<4)
+#define FDI_SEL_PCDCLK (1<<4)
+
+#define FDI_RXA_MISC 0xf0010
+#define FDI_RXB_MISC 0xf1010
+#define FDI_RXA_TUSIZE1 0xf0030
+#define FDI_RXA_TUSIZE2 0xf0038
+#define FDI_RXB_TUSIZE1 0xf1030
+#define FDI_RXB_TUSIZE2 0xf1038
+
+/* FDI_RX interrupt register format */
+#define FDI_RX_INTER_LANE_ALIGN (1<<10)
+#define FDI_RX_SYMBOL_LOCK (1<<9) /* train 2 */
+#define FDI_RX_BIT_LOCK (1<<8) /* train 1 */
+#define FDI_RX_TRAIN_PATTERN_2_FAIL (1<<7)
+#define FDI_RX_FS_CODE_ERR (1<<6)
+#define FDI_RX_FE_CODE_ERR (1<<5)
+#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1<<4)
+#define FDI_RX_HDCP_LINK_FAIL (1<<3)
+#define FDI_RX_PIXEL_FIFO_OVERFLOW (1<<2)
+#define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1)
+#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0)
+
+#define FDI_RXA_IIR 0xf0014
+#define FDI_RXA_IMR 0xf0018
+#define FDI_RXB_IIR 0xf1014
+#define FDI_RXB_IMR 0xf1018
+
+#define FDI_PLL_CTL_1 0xfe000
+#define FDI_PLL_CTL_2 0xfe004
+
+/* CRT */
+#define PCH_ADPA 0xe1100
+#define ADPA_TRANS_SELECT_MASK (1<<30)
+#define ADPA_TRANS_A_SELECT 0
+#define ADPA_TRANS_B_SELECT (1<<30)
+/* HPD is here */
+#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */
+#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2<<24)
+#define ADPA_CRT_HOTPLUG_ENABLE (1<<23)
+#define ADPA_CRT_HOTPLUG_PERIOD_64 (0<<22)
+#define ADPA_CRT_HOTPLUG_PERIOD_128 (1<<22)
+#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0<<21)
+#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1<<21)
+#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0<<20)
+#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1<<20)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3<<18)
+#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0<<17)
+#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17)
+#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
+/* polarity control not changed */
+
+/* or SDVOB */
+#define HDMIB 0xe1140
+#define PORT_ENABLE (1 << 31)
+#define TRANSCODER_A (0)
+#define TRANSCODER_B (1 << 30)
+#define COLOR_FORMAT_8bpc (0)
+#define COLOR_FORMAT_12bpc (3 << 26)
+#define SDVOB_HOTPLUG_ENABLE (1 << 23)
+#define SDVO_ENCODING (0)
+#define TMDS_ENCODING (2 << 10)
+#define NULL_PACKET_VSYNC_ENABLE (1 << 9)
+#define SDVOB_BORDER_ENABLE (1 << 7)
+#define AUDIO_ENABLE (1 << 6)
+#define VSYNC_ACTIVE_HIGH (1 << 4)
+#define HSYNC_ACTIVE_HIGH (1 << 3)
+#define PORT_DETECTED (1 << 2)
+
+#define HDMIC 0xe1150
+#define HDMID 0xe1160
+#define PCH_LVDS 0xe1180
+
+#define AUD_CONFIG 0x62000
+#define AUD_DEBUG 0x62010
+#define AUD_VID_DID 0x62020
+#define AUD_RID 0x62024
+#define AUD_SUBN_CNT 0x62028
+#define AUD_FUNC_GRP 0x62040
+#define AUD_SUBN_CNT2 0x62044
+#define AUD_GRP_CAP 0x62048
+#define AUD_PWRST 0x6204c
+#define AUD_SUPPWR 0x62050
+#define AUD_SID 0x62054
+#define AUD_OUT_CWCAP 0x62070
+#define AUD_OUT_PCMSIZE 0x62074
+#define AUD_OUT_STR 0x62078
+#define AUD_OUT_DIG_CNVT 0x6207c
+#define AUD_OUT_CH_STR 0x62080
+#define AUD_OUT_STR_DESC 0x62084
+#define AUD_PINW_CAP 0x620a0
+#define AUD_PIN_CAP 0x620a4
+#define AUD_PINW_CONNLNG 0x620a8
+#define AUD_PINW_CONNLST 0x620ac
+#define AUD_PINW_CNTR 0x620b0
+#define AUD_PINW_UNSOLRESP 0x620b8
+#define AUD_CNTL_ST 0x620b4
+#define AUD_PINW_CONFIG 0x620bc
+#define AUD_HDMIW_STATUS 0x620d4
+#define AUD_HDMIW_HDMIEDID 0x6210c
+#define AUD_HDMIW_INFOFR 0x62118
+#define AUD_CONV_CHCNT 0x62120
+#define AUD_CTS_ENABLE 0x62128
+
+#define VIDEO_DIP_CTL 0x61170
+
+#endif /* _I810_REG_H */
diff --git a/src/legacy/i810/i810_ring.h b/src/legacy/i810/i810_ring.h
new file mode 100644
index 00000000..e6e354fd
--- /dev/null
+++ b/src/legacy/i810/i810_ring.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright © 2002 David Dawes
+
+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.
+
+**************************************************************************/
+
+#ifndef _INTEL_RING_H
+#define _INTEL_RING_H
+
+#define OUT_RING(n) do { \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF("OUT_RING %lx: %x, (mask %x)\n", \
+ (unsigned long)(outring), (unsigned int)(n), ringmask); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outring += 4; ringused += 4; \
+ outring &= ringmask; \
+} while (0)
+
+#define ADVANCE_LP_RING() do { \
+ if (ringused > needed) \
+ FatalError("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \
+ __FUNCTION__, ringused, needed); \
+ else if (ringused < needed) \
+ FatalError("%s: ADVANCE_LP_RING: under-used allocation %d/%d\n ", \
+ __FUNCTION__, ringused, needed); \
+ pI810->LpRing->tail = outring; \
+ pI810->LpRing->space -= ringused; \
+ if (outring & 0x07) \
+ FatalError("%s: ADVANCE_LP_RING: " \
+ "outring (0x%x) isn't on a QWord boundary\n", \
+ __FUNCTION__, outring); \
+ OUTREG(LP_RING + RING_TAIL, outring); \
+} while (0)
+
+/*
+ * XXX Note: the head/tail masks are different for 810 and i830.
+ * If the i810 always sets the higher bits to 0, then this shouldn't be
+ * a problem. Check this!
+ */
+#define DO_RING_IDLE() do { \
+ int _head; \
+ int _tail; \
+ do { \
+ _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; \
+ _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK; \
+ DELAY(10); \
+ } while (_head != _tail); \
+} while( 0)
+
+#define BEGIN_LP_RING(n) \
+ unsigned int outring, ringmask, ringused = 0; \
+ volatile unsigned char *virt; \
+ int needed; \
+ if ((n) & 1) \
+ ErrorF("BEGIN_LP_RING called with odd argument: %d\n", n); \
+ if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \
+ DO_RING_IDLE(); \
+ needed = (n) * 4; \
+ if (pI810->LpRing->space < needed) \
+ WaitRingFunc(pScrn, needed, 0); \
+ outring = pI810->LpRing->tail; \
+ ringmask = pI810->LpRing->tail_mask; \
+ virt = pI810->LpRing->virtual_start; \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME);
+
+#endif /* _INTEL_RING_H */
diff --git a/src/legacy/i810/i810_video.c b/src/legacy/i810/i810_video.c
new file mode 100644
index 00000000..7e3db8c7
--- /dev/null
+++ b/src/legacy/i810/i810_video.c
@@ -0,0 +1,1423 @@
+/***************************************************************************
+
+Copyright 2000 Intel Corporation. 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 INTEL, 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.
+
+**************************************************************************/
+
+/*
+ * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich.
+ *
+ * Authors:
+ * Jonathan Bian <jonathan.bian@intel.com>
+ * Offscreen Images:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i810.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#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)
+
+static void I810InitOffscreenImages(ScreenPtr);
+
+static XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr);
+static void I810StopVideo(ScrnInfoPtr, pointer, Bool);
+static int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static void I810QueryBestSize(ScrnInfoPtr, Bool,
+ short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int I810PutImage( ScrnInfoPtr,
+ short, short, short, short, short, short, short, short,
+ int, unsigned char*, short, short, Bool, RegionPtr, pointer,
+ DrawablePtr);
+static int I810QueryImageAttributes(ScrnInfoPtr,
+ int, unsigned short *, unsigned short *, int *, int *);
+
+static void I810BlockHandler(int, pointer, pointer, pointer);
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvColorKey;
+
+#define IMAGE_MAX_WIDTH 1440
+#define IMAGE_FAST_WIDTH 720
+#define IMAGE_MAX_HEIGHT 1080
+#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
+
+#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000);
+
+/*
+ * OV0CMD - Overlay Command Register
+ */
+#define VERTICAL_CHROMINANCE_FILTER 0x70000000
+#define VC_SCALING_OFF 0x00000000
+#define VC_LINE_REPLICATION 0x10000000
+#define VC_UP_INTERPOLATION 0x20000000
+#define VC_PIXEL_DROPPING 0x50000000
+#define VC_DOWN_INTERPOLATION 0x60000000
+#define VERTICAL_LUMINANCE_FILTER 0x0E000000
+#define VL_SCALING_OFF 0x00000000
+#define VL_LINE_REPLICATION 0x02000000
+#define VL_UP_INTERPOLATION 0x04000000
+#define VL_PIXEL_DROPPING 0x0A000000
+#define VL_DOWN_INTERPOLATION 0x0C000000
+#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000
+#define HC_SCALING_OFF 0x00000000
+#define HC_LINE_REPLICATION 0x00400000
+#define HC_UP_INTERPOLATION 0x00800000
+#define HC_PIXEL_DROPPING 0x01400000
+#define HC_DOWN_INTERPOLATION 0x01800000
+#define HORIZONTAL_LUMINANCE_FILTER 0x00380000
+#define HL_SCALING_OFF 0x00000000
+#define HL_LINE_REPLICATION 0x00080000
+#define HL_UP_INTERPOLATION 0x00100000
+#define HL_PIXEL_DROPPING 0x00280000
+#define HL_DOWN_INTERPOLATION 0x00300000
+
+#define Y_ADJUST 0x00010000
+#define OV_BYTE_ORDER 0x0000C000
+#define UV_SWAP 0x00004000
+#define Y_SWAP 0x00008000
+#define Y_AND_UV_SWAP 0x0000C000
+#define SOURCE_FORMAT 0x00003C00
+#define RGB_555 0x00000800
+#define RGB_565 0x00000C00
+#define YUV_422 0x00002000
+#define YUV_411 0x00002400
+#define YUV_420 0x00003000
+#define YUV_410 0x00003800
+#define BUFFER_AND_FIELD 0x00000006
+#define BUFFER0_FIELD0 0x00000000
+#define BUFFER1_FIELD0 0x00000004
+#define OVERLAY_ENABLE 0x00000001
+
+#define UV_VERT_BUF1 0x02
+#define UV_VERT_BUF0 0x04
+
+/*
+ * DOV0STA - Display/Overlay 0 Status Register
+ */
+#define DOV0STA 0x30008
+
+#define MINUV_SCALE 0x1
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+#define RGB15ToColorKey(c) \
+ (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
+
+void I810InitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+ if (pScrn->bitsPerPixel != 8)
+ {
+ newAdaptor = I810SetupImageVideo(pScreen);
+ I810InitOffscreenImages(pScreen);
+ }
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if(newAdaptor) {
+ if(!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ free(newAdaptors);
+}
+
+/* *INDENT-OFF* */
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding[1] =
+{
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+ {1, 1}
+ }
+};
+
+#define NUM_FORMATS 3
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+#define NUM_ATTRIBUTES 3
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_IMAGES 6
+
+#define I810_RV15 0x35315652
+#define I810_RV16 0x36315652
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ {
+ I810_RV15,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','5',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 15, 0x7C00, 0x03E0, 0x001F,
+ 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
+ },
+ {
+ I810_RV16,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','6',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 16, 0xF800, 0x07E0, 0x001F,
+ 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
+ },
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+/* *INDENT-ON* */
+
+typedef struct {
+ uint32_t OBUF_0Y;
+ uint32_t OBUF_1Y;
+ uint32_t OBUF_0U;
+ uint32_t OBUF_0V;
+ uint32_t OBUF_1U;
+ uint32_t OBUF_1V;
+ uint32_t OV0STRIDE;
+ uint32_t YRGB_VPH;
+ uint32_t UV_VPH;
+ uint32_t HORZ_PH;
+ uint32_t INIT_PH;
+ uint32_t DWINPOS;
+ uint32_t DWINSZ;
+ uint32_t SWID;
+ uint32_t SWIDQW;
+ uint32_t SHEIGHT;
+ uint32_t YRGBSCALE;
+ uint32_t UVSCALE;
+ uint32_t OV0CLRC0;
+ uint32_t OV0CLRC1;
+ uint32_t DCLRKV;
+ uint32_t DCLRKM;
+ uint32_t SCLRKVH;
+ uint32_t SCLRKVL;
+ uint32_t SCLRKM;
+ uint32_t OV0CONF;
+ uint32_t OV0CMD;
+} I810OverlayRegRec, *I810OverlayRegPtr;
+
+typedef struct {
+ uint32_t YBuf0offset;
+ uint32_t UBuf0offset;
+ uint32_t VBuf0offset;
+
+ uint32_t YBuf1offset;
+ uint32_t UBuf1offset;
+ uint32_t VBuf1offset;
+
+ unsigned char currentBuf;
+
+ int brightness;
+ int contrast;
+
+ RegionRec clip;
+ uint32_t colorKey;
+
+ uint32_t videoStatus;
+ Time offTime;
+ Time freeTime;
+ FBLinearPtr linear;
+} I810PortPrivRec, *I810PortPrivPtr;
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+
+static void I810ResetVideo(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ /*
+ * Default to maximum image size in YV12
+ */
+
+ overlay->YRGB_VPH = 0;
+ overlay->UV_VPH = 0;
+ overlay->HORZ_PH = 0;
+ overlay->INIT_PH = 0;
+ overlay->DWINPOS = 0;
+ overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
+ overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15);
+ overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
+ overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
+ overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */
+ overlay->UVSCALE = 0x80004000; /* scale factor 1 */
+ overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
+ overlay->OV0CLRC1 = 0x80; /* saturation: bypass */
+
+ /*
+ * Enable destination color keying
+ */
+ switch(pScrn->depth) {
+ case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x80070307;
+ break;
+ case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x80070707;
+ break;
+ default: overlay->DCLRKV = pPriv->colorKey;
+ overlay->DCLRKM = 0x80000000;
+ break;
+ }
+
+ overlay->SCLRKVH = 0;
+ overlay->SCLRKVL = 0;
+ overlay->SCLRKM = 0; /* source color key disable */
+ overlay->OV0CONF = 0; /* two 720 pixel line buffers */
+
+ overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
+ YUV_420;
+
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+}
+
+
+static XF86VideoAdaptorPtr
+I810SetupImageVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ I810PortPrivPtr pPriv;
+
+ if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(I810PortPrivRec) +
+ sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "I810 Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]);
+
+ adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = I810StopVideo;
+ adapt->SetPortAttribute = I810SetPortAttribute;
+ adapt->GetPortAttribute = I810GetPortAttribute;
+ adapt->QueryBestSize = I810QueryBestSize;
+ adapt->PutImage = I810PutImage;
+ adapt->QueryImageAttributes = I810QueryImageAttributes;
+
+ pPriv->colorKey = pI810->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_NULL(pScreen, &pPriv->clip);
+
+ pI810->adaptor = adapt;
+
+ pI810->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = I810BlockHandler;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ I810ResetVideo(pScrn);
+
+ return adapt;
+}
+
+
+/* I810ClipVideo -
+
+ 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
+I810ClipVideo(
+ 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
+I810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(shutdown) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ }
+ 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
+I810SetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ if(attribute == xvBrightness) {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
+ OVERLAY_UPDATE(pI810->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(pI810->OverlayPhysical);
+ } else
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ switch(pScrn->depth) {
+ case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ break;
+ case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ break;
+ default: overlay->DCLRKV = pPriv->colorKey;
+ break;
+ }
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+I810GetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)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
+I810QueryBestSize(
+ 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;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+
+static void
+I810CopyPackedData(
+ ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch,
+ int top,
+ int left,
+ int h,
+ int w
+ )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ unsigned char *src, *dst;
+
+ src = buf + (top*srcPitch) + (left<<1);
+
+ if (pPriv->currentBuf == 0)
+ dst = pI810->FbBase + pPriv->YBuf0offset;
+ else
+ dst = pI810->FbBase + pPriv->YBuf1offset;
+
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+I810CopyPlanarData(
+ ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch, /* of chroma */
+ int srcH,
+ int top,
+ int left,
+ int h,
+ int w,
+ int id
+ )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ int i;
+ unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+
+ /* Copy Y data */
+ src1 = buf + (top*srcPitch) + left;
+ if (pPriv->currentBuf == 0)
+ dst1 = pI810->FbBase + pPriv->YBuf0offset;
+ else
+ dst1 = pI810->FbBase + pPriv->YBuf1offset;
+
+ for (i = 0; i < h; i++) {
+ memcpy(dst1, src1, w);
+ src1 += srcPitch;
+ dst1 += dstPitch << 1;
+ }
+
+ /* Copy V data for YV12, or U data for I420 */
+ src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst2 = pI810->FbBase + pPriv->UBuf0offset;
+ else
+ dst2 = pI810->FbBase + pPriv->VBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst2 = pI810->FbBase + pPriv->UBuf1offset;
+ else
+ dst2 = pI810->FbBase + pPriv->VBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst2, src2, w/2);
+ src2 += srcPitch>>1;
+ dst2 += dstPitch;
+ }
+
+ /* Copy U data for YV12, or V data for I420 */
+ src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst3 = pI810->FbBase + pPriv->VBuf0offset;
+ else
+ dst3 = pI810->FbBase + pPriv->UBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst3 = pI810->FbBase + pPriv->VBuf1offset;
+ else
+ dst3 = pI810->FbBase + pPriv->UBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst3, src3, w/2);
+ src3 += srcPitch>>1;
+ dst3 += dstPitch;
+ }
+}
+
+static void
+I810DisplayVideo(
+ 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
+){
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0;
+ unsigned int swidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ swidth = (width + 7) & ~7;
+ overlay->SWID = (swidth << 15) | swidth;
+ overlay->SWIDQW = (swidth << 12) | (swidth >> 3);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ swidth = ((width + 3) & ~3) << 1;
+ overlay->SWID = swidth;
+ overlay->SWIDQW = swidth >> 3;
+ break;
+ }
+
+ /* wide video formats (>720 pixels) are special */
+ if( swidth > IMAGE_FAST_WIDTH ) {
+ overlay->OV0CONF = 1; /* one 1440 pixel line buffer */
+ } else {
+ overlay->OV0CONF = 0; /* two 720 pixel line buffers */
+ }
+
+ overlay->SHEIGHT = height | (height << 15);
+ overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1);
+ overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
+ (dstBox->x2 - dstBox->x1);
+
+ /* buffer locations */
+ overlay->OBUF_0Y = pPriv->YBuf0offset;
+ overlay->OBUF_1Y = pPriv->YBuf1offset;
+ overlay->OBUF_0U = pPriv->UBuf0offset;
+ overlay->OBUF_0V = pPriv->VBuf0offset;
+ overlay->OBUF_1U = pPriv->UBuf1offset;
+ overlay->OBUF_1V = pPriv->VBuf1offset;
+
+ /*
+ * Calculate horizontal and vertical scaling factors, default to 1:1
+ */
+ overlay->YRGBSCALE = 0x80004000;
+ overlay->UVSCALE = 0x80004000;
+
+ /*
+ * Initially, YCbCr and Overlay Enable and
+ * vertical chrominance up interpolation and horozontal chrominance
+ * up interpolation
+ */
+ overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
+ OVERLAY_ENABLE;
+
+ if ((drw_w != src_w) || (drw_h != src_h))
+ {
+ xscaleInt = (src_w / drw_w) & 0x3;
+ xscaleFract = (src_w << 12) / drw_w;
+ yscaleInt = (src_h / drw_h) & 0x3;
+ yscaleFract = (src_h << 12) / drw_h;
+
+ overlay->YRGBSCALE = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) |
+ (yscaleInt) |
+ ((yscaleFract & 0xFFF) << 20);
+
+ if (drw_w > src_w)
+ {
+ /* horizontal up-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
+ }
+
+ if (drw_h > src_h)
+ {
+ /* vertical up-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
+ }
+
+ if (drw_w < src_w)
+ {
+ /* horizontal down-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
+ }
+
+ if (drw_h < src_h)
+ {
+ /* vertical down-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
+ }
+
+ /* now calculate the UV scaling factor */
+
+ if (xscaleFract)
+ {
+ xscaleFractUV = xscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= HC_UP_INTERPOLATION;
+ }
+
+ if (xscaleInt)
+ {
+ xscaleIntUV = xscaleInt >> MINUV_SCALE;
+ if (xscaleIntUV)
+ {
+ overlay->OV0CMD &= ~HC_UP_INTERPOLATION;
+ }
+ }
+
+ if (yscaleFract)
+ {
+ yscaleFractUV = yscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= VC_UP_INTERPOLATION;
+ }
+
+ if (yscaleInt)
+ {
+ yscaleIntUV = yscaleInt >> MINUV_SCALE;
+ if (yscaleIntUV)
+ {
+ overlay->OV0CMD &= ~VC_UP_INTERPOLATION;
+ overlay->OV0CMD |= VC_DOWN_INTERPOLATION;
+ }
+ }
+
+ overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ }
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ /* set UV vertical phase to -0.25 */
+ overlay->UV_VPH = 0x30003000;
+ overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1;
+ overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_420;
+ break;
+ case I810_RV15:
+ case I810_RV16:
+ overlay->UV_VPH = 0;
+ overlay->INIT_PH = 0;
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565);
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ overlay->UV_VPH = 0;
+ overlay->INIT_PH = 0;
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_422;
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ if (id == FOURCC_UYVY)
+ overlay->OV0CMD |= Y_SWAP;
+ break;
+ }
+
+ overlay->OV0CMD &= ~BUFFER_AND_FIELD;
+ if (pPriv->currentBuf == 0)
+ overlay->OV0CMD |= BUFFER0_FIELD0;
+ else
+ overlay->OV0CMD |= BUFFER1_FIELD0;
+
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+
+}
+
+static FBLinearPtr
+I810AllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBLinearPtr linear,
+ int size
+){
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+
+ 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) return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
+ NULL, NULL, NULL);
+ }
+
+ return new_linear;
+}
+
+static int
+I810PutImage(
+ 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,
+ DrawablePtr pDraw
+){
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch;
+ int top, left, npixels, nlines, size, loops;
+ BoxRec dstBox;
+
+
+ /* 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;
+
+ I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScrn->pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2))
+ return Success;
+ /*
+ * Fix for 4 pixel granularity of AdjustFrame
+ * unless boarder is clipped by frame
+ */
+ dstBox.x1 -= (pScrn->frameX0 &
+ ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
+ dstBox.x2 -= (pScrn->frameX0 & ~0x3);
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ dstPitch = ((width >> 1) + 7) & ~7; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 7) & ~7;
+ size = dstPitch * height;
+ break;
+ }
+
+ if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear,
+ (pScrn->bitsPerPixel == 16) ? size : (size >> 1))))
+ return BadAlloc;
+
+ /* fixup pointers */
+ pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp;
+ pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+ pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);
+
+ pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size;
+ pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+ pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);
+
+
+ /* Make sure this buffer isn't in use */
+ loops = 0;
+ while (loops < 1000000) {
+ if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) {
+ break;
+ }
+ loops++;
+ }
+ if(loops >= 1000000) {
+ pPriv->currentBuf = !pPriv->currentBuf;
+ }
+
+
+ /* buffer swap */
+ if (pPriv->currentBuf == 0)
+ pPriv->currentBuf = 1;
+ else
+ pPriv->currentBuf = 0;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left,
+ nlines, npixels, id);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ break;
+ }
+
+ /* update cliplist */
+ if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
+ }
+
+ I810DisplayVideo(pScrn, id, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ return Success;
+}
+
+
+static int
+I810QueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH;
+ if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ /* IA44 is for XvMC only */
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ if(pitches) pitches[0] = *w;
+ size = *w * *h;
+ break;
+ 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
+I810BlockHandler (
+ int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ pScreen->BlockHandler = pI810->BlockHandler;
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ pScreen->BlockHandler = I810BlockHandler;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ UpdateCurrentTime();
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < currentTime.milliseconds) {
+ /* Turn off the overlay */
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if(pPriv->freeTime < currentTime.milliseconds) {
+ if(pPriv->linear) {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ * Offscreen Images
+ ***************************************************************************/
+
+typedef struct {
+ FBLinearPtr linear;
+ Bool isOn;
+} OffscreenPrivRec, * OffscreenPrivPtr;
+
+static int
+I810AllocateSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h,
+ XF86SurfacePtr surface
+){
+ FBLinearPtr linear;
+ int pitch, size, bpp;
+ OffscreenPrivPtr pPriv;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if((w > 1024) || (h > 1024))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ bpp = pScrn->bitsPerPixel >> 3;
+ size = ((pitch * h) + bpp - 1) / bpp;
+
+ if(!(linear = I810AllocateMemory(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if(!(surface->pitches = malloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(surface->offsets = malloc(sizeof(int)))) {
+ free(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
+ free(surface->pitches);
+ free(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 * bpp;
+ surface->devPrivate.ptr = (pointer)pPriv;
+
+ memset(pI810->FbBase + surface->offsets[0],0,size);
+
+ return Success;
+}
+
+static int
+I810StopSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn) {
+ I810Ptr pI810 = I810PTR(surface->pScrn);
+
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+
+ pPriv->isOn = FALSE;
+ }
+
+ return Success;
+}
+
+
+static int
+I810FreeSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn) {
+ I810StopSurface(surface);
+ }
+ xf86FreeOffscreenLinear(pPriv->linear);
+ free(surface->pitches);
+ free(surface->offsets);
+ free(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+I810GetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value
+){
+ return I810GetPortAttribute(pScrn, attribute, value, NULL);
+}
+
+static int
+I810SetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value
+){
+ return I810SetPortAttribute(pScrn, attribute, value, NULL);
+}
+
+
+static int
+I810DisplaySurface(
+ 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;
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn);
+
+ INT32 x1, y1, x2, y2;
+ INT32 loops = 0;
+ BoxRec dstBox;
+
+ 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;
+
+ I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(screenInfo.screens[0], clipBoxes),
+ surface->width, surface->height);
+
+ /*
+ * Fix for 4 pixel granularity of AdjustFrame
+ * unless boarder is clipped by frame
+ */
+ dstBox.x1 -= (pScrn->frameX0 &
+ ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
+ dstBox.x2 -= (pScrn->frameX0 & ~0x3);
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ /* fixup pointers */
+ pI810Priv->YBuf0offset = surface->offsets[0];
+ pI810Priv->YBuf1offset = pI810Priv->YBuf0offset;
+
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) {
+ if(loops == 200000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
+ break;
+ }
+ loops++;
+ }
+
+ /* buffer swap */
+ if (pI810Priv->currentBuf == 0)
+ pI810Priv->currentBuf = 1;
+ else
+ pI810Priv->currentBuf = 0;
+
+ I810ResetVideo(pScrn);
+
+ I810DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+ surface->pitches[0], x1, y1, x2, y2, &dstBox,
+ src_w, src_h, drw_w, drw_h);
+
+ xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes);
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip);
+ UpdateCurrentTime();
+ pI810Priv->videoStatus = FREE_TIMER;
+ pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ pScrn->pScreen->BlockHandler = I810BlockHandler;
+ }
+
+ return Success;
+}
+
+
+static void
+I810InitOffscreenImages(ScreenPtr pScreen)
+{
+ XF86OffscreenImagePtr offscreenImages;
+
+ /* need to free this someplace */
+ if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) {
+ return;
+ }
+
+ offscreenImages[0].image = &Images[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
+ VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = I810AllocateSurface;
+ offscreenImages[0].free_surface = I810FreeSurface;
+ offscreenImages[0].display = I810DisplaySurface;
+ offscreenImages[0].stop = I810StopSurface;
+ offscreenImages[0].setAttribute = I810SetSurfaceAttribute;
+ offscreenImages[0].getAttribute = I810GetSurfaceAttribute;
+ offscreenImages[0].max_width = 1024;
+ offscreenImages[0].max_height = 1024;
+ offscreenImages[0].num_attributes = 1;
+ offscreenImages[0].attributes = Attributes;
+
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
+
diff --git a/src/legacy/i810/i810_wmark.c b/src/legacy/i810/i810_wmark.c
new file mode 100644
index 00000000..71b2a825
--- /dev/null
+++ b/src/legacy/i810/i810_wmark.c
@@ -0,0 +1,313 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i810.h"
+
+struct wm_info {
+ double freq;
+ unsigned int wm;
+};
+
+static struct wm_info i810_wm_8_100[] = {
+ {0, 0x22003000},
+ {25.2, 0x22003000},
+ {28.0, 0x22003000},
+ {31.5, 0x22003000},
+ {36.0, 0x22007000},
+ {40.0, 0x22007000},
+ {45.0, 0x22007000},
+ {49.5, 0x22008000},
+ {50.0, 0x22008000},
+ {56.3, 0x22008000},
+ {65.0, 0x22008000},
+ {75.0, 0x22008000},
+ {78.8, 0x22008000},
+ {80.0, 0x22008000},
+ {94.0, 0x22008000},
+ {96.0, 0x22107000},
+ {99.0, 0x22107000},
+ {108.0, 0x22107000},
+ {121.0, 0x22107000},
+ {128.9, 0x22107000},
+ {132.0, 0x22109000},
+ {135.0, 0x22109000},
+ {157.5, 0x2210b000},
+ {162.0, 0x2210b000},
+ {175.5, 0x2210b000},
+ {189.0, 0x2220e000},
+ {202.5, 0x2220e000}
+};
+
+static struct wm_info i810_wm_16_100[] = {
+ {0, 0x22004000},
+ {25.2, 0x22006000},
+ {28.0, 0x22006000},
+ {31.5, 0x22007000},
+ {36.0, 0x22007000},
+ {40.0, 0x22007000},
+ {45.0, 0x22007000},
+ {49.5, 0x22009000},
+ {50.0, 0x22009000},
+ {56.3, 0x22108000},
+ {65.0, 0x2210e000},
+ {75.0, 0x2210e000},
+ {78.8, 0x2210e000},
+ {80.0, 0x22210000},
+ {94.5, 0x22210000},
+ {96.0, 0x22210000},
+ {99.0, 0x22210000},
+ {108.0, 0x22210000},
+ {121.0, 0x22210000},
+ {128.9, 0x22210000},
+ {132.0, 0x22314000},
+ {135.0, 0x22314000},
+ {157.5, 0x22415000},
+ {162.0, 0x22416000},
+ {175.5, 0x22416000},
+ {189.0, 0x22416000},
+ {195.0, 0x22416000},
+ {202.5, 0x22416000}
+};
+
+static struct wm_info i810_wm_24_100[] = {
+ {0, 0x22006000},
+ {25.2, 0x22009000},
+ {28.0, 0x22009000},
+ {31.5, 0x2200a000},
+ {36.0, 0x2210c000},
+ {40.0, 0x2210c000},
+ {45.0, 0x2210c000},
+ {49.5, 0x22111000},
+ {50.0, 0x22111000},
+ {56.3, 0x22111000},
+ {65.0, 0x22214000},
+ {75.0, 0x22214000},
+ {78.8, 0x22215000},
+ {80.0, 0x22216000},
+ {94.5, 0x22218000},
+ {96.0, 0x22418000},
+ {99.0, 0x22418000},
+ {108.0, 0x22418000},
+ {121.0, 0x22418000},
+ {128.9, 0x22419000},
+ {132.0, 0x22519000},
+ {135.0, 0x4441d000},
+ {157.5, 0x44419000},
+ {162.0, 0x44419000},
+ {175.5, 0x44419000},
+ {189.0, 0x44419000},
+ {195.0, 0x44419000},
+ {202.5, 0x44419000}
+};
+
+#if 0
+/* not used */
+static struct wm_info i810_wm_32_100[] = {
+ {0, 0x2210b000},
+ {60, 0x22415000}, /* 0x314000 works too */
+ {80, 0x22419000} /* 0x518000 works too */
+};
+#endif
+
+static struct wm_info i810_wm_8_133[] = {
+ {0, 0x22003000},
+ {25.2, 0x22003000},
+ {28.0, 0x22003000},
+ {31.5, 0x22003000},
+ {36.0, 0x22007000},
+ {40.0, 0x22007000},
+ {45.0, 0x22007000},
+ {49.5, 0x22008000},
+ {50.0, 0x22008000},
+ {56.3, 0x22008000},
+ {65.0, 0x22008000},
+ {75.0, 0x22008000},
+ {78.8, 0x22008000},
+ {80.0, 0x22008000},
+ {94.0, 0x22008000},
+ {96.0, 0x22107000},
+ {99.0, 0x22107000},
+ {108.0, 0x22107000},
+ {121.0, 0x22107000},
+ {128.9, 0x22107000},
+ {132.0, 0x22109000},
+ {135.0, 0x22109000},
+ {157.5, 0x2210b000},
+ {162.0, 0x2210b000},
+ {175.5, 0x2210b000},
+ {189.0, 0x2220e000},
+ {202.5, 0x2220e000}
+};
+
+static struct wm_info i810_wm_16_133[] = {
+ {0, 0x22004000},
+ {25.2, 0x22006000},
+ {28.0, 0x22006000},
+ {31.5, 0x22007000},
+ {36.0, 0x22007000},
+ {40.0, 0x22007000},
+ {45.0, 0x22007000},
+ {49.5, 0x22009000},
+ {50.0, 0x22009000},
+ {56.3, 0x22108000},
+ {65.0, 0x2210e000},
+ {75.0, 0x2210e000},
+ {78.8, 0x2210e000},
+ {80.0, 0x22210000},
+ {94.5, 0x22210000},
+ {96.0, 0x22210000},
+ {99.0, 0x22210000},
+ {108.0, 0x22210000},
+ {121.0, 0x22210000},
+ {128.9, 0x22210000},
+ {132.0, 0x22314000},
+ {135.0, 0x22314000},
+ {157.5, 0x22415000},
+ {162.0, 0x22416000},
+ {175.5, 0x22416000},
+ {189.0, 0x22416000},
+ {195.0, 0x22416000},
+ {202.5, 0x22416000}
+};
+
+static struct wm_info i810_wm_24_133[] = {
+ {0, 0x22006000},
+ {25.2, 0x22009000},
+ {28.0, 0x22009000},
+ {31.5, 0x2200a000},
+ {36.0, 0x2210c000},
+ {40.0, 0x2210c000},
+ {45.0, 0x2210c000},
+ {49.5, 0x22111000},
+ {50.0, 0x22111000},
+ {56.3, 0x22111000},
+ {65.0, 0x22214000},
+ {75.0, 0x22214000},
+ {78.8, 0x22215000},
+ {80.0, 0x22216000},
+ {94.5, 0x22218000},
+ {96.0, 0x22418000},
+ {99.0, 0x22418000},
+ {108.0, 0x22418000},
+ {121.0, 0x22418000},
+ {128.9, 0x22419000},
+ {132.0, 0x22519000},
+ {135.0, 0x4441d000},
+ {157.5, 0x44419000},
+ {162.0, 0x44419000},
+ {175.5, 0x44419000},
+ {189.0, 0x44419000},
+ {195.0, 0x44419000},
+ {202.5, 0x44419000}
+};
+
+#define Elements(x) (sizeof(x)/sizeof(*x))
+
+/*
+ * I810CalcFIFO --
+ *
+ * Calculate burst length and FIFO watermark.
+ */
+
+unsigned int
+I810CalcWatermark(ScrnInfoPtr pScrn, double freq, Bool dcache)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ struct wm_info *tab;
+ int nr;
+ int i;
+
+ if (pI810->LmFreqSel == 100) {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ tab = i810_wm_8_100;
+ nr = Elements(i810_wm_8_100);
+ break;
+ case 16:
+ tab = i810_wm_16_100;
+ nr = Elements(i810_wm_16_100);
+ break;
+ case 24:
+ tab = i810_wm_24_100;
+ nr = Elements(i810_wm_24_100);
+ break;
+ default:
+ return 0;
+ }
+ } else {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ tab = i810_wm_8_133;
+ nr = Elements(i810_wm_8_133);
+ break;
+ case 16:
+ tab = i810_wm_16_133;
+ nr = Elements(i810_wm_16_133);
+ break;
+ case 24:
+ tab = i810_wm_24_133;
+ nr = Elements(i810_wm_24_133);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ for (i = 0; i < nr && tab[i].freq < freq; i++) ;
+
+ if (i == nr)
+ i--;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "chose watermark 0x%x: (tab.freq %.1f)\n",
+ tab[i].wm, tab[i].freq);
+
+ /* None of these values (sourced from intel) have watermarks for
+ * the dcache memory. Fake it for now by using the same watermark
+ * for both...
+ *
+ * Update: this is probably because dcache isn't real useful as
+ * framebuffer memory, so intel's drivers don't need watermarks
+ * for that memory because they never use it to feed the ramdacs.
+ * We do use it in the fallback mode, so keep the watermarks for
+ * now.
+ */
+ if (dcache)
+ return (tab[i].wm & ~0xffffff) | ((tab[i].wm >> 12) & 0xfff);
+ else
+ return tab[i].wm;
+}
diff --git a/src/legacy/i810/xvmc/I810XvMC.c b/src/legacy/i810/xvmc/I810XvMC.c
new file mode 100644
index 00000000..0754ff44
--- /dev/null
+++ b/src/legacy/i810/xvmc/I810XvMC.c
@@ -0,0 +1,4509 @@
+/***************************************************************************
+
+Copyright 2001 Intel Corporation. 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 INTEL, 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.
+
+**************************************************************************/
+
+/*************************************************************************
+** File libI810XvMC.c
+**
+** Authors:
+** Matt Sottek <matthew.j.sottek@intel.com>
+** Bob Paauwe <bob.j.paauwe@intel.com>
+**
+**
+***************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <X11/Xlibint.h>
+#include <fourcc.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+#include "I810XvMC.h"
+
+static int error_base;
+static int event_base;
+
+/***************************************************************************
+// Function: i810_get_free_buffer
+// Description: Allocates a free dma page using kernel ioctls, then
+// programs the data into the already allocated dma buffer list.
+// Arguments: pI810XvMC private data structure from the current context.
+// Notes: We faked the drmMapBufs for the i810's security so now we have
+// to insert an allocated page into the correct spot in the faked
+// list to keep up appearences.
+// Concept for this function was taken from Mesa sources.
+// Returns: drmBufPtr containing the information about the allocated page.
+***************************************************************************/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) {
+ drmI810DMA dma;
+ drmBufPtr buf;
+
+ dma.granted = 0;
+ dma.request_size = 4096;
+ while(!dma.granted) {
+ if(GET_BUFFER(pI810XvMC, dma) || !dma.granted)
+ FLUSH(pI810XvMC);
+ } /* No DMA granted */
+
+ buf = &(pI810XvMC->dmabufs->list[dma.request_idx]);
+ buf->idx = dma.request_idx;
+ buf->used = 0;
+ buf->total = dma.request_size;
+ buf->address = (drmAddress)dma.virtual;
+ return buf;
+}
+
+/***************************************************************************
+// Function: free_privContext
+// Description: Free's the private context structure if the reference
+// count is 0.
+***************************************************************************/
+void i810_free_privContext(i810XvMCContext *pI810XvMC) {
+
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+
+ pI810XvMC->ref--;
+ if(!pI810XvMC->ref) {
+ drmUnmapBufs(pI810XvMC->dmabufs);
+ drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size);
+ drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size);
+ drmClose(pI810XvMC->fd);
+
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ }
+
+ I810_UNLOCK(pI810XvMC);
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateContext
+// Description: Create a XvMC context for the given surface parameters.
+// Arguments:
+// display - Connection to the X server.
+// port - XvPortID to use as avertised by the X connection.
+// surface_type_id - Unique identifier for the Surface type.
+// width - Width of the surfaces.
+// height - Height of the surfaces.
+// flags - one or more of the following
+// XVMC_DIRECT - A direct rendered context is requested.
+//
+// Notes: surface_type_id and width/height parameters must match those
+// returned by XvMCListSurfaceTypes.
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
+ int surface_type_id, int width, int height, int flags,
+ XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+ int priv_count;
+ uint *priv_data;
+ uint magic;
+ Status ret;
+ int major, minor;
+
+ /* Verify Obvious things first */
+ if(context == NULL) {
+ return XvMCBadContext;
+ }
+
+ if(!(flags & XVMC_DIRECT)) {
+ /* Indirect */
+ printf("Indirect Rendering not supported!\nUsing Direct.");
+ }
+
+ /* Limit use to root for now */
+ if(geteuid()) {
+ printf("Use of XvMC on i810 is currently limited to root\n");
+ return BadAccess;
+ }
+
+ /* FIXME: Check $DISPLAY for legal values here */
+
+ context->surface_type_id = surface_type_id;
+ context->width = (unsigned short)width;
+ context->height = (unsigned short)height;
+ context->flags = flags;
+ context->port = port;
+ /*
+ Width, Height, and flags are checked against surface_type_id
+ and port for validity inside the X server, no need to check
+ here.
+ */
+
+ /* Allocate private Context data */
+ context->privData = (void *)malloc(sizeof(i810XvMCContext));
+ if(!context->privData) {
+ printf("Unable to allocate resources for XvMC context.\n");
+ return BadAlloc;
+ }
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+
+ /* Verify the XvMC extension exists */
+ if(! XvMCQueryExtension(display, &event_base,
+ &error_base)) {
+ printf("XvMC Extension is not available!\n");
+ return BadAlloc;
+ }
+ /* Verify XvMC version */
+ ret = XvMCQueryVersion(display, &major, &minor);
+ if(ret) {
+ printf("XvMCQuery Version Failed, unable to determine protocol version\n");
+ }
+ /* FIXME: Check Major and Minor here */
+
+ /* Check for drm */
+ if(! drmAvailable()) {
+ printf("Direct Rendering is not avilable on this system!\n");
+ return BadAlloc;
+ }
+
+ /*
+ Build the Attribute Atoms, and Initialize the ones that exist
+ in Xv.
+ */
+ pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0);
+ if(!pI810XvMC->xv_colorkey) {
+ return XvBadPort;
+ }
+ ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey,
+ &pI810XvMC->colorkey);
+ if(ret) {
+ return ret;
+ }
+ pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0);
+ pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0);
+ pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0);
+ pI810XvMC->brightness = 0;
+ pI810XvMC->saturation = 0x80; /* 1.0 in 3.7 format */
+ pI810XvMC->contrast = 0x40; /* 1.0 in 3.6 format */
+
+ /* Open DRI Device */
+ if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) {
+ printf("DRM Device for i810 could not be opened.\n");
+ free(pI810XvMC);
+ return BadAccess;
+ } /* !pI810XvMC->fd */
+
+ /* Get magic number and put it in privData for passing */
+ drmGetMagic(pI810XvMC->fd,&magic);
+ context->flags = (unsigned long)magic;
+
+ /*
+ Pass control to the X server to create a drm_context_t for us and
+ validate the with/height and flags.
+ */
+ if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
+ printf("Unable to create XvMC Context.\n");
+ return ret;
+ }
+
+ /*
+ X server returns a structure like this:
+ drm_context_t
+ fbBase
+ OverlayOffset
+ OverlaySize
+ SurfacesOffset
+ SurfacesSize
+ busIdString = 9 char + 1
+ */
+ if(priv_count != 9) {
+ printf("_xvmc_create_context() returned incorrect data size!\n");
+ printf("\tExpected 9, got %d\n",priv_count);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ }
+ pI810XvMC->drmcontext = priv_data[0];
+ pI810XvMC->fb_base = priv_data[1];
+ pI810XvMC->overlay.offset = priv_data[2] + priv_data[1];
+ pI810XvMC->overlay.size = priv_data[3];
+ pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1];
+ pI810XvMC->surfaces.size = priv_data[5];
+ strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9);
+ pI810XvMC->busIdString[9] = '\0';
+
+ /* Must free the private data we were passed from X */
+ free(priv_data);
+
+ /* Initialize private context values */
+ pI810XvMC->current = 0;
+ pI810XvMC->lock = 0;
+ pI810XvMC->last_flip = 0;
+ pI810XvMC->dual_prime = 0;
+
+ /*
+ Map dma Buffers: Not really, this would be a drmMapBufs
+ but due to the i810 security model we have to just create an
+ empty data structure to fake it.
+ */
+ pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap));
+ if(pI810XvMC->dmabufs == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs == NULL */
+ memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap));
+ pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) *
+ I810_DMA_BUF_NR);
+ if(pI810XvMC->dmabufs->list == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs->list == NULL */
+ memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
+
+ /* Map the Overlay memory */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset,
+ pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) {
+ printf("Unable to map Overlay at offset 0x%x and size 0x%x\n",
+ (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /* Overlay Regs are offset 1024 into Overlay Map */
+ pI810XvMC->oregs = (i810OverlayRec *)
+ ((unsigned char *)pI810XvMC->overlay.address + 1024);
+
+ /* Map Surfaces */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset,
+ pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) {
+ printf("Unable to map XvMC Surfaces.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /*
+ There is a tiny chance that someone was using the overlay and
+ issued a flip that hasn't finished. To be 100% sure I'll just
+ take the lock and sleep for the worst case time for a flip.
+ */
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+ usleep(20000); /* 1/50th Sec for 50hz refresh */
+
+ /* Set up Overlay regs with Initial Values */
+ pI810XvMC->oregs->YRGB_VPH = 0;
+ pI810XvMC->oregs->UV_VPH = 0;
+ pI810XvMC->oregs->HORZ_PH = 0;
+ pI810XvMC->oregs->INIT_PH = 0;
+ pI810XvMC->oregs->DWINPOS = 0;
+ pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) |
+ I810_XVMC_MAXWIDTH;
+ pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15);
+ pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) |
+ (I810_XVMC_MAXWIDTH << 12);
+ pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT |
+ (I810_XVMC_MAXHEIGHT << 15);
+ pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->UVSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
+ pI810XvMC->oregs->OV0CLRC1 = 0x80; /* saturation: bypass */
+
+ /* Destination Colorkey Setup */
+ pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
+ pI810XvMC->oregs->DCLRKM = 0x80070307;
+
+
+ pI810XvMC->oregs->SCLRKVH = 0;
+ pI810XvMC->oregs->SCLRKVL = 0;
+ pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */
+ pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST | YUV_420;
+
+ pI810XvMC->ref = 1;
+
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+
+}
+
+/***************************************************************************
+// Function: XvMCDestroyContext
+// Description: Destorys the specified context.
+//
+// Arguments:
+// display - Specifies the connection to the server.
+// context - The context to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(context->privData == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+ /* Turn off the overlay */
+ if(pI810XvMC->last_flip) {
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+ /* Make sure last flip is done */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST;
+ pI810XvMC->current = !pI810XvMC->current;
+ if(pI810XvMC->current == 1) {
+ pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ OVERLAY_FLIP(pI810XvMC);
+ pI810XvMC->last_flip++;
+
+ /* Wait for the flip */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ I810_UNLOCK(pI810XvMC);
+ }
+
+ /* Pass Control to the X server to destroy the drm_context_t */
+ _xvmc_destroy_context(display, context);
+
+ i810_free_privContext(pI810XvMC);
+ context->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateSurface
+***************************************************************************/
+_X_EXPORT Status XvMCCreateSurface( Display *display, XvMCContext *context,
+ XvMCSurface *surface) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSurface *pI810Surface;
+ int priv_count;
+ uint *priv_data;
+ Status ret;
+
+ if((surface == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pI810XvMC = (i810XvMCContext *)context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+
+ surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface));
+ if(!surface->privData) {
+ return BadAlloc;
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+
+ /* Initialize private values */
+ pI810Surface->privContext = pI810XvMC;
+ pI810Surface->last_render = 0;
+ pI810Surface->last_flip = 0;
+ pI810Surface->second_field = 0;
+
+ if((ret = _xvmc_create_surface(display, context, surface,
+ &priv_count, &priv_data))) {
+ free(pI810Surface);
+ printf("Unable to create XvMCSurface.\n");
+ return ret;
+ }
+
+ /*
+ _xvmc_create_subpicture returns 2 uints with the offset into
+ the DRM map for the Y surface and UV surface.
+ */
+ if(priv_count != 2) {
+ printf("_xvmc_create_surface() return incorrect data size.\n");
+ printf("Expected 2 got %d\n",priv_count);
+ free(priv_data);
+ free(pI810Surface);
+ return BadAlloc;
+ }
+ /* Data == Client Address, offset == Physical address offset */
+ pI810Surface->data = pI810XvMC->surfaces.address;
+ pI810Surface->offset = pI810XvMC->surfaces.offset;
+
+
+ /*
+ i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
+ and the Tiler need 512k aligned surfaces, basically we are
+ stuck with fixed memory with pitch 1024 for Y data. UV = 512.
+ */
+ pI810Surface->pitch = 10;
+ if((surface->surface_type_id == FOURCC_UYVY) ||
+ (surface->surface_type_id == FOURCC_YUY2)) {
+ /* This is not implemented server side. */
+ pI810Surface->pitch++;
+ }
+
+ /*
+ offsets[0,1,2] == Offsets from either data or offset for the Y
+ U and V surfaces.
+ */
+ pI810Surface->offsets[0] = priv_data[0];
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) {
+ printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n");
+ }
+
+ if((surface->surface_type_id == FOURCC_UYVY) ||
+ (surface->surface_type_id == FOURCC_YUY2)) {
+ /* Packed surface, not fully implemented */
+ pI810Surface->offsets[1] = 0;
+ pI810Surface->offsets[2] = 0;
+ }
+ else {
+ /* Planar surface */
+ pI810Surface->offsets[1] = priv_data[1];
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) {
+ printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n");
+ }
+
+ pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] +
+ (1<<(pI810Surface->pitch - 1)) * 288);
+ if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) {
+ printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n");
+ }
+
+ }
+
+ /* Free data returned from xvmc_create_surface */
+ free(priv_data);
+
+ /* Clear the surface to 0 */
+ memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]),
+ 0, ((1<<pI810Surface->pitch) * surface->height));
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ /* Destination buffer info command */
+ pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 9));
+ pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[1]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 10));
+ pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[2]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 10));
+
+ /* Destination buffer variables command */
+ pI810Surface->dbv1 = (0x8<<20) | (0x8<<16);
+ /* Map info command */
+ pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3);
+ pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
+ pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
+
+ pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) |
+ ((unsigned int)surface->width - 1);
+ pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) |
+ (((unsigned int)surface->width - 1)>>1);
+ pI810Surface->mi2v = pI810Surface->mi2u;
+
+ pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0x0000000f;
+ pI810Surface->mi3u = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[1]) & ~0x0000000f;
+ pI810Surface->mi3v = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[2]) & ~0x0000000f;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ /* Destination buffer info command */
+ pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff) |
+ (pI810Surface->pitch - 9));
+ /* Destination buffer variables command */
+ if(surface->surface_type_id == FOURCC_YUY2) {
+ pI810Surface->dbv1 = 0x5<<8;
+ pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21;
+ }
+ else {
+ pI810Surface->dbv1 = 0x4<<8;
+ pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3);
+ }
+ pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) |
+ ((unsigned int)surface->height - 1);
+ pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
+ pI810Surface->offsets[0]) & ~0xfc000fff;
+ break;
+ }
+ pI810XvMC->ref++;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySurface
+***************************************************************************/
+_X_EXPORT Status XvMCDestroySurface(Display *display, XvMCSurface *surface) {
+ i810XvMCSurface *pI810Surface;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+ if(pI810Surface->last_flip) {
+ XvMCSyncSurface(display,surface);
+ }
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+
+ _xvmc_destroy_surface(display,surface);
+
+ i810_free_privContext(pI810XvMC);
+
+ free(pI810Surface);
+ surface->privData = NULL;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateBlocks
+***************************************************************************/
+_X_EXPORT Status XvMCCreateBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCBlockArray *block) {
+
+ if((display == NULL) || (context == NULL) || (num_blocks == 0)) {
+ return BadValue;
+ }
+
+ block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short));
+ if(block->blocks == NULL) {
+ return BadAlloc;
+ }
+
+ block->num_blocks = num_blocks;
+ block->context_id = context->context_id;
+
+ block->privData = NULL;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyBlocks
+***************************************************************************/
+_X_EXPORT Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) {
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ free(block->blocks);
+ block->num_blocks = 0;
+ block->context_id = 0;
+ block->privData = NULL;
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCreateMacroBlocks
+***************************************************************************/
+_X_EXPORT Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context,
+ unsigned int num_blocks,
+ XvMCMacroBlockArray *blocks) {
+
+ if((display == NULL) || (context == NULL) || (blocks == NULL) ||
+ (num_blocks == 0)) {
+ return BadValue;
+ }
+ memset(blocks,0,sizeof(XvMCMacroBlockArray));
+ blocks->context_id = context->context_id;
+ blocks->privData = NULL;
+
+ blocks->macro_blocks = (XvMCMacroBlock *)
+ malloc(num_blocks * sizeof(XvMCMacroBlock));
+ if(blocks->macro_blocks == NULL) {
+ return BadAlloc;
+ }
+ blocks->num_blocks = num_blocks;
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCDestroyMacroBlocks
+***************************************************************************/
+_X_EXPORT Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) {
+ if((display == NULL) || (block == NULL)) {
+ return BadValue;
+ }
+ if(block->macro_blocks) {
+ free(block->macro_blocks);
+ }
+ block->context_id = 0;
+ block->num_blocks = 0;
+ block->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: dp (Debug Print)
+// Description: This function prints out in hex i * uint32_t at the address
+// supplied. This enables you to print out the dma buffers from
+// within the debugger even though they are not in your address space.
+***************************************************************************/
+void dp(unsigned int *address, unsigned int i) {
+ int j;
+
+ printf("DebugPrint:\n");
+ for(j=0; j<i; j++) {
+ printf("0x%8.8x ",address[j]);
+ if(j && !(j & 7)) { printf("\n");}
+ }
+}
+
+/***************************************************************************
+// Macro: PACK_*
+// Description: Packs 16bit signed data from blocks into either 8bit unsigned
+// intra data or 16bit signed correction data, both packed into
+// 32 bit integers.
+***************************************************************************/
+#define PACK_INTRA_DATA(d,b,n) \
+ do { \
+ char *dp = (char *)d; \
+ char *bp = (char *)b; \
+ int counter; \
+ for(counter = 0; counter < n; counter++) { \
+ *dp++ = *bp; \
+ bp += 2; \
+ } \
+ }while(0);
+
+#define PACK_CORR_DATA(d,b,n) \
+ memcpy(d,b,n); \
+ d = (uint *)((unsigned long)d + n);
+
+#define MARK_CORR_DATA(d,n) \
+ do { \
+ uint* q = (uint*)((unsigned long)d - n); \
+ while((unsigned long)q < (unsigned long)d) { \
+ *q++ += 0x00330033; \
+ } \
+ }while(0);
+
+#define MARK_INTRA_BLOCK(d) \
+ do { \
+ int q; \
+ for(q=0; q<16; q++) { \
+ d[q] += 0x33333333; \
+ } \
+ }while(0);
+
+/*
+ Used for DCT 1 when we need DCT 0. Instead
+ of reading from one block we read from two and
+ interlace.
+*/
+#define PACK_CORR_DATA_1to0(d,top,bottom) \
+ do { \
+ short *t = top,*b = bottom; \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 16); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 16); \
+ }while(0);
+
+/* Used for DCT 0 when we need DCT 1. */
+#define PACK_CORR_DATA_0to1(d,top,bottom) \
+ do{ \
+ short *t = top,*b = bottom; \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,t,16); \
+ t = (short *)((unsigned long)t + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ }while(0);
+
+#define PACK_CORR_DATA_SHORT(d,block) \
+ do { \
+ short *b = block; \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ PACK_CORR_DATA(d,b,16); \
+ b = (short *)((unsigned long)b + 32); \
+ }while(0);
+
+/* Lookup tables to speed common calculations */
+static unsigned int drps_table[] = {2<<6,3<<6};
+
+static unsigned int mvfs_table[] = {
+ 0x12,
+ 0x1a,
+ 0x13,
+ 0x1b
+};
+
+static unsigned int type_table[] = {
+ 0x1<<12, /* This is an error so make it Forward motion */
+ 0x1<<12,
+ 0x1<<12,
+ 0x1<<12,
+ 0x2<<12,
+ 0x2<<12,
+ 0x3<<12,
+ 0x3<<12,
+ 0x1<<12, /* Pattern but no Motion, Make motion Forward */
+ 0x1<<12,
+ 0x1<<12,
+ 0x1<<12,
+ 0x2<<12,
+ 0x2<<12,
+ 0x3<<12,
+ 0x3<<12
+};
+
+static unsigned int y_frame_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,384,384,384,384,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,384,384,384,384,
+ 256,256,256,256,384,384,384,384,
+ 384,384,384,384,512,512,512,512
+};
+
+static unsigned int u_frame_bytes[] = {
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128,
+ 0,0,128,128,0,0,128,128
+};
+
+static unsigned int v_frame_bytes[] = {
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128,
+ 0,128,0,128,0,128,0,128
+};
+
+static unsigned int y_first_field_bytes[] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 128,128,128,128,128,128,128,128,
+ 256,256,256,256,256,256,256,256,
+ 256,256,256,256,256,256,256,256
+};
+
+static unsigned int y_second_field_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256
+};
+
+static unsigned int y_dct0_field_bytes[] = {
+ 0,0,0,0,128,128,128,128,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,128,128,128,128,
+ 256,256,256,256,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 128,128,128,128,256,256,256,256,
+ 256,256,256,256,256,256,256,256,
+ 256,256,256,256,256,256,256,256
+};
+
+static unsigned int y_dct1_frame_bytes[] = {
+ 0,0,0,0,256,256,256,256,
+ 256,256,256,256,512,512,512,512,
+ 256,256,256,256,256,256,256,256,
+ 512,512,512,512,512,512,512,512,
+ 256,256,256,256,512,512,512,512,
+ 256,256,256,256,512,512,512,512,
+ 512,512,512,512,512,512,512,512,
+ 512,512,512,512,512,512,512,512
+};
+
+static unsigned int u_field_bytes[] = {
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64,
+ 0,0,64,64,0,0,64,64
+};
+
+static unsigned int v_field_bytes[] = {
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64,
+ 0,64,0,64,0,64,0,64
+};
+
+static short empty_block[] = {
+ 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,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,0,0,0,0,0,0
+};
+
+
+/***************************************************************************
+// Function: dispatchYContext
+// Description: Allocate a DMA buffer write the Y MC Context info in it,
+// and dispatch it to hardware.
+***************************************************************************/
+
+static __inline__ void dispatchYContext(i810XvMCSurface *privTarget,
+ i810XvMCSurface *privPast,
+ i810XvMCSurface *privFuture,
+ i810XvMCContext *pI810XvMC) {
+ uint *data;
+ drmBufPtr pDMA;
+ drm_i810_mc_t mc;
+
+ pDMA = i810_get_free_buffer(pI810XvMC);
+ data = pDMA->address;
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1y;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+ /* Past Surface */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privPast->mi1y;
+ *data++ = privPast->mi2y;
+ *data++ = privPast->mi3y;
+ /* Future Surface */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privFuture->mi1y | 0x1<<28;
+ *data++ = privFuture->mi2y;
+ *data++ = privFuture->mi3y;
+
+ mc.idx = pDMA->idx;
+ mc.used = (unsigned long)data - (unsigned long)pDMA->address;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+}
+
+static __inline__ void renderError(void) {
+ printf("Invalid Macroblock Parameters found.\n");
+ return;
+}
+
+/***************************************************************************
+// Function: renderIntrainFrame
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in a Frame picture.
+***************************************************************************/
+static __inline__ void renderIntrainFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,
+ short *block_ptr) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 68;
+ *dy++ = (1<<30) | (3<<28) | (0xf<<24);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+ *dy++ = (16<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,256);
+ dy += 64;
+ block_ptr += 256;
+ /* End Y Blocks */
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23);
+ *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22);
+ *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderIntrainFrameDCT1
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in a Frame picture with DCT type 1.
+***************************************************************************/
+static __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 36;
+ *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+ *dy++ = (8<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,128);
+ dy += 32;
+ block_ptr += 128;
+
+ /* Second Y block */
+ *dy++ = GFXBLOCK + 36;
+ *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6);
+ *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+ *dy++ = (8<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,128);
+ dy += 32;
+ block_ptr += 128;
+ /* End Y Blocks */
+
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23);
+ *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22);
+ *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: renderIntrainField
+// Description: inline function that sets hardware parameters for an Intra
+// encoded macroblock in Field pictures.
+***************************************************************************/
+static __inline__ void renderIntrainField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+ uint dw1 = drps_table[~ps & 0x1];
+
+ /* Y Blocks */
+ *dy++ = GFXBLOCK + 68;
+ *dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = 0;
+ *dy++ = 0;
+ PACK_INTRA_DATA(dy,block_ptr,256);
+ dy += 64;
+ block_ptr += 256;
+ /* End Y Blocks */
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 20;
+ *du++ = (2<<30) | (1<<28) | (1<<23) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = 0;
+ *du++ = 0;
+ PACK_INTRA_DATA(du,block_ptr,64);
+ du += 16;
+ block_ptr += 64;
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 20;
+ *dv++ = (3<<30) | (1<<28) | (1<<22) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = 0;
+ *dv++ = 0;
+ PACK_INTRA_DATA(dv,block_ptr,64);
+ dv += 16;
+ block_ptr += 64;
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: renderFieldinField
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a Field Picture.
+***************************************************************************/
+static __inline__ void renderFieldinField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps, uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[2];
+ short bmv[2];
+ /* gfxblock dword 1 */
+ uint dw1;
+
+ uint parity = ~ps & XVMC_TOP_FIELD;
+
+ uint ysize = y_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ /* i810 Specific flag used to identify the second field in a P frame */
+ if(flags & 0x80000000) {
+ /* P Frame */
+ if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
+ parity) {
+ /* Same parity, use reference field (map0) */
+ dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ (((uint)mb->coded_block_pattern)<<22);
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = 0;
+ bmv[1] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ (((uint)mb->coded_block_pattern)<<22);
+ bmv[0] = mb->PMV[0][0][1];
+ bmv[1] = mb->PMV[0][0][0];
+ fmv[0] = 0;
+ fmv[1] = 0;
+ }
+ }
+ else {
+ dw1 = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+ }
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: render16x8inField
+// Description: inline function that sets hardware parameters for a 16x8
+// encoded macroblock in a field picture.
+***************************************************************************/
+static __inline__ void render16x8inField(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint ps, uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[4];
+ short bmv[4];
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint parity = ~ps & XVMC_TOP_FIELD;
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ /* i810 Specific flag used to identify the second field in a P frame */
+ if(flags & 0x80000000) {
+ /* P Frame */
+ if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
+ parity) {
+ /* Same parity, use reference field (map0) */
+ dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = 0;
+ bmv[1] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ bmv[0] = mb->PMV[0][0][1];
+ bmv[1] = mb->PMV[0][0][0];
+ fmv[0] = 0;
+ fmv[1] = 0;
+ }
+ if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) ==
+ (parity<<2)) {
+ /* Same parity, use reference field (map0) */
+ dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ fmv[2] = mb->PMV[1][0][1];
+ fmv[3] = mb->PMV[1][0][0];
+ bmv[2] = 0;
+ bmv[3] = 0;
+ }
+ else {
+ /*
+ Opposite parity, set up as if it were backward
+ motion and use map1.
+ */
+ dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ bmv[2] = mb->PMV[1][0][1];
+ bmv[3] = mb->PMV[1][0][0];
+ fmv[2] = 0;
+ fmv[3] = 0;
+ }
+ }
+ else {
+ dw1[0] = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] |
+ drps_table[~ps & 0x1] |
+ mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] |
+ ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
+ (((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
+
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1];
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1];
+ bmv[3] = mb->PMV[1][1][0];
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = (xy + 8);
+ *dy++ = (8<<16) | 16;
+ *dy++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ fmv[2] /= 2;
+ fmv[3] /= 2;
+
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ bmv[2] /= 2;
+ bmv[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* Second U block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = (xy + 4);
+ *du++ = (4<<16) | 8;
+ *du++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = (xy + 4);
+ *dv++ = (4<<16) | 8;
+ *dv++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinField
+// Description: inline function that sets hardware parameters for a Dual
+// prime encoded macroblock in a field picture.
+***************************************************************************/
+static __inline__ void renderDualPrimeinField(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint ps,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ short fmv[2];
+ short bmv[2];
+ /* gfxblock dword 1 */
+ uint dw1;
+
+
+ uint ysize = y_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+
+ if(ps & XVMC_TOP_FIELD) {
+ dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3;
+ }
+ else {
+ dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2;
+ }
+ fmv[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[0][1][1];
+ bmv[1] = mb->PMV[0][1][0];
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = *(uint *)fmv;
+ *du++ = *(uint *)bmv;
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFieldinFrame
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a frame picture.
+***************************************************************************/
+typedef union {
+ short s[4];
+ uint u[2];
+} su_t;
+
+static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
+ mvfs_table[mb->motion_vertical_field_select>>2] |
+ (((mb->coded_block_pattern & 0x3) |
+ ((mb->coded_block_pattern & 0xc)<<2))<<22);
+
+ fmv.s[0] = mb->PMV[0][0][1]/2;
+ fmv.s[1] = mb->PMV[0][0][0];
+ fmv.s[2] = mb->PMV[1][0][1]/2;
+ fmv.s[3] = mb->PMV[1][0][0];
+
+ bmv.s[0] = mb->PMV[0][1][1]/2;
+ bmv.s[1] = mb->PMV[0][1][0];
+ bmv.s[2] = mb->PMV[1][1][1]/2;
+ bmv.s[3] = mb->PMV[1][1][0];
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[1];
+ *dy++ = bmv.u[1];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+ /* End Y Blocks */
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+ fmv.s[2] /= 2;
+ fmv.s[3] /= 2;
+
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+ bmv.s[2] /= 2;
+ bmv.s[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ if(usize) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[1];
+ *du++ = bmv.u[1];
+ if(usize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ if(vsize) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[1];
+ *dv++ = bmv.u[1];
+ if(vsize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFieldinFrameDCT0
+// Description: inline function that sets hardware parameters for a Field
+// encoded macroblock in a frame picture with DCT0.
+***************************************************************************/
+static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+ /* CBP */
+ uint cbp = (uint)mb->coded_block_pattern;
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ unsigned int ysize = y_dct0_field_bytes[cbp];
+ unsigned int usize = u_field_bytes[cbp];
+ unsigned int vsize = v_field_bytes[cbp];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
+ mvfs_table[mb->motion_vertical_field_select & 3] |
+ ((cbp | ((cbp<<2) & 0x30))<<22);
+
+ dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
+ mvfs_table[mb->motion_vertical_field_select>>2] |
+ ((cbp | ((cbp<<2) & 0x30))<<22);
+
+
+ fmv.s[0] = mb->PMV[0][0][1]/2;
+ fmv.s[1] = mb->PMV[0][0][0];
+ fmv.s[2] = mb->PMV[1][0][1]/2;
+ fmv.s[3] = mb->PMV[1][0][0];
+
+ bmv.s[0] = mb->PMV[0][1][1]/2;
+ bmv.s[1] = mb->PMV[0][1][0];
+ bmv.s[2] = mb->PMV[1][1][1]/2;
+ bmv.s[3] = mb->PMV[1][1][0];
+
+ /*
+ The i810 cannot use DCT0 directly with field motion, we have to
+ interlace the data for it. We use a zero block when the CBP has
+ one half of the to-be-interlaced data but not the other half.
+ */
+ top_left_b = &empty_block[0];
+ if(cbp & 0x20) {
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(cbp & 0x10) {
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(cbp & 0x8) {
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(cbp & 0x4) {
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];
+ if(dw1[0] & (1<<27)) {
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1[0] & (1<<26)) {
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[1];
+ *dy++ = bmv.u[1];
+ if(dw1[1] & (1<<27)) {
+ top_left_b = (short *)((unsigned long)top_left_b + 16);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1[1] & (1<<26)) {
+ top_right_b = (short *)((unsigned long)top_right_b + 16);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Blocks */
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+ fmv.s[2] /= 2;
+ fmv.s[3] /= 2;
+
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+ bmv.s[2] /= 2;
+ bmv.s[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ if(usize) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[1];
+ *du++ = bmv.u[1];
+ if(usize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ if(vsize) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[1];
+ *dv++ = bmv.u[1];
+ if(vsize) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFrameinFrame
+// Description: inline function that sets hardware parameters for a Frame
+// encoded macroblock in a frame picture.
+***************************************************************************/
+static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+ /* gfxblock dword 1 */
+ uint dw1;
+
+ unsigned int ysize = y_frame_bytes[mb->coded_block_pattern];
+ unsigned int usize = u_frame_bytes[mb->coded_block_pattern];
+ unsigned int vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ dw1 = type_table[mb->macroblock_type & 0xf] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+
+ bmv.s[0] = mb->PMV[0][1][1];
+ bmv.s[1] = mb->PMV[0][1][0];
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];
+ PACK_CORR_DATA(dy,block_ptr,ysize);
+ block_ptr = (short *)((unsigned long)block_ptr + ysize);
+ /* End Y Blocks */
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+ /* End U Block */
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+ /* End V Block */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderFrameinFrameDCT1
+// Description: inline function that sets hardware parameters for a Frame
+// encoded macroblock in a frame picture with DCT type 1.
+***************************************************************************/
+static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ uint temp_bp = 0;
+
+ uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern];
+ uint usize = u_frame_bytes[mb->coded_block_pattern];
+ uint vsize = v_frame_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
+
+ uint dw1 = type_table[mb->macroblock_type & 0xf] |
+ (((uint)mb->coded_block_pattern)<<22);
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+
+ bmv.s[0] = mb->PMV[0][1][1];
+ bmv.s[1] = mb->PMV[0][1][0];
+
+ /*
+ It is easiest to find out what blocks are in need of reading first
+ rather than as we go.
+ */
+ top_left_b = &empty_block[0];
+ if(dw1 & (1<<27)) {
+ temp_bp |= (1<<25);
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(dw1 & (1<<26)) {
+ temp_bp |= (1<<24);
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(dw1 & (1<<25)) {
+ temp_bp |= (1<<27);
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(dw1 & (1<<24)) {
+ temp_bp |= (1<<26);
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+ dw1 |= temp_bp;
+
+ /* Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (3<<28) | dw1;
+ *dy++ = xy;
+ *dy++ = (16<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];
+ if(dw1 & (1<<27)) {
+ PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
+ top_left_b = (short *)((unsigned long)top_left_b + 64);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 64);
+ }
+ if(dw1 & (1<<26)) {
+ PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
+ top_right_b = (short *)((unsigned long)top_right_b + 64);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 64);
+ }
+ if(dw1 & (1<<27)) {
+ PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
+ }
+ if(dw1 & (1<<26)) {
+ PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Block */
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+
+ xy >>= 1;
+
+ /* U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1;
+ *du++ = xy;
+ *du++ = (8<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ PACK_CORR_DATA(du,block_ptr,usize);
+ block_ptr = (short *)((unsigned long)block_ptr + usize);
+
+ /* V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1;
+ *dv++ = xy;
+ *dv++ = (8<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ PACK_CORR_DATA(dv,block_ptr,vsize);
+ block_ptr = (short *)((unsigned long)block_ptr + vsize);
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinFrame
+// Description: inline function that sets hardware parameters for a Dual
+// Prime encoded macroblock in a frame picture with dct 1.
+***************************************************************************/
+static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
+ uint **datav,XvMCMacroBlock *mb,
+ short *block_ptr,uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ uint y1size = y_first_field_bytes[mb->coded_block_pattern];
+ uint y2size = y_second_field_bytes[mb->coded_block_pattern];
+ uint usize = u_field_bytes[mb->coded_block_pattern];
+ uint vsize = v_field_bytes[mb->coded_block_pattern];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ /*
+ Past Surface (map 0) is used for same parity prediction,
+ Future surface (map 1) is used for opposite.
+ */
+ dw1[0] = (((uint)mb->coded_block_pattern)<<22) |
+ 3<<12 | 2<<6 | 2<<3 | 3;
+ dw1[1] = (((mb->coded_block_pattern & 0x3) |
+ ((mb->coded_block_pattern & 0xc)<<2))<<22) |
+ 3<<12 | 3<<6 | 3<<3 | 2;
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+ bmv.s[0] = mb->PMV[1][0][1];
+ bmv.s[1] = mb->PMV[1][0][0];
+
+ fmv.s[2] = mb->PMV[0][0][1];
+ fmv.s[3] = mb->PMV[0][0][0];
+ bmv.s[2] = mb->PMV[1][1][1];
+ bmv.s[3] = mb->PMV[1][1][0];
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (y1size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];;
+ PACK_CORR_DATA(dy,block_ptr,y1size);
+ block_ptr = (short *)((unsigned long)block_ptr + y1size);
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (y2size>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[1];
+ *dy++ = bmv.u[1];
+ PACK_CORR_DATA(dy,block_ptr,y2size);
+ block_ptr = (short *)((unsigned long)block_ptr + y2size);
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+
+ fmv.s[2] /= 2;
+ fmv.s[3] /= 2;
+ bmv.s[2] /= 2;
+ bmv.s[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ if(dw1[0] & (1<<23)) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[1];
+ *du++ = bmv.u[1];
+ if(dw1[1] & (1<<23)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ if(dw1[0] & (1<<22)) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[1];
+ *dv++ = bmv.u[1];
+ if(dw1[1] & (1<<22)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+/***************************************************************************
+// Function: renderDualPrimeinFrameDCT0
+// Description: inline function that sets hardware parameters for a Dual
+// Prime encoded macroblock in a frame picture with dct 0.
+***************************************************************************/
+static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
+ uint **datav,
+ XvMCMacroBlock *mb,
+ short *block_ptr,
+ uint flags) {
+
+ register uint *dy = *datay;
+ register uint *du = *datau;
+ register uint *dv = *datav;
+
+ /* Motion Vectors */
+ su_t fmv;
+ su_t bmv;
+ /* gfxblock dword 1 */
+ uint dw1[2];
+
+ short * top_left_b = NULL;
+ short * top_right_b = NULL;
+ short * bottom_left_b = NULL;
+ short * bottom_right_b = NULL;
+
+ uint cbp = (uint)mb->coded_block_pattern;
+
+ uint ysize = y_dct0_field_bytes[cbp];
+ uint usize = u_field_bytes[cbp];
+ uint vsize = v_field_bytes[cbp];
+
+ uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
+
+ /*
+ Past Surface (map 0) is used for same parity prediction,
+ Future surface (map 1) is used for opposite.
+ */
+ dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) |
+ 3<<12 | 2<<6 | 2<<3 | 3;
+ dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
+ 3<<12 | 3<<6 | 3<<3 | 2;
+
+ fmv.s[0] = mb->PMV[0][0][1];
+ fmv.s[1] = mb->PMV[0][0][0];
+ bmv.s[0] = mb->PMV[1][0][1];
+ bmv.s[1] = mb->PMV[1][0][0];
+
+ fmv.s[2] = mb->PMV[0][0][1];
+ fmv.s[3] = mb->PMV[0][0][0];
+ bmv.s[2] = mb->PMV[1][1][1];
+ bmv.s[3] = mb->PMV[1][1][0];
+
+ /*
+ The i810 cannot use DCT0 directly with field motion, we have to
+ interlace the data for it. We use a zero block when the CBP has
+ one half of the to-be-interlaced data but not the other half.
+ */
+ top_left_b = &empty_block[0];
+ if(cbp & 0x20) {
+ top_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ top_right_b = &empty_block[0];
+ if(cbp & 0x10) {
+ top_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_left_b = &empty_block[0];
+ if(cbp & 0x8) {
+ bottom_left_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ bottom_right_b = &empty_block[0];
+ if(cbp & 0x4) {
+ bottom_right_b = block_ptr;
+ block_ptr += 64;
+ }
+
+ /* First Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[0];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[0];
+ *dy++ = bmv.u[0];
+ if(cbp & 0x20) {
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(cbp & 0x10) {
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+
+ /* Second Y Block */
+ *dy++ = GFXBLOCK + 4 + (ysize>>2);
+ *dy++ = (1<<30) | (2<<28) | dw1[1];
+ *dy++ = xy;
+ *dy++ = (8<<16) | 16;
+ *dy++ = fmv.u[1];
+ *dy++ = bmv.u[1];
+ if(cbp & 0x20) {
+ top_left_b = (short *)((unsigned long)top_left_b + 16);
+ bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
+ }
+ if(cbp & 0x10) {
+ top_right_b = (short *)((unsigned long)top_right_b + 16);
+ bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
+ PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
+ }
+ /* End Y Blocks */
+
+
+ fmv.s[0] /= 2;
+ fmv.s[1] /= 2;
+ bmv.s[0] /= 2;
+ bmv.s[1] /= 2;
+
+ fmv.s[2] /= 2;
+ fmv.s[3] /= 2;
+ bmv.s[2] /= 2;
+ bmv.s[3] /= 2;
+
+ xy >>= 1;
+
+ /* U Blocks */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[0];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[0];
+ *du++ = bmv.u[0];
+ if(cbp & (1<<23)) {
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ }
+
+ /* Second U Block */
+ *du++ = GFXBLOCK + 4 + (usize>>2);
+ *du++ = (2<<30) | (1<<28) | dw1[1];
+ *du++ = xy;
+ *du++ = (4<<16) | 8;
+ *du++ = fmv.u[1];
+ *du++ = bmv.u[1];
+ if(cbp & (1<<23)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(du,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End U Blocks */
+
+ /* V Blocks */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[0];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[0];
+ *dv++ = bmv.u[0];
+ if(cbp & (1<<22)) {
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ }
+
+ /* Second V Block */
+ *dv++ = GFXBLOCK + 4 + (vsize>>2);
+ *dv++ = (3<<30) | (1<<28) | dw1[1];
+ *dv++ = xy;
+ *dv++ = (4<<16) | 8;
+ *dv++ = fmv.u[1];
+ *dv++ = bmv.u[1];
+ if(cbp & (1<<22)) {
+ block_ptr = (short *)((unsigned long)block_ptr + 16);
+ PACK_CORR_DATA_SHORT(dv,block_ptr);
+ block_ptr = (short *)((unsigned long)block_ptr + 112);
+ }
+ /* End V Blocks */
+
+ *datay = dy;
+ *datau = du;
+ *datav = dv;
+}
+
+
+/***************************************************************************
+// Function: XvMCRenderSurface
+// Description: This function does the actual HWMC. Given a list of
+// macroblock structures it dispatched the hardware commands to execute
+// them. DMA buffer containing Y data are dispatched as they fill up
+// U and V DMA buffers are queued until all Y's are done. This minimizes
+// the context flipping and flushing required when switching between Y
+// U and V surfaces.
+***************************************************************************/
+#define UV_QUEUE 14
+_X_EXPORT Status XvMCRenderSurface(Display *display, XvMCContext *context,
+ unsigned int picture_structure,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface,
+ unsigned int flags,
+ unsigned int num_macroblocks,
+ unsigned int first_macroblock,
+ XvMCMacroBlockArray *macroblock_array,
+ XvMCBlockArray *blocks) {
+ /* Dma Data Structures */
+ drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE];
+ int u_index = 0,v_index = 0;
+ int dirty_context = 1;
+
+ /* Block Pointer */
+ short *block_ptr;
+ /* Current Macroblock Pointer */
+ XvMCMacroBlock *mb;
+
+ drm_i810_mc_t mc;
+ int i,j;
+ i810XvMCSurface *privTarget;
+ i810XvMCSurface *privFuture = NULL;
+ i810XvMCSurface *privPast = NULL;
+ i810XvMCContext *pI810XvMC;
+
+ /* DMA Pointers set to NULL */
+ uint *datay = NULL;
+ uint *datau = NULL;
+ uint *datav = NULL;
+
+
+ /* Check Parameters for validity */
+ if((target_surface == NULL) || (context == NULL) || (display == NULL)) {
+ printf("Error, Invalid Target,Context, or DIsplay!\n");
+ return BadValue;
+ }
+
+ if(num_macroblocks == 0) {return Success;}
+ if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;}
+ if(context->privData == NULL) {return BadValue;}
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+
+ if(target_surface->privData == NULL) {
+ printf("Error, Invalid Target Surface!\n");
+ return BadValue;
+ }
+ privTarget = (i810XvMCSurface *)target_surface->privData;
+
+ if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
+ printf("Error, Too many macroblocks requested for MB array size.\n");
+ return BadValue;
+ }
+
+ /* Test For YV12 Surface */
+ if(context->surface_type_id != FOURCC_YV12) {
+ printf("Error, HWMC only possible on YV12 Surfaces\n");
+ return BadValue;
+ }
+
+ /* P Frame Test */
+ if(past_surface == NULL) {
+ /* Just to avoid some ifs later. */
+ privPast = privTarget;
+ }
+ else {
+ if(past_surface->privData == NULL) {
+ printf("Error, Invalid Past Surface!\n");
+ return BadValue;
+ }
+ privPast = (i810XvMCSurface *)past_surface->privData;
+ }
+
+
+ /* B Frame Test */
+ if(future_surface == NULL) {
+ privFuture = privTarget;
+ if(pI810XvMC->dual_prime) {
+ privFuture = privPast;
+ /* I810 Specific flag for marking when dual prime is in use. */
+ flags |= 0x40000000;
+ }
+
+ /*
+ References are different for the Second Field Picture. The
+ i810 needs to know if it is the second field picture in a
+ P picture. We use a Private flag to mark this.
+ */
+ if(flags & XVMC_SECOND_FIELD) {
+ /* I810 Specific flag for marking second fields. */
+ flags |= 0x80000000;
+ }
+ }
+ else {
+ if((future_surface->privData == NULL) || (past_surface == NULL)) {
+ printf("Error, Invalid Future Surface or No Past Surface!\n");
+ return BadValue;
+ }
+ privFuture = (i810XvMCSurface *)future_surface->privData;
+
+ /*
+ Undo Second Field flag since the second field in B frames is just like
+ the first.
+ */
+ flags &= ~0x80000000;
+ }
+
+ /* Lock For DMA */
+ I810_LOCK(pI810XvMC,0);
+
+ for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) {
+ /* Set up values needed for each macroblock */
+ mb = &macroblock_array->macro_blocks[i];
+ block_ptr = &(blocks->blocks[mb->index<<6]);
+
+ /* Lockup can happen if the coordinates are too far out of range */
+ if(mb->x > target_surface->width>>4) {
+ mb->x = 0;
+ }
+ if(mb->y > target_surface->height>>4) {
+ mb->y = 0;
+ }
+
+ /* If buffers are almost full dispatch them */
+ if(datay) {
+ pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address;
+ if(pDMAy->used > 3520) {
+ if(dirty_context) {
+ dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
+ }
+ dirty_context = 0;
+ mc.idx = pDMAy->idx;
+ mc.used = pDMAy->used;
+ datay = NULL;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ } /* datay near full */
+ } /* if(datay) */
+ if(datau) {
+ pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
+ if(pDMAu[u_index]->used > 3904) {
+ u_index++;
+ datau = NULL;
+ if(u_index == UV_QUEUE) {
+ for(j=0; j<UV_QUEUE; j++) {
+ mc.idx = pDMAu[j]->idx;
+ mc.used = pDMAu[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ u_index = 0;
+ dirty_context = 1;
+ } /* if(u_index == UV_QUEUE) */
+ } /* datau near full */
+ } /* if(datau) */
+ if(datav) {
+ pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
+ if(pDMAv[v_index]->used > 3904) {
+ v_index++;
+ datav = NULL;
+ if(v_index == UV_QUEUE) {
+ for(j=0; j<UV_QUEUE; j++) {
+ mc.idx = pDMAv[j]->idx;
+ mc.used = pDMAv[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ v_index = 0;
+ dirty_context = 1;
+ } /* if(v_index == UV_QUEUE) */
+ } /* datav near full */
+ } /* if(datav) */
+
+ /* Allocate buffers if this is the first loop,or if we just dispatched */
+ if(datay == NULL) {
+ pDMAy = i810_get_free_buffer(pI810XvMC);
+ datay = pDMAy->address;
+ }/* if(datay == NULL) */
+ if(datau == NULL) {
+ pDMAu[u_index] = i810_get_free_buffer(pI810XvMC);
+ datau = pDMAu[u_index]->address;
+ if(u_index == 0) {
+ *datau++ = CMD_FLUSH;
+ *datau++ = BOOLEAN_ENA_2;
+ *datau++ = CMD_FLUSH;
+ *datau++ = DEST_BUFFER_INFO;
+ *datau++ = privTarget->dbi1u;
+ *datau++ = DEST_BUFFER_VAR;
+ *datau++ = privTarget->dbv1;
+ /* Past Surface */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privPast->mi1u;
+ *datau++ = privPast->mi2u;
+ *datau++ = privPast->mi3u;
+ /* Future Surface */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ }
+ } /* if(datau == NULL) */
+ if(datav == NULL) {
+ pDMAv[v_index] = i810_get_free_buffer(pI810XvMC);
+ datav = pDMAv[v_index]->address;
+ if(v_index == 0) {
+ *datav++ = CMD_FLUSH;
+ *datav++ = BOOLEAN_ENA_2;
+ *datav++ = CMD_FLUSH;
+ *datav++ = DEST_BUFFER_INFO;
+ *datav++ = privTarget->dbi1v;
+ *datav++ = DEST_BUFFER_VAR;
+ *datav++ = privTarget->dbv1;
+ /* Past Surface */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privPast->mi1v;
+ *datav++ = privPast->mi2v;
+ *datav++ = privPast->mi3v;
+ /* Future Surface */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+ }/* if(datav == NULL) */
+
+ /* Catch no pattern case */
+ if(!(mb->macroblock_type & 0x8)) {
+ mb->coded_block_pattern = 0;
+ }
+
+
+ if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) {
+ /*
+ By default the maps will not be set up for dual
+ prime. We have to change them.
+ */
+ if(!pI810XvMC->dual_prime) {
+ pI810XvMC->dual_prime = 1;
+ privFuture = privPast;
+ /* Y */
+ *datay++ = CMD_MAP_INFO;
+ *datay++ = privFuture->mi1y | 0x1<<28;
+ *datay++ = privFuture->mi2y;
+ *datay++ = privFuture->mi3y;
+ /* U */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ /* V */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+ }
+ if((pI810XvMC->dual_prime) &&
+ (mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) {
+ pI810XvMC->dual_prime = 0;
+ privFuture = privTarget;
+ /* Y */
+ *datay++ = CMD_MAP_INFO;
+ *datay++ = privFuture->mi1y | 0x1<<28;
+ *datay++ = privFuture->mi2y;
+ *datay++ = privFuture->mi3y;
+ /* U */
+ *datau++ = CMD_MAP_INFO;
+ *datau++ = privFuture->mi1u | 0x1<<28;
+ *datau++ = privFuture->mi2u;
+ *datau++ = privFuture->mi3u;
+ /* V */
+ *datav++ = CMD_MAP_INFO;
+ *datav++ = privFuture->mi1v | 0x1<<28;
+ *datav++ = privFuture->mi2v;
+ *datav++ = privFuture->mi3v;
+ }
+
+
+ /* Frame Picture */
+ if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
+ /* Intra Blocks */
+ if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ if(mb->dct_type) {
+ renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ }
+ renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr);
+ continue;
+ }
+ switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) {
+ case 0x2: /* Frame DCT0 */
+ renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x5: /* Field DCT1 */
+ renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x6: /* Frame DCT1 */
+ renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x1: /* Field DCT0 */
+ renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x3: /* Dual Prime DCT0 */
+ renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ case 0x7: /* Dual Prime DCT1 */
+ renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
+ continue;
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ } /* Switch */
+ } /* Frame Picture */
+
+ /* Field Pictures */
+ if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
+ renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure);
+ continue;
+ }
+ switch(mb->motion_type & 0x3) {
+ case 0x1: /* Field Motion */
+ renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
+ flags);
+ continue;
+ case 0x2: /* 16x8 Motion */
+ render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
+ flags);
+ continue;
+ case 0x3: /* Dual Prime */
+ renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr,
+ picture_structure,flags);
+ continue;
+ default: /* No Motion Type */
+ renderError();
+ continue;
+ }
+ continue;
+
+ } /* for each Macroblock */
+
+ /* Dispatch remaining DMA buffers */
+ if(dirty_context) {
+ dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
+ }
+ mc.idx = pDMAy->idx;
+ mc.used = (unsigned long)datay - (unsigned long)pDMAy->address;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+
+ pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
+ for(j=0; j<=u_index; j++) {
+ mc.idx = pDMAu[j]->idx;
+ mc.used = pDMAu[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+ pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
+ for(j=0; j<=v_index; j++) {
+ mc.idx = pDMAv[j]->idx;
+ mc.used = pDMAv[j]->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+ }
+
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCPutSurface
+// Description:
+// Arguments:
+// display: Connection to X server
+// surface: Surface to be displayed
+// draw: X Drawable on which to display the surface
+// srcx: X coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcy: Y coordinate of the top left corner of the region to be
+// displayed within the surface.
+// srcw: Width of the region to be displayed.
+// srch: Height of the region to be displayed.
+// destx: X cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// desty: Y cordinate of the top left corner of the destination region
+// in the drawable coordinates.
+// destw: Width of the destination region.
+// desth: Height of the destination region.
+// flags: One or more of the following.
+// XVMC_TOP_FIELD - Display only the Top field of the surface.
+// XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface.
+// XVMC_FRAME_PICTURE - Display both fields or frame.
+//
+// Info: Portions of this function derived from i810_video.c (XFree86)
+//
+// This function is organized so that we wait as long as possible before
+// touching the overlay registers. Since we don't know that the last
+// flip has happened yet we want to give the overlay as long as
+// possible to catch up before we have to check on its progress. This
+// makes it unlikely that we have to wait on the last flip.
+***************************************************************************/
+_X_EXPORT Status XvMCPutSurface(Display *display,XvMCSurface *surface,
+ Drawable draw, short srcx, short srcy,
+ unsigned short srcw, unsigned short srch,
+ short destx, short desty,
+ unsigned short destw, unsigned short desth,
+ int flags) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSurface *pI810Surface;
+ i810OverlayRecPtr pORegs;
+ unsigned int ysrc_offset,uvsrc_offset;
+ Box extents;
+ uint window_width,window_height;
+ unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0;
+ unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0;
+ unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0;
+ unsigned int ovcmd = 0;
+ uint d;
+ double xscale,yscale;
+ int diff;
+ int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty;
+ int clipped_srcw, clipped_srch, clipped_destw, clipped_desth;
+ uint x1,y1,root_width,root_height;
+ int x2 = 0, y2 = 0,unused;
+ uint nChilds;
+ int stat;
+ Window win,root,parent,*pChilds;
+
+
+ if((display == NULL) || (surface == NULL)) {
+ return BadValue;
+ }
+
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+ pORegs = (i810OverlayRecPtr)pI810XvMC->oregs;
+
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ yPitch = (srcw + 7) & ~7;
+ uvPitch = ((srcw>>1) + 7) & ~7;
+ if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
+ srch = srch>>1;
+ }
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ /* FIXME: Non Planar not fully implemented. */
+ return BadValue;
+ yPitch = ((srcw + 7) & ~7) << 1;
+ break;
+ }/* switch(surface->surface_type_id) */
+
+ /*
+ FIXME: This should be using the DRI's clip rect but that isn't
+ all hooked up yet. This has some latency but we get by.
+ */
+ win = draw;
+ XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
+ if(nChilds) XFree(pChilds);
+ XGetGeometry(display,win, &root, &x2, &y2, &window_width,
+ &window_height, &d, &d);
+ x1 = x2;
+ y1 = y2;
+ win = parent;
+ do {
+ XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
+ if(nChilds) XFree(pChilds);
+ XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d);
+ x1 += x2;
+ y1 += y2;
+ win = parent;
+ }while(win != root);
+ XGetGeometry(display,root, &root, &unused, &unused,
+ &root_width, &root_height, &d, &d);
+
+ /* Left edge of Video window clipped to screen */
+ extents.x1 = 0;
+ if(x1 > extents.x1) {
+ extents.x1 = x1;
+ }
+ /* Right edge of Video window clipped to screen */
+ extents.x2 = root_width;
+ if(extents.x2 > (x1 + window_width)) {
+ extents.x2 = x1 + window_width;
+ }
+ /* Top edge of Video window clipped to screen */
+ extents.y1 = 0;
+ if(y1 > extents.y1) {
+ extents.y1 = y1;
+ }
+ /* Bottom edge of Video window clipped to screen */
+ extents.y2 = root_height;
+ if(extents.y2 > (y1 + window_height)) {
+ extents.y2 = y1 + window_height;
+ }
+
+ /*
+ Clipping is more difficult than is seems. We need to keep the
+ scaling factors even if the destination window needs to be clipped.
+ We clip the destination window first then apply a scaled version
+ to the source window.
+ */
+
+ /* Put destination coords in screen coords */
+ destx += x1;
+ desty += y1;
+
+ /* Scale factors requested */
+ xscale = (double)srcw / (double)destw;
+ yscale = (double)srch / (double)desth;
+
+ /*
+ If destination window needs to be clipped we actually adjust both
+ the src and dest window so as to keep the scaling that was requested
+ */
+ clipped_srcx = srcx;
+ clipped_srcy = srcy;
+ clipped_destx = destx;
+ clipped_desty = desty;
+ clipped_srcw = srcw;
+ clipped_srch = srch;
+ clipped_destw = destw;
+ clipped_desth = desth;
+
+ /* Clip to the source surface boundaries */
+ if(clipped_srcx < 0) {
+ clipped_destx += (0 - clipped_srcx) / xscale;
+ clipped_srcw -= clipped_srcx;
+ clipped_destw -= clipped_srcx / xscale;
+ clipped_srcx = 0;
+ }
+ if((clipped_srcw + clipped_srcx) > surface->width) {
+ clipped_srcw = surface->width - clipped_srcx;
+ clipped_destw -= (clipped_srcw - srcw) / xscale;
+ }
+ if(clipped_srcy < 0) {
+ clipped_desty += (0 - clipped_srcy) / yscale;
+ clipped_srch -= clipped_srcy;
+ clipped_desth -= clipped_srcy / yscale;
+ clipped_srcy = 0;
+ }
+ if((clipped_srch + clipped_srcy) > surface->height) {
+ clipped_srch = surface->height - clipped_srcy;
+ clipped_desth -= (clipped_srch - srch) / yscale;
+ }
+
+ /* Clip to the extents */
+ if(clipped_destx < extents.x1) {
+ diff = extents.x1 - clipped_destx;
+ clipped_srcx += diff * xscale;
+ clipped_srcw -= diff * xscale;
+ clipped_destw -= diff;
+ clipped_destx = extents.x1;
+ }
+
+ diff = (clipped_destx + clipped_destw) - extents.x2;
+ if(diff > 0) {
+ clipped_destw -= diff;
+ clipped_srcw -= diff * xscale;
+ }
+
+ if(clipped_desty < extents.y1) {
+ diff = extents.y1 - clipped_desty;
+ clipped_srcy += diff * yscale;
+ clipped_srch -= diff * yscale;
+ clipped_desth -= diff;
+ clipped_desty = 0;
+ }
+
+ diff = (clipped_desty + clipped_desth) - extents.y2;
+ if(diff > 0) {
+ clipped_desth -= diff;
+ clipped_srch -= diff * yscale;
+ }
+
+ /* If the whole window is clipped turn off the overlay */
+ if((clipped_destx + clipped_destw < extents.x1) ||
+ (clipped_desty + clipped_desth < extents.y1) ||
+ (clipped_destx > extents.x2) ||
+ (clipped_desty > extents.y2)) {
+ return XvMCHideSurface(display, surface);
+ }
+
+ /*
+ Adjust the source offset width and height according to the clipped
+ destination window.
+ */
+ ysrc_offset = ((clipped_srcx + 1) & ~1) +
+ ((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch);
+ uvsrc_offset = (clipped_srcx>>1) +
+ (clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1));
+
+ /*
+ Initially, YCbCr and Overlay Enable and
+ vertical chrominance up interpolation and horozontal chrominance
+ up interpolation
+ */
+ ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST | OVERLAY_ENABLE;
+
+ if ((clipped_destw != clipped_srcw) ||
+ (clipped_desth != clipped_srch)) {
+ xscaleInt = (clipped_srcw / clipped_destw) & 0x3;
+ xscaleFract = (clipped_srcw << 12) / clipped_destw;
+ yscaleInt = (clipped_srch / clipped_desth) & 0x3;
+ yscaleFract = (clipped_srch << 12) / clipped_desth;
+
+ if (clipped_destw > clipped_srcw) {
+ /* horizontal up-scaling */
+ ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
+ ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
+ }
+
+ if (clipped_desth > clipped_srch) {
+ /* vertical up-scaling */
+ ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
+ ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
+ ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
+ }
+
+ if (clipped_destw < clipped_srcw) {
+ /* horizontal down-scaling */
+ ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
+ ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
+ }
+
+ if (clipped_desth < clipped_srch) {
+ /* vertical down-scaling */
+ ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
+ ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
+ ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
+ }
+
+ /* now calculate the UV scaling factor */
+ if (xscaleFract) {
+ xscaleFractUV = xscaleFract >> MINUV_SCALE;
+ ovcmd &= ~HC_DOWN_INTERPOLATION;
+ ovcmd |= HC_UP_INTERPOLATION;
+ }
+
+ if (xscaleInt) {
+ xscaleIntUV = xscaleInt >> MINUV_SCALE;
+ if (xscaleIntUV) {
+ ovcmd &= ~HC_UP_INTERPOLATION;
+ }
+ }
+
+ if (yscaleFract) {
+ yscaleFractUV = yscaleFract >> MINUV_SCALE;
+ ovcmd &= ~VC_DOWN_INTERPOLATION;
+ ovcmd |= VC_UP_INTERPOLATION;
+ }
+
+ if (yscaleInt) {
+ yscaleIntUV = yscaleInt >> MINUV_SCALE;
+ if (yscaleIntUV) {
+ ovcmd &= ~VC_UP_INTERPOLATION;
+ ovcmd |= VC_DOWN_INTERPOLATION;
+ }
+ }
+
+ }/* if((destw != srcw) || (desth != srch)) */
+
+ /* Lock the DRM */
+ I810_LOCK(pI810XvMC,0);
+
+ /* Block until rendering on this surface is finished */
+ stat = XVMC_RENDERING;
+ while(stat & XVMC_RENDERING) {
+ XvMCGetSurfaceStatus(display,surface,&stat);
+ }
+ /* Block until the last flip is finished */
+ if(pI810XvMC->last_flip) {
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+ }
+
+ pI810XvMC->current = !pI810XvMC->current;
+ pORegs->OV0CMD = ovcmd;
+
+ if ((clipped_destw != clipped_srcw) ||
+ (clipped_desth != clipped_srch)) {
+ pORegs->YRGBSCALE = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) | (yscaleInt) |
+ ((yscaleFract & 0xFFF) << 20);
+
+ pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ }
+ else {
+ /* Normal 1:1 scaling */
+ pORegs->YRGBSCALE = 0x80004000;
+ pORegs->UVSCALE = 0x80004000;
+ }
+
+ pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15);
+ pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx;
+ pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw));
+
+ /* Attributes */
+ pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) |
+ (pI810XvMC->brightness & 0xff);
+ pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff);
+
+ /* Destination Colorkey Setup */
+ pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
+
+ /* buffer locations, add the offset from the clipping */
+ if(pI810XvMC->current) {
+ pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
+ pORegs->OBUF_1V = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
+ pORegs->OBUF_1U = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
+ }
+ else {
+ pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[0] + ysrc_offset;
+ pORegs->OBUF_0V = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
+ pORegs->OBUF_0U = (unsigned long)pI810Surface->offset +
+ (unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
+ }
+
+ switch(surface->surface_type_id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ pORegs->SWID = (uvPitch << 16) | yPitch;
+ pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3);
+ pORegs->OV0STRIDE = (1<<pI810Surface->pitch) |
+ ((1<<pI810Surface->pitch) << 15);
+ pORegs->OV0CMD &= ~SOURCE_FORMAT;
+ pORegs->OV0CMD |= YUV_420;
+ if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
+ /* Top Field Only */
+ if(flags & XVMC_TOP_FIELD) {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER1_FIELD0);
+ }
+ else {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER0_FIELD0);
+ }
+ pORegs->YRGB_VPH = 1<<15 | 1<<31;
+ pORegs->UV_VPH = 3<<14 | 3<<30;
+ pORegs->INIT_PH = 0x06 | 0x18;
+ }
+ /* Bottom Field Only */
+ else {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER1_FIELD1);
+ }
+ else {
+ pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
+ BUFFER0_FIELD1);
+ }
+ pORegs->YRGB_VPH = 0;
+ pORegs->UV_VPH = 7<<29 | 7<<13;
+ pORegs->INIT_PH = 0x06;
+ }
+ }
+ /* Frame Picture */
+ else {
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ pORegs->YRGB_VPH = 0;
+ pORegs->UV_VPH = 0;
+ pORegs->INIT_PH = 0;
+ }
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ pORegs->SWID = srcw;
+ pORegs->SWIDQW = srcw >> 3;
+ pORegs->OV0STRIDE = pI810Surface->pitch;
+ pORegs->OV0CMD &= ~SOURCE_FORMAT;
+ pORegs->OV0CMD |= YUV_422;
+ pORegs->OV0CMD &= ~OV_BYTE_ORDER;
+ if (surface->surface_type_id == FOURCC_UYVY) {
+ pORegs->OV0CMD |= Y_SWAP;
+ }
+
+ pORegs->OV0CMD &= ~BUFFER_AND_FIELD;
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+
+ break;
+ } /* switch(surface->surface_type_id) */
+
+
+
+ OVERLAY_FLIP(pI810XvMC);
+
+ /*
+ The Overlay only flips when it knows you changed
+ something. So the first time change stuff while it
+ is watching to be sure.
+ */
+ if(!pI810XvMC->last_flip) {
+ pORegs->OV0CMD &= ~0x4;
+ if(pI810XvMC->current == 1) {
+ pORegs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pORegs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ }
+ pI810Surface->last_flip = ++pI810XvMC->last_flip;
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCSyncSurface
+// Arguments:
+// display - Connection to the X server
+// surface - The surface to synchronize
+// Info:
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
+ Status ret;
+ int stat=0;
+ /*
+ FIXME: Perhaps a timer here to prevent lockup?
+ FIXME: Perhaps a usleep to not be busy waiting?
+ */
+ do {
+ ret = XvMCGetSurfaceStatus(display,surface,&stat);
+ }while(!ret && (stat & XVMC_RENDERING));
+ return ret;
+}
+
+/***************************************************************************
+// Function: XvMCFlushSurface
+// Description:
+// This function commits pending rendering requests to ensure that they
+// wll be completed in a finite amount of time.
+// Arguments:
+// display - Connection to X server
+// surface - Surface to flush
+// Info:
+// This command is a noop for i810 becuase we always dispatch buffers in
+// render. There is little gain to be had with 4k buffers.
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface *surface) {
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCGetSurfaceStatus
+// Description:
+// Arguments:
+// display: connection to X server
+// surface: The surface to query
+// stat: One of the Following
+// XVMC_RENDERING - The last XvMCRenderSurface command has not
+// completed.
+// XVMC_DISPLAYING - The surface is currently being displayed or a
+// display is pending.
+***************************************************************************/
+_X_EXPORT Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface,
+ int *stat) {
+ i810XvMCSurface *privSurface;
+ i810XvMCContext *pI810XvMC;
+ int temp;
+
+ if((display == NULL) || (surface == NULL) || (stat == NULL)) {
+ return BadValue;
+ }
+ if(surface->privData == NULL) {
+ return BadValue;
+ }
+ *stat = 0;
+ privSurface = surface->privData;
+
+ pI810XvMC = privSurface->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ I810_LOCK(pI810XvMC,0);
+ if(privSurface->last_flip) {
+ /* This can not happen */
+ if(pI810XvMC->last_flip < privSurface->last_flip) {
+ printf("Error: Context last flip is less than surface last flip.\n");
+ return BadValue;
+ }
+ /*
+ If the context has 2 or more flips after this surface it
+ cannot be displaying. Don't bother to check.
+ */
+ if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) {
+ /*
+ If this surface was the last flipped it is either displaying
+ or about to be so don't bother checking.
+ */
+ if(pI810XvMC->last_flip == privSurface->last_flip) {
+ *stat |= XVMC_DISPLAYING;
+ }
+ else {
+ /*
+ In this case there has been one more flip since our surface's
+ but we need to check if it is finished or not.
+ */
+ temp = GET_FSTATUS(pI810XvMC);
+ if(((temp & (1<<20))>>20) != pI810XvMC->current) {
+ *stat |= XVMC_DISPLAYING;
+ }
+ }
+ }
+ }
+
+ if(privSurface->last_render &&
+ (privSurface->last_render > GET_RSTATUS(pI810XvMC))) {
+ *stat |= XVMC_RENDERING;
+ }
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+/***************************************************************************
+//
+// Surface manipulation functions
+//
+***************************************************************************/
+
+/***************************************************************************
+// Function: XvMCHideSurface
+// Description: Stops the display of a surface.
+// Arguments:
+// display - Connection to the X server.
+// surface - surface to be hidden.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCHideSurface(Display *display, XvMCSurface *surface) {
+ i810XvMCSurface *pI810Surface;
+ i810XvMCContext *pI810XvMC;
+ int ss, xx;
+
+ /* Did we get a good display and surface passed into us? */
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ if(surface == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ XvMCSyncSurface(display, surface);
+
+ /* Get surface private data pointer */
+ if(surface->privData == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+ pI810Surface = (i810XvMCSurface *)surface->privData;
+
+ /*
+ Get the status of the surface, if it is not currently displayed
+ we don't need to worry about it.
+ */
+ if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) {
+ return xx;
+ }
+ if(! (ss & XVMC_DISPLAYING)) {
+ return Success;
+ }
+
+ /* Get the associated context pointer */
+ pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if(pI810XvMC->last_flip) {
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+ /* Make sure last flip is done */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ /* Set the registers to turn the overlay off */
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST;
+ pI810XvMC->current = !pI810XvMC->current;
+ if(pI810XvMC->current == 1) {
+ pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ OVERLAY_FLIP(pI810XvMC);
+ /*
+ Increment the context flip but not the surface. This way no
+ surface has the last flip #.
+ */
+ pI810XvMC->last_flip++;
+
+
+ /* Now wait until the hardware reads the registers and makes the change. */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current)
+
+ I810_UNLOCK(pI810XvMC);
+ }
+
+ return Success;
+}
+
+
+
+
+/***************************************************************************
+//
+// Functions that deal with subpictures
+//
+***************************************************************************/
+
+
+
+/***************************************************************************
+// Function: XvMCCreateSubpicture
+// Description: This creates a subpicture by filling out the XvMCSubpicture
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// context - The context to create the subpicture for.
+// subpicture - Pre-allocated XvMCSubpicture structure to be filled in.
+// width - of subpicture
+// height - of subpicture
+// xvimage_id - The id describing the XvImage format.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCCreateSubpicture(Display *display, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ unsigned short width, unsigned short height,
+ int xvimage_id) {
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int priv_count;
+ uint *priv_data;
+ Status ret;
+
+ if((subpicture == NULL) || (context == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ pI810XvMC = (i810XvMCContext *)context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+
+ /* These need to be checked to make sure they are not too big! */
+ subpicture->width = width;
+ subpicture->height = height;
+
+ subpicture->privData =
+ (i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture));
+
+ if(!subpicture->privData) {
+ return BadAlloc;
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+
+ if((ret = _xvmc_create_subpicture(display, context, subpicture,
+ &priv_count, &priv_data))) {
+ printf("Unable to create XvMCSubpicture.\n");
+ return ret;
+ }
+
+ if(priv_count != 1) {
+ printf("_xvmc_create_subpicture() returned incorrect data size.\n");
+ printf("Expected 1 got %d\n",priv_count);
+ free(priv_data);
+ return BadAlloc;
+ }
+ /* Data == Client Address, offset == Physical address offset */
+ pI810Subpicture->data = pI810XvMC->surfaces.address;
+ pI810Subpicture->offset = pI810XvMC->surfaces.offset;
+
+ /* Initialize private values */
+ pI810Subpicture->privContext = pI810XvMC;
+
+ pI810Subpicture->last_render = 0;
+ pI810Subpicture->last_flip = 0;
+
+ /* Based on the xvimage_id we will need to set the other values */
+ subpicture->num_palette_entries = 16;
+ subpicture->entry_bytes = 3;
+ strcpy(subpicture->component_order,"YUV");
+
+ /*
+ i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch
+ and the Tiler need 512k aligned surfaces, basically we are
+ stuck with fixed memory with pitch 1024.
+ */
+ pI810Subpicture->pitch = 10;
+
+ /*
+ offsets[0] == offset into the map described by either
+ address (Client memeory address) or offset (physical offset from fb base)
+ */
+ pI810Subpicture->offsets[0] = priv_data[0];
+ if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) {
+ printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n");
+ }
+
+ /* Free data returned from xvmc_create_surface */
+ free(priv_data);
+
+ /* Clear the surface to 0 */
+ memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]),
+ 0, ((1<<pI810Subpicture->pitch) * subpicture->height));
+
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ /* Destination buffer info command */
+ pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset +
+ pI810Subpicture->offsets[0]) & ~0xfc000fff) |
+ (pI810Subpicture->pitch - 9));
+
+ /* Destination buffer variables command */
+ pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16);
+
+ /* Map info command */
+ pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) |
+ (pI810Subpicture->pitch - 3);
+
+ pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) |
+ ((unsigned int)subpicture->width - 1);
+
+ pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset +
+ pI810Subpicture->offsets[0]) & ~0xfc00000f;
+ break;
+ default:
+ free(subpicture->privData);
+ return BadMatch;
+ }
+
+ pI810XvMC->ref++;
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCClearSubpicture
+// Description: Clear the area of the given subpicture to "color".
+// structure passed to it and returning Success.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// x, y, width, height - rectangle in the subpicture to clear.
+// color - The data to file the rectangle with.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture,
+ short x, short y,
+ unsigned short width, unsigned short height,
+ unsigned int color) {
+
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int i;
+
+ if((subpicture == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((x < 0) || (x + width > subpicture->width)) {
+ return BadValue;
+ }
+
+ if((y < 0) || (y + height > subpicture->height)) {
+ return BadValue;
+ }
+
+ for(i=y; i<y + height; i++) {
+ memset((void *)((unsigned long)pI810Subpicture->data +
+ (unsigned long)pI810Subpicture->offsets[0] + x +
+ (1<<pI810Subpicture->pitch) * i),(char)color,width);
+ }
+
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCCompositeSubpicture
+// Description: Composite the XvImae on the subpicture. This composit uses
+// non-premultiplied alpha. Destination alpha is utilized
+// except for with indexed subpictures. Indexed subpictures
+// use a simple "replace".
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to clear.
+// image - the XvImage to be used as the source of the composite.
+// srcx, srcy, width, height - The rectangle from the image to be used.
+// dstx, dsty - location in the subpicture to composite the source.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx, short srcy,
+ unsigned short width, unsigned short height,
+ short dstx, short dsty) {
+
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *pI810Subpicture;
+ int i;
+
+ if((subpicture == NULL) || (display == NULL)){
+ return BadValue;
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((srcx < 0) || (srcx + width > image->width)) {
+ return BadValue;
+ }
+
+ if((dstx < 0) || (dstx + width > subpicture->width)) {
+ return BadValue;
+ }
+
+ if((srcy < 0) || (srcy + height > image->height)) {
+ return BadValue;
+ }
+
+ if((dsty < 0) || (dsty + height > subpicture->height)) {
+ return BadValue;
+ }
+
+ for(i=0; i<height; i++) {
+ memcpy((void *)((unsigned long)pI810Subpicture->data +
+ (unsigned long)pI810Subpicture->offsets[0] + dstx +
+ (1<<pI810Subpicture->pitch) * (i + dsty)),
+ (void *)((unsigned long)image->data +
+ (unsigned long)image->offsets[0] + srcx +
+ image->pitches[0] * (i + srcy))
+ ,width);
+ }
+
+ return Success;
+
+}
+
+
+/***************************************************************************
+// Function: XvMCDestroySubpicture
+// Description: Destroys the specified subpicture.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpicture to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) {
+
+ i810XvMCSubpicture *pI810Subpicture;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (subpicture == NULL)) {
+ return BadValue;
+ }
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
+ if(!pI810XvMC) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+
+ if(pI810Subpicture->last_render) {
+ XvMCSyncSubpicture(display,subpicture);
+ }
+
+ _xvmc_destroy_subpicture(display,subpicture);
+
+ i810_free_privContext(pI810XvMC);
+
+ free(pI810Subpicture);
+ subpicture->privData = NULL;
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCSetSubpicturePalette
+// Description: Set the subpictures palette
+// Arguments:
+// display - Connection to the X server.
+// subpicture - Subpiture to set palette for.
+// palette - A pointer to an array holding the palette data. The array
+// is num_palette_entries * entry_bytes in size.
+// Returns: Status
+***************************************************************************/
+
+_X_EXPORT Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture,
+ unsigned char *palette) {
+ i810XvMCSubpicture *privSubpicture;
+ int i,j;
+
+ if((display == NULL) || (subpicture == NULL)) {
+ return BadValue;
+ }
+ if(subpicture->privData == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ j=0;
+ for(i=0; i<16; i++) {
+ privSubpicture->palette[0][i] = palette[j++];
+ privSubpicture->palette[1][i] = palette[j++];
+ privSubpicture->palette[2][i] = palette[j++];
+ }
+ return Success;
+}
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i810 only support frontend behavior.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture is a no-op in this case.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx, short suby,
+ unsigned short subw, unsigned short subh,
+ short surfx, short surfy,
+ unsigned short surfw, unsigned short surfh) {
+
+ return BadMatch;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCBlendSubpicture2
+// Description:
+// The behavior of this function is different depending on whether
+// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo.
+// i810 only supports frontend blending.
+//
+// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior):
+//
+// XvMCBlendSubpicture2 blends the source_surface and subpicture and
+// puts it in the target_surface. This does not effect the status of
+// the source surface but will cause the target_surface to query
+// XVMC_RENDERING until the blend is completed.
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to be blended into the video.
+// target_surface - The surface to be displayed with the blended subpic.
+// source_surface - Source surface prior to blending.
+// subx, suby, subw, subh - The rectangle from the subpicture to use.
+// surfx, surfy, surfw, surfh - The rectangle in the surface to blend
+// blend the subpicture rectangle into. Scaling can ocure if
+// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set.
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCBlendSubpicture2(Display *display,
+ XvMCSurface *source_surface,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx, short suby,
+ unsigned short subw, unsigned short subh,
+ short surfx, short surfy,
+ unsigned short surfw, unsigned short surfh) {
+ drmBufPtr pDMA;
+ unsigned int *data;
+ i810XvMCContext *pI810XvMC;
+ i810XvMCSubpicture *privSubpicture;
+ i810XvMCSurface *privTarget;
+ i810XvMCSurface *privSource;
+ drm_i810_mc_t mc;
+ int i,j;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+
+ if(subpicture == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if((target_surface == NULL) || (source_surface == NULL)) {
+ return (error_base + XvMCBadSurface);
+ }
+
+ if((subpicture->xvimage_id != FOURCC_AI44) &&
+ (subpicture->xvimage_id != FOURCC_IA44)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if(!subpicture->privData) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ if(!target_surface->privData) {
+ return (error_base + XvMCBadSurface);
+ }
+ privTarget = (i810XvMCSurface *)target_surface->privData;
+
+ if(!source_surface->privData) {
+ return (error_base + XvMCBadSurface);
+ }
+ privSource = (i810XvMCSurface *)source_surface->privData;
+
+
+ /* Check that size isn't bigger than subpicture */
+ if((subx + subw) > subpicture->width) {
+ return BadValue;
+ }
+ if((suby + subh) > subpicture->height) {
+ return BadValue;
+ }
+ /* Check that dest isn't bigger than surface */
+ if((surfx + surfw) > target_surface->width) {
+ return BadValue;
+ }
+ if((surfy + surfh) > target_surface->height) {
+ return BadValue;
+ }
+ /* Make sure surfaces match */
+ if(target_surface->width != source_surface->width) {
+ return BadValue;
+ }
+ if(target_surface->height != source_surface->height) {
+ return BadValue;
+ }
+
+ /* Lock For DMA */
+ I810_LOCK(pI810XvMC,0);
+
+ /* Allocate DMA buffer */
+ pDMA = i810_get_free_buffer(pI810XvMC);
+ data = pDMA->address;
+
+ /* Copy Y data first */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch);
+ *data++ = (target_surface->height<<16) | target_surface->width;
+ *data++ = privTarget->offset + privTarget->offsets[0];
+ *data++ = (1<<privSource->pitch);
+ *data++ = privSource->offset + privSource->offsets[0];
+
+ /* Select Context 1 for loading */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+
+ /* Load Palette */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ /* *data++ = CMD_FLUSH; */
+ /* *data++ = BOOLEAN_ENA_2; */
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1y;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = DRAWING_RECT_INFO;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+ *data++ = 0x0;
+
+ /* GFXPRIMITIVE RECTANGLE */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right Vertex */
+ *(float *)data++ = (float) (surfx + surfw);
+ *(float *)data++ = (float) (surfy + surfh);
+ *(float *)data++ = (float) (subx + subw);
+ *(float *)data++ = (float) (suby + subh);
+ /* Bottom Left Vertex */
+ *(float *)data++ = (float) surfx;
+ *(float *)data++ = (float) (surfy + surfh);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) (suby + subh);
+ /* Top Left Vertex */
+ *(float *)data++ = (float) surfx;
+ *(float *)data++ = (float) surfy;
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+ /* U data */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
+ *data++ = (target_surface->height<<15) | (target_surface->width>>1);
+ *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1];
+ *data++ = (1<<(privSource->pitch - 1));
+ *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1];
+
+ /* Context 1 select */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+ /* ALPHA PALETTE */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1u;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+
+ /* Rectangle */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right */
+ *(float *)data++ = (float) ((surfx + surfw)>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx + subw;
+ *(float *)data++ = (float) suby + subh;
+ /* Bottom Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby + subh;
+ /* Top Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) (surfy>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+ /* V data */
+ /* SOURCE_COPY_BLT */
+ *data++ = (2<<29) | (0x43<<22) | 0x4;
+ *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
+ *data++ = (target_surface->height<<15) | (target_surface->width>>1);
+ *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2];
+ *data++ = (1<<(privSource->pitch - 1));
+ *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2];
+
+ /* Context 1 select */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<8);
+ *data++ = CMD_FLUSH;
+
+ /* ALPHA PALETTE */
+ *data++ = MAP_PALETTE_LOAD;
+ /* 16 levels of alpha for each Y */
+ switch(subpicture->xvimage_id) {
+ case FOURCC_IA44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i];
+ }
+ }
+ break;
+ case FOURCC_AI44:
+ for(i=0; i<16; i++) {
+ for(j=0; j<16; j++) {
+ *data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j];
+ }
+ }
+ break;
+ }
+ /* TARGET */
+ *data++ = CMD_FLUSH;
+ *data++ = BOOLEAN_ENA_2;
+ *data++ = CMD_FLUSH;
+ *data++ = DEST_BUFFER_INFO;
+ *data++ = privTarget->dbi1v;
+ *data++ = DEST_BUFFER_VAR;
+ *data++ = privTarget->dbv1;
+
+ /* ALPHA */
+ *data++ = CMD_MAP_INFO;
+ *data++ = privSubpicture->mi1;
+ *data++ = privSubpicture->mi2;
+ *data++ = privSubpicture->mi3;
+
+ *data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
+ *data++ = BOOLEAN_ENA_1;
+ *data++ = SRC_DEST_BLEND_MONO | (0x940);
+ /* Map Filter */
+ *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
+
+ /* Use context 1 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<16) | 1;
+ *data++ = CMD_FLUSH;
+
+ /* Drawing Rect Info */
+ *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+
+ /* Rectangle */
+ *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
+ /* Bottom Right */
+ *(float *)data++ = (float) ((surfx + surfw)>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx + subw;
+ *(float *)data++ = (float) suby + subh;
+ /* Bottom Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) ((surfy + surfh)>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby + subh;
+ /* Top Left */
+ *(float *)data++ = (float) (surfx>>1);
+ *(float *)data++ = (float) (surfy>>1);
+ *(float *)data++ = (float) subx;
+ *(float *)data++ = (float) suby;
+
+ /* Load and Use Context 0 */
+ *data++ = CMD_FLUSH;
+ *data++ = (5<<23) | (1<<17) | (1<<16);
+ *data++ = CMD_FLUSH;
+
+
+ /* Dispatch */
+ pDMA->used = (unsigned long)data - (unsigned long)pDMA->address;
+ mc.idx = pDMA->idx;
+ mc.used = pDMA->used;
+ mc.last_render = ++pI810XvMC->last_render;
+ privTarget->last_render = pI810XvMC->last_render;
+ I810_MC(pI810XvMC,mc);
+
+ I810_UNLOCK(pI810XvMC);
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCSyncSubpicture
+// Description: This function blocks until all composite/clear requests on
+// the subpicture have been complete.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture to synchronize
+//
+// Returns: Status
+***************************************************************************/
+_X_EXPORT Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) {
+ Status ret;
+ int stat=0;
+ do {
+ ret = XvMCGetSubpictureStatus(display,subpicture,&stat);
+ }while(!ret && (stat & XVMC_RENDERING));
+ return ret;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCFlushSubpicture
+// Description: This function commits pending composite/clear requests to
+// ensure that they will be completed in a finite amount of
+// time.
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos compsiting should be flushed
+//
+// Returns: Status
+// NOTES: i810 always dispatches commands so flush is a no-op
+***************************************************************************/
+_X_EXPORT Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) {
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(subpicture == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ return Success;
+}
+
+
+
+/***************************************************************************
+// Function: XvMCGetSubpictureStatus
+// Description: This function gets the current status of a subpicture
+//
+// Arguments:
+// display - Connection to the X server.
+// subpicture - The subpicture whos status is being queried
+// stat - The status of the subpicture. It can be any of the following
+// OR'd together:
+// XVMC_RENDERING - Last composite or clear request not completed
+// XVMC_DISPLAYING - Suppicture currently being displayed.
+//
+// Returns: Status
+// Notes: i810 always blends into a third surface so the subpicture is
+// never actually displaying, only a copy of it is displaying. We only
+// have to worry about the rendering case.
+***************************************************************************/
+_X_EXPORT Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture,
+ int *stat) {
+
+ i810XvMCSubpicture *privSubpicture;
+ i810XvMCContext *pI810XvMC;
+
+ if((display == NULL) || (stat == NULL)) {
+ return BadValue;
+ }
+ if((subpicture == NULL) || (subpicture->privData == NULL)) {
+ return (error_base + XvMCBadSubpicture);
+ }
+ *stat = 0;
+ privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
+
+ pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadSubpicture);
+ }
+
+ I810_LOCK(pI810XvMC,0);
+
+ if(privSubpicture->last_render &&
+ (privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) {
+ *stat |= XVMC_RENDERING;
+ }
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+}
+
+#define NUM_XVMC_ATTRIBUTES 4
+static XvAttribute I810_XVMC_ATTRIBUTES[] = {
+ {XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"},
+ {XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"},
+ {XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"},
+ {XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"}
+};
+
+
+/***************************************************************************
+// Function: XvMCQueryAttributes
+// Description: An array of XvAttributes of size "number" is returned by
+// this function. If there are no attributes, NULL is returned and number
+// is set to 0. The array may be freed with xfree().
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// number - The number of returned atoms.
+//
+// Returns:
+// An array of XvAttributes.
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+_X_EXPORT XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context,
+ int *number) {
+ i810XvMCContext *pI810XvMC;
+ XvAttribute *attributes;
+
+ if(number == NULL) {
+ return NULL;
+ }
+ if(display == NULL) {
+ *number = 0;
+ return NULL;
+ }
+ if(context == NULL) {
+ *number = 0;
+ return NULL;
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ *number = 0;
+ return NULL;
+ }
+
+ attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES *
+ sizeof(XvAttribute));
+ if(attributes == NULL) {
+ *number = 0;
+ return NULL;
+ }
+
+ memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES *
+ sizeof(XvAttribute)));
+
+ *number = NUM_XVMC_ATTRIBUTES;
+ return attributes;
+}
+
+/***************************************************************************
+// Function: XvMCSetAttribute
+// Description: This function sets a context-specific attribute.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be changed.
+// value - The new value for the attribute.
+//
+// Returns:
+// Status
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+_X_EXPORT Status XvMCSetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int value) {
+ i810XvMCContext *pI810XvMC;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+
+ if(attribute == pI810XvMC->xv_colorkey) {
+ if((value < I810_XVMC_ATTRIBUTES[0].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[0].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->colorkey = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_brightness) {
+ if((value < I810_XVMC_ATTRIBUTES[1].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[1].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->brightness = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_saturation) {
+ if((value < I810_XVMC_ATTRIBUTES[2].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[2].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->saturation = value;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_contrast) {
+ if((value < I810_XVMC_ATTRIBUTES[3].min_value) ||
+ (value > I810_XVMC_ATTRIBUTES[3].max_value)) {
+ return BadValue;
+ }
+ pI810XvMC->contrast = value;
+ return Success;
+ }
+ return BadValue;
+}
+
+/***************************************************************************
+// Function: XvMCGetAttribute
+// Description: This function queries a context-specific attribute and
+// returns the value.
+//
+// Arguments:
+// display - Connection to the X server.
+// context - The context whos attributes we are querying.
+// attribute - The X atom of the attribute to be queried
+// value - The returned attribute value
+//
+// Returns:
+// Status
+// Notes:
+// For i810 we support these Attributes:
+// XV_COLORKEY: The colorkey value, initialized from the Xv value at
+// context creation time.
+// XV_BRIGHTNESS
+// XV_CONTRAST
+// XV_SATURATION
+***************************************************************************/
+_X_EXPORT Status XvMCGetAttribute(Display *display, XvMCContext *context,
+ Atom attribute, int *value) {
+ i810XvMCContext *pI810XvMC;
+
+ if(display == NULL) {
+ return BadValue;
+ }
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = context->privData;
+ if(pI810XvMC == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(value == NULL) {
+ return BadValue;
+ }
+
+ if(attribute == pI810XvMC->xv_colorkey) {
+ *value = pI810XvMC->colorkey;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_brightness) {
+ *value = pI810XvMC->brightness;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_saturation) {
+ *value = pI810XvMC->saturation;
+ return Success;
+ }
+ if(attribute == pI810XvMC->xv_contrast) {
+ *value = pI810XvMC->contrast;
+ return Success;
+ }
+ return BadValue;
+}
+
+
+
+
diff --git a/src/legacy/i810/xvmc/I810XvMC.h b/src/legacy/i810/xvmc/I810XvMC.h
new file mode 100644
index 00000000..9e311473
--- /dev/null
+++ b/src/legacy/i810/xvmc/I810XvMC.h
@@ -0,0 +1,366 @@
+/***************************************************************************
+
+Copyright 2001 Intel Corporation. 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 INTEL, 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.
+
+**************************************************************************/
+
+/***************************************************************************
+ * libI810XvMC.h: MC Driver i810 includes
+ *
+ * Authors:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ *
+ *
+ ***************************************************************************/
+
+
+#ifndef I810XVMC_H
+#define I810XVMC_H
+
+/* #define XVMC_DEBUG(x) do {x; }while(0); */
+#define XVMC_DEBUG(x)
+
+#include <stdint.h>
+#include "xf86drm.h"
+#include "../i810_common.h"
+#include <X11/Xlibint.h>
+
+
+/***************************************************************************
+// i810OverlayRec: Structure that is used to reference the overlay
+// register memory. A i810OverlayRecPtr is set to the address of the
+// allocated overlay registers.
+***************************************************************************/
+typedef struct _i810OverlayRec {
+ unsigned int OBUF_0Y;
+ unsigned int OBUF_1Y;
+ unsigned int OBUF_0U;
+ unsigned int OBUF_0V;
+ unsigned int OBUF_1U;
+ unsigned int OBUF_1V;
+ unsigned int OV0STRIDE;
+ unsigned int YRGB_VPH;
+ unsigned int UV_VPH;
+ unsigned int HORZ_PH;
+ unsigned int INIT_PH;
+ unsigned int DWINPOS;
+ unsigned int DWINSZ;
+ unsigned int SWID;
+ unsigned int SWIDQW;
+ unsigned int SHEIGHT;
+ unsigned int YRGBSCALE;
+ unsigned int UVSCALE;
+ unsigned int OV0CLRC0;
+ unsigned int OV0CLRC1;
+ unsigned int DCLRKV;
+ unsigned int DCLRKM;
+ unsigned int SCLRKVH;
+ unsigned int SCLRKVL;
+ unsigned int SCLRKM;
+ unsigned int OV0CONF;
+ unsigned int OV0CMD;
+} i810OverlayRec, *i810OverlayRecPtr;
+
+
+/***************************************************************************
+// i810XvMCDrmMap: Holds the data about the DRM maps
+***************************************************************************/
+typedef struct _i810XvMCDrmMap {
+ drm_handle_t offset;
+ drmAddress address;
+ unsigned int size;
+} i810XvMCDrmMap, *i810XvMCDrmMapPtr;
+
+/***************************************************************************
+// i810XvMCContext: Private Context data referenced via the privData
+// pointer in the XvMCContext structure.
+***************************************************************************/
+typedef struct _i810XvMCContext {
+ int fd; /* File descriptor for /dev/dri */
+ i810XvMCDrmMap overlay;
+ i810XvMCDrmMap surfaces;
+ drmBufMapPtr dmabufs; /* Data structure to hold available dma buffers */
+ drm_context_t drmcontext;
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned short ref;
+ unsigned short current;
+ int lock; /* Lightweight lock to avoid locking twice */
+ char busIdString[10]; /* PCI:0:1:0 or PCI:0:2:0 */
+ i810OverlayRecPtr oregs;
+ unsigned int dual_prime; /* Flag to identify when dual prime is in use. */
+ unsigned int fb_base;
+ Atom xv_colorkey;
+ Atom xv_brightness;
+ Atom xv_contrast;
+ Atom xv_saturation;
+ int brightness;
+ int saturation;
+ int contrast;
+ int colorkey;
+} i810XvMCContext;
+
+/***************************************************************************
+// i810XvMCSurface: Private data structure for each XvMCSurface. This
+// structure is referenced by the privData pointer in the XvMCSurface
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSurface {
+ unsigned int pitch;
+ unsigned int dbi1y; /* Destination buffer info command word 1 for Y */
+ unsigned int dbi1u; /* Destination buffer info command word 1 for U */
+ unsigned int dbi1v; /* Destination buffer info command word 1 for V */
+ unsigned int dbv1; /* Destination buffer variables command word 1 */
+ unsigned int mi1y; /* Map Info command word 1 (Minus bit 28) for Y */
+ unsigned int mi1u; /* Map Info command word 1 (Minus bit 28) for U */
+ unsigned int mi1v; /* Map Info command word 1 (Minus bit 28) for V */
+ unsigned int mi2y; /* Map info command word 2 for y */
+ unsigned int mi2u; /* Map info command word 2 for y */
+ unsigned int mi2v; /* Map info command word 2 for y */
+ unsigned int mi3y; /* Map info command word 3 */
+ unsigned int mi3u; /* Map info command word 3 */
+ unsigned int mi3v; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned int second_field; /* Flags a surface that is only half done */
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[3];
+ i810XvMCContext *privContext;
+} i810XvMCSurface;
+
+/***************************************************************************
+// i810XvMCSubpicture: Private data structure for each XvMCSubpicture. This
+// structure is referenced by the privData pointer in the XvMCSubpicture
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSubpicture {
+ unsigned int pitch;
+ unsigned int dbi1; /* Destination buffer info command word 1 */
+ unsigned int dbv1; /* Destination buffer variables command word */
+ unsigned int mi1; /* Map Info command word 1 (Minus bit 28) */
+ unsigned int mi2; /* Map info command word 2 */
+ unsigned int mi3; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[1];
+ unsigned char palette[3][16];
+ i810XvMCContext *privContext;
+} i810XvMCSubpicture;
+
+typedef struct _Box {
+ int x1,y1,x2,y2;
+} Box, *BoxPtr;
+
+/***************************************************************************
+// drm_i810_overlay_t: Structure returned by overlay info ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_overlay_t {
+ unsigned int offset;
+ unsigned int physical;
+} drm_i810_overlay_t;
+
+/***************************************************************************
+// drm_i810_dma_t: Structure used by dma allocation ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
+/***************************************************************************
+// drm_i810_mc_t: Structure used by mc dispatch ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_mc {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int num_blocks; /* number of GFXBlocks */
+ int *length; /* List of lengths for GFXBlocks */
+ unsigned int last_render; /* Last render request */
+} drm_i810_mc_t;
+
+/* Subpicture fourcc */
+#define FOURCC_IA44 0x34344149
+
+/* Static Parameters */
+#define I810_XVMC_MAXWIDTH 720
+#define I810_XVMC_MAXHEIGHT 576
+#define I810_DEFAULT16_COLORKEY 31
+#define I810_DMA_BUF_NR 256
+
+/* COMMANDS */
+#define CMD_FLUSH ((4<<23) | 0x1)
+#define BOOLEAN_ENA_1 ((3<<29) | (3<<24) | (3<<2))
+#define BOOLEAN_ENA_2 ((3<<29) | (4<<24) | (3<<16) | (1<<3) | (1<<2))
+#define DEST_BUFFER_INFO (0x15<<23)
+#define DEST_BUFFER_VAR ((0x3<<29) | (0x1d<<24) | (0x85<<16))
+#define DRAWING_RECT_INFO ((3<<29) | (0x1d<<24) | (0x80<<16) | 3)
+#define GFXBLOCK ((0x3<<29) | (0x1e<<24))
+#define CMD_MAP_INFO ((0x3<<29) | (0x1d<<24) | 0x2)
+#define MAP_PALETTE_LOAD ((3<<29) | (0x1d<<24) | (0x82<<16) | 0xff)
+#define VERTEX_FORMAT ((3<<29) | (0x5<<24))
+#define SRC_DEST_BLEND_MONO ((3<<29) | (8<<24))
+
+/* Bit Patterns */
+
+/*
+ * OV0CMD - Overlay Command Register
+ */
+#define VERTICAL_CHROMINANCE_FILTER 0x70000000
+#define VC_SCALING_OFF 0x00000000
+#define VC_LINE_REPLICATION 0x10000000
+#define VC_UP_INTERPOLATION 0x20000000
+#define VC_PIXEL_DROPPING 0x50000000
+#define VC_DOWN_INTERPOLATION 0x60000000
+#define VERTICAL_LUMINANCE_FILTER 0x0E000000
+#define VL_SCALING_OFF 0x00000000
+#define VL_LINE_REPLICATION 0x02000000
+#define VL_UP_INTERPOLATION 0x04000000
+#define VL_PIXEL_DROPPING 0x0A000000
+#define VL_DOWN_INTERPOLATION 0x0C000000
+#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000
+#define HC_SCALING_OFF 0x00000000
+#define HC_LINE_REPLICATION 0x00400000
+#define HC_UP_INTERPOLATION 0x00800000
+#define HC_PIXEL_DROPPING 0x01400000
+#define HC_DOWN_INTERPOLATION 0x01800000
+#define HORIZONTAL_LUMINANCE_FILTER 0x00380000
+#define HL_SCALING_OFF 0x00000000
+#define HL_LINE_REPLICATION 0x00080000
+#define HL_UP_INTERPOLATION 0x00100000
+#define HL_PIXEL_DROPPING 0x00280000
+#define HL_DOWN_INTERPOLATION 0x00300000
+
+#define Y_ADJUST 0x00010000
+#define OV_BYTE_ORDER 0x0000C000
+#define UV_SWAP 0x00004000
+#define Y_SWAP 0x00008000
+#define Y_AND_UV_SWAP 0x0000C000
+#define SOURCE_FORMAT 0x00003C00
+#define RGB_555 0x00000800
+#define RGB_565 0x00000C00
+#define YUV_422 0x00002000
+#define YUV_411 0x00002400
+#define YUV_420 0x00003000
+#define YUV_410 0x00003800
+#define VERTICAL_PHASE_BOTH 0x00000020
+#define FLIP_TYPE_FIELD 0x00000020
+#define FLIP_TYPE_FRAME 0x00000000
+#define BUFFER_AND_FIELD 0x00000006
+#define BUFFER0_FIELD0 0x00000000
+#define BUFFER0_FIELD1 0x00000002
+#define BUFFER1_FIELD0 0x00000004
+#define BUFFER1_FIELD1 0x00000006
+#define OVERLAY_ENABLE 0x00000001
+
+/*
+ * DOV0STA - Display/Overlay 0 Status Register
+ */
+#define DOV0STA 0x30008
+#define OV0ADD 0x30000
+#define MINUV_SCALE 0x1
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+/* Locking Macros lightweight lock used to prevent relocking */
+#define I810_LOCK(c,f) \
+ if(!c->lock) { \
+ drmGetLock(c->fd, c->drmcontext, f); \
+ } \
+ c->lock++;
+
+#define I810_UNLOCK(c) \
+ c->lock--; \
+ if(!c->lock) { \
+ drmUnlock(c->fd, c->drmcontext); \
+ }
+
+/*
+ Block until the passed in value (n) is the active
+ buffer on the overlay.
+*/
+#define BLOCK_OVERLAY(c,n) \
+ do { \
+ int temp,i=0; \
+ while(i < 100000) { \
+ temp = GET_FSTATUS(c); \
+ if(((temp & (1<<20))>>20) == n) { \
+ break; \
+ } \
+ usleep(10); \
+ } \
+ if(i == 100000) { \
+ printf("Overlay Lockup.\n"); \
+ return BadAlloc; \
+ } \
+ }while(0);
+
+#define OVERLAY_INFO(c,i) drmCommandRead(c->fd, DRM_I810_OV0INFO, &i, sizeof(i))
+#define OVERLAY_FLIP(c) drmCommandNone(c->fd, DRM_I810_OV0FLIP)
+#define GET_FSTATUS(c) drmCommandNone(c->fd, DRM_I810_FSTATUS)
+#define I810_MC(c,mc) drmCommandWrite(c->fd, DRM_I810_MC, &mc, sizeof(mc))
+#define GET_RSTATUS(c) drmCommandNone(c->fd, DRM_I810_RSTATUS)
+#define GET_BUFFER(c,dma) drmCommandWriteRead(c->fd, DRM_I810_GETBUF, &dma, sizeof(drmI810DMA))
+#define FLUSH(c) drmCommandNone(c->fd, DRM_I810_FLUSH)
+
+/*
+ Definitions for temporary wire protocol hooks to be replaced
+ when a HW independent libXvMC is created.
+*/
+extern Status _xvmc_create_context(Display *dpy, XvMCContext *context,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context);
+
+extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context,
+ XvMCSurface *surface, int *priv_count,
+ uint **priv_data);
+
+extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface);
+
+extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_subpicture(Display *dpy,
+ XvMCSubpicture *subpicture);
+
+/*
+ Prototypes
+*/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC);
+void i810_free_privContext(i810XvMCContext *pI810XvMC);
+void dp(unsigned int *address, unsigned int i);
+
+#endif
diff --git a/src/legacy/i810/xvmc/Makefile.am b/src/legacy/i810/xvmc/Makefile.am
new file mode 100644
index 00000000..69add1e4
--- /dev/null
+++ b/src/legacy/i810/xvmc/Makefile.am
@@ -0,0 +1,11 @@
+if XVMC
+lib_LTLIBRARIES=libI810XvMC.la
+endif
+
+libI810XvMC_la_SOURCES = I810XvMC.c \
+ I810XvMC.h
+
+libI810XvMC_la_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
+ -DTRUE=1 -DFALSE=0
+libI810XvMC_la_LDFLAGS = -version-number 1:0:0
+libI810XvMC_la_LIBADD = @DRI_LIBS@ @DRM_LIBS@ @XVMCLIB_LIBS@