summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit3ad0d9a73bc0a4f3edb858d5f3a7c36827b7a429 (patch)
treec6951ce1ecfa6a5887b0b7b69f338268bf123786
downloadxorg-driver-xf86-video-intel-3ad0d9a73bc0a4f3edb858d5f3a7c36827b7a429.tar.gz
Initial revision
-rw-r--r--README.sgml127
-rw-r--r--man/i810.man74
-rw-r--r--src/common.h327
-rw-r--r--src/i810.h324
-rw-r--r--src/i810_accel.c662
-rw-r--r--src/i810_common.h188
-rw-r--r--src/i810_cursor.c202
-rw-r--r--src/i810_dga.c293
-rw-r--r--src/i810_dri.c1220
-rw-r--r--src/i810_dri.h122
-rw-r--r--src/i810_driver.c2397
-rw-r--r--src/i810_hwmc.c417
-rw-r--r--src/i810_io.c144
-rw-r--r--src/i810_memory.c399
-rw-r--r--src/i810_reg.h992
-rw-r--r--src/i810_video.c1399
-rw-r--r--src/i810_wmark.c321
-rw-r--r--src/i830.h395
-rw-r--r--src/i830_accel.c770
-rw-r--r--src/i830_common.h288
-rw-r--r--src/i830_cursor.c281
-rw-r--r--src/i830_dga.c293
-rw-r--r--src/i830_dri.c1664
-rw-r--r--src/i830_dri.h146
-rw-r--r--src/i830_driver.c3586
-rw-r--r--src/i830_memory.c1458
-rw-r--r--src/i830_video.c1840
-rw-r--r--src/xvmc/I810XvMC.c4507
-rw-r--r--src/xvmc/I810XvMC.h469
29 files changed, 25305 insertions, 0 deletions
diff --git a/README.sgml b/README.sgml
new file mode 100644
index 00000000..575989f6
--- /dev/null
+++ b/README.sgml
@@ -0,0 +1,127 @@
+<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN" [
+<!ENTITY % defs SYSTEM "defs.ent"> %defs;
+]>
+
+<article>
+<title>Information for i810 Users
+<author>Precision Insight, Inc.
+<date>3 March 2000
+<ident>
+$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/i810.sgml,v 1.3 2001/04/04 01:34:18 dawes Exp $
+</ident>
+<toc>
+
+<sect>Supported Hardware
+<p>
+<itemize>
+ <item>Intel 810 motherboards:
+ <itemize>
+ <item>i810,
+ <item>i810-dc100,
+ <item>i810e
+ <item>i815
+ </itemize>
+</itemize>
+
+
+<sect>Features
+<p>
+<itemize>
+ <item>Full support for 8, 15, 16, and 24 bit pixel depths.
+ <item>Hardware cursor support to reduce sprite flicker.
+ <item>Hardware accelerated 2D drawing engine support for 8, 15, 16 and
+ 24 bit pixel depths.
+ <item>Support for high resolution video modes up to 1600x1200.
+ <item>Fully programmable clock supported.
+ <item>Robust text mode restore for VT switching.
+</itemize>
+
+
+<sect>Technical Notes
+<p>
+<itemize>
+ <item>Hardware acceleration is not possible when using the framebuffer
+ in 32 bit per pixel format, and this mode is not supported by
+ this driver.
+ <item>Interlace modes cannot be supported.
+ <item>This driver currently only works for Linux/ix86 and recent versions
+ of FreeBSD. It requires the agpgart kernel support, which is
+ included in Linux kernels 2.3.42 and higher, and FreeBSD 4.1
+ and higher.
+</itemize>
+
+
+<sect>Reported Working Video Cards
+<p>
+<itemize>
+ <item>Intel evaluation hardware - i810, i810-dc100, i810e and i815.
+ <item>Tyan Tomcat Motherboard.
+ <item>HappyPC set-top box.
+</itemize>
+
+
+<sect>Configuration
+<p>
+The driver auto-detects all device information necessary to
+initialize the card. The only lines you need in the "Device"
+section of your XF86Config file are:
+<verb>
+ Section "Device"
+ Identifier "Intel i810"
+ Driver "i810"
+ EndSection
+</verb>
+or let <tt>xf86config</tt> do this for you.
+
+However, if you have problems with auto-detection, you can specify:
+<itemize>
+ <item>DacSpeed - in MHz
+ <item>MemBase - physical address of the linear framebuffer
+ <item>IOBase - physical address of the memory mapped IO registers
+</itemize>
+
+In order to use most resolutions, it is necessary to install the
+'agpgart.o' module. You will probably have to compile the module yourself
+(see the notes in the module).
+
+Note: the i810 driver detects whether your motherboard has display cache
+video memory. This memory is has reduced bandwidth compared to normal
+system memory, and isn't used by the server. The main function of this
+memory is for ancillary buffers (eg. z buffer) in a forthcoming 3d
+capable server.
+
+
+<sect>Driver Options
+<p>
+<itemize>
+ <item>"NoAccel" - Turn off hardware acceleration
+ <item>"SWCursor" - Request a software cursor (hardware is default)
+ <item>"Dac6Bit" - Force the use of a 6 Bit Dac (8 Bit is the default)
+</itemize>
+
+<sect>Known Limitations
+<p>
+<itemize>
+ <item>No 3D support in this release.
+ <item>Running two X servers on different VTs is not supported at this time.
+</itemize>
+
+
+<sect>Author
+<p>
+<itemize>
+ <item>Keith Whitwell
+</itemize>
+
+This driver was donated to The XFree86 Project by:
+<verb>
+ Precision Insight, Inc.
+ Cedar Park, TX
+ USA
+</verb>
+
+<htmlurl name="http://www.precisioninsight.com"
+ url="http://www.precisioninsight.com">
+
+
+</article>
diff --git a/man/i810.man b/man/i810.man
new file mode 100644
index 00000000..b10e6421
--- /dev/null
+++ b/man/i810.man
@@ -0,0 +1,74 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man,v 1.3 2003/02/17 19:19:02 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH I810 __drivermansuffix__ __vendorversion__
+.SH NAME
+i810 \- Intel 8xx integrated graphics chipsets
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qi810\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B i810
+is an XFree86 driver for Intel integrated graphics chipsets.
+The driver supports depths 8, 15, 16 and 24. All visual types are
+supported in depth 8, other depths only support TrueColor. The driver
+supports hardware accelerated 3D via the Direct Rendering Infrastructure (DRI),
+but only in depth 16 for the i810/i815 and depths 16 and 24 for later chipsets.
+.SH SUPPORTED HARDWARE
+.B i810
+supports the i810, i810-DC100, i810e, i815, 830M, 845G, 852GM, 855GM,
+and 865G chipsets.
+
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.PP
+The Intel 8xx family of integrated graphics chipsets has a unified memory
+architecture and uses system memory for video ram. By default 8 Megabytes
+of system memory are used for graphics. For the 830M and later, the
+default is 8 Megabytes when DRI is not enabled and 32 Megabytes with
+DRI is enabled. This amount may be changed with the
+.B VideoRam
+entry in the config file
+.B "Device"
+section. It may be set to any reasonable value up to 64MB for older
+chipsets or 128MB for newer chipets. Note that increasing this value
+will reduce the amount of system memory available for other applications.
+.PP
+The following driver
+.B Options
+are supported
+.TP
+.BI "Option \*qNoAccel\*q \*q" boolean \*q
+Disable or enable acceleration. Default: acceleration is enabled.
+.TP
+.BI "Option \*qSWCursor\*q \*q" boolean \*q
+Disable or enable software cursor. Default: software cursor is disable
+and a hardware cursor is used.
+.TP
+.BI "Option \*qColorKey\*q \*q" integer \*q
+This sets the default pixel value for the YUV video overlay key.
+Default: undefined.
+.TP
+.BI "Option \*qCacheLines\*q \*q" integer \*q
+This allows the user to change the amount of graphics memory used for
+2D acceleration and video. Decreasing this amount leaves more for 3D
+textures. Increasing it can improve 2D performance at the expense of
+3D performance.
+Default: 256 to 768 depending on the resolution and depth.
+
+
+
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek,
+Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu. 830M and 845G
+support reworked for XFree86 4.3 by David Dawes and Keith Whitwell.
+852GM, 855GM, and 865G support added by David Dawes and Keith Whitwell.
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 00000000..5e71cad8
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,327 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/common.h,v 1.6 2003/02/06 04:18:04 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ */
+
+#ifndef _INTEL_COMMON_H_
+#define _INTEL_COMMON_H_
+
+#ifdef __GNUC__
+#define PFX __FILE__,__LINE__,__FUNCTION__
+#define FUNCTION_NAME __FUNCTION__
+#else
+#define PFX __FILE__,__LINE__,""
+#define FUNCTION_NAME ""
+#endif
+
+#ifdef I830DEBUG
+#define MARKER() ErrorF("\n### %s:%d: >>> %s <<< ###\n\n", \
+ __FILE__, __LINE__,__FUNCTION__)
+#define DPRINTF I830DPRINTF_stub
+#else /* #ifdef I830DEBUG */
+#define MARKER()
+/* this is a real ugly hack to get the compiler to optimize the debugging statements into oblivion */
+#define DPRINTF if(0) I830DPRINTF_stub
+#endif /* #ifdef I830DEBUG */
+
+#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
+
+/* I830 hooks for the I810 driver setup/probe. */
+extern const OptionInfoRec *I830BIOSAvailableOptions(int chipid, int busid);
+extern void I830InitpScrn(ScrnInfoPtr pScrn);
+
+/* Symbol lists shared by the i810 and i830 parts. */
+extern const char *I810vgahwSymbols[];
+extern const char *I810ramdacSymbols[];
+extern const char *I810int10Symbols[];
+extern const char *I810vbeSymbols[];
+extern const char *I810ddcSymbols[];
+extern const char *I810fbSymbols[];
+extern const char *I810xaaSymbols[];
+extern const char *I810shadowSymbols[];
+
+extern void I830DPRINTF_stub(const char *filename, int line,
+ const char *function, const char *fmt, ...);
+
+#ifdef _I830_H_
+#define PrintErrorState I830PrintErrorState
+#define WaitRingFunc I830WaitLpRing
+#define RecPtr pI830
+#else
+#define PrintErrorState I810PrintErrorState
+#define WaitRingFunc I810WaitLpRing
+#define RecPtr pI810
+#endif
+
+/* BIOS debug macro */
+#define xf86ExecX86int10_wrapper(pInt, pScrn) do { \
+ if (I810_DEBUG & DEBUG_VERBOSE_BIOS) { \
+ ErrorF("\n\n\n\nExecuting (ax == 0x%x) BIOS call\n", pInt->ax); \
+ ErrorF("Checking Error state before execution\n"); \
+ PrintErrorState(pScrn); \
+ } \
+ xf86ExecX86int10(pInt); \
+ if(I810_DEBUG & DEBUG_VERBOSE_BIOS) { \
+ ErrorF("Checking Error state after execution\n"); \
+ usleep(50000); \
+ PrintErrorState(pScrn); \
+ } \
+} while (0)
+
+#define OUT_RING(n) do { \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF( "OUT_RING %x: %x, (mask %x)\n", outring, n, ringmask); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+ outring += 4; \
+ outring &= ringmask; \
+} while (0)
+
+#if 1
+#define ADVANCE_LP_RING() do { \
+ RecPtr->LpRing.tail = outring; \
+ if (outring & 0x07) \
+ ErrorF("ADVANCE_LP_RING: " \
+ "outring (0x%x) isn't on a QWord boundary", outring); \
+ OUTREG(LP_RING + RING_TAIL, outring); \
+} while (0)
+#else
+#define ADVANCE_LP_RING() { \
+ RecPtr->LpRing.tail = outring; \
+ if (outring & 0x07) \
+ ErrorF("ADVANCE_LP_RING: " \
+ "outring (0x%x) isn't on a QWord boundary", outring); \
+ ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \
+ OUTREG(LP_RING + RING_TAIL, outring); \
+ ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \
+}
+#endif
+
+/*
+ * 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)
+
+/*
+ * This is for debugging a potential problem writing the tail pointer
+ * close to the end of the ring buffer.
+ */
+#ifndef AVOID_TAIL_END
+#define AVOID_TAIL_END 0
+#endif
+#ifndef AVOID_SIZE
+#define AVOID_SIZE 64
+#endif
+
+#if AVOID_TAIL_END
+
+#define BEGIN_LP_RING(n) \
+ unsigned int outring, ringmask; \
+ volatile unsigned char *virt; \
+ unsigned 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 ((RecPtr->LpRing.tail > RecPtr->LpRing.tail_mask - AVOID_SIZE) || \
+ (RecPtr->LpRing.tail + needed) > \
+ RecPtr->LpRing.tail_mask - AVOID_SIZE) { \
+ needed += RecPtr->LpRing.tail_mask + 1 - RecPtr->LpRing.tail; \
+ ErrorF("BEGIN_LP_RING: skipping last 64 bytes of " \
+ "ring (%d vs %d)\n", needed, (n) * 4); \
+ } \
+ if (RecPtr->LpRing.space < needed) \
+ WaitRingFunc(pScrn, needed, 0); \
+ RecPtr->LpRing.space -= needed; \
+ outring = RecPtr->LpRing.tail; \
+ ringmask = RecPtr->LpRing.tail_mask; \
+ virt = RecPtr->LpRing.virtual_start; \
+ while (needed > (n) * 4) { \
+ ErrorF("BEGIN_LP_RING: putting MI_NOOP at 0x%x (remaining %d)\n", \
+ outring, needed - (n) * 4); \
+ OUT_RING(MI_NOOP); \
+ needed -= 4; \
+ } \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME);
+
+#else /* AVOID_TAIL_END */
+
+#define BEGIN_LP_RING(n) \
+ unsigned int outring, ringmask; \
+ volatile unsigned char *virt; \
+ unsigned 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 (RecPtr->LpRing.space < needed) \
+ WaitRingFunc(pScrn, needed, 0); \
+ RecPtr->LpRing.space -= needed; \
+ outring = RecPtr->LpRing.tail; \
+ ringmask = RecPtr->LpRing.tail_mask; \
+ virt = RecPtr->LpRing.virtual_start; \
+ if (I810_DEBUG & DEBUG_VERBOSE_RING) \
+ ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME);
+
+#endif /* AVOID_TAIL_END */
+
+
+/* Memory mapped register access macros */
+#define INREG8(addr) *(volatile CARD8 *)(RecPtr->MMIOBase + (addr))
+#define INREG16(addr) *(volatile CARD16 *)(RecPtr->MMIOBase + (addr))
+#define INREG(addr) *(volatile CARD32 *)(RecPtr->MMIOBase + (addr))
+
+#define OUTREG8(addr, val) do { \
+ *(volatile CARD8 *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG8(0x%x, 0x%x) in %s\n", addr, val, FUNCTION_NAME); \
+ } \
+} while (0)
+
+#define OUTREG16(addr, val) do { \
+ *(volatile CARD16 *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG16(0x%x, 0x%x) in %s\n", addr, val, FUNCTION_NAME); \
+ } \
+} while (0)
+
+#define OUTREG(addr, val) do { \
+ *(volatile CARD32 *)(RecPtr->MMIOBase + (addr)) = (val); \
+ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \
+ ErrorF("OUTREG(0x%x, 0x%x) in %s\n", addr, 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
+
+#ifndef PCI_CHIP_I810
+#define PCI_CHIP_I810 0x7121
+#define PCI_CHIP_I810_DC100 0x7123
+#define PCI_CHIP_I810_E 0x7125
+#define PCI_CHIP_I815 0x1132
+#define PCI_CHIP_I810_BRIDGE 0x7120
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_E_BRIDGE 0x7124
+#define PCI_CHIP_I815_BRIDGE 0x1130
+#endif
+
+#ifndef PCI_CHIP_I855_GM
+#define PCI_CHIP_I855_GM 0x3582
+#define PCI_CHIP_I855_GM_BRIDGE 0x3580
+#endif
+
+#ifndef PCI_CHIP_I865_G
+#define PCI_CHIP_I865_G 0x2572
+#define PCI_CHIP_I865_G_BRIDGE 0x2570
+#endif
+
+#define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 || \
+ pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
+ pI810->PciInfo->chipType == PCI_CHIP_I810_E)
+#define IS_I815(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I815)
+#define IS_I830(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I830_M)
+#define IS_845G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_845_G)
+#define IS_I85X(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM)
+#define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G)
+
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810))
+
+#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 OVERLAY_SIZE GTT_PAGE_SIZE
+
+/* Use a 64x64 HW cursor */
+#define I810_CURSOR_X 64
+#define I810_CURSOR_Y I810_CURSOR_X
+
+/* XXX Need to check if these are reasonable. */
+#define MAX_DISPLAY_PITCH 2048
+#define MAX_DISPLAY_HEIGHT 2048
+
+#define PIPE_NAME(n) ('A' + (n))
+
+#endif /* _INTEL_COMMON_H_ */
diff --git a/src/i810.h b/src/i810.h
new file mode 100644
index 00000000..128b659a
--- /dev/null
+++ b/src/i810.h
@@ -0,0 +1,324 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h,v 1.38 2003/02/26 04:19:36 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ */
+
+#ifndef _I810_H_
+#define _I810_H_
+
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "i810_reg.h"
+#include "xaa.h"
+#include "xf86Cursor.h"
+#include "xf86xv.h"
+#include "xf86int10.h"
+#include "vbe.h"
+#include "vgaHW.h"
+
+#ifdef XF86DRI
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#include "i810_dri.h"
+#endif
+
+#include "common.h"
+
+#define I810_VERSION 4000
+#define I810_NAME "I810"
+#define I810_DRIVER_NAME "i810"
+#define I810_MAJOR_VERSION 1
+#define I810_MINOR_VERSION 3
+#define I810_PATCHLEVEL 0
+
+
+/* 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,
+ CARD8 index, CARD8 value);
+typedef CARD8(*I810ReadIndexedByteFunc)(I810Ptr pI810, IOADDRESS addr,
+ CARD8 index);
+typedef void (*I810WriteByteFunc)(I810Ptr pI810, IOADDRESS addr, CARD8 value);
+typedef CARD8(*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;
+
+ int CursorOffset;
+ unsigned long CursorPhysical;
+ unsigned long CursorStart;
+ unsigned long OverlayPhysical;
+ unsigned long OverlayStart;
+ int colorKey;
+ 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;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+
+ I810RingBuffer LpRing;
+ unsigned int BR[20];
+
+ int LmFreqSel;
+
+ int VramKey;
+ unsigned long VramOffset;
+ int DcacheKey;
+ unsigned long DcacheOffset;
+ int HwcursKey;
+ unsigned long HwcursOffset;
+
+ 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 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 xvmcHandle;
+ unsigned long sysmemHandle;
+ Bool agpAcquired;
+ drmHandle buffer_map;
+ drmHandle ring_map;
+ drmHandle overlay_map;
+ drmHandle mc_map;
+ drmHandle xvmcContext;
+#endif
+ Bool agpAcquired2d;
+
+ XF86VideoAdaptorPtr adaptor;
+ OptionInfoPtr Options;
+
+ int configured_device;
+
+ Bool showCache;
+ Bool noAccel;
+} I810Rec;
+
+#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
+
+#define I810_SELECT_FRONT 0
+#define I810_SELECT_BACK 1
+#define I810_SELECT_DEPTH 2
+
+extern Bool I810DRIScreenInit(ScreenPtr pScreen);
+extern void I810DRICloseScreen(ScreenPtr pScreen);
+extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen);
+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/i810_accel.c b/src/i810_accel.c
new file mode 100644
index 00000000..17c24b37
--- /dev/null
+++ b/src/i810_accel.c
@@ -0,0 +1,662 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c,v 1.17 2002/11/25 14:04:59 eich Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86_ansic.h"
+#include "xf86.h"
+
+#include "i810.h"
+
+static unsigned int i810Rop[16] = {
+ 0x00, /* GXclear */
+ 0x88, /* GXand */
+ 0x44, /* GXandReverse */
+ 0xCC, /* GXcopy */
+ 0x22, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x66, /* GXxor */
+ 0xEE, /* GXor */
+ 0x11, /* GXnor */
+ 0x99, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xDD, /* GXorReverse */
+ 0x33, /* GXcopyInvert */
+ 0xBB, /* GXorInverted */
+ 0x77, /* GXnand */
+ 0xFF /* GXset */
+};
+
+static unsigned int i810PatternRop[16] = {
+ 0x00, /* GXclear */
+ 0xA0, /* GXand */
+ 0x50, /* GXandReverse */
+ 0xF0, /* GXcopy */
+ 0x0A, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x5A, /* GXxor */
+ 0xFA, /* GXor */
+ 0x05, /* GXnor */
+ 0xA5, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xF5, /* GXorReverse */
+ 0x0F, /* GXcopyInvert */
+ 0xAF, /* GXorInverted */
+ 0x5F, /* GXnand */
+ 0xFF /* GXset */
+};
+
+static void 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;
+ /* There is a bit blt bug in 24 bpp. This is a problem, but
+ * at least without the pixmap cache we can pass the test suite */
+ if (pScrn->depth != 24)
+ 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 |
+ (i810PatternRop[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] |= i810Rop[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.
+ */
+ if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3
+ && (y2 - y1) >= 0 && (x2 - x1) <= (w + 4) && (w > 4))
+ w = 4;
+ 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;
+ 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] |= i810PatternRop[rop] << 16;
+ if (bg == -1)
+ pI810->BR[13] |= BR13_MONO_TRANSPCY;
+}
+
+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] |= i810Rop[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;
+
+ 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/i810_common.h b/src/i810_common.h
new file mode 100644
index 00000000..2a2e21a5
--- /dev/null
+++ b/src/i810_common.h
@@ -0,0 +1,188 @@
+/* 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>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_common.h,v 1.1 2002/09/11 00:29:31 dawes Exp $
+ *
+ */
+
+/* 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_
+
+#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
+
+#endif
+
+typedef struct {
+ enum {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02
+ } 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/i810_cursor.c b/src/i810_cursor.c
new file mode 100644
index 00000000..26023f3f
--- /dev/null
+++ b/src/i810_cursor.c
@@ -0,0 +1,202 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_cursor.c,v 1.7 2002/10/30 12:52:17 alanh Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86fbman.h"
+
+#include "i810.h"
+
+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;
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+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);
+ CARD8 *pcurs = (CARD8 *) (pI810->FbBase + pI810->CursorStart);
+ int x, y;
+
+ 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));
+
+ OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical);
+}
+
+static void
+I810ShowCursor(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ unsigned char tmp;
+
+ 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);
+
+ 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/i810_dga.c b/src/i810_dga.c
new file mode 100644
index 00000000..0abac2bf
--- /dev/null
+++ b/src/i810_dga.c
@@ -0,0 +1,293 @@
+/*
+ * 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>
+ */
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dga.c,v 1.6 2003/02/26 04:19:36 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "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;
+
+ MARKER();
+
+ pMode = firstMode = pScrn->modes;
+
+ while (pMode) {
+
+ newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
+
+ if (!newmodes) {
+ xfree(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+
+ currentMode = modes + num;
+ num++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if (!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);
+
+ MARKER();
+
+ if (!pMode) { /* restore the original mode */
+ DPRINTF(PFX, "Restoring original mode (from DGA mode)\n");
+ 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) {
+ DPRINTF(PFX, "Setting DGA mode\n");
+ 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);
+
+ MARKER();
+
+ return pI810->DGAViewportStatus;
+}
+
+static void
+I810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ MARKER();
+
+ 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);
+
+ MARKER();
+
+ 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);
+
+ MARKER();
+
+ 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);
+
+ MARKER();
+
+ 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)
+{
+
+ MARKER();
+
+ /* 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);
+
+ MARKER();
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char *)pI810->LinearAddr;
+ *size = pI810->FbMapSize;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ DPRINTF(PFX,
+ " mem == 0x%.8x (pI810->LinearAddr)\n"
+ "size == %lu (pI810->FbMapSize)\n", *mem, *size);
+
+ return TRUE;
+}
diff --git a/src/i810_dri.c b/src/i810_dri.c
new file mode 100644
index 00000000..11ecacf0
--- /dev/null
+++ b/src/i810_dri.c
@@ -0,0 +1,1220 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v 1.33 2002/12/10 01:27:04 dawes Exp $ */
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Priv.h"
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+#include "windowstr.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,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void I810DestroyContext(ScreenPtr pScreen, drmContext 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);
+
+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
+};
+
+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.func = I810_INIT_DMA;
+
+ 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;
+
+ 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 = 0;
+ I810ConfigPrivPtr pI810Configs = 0;
+ I810ConfigPrivPtr *pI810ConfigPtrs = 0;
+ int accum, stencil, db, depth;
+ int i;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 24:
+ case 32:
+ break;
+ case 16:
+ numConfigs = 8;
+
+ pConfigs =
+ (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs);
+ if (!pConfigs)
+ return FALSE;
+
+ pI810Configs =
+ (I810ConfigPrivPtr) xcalloc(sizeof(I810ConfigPrivRec),
+ numConfigs);
+ if (!pI810Configs) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+
+ pI810ConfigPtrs =
+ (I810ConfigPrivPtr *) xcalloc(sizeof(I810ConfigPrivPtr),
+ numConfigs);
+ if (!pI810ConfigPtrs) {
+ xfree(pConfigs);
+ xfree(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].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 = 16;
+ } 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_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ 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;
+ unsigned long agpHandle;
+ unsigned long dcacheHandle;
+ int sysmem_size = 0;
+ int back_size = 0;
+ 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("DRIScreenInit"))
+ 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;
+ }
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d bug version 4.0.x is needed.\n"
+ "[dri] Disabling DRI.\n", major, minor, patch);
+ 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;
+ pDRIInfo->busIdString = xalloc(64);
+
+ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ ((pciConfigPtr) pI810->PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI810->PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI810->PciInfo->thisCard)->funcnum);
+ pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
+ pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
+ pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
+ pDRIInfo->frameBufferPhysicalAddress = 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) xcalloc(sizeof(I810DRIRec), 1))) {
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = 0;
+ 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->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");
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = 0;
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = 0;
+ 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) {
+ 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;
+ }
+ drmFreeVersion(version);
+ }
+ }
+
+ pI810DRI->regsSize = I810_REG_SIZE;
+ if (drmAddMap(pI810->drmSubFD, (drmHandle) pI810->MMIOAddr,
+ pI810DRI->regsSize, DRM_REGISTERS, 0, &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%08lx\n",
+ pI810DRI->regs);
+
+ pI810->backHandle = 0;
+ pI810->zHandle = 0;
+ pI810->cursorHandle = 0;
+ pI810->xvmcHandle = 0;
+ pI810->sysmemHandle = 0;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = 0;
+
+ /* 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;
+
+ /* Dcache - half the speed of normal ram, but has use as a Z buffer
+ * under the DRI.
+ */
+
+ drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, &dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle;
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : %p\n",
+ dcacheHandle);
+
+#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 {
+ back_size = i810_pitches[pitch_idx] * (pScrn->virtualY + 4);
+ back_size = ((back_size + 4096 - 1) / 4096) * 4096;
+ }
+
+ sysmem_size = pScrn->videoRam * 1024;
+ if (dcacheHandle != 0) {
+ 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 = 0;
+ } 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 */
+
+ pI810->SysMem.Start = 0;
+ pI810->SysMem.Size = sysmem_size;
+ pI810->SysMem.End = sysmem_size;
+ tom = sysmem_size;
+
+ pI810->SavedSysMem = pI810->SysMem;
+
+ if (dcacheHandle != 0) {
+ 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 = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: no dcache memory found\n");
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+ pI810->backHandle = agpHandle;
+
+ if (agpHandle != 0) {
+ 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 == 0) {
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+ pI810->zHandle = agpHandle;
+
+ if (agpHandle != 0) {
+ 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, &agpHandle);
+ if (agpHandle == 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAlloc failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pI810->sysmemHandle = agpHandle;
+
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) != 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpBind failed\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, &agpHandle);
+ pI810->xvmcHandle = agpHandle;
+
+ if (agpHandle != 0) {
+ 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, &agpHandle);
+ pI810->cursorHandle = agpHandle;
+
+ if (agpHandle != 0) {
+ 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;
+ }
+
+ /* 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, (drmHandle) pI810->BackBuffer.Start,
+ pI810->BackBuffer.Size, DRM_AGP, 0,
+ &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, (drmHandle) pI810->DepthBuffer.Start,
+ pI810->DepthBuffer.Size, DRM_AGP, 0,
+ &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, (drmHandle) pI810->BufferMem.Start,
+ pI810->BufferMem.Size, DRM_AGP, 0, &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, (drmHandle) pI810->LpRing.mem.Start,
+ pI810->LpRing.mem.Size, DRM_AGP, 0, &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, (drmHandle) pI810->TexMem.Start,
+ pI810->TexMem.Size, DRM_AGP, 0, &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,
+ ((pciConfigPtr) pI810->
+ PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI810->
+ PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI810->
+ PciInfo->thisCard)->funcnum);
+ 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 = pI810->PciInfo->chipType;
+ 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);
+
+ I810CleanupDma(pScrn);
+
+ if (pI810->dcacheHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
+ if (pI810->backHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->backHandle);
+ if (pI810->zHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->zHandle);
+ if (pI810->cursorHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
+ if (pI810->xvmcHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
+ if (pI810->sysmemHandle)
+ drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
+
+ if (pI810->agpAcquired == TRUE)
+ drmAgpRelease(pI810->drmSubFD);
+
+ pI810->backHandle = 0;
+ pI810->zHandle = 0;
+ pI810->cursorHandle = 0;
+ pI810->xvmcHandle = 0;
+ pI810->sysmemHandle = 0;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = 0;
+
+ DRICloseScreen(pScreen);
+
+ if (pI810->pDRIInfo) {
+ if (pI810->pDRIInfo->devPrivate) {
+ xfree(pI810->pDRIInfo->devPrivate);
+ pI810->pDRIInfo->devPrivate = 0;
+ }
+ DRIDestroyInfoRec(pI810->pDRIInfo);
+ pI810->pDRIInfo = 0;
+ }
+ if (pI810->pVisualConfigs)
+ xfree(pI810->pVisualConfigs);
+ if (pI810->pVisualConfigsPriv)
+ xfree(pI810->pVisualConfigsPriv);
+}
+
+static Bool
+I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+I810DestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+I810DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
+
+ memset(sPriv, 0, sizeof(sPriv));
+ 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);
+ 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;
+ int xdir, ydir;
+
+ int screenwidth = pScrn->virtualX;
+ int screenheight = pScrn->virtualY;
+
+ BoxPtr pbox = REGION_RECTS(prgnSrc);
+ int nbox = REGION_NUM_RECTS(prgnSrc);
+
+ BoxPtr pboxNew1 = 0;
+ BoxPtr pboxNew2 = 0;
+ DDXPointPtr pptNew1 = 0;
+ 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) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
+ if (!pboxNew1)
+ return;
+ pptNew1 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
+ if (!pptNew1) {
+ DEALLOCATE_LOCAL(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) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
+ pptNew2 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
+ if (!pboxNew2 || !pptNew2) {
+ if (pptNew2)
+ DEALLOCATE_LOCAL(pptNew2);
+ if (pboxNew2)
+ DEALLOCATE_LOCAL(pboxNew2);
+ if (pboxNew1) {
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(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) {
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ }
+ if (pboxNew1) {
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+ }
+
+ pI810->AccelInfoRec->NeedToSync = TRUE;
+}
diff --git a/src/i810_dri.h b/src/i810_dri.h
new file mode 100644
index 00000000..cf0532cb
--- /dev/null
+++ b/src/i810_dri.h
@@ -0,0 +1,122 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.h,v 1.10 2002/12/10 01:27:04 dawes Exp $ */
+
+#ifndef _I810_DRI_
+#define _I810_DRI_
+
+#include "xf86drm.h"
+#include "i810_common.h"
+
+#define I810_MAX_DRAWABLES 256
+
+typedef struct {
+ drmHandle regs;
+ drmSize regsSize;
+ drmAddress regsMap;
+
+ drmSize backbufferSize;
+ drmHandle backbuffer;
+
+ drmSize depthbufferSize;
+ drmHandle depthbuffer;
+
+ drmHandle textures;
+ int textureSize;
+
+ drmHandle 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;
+ XF86DRIClipRectRec 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.
+ */
+ I810TexRegionRec 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;
+
+} 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/i810_driver.c b/src/i810_driver.c
new file mode 100644
index 00000000..746e186f
--- /dev/null
+++ b/src/i810_driver.c
@@ -0,0 +1,2397 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c,v 1.80 2003/02/26 04:19:36 dawes Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+/*
+ * This server does not support these XFree86 4.0 features yet
+ * shadowFb (if requested or acceleration is off)
+ * Overlay planes
+ * DGA
+ */
+
+/*
+ * These are X and server generic header files.
+ */
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+#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 "Xv.h"
+#include "vbe.h"
+
+#include "i810.h"
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+/* Required Functions: */
+
+static void I810Identify(int flags);
+static Bool I810Probe(DriverPtr drv, int flags);
+#ifndef I830_ONLY
+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 int I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool
+ verbose, int flags);
+#endif /* I830_ONLY */
+
+
+DriverRec I810 = {
+ I810_VERSION,
+ I810_DRIVER_NAME,
+ I810Identify,
+ I810Probe,
+ I810AvailableOptions,
+ NULL,
+ 0
+};
+
+/* *INDENT-OFF* */
+/* Chipsets */
+static SymTabRec I810Chipsets[] = {
+#ifndef I830_ONLY
+ {PCI_CHIP_I810, "i810"},
+ {PCI_CHIP_I810_DC100, "i810-dc100"},
+ {PCI_CHIP_I810_E, "i810e"},
+ {PCI_CHIP_I815, "i815"},
+#endif
+ {PCI_CHIP_I830_M, "i830M"},
+ {PCI_CHIP_845_G, "845G"},
+ {PCI_CHIP_I855_GM, "852GM/855GM"},
+ {PCI_CHIP_I865_G, "865G"},
+ {-1, NULL}
+};
+
+static PciChipsets I810PciChipsets[] = {
+#ifndef I830_ONLY
+ {PCI_CHIP_I810, PCI_CHIP_I810, RES_SHARED_VGA},
+ {PCI_CHIP_I810_DC100, PCI_CHIP_I810_DC100, RES_SHARED_VGA},
+ {PCI_CHIP_I810_E, PCI_CHIP_I810_E, RES_SHARED_VGA},
+ {PCI_CHIP_I815, PCI_CHIP_I815, RES_SHARED_VGA},
+#endif
+ {PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA},
+ {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA},
+ {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA},
+ {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA},
+ {-1, -1, RES_UNDEFINED }
+};
+
+#ifndef I830_ONLY
+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
+} 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},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+/* *INDENT-ON* */
+#endif
+
+const char *I810vgahwSymbols[] = {
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWInit",
+ "vgaHWLock",
+ "vgaHWMapMem",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSaveScreen",
+ "vgaHWSetMmioFuncs",
+ "vgaHWUnlock",
+ "vgaHWUnmapMem",
+ NULL
+};
+
+const char *I810fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+const char *I810vbeSymbols[] = {
+ "VBEFreeModeInfo",
+ "VBEFreeVBEInfo",
+ "VBEGetModeInfo",
+ "VBEGetModePool",
+ "VBEGetVBEInfo",
+ "VBEGetVBEMode",
+ "VBEInit",
+ "VBEPrintModes",
+ "VBESaveRestore",
+ "VBESetDisplayStart",
+ "VBESetGetDACPaletteFormat",
+ "VBESetGetLogicalScanlineLength",
+ "VBESetGetPaletteData",
+ "VBESetModeNames",
+ "VBESetModeParameters",
+ "VBESetVBEMode",
+ "VBEValidateModes",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+#ifdef XFree86LOADER
+static const char *vbeOptionalSymbols[] = {
+ "VBEDPMSSet",
+ "VBEGetPixelClock",
+ NULL
+};
+#endif
+
+const char *I810ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86SetDDCproperties",
+ NULL
+};
+
+const char *I810int10Symbols[] = {
+ "xf86ExecX86int10",
+ "xf86InitInt10",
+ "xf86Int10AllocPages",
+ "xf86int10Addr",
+ NULL
+};
+
+const char *I810xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAFillSolidRects",
+ "XAAInit",
+ NULL
+};
+
+const char *I810ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+#ifndef I830_ONLY
+#ifdef XFree86LOADER
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAgpAcquire",
+ "drmAgpAlloc",
+ "drmAgpBind",
+ "drmAgpEnable",
+ "drmAgpFree",
+ "drmAgpRelease",
+ "drmAuthMagic",
+ "drmCommandWrite",
+ "drmCreateContext",
+ "drmCtlInstHandler",
+ "drmDestroyContext",
+ "drmFreeVersion",
+ "drmGetInterruptFromBusID",
+ "drmGetLibVersion",
+ "drmGetVersion",
+ NULL
+};
+
+
+static const char *driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ NULL
+};
+
+#endif
+#endif
+
+#ifdef XF86DRI
+const char *I810shadowSymbols[] = {
+ "shadowInit",
+ "shadowSetup",
+ "shadowAdd",
+ NULL
+};
+#endif
+
+#endif /* I830_ONLY */
+
+#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
+
+#ifndef I830_ONLY
+#ifdef XF86DRI
+static int i810_pitches[] = {
+ 512,
+ 1024,
+ 2048,
+ 4096,
+ 0
+};
+#endif
+#endif
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(i810Setup);
+
+static XF86ModuleVersionInfo i810VersRec = {
+ "i810",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ I810_MAJOR_VERSION, I810_MINOR_VERSION, I810_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, 0 };
+
+static pointer
+i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = 0;
+
+ /* This module should be loaded only once, but check to be sure.
+ */
+ if (!setupDone) {
+ setupDone = 1;
+ xf86AddDriver(&I810, module, 0);
+
+ /*
+ * Tell the loader about symbols from other modules that this module
+ * might refer to.
+ */
+ LoaderRefSymLists(I810vgahwSymbols,
+ I810fbSymbols, I810xaaSymbols, I810ramdacSymbols,
+#ifdef XF86DRI
+ drmSymbols,
+ driSymbols,
+ I810shadowSymbols,
+#endif
+ I810vbeSymbols, vbeOptionalSymbols,
+ I810ddcSymbols, I810int10Symbols, NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer) 1;
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif
+
+#ifndef I830_ONLY
+/*
+ * 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;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = 0;
+}
+#endif
+
+/*
+ * I810Identify --
+ *
+ * Returns the string name for the driver based on the chipset. In this
+ * case it will always be an I810, so we can return a static string.
+ *
+ */
+static void
+I810Identify(int flags)
+{
+ xf86PrintChipsets(I810_NAME, "Driver for Intel Integrated Graphics Chipsets",
+ I810Chipsets);
+}
+
+const OptionInfoRec *
+I810AvailableOptions(int chipid, int busid)
+{
+#ifndef I830_ONLY
+ const OptionInfoRec *pOptions;
+
+ if ((pOptions = I830BIOSAvailableOptions(chipid, busid)))
+ return pOptions;
+ return I810Options;
+#else
+ return I830BIOSAvailableOptions(chipid, busid);
+#endif
+}
+
+/*
+ * I810Probe --
+ *
+ * Look through the PCI bus to find cards that are I810 boards.
+ * Setup the dispatch table for the rest of the driver functions.
+ *
+ */
+static Bool
+I810Probe(DriverPtr drv, int flags)
+{
+ int i, numUsed, numDevSections, *usedChips;
+ GDevPtr *devSections;
+ Bool foundScreen = FALSE;
+ pciVideoPtr *VideoInfo;
+ pciVideoPtr *ppPci;
+ PciChipsets *id;
+
+ /*
+ * Find the config file Device sections that match this
+ * driver, and return if there are none.
+ */
+ if ((numDevSections =
+ xf86MatchDevice(I810_DRIVER_NAME, &devSections)) <= 0) {
+ return FALSE;
+ }
+
+ /*
+ * This probing is just checking the PCI data the server already
+ * collected.
+ */
+ if (!(VideoInfo = xf86GetPciVideoInfo()))
+ return FALSE;
+
+ /*
+ * Mobile platforms may have both function 0 and 1 active, but they
+ * are handled as a single entity. To make sure that the function 1
+ * entity isn't assigned to a screen, check for and claim it here
+ * first.
+ *
+ * XXX If function 1's resources are ever needed, they'll need to be
+ * added to the screen and marked active.
+ */
+ for (ppPci = VideoInfo; ppPci != NULL && *ppPci != NULL; ppPci++) {
+ if ((*ppPci)->vendor == PCI_VENDOR_INTEL &&
+ (*ppPci)->func == 1) {
+ for (id = I810PciChipsets; id->PCIid != -1; id++) {
+ if (id->PCIid == (*ppPci)->chipType) {
+ /* Claim slot */
+ if (xf86CheckPciSlot((*ppPci)->bus, (*ppPci)->device,
+ (*ppPci)->func)) {
+ xf86ClaimPciSlot((*ppPci)->bus, (*ppPci)->device,
+ (*ppPci)->func, drv, id->PCIid,
+ NULL, FALSE);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* Look for Intel i8xx devices. */
+ numUsed = xf86MatchPciInstances(I810_NAME, PCI_VENDOR_INTEL,
+ I810Chipsets, I810PciChipsets,
+ devSections, numDevSections,
+ drv, &usedChips);
+
+ if (flags & PROBE_DETECT) {
+ if (numUsed > 0)
+ foundScreen = TRUE;
+ } else {
+ for (i = 0; i < numUsed; i++) {
+ ScrnInfoPtr pScrn = NULL;
+
+ /* Allocate new ScrnInfoRec and claim the slot */
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ I810PciChipsets, 0, 0, 0, 0, 0))) {
+ EntityInfoPtr pEnt;
+
+ pEnt = xf86GetEntityInfo(usedChips[i]);
+
+ pScrn->driverVersion = I810_VERSION;
+ pScrn->driverName = I810_DRIVER_NAME;
+ pScrn->name = I810_NAME;
+ pScrn->Probe = I810Probe;
+ foundScreen = TRUE;
+ switch (pEnt->chipset) {
+ case PCI_CHIP_I830_M:
+ case PCI_CHIP_845_G:
+ case PCI_CHIP_I855_GM:
+ case PCI_CHIP_I865_G:
+ I830InitpScrn(pScrn);
+ break;
+#ifndef I830_ONLY
+ default:
+ pScrn->PreInit = I810PreInit;
+ pScrn->ScreenInit = I810ScreenInit;
+ pScrn->SwitchMode = I810SwitchMode;
+ pScrn->AdjustFrame = I810AdjustFrame;
+ pScrn->EnterVT = I810EnterVT;
+ pScrn->LeaveVT = I810LeaveVT;
+ pScrn->FreeScreen = I810FreeScreen;
+ pScrn->ValidMode = I810ValidMode;
+ break;
+#endif
+ }
+ }
+ }
+ }
+
+ xfree(usedChips);
+ xfree(devSections);
+
+ return foundScreen;
+}
+
+#ifndef I830_ONLY
+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))) {
+ xf86LoaderReqSymLists(I810vbeSymbols, NULL);
+ 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;
+
+ 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;
+
+ xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
+
+ /* Allocate a vgaHWRec */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+ hwp = VGAHWPTR(pScrn);
+ pI810->ioBase = hwp->PIOOffset;
+
+ pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
+ pI810->PciTag = pciTag(pI810->PciInfo->bus, pI810->PciInfo->device,
+ pI810->PciInfo->func);
+
+ if (xf86RegisterResources(pI810->pEnt->index, 0, ResNone))
+ return FALSE;
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, flags24)) {
+ return FALSE;
+ } else {
+ switch (pScrn->depth) {
+ case 8:
+ case 15:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by 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 = xalloc(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;
+ }
+
+ /* Get DDC info from monitor */
+ /* after xf86ProcessOptions,
+ * because it is controlled by options [no]vbe and [no]ddc
+ */
+ pScrn->monitor->DDC = I810DoDDC(pScrn, pI810->pEnt->index);
+
+ /* We have to use PIO to probe, because we haven't mapped yet */
+ I810SetPIOAccess(pI810);
+
+ /*
+ * 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(I810Chipsets,
+ 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(I810Chipsets,
+ pI810->PciInfo->chipType);
+ }
+ 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");
+
+ if (pI810->pEnt->device->MemBase != 0) {
+ pI810->LinearAddr = pI810->pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else {
+ if (pI810->PciInfo->memBase[1] != 0) {
+ pI810->LinearAddr = pI810->PciInfo->memBase[0] & 0xFF000000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid FB address in PCI config space\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pI810->LinearAddr);
+
+ if (pI810->pEnt->device->IOBase != 0) {
+ pI810->MMIOAddr = pI810->pEnt->device->IOBase;
+ from = X_CONFIG;
+ } else {
+ if (pI810->PciInfo->memBase[1]) {
+ pI810->MMIOAddr = pI810->PciInfo->memBase[1] & 0xFFF80000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid MMIO address in PCI config space\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ 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.
+ */
+ {
+ unsigned long whtcfg_pamr_drp = pciReadLong(pI810->PciTag,
+ 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).
+ */
+ pScrn->videoRam = 8192;
+ from = X_DEFAULT;
+ if (pI810->pEnt->device->videoRam) {
+ pScrn->videoRam = pI810->pEnt->device->videoRam;
+ from = X_CONFIG;
+ }
+
+ mem = I810CheckAvailableMemory(pScrn);
+ 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 */
+ {
+ PCITAG bridge;
+ long smram_miscc;
+
+ bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+ smram_miscc = pciReadLong(bridge, 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];
+ from = X_CONFIG;
+ } 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;
+ clockRanges->minClock = 12000; /* !!! What's the min clock? !!! */
+ 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;
+ }
+ xf86LoaderReqSymLists(I810fbSymbols, NULL);
+
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
+ pI810->noAccel = TRUE;
+
+ if (!pI810->noAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810xaaSymbols, NULL);
+ }
+
+ if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ /* We won't be using the VGA access after the probe */
+ I810SetMMIOAccess(pI810);
+ xf86SetOperatingState(resVgaIo, pI810->pEnt->index, ResUnusedOpr);
+ xf86SetOperatingState(resVgaMem, pI810->pEnt->index, ResDisableOpr);
+
+ return TRUE;
+}
+
+static Bool
+I810MapMMIO(ScrnInfoPtr pScrn)
+{
+ int mmioFlags;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+#if !defined(__alpha__)
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
+#else
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
+#endif
+
+ pI810->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+ pI810->PciTag,
+ pI810->MMIOAddr, I810_REG_SIZE);
+ if (!pI810->MMIOBase)
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+I810MapMem(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ unsigned i;
+
+ for (i = 2; i < pI810->FbMapSize; i <<= 1) ;
+ pI810->FbMapSize = i;
+
+ if (!I810MapMMIO(pScrn))
+ return FALSE;
+
+ pI810->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pI810->PciTag,
+ pI810->LinearAddr, pI810->FbMapSize);
+ if (!pI810->FbBase)
+ return FALSE;
+
+ pI810->LpRing.virtual_start = pI810->FbBase + pI810->LpRing.mem.Start;
+
+ return TRUE;
+}
+
+static void
+I810UnmapMMIO(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->MMIOBase,
+ I810_REG_SIZE);
+ pI810->MMIOBase = 0;
+}
+
+static Bool
+I810UnmapMem(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI810->FbBase,
+ pI810->FbMapSize);
+ pI810->FbBase = 0;
+ 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",
+ INREG(PGETBL_CTL), INREG(PGE_ERR));
+
+ ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
+
+ ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+ INREG(LP_RING + RING_TAIL),
+ INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+ INREG(LP_RING + RING_LEN), 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", INREG(MEMMODE), 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;
+ CARD32 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 */
+ {
+ CARD32 LCD_TV_Control = INREG(LCD_TV_C);
+
+ if(!(LCD_TV_Control & LCD_TV_ENABLE)
+ || (LCD_TV_Control & LCD_TV_VGAMOD)) {
+ OUTREG(LCD_TV_OVRACT,
+ (i810Reg->OverlayActiveEnd << 16)
+ | i810Reg->OverlayActiveStart);
+ }
+ }
+
+ /* 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, f_best;
+ 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);
+ 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;
+ f_best = f_out;
+ 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 %.1lf 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 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;
+ 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;
+ vgaRegPtr pVga;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+
+ vgaHWUnlock(hwp);
+
+ if (!vgaHWInit(pScrn, mode))
+ return FALSE;
+ /*
+ * 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 = &VGAHWPTR(pScrn)->ModeReg;
+ 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;
+
+ 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)
+{
+ I810Ptr pI810;
+ vgaHWPtr hwp;
+ int i, j, index;
+ unsigned char r, g, b;
+
+ pI810 = I810PTR(pScrn);
+ 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)
+{
+ I810Ptr pI810;
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ pI810 = I810PTR(pScrn);
+ 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)
+{
+ I810Ptr pI810;
+ vgaHWPtr hwp;
+ int i, index;
+ unsigned char r, g, b;
+
+ pI810 = I810PTR(pScrn);
+ 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;
+ } else
+ DPRINTF(PFX,
+ "Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
+ pI810->FrontBuffer.Start,
+ pI810->FrontBuffer.Size / 1024, pI810->FrontBuffer.Size);
+
+ memset(&(pI810->LpRing), 0, sizeof(I810RingBuffer));
+ if (I810AllocLow(&(pI810->LpRing.mem), &(pI810->SysMem), 16 * 4096)) {
+ DPRINTF(PFX,
+ "Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
+ pI810->LpRing.mem.Start,
+ pI810->LpRing.mem.Size / 1024, pI810->LpRing.mem.Size);
+
+ 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)) {
+ DPRINTF(PFX,
+ "Scratch memory at 0x%.8x (%luk, %lu bytes)\n",
+ pI810->Scratch.Start,
+ pI810->Scratch.Size / 1024, pI810->Scratch.Size);
+
+ 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;
+ MessageType driFrom = X_DEFAULT;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI810 = I810PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ 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 cfbScreenInit
+ * is called. cfbScreenInit will eventually call into the drivers
+ * InitGLXVisuals call back.
+ */
+
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE) ||
+ !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE)) {
+ pI810->directRenderingEnabled = FALSE;
+ driFrom = X_CONFIG;
+ } else {
+ 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, 0, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+#ifdef XF86DRI
+ if (pI810->LpRing.mem.Start == 0 && pI810->directRenderingEnabled) {
+ pI810->directRenderingEnabled = FALSE;
+ driFrom = X_PROBED;
+ I810DRICloseScreen(pScreen);
+ }
+
+ if (!pI810->directRenderingEnabled) {
+ pI810->DoneFrontAlloc = FALSE;
+ if (!I810AllocateGARTMemory(pScrn))
+ return FALSE;
+ if (!I810AllocateFront(pScrn))
+ return FALSE;
+ }
+#endif
+
+ I810DGAInit(pScreen);
+
+ 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");
+ }
+ }
+ }
+
+ 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, 0,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ } else {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, 0,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+ } else {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, 0,
+ CMAP_PALETTED_TRUECOLOR |
+ CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+
+ xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0);
+
+ I810InitVideo(pScreen);
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ /* Now that mi, cfb, 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, driFrom, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, driFrom, "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 (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF("I810SwitchMode %p %x\n", mode, flags);
+
+ 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 (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;
+
+ 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) {
+ 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) {
+ xfree(pI810->ScanlineColorExpandBuffers);
+ pI810->ScanlineColorExpandBuffers = 0;
+ }
+
+ if (infoPtr) {
+ if (infoPtr->ScanlineColorExpandBuffers)
+ xfree(infoPtr->ScanlineColorExpandBuffers);
+ XAADestroyInfoRec(infoPtr);
+ pI810->AccelInfoRec = 0;
+ }
+
+ if (pI810->CursorInfoRec) {
+ xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
+ pI810->CursorInfoRec = 0;
+ }
+
+ /* 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);
+
+ 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 int
+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);
+}
+#endif /* I830_ONLY */
diff --git a/src/i810_hwmc.c b/src/i810_hwmc.c
new file mode 100644
index 00000000..525ad361
--- /dev/null
+++ b/src/i810_hwmc.c
@@ -0,0 +1,417 @@
+/***************************************************************************
+
+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>
+ *
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_hwmc.c,v 1.4 2002/09/11 00:29:32 dawes Exp $ */
+
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i810.h"
+#include "i810_dri.h"
+
+#include "xf86xv.h"
+#include "xf86xvmc.h"
+#include "Xv.h"
+#include "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 {
+ drmContext 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, (drmHandle)pI810->CursorStart,
+ 4096, DRM_AGP, 0, &pI810->overlay_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
+ return;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->MC.Start,
+ pI810->MC.Size, DRM_AGP, 0, &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 *) xcalloc (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(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
+ return BadAlloc;
+ }
+
+ /* Context Already in use! */
+ if(pI810->xvmcContext) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
+ return BadAlloc;
+ }
+
+ *priv = xcalloc(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(X_ERROR, pScrn->scrnIndex,
+ "I810XvMCCreateContext: Unable to create DRMContext!\n");
+ xfree(*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 *)xcalloc(2,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "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 *)xcalloc(1,sizeof(long));
+
+ if(!*priv) {
+ xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+ "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/i810_io.c b/src/i810_io.c
new file mode 100644
index 00000000..de947dde
--- /dev/null
+++ b/src/i810_io.c
@@ -0,0 +1,144 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_io.c,v 1.5 2002/09/11 00:29:32 dawes Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_ansic.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 CARD8 *)(pI810->MMIOBase + (p))
+#define moutb(p,v) *(volatile CARD8 *)(pI810->MMIOBase + (p)) = (v)
+
+static void
+I810WriteControlPIO(I810Ptr pI810, IOADDRESS addr, CARD8 index, CARD8 val)
+{
+ addr += pI810->ioBase;
+ outb(addr, index);
+ outb(addr + 1, val);
+}
+
+static CARD8
+I810ReadControlPIO(I810Ptr pI810, IOADDRESS addr, CARD8 index)
+{
+ addr += pI810->ioBase;
+ outb(addr, index);
+ return inb(addr + 1);
+}
+
+static void
+I810WriteStandardPIO(I810Ptr pI810, IOADDRESS addr, CARD8 val)
+{
+ outb(pI810->ioBase + addr, val);
+}
+
+static CARD8
+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, CARD8 index, CARD8 val)
+{
+ moutb(addr, index);
+ moutb(addr + 1, val);
+}
+
+static CARD8
+I810ReadControlMMIO(I810Ptr pI810, IOADDRESS addr, CARD8 index)
+{
+ moutb(addr, index);
+ return minb(addr + 1);
+}
+
+static void
+I810WriteStandardMMIO(I810Ptr pI810, IOADDRESS addr, CARD8 val)
+{
+ moutb(addr, val);
+}
+
+static CARD8
+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/i810_memory.c b/src/i810_memory.c
new file mode 100644
index 00000000..5efa23a9
--- /dev/null
+++ b/src/i810_memory.c
@@ -0,0 +1,399 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_memory.c,v 1.27 2002/12/10 01:27:05 dawes Exp $ */
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+
+#include "i810.h"
+#include "i810_reg.h"
+
+int
+I810AllocLow(I810MemRange * result, I810MemRange * pool, int size)
+{
+ if (size > 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 > 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;
+
+ /*
+ * 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 %d 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 %d 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 %d bytes for HW cursor failed\n", size);
+ pI810->HwcursKey = -1;
+ } else {
+ pI810->CursorPhysical = physical;
+ pI810->CursorStart = 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;
+ CARD32 val;
+ CARD32 fence_mask = 0;
+
+ if (nr < 0 || nr > 7) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex, "%s - fence %d out of range\n",
+ "I810SetTiledMemory", nr);
+ return;
+ }
+
+ i810Reg->Fence[nr] = 0;
+
+ fence_mask = ~FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "%s %d: start (%x) is not 512k aligned\n",
+ "I810SetTiledMemory", nr, start);
+ return;
+ }
+
+ if (start % size) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "%s %d: start (%x) is not size (%x) aligned\n",
+ "I810SetTiledMemory", nr, start, size);
+ return;
+ }
+
+ if (pitch & 127) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "%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(X_WARNING, pScrn->scrnIndex,
+ "%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(X_WARNING, pScrn->scrnIndex,
+ "%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;
+
+ 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 (!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/i810_reg.h b/src/i810_reg.h
new file mode 100644
index 00000000..c935982a
--- /dev/null
+++ b/src/i810_reg.h
@@ -0,0 +1,992 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_reg.h,v 1.13 2003/02/06 04:18:04 dawes Exp $ */
+/**************************************************************************
+
+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>
+ *
+ * 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
+
+/* 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
+
+/* 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
+
+
+/* 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
+
+
+
+/* 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
+
+#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 INST_DONE 0x2090
+#define INST_PS 0x20c4
+
+#define MEMMODE 0x20dc
+
+
+/* Instruction parser error register. p279
+ */
+#define IPEIR 0x2088
+#define IPEHR 0x208C
+
+
+/* General error reporting regs, p296
+ */
+#define EIR 0x20B0
+#define EMR 0x20B4
+#define ESR 0x20B8
+#define IP_ERR 0x0001
+#define ERROR_RESERVED 0xffc6
+
+
+/* Interrupt Control Registers
+ * - new bits for i810
+ * - new register hwstam (mask)
+ */
+#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 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 FENCE_PITCH_MASK 0x00000070
+#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
+
+/* Register containing pge table error results, p276
+ */
+#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
+
+
+
+/* Page table entries loaded via mmio region, p323
+ */
+#define PTE_BASE 0x10000
+#define PTE_ADDR_MASK 0x3FFFF000
+#define PTE_TYPE_MASK 0x00000006
+#define PTE_LOCAL 0x00000002
+#define PTE_MAIN_UNCACHED 0x00000000
+#define PTE_MAIN_CACHED 0x00000006
+#define PTE_VALID_MASK 0x00000001
+#define PTE_VALID 0x00000001
+
+
+/* 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 0x00FFFFF8
+#define I830_RING_START_MASK 0xFFFFF000
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x000FF000
+#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_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 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 DPLL_A 0x06014
+#define DPLL_B 0x06018
+#define FPA0 0x06040
+#define FPA1 0x06044
+
+#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 DVOA_SRCDIM 0x61124
+#define DVOB_SRCDIM 0x61144
+#define DVOC_SRCDIM 0x61164
+
+#define LVDS 0x61180
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (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)
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE (1<<31)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_GAMMA (1<<24)
+#define PIPEBCONF_PALETTE 0
+
+#define DSPACNTR 0x70180
+#define DSPBCNTR 0x71180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#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)
+#define DISPPLANE_32BPP (0x7<<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
+#define DISPPLANE_SEL_PIPE_B (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)
+
+#define DSPABASE 0x70184
+#define DSPASTRIDE 0x70188
+
+#define DSPBBASE 0x71184
+#define DSPBADDR DSPBBASE
+#define DSPBSTRIDE 0x71188
+
+/* 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 (0x7 << 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 I85X_CAPID 0x44
+#define I85X_VARIANT_MASK 0x7
+#define I85X_VARIANT_SHIFT 5
+#define I855_GME 0x0
+#define I855_GM 0x4
+#define I852_GME 0x2
+#define I852_GM 0x5
+
+/* 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_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 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_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)
+
+/* 3d state */
+#define STATE3D_FOG_MODE ((3<<29)|(0x1d<<24)|(0x89<<16)|2)
+#define FOG_MODE_VERTEX (1<<31)
+#define STATE3D_MAP_COORD_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8c<<16))
+#define DISABLE_TEX_TRANSFORM (1<<28)
+#define TEXTURE_SET(x) (x<<29)
+#define STATE3D_RASTERIZATION_RULES ((3<<29)|(0x07<<24))
+#define POINT_RASTER_ENABLE (1<<15)
+#define POINT_RASTER_OGL (1<<13)
+#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_OVERLAY_FLIP (1<<16)
+
+/* Flush */
+#define MI_FLUSH (0x04<<23)
+#define MI_WRITE_DIRTY_STATE (1<<4)
+#define MI_END_SCENE (1<<3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2)
+#define MI_INVALIDATE_MAP_CACHE (1<<0)
+
+/* 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))
+
+/* 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,
+ Tv2Index,
+ Dfp2Index,
+ UnknownIndex,
+ Unknown2Index,
+ NumDisplayTypes,
+ NumKnownDisplayTypes = UnknownIndex
+} 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_TV2_ACTIVE (1 << Tv2Index)
+#define PIPE_DFP2_ACTIVE (1 << Dfp2Index)
+#define PIPE_UNKNOWN_ACTIVE ((1 << UnknownIndex) | \
+ (1 << Unknown2Index))
+
+#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
+
+#endif /* _I810_REG_H */
diff --git a/src/i810_video.c b/src/i810_video.c
new file mode 100644
index 00000000..9ae60bc5
--- /dev/null
+++ b/src/i810_video.c
@@ -0,0 +1,1399 @@
+/***************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_video.c,v 1.22 2002/09/11 00:29:32 dawes Exp $ */
+
+/*
+ * 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>
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i810.h"
+#include "xf86xv.h"
+#include "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);
+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 */
+ xalloc((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)
+ xfree(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 4
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+/* *INDENT-ON* */
+
+typedef struct {
+ CARD32 OBUF_0Y;
+ CARD32 OBUF_1Y;
+ CARD32 OBUF_0U;
+ CARD32 OBUF_0V;
+ CARD32 OBUF_1U;
+ CARD32 OBUF_1V;
+ CARD32 OV0STRIDE;
+ CARD32 YRGB_VPH;
+ CARD32 UV_VPH;
+ CARD32 HORZ_PH;
+ CARD32 INIT_PH;
+ CARD32 DWINPOS;
+ CARD32 DWINSZ;
+ CARD32 SWID;
+ CARD32 SWIDQW;
+ CARD32 SHEIGHT;
+ CARD32 YRGBSCALE;
+ CARD32 UVSCALE;
+ CARD32 OV0CLRC0;
+ CARD32 OV0CLRC1;
+ CARD32 DCLRKV;
+ CARD32 DCLRKM;
+ CARD32 SCLRKVH;
+ CARD32 SCLRKVL;
+ CARD32 SCLRKM;
+ CARD32 OV0CONF;
+ CARD32 OV0CMD;
+} I810OverlayRegRec, *I810OverlayRegPtr;
+
+typedef struct {
+ CARD32 YBuf0offset;
+ CARD32 UBuf0offset;
+ CARD32 VBuf0offset;
+
+ CARD32 YBuf1offset;
+ CARD32 UBuf1offset;
+ CARD32 VBuf1offset;
+
+ unsigned char currentBuf;
+
+ int brightness;
+ int contrast;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ CARD32 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 = xcalloc(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_INIT(pScreen, &pPriv->clip, NullBox, 0);
+
+ 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;
+}
+
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+
+/* 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 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
+){
+ 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(pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ 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(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+
+ 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, fbpitch, 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;
+ fbpitch = bpp * pScrn->displayWidth;
+ size = ((pitch * h) + bpp - 1) / bpp;
+
+ if(!(linear = I810AllocateMemory(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if(!(surface->pitches = xalloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+
+ pPriv->linear = linear;
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = linear->offset * 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);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+I810GetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value
+){
+ return I810GetPortAttribute(pScrn, attribute, value, 0);
+}
+
+static int
+I810SetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value
+){
+ return I810SetPortAttribute(pScrn, attribute, value, 0);
+}
+
+
+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);
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ 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);
+
+ XAAFillSolidRects(pScrn, pI810Priv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if(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 = xalloc(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/i810_wmark.c b/src/i810_wmark.c
new file mode 100644
index 00000000..9a6bdd34
--- /dev/null
+++ b/src/i810_wmark.c
@@ -0,0 +1,321 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_wmark.c,v 1.8 2002/10/30 12:52:18 alanh Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "xf86.h"
+#include "i810.h"
+
+struct wm_info {
+ double freq;
+ unsigned int wm;
+};
+
+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}
+};
+
+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}
+};
+
+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}
+};
+
+struct wm_info i810_wm_32_100[] = {
+ {0, 0x2210b000},
+ {60, 0x22415000}, /* 0x314000 works too */
+ {80, 0x22419000} /* 0x518000 works too */
+};
+
+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}
+};
+
+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}
+};
+
+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/i830.h b/src/i830.h
new file mode 100644
index 00000000..e141931a
--- /dev/null
+++ b/src/i830.h
@@ -0,0 +1,395 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830.h,v 1.7 2003/01/28 22:47:09 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ */
+
+#if 0
+#define I830DEBUG
+#endif
+
+#ifndef REMAP_RESERVED
+#define REMAP_RESERVED 0
+#endif
+
+#ifndef _I830_H_
+#define _I830_H_
+
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "i810_reg.h"
+#include "xaa.h"
+#include "xf86Cursor.h"
+#include "xf86xv.h"
+#include "xf86int10.h"
+#include "vbe.h"
+#include "vgaHW.h"
+
+#ifdef XF86DRI
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#include "i830_dri.h"
+#endif
+
+#include "common.h"
+
+/* I830 Video BIOS support */
+
+/*
+ * The mode handling is based upon the VESA driver written by
+ * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>.
+ */
+
+typedef struct _VESARec {
+ /* SVGA state */
+ pointer state, pstate;
+ int statePage, stateSize, stateMode;
+ CARD32 *savedPal;
+ int savedScanlinePitch;
+ xf86MonPtr monitor;
+ /* Don't try to set the refresh rate for any modes. */
+ Bool useDefaultRefresh;
+} VESARec, *VESAPtr;
+
+
+typedef struct _I830Rec *I830Ptr;
+
+typedef void (*I830WriteIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
+ CARD8 index, CARD8 value);
+typedef CARD8(*I830ReadIndexedByteFunc)(I830Ptr pI830, IOADDRESS addr,
+ CARD8 index);
+typedef void (*I830WriteByteFunc)(I830Ptr pI830, IOADDRESS addr, CARD8 value);
+typedef CARD8(*I830ReadByteFunc)(I830Ptr pI830, IOADDRESS addr);
+
+/* Linear region allocated in framebuffer. */
+typedef struct _I830MemPool *I830MemPoolPtr;
+typedef struct _I830MemRange *I830MemRangePtr;
+typedef struct _I830MemRange {
+ long Start;
+ long End;
+ long Size;
+ unsigned long Physical;
+ unsigned long Offset; /* Offset of AGP-allocated portion */
+ unsigned long Alignment;
+ int Key;
+ I830MemPoolPtr Pool;
+} I830MemRange;
+
+typedef struct _I830MemPool {
+ I830MemRange Total;
+ I830MemRange Free;
+ I830MemRange Fixed;
+ I830MemRange Allocated;
+} I830MemPool;
+
+typedef struct {
+ int tail_mask;
+ I830MemRange mem;
+ unsigned char *virtual_start;
+ int head;
+ int tail;
+ int space;
+} I830RingBuffer;
+
+typedef struct {
+ unsigned int Fence[8];
+} I830RegRec, *I830RegPtr;
+
+typedef struct _I830Rec {
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+ int cpp;
+
+ unsigned int bufferOffset; /* for I830SelectBuffer */
+ BoxRec FbMemBox;
+ int CacheLines;
+
+ /* These are set in PreInit and never changed. */
+ unsigned long FbMapSize;
+ unsigned long TotalVideoRam;
+ I830MemRange StolenMemory; /* pre-allocated memory */
+ unsigned long BIOSMemorySize; /* min stolen pool size */
+
+ /* These change according to what has been allocated. */
+ long FreeMemory;
+ I830MemRange MemoryAperture;
+ I830MemPool StolenPool;
+ unsigned long allocatedMemory;
+
+ /* Regions allocated either from the above pools, or from agpgart. */
+ I830MemRange FrontBuffer;
+ I830MemRange CursorMem;
+ I830RingBuffer LpRing;
+ I830MemRange Scratch;
+
+#if REMAP_RESERVED
+ I830MemRange Dummy;
+#endif
+
+#ifdef I830_XV
+ /* For Xvideo */
+ I830MemRange OverlayMem;
+#endif
+
+#ifdef XF86DRI
+ I830MemRange BackBuffer;
+ I830MemRange DepthBuffer;
+ I830MemRange TexMem;
+ I830MemRange BufferMem;
+ I830MemRange ContextMem;
+ int TexGranularity;
+ int drmMinor;
+ Bool have3DWindows;
+#endif
+
+ Bool NeedRingBufferLow;
+ Bool allowPageFlip;
+
+ int auxPitch;
+ int auxPitchBits;
+
+ Bool CursorNeedsPhysical;
+
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+
+ int Chipset;
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+ IOADDRESS ioBase;
+ EntityInfoPtr pEnt;
+ pciVideoPtr PciInfo;
+ PCITAG PciTag;
+ CARD8 variant;
+
+ unsigned int BR[20];
+
+ int GttBound;
+
+ unsigned char **ScanlineColorExpandBuffers;
+ int NumScanlineColorExpandBuffers;
+ int nextColorExpandBuf;
+
+ I830RegRec SavedReg;
+ I830RegRec ModeReg;
+
+ Bool noAccel;
+ Bool SWCursor;
+ Bool cursorOn;
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ CloseScreenProcPtr CloseScreen;
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+ I830WriteIndexedByteFunc writeControl;
+ I830ReadIndexedByteFunc readControl;
+ I830WriteByteFunc writeStandard;
+ I830ReadByteFunc readStandard;
+
+ Bool XvDisabled; /* Xv disabled in PreInit. */
+ Bool XvEnabled; /* Xv enabled for this generation. */
+
+#ifdef I830_XV
+ int colorKey;
+ XF86VideoAdaptorPtr adaptor;
+ Bool overlayOn;
+#endif
+
+ Bool directRenderingDisabled; /* DRI disabled in PreInit. */
+ Bool directRenderingEnabled; /* DRI enabled this generation. */
+
+#ifdef XF86DRI
+ Bool directRenderingOpen;
+ int LockHeld;
+ DRIInfoPtr pDRIInfo;
+ int drmSubFD;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ I830ConfigPrivPtr pVisualConfigsPriv;
+ drmHandle buffer_map;
+ drmHandle ring_map;
+#endif
+
+ OptionInfoPtr Options;
+
+ /* Stolen memory support */
+ Bool StolenOnly;
+
+ /* Video BIOS support. */
+ vbeInfoPtr pVbe;
+ VbeInfoBlock *vbeInfo;
+ VESAPtr vesa;
+
+ Bool overrideBIOSMemSize;
+ int saveBIOSMemSize;
+ int newBIOSMemSize;
+ Bool useSWF1;
+ int saveSWF1;
+
+ Bool swfSaved;
+ CARD32 saveSWF0;
+ CARD32 saveSWF4;
+
+ /* Use BIOS call 0x5f64 to explicitly enable displays. */
+ Bool enableDisplays;
+ /* Use BIOS call 0x5f05 to set the refresh rate. */
+ Bool useExtendedRefresh;
+
+ int configuredDevices;
+
+ /* These are indexed by the display types */
+ Bool displayAttached[NumDisplayTypes];
+ Bool displayPresent[NumDisplayTypes];
+ BoxRec displaySize[NumDisplayTypes];
+
+ /* [0] is Pipe A, [1] is Pipe B. */
+ int availablePipes;
+ int pipeDevices[MAX_DISPLAY_PIPES];
+ /* [0] is display plane A, [1] is display plane B. */
+ Bool pipeEnabled[MAX_DISPLAY_PIPES];
+ BoxRec pipeDisplaySize[MAX_DISPLAY_PIPES];
+ int planeEnabled[MAX_DISPLAY_PIPES];
+
+ /* Driver phase/state information */
+ Bool starting;
+ Bool closing;
+ Bool suspended;
+
+} I830Rec;
+
+#define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
+#define I830REGPTR(p) (&(I830PTR(p)->ModeReg))
+
+#define I830_SELECT_FRONT 0
+#define I830_SELECT_BACK 1
+#define I830_SELECT_DEPTH 2
+
+/* I830 specific functions */
+extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
+extern void I830SetPIOAccess(I830Ptr pI830);
+extern void I830SetMMIOAccess(I830Ptr pI830);
+extern void I830PrintErrorState(ScrnInfoPtr pScrn);
+extern void I830Sync(ScrnInfoPtr pScrn);
+extern void I830InitHWCursor(ScrnInfoPtr pScrn);
+extern Bool I830CursorInit(ScreenPtr pScreen);
+extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
+extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
+
+extern void I830RefreshRing(ScrnInfoPtr pScrn);
+extern void I830EmitFlush(ScrnInfoPtr pScrn);
+
+extern Bool I830DGAInit(ScreenPtr pScreen);
+
+#ifdef I830_XV
+extern void I830InitVideo(ScreenPtr pScreen);
+extern void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode);
+extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode);
+#endif
+
+#ifdef XF86DRI
+extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
+extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
+extern Bool I830DRIScreenInit(ScreenPtr pScreen);
+extern Bool I830DRIDoMappings(ScreenPtr pScreen);
+extern void I830DRICloseScreen(ScreenPtr pScreen);
+extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen);
+#endif
+extern Bool I830AccelInit(ScreenPtr pScreen);
+extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
+ int ydir, int rop,
+ unsigned int planemask,
+ int trans_color);
+extern void I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
+ int srcY, int dstX, int dstY,
+ int w, int h);
+extern void I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+extern void I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+
+extern void I830ResetAllocations(ScrnInfoPtr pScrn, const int flags);
+extern long I830CheckAvailableMemory(ScrnInfoPtr pScrn);
+extern long I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn);
+extern Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool);
+extern Bool I830FixupOffsets(ScrnInfoPtr pScrn);
+extern Bool I830BindGARTMemory(ScrnInfoPtr pScrn);
+extern Bool I830UnbindGARTMemory(ScrnInfoPtr pScrn);
+extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result,
+ I830MemPool *pool, unsigned long size,
+ unsigned long alignment, int flags);
+
+extern void I830PrintAllRegisters(I830RegPtr i830Reg);
+extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg);
+
+extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
+
+/*
+ * 12288 is set as the maximum, chosen because it is enough for
+ * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
+ */
+#define I830_MAXIMUM_VBIOS_MEM 12288
+#define I830_DEFAULT_VIDEOMEM_2D (MB(8) / 1024)
+#define I830_DEFAULT_VIDEOMEM_3D (MB(32) / 1024)
+
+/* Flags for memory allocation function */
+#define FROM_ANYWHERE 0x00000000
+#define FROM_POOL_ONLY 0x00000001
+#define FROM_NEW_ONLY 0x00000002
+#define FROM_MASK 0x0000000f
+
+#define ALLOCATE_AT_TOP 0x00000010
+#define ALLOCATE_AT_BOTTOM 0x00000020
+#define FORCE_GAPS 0x00000040
+
+#define NEED_PHYSICAL_ADDR 0x00000100
+#define ALIGN_BOTH_ENDS 0x00000200
+#define FORCE_LOW 0x00000400
+
+#define ALLOC_NO_TILING 0x00001000
+#define ALLOC_INITIAL 0x00002000
+
+#define ALLOCATE_DRY_RUN 0x80000000
+
+
+#endif /* _I830_H_ */
diff --git a/src/i830_accel.c b/src/i830_accel.c
new file mode 100644
index 00000000..1a071497
--- /dev/null
+++ b/src/i830_accel.c
@@ -0,0 +1,770 @@
+/*
+ * XXX So far, for GXxor this is about 40% of the speed of SW, but CPU
+ * utilisation falls from 95% to < 5%.
+ */
+#ifndef DO_SCANLINE_IMAGE_WRITE
+#define DO_SCANLINE_IMAGE_WRITE 0
+#endif
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_accel.c,v 1.4 2002/12/10 01:27:05 dawes Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "xf86_ansic.h"
+#include "xf86.h"
+
+#include "i830.h"
+#include "i810_reg.h"
+
+static unsigned int i810Rop[16] = {
+ 0x00, /* GXclear */
+ 0x88, /* GXand */
+ 0x44, /* GXandReverse */
+ 0xCC, /* GXcopy */
+ 0x22, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x66, /* GXxor */
+ 0xEE, /* GXor */
+ 0x11, /* GXnor */
+ 0x99, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xDD, /* GXorReverse */
+ 0x33, /* GXcopyInvert */
+ 0xBB, /* GXorInverted */
+ 0x77, /* GXnand */
+ 0xFF /* GXset */
+};
+
+static unsigned int i810PatternRop[16] = {
+ 0x00, /* GXclear */
+ 0xA0, /* GXand */
+ 0x50, /* GXandReverse */
+ 0xF0, /* GXcopy */
+ 0x0A, /* GXandInvert */
+ 0xAA, /* GXnoop */
+ 0x5A, /* GXxor */
+ 0xFA, /* GXor */
+ 0x05, /* GXnor */
+ 0xA5, /* GXequiv */
+ 0x55, /* GXinvert */
+ 0xF5, /* GXorReverse */
+ 0x0F, /* GXcopyInvert */
+ 0xAF, /* GXorInverted */
+ 0x5F, /* GXnand */
+ 0xFF /* GXset */
+};
+
+int
+I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RingBuffer *ring = &(pI830->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("I830WaitLpRing %d\n", n);
+ first = GetTimeInMillis();
+ }
+
+ while (ring->space < n) {
+ ring->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+ 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 I830WaitLpRing(), now is %d, start is %d\n", now,
+ start);
+ I830PrintErrorState(pScrn);
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ pI830->AccelInfoRec = NULL; /* Stops recursive behavior */
+ FatalError("lockup\n");
+ }
+
+ DELAY(10);
+ }
+
+ 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
+I830Sync(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
+ ErrorF("I830Sync\n");
+
+#ifdef XF86DRI
+ /* VT switching tries to do this.
+ */
+ if (!pI830->LockHeld && pI830->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(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+ OUT_RING(MI_NOOP); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ I830WaitLpRing(pScrn, pI830->LpRing.mem.Size - 8, 0);
+
+ pI830->LpRing.space = pI830->LpRing.mem.Size - 8;
+ pI830->nextColorExpandBuf = 0;
+}
+
+void
+I830EmitFlush(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+ OUT_RING(MI_NOOP); /* pad to quadword */
+ ADVANCE_LP_RING();
+}
+
+void
+I830SelectBuffer(ScrnInfoPtr pScrn, int buffer)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ switch (buffer) {
+#ifdef XF86DRI
+ case I830_SELECT_BACK:
+ pI830->bufferOffset = pI830->BackBuffer.Start;
+ break;
+ case I830_SELECT_DEPTH:
+ pI830->bufferOffset = pI830->DepthBuffer.Start;
+ break;
+#endif
+ default:
+ case I830_SELECT_FRONT:
+ pI830->bufferOffset = pI830->FrontBuffer.Start;
+ break;
+ }
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SelectBuffer %d --> offset %x\n",
+ buffer, pI830->bufferOffset);
+}
+
+void
+I830RefreshRing(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->LpRing.head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+ pI830->LpRing.tail = INREG(LP_RING + RING_TAIL);
+ pI830->LpRing.space = pI830->LpRing.head - (pI830->LpRing.tail + 8);
+ if (pI830->LpRing.space < 0)
+ pI830->LpRing.space += pI830->LpRing.mem.Size;
+
+ if (pI830->AccelInfoRec)
+ pI830->AccelInfoRec->NeedToSync = TRUE;
+}
+
+/* I830 Accel Functions */
+
+static void I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int x, int y, int w, int h);
+
+static void I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int mask);
+
+static void I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
+ pScrn, int x,
+ int y, int w,
+ int h,
+ int skipleft);
+
+static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
+
+#if DO_SCANLINE_IMAGE_WRITE
+static void I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
+ unsigned int planemask,
+ int trans_color, int bpp,
+ int depth);
+static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h,
+ int skipleft);
+static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno);
+#endif
+
+
+/* The following function sets up the supported acceleration. Call it
+ * from the FbInit() function in the SVGA driver, or before ScreenInit
+ * in a monolithic server.
+ */
+Bool
+I830AccelInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830AccelInit\n");
+
+ pI830->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ pI830->bufferOffset = 0;
+ infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
+
+ /* Use the same sync function as the I830.
+ */
+ infoPtr->Sync = I830Sync;
+
+ /* Everything else is different enough to justify different functions */
+ {
+ infoPtr->SolidFillFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidFill = I830SetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = I830SubsequentSolidFillRect;
+ }
+
+ {
+ infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY);
+
+ infoPtr->SetupForScreenToScreenCopy = I830SetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy =
+ I830SubsequentScreenToScreenCopy;
+ }
+
+ {
+ infoPtr->SetupForMono8x8PatternFill = I830SetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ I830SubsequentMono8x8PatternFillRect;
+
+ infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN |
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+ NO_PLANEMASK);
+
+ }
+
+ if (pI830->Scratch.Size != 0) {
+ int i;
+ int width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ int nr_buffers = pI830->Scratch.Size / width;
+ unsigned char *ptr = pI830->FbBase + pI830->Scratch.Start;
+
+ pI830->NumScanlineColorExpandBuffers = nr_buffers;
+ pI830->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(nr_buffers, sizeof(unsigned char *));
+
+ for (i = 0; i < nr_buffers; i++, ptr += width)
+ pI830->ScanlineColorExpandBuffers[i] = ptr;
+
+ infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
+ (NO_PLANEMASK | ROP_NEEDS_SOURCE | BIT_ORDER_IN_BYTE_MSBFIRST);
+
+ infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(1, sizeof(unsigned char *));
+ infoPtr->NumScanlineColorExpandBuffers = 1;
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI830->ScanlineColorExpandBuffers[0];
+ pI830->nextColorExpandBuf = 0;
+
+ infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
+ I830SetupForScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ I830SubsequentScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentColorExpandScanline =
+ I830SubsequentColorExpandScanline;
+
+#if DO_SCANLINE_IMAGE_WRITE
+ infoPtr->NumScanlineImageWriteBuffers = 1;
+ infoPtr->ScanlineImageWriteBuffers = infoPtr->ScanlineColorExpandBuffers;
+ infoPtr->SetupForScanlineImageWrite = I830SetupForScanlineImageWrite;
+ infoPtr->SubsequentScanlineImageWriteRect =
+ I830SubsequentScanlineImageWriteRect;
+ infoPtr->SubsequentImageWriteScanline = I830SubsequentImageWriteScanline;
+ infoPtr->ScanlineImageWriteFlags = NO_GXCOPY |
+ NO_PLANEMASK |
+ ROP_NEEDS_SOURCE |
+ SCANLINE_PAD_DWORD;
+#endif
+ }
+
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+ return XAAInit(pScreen, infoPtr);
+}
+
+void
+I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n",
+ color, rop, planemask);
+
+ pI830->BR[13] = ((i810PatternRop[rop] << 16) |
+ (pScrn->displayWidth * pI830->cpp));
+
+ pI830->BR[16] = color;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+}
+
+void
+I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
+
+ {
+ BEGIN_LP_RING(6);
+
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
+ COLOR_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(COLOR_BLT_CMD);
+ }
+ OUT_RING(pI830->BR[13]);
+ OUT_RING((h << 16) | (w * pI830->cpp));
+ OUT_RING(pI830->bufferOffset + (y * pScrn->displayWidth + x) *
+ pI830->cpp);
+ OUT_RING(pI830->BR[16]);
+ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+}
+
+void
+I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int transparency_color)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SetupForScreenToScreenCopy %d %d %x %x %d\n",
+ xdir, ydir, rop, planemask, transparency_color);
+
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ pI830->BR[13] |= i810Rop[rop] << 16;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+
+}
+
+void
+I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1,
+ int dst_x1, int dst_y1, int w, int h)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int dst_x2, dst_y2;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
+ src_x1, src_y1, dst_x1, dst_y1, w, h);
+
+ dst_x2 = dst_x1 + w;
+ dst_y2 = dst_y1 + h;
+
+ {
+ BEGIN_LP_RING(8);
+
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(XY_SRC_COPY_BLT_CMD);
+ }
+ OUT_RING(pI830->BR[13]);
+ OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+ OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+ OUT_RING(pI830->bufferOffset);
+ OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+ OUT_RING(pI830->BR[13] & 0xFFFF);
+ OUT_RING(pI830->bufferOffset);
+
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SetupForMono8x8PatternFill\n");
+
+ pI830->BR[16] = pattx;
+ pI830->BR[17] = patty;
+ pI830->BR[18] = bg;
+ pI830->BR[19] = fg;
+
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); /* In bytes */
+ pI830->BR[13] |= i810PatternRop[rop] << 16;
+ if (bg == -1)
+ pI830->BR[13] |= (1 << 28);
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+
+}
+
+static void
+I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
+ int x, int y, int w, int h)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int x1, x2, y1, y2;
+
+ x1 = x;
+ x2 = x + w;
+ y1 = y;
+ y2 = y + h;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentMono8x8PatternFillRect\n");
+
+ {
+ BEGIN_LP_RING(10);
+
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA |
+ XY_MONO_PAT_BLT_WRITE_RGB |
+ ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
+ ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
+ } else {
+ OUT_RING(XY_MONO_PAT_BLT_CMD |
+ ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
+ ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
+ }
+ OUT_RING(pI830->BR[13]);
+ OUT_RING((y1 << 16) | x1);
+ OUT_RING((y2 << 16) | x2);
+ OUT_RING(pI830->bufferOffset);
+ OUT_RING(pI830->BR[18]); /* bg */
+ OUT_RING(pI830->BR[19]); /* fg */
+ OUT_RING(pI830->BR[16]); /* pattern data */
+ OUT_RING(pI830->BR[17]);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
+
+ if (pI830->nextColorExpandBuf == pI830->NumScanlineColorExpandBuffers)
+ I830Sync(pScrn);
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI830->ScanlineColorExpandBuffers[pI830->nextColorExpandBuf];
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("using color expand buffer %d\n", pI830->nextColorExpandBuf);
+
+ pI830->nextColorExpandBuf++;
+}
+
+static void
+I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
+ fg, bg, rop, planemask);
+
+ /* Fill out register values */
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ pI830->BR[13] |= i810Rop[rop] << 16;
+ if (bg == -1)
+ pI830->BR[13] |= (1 << 29);
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+
+ pI830->BR[18] = bg;
+ pI830->BR[19] = fg;
+
+ I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I830SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h, int skipleft)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentScanlineCPUToScreenColorExpandFill "
+ "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+ /* Fill out register values */
+ pI830->BR[9] = (pI830->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI830->cpp);
+ pI830->BR[11] = ((1 << 16) | w);
+}
+
+static void
+I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI830->FbBase);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n",
+ bufno, pI830->BR[12]);
+
+ {
+ BEGIN_LP_RING(8);
+
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA |
+ XY_MONO_SRC_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(XY_MONO_SRC_BLT_CMD);
+ }
+ OUT_RING(pI830->BR[13]);
+ OUT_RING(0); /* x1 = 0, y1 = 0 */
+ OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */
+ OUT_RING(pI830->BR[9]); /* dst addr */
+ OUT_RING(pI830->BR[12]); /* src addr */
+ OUT_RING(pI830->BR[18]); /* bg */
+ OUT_RING(pI830->BR[19]); /* fg */
+
+ ADVANCE_LP_RING();
+ }
+
+ /* Advance to next scanline.
+ */
+ pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
+ I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+#if DO_SCANLINE_IMAGE_WRITE
+static void
+I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
+ unsigned int planemask, int trans_color,
+ int bpp, int depth)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SetupForScanlineImageWrite %x %x\n", rop, planemask);
+
+ /* Fill out register values */
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ pI830->BR[13] |= i810Rop[rop] << 16;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+
+ I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int skipleft)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentScanlineImageWriteRect "
+ "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+ /* Fill out register values */
+ pI830->BR[9] = (pI830->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI830->cpp);
+ pI830->BR[11] = ((1 << 16) | w);
+}
+
+static void
+I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI830->FbBase);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n",
+ bufno, pI830->BR[12]);
+
+ {
+ BEGIN_LP_RING(8);
+
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(XY_SRC_COPY_BLT_CMD);
+ }
+ OUT_RING(pI830->BR[13]);
+ OUT_RING(0); /* x1 = 0, y1 = 0 */
+ OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */
+ OUT_RING(pI830->BR[9]); /* dst addr */
+ OUT_RING(0); /* source origin (0,0) */
+ OUT_RING(pI830->BR[11] & 0xffff); /* source pitch */
+ OUT_RING(pI830->BR[12]); /* src addr */
+
+ ADVANCE_LP_RING();
+ }
+
+ /* Advance to next scanline.
+ */
+ pI830->BR[9] += pScrn->displayWidth * pI830->cpp;
+ I830GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+#endif
diff --git a/src/i830_common.h b/src/i830_common.h
new file mode 100644
index 00000000..3367bfc1
--- /dev/null
+++ b/src/i830_common.h
@@ -0,0 +1,288 @@
+/**************************************************************************
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+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
+on 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
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.2 2002/12/10 01:27:05 dawes Exp $ */
+
+/* Author: Jeff Hartmann <jhartmann@valinux.com>
+
+ Converted to common header format:
+ Jens Owen <jens@tungstengraphics.com>
+ */
+
+#ifndef _I830_COMMON_H_
+#define _I830_COMMON_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _I830_DEFINES_
+#define _I830_DEFINES_
+
+#define I830_DMA_BUF_ORDER 12
+#define I830_DMA_BUF_SZ (1<<I830_DMA_BUF_ORDER)
+#define I830_DMA_BUF_NR 256
+#define I830_NR_SAREA_CLIPRECTS 8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I830_NR_TEX_REGIONS 64
+#define I830_LOG_MIN_TEX_REGION_SIZE 16
+
+/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */
+#if !defined(I830_ENABLE_4_TEXTURES)
+#define I830_TEXTURE_COUNT 2
+#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */
+#else /* defined(I830_ENABLE_4_TEXTURES) */
+#define I830_TEXTURE_COUNT 4
+#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */
+#endif /* I830_ENABLE_4_TEXTURES */
+
+#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
+
+#define I830_UPLOAD_CTX 0x1
+#define I830_UPLOAD_BUFFERS 0x2
+#define I830_UPLOAD_CLIPRECTS 0x4
+#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
+#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
+#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
+#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
+#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
+#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
+#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
+#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
+#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2))
+#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2))
+#define I830_UPLOAD_TEXIMAGE_MASK 0xff00
+#define I830_UPLOAD_TEX0 0x10000
+#define I830_UPLOAD_TEX1 0x20000
+#define I830_UPLOAD_TEX2 0x40000
+#define I830_UPLOAD_TEX3 0x80000
+#define I830_UPLOAD_TEX_N(n) (0x10000 << (n))
+#define I830_UPLOAD_TEX_MASK 0xf0000
+#define I830_UPLOAD_TEXBLEND0 0x100000
+#define I830_UPLOAD_TEXBLEND1 0x200000
+#define I830_UPLOAD_TEXBLEND2 0x400000
+#define I830_UPLOAD_TEXBLEND3 0x800000
+#define I830_UPLOAD_TEXBLEND_N(n) (0x100000 << (n))
+#define I830_UPLOAD_TEXBLEND_MASK 0xf00000
+#define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n))
+#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
+#define I830_UPLOAD_STIPPLE 0x8000000
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* 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 I830_DESTREG_CBUFADDR 0
+/* Invarient */
+#define I830_DESTREG_DBUFADDR 1
+#define I830_DESTREG_DV0 2
+#define I830_DESTREG_DV1 3
+#define I830_DESTREG_SENABLE 4
+#define I830_DESTREG_SR0 5
+#define I830_DESTREG_SR1 6
+#define I830_DESTREG_SR2 7
+#define I830_DESTREG_DR0 8
+#define I830_DESTREG_DR1 9
+#define I830_DESTREG_DR2 10
+#define I830_DESTREG_DR3 11
+#define I830_DESTREG_DR4 12
+#define I830_DEST_SETUP_SIZE 13
+
+/* Context state
+ */
+#define I830_CTXREG_STATE1 0
+#define I830_CTXREG_STATE2 1
+#define I830_CTXREG_STATE3 2
+#define I830_CTXREG_STATE4 3
+#define I830_CTXREG_STATE5 4
+#define I830_CTXREG_IALPHAB 5
+#define I830_CTXREG_STENCILTST 6
+#define I830_CTXREG_ENABLES_1 7
+#define I830_CTXREG_ENABLES_2 8
+#define I830_CTXREG_AA 9
+#define I830_CTXREG_FOGCOLOR 10
+#define I830_CTXREG_BLENDCOLR0 11
+#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
+#define I830_CTXREG_VF 13
+#define I830_CTXREG_VF2 14
+#define I830_CTXREG_MCSB0 15
+#define I830_CTXREG_MCSB1 16
+#define I830_CTX_SETUP_SIZE 17
+
+/* 1.3: Stipple state
+ */
+#define I830_STPREG_ST0 0
+#define I830_STPREG_ST1 1
+#define I830_STP_SETUP_SIZE 2
+
+/* Texture state (per tex unit)
+ */
+#define I830_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (6 dwords) */
+#define I830_TEXREG_MI1 1
+#define I830_TEXREG_MI2 2
+#define I830_TEXREG_MI3 3
+#define I830_TEXREG_MI4 4
+#define I830_TEXREG_MI5 5
+#define I830_TEXREG_MF 6 /* GFX_OP_MAP_FILTER */
+#define I830_TEXREG_MLC 7 /* GFX_OP_MAP_LOD_CTL */
+#define I830_TEXREG_MLL 8 /* GFX_OP_MAP_LOD_LIMITS */
+#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
+#define I830_TEX_SETUP_SIZE 10
+
+/* New version. Kernel auto-detects.
+ */
+#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0S0 1
+#define I830_TEXREG_TM0S1 2
+#define I830_TEXREG_TM0S2 3
+#define I830_TEXREG_TM0S3 4
+#define I830_TEXREG_TM0S4 5
+#define I830_TEXREG_NOP0 6 /* noop */
+#define I830_TEXREG_NOP1 7 /* noop */
+#define I830_TEXREG_NOP2 8 /* noop */
+#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
+#define __I830_TEX_SETUP_SIZE 10
+
+
+#define I830_FRONT 0x1
+#define I830_BACK 0x2
+#define I830_DEPTH 0x4
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_I830_INIT 0x00
+#define DRM_I830_VERTEX 0x01
+#define DRM_I830_CLEAR 0x02
+#define DRM_I830_FLUSH 0x03
+#define DRM_I830_GETAGE 0x04
+#define DRM_I830_GETBUF 0x05
+#define DRM_I830_SWAP 0x06
+#define DRM_I830_COPY 0x07
+#define DRM_I830_DOCOPY 0x08
+#define DRM_I830_FLIP 0x09
+#define DRM_I830_IRQ_EMIT 0x0a
+#define DRM_I830_IRQ_WAIT 0x0b
+#define DRM_I830_GETPARAM 0x0c
+#define DRM_I830_SETPARAM 0x0d
+
+#endif /* _I830_DEFINES_ */
+
+typedef struct {
+ enum {
+ I830_INIT_DMA = 0x01,
+ I830_CLEANUP_DMA = 0x02
+ } 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 w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
+ unsigned int back_pitch;
+ unsigned int depth_pitch;
+ unsigned int cpp;
+} drmI830Init;
+
+typedef struct {
+ int clear_color;
+ int clear_depth;
+ int flags;
+ unsigned int clear_colormask;
+ unsigned int clear_depthmask;
+} drmI830Clear;
+
+/* These may be placeholders if we have more cliprects than
+ * I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+} drmI830Vertex;
+
+typedef struct {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ void *address; /* Address to copy from */
+} drmI830Copy;
+
+typedef struct {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drmI830DMA;
+
+typedef struct drm_i830_irq_emit {
+ int *irq_seq;
+} drmI830IrqEmit;
+
+typedef struct drm_i830_irq_wait {
+ int irq_seq;
+} drmI830IrqWait;
+
+typedef struct drm_i830_getparam {
+ int param;
+ int *value;
+} drmI830GetParam;
+
+#define I830_PARAM_IRQ_ACTIVE 1
+
+
+typedef struct drm_i830_setparam {
+ int param;
+ int value;
+} drmI830SetParam;
+
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
+
+
+
+#endif /* _I830_DRM_H_ */
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
new file mode 100644
index 00000000..419fd583
--- /dev/null
+++ b/src/i830_cursor.c
@@ -0,0 +1,281 @@
+
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_cursor.c,v 1.6 2002/12/18 15:49:01 dawes Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86fbman.h"
+
+#include "i830.h"
+
+static void I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void I830ShowCursor(ScrnInfoPtr pScrn);
+static void I830HideCursor(ScrnInfoPtr pScrn);
+static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
+static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static Bool I830UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
+
+void
+I830InitHWCursor(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp;
+
+ DPRINTF(PFX, "I830InitHWCursor\n");
+
+ /* Initialise the HW cursor registers, leaving the cursor hidden. */
+ if (IS_MOBILE(pI830)) {
+ temp = INREG(CURSOR_A_CONTROL);
+ temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
+ MCURSOR_PIPE_SELECT);
+ temp |= CURSOR_MODE_DISABLE;
+ /*
+ * XXX Should enable cursor B when both pipes are enabled.
+ * For now, give pipe A preference.
+ */
+ if (pI830->pipeEnabled[0])
+ temp |= MCURSOR_PIPE_A;
+ else if (pI830->pipeEnabled[1])
+ temp |= MCURSOR_PIPE_B;
+ /* Need to set control, then address. */
+ OUTREG(CURSOR_A_CONTROL, temp);
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ } else {
+ temp = INREG(CURSOR_CONTROL);
+ temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
+ CURSOR_ENABLE | CURSOR_STRIDE_MASK);
+ temp |= (CURSOR_FORMAT_3C);
+ /* This initialises the format and leave the cursor disabled. */
+ OUTREG(CURSOR_CONTROL, temp);
+ /* Need to set address and size after disabling. */
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMem.Start);
+ temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
+ ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
+ OUTREG(CURSOR_SIZE, temp);
+ }
+}
+
+Bool
+I830CursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ I830Ptr pI830;
+ xf86CursorInfoPtr infoPtr;
+
+ DPRINTF(PFX, "I830CursorInit\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ pI830 = I830PTR(pScrn);
+ pI830->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 = I830SetCursorColors;
+ infoPtr->SetCursorPosition = I830SetCursorPosition;
+ infoPtr->LoadCursorImage = I830LoadCursorImage;
+ infoPtr->HideCursor = I830HideCursor;
+ infoPtr->ShowCursor = I830ShowCursor;
+ infoPtr->UseHWCursor = I830UseHWCursor;
+
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical)
+ return FALSE;
+
+ I830HideCursor(pScrn);
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+static Bool
+I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830UseHWCursor\n");
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem.Start);
+ int x, y;
+
+ DPRINTF(PFX, "I830LoadCursorImage\n");
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64 / 4; x++) {
+ *pcurs++ = *src++;
+ }
+ }
+}
+
+
+static void
+I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp = 0;
+ static Bool outsideViewport = FALSE;
+ Bool hide = FALSE, show = FALSE;
+
+ /*
+ * There is a screen display problem when the cursor position is set
+ * wholely outside of the viewport. We trap that here, turning the
+ * cursor off when that happens, and back on when it comes back into
+ * the viewport.
+ */
+ if (x >= pScrn->currentMode->HDisplay ||
+ y >= pScrn->currentMode->VDisplay ||
+ x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) {
+ hide = TRUE;
+ outsideViewport = TRUE;
+ } else if (outsideViewport) {
+ show = TRUE;
+ outsideViewport = FALSE;
+ }
+
+ if (x < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+ x = -x;
+ }
+ if (y < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+ y = -y;
+ }
+ temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+ temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+ OUTREG(CURSOR_A_POSITION, temp);
+
+ if (pI830->cursorOn) {
+ if (hide)
+ pI830->CursorInfoRec->HideCursor(pScrn);
+ else if (show)
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ pI830->cursorOn = TRUE;
+ }
+}
+
+static void
+I830ShowCursor(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp;
+
+ DPRINTF(PFX, "I830ShowCursor\n");
+ DPRINTF(PFX,
+ "Value of CursorMem.Physical is %x, "
+ " Value of CursorMem.Start is %x ",
+ pI830->CursorMem.Physical, pI830->CursorMem.Start);
+
+ pI830->cursorOn = TRUE;
+ if (IS_MOBILE(pI830)) {
+ temp = INREG(CURSOR_A_CONTROL);
+ temp &= ~CURSOR_MODE;
+ temp |= CURSOR_MODE_64_4C_AX;
+ /* Need to set mode, then address. */
+ OUTREG(CURSOR_A_CONTROL, temp);
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ } else {
+ temp = INREG(CURSOR_CONTROL);
+ temp |= CURSOR_ENABLE;
+ OUTREG(CURSOR_CONTROL, temp);
+ }
+}
+
+static void
+I830HideCursor(ScrnInfoPtr pScrn)
+{
+ CARD32 temp;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830HideCursor\n");
+
+ pI830->cursorOn = FALSE;
+ if (IS_MOBILE(pI830)) {
+ temp = INREG(CURSOR_A_CONTROL);
+ temp &= ~CURSOR_MODE;
+ temp |= CURSOR_MODE_DISABLE;
+ OUTREG(CURSOR_A_CONTROL, temp);
+ /* This is needed to flush the above change. */
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ } else {
+ temp = INREG(CURSOR_CONTROL);
+ temp &= ~CURSOR_ENABLE;
+ OUTREG(CURSOR_CONTROL, temp);
+ }
+}
+
+static void
+I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830SetCursorColors\n");
+
+ OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
+ OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
+ OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
+ OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
+}
diff --git a/src/i830_dga.c b/src/i830_dga.c
new file mode 100644
index 00000000..bb4c103a
--- /dev/null
+++ b/src/i830_dga.c
@@ -0,0 +1,293 @@
+/*
+ * 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>
+ */
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dga.c,v 1.3 2003/02/26 04:11:23 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "i830.h"
+#include "i810_reg.h"
+#include "dgaproc.h"
+#include "vgaHW.h"
+
+static Bool I830_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool I830_SetMode(ScrnInfoPtr, DGAModePtr);
+static void I830_Sync(ScrnInfoPtr);
+static int I830_GetViewport(ScrnInfoPtr);
+static void I830_SetViewport(ScrnInfoPtr, int, int, int);
+static void I830_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void I830_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+
+#if 0
+static void I830_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+#endif
+
+static
+DGAFunctionRec I830DGAFuncs = {
+ I830_OpenFramebuffer,
+ NULL,
+ I830_SetMode,
+ I830_SetViewport,
+ I830_GetViewport,
+ I830_Sync,
+ I830_FillRect,
+ I830_BlitRect,
+#if 0
+ I830_BlitTransRect
+#else
+ NULL
+#endif
+};
+
+Bool
+I830DGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ DGAModePtr modes = NULL, newmodes = NULL, currentMode;
+ DisplayModePtr pMode, firstMode;
+ int Bpp = pScrn->bitsPerPixel >> 3;
+ int num = 0;
+
+ MARKER();
+
+ pMode = firstMode = pScrn->modes;
+
+ while (pMode) {
+
+ newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
+
+ if (!newmodes) {
+ xfree(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+
+ currentMode = modes + num;
+ num++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if (!pI830->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 = pI830->FbBase + pScrn->fbOffset;
+
+ currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+ currentMode->imageWidth = pI830->FbMemBox.x2;
+ currentMode->imageHeight = pI830->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;
+ }
+
+ pI830->numDGAModes = num;
+ pI830->DGAModes = modes;
+
+ return DGAInit(pScreen, &I830DGAFuncs, modes, num);
+}
+
+static DisplayModePtr I830SavedDGAModes[MAXSCREENS];
+
+static Bool
+I830_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ int index = pScrn->pScreen->myNum;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ if (!pMode) { /* restore the original mode */
+ DPRINTF(PFX, "Restoring original mode (from DGA mode)\n");
+ if (pI830->DGAactive) {
+ pScrn->currentMode = I830SavedDGAModes[index];
+ pScrn->SwitchMode(index, pScrn->currentMode, 0);
+ pScrn->AdjustFrame(index, 0, 0, 0);
+ pI830->DGAactive = FALSE;
+ }
+ } else {
+ if (!pI830->DGAactive) {
+ DPRINTF(PFX, "Setting DGA mode\n");
+ I830SavedDGAModes[index] = pScrn->currentMode;
+ pI830->DGAactive = TRUE;
+ }
+
+ pScrn->SwitchMode(index, pMode->mode, 0);
+ }
+
+ return TRUE;
+}
+
+static int
+I830_GetViewport(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ return pI830->DGAViewportStatus;
+}
+
+static void
+I830_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ MARKER();
+
+ pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+
+ /* wait for retrace */
+ while ((hwp->readST01(hwp) & 0x08)) ;
+ while (!(hwp->readST01(hwp) & 0x08)) ;
+
+ pI830->DGAViewportStatus = 0;
+}
+
+static void
+I830_FillRect(ScrnInfoPtr pScrn,
+ int x, int y, int w, int h, unsigned long color)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ if (pI830->AccelInfoRec) {
+ (*pI830->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
+ (*pI830->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
+ SET_SYNC_FLAG(pI830->AccelInfoRec);
+ }
+}
+
+static void
+I830_Sync(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ if (pI830->AccelInfoRec) {
+ (*pI830->AccelInfoRec->Sync) (pScrn);
+ }
+}
+
+static void
+I830_BlitRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ if (pI830->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pI830->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
+ GXcopy, ~0, -1);
+ (*pI830->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+ SET_SYNC_FLAG(pI830->AccelInfoRec);
+ }
+}
+
+#if 0
+static void
+I830_BlitTransRect(ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h, int dstx, int dsty, unsigned long color)
+{
+
+ MARKER();
+
+ /* this one should be separate since the XAA function would
+ * prohibit usage of ~0 as the key */
+}
+#endif
+
+static Bool
+I830_OpenFramebuffer(ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem, int *size, int *offset, int *flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ MARKER();
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char *)(pI830->LinearAddr + pScrn->fbOffset);
+ *size = pI830->FrontBuffer.Size;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ DPRINTF(PFX,
+ " mem == 0x%.8x (pI830->LinearAddr)\n"
+ "size == %lu (pI830->FbMapSize)\n", *mem, *size);
+
+ return TRUE;
+}
diff --git a/src/i830_dri.c b/src/i830_dri.c
new file mode 100644
index 00000000..197a8252
--- /dev/null
+++ b/src/i830_dri.c
@@ -0,0 +1,1664 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.12 2003/02/08 21:26:57 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+Copyright © 2002 by 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
+on 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
+ATI, VA LINUX SYSTEMS AND/OR THEIR 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.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors: Jeff Hartmann <jhartmann@valinux.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * This driver does AGP memory allocation a little differently from most
+ * others. The 2D and 3D allocations have been unified (see i830_memory.c).
+ * The driver does the AGP allocations and binding directly, then passes
+ * on the mappings to the DRM module. The DRM's AGP interfaces are not used.
+ * The main difference with this is that the offsets need to include
+ * the AGP aperture base address because that won't be known or added on
+ * by the DRM module.
+ *
+ * DHD 07/2002
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Priv.h"
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+#include "windowstr.h"
+#include "shadow.h"
+
+#include "GL/glxtokens.h"
+
+#include "i830.h"
+#include "i830_dri.h"
+#include "i830_3d_reg.h"
+
+static char I830KernelDriverName[] = "i830";
+static char I830ClientDriverName[] = "i830";
+
+static Bool I830InitVisualConfigs(ScreenPtr pScreen);
+static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void I830DestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore);
+static void I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType readContextType,
+ void *readContextStore,
+ DRIContextType writeContextType,
+ void *writeContextStore);
+static void I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
+static void I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index);
+
+static Bool I830DRICloseFullScreen(ScreenPtr pScreen);
+static Bool I830DRIOpenFullScreen(ScreenPtr pScreen);
+static void I830DRITransitionTo2d(ScreenPtr pScreen);
+static void I830DRITransitionTo3d(ScreenPtr pScreen);
+static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+
+static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
+
+extern void GlxSetVisualConfigs(int nconfigs,
+ __GLXvisualConfig * configs,
+ void **configprivs);
+
+static Bool
+I830CleanupDma(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ drmI830Init info;
+
+ memset(&info, 0, sizeof(drmI830Init));
+ info.func = I830_CLEANUP_DMA;
+
+ if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
+ &info, sizeof(drmI830Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830InitDma(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RingBuffer *ring = &(pI830->LpRing);
+ I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+ drmI830Init info;
+
+ memset(&info, 0, sizeof(drmI830Init));
+ info.func = I830_INIT_DMA;
+
+ info.ring_start = ring->mem.Start + pI830->LinearAddr;
+ info.ring_end = ring->mem.End + pI830->LinearAddr;
+ info.ring_size = ring->mem.Size;
+
+ info.mmio_offset = (unsigned int)pI830DRI->regs;
+ info.buffers_offset = (unsigned int)pI830->buffer_map;
+
+ info.sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ info.front_offset = pI830->FrontBuffer.Start;
+ info.back_offset = pI830->BackBuffer.Start;
+ info.depth_offset = pI830->DepthBuffer.Start;
+ info.w = pScrn->virtualX;
+ info.h = pScrn->virtualY;
+ info.pitch = pI830->auxPitch;
+ info.pitch_bits = pI830->auxPitchBits;
+ info.back_pitch = pI830->auxPitch;
+ info.depth_pitch = pI830->auxPitch;
+ info.cpp = pI830->cpp;
+
+ if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
+ &info, sizeof(drmI830Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I830 Dma Initialization Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830SetParam(ScrnInfoPtr pScrn, int param, int value)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ drmI830SetParam sp;
+
+ memset(&sp, 0, sizeof(sp));
+ sp.param = param;
+ sp.value = value;
+
+ if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static Bool
+I830InitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ I830ConfigPrivPtr pI830Configs = 0;
+ I830ConfigPrivPtr *pI830ConfigPtrs = 0;
+ int accum, stencil, db, depth;
+ int i;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 24:
+ break;
+
+ case 16:
+ numConfigs = 8;
+
+ pConfigs =
+ (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs);
+ if (!pConfigs)
+ return FALSE;
+
+ pI830Configs =
+ (I830ConfigPrivPtr) xcalloc(sizeof(I830ConfigPrivRec),
+ numConfigs);
+ if (!pI830Configs) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+
+ pI830ConfigPtrs =
+ (I830ConfigPrivPtr *) xcalloc(sizeof(I830ConfigPrivPtr),
+ numConfigs);
+ if (!pI830ConfigPtrs) {
+ xfree(pConfigs);
+ xfree(pI830Configs);
+ return FALSE;
+ }
+
+ for (i = 0; i < numConfigs; i++)
+ pI830ConfigPtrs[i] = &pI830Configs[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].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 = 16;
+ } 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_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ 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;
+
+ case 32:
+ numConfigs = 8;
+
+ pConfigs = (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs);
+ if (!pConfigs) {
+ return FALSE;
+ }
+
+ pI830Configs = (I830ConfigPrivPtr) xcalloc(sizeof(I830ConfigPrivRec),
+ numConfigs);
+ if (!pI830Configs) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+
+ pI830ConfigPtrs = (I830ConfigPrivPtr *)
+ xcalloc(sizeof(I830ConfigPrivPtr), numConfigs);
+ if (!pI830ConfigPtrs) {
+ xfree(pConfigs);
+ xfree(pI830Configs);
+ return FALSE;
+ }
+
+ for (i = 0; i < numConfigs; i++) {
+ pI830ConfigPtrs[i] = &pI830Configs[i];
+ }
+
+ i = 0;
+ for (accum = 0; accum <= 1; accum++) {
+ for (depth = 0; depth <= 1; depth++) { /* and stencil */
+ for (db = 1; db >= 0; db--) {
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+ pConfigs[i].alphaMask = 0x00000000;;
+ 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;
+ }
+ if (db) {
+ pConfigs[i].doubleBuffer = TRUE;
+ } else {
+ pConfigs[i].doubleBuffer = FALSE;
+ }
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 24;
+ if (depth) {
+ pConfigs[i].depthSize = 24;
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].depthSize = 0;
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum) {
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ }
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ if (i != numConfigs) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] Incorrect initialization of visuals\n");
+ return FALSE;
+ }
+ break;
+
+ }
+ pI830->numVisualConfigs = numConfigs;
+ pI830->pVisualConfigs = pConfigs;
+ pI830->pVisualConfigsPriv = pI830Configs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI830ConfigPtrs);
+ return TRUE;
+}
+
+Bool
+I830DRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ I830DRIPtr pI830DRI;
+
+ DPRINTF(PFX, "I830DRIScreenInit\n");
+ /* Hardware 3D rendering only implemented for 16bpp and 32 bpp */
+ if (((pScrn->bitsPerPixel / 8) != 2 && pScrn->depth != 16) &&
+ (pScrn->bitsPerPixel / 8) != 4) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Direct rendering only supported in 16 and 32 bpp modes\n");
+ 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("DRIScreenInit"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] %s failed (libdri.a too old)\n", "I830DRIScreenInit");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] %s failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d bug version 4.0.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ "I830DRIScreenInit", major, minor, patch);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (!pDRIInfo) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRICreateInfoRec failed. Disabling DRI.\n");
+ return FALSE;
+ }
+
+ pI830->pDRIInfo = pDRIInfo;
+ pI830->LockHeld = 0;
+
+ pDRIInfo->drmDriverName = I830KernelDriverName;
+ pDRIInfo->clientDriverName = I830ClientDriverName;
+ pDRIInfo->busIdString = xalloc(64);
+
+ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ ((pciConfigPtr) pI830->PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI830->PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum);
+ pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
+ pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
+ pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
+ pDRIInfo->frameBufferPhysicalAddress = pI830->LinearAddr +
+ pI830->FrontBuffer.Start;
+ pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
+ pScrn->virtualY * pI830->cpp);
+ pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+ pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
+
+ if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
+ pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
+ else
+ pDRIInfo->maxDrawableTableEntry = I830_MAX_DRAWABLES;
+
+ if (sizeof(XF86DRISAREARec) + sizeof(I830SAREARec) > SAREA_MAX) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] Data does not fit in SAREA\n");
+ return FALSE;
+ }
+ /* This is a hack for now. We have to have more than a 4k page here
+ * because of the size of the state. However, the state should be
+ * in a per-context mapping. This will be added in the Mesa 3.5 port
+ * of the I830 driver.
+ */
+ pDRIInfo->SAREASize = SAREA_MAX;
+
+ if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) {
+ DRIDestroyInfoRec(pI830->pDRIInfo);
+ pI830->pDRIInfo = 0;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pI830DRI;
+ pDRIInfo->devPrivateSize = sizeof(I830DRIRec);
+ pDRIInfo->contextSize = sizeof(I830DRIContextRec);
+
+ pDRIInfo->CreateContext = I830CreateContext;
+ pDRIInfo->DestroyContext = I830DestroyContext;
+ pDRIInfo->SwapContext = I830DRISwapContext;
+ pDRIInfo->InitBuffers = I830DRIInitBuffers;
+ pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+ pDRIInfo->OpenFullScreen = I830DRIOpenFullScreen;
+ pDRIInfo->CloseFullScreen = I830DRICloseFullScreen;
+ pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
+ pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
+ pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = 0;
+ DRIDestroyInfoRec(pI830->pDRIInfo);
+ pI830->pDRIInfo = 0;
+ return FALSE;
+ }
+
+ /* Check the i830 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(pI830->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(pI830->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] I830DRIScreenInit 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);
+ I830DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Check the i830 DRM version */
+ version = drmGetVersion(pI830->drmSubFD);
+ if (version) {
+ if (version->version_major != 1 || version->version_minor < 3) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] %s failed because of a version mismatch.\n"
+ "[dri] i830.o kernel module version is %d.%d.%d but version 1.3 or greater is needed.\n"
+ "[dri] Disabling DRI.\n",
+ "I830DRIScreenInit",
+ version->version_major,
+ version->version_minor, version->version_patchlevel);
+ I830DRICloseScreen(pScreen);
+ drmFreeVersion(version);
+ return FALSE;
+ }
+ pI830->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+ }
+ return TRUE;
+}
+
+Bool
+I830DRIDoMappings(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ DRIInfoPtr pDRIInfo = pI830->pDRIInfo;
+ I830DRIPtr pI830DRI = pDRIInfo->devPrivate;
+ int bufs;
+
+ DPRINTF(PFX, "I830DRIDoMappings\n");
+ pI830DRI->regsSize = I830_REG_SIZE;
+ if (drmAddMap(pI830->drmSubFD, (drmHandle)pI830->MMIOAddr,
+ pI830DRI->regsSize, DRM_REGISTERS, 0, &pI830DRI->regs) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n",
+ pI830DRI->regs);
+
+ /*
+ * The tile setup is now initiated from I830BIOSScreenInit().
+ */
+
+ pI830->auxPitch = pScrn->displayWidth;
+ pI830->auxPitchBits = 0;
+
+ pI830DRI->backbufferSize = pI830->BackBuffer.Size;
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drmHandle)pI830->BackBuffer.Start + pI830->LinearAddr,
+ pI830->BackBuffer.Size, DRM_AGP, 0,
+ &pI830DRI->backbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Back Buffer = 0x%08lx\n",
+ pI830DRI->backbuffer);
+
+ pI830DRI->depthbufferSize = pI830->DepthBuffer.Size;
+ if (drmAddMap(pI830->drmSubFD,
+ (drmHandle)pI830->DepthBuffer.Start + pI830->LinearAddr,
+ pI830->DepthBuffer.Size, DRM_AGP, 0,
+ &pI830DRI->depthbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(depthbuffer) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Depth Buffer = 0x%08lx\n",
+ pI830DRI->depthbuffer);
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drmHandle)pI830->BufferMem.Start + pI830->LinearAddr,
+ pI830->BufferMem.Size, DRM_AGP, 0,
+ &pI830->buffer_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(buffer_map) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] DMA Buffers = 0x%08lx\n",
+ pI830->buffer_map);
+
+ pI830DRI->agp_buffers = pI830->buffer_map;
+ pI830DRI->agp_buf_size = pI830->BufferMem.Size;
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drmHandle)pI830->LpRing.mem.Start + pI830->LinearAddr,
+ pI830->LpRing.mem.Size, DRM_AGP, 0,
+ &pI830->ring_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08lx\n",
+ pI830->ring_map);
+
+ pI830DRI->textureSize = pI830->TexMem.Size;
+ pI830DRI->logTextureGranularity = pI830->TexGranularity;
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drmHandle)pI830->TexMem.Start + pI830->LinearAddr,
+ pI830->TexMem.Size, DRM_AGP, 0,
+ &pI830DRI->textures) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(textures) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] textures = 0x%08lx\n",
+ pI830DRI->textures);
+
+ if ((bufs = drmAddBufs(pI830->drmSubFD,
+ I830_DMA_BUF_NR,
+ I830_DMA_BUF_SZ,
+ DRM_AGP_BUFFER, pI830DRI->agp_buffers)) <= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding %d %d byte DMA buffers\n",
+ I830_DMA_BUF_NR, I830_DMA_BUF_SZ);
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] added %d %d byte DMA buffers\n", bufs, I830_DMA_BUF_SZ);
+
+ I830InitDma(pScrn);
+
+ if (pI830->PciInfo->chipType != PCI_CHIP_845_G &&
+ pI830->PciInfo->chipType != PCI_CHIP_I830_M) {
+ I830SetParam(pScrn, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
+ }
+
+ /* Okay now initialize the dma engine */
+ if (!pI830DRI->irq) {
+ pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->funcnum);
+#if 1
+ if ((drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] failure adding irq handler, there is a device already using that irq\n"
+ "[drm] Consider rearranging your PCI cards\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+#endif
+ }
+
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n", pI830DRI->irq);
+
+ pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+ pI830DRI->deviceID = pI830->PciInfo->chipType;
+ pI830DRI->width = pScrn->virtualX;
+ pI830DRI->height = pScrn->virtualY;
+ pI830DRI->mem = pScrn->videoRam * 1024;
+ pI830DRI->cpp = pI830->cpp;
+
+ pI830DRI->fbOffset = pI830->FrontBuffer.Start;
+ pI830DRI->fbStride = pI830->auxPitch;
+
+ pI830DRI->bitsPerPixel = pScrn->bitsPerPixel;
+
+ pI830DRI->textureOffset = pI830->TexMem.Start;
+
+ pI830DRI->backOffset = pI830->BackBuffer.Start;
+ pI830DRI->depthOffset = pI830->DepthBuffer.Start;
+
+ pI830DRI->ringOffset = pI830->LpRing.mem.Start;
+ pI830DRI->ringSize = pI830->LpRing.mem.Size;
+
+ pI830DRI->auxPitch = pI830->auxPitch;
+ pI830DRI->auxPitchBits = pI830->auxPitchBits;
+ pI830DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ if (!(I830InitVisualConfigs(pScreen))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I830InitVisualConfigs failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n");
+ pI830->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+
+ return TRUE;
+}
+
+void
+I830DRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830DRICloseScreen\n");
+
+ I830CleanupDma(pScrn);
+
+ DRICloseScreen(pScreen);
+
+ if (pI830->pDRIInfo) {
+ if (pI830->pDRIInfo->devPrivate) {
+ xfree(pI830->pDRIInfo->devPrivate);
+ pI830->pDRIInfo->devPrivate = 0;
+ }
+ DRIDestroyInfoRec(pI830->pDRIInfo);
+ pI830->pDRIInfo = 0;
+ }
+ if (pI830->pVisualConfigs)
+ xfree(pI830->pVisualConfigs);
+ if (pI830->pVisualConfigsPriv)
+ xfree(pI830->pVisualConfigsPriv);
+}
+
+static Bool
+I830CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+I830DestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+I830DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830DRIFinishScreenInit\n");
+
+ memset(sPriv, 0, sizeof(sPriv));
+
+ /* Have shadow run only while there is 3d active.
+ */
+ if (pI830->allowPageFlip && pI830->drmMinor >= 3) {
+ shadowSetup(pScreen);
+ shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0);
+ }
+ else
+ pI830->allowPageFlip = 0;
+
+ return DRIFinishScreenInit(pScreen);
+}
+
+void
+I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (syncType == DRI_3D_SYNC &&
+ oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("i830DRISwapContext (in)\n");
+
+ pI830->LockHeld = 1;
+ I830RefreshRing(pScrn);
+ } else if (syncType == DRI_2D_SYNC &&
+ oldContextType == DRI_NO_CONTEXT &&
+ newContextType == DRI_2D_CONTEXT) {
+ pI830->LockHeld = 0;
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("i830DRISwapContext (out)\n");
+ } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("i830DRISwapContext (other)\n");
+}
+
+static void
+I830DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ BoxPtr pbox = REGION_RECTS(prgn);
+ int nbox = REGION_NUM_RECTS(prgn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I830DRIInitBuffers\n");
+
+ I830SetupForSolidFill(pScrn, 0, GXcopy, -1);
+ while (nbox--) {
+ I830SelectBuffer(pScrn, I830_SELECT_BACK);
+ I830SubsequentSolidFillRect(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);
+
+ I830SelectBuffer(pScrn, I830_SELECT_DEPTH);
+
+ switch (pScrn->bitsPerPixel) {
+ case 16:
+ I830SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
+ break;
+ case 32:
+ I830SetupForSolidFill(pScrn, 0xffffff, GXcopy, -1);
+ break;
+ }
+
+ while (nbox--) {
+ I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+ pI830->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.
+ */
+static void
+I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index)
+{
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ BoxPtr pboxTmp, pboxNext, pboxBase;
+ DDXPointPtr pptTmp, pptNew2;
+ int xdir, ydir;
+
+ int screenwidth = pScrn->virtualX;
+ int screenheight = pScrn->virtualY;
+
+ BoxPtr pbox = REGION_RECTS(prgnSrc);
+ int nbox = REGION_NUM_RECTS(prgnSrc);
+
+ BoxPtr pboxNew1 = 0;
+ BoxPtr pboxNew2 = 0;
+ DDXPointPtr pptNew1 = 0;
+ 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) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
+ if (!pboxNew1)
+ return;
+ pptNew1 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
+ if (!pptNew1) {
+ DEALLOCATE_LOCAL(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) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
+ pptNew2 = (DDXPointPtr) ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
+ if (!pboxNew2 || !pptNew2) {
+ if (pptNew2)
+ DEALLOCATE_LOCAL(pptNew2);
+ if (pboxNew2)
+ DEALLOCATE_LOCAL(pboxNew2);
+ if (pboxNew1) {
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(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.
+ */
+ I830EmitFlush(pScrn);
+ I830SetupForScreenToScreenCopy(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);
+
+ I830SelectBuffer(pScrn, I830_SELECT_BACK);
+ I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+ I830SelectBuffer(pScrn, I830_SELECT_DEPTH);
+ I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+ }
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+ I830EmitFlush(pScrn);
+
+ if (pboxNew2) {
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ }
+ if (pboxNew1) {
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+ }
+
+ pI830->AccelInfoRec->NeedToSync = TRUE;
+}
+
+/* Completely Initialize the first context */
+void
+I830EmitInvarientState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+ CARD32 ctx_addr, temp;
+
+ BEGIN_LP_RING(128-2);
+
+ ctx_addr = pI830->ContextMem.Start;
+ /* Align to a 2k boundry */
+ ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
+
+ OUT_RING(MI_SET_CONTEXT);
+ OUT_RING(ctx_addr |
+ CTXT_NO_RESTORE |
+ CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
+
+ OUT_RING(STATE3D_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE |
+ AA_LINE_REGION_WIDTH_1_0 | AA_LINE_DISABLE);
+
+ OUT_RING(STATE3D_BUF_INFO_CMD);
+ OUT_RING(BUF_3D_ID_COLOR_BACK |
+ BUF_3D_USE_FENCE |
+ BUF_3D_PITCH((pI830->cpp * pScrn->displayWidth) / 4));
+ OUT_RING(BUF_3D_ADDR(pI830DRI->backOffset));
+
+ OUT_RING(STATE3D_BUF_INFO_CMD);
+ OUT_RING(BUF_3D_ID_DEPTH |
+ BUF_3D_USE_FENCE |
+ BUF_3D_PITCH((pI830->cpp * pScrn->displayWidth) / 4));
+ OUT_RING(BUF_3D_ADDR(pI830DRI->depthOffset));
+
+ OUT_RING(STATE3D_COLOR_FACTOR);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_COLOR_FACTOR_CMD(0));
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_COLOR_FACTOR_CMD(1));
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_COLOR_FACTOR_CMD(2));
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_COLOR_FACTOR_CMD(3));
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_DFLT_DIFFUSE_CMD);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_DFLT_SPEC_CMD);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_DFLT_Z_CMD);
+ OUT_RING(0);
+
+ switch (pScrn->bitsPerPixel) {
+ case 15:
+ temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB555;
+ break;
+ case 16:
+ temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB565;
+ break;
+ case 32:
+ temp = DEPTH_FRMT_24_FIXED_8_OTHER | COLR_BUF_ARGB8888;
+ break;
+ default:
+ temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB565;
+ break;
+ }
+
+ OUT_RING(STATE3D_DST_BUF_VARS_CMD);
+ OUT_RING(DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z | temp);
+
+ OUT_RING(STATE3D_DRAW_RECT_CMD);
+ OUT_RING(DRAW_RECT_DIS_DEPTH_OFS);
+ OUT_RING(0);
+ OUT_RING((pI830DRI->height << 16) | pI830DRI->width);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_ENABLES_1_CMD |
+ DISABLE_LOGIC_OP |
+ DISABLE_STENCIL_TEST |
+ DISABLE_DEPTH_BIAS |
+ DISABLE_SPEC_ADD |
+ I830_DISABLE_FOG |
+ DISABLE_ALPHA_TEST | DISABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
+
+ OUT_RING(STATE3D_ENABLES_2_CMD |
+ DISABLE_STENCIL_WRITE |
+ ENABLE_TEX_CACHE |
+ ENABLE_DITHER |
+ ENABLE_COLOR_MASK | ENABLE_COLOR_WRITE | ENABLE_DEPTH_WRITE);
+
+ OUT_RING(STATE3D_FOG_COLOR_CMD |
+ FOG_COLOR_RED(0) | FOG_COLOR_GREEN(0) | FOG_COLOR_BLUE(0));
+
+ OUT_RING(STATE3D_FOG_MODE);
+ OUT_RING(FOG_MODE_VERTEX |
+ ENABLE_FOG_CONST | ENABLE_FOG_SOURCE | ENABLE_FOG_DENSITY);
+ OUT_RING(0);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_INDPT_ALPHA_BLEND_CMD |
+ DISABLE_INDPT_ALPHA_BLEND |
+ ENABLE_ALPHA_BLENDFUNC |
+ ABLENDFUNC_ADD |
+ ENABLE_SRC_ABLEND_FACTOR |
+ SRC_ABLEND_FACT(BLENDFACT_ONE) |
+ ENABLE_DST_ABLEND_FACTOR | SRC_ABLEND_FACT(BLENDFACT_ZERO));
+
+ /* I need to come back to texture state */
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(0) |
+ TEXPIPE_COLOR |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(1) |
+ TEXPIPE_COLOR |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(2) |
+ TEXPIPE_COLOR |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(3) |
+ TEXPIPE_COLOR |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(0) |
+ TEXPIPE_ALPHA |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(1) |
+ TEXPIPE_ALPHA |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(2) |
+ TEXPIPE_ALPHA |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+ OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(3) |
+ TEXPIPE_ALPHA |
+ TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE);
+
+ OUT_RING(STATE3D_MAP_BLEND_OP_CMD(0) |
+ TEXPIPE_COLOR |
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
+ DISABLE_TEX_CNTRL_STAGE |
+ TEXOP_SCALE_1X |
+ TEXOP_MODIFY_PARMS | TEXOP_LAST_STAGE | TEXBLENDOP_ARG1);
+ OUT_RING(STATE3D_MAP_BLEND_OP_CMD(0) |
+ TEXPIPE_ALPHA |
+ ENABLE_TEXOUTPUT_WRT_SEL |
+ TEXOP_OUTPUT_CURRENT |
+ TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
+
+ OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
+ OUT_RING(TEXBIND_SET3(TEXCOORDSRC_DEFAULT) |
+ TEXBIND_SET2(TEXCOORDSRC_DEFAULT) |
+ TEXBIND_SET1(TEXCOORDSRC_DEFAULT) |
+ TEXBIND_SET0(TEXCOORDSRC_DEFAULT));
+
+ OUT_RING(STATE3D_MAP_COORD_SET_CMD |
+ MAP_UNIT(0) |
+ TEXCOORDS_ARE_IN_TEXELUNITS |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL |
+ ENABLE_ADDR_U_CNTL |
+ TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
+ TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
+ OUT_RING(STATE3D_MAP_COORD_SET_CMD |
+ MAP_UNIT(1) |
+ TEXCOORDS_ARE_IN_TEXELUNITS |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL |
+ ENABLE_ADDR_U_CNTL |
+ TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
+ TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
+ OUT_RING(STATE3D_MAP_COORD_SET_CMD |
+ MAP_UNIT(2) |
+ TEXCOORDS_ARE_IN_TEXELUNITS |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL |
+ ENABLE_ADDR_U_CNTL |
+ TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
+ TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
+ OUT_RING(STATE3D_MAP_COORD_SET_CMD |
+ MAP_UNIT(3) |
+ TEXCOORDS_ARE_IN_TEXELUNITS |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL |
+ ENABLE_ADDR_U_CNTL |
+ TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
+ TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
+
+ OUT_RING(STATE3D_MAP_TEX_STREAM_CMD |
+ MAP_UNIT(0) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(0) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
+ OUT_RING(STATE3D_MAP_TEX_STREAM_CMD |
+ MAP_UNIT(1) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(1) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
+ OUT_RING(STATE3D_MAP_TEX_STREAM_CMD |
+ MAP_UNIT(2) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(2) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
+ OUT_RING(STATE3D_MAP_TEX_STREAM_CMD |
+ MAP_UNIT(3) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(3) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
+
+#if 0
+ OUT_RING(STATE3D_MAP_FILTER_CMD |
+ MAP_UNIT(0) |
+ ENABLE_CHROMA_KEY_PARAMS |
+ ENABLE_MIP_MODE_FILTER |
+ MIPFILTER_NEAREST |
+ ENABLE_MAG_MODE_FILTER |
+ ENABLE_MIN_MODE_FILTER |
+ MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST));
+ OUT_RING(STATE3D_MAP_FILTER_CMD |
+ MAP_UNIT(1) |
+ ENABLE_CHROMA_KEY_PARAMS |
+ ENABLE_MIP_MODE_FILTER |
+ MIPFILTER_NEAREST |
+ ENABLE_MAG_MODE_FILTER |
+ ENABLE_MIN_MODE_FILTER |
+ MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST));
+ OUT_RING(STATE3D_MAP_FILTER_CMD |
+ MAP_UNIT(2) |
+ ENABLE_CHROMA_KEY_PARAMS |
+ ENABLE_MIP_MODE_FILTER |
+ MIPFILTER_NEAREST |
+ ENABLE_MAG_MODE_FILTER |
+ ENABLE_MIN_MODE_FILTER |
+ MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST));
+ OUT_RING(STATE3D_MAP_FILTER_CMD |
+ MAP_UNIT(3) |
+ ENABLE_CHROMA_KEY_PARAMS |
+ ENABLE_MIP_MODE_FILTER |
+ MIPFILTER_NEAREST |
+ ENABLE_MAG_MODE_FILTER |
+ ENABLE_MIN_MODE_FILTER |
+ MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST));
+
+ OUT_RING(STATE3D_MAP_INFO_COLR_CMD);
+ OUT_RING(MAP_INFO_TEX(0) |
+ MAPSURF_32BIT |
+ MT_32BIT_ARGB8888 |
+ MAP_INFO_OUTMUX_F0F1F2F3 |
+ MAP_INFO_VERTLINESTRIDEOFS_0 |
+ MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE);
+ OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0));
+ OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start));
+ OUT_RING(MAP_INFO_DWORD_PITCH(31));
+ OUT_RING(MAP_INFO_DFLT_COLR(0));
+
+ OUT_RING(STATE3D_MAP_INFO_COLR_CMD);
+ OUT_RING(MAP_INFO_TEX(1) |
+ MAPSURF_32BIT |
+ MT_32BIT_ARGB8888 |
+ MAP_INFO_OUTMUX_F0F1F2F3 |
+ MAP_INFO_VERTLINESTRIDEOFS_0 |
+ MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE);
+ OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0));
+ OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start));
+ OUT_RING(MAP_INFO_DWORD_PITCH(31));
+ OUT_RING(MAP_INFO_DFLT_COLR(0));
+
+ OUT_RING(STATE3D_MAP_INFO_COLR_CMD);
+ OUT_RING(MAP_INFO_TEX(2) |
+ MAPSURF_32BIT |
+ MT_32BIT_ARGB8888 |
+ MAP_INFO_OUTMUX_F0F1F2F3 |
+ MAP_INFO_VERTLINESTRIDEOFS_0 |
+ MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE);
+ OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0));
+ OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start));
+ OUT_RING(MAP_INFO_DWORD_PITCH(31));
+ OUT_RING(MAP_INFO_DFLT_COLR(0));
+
+ OUT_RING(STATE3D_MAP_INFO_COLR_CMD);
+ OUT_RING(MAP_INFO_TEX(3) |
+ MAPSURF_32BIT |
+ MT_32BIT_ARGB8888 |
+ MAP_INFO_OUTMUX_F0F1F2F3 |
+ MAP_INFO_VERTLINESTRIDEOFS_0 |
+ MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE);
+ OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0));
+ OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start));
+ OUT_RING(MAP_INFO_DWORD_PITCH(31));
+ OUT_RING(MAP_INFO_DFLT_COLR(0));
+
+ OUT_RING(STATE3D_MAP_LOD_CNTL_CMD |
+ MAP_UNIT(0) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0));
+ OUT_RING(STATE3D_MAP_LOD_CNTL_CMD |
+ MAP_UNIT(1) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0));
+ OUT_RING(STATE3D_MAP_LOD_CNTL_CMD |
+ MAP_UNIT(2) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0));
+ OUT_RING(STATE3D_MAP_LOD_CNTL_CMD |
+ MAP_UNIT(3) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0));
+
+ OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD |
+ MAP_UNIT(0) |
+ ENABLE_MAX_MIP_LVL |
+ ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0));
+ OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD |
+ MAP_UNIT(1) |
+ ENABLE_MAX_MIP_LVL |
+ ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0));
+ OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD |
+ MAP_UNIT(2) |
+ ENABLE_MAX_MIP_LVL |
+ ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0));
+ OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD |
+ MAP_UNIT(3) |
+ ENABLE_MAX_MIP_LVL |
+ ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0));
+#endif
+
+ OUT_RING(STATE3D_MAP_COORD_TRANSFORM);
+ OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
+ OUT_RING(STATE3D_MAP_COORD_TRANSFORM);
+ OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
+ OUT_RING(STATE3D_MAP_COORD_TRANSFORM);
+ OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
+ OUT_RING(STATE3D_MAP_COORD_TRANSFORM);
+ OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
+
+ /* End texture state */
+
+ OUT_RING(STATE3D_MODES_1_CMD |
+ ENABLE_COLR_BLND_FUNC |
+ BLENDFUNC_ADD |
+ ENABLE_SRC_BLND_FACTOR |
+ ENABLE_DST_BLND_FACTOR |
+ SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ZERO));
+
+ OUT_RING(STATE3D_MODES_2_CMD |
+ ENABLE_GLOBAL_DEPTH_BIAS |
+ GLOBAL_DEPTH_BIAS(0) |
+ ENABLE_ALPHA_TEST_FUNC |
+ ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) | ALPHA_REF_VALUE(0));
+
+ OUT_RING(STATE3D_MODES_3_CMD |
+ ENABLE_DEPTH_TEST_FUNC |
+ DEPTH_TEST_FUNC(COMPAREFUNC_LESS) |
+ ENABLE_ALPHA_SHADE_MODE |
+ ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
+ ENABLE_FOG_SHADE_MODE |
+ FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
+ ENABLE_SPEC_SHADE_MODE |
+ SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
+ ENABLE_COLOR_SHADE_MODE |
+ COLOR_SHADE_MODE(SHADE_MODE_LINEAR) |
+ ENABLE_CULL_MODE | CULLMODE_NONE);
+
+ OUT_RING(STATE3D_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC |
+ LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_TEST_MASK |
+ STENCIL_TEST_MASK(0xff) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff));
+
+ OUT_RING(STATE3D_MODES_5_CMD |
+ ENABLE_SPRITE_POINT_TEX |
+ SPRITE_POINT_TEX_OFF |
+ FLUSH_RENDER_CACHE |
+ FLUSH_TEXTURE_CACHE |
+ ENABLE_FIXED_LINE_WIDTH |
+ FIXED_LINE_WIDTH(0x2) |
+ ENABLE_FIXED_POINT_WIDTH | FIXED_POINT_WIDTH(1));
+
+ OUT_RING(STATE3D_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ ENABLE_TRI_STRIP_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
+
+ OUT_RING(STATE3D_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+
+ OUT_RING(STATE3D_SCISSOR_RECT_0_CMD);
+ OUT_RING(0);
+ OUT_RING(0);
+
+ OUT_RING(STATE3D_STENCIL_TEST_CMD |
+ ENABLE_STENCIL_PARMS |
+ STENCIL_FAIL_OP(STENCILOP_KEEP) |
+ STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) |
+ STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) |
+ ENABLE_STENCIL_TEST_FUNC |
+ STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) |
+ ENABLE_STENCIL_REF_VALUE | STENCIL_REF_VALUE(0));
+
+ OUT_RING(VRTX_FORMAT_NTEX(1));
+
+ OUT_RING(STATE3D_VERTEX_FORMAT_2_CMD |
+ VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_4_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_5_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_6_FMT(TEXCOORDFMT_2D) |
+ VRTX_TEX_SET_7_FMT(TEXCOORDFMT_2D));
+
+ OUT_RING(STATE3D_VERTEX_TRANSFORM);
+ OUT_RING(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
+
+ OUT_RING(STATE3D_W_STATE_CMD);
+ OUT_RING(MAGIC_W_STATE_DWORD1);
+ OUT_RING(0x3f800000 /* 1.0 in IEEE float */ );
+
+#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+
+ OUT_RING(GFX_OP_STIPPLE);
+ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+}
+
+/* Fullscreen hooks. The DRI fullscreen mode can probably be removed
+ * as it adds little or nothing above the mechanism below. (and isn't
+ * widely used)
+ */
+static Bool
+I830DRIOpenFullScreen(ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+static Bool
+I830DRICloseFullScreen(ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+
+/* Use callbacks from dri.c to support pageflipping mode for a single
+ * 3d context without need for any specific full-screen extension.
+ *
+ * Also see tdfx driver for example of using these callbacks to
+ * allocate and free 3d-specific memory on demand.
+ */
+
+
+
+
+
+/* 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,
+ * Otherwise will have to sync again???
+ */
+static void
+I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ RegionPtr damage = &pBuf->damage;
+ int i, num = REGION_NUM_RECTS(damage);
+ BoxPtr pbox = REGION_RECTS(damage);
+ I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+ int cmd, br13;
+
+ /* 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 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
+
+ if (pScrn->bitsPerPixel == 32) {
+ cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ br13 |= 3 << 24;
+ } else {
+ cmd = (XY_SRC_COPY_BLT_CMD);
+ br13 |= 1 << 24;
+ }
+
+ for (i = 0 ; i < num ; i++, pbox++) {
+ BEGIN_LP_RING(8);
+ OUT_RING(cmd);
+ OUT_RING(br13);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING((pbox->y2 << 16) | pbox->x2);
+ OUT_RING(pI830->BackBuffer.Start);
+ OUT_RING((pbox->y1 << 16) | pbox->x1);
+ OUT_RING(br13 & 0xffff);
+ OUT_RING(pI830->FrontBuffer.Start);
+ ADVANCE_LP_RING();
+ }
+}
+
+
+static void
+I830EnablePageFlip(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ pSAREAPriv->pf_enabled = pI830->allowPageFlip;
+ pSAREAPriv->pf_active = 0;
+
+ if (pI830->allowPageFlip) {
+ int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
+
+ BEGIN_LP_RING(8);
+ if (pScrn->bitsPerPixel == 32) {
+ OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ br13 |= 3 << 24;
+ } else {
+ OUT_RING(XY_SRC_COPY_BLT_CMD);
+ br13 |= 1 << 24;
+ }
+
+ OUT_RING(br13);
+ OUT_RING(0);
+ OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX);
+ OUT_RING(pI830->BackBuffer.Start);
+ OUT_RING(0);
+ OUT_RING(br13 & 0xffff);
+ OUT_RING(pI830->FrontBuffer.Start);
+ ADVANCE_LP_RING();
+
+ pSAREAPriv->pf_active = 1;
+ }
+}
+
+static void
+I830DisablePageFlip(ScreenPtr pScreen)
+{
+ I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ pSAREAPriv->pf_active = 0;
+}
+
+
+static void
+I830DRITransitionSingleToMulti3d(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.
+ */
+ I830DisablePageFlip(pScreen);
+}
+
+static void
+I830DRITransitionMultiToSingle3d(ScreenPtr pScreen)
+{
+ /* Let the remaining 3d app start page flipping again.
+ */
+ I830EnablePageFlip(pScreen);
+}
+
+
+static void
+I830DRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ I830EnablePageFlip(pScreen);
+ pI830->have3DWindows = 1;
+}
+
+
+static void
+I830DRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen);
+
+ /* Shut down shadowing if we've made it back to the front page:
+ */
+ if (sPriv->pf_current_page == 0) {
+ I830DisablePageFlip(pScreen);
+ }
+
+ pI830->have3DWindows = 0;
+}
+
+
diff --git a/src/i830_dri.h b/src/i830_dri.h
new file mode 100644
index 00000000..b60c7201
--- /dev/null
+++ b/src/i830_dri.h
@@ -0,0 +1,146 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.5 2002/12/10 01:27:05 dawes Exp $ */
+
+#ifndef _I830_DRI_H
+#define _I830_DRI_H
+
+#include "xf86drm.h"
+#include "i830_common.h"
+
+#define I830_MAX_DRAWABLES 256
+
+#define I830_MAJOR_VERSION 1
+#define I830_MINOR_VERSION 3
+#define I830_PATCHLEVEL 0
+
+#define I830_REG_SIZE 0x80000
+
+typedef struct _I830DRIRec {
+ drmHandle regs;
+ drmSize regsSize;
+ drmAddress regsMap;
+
+ drmSize backbufferSize;
+ drmHandle backbuffer;
+
+ drmSize depthbufferSize;
+ drmHandle depthbuffer;
+
+ drmHandle textures;
+ int textureSize;
+
+ drmHandle 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;
+ int sarea_priv_offset;
+} I830DRIRec, *I830DRIPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I830ConfigPrivRec, *I830ConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I830DRIContextRec, *I830DRIContextPtr;
+
+/* Warning: If you change the SAREA structure you must change the kernel
+ * structure as well */
+
+typedef struct _I830TexRegion {
+ 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 */
+} I830TexRegion;
+
+typedef struct _I830SAREA {
+ unsigned int ContextState[I830_CTX_SETUP_SIZE];
+ unsigned int BufferState[I830_DEST_SETUP_SIZE];
+ unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
+ unsigned int Palette[2][256];
+ unsigned int dirty;
+
+ unsigned int nbox;
+ XF86DRIClipRectRec boxes[I830_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.
+ */
+
+ I830TexRegion texList[I830_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? */
+
+ int perf_boxes; /* performance boxes to be displayed */
+
+ /* Here's the state for texunits 2,3:
+ */
+ unsigned int TexState2[I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed2;
+
+ unsigned int TexState3[I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed3;
+
+ unsigned int StippleState[I830_STP_SETUP_SIZE];
+} I830SAREARec, *I830SAREAPtr;
+
+/* Flags for perf_boxes
+ */
+#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
+#define I830_BOX_FLIP 0x2 /* populated by kernel */
+#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
+
+#endif
diff --git a/src/i830_driver.c b/src/i830_driver.c
new file mode 100644
index 00000000..073f8eb6
--- /dev/null
+++ b/src/i830_driver.c
@@ -0,0 +1,3586 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.27 2003/02/14 17:12:42 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+Copyright © 2002 by 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
+on 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
+THE COPYRIGHT HOLDERS AND/OR THEIR 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.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors: Jeff Hartmann <jhartmann@valinux.com>
+ * Abraham van der Merwe <abraham@2d3d.co.za>
+ * David Dawes <dawes@tungstengraphics.com>
+ */
+
+/*
+ * Mode handling is based on the VESA driver written by:
+ * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
+ */
+
+/*
+ * Changes:
+ *
+ * 23/08/2001 Abraham van der Merwe <abraham@2d3d.co.za>
+ * - Fixed display timing bug (mode information for some
+ * modes were not initialized correctly)
+ * - Added workarounds for GTT corruptions (I don't adjust
+ * the pitches for 1280x and 1600x modes so we don't
+ * need extra memory)
+ * - The code will now default to 60Hz if LFP is connected
+ * - Added different refresh rate setting code to work
+ * around 0x4f02 BIOS bug
+ * - BIOS workaround for some mode sets (I use legacy BIOS
+ * calls for setting those)
+ * - Removed 0x4f04, 0x01 (save state) BIOS call which causes
+ * LFP to malfunction (do some house keeping and restore
+ * modes ourselves instead - not perfect, but at least the
+ * LFP is working now)
+ * - Several other smaller bug fixes
+ *
+ * 06/09/2001 Abraham van der Merwe <abraham@2d3d.co.za>
+ * - Preliminary local memory support (works without agpgart)
+ * - DGA fixes (the code were still using i810 mode sets, etc.)
+ * - agpgart fixes
+ *
+ * 18/09/2001
+ * - Proper local memory support (should work correctly now
+ * with/without agpgart module)
+ * - more agpgart fixes
+ * - got rid of incorrect GTT adjustments
+ *
+ * 09/10/2001
+ * - Changed the DPRINTF() variadic macro to an ANSI C compatible
+ * version
+ *
+ * 10/10/2001
+ * - Fixed DPRINTF_stub(). I forgot the __...__ macros in there
+ * instead of the function arguments :P
+ * - Added a workaround for the 1600x1200 bug (Text mode corrupts
+ * when you exit from any 1600x1200 mode and 1280x1024@85Hz. I
+ * suspect this is a BIOS bug (hence the 1280x1024@85Hz case)).
+ * For now I'm switching to 800x600@60Hz then to 80x25 text mode
+ * and then restoring the registers - very ugly indeed.
+ *
+ * 15/10/2001
+ * - Improved 1600x1200 mode set workaround. The previous workaround
+ * was causing mode set problems later on.
+ *
+ * 18/10/2001
+ * - Fixed a bug in I830BIOSLeaveVT() which caused a bug when you
+ * switched VT's
+ */
+/*
+ * 07/2002 David Dawes
+ * - Add Intel(R) 855GM/852GM support.
+ */
+/*
+ * 07/2002 David Dawes
+ * - Cleanup code formatting.
+ * - Improve VESA mode selection, and fix refresh rate selection.
+ * - Don't duplicate functions provided in 4.2 vbe modules.
+ * - Don't duplicate functions provided in the vgahw module.
+ * - Rewrite memory allocation.
+ * - Rewrite initialisation and save/restore state handling.
+ * - Decouple the i810 support from i830 and later.
+ * - Remove various unnecessary hacks and workarounds.
+ * - Fix an 845G problem with the ring buffer not in pre-allocated
+ * memory.
+ * - Fix screen blanking.
+ * - Clear the screen at startup so you don't see the previous session.
+ * - Fix some HW cursor glitches, and turn HW cursor off at VT switch
+ * and exit.
+ *
+ * 08/2002 Keith Whitwell
+ * - Fix DRI initialisation.
+ */
+/*
+ * 08/2002 Alan Hourihane and David Dawes
+ * - Add XVideo support.
+ */
+/*
+ * 10/2002 David Dawes
+ * - Add Intel(R) 865G support.
+ */
+
+
+#ifndef PRINT_MODE_INFO
+#define PRINT_MODE_INFO 0
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.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 "Xv.h"
+#include "vbe.h"
+#include "vbeModes.h"
+
+#include "i830.h"
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+#define BIT(x) (1 << (x))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define NB_OF(x) (sizeof (x) / sizeof (*x))
+
+/* *INDENT-OFF* */
+static SymTabRec I830BIOSChipsets[] = {
+ {PCI_CHIP_I830_M, "i830"},
+ {PCI_CHIP_845_G, "845G"},
+ {PCI_CHIP_I855_GM, "852GM/855GM"},
+ {PCI_CHIP_I865_G, "865G"},
+ {-1, NULL}
+};
+
+static PciChipsets I830BIOSPciChipsets[] = {
+ {PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA},
+ {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA},
+ {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA},
+ {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA},
+ {-1, -1, RES_UNDEFINED}
+};
+
+/*
+ * Note: "ColorKey" is provided for compatibility with the i810 driver.
+ * However, the correct option name is "VideoKey". "ColorKey" usually
+ * refers to the tranparency key for 8+24 overlays, not for video overlays.
+ */
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_CACHE_LINES,
+ OPTION_DRI,
+ OPTION_PAGEFLIP,
+ OPTION_XVIDEO,
+ OPTION_VIDEO_KEY,
+ OPTION_COLOR_KEY,
+ OPTION_STRETCH,
+ OPTION_CENTER
+} I830Opts;
+
+static OptionInfoRec I830BIOSOptions[] = {
+ {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE},
+ {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE},
+ {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_CENTER, "Center", OPTV_BOOLEAN, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+/* *INDENT-ON* */
+
+static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags);
+static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags);
+static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
+static Bool I830BIOSEnterVT(int scrnIndex, int flags);
+static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
+ VbeCRTCInfoBlock *block);
+
+static Bool OffsetFrame = FALSE;
+
+
+
+#ifdef I830DEBUG
+void
+I830DPRINTF_stub(const char *filename, int line, const char *function,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ ErrorF("\n##############################################\n"
+ "*** In function %s, on line %d, in file %s ***\n",
+ function, line, filename);
+ va_start(ap, fmt);
+ VErrorF(fmt, ap);
+ va_end(ap);
+ ErrorF("##############################################\n\n");
+}
+#else /* #ifdef I830DEBUG */
+void
+I830DPRINTF_stub(const char *filename, int line, const char *function,
+ const char *fmt, ...)
+{
+ /* do nothing */
+}
+#endif /* #ifdef I830DEBUG */
+
+/* XXX Check if this is still needed. */
+const OptionInfoRec *
+I830BIOSAvailableOptions(int chipid, int busid)
+{
+ int i;
+
+ for (i = 0; I830BIOSPciChipsets[i].PCIid > 0; i++) {
+ if (chipid == I830BIOSPciChipsets[i].PCIid)
+ return I830BIOSOptions;
+ }
+ return NULL;
+}
+
+static Bool
+I830BIOSGetRec(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830;
+
+ if (pScrn->driverPrivate)
+ return TRUE;
+ pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1);
+ pI830->vesa = xnfcalloc(sizeof(VESARec), 1);
+ return TRUE;
+}
+
+static void
+I830BIOSFreeRec(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830;
+ VESAPtr pVesa;
+ DisplayModePtr mode;
+
+ if (!pScrn)
+ return;
+ if (!pScrn->driverPrivate)
+ return;
+
+ pI830 = I830PTR(pScrn);
+ mode = pScrn->modes;
+
+ if (mode) {
+ do {
+ if (mode->Private) {
+ VbeModeInfoData *data = (VbeModeInfoData *) mode->Private;
+
+ if (data->block)
+ xfree(data->block);
+ xfree(data);
+ mode->Private = NULL;
+ }
+ mode = mode->next;
+ } while (mode && mode != pScrn->modes);
+ }
+
+ if (pI830->vbeInfo)
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ if (pI830->pVbe)
+ vbeFree(pI830->pVbe);
+
+ pVesa = pI830->vesa;
+ if (pVesa->monitor)
+ xfree(pVesa->monitor);
+ if (pVesa->savedPal)
+ xfree(pVesa->savedPal);
+ xfree(pVesa);
+
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+static void
+I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+
+ /* The vbe module gets loaded in PreInit(), so no need to load it here. */
+
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+}
+
+/* Various extended video BIOS functions. */
+static const int refreshes[] = {
+ 43, 56, 60, 70, 72, 75, 85, 100, 120
+};
+static const int nrefreshes = sizeof(refreshes) / sizeof(refreshes[0]);
+
+static Bool
+Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
+{
+ if (ax == 0x005f)
+ return TRUE;
+ else if (ax == 0x015f) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Extended BIOS function 0x%04x failed.\n", func);
+ return FALSE;
+ } else if ((ax & 0xff) != 0x5f) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Extended BIOS function 0x%04x not supported.\n", func);
+ return FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Extended BIOS function 0x%04x returns 0x%04x.\n",
+ func, ax & 0xffff);
+ return FALSE;
+ }
+}
+
+#if 0
+static int
+BitToRefresh(int bits)
+{
+ int i;
+
+ for (i = 0; i < nrefreshes; i++)
+ if (bits & (1 << i))
+ return refreshes[i];
+ return 0;
+}
+
+static int
+GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetRefreshRate\n");
+
+ /* Only 8-bit mode numbers are supported. */
+ if (mode & 0x100)
+ return 0;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f05;
+ pVbe->pInt10->bx = (mode & 0xff) | 0x100;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) {
+ if (availRefresh)
+ *availRefresh = pVbe->pInt10->bx;
+ return BitToRefresh(pVbe->pInt10->cx);
+ } else
+ return 0;
+}
+#endif
+
+static int
+SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
+{
+ int i;
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
+
+ /* Only 8-bit mode numbers are supported. */
+ if (mode & 0x100)
+ return 0;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f05;
+ pVbe->pInt10->bx = mode & 0xff;
+
+ for (i = nrefreshes - 1; i >= 0; i--) {
+ /*
+ * Look for the highest value that the requested (refresh + 2) is
+ * greater than or equal to.
+ */
+ if (refreshes[i] <= (refresh + 2))
+ break;
+ }
+ /* i can be 0 if the requested refresh was higher than the max. */
+ if (i == 0) {
+ if (refresh >= refreshes[nrefreshes - 1])
+ i = nrefreshes - 1;
+ }
+ DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
+ refreshes[i], mode & 0xff);
+ pVbe->pInt10->cx = 1 << i;
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
+ return refreshes[i];
+ else
+ return 0;
+}
+
+static Bool
+GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
+ int devicesPipeA, int devicesPipeB, int *maxBandwidth,
+ int *bandwidthPipeA, int *bandwidthPipeB)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetModeSupport: modes 0x%x, 0x%x, devices: 0x%x, 0x%x\n",
+ modePipeA, modePipeB, devicesPipeA, devicesPipeB);
+
+ /* Only 8-bit mode numbers are supported. */
+ if ((modePipeA & 0x100) || (modePipeB & 0x100))
+ return 0;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f28;
+ pVbe->pInt10->bx = (modePipeA & 0xff) | ((modePipeB & 0xff) << 8);
+ if ((devicesPipeA & 0x80) || (devicesPipeB & 0x80))
+ pVbe->pInt10->cx = 0x8000;
+ else
+ pVbe->pInt10->cx = (devicesPipeA & 0xff) | ((devicesPipeB & 0xff) << 8);
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f28, pVbe->pInt10->ax)) {
+ if (maxBandwidth)
+ *maxBandwidth = pVbe->pInt10->cx;
+ if (bandwidthPipeA)
+ *bandwidthPipeA = pVbe->pInt10->dx & 0xffff;
+ /* XXX For XFree86 4.2.0 and earlier, ->dx is truncated to 16 bits. */
+ if (bandwidthPipeB)
+ *bandwidthPipeB = (pVbe->pInt10->dx >> 16) & 0xffff;
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+static int
+GetLFPCompMode(ScrnInfoPtr pScrn)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetLFPCompMode\n");
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f61;
+ pVbe->pInt10->bx = 0x100;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax))
+ return pVbe->pInt10->cx & 0xffff;
+ else
+ return -1;
+}
+
+#if 0
+static Bool
+SetLFPCompMode(ScrnInfoPtr pScrn, int compMode)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "SetLFPCompMode: compMode %d\n", compMode);
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f61;
+ pVbe->pInt10->bx = 0;
+ pVbe->pInt10->cx = compMode;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ return Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax);
+}
+#endif
+
+static int
+GetDisplayDevices(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+
+ DPRINTF(PFX, "GetDisplayDevices\n");
+
+#if 0
+ {
+ CARD32 temp;
+ ErrorF("ADPA is 0x%08x\n", INREG(ADPA));
+ ErrorF("DVOA is 0x%08x\n", INREG(DVOA));
+ ErrorF("DVOB is 0x%08x\n", INREG(DVOB));
+ ErrorF("DVOC is 0x%08x\n", INREG(DVOC));
+ ErrorF("LVDS is 0x%08x\n", INREG(LVDS));
+ temp = INREG(DVOA_SRCDIM);
+ ErrorF("DVOA_SRCDIM is 0x%08x (%d x %d)\n", temp,
+ (temp >> 12) & 0xfff, temp & 0xfff);
+ temp = INREG(DVOB_SRCDIM);
+ ErrorF("DVOB_SRCDIM is 0x%08x (%d x %d)\n", temp,
+ (temp >> 12) & 0xfff, temp & 0xfff);
+ temp = INREG(DVOC_SRCDIM);
+ ErrorF("DVOC_SRCDIM is 0x%08x (%d x %d)\n", temp,
+ (temp >> 12) & 0xfff, temp & 0xfff);
+ ErrorF("SWF0 is 0x%08x\n", INREG(SWF0));
+ ErrorF("SWF4 is 0x%08x\n", INREG(SWF4));
+ }
+#endif
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x100;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+ return pVbe->pInt10->cx & 0xffff;
+ else
+ return -1;
+}
+
+static Bool
+SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ CARD32 temp;
+
+ DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x1;
+ pVbe->pInt10->cx = devices;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+ return TRUE;
+ else {
+ ErrorF("Writing config directly to SWF0\n");
+ temp = INREG(SWF0);
+ OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
+ ErrorF("SetDisplayDevices failed. devices is 0x%x instead of 0x%x\n",
+ GetDisplayDevices(pScrn), devices);
+ return FALSE;
+ }
+}
+
+#if 0
+static Bool
+GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached,
+ int *encoderPresent)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetDevicePresence\n");
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x200;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ if (required)
+ *required = ((pVbe->pInt10->bx & 0x1) == 0);
+ if (attached)
+ *attached = (pVbe->pInt10->cx >> 8) & 0xff;
+ if (encoderPresent)
+ *encoderPresent = pVbe->pInt10->cx & 0xff;
+ return TRUE;
+ } else
+ return FALSE;
+}
+#endif
+
+static Bool
+GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present,
+ short *x, short *y)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetDisplayInfo: device: 0x%x\n", device);
+
+ switch (device & 0xff) {
+ case 0x01:
+ case 0x02:
+ case 0x04:
+ case 0x08:
+ case 0x10:
+ case 0x20:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "GetDisplayInfo: invalid device: 0x%x\n", device & 0xff);
+ return FALSE;
+ }
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x300;
+ pVbe->pInt10->cx = device & 0xff;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ if (attached)
+ *attached = ((pVbe->pInt10->bx & 0x2) != 0);
+ if (present)
+ *present = ((pVbe->pInt10->bx & 0x1) != 0);
+ if (pVbe->pInt10->cx != (device & 0xff)) {
+ if (y) {
+ *y = pVbe->pInt10->cx & 0xffff;
+ }
+ if (x) {
+ *x = (pVbe->pInt10->cx >> 16) & 0xffff;
+ }
+ }
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+/*
+ * Returns a string matching the device corresponding to the first bit set
+ * in "device". savedDevice is then set to device with that bit cleared.
+ * Subsequent calls with device == -1 will use savedDevice.
+ */
+
+static const char *displayDevices[] = {
+ "CRT",
+ "TV",
+ "DFP (digital flat panel)",
+ "LFP (local flat panel)",
+ "TV2 (second TV)",
+ "DFP2 (second digital flat panel)",
+ NULL
+};
+
+static const char *
+DeviceToString(int device)
+{
+ static int savedDevice = -1;
+ static int bit = 0;
+ const char *name;
+
+ if (device == -1) {
+ device = savedDevice;
+ bit = 0;
+ }
+
+ if (device == -1)
+ return NULL;
+
+ while (displayDevices[bit]) {
+ if (device & (1 << bit)) {
+ name = displayDevices[bit];
+ savedDevice = device & ~(1 << bit);
+ bit++;
+ return name;
+ }
+ bit++;
+ }
+ return NULL;
+}
+
+static void
+PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int pipe, n;
+ int displays;
+
+ DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
+
+ displays = pI830->configuredDevices;
+ if (displays == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No active display devices.\n");
+ return;
+ }
+
+ /* Check for active devices connected to each display pipe. */
+ for (n = 0; n < pI830->availablePipes; n++) {
+ pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
+ if (pipe) {
+ const char *name;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Currently active displays on Pipe %c:\n", PIPE_NAME(n));
+ name = DeviceToString(pipe);
+ do {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
+ name = DeviceToString(-1);
+ } while (name);
+
+ if (pipe & PIPE_UNKNOWN_ACTIVE)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "\tSome unknown display devices may also be present\n");
+
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No active displays on Pipe %c.\n", PIPE_NAME(n));
+ }
+
+ if (pI830->pipeDisplaySize[n].x2 != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Lowest common panel size for pipe %c is %d x %d\n",
+ PIPE_NAME(n), pI830->pipeDisplaySize[n].x2,
+ pI830->pipeDisplaySize[n].y2);
+ } else if (pI830->pipeEnabled[n] && pipe & ~PIPE_CRT_ACTIVE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No display size information available for pipe %c.\n",
+ PIPE_NAME(n));
+ }
+ }
+}
+
+static void
+GetPipeSizes(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int pipe, n;
+ DisplayType i;
+
+ DPRINTF(PFX, "GetPipeSizes\n");
+
+
+ for (n = 0; n < pI830->availablePipes; n++) {
+ pipe = (pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK;
+ pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0;
+ pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096;
+ for (i = 0; i < NumKnownDisplayTypes; i++) {
+ if (pipe & (1 << i) & PIPE_SIZED_DISP_MASK) {
+ if (pI830->displaySize[i].x2 != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Size of device %s is %d x %d\n",
+ displayDevices[i],
+ pI830->displaySize[i].x2,
+ pI830->displaySize[i].y2);
+ if (pI830->displaySize[i].x2 < pI830->pipeDisplaySize[n].x2)
+ pI830->pipeDisplaySize[n].x2 = pI830->displaySize[i].x2;
+ if (pI830->displaySize[i].y2 < pI830->pipeDisplaySize[n].y2)
+ pI830->pipeDisplaySize[n].y2 = pI830->displaySize[i].y2;
+ }
+ }
+ }
+
+ if (pI830->pipeDisplaySize[n].x2 == 4096)
+ pI830->pipeDisplaySize[n].x2 = 0;
+ if (pI830->pipeDisplaySize[n].y2 == 4096)
+ pI830->pipeDisplaySize[n].y2 = 0;
+ }
+}
+
+static Bool
+I830DetectDisplayDevice(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int pipe, n;
+ DisplayType i;
+
+ for (i = 0; i < NumKnownDisplayTypes; i++) {
+ if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i],
+ &pI830->displayPresent[i],
+ &pI830->displaySize[i].x2,
+ &pI830->displaySize[i].y2)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Display Info: %s: attached: %s, present: %s, size: "
+ "(%d,%d)\n", displayDevices[i],
+ BOOLTOSTRING(pI830->displayAttached[i]),
+ BOOLTOSTRING(pI830->displayPresent[i]),
+ pI830->displaySize[i].x2, pI830->displaySize[i].y2);
+ }
+ }
+
+ pI830->configuredDevices = GetDisplayDevices(pScrn);
+ if (pI830->configuredDevices == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Failed to detect active display devices\n");
+ return FALSE;
+ }
+
+ /* Check for active devices connected to each display pipe. */
+ for (n = 0; n < pI830->availablePipes; n++) {
+ pipe = ((pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
+ if (pipe) {
+ pI830->pipeEnabled[n] = TRUE;
+ }
+ }
+
+ GetPipeSizes(pScrn);
+ PrintDisplayDeviceInfo(pScrn);
+
+#if 0
+ /* A quick hack to change the set of enabled devices. */
+ enabledDevices = PIPE_CRT_ACTIVE;
+ if (!SetDisplayDevices(pScrn, enabledDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch to configured display devices\n");
+ }
+#endif
+
+ return TRUE;
+}
+
+static int
+I830DetectMemory(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ PCITAG bridge;
+ CARD16 gmch_ctrl;
+ int memsize = 0;
+
+ bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+
+ if (IS_I85X(pI830) || IS_I865G(pI830))
+ {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I855_GMCH_GMS_STOLEN_1M:
+ memsize = MB(1) - KB(132);
+ break;
+ case I855_GMCH_GMS_STOLEN_4M:
+ memsize = MB(4) - KB(132);
+ break;
+ case I855_GMCH_GMS_STOLEN_8M:
+ memsize = MB(8) - KB(132);
+ break;
+ case I855_GMCH_GMS_STOLEN_16M:
+ memsize = MB(16) - KB(132);
+ break;
+ case I855_GMCH_GMS_STOLEN_32M:
+ memsize = MB(32) - KB(132);
+ break;
+ }
+ } else
+ {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I830_GMCH_GMS_STOLEN_512:
+ memsize = KB(512) - KB(132);
+ break;
+ case I830_GMCH_GMS_STOLEN_1024:
+ memsize = MB(1) - KB(132);
+ break;
+ case I830_GMCH_GMS_STOLEN_8192:
+ memsize = MB(8) - KB(132);
+ break;
+ case I830_GMCH_GMS_LOCAL:
+ memsize = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Local memory found, but won't be used.\n");
+ break;
+ }
+ }
+ if (memsize > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "detected %d kB stolen memory.\n", memsize / 1024);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
+ }
+ return memsize;
+}
+
+static Bool
+I830MapMMIO(ScrnInfoPtr pScrn)
+{
+ int mmioFlags;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+#if !defined(__alpha__)
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
+#else
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
+#endif
+
+ pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+ pI830->PciTag,
+ pI830->MMIOAddr, I810_REG_SIZE);
+ if (!pI830->MMIOBase)
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+I830MapMem(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned i;
+
+ for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
+ pI830->FbMapSize = i;
+
+ if (!I830MapMMIO(pScrn))
+ return FALSE;
+
+ pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pI830->PciTag,
+ pI830->LinearAddr, pI830->FbMapSize);
+ if (!pI830->FbBase)
+ return FALSE;
+
+ pI830->LpRing.virtual_start = pI830->FbBase + pI830->LpRing.mem.Start;
+
+ return TRUE;
+}
+
+static void
+I830UnmapMMIO(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
+ I810_REG_SIZE);
+ pI830->MMIOBase = 0;
+}
+
+static Bool
+I830UnmapMem(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
+ pI830->FbMapSize);
+ pI830->FbBase = 0;
+ I830UnmapMMIO(pScrn);
+ return TRUE;
+}
+
+#ifndef HAVE_GET_PUT_BIOSMEMSIZE
+#define HAVE_GET_PUT_BIOSMEMSIZE 1
+#endif
+
+#if HAVE_GET_PUT_BIOSMEMSIZE
+/*
+ * Tell the BIOS how much video memory is available. The BIOS call used
+ * here won't always be available.
+ */
+static Bool
+PutBIOSMemSize(ScrnInfoPtr pScrn, int memSize)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "PutBIOSMemSize: %d kB\n", memSize / 1024);
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f11;
+ pVbe->pInt10->bx = 0;
+ pVbe->pInt10->cx = memSize / GTT_PAGE_SIZE;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ return Check5fStatus(pScrn, 0x5f11, pVbe->pInt10->ax);
+}
+
+/*
+ * This reports what the previous VBEGetVBEInfo() found. Be sure to call
+ * VBEGetVBEInfo() after changing the BIOS memory size view. If
+ * a separate BIOS call is added for this, it can be put here. Only
+ * return a valid value if the funtionality for PutBIOSMemSize()
+ * is available.
+ */
+static int
+GetBIOSMemSize(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int memSize = KB(pI830->vbeInfo->TotalMemory * 64);
+
+ DPRINTF(PFX, "GetBIOSMemSize\n");
+
+ if (PutBIOSMemSize(pScrn, memSize))
+ return memSize;
+ else
+ return -1;
+}
+#endif
+
+/*
+ * These three functions allow the video BIOS's view of the available video
+ * memory to be changed. This is currently implemented only for the 830
+ * and 845G, which can do this via a BIOS scratch register that holds the
+ * BIOS's view of the (pre-reserved) memory size. If another mechanism
+ * is available in the future, it can be plugged in here.
+ *
+ * The mapping used for the 830/845G scratch register's low 4 bits is:
+ *
+ * 320k => 0
+ * 832k => 1
+ * 8000k => 8
+ *
+ * The "unusual" values are the 512k, 1M, 8M pre-reserved memory, less
+ * overhead, rounded down to the BIOS-reported 64k granularity.
+ */
+
+static Bool
+SaveBIOSMemSize(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "SaveBIOSMemSize\n");
+
+ pI830->useSWF1 = FALSE;
+
+#if HAVE_GET_PUT_BIOSMEMSIZE
+ if ((pI830->saveBIOSMemSize = GetBIOSMemSize(pScrn)) != -1)
+ return TRUE;
+#endif
+
+ if (IS_I830(pI830) || IS_845G(pI830)) {
+ pI830->useSWF1 = TRUE;
+ pI830->saveSWF1 = INREG(SWF1) & 0x0f;
+
+ /*
+ * This is for sample purposes only. pI830->saveBIOSMemSize isn't used
+ * when pI830->useSWF1 is TRUE.
+ */
+ switch (pI830->saveSWF1) {
+ case 0:
+ pI830->saveBIOSMemSize = KB(320);
+ break;
+ case 1:
+ pI830->saveBIOSMemSize = KB(832);
+ break;
+ case 8:
+ pI830->saveBIOSMemSize = KB(8000);
+ break;
+ default:
+ pI830->saveBIOSMemSize = 0;
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+RestoreBIOSMemSize(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 swf1;
+
+ DPRINTF(PFX, "RestoreBIOSMemSize\n");
+
+ if (!pI830->overrideBIOSMemSize)
+ return;
+
+#if HAVE_GET_PUT_BIOSMEMSIZE
+ if (!pI830->useSWF1) {
+ PutBIOSMemSize(pScrn, pI830->saveBIOSMemSize);
+ return;
+ }
+#endif
+
+ if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
+ swf1 = INREG(SWF1);
+ swf1 &= ~0x0f;
+ swf1 |= (pI830->saveSWF1 & 0x0f);
+ OUTREG(SWF1, swf1);
+ }
+}
+
+static void
+SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 swf1;
+ Bool mapped;
+
+ DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024);
+
+ if (!pI830->overrideBIOSMemSize)
+ return;
+
+#if HAVE_GET_PUT_BIOSMEMSIZE
+ if (!pI830->useSWF1) {
+ PutBIOSMemSize(pScrn, newSize);
+ return;
+ }
+#endif
+
+ if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
+ CARD32 newSWF1;
+
+ /* Need MMIO access here. */
+ mapped = (pI830->MMIOBase != NULL);
+ if (!mapped)
+ I830MapMMIO(pScrn);
+
+ if (newSize <= KB(832))
+ newSWF1 = 1;
+ else
+ newSWF1 = 8;
+
+ swf1 = INREG(SWF1);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08x\n", swf1);
+ swf1 &= ~0x0f;
+ swf1 |= (newSWF1 & 0x0f);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08x\n", swf1);
+ OUTREG(SWF1, swf1);
+ if (!mapped)
+ I830UnmapMMIO(pScrn);
+ }
+}
+
+/*
+ * Use the native method instead of the vgahw method. So far this is
+ * only used for 8-bit mode.
+ *
+ * XXX Look into using the 10-bit gamma correction mode for 15/16/24 bit,
+ * and see if a DirectColor visual can be offered.
+ */
+static void
+I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ I830Ptr pI830;
+ int i, index;
+ unsigned char r, g, b;
+ CARD32 val, temp;
+
+ DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
+ pI830 = I830PTR(pScrn);
+
+ if (pI830->pipeEnabled[0]) {
+ /* It seems that an initial read is needed. */
+ temp = INREG(PALETTE_A);
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ r = colors[index].red;
+ g = colors[index].green;
+ b = colors[index].blue;
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(PALETTE_A + index * 4, val);
+ }
+ }
+ if (pI830->pipeEnabled[1]) {
+ /* It seems that an initial read is needed. */
+ temp = INREG(PALETTE_B);
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ r = colors[index].red;
+ g = colors[index].green;
+ b = colors[index].blue;
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(PALETTE_B + index * 4, val);
+ }
+ }
+}
+
+static void
+PreInitCleanup(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ RestoreBIOSMemSize(pScrn);
+ if (pI830->swfSaved) {
+ OUTREG(SWF0, pI830->saveSWF0);
+ OUTREG(SWF4, pI830->saveSWF4);
+ }
+ if (pI830->MMIOBase)
+ I830UnmapMMIO(pScrn);
+ I830BIOSFreeRec(pScrn);
+}
+
+static Bool
+I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ vgaHWPtr hwp;
+ I830Ptr pI830;
+ MessageType from;
+ rgb defaultWeight = { 0, 0, 0 };
+ vbeInfoPtr pVbe;
+ EntityInfoPtr pEnt;
+ int mem, memsize;
+ int flags24;
+ int i, n;
+ pointer pDDCModule, pVBEModule;
+ Bool enable;
+ const char *chipname;
+
+ if (pScrn->numEntities != 1)
+ return FALSE;
+
+ /* Load int10 module */
+ if (!xf86LoadSubModule(pScrn, "int10"))
+ return FALSE;
+ xf86LoaderReqSymLists(I810int10Symbols, NULL);
+
+ /* Load vbe module */
+ if (!(pVBEModule = xf86LoadSubModule(pScrn, "vbe")))
+ return FALSE;
+ xf86LoaderReqSymLists(I810vbeSymbols, NULL);
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ if (flags & PROBE_DETECT) {
+ I830BIOSProbeDDC(pScrn, pEnt->index);
+ return TRUE;
+ }
+
+ /* The vgahw module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+ xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
+
+
+ /* Allocate a vgaHWRec */
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+
+ /* Allocate driverPrivate */
+ if (!I830BIOSGetRec(pScrn))
+ return FALSE;
+
+ pI830 = I830PTR(pScrn);
+ pI830->pEnt = pEnt;
+
+ if (pI830->pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index);
+ pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device,
+ pI830->PciInfo->func);
+
+ if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+
+ }
+
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
+ pScrn->monitor = pScrn->confScreen->monitor;
+ pScrn->progClock = TRUE;
+ pScrn->rgbBits = 8;
+
+ flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
+
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24))
+ return FALSE;
+
+ 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 I830 driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
+ return FALSE;
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return FALSE;
+
+ hwp = VGAHWPTR(pScrn);
+ pI830->cpp = pScrn->bitsPerPixel / 8;
+
+ /* Process the options */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(pI830->Options = xalloc(sizeof(I830BIOSOptions))))
+ return FALSE;
+ memcpy(pI830->Options, I830BIOSOptions, sizeof(I830BIOSOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options);
+
+ /* We have to use PIO to probe, because we haven't mapped yet. */
+ I830SetPIOAccess(pI830);
+
+ /* Initialize VBE record */
+ if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n");
+ return FALSE;
+ }
+
+ switch (pI830->PciInfo->chipType) {
+ case PCI_CHIP_I830_M:
+ chipname = "830M";
+ break;
+ case PCI_CHIP_845_G:
+ chipname = "845G";
+ break;
+ case PCI_CHIP_I855_GM:
+ /* Check capid register to find the chipset variant */
+ pI830->variant = (pciReadLong(pI830->PciTag, I85X_CAPID)
+ >> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK;
+ switch (pI830->variant) {
+ case I855_GM:
+ chipname = "855GM";
+ break;
+ case I855_GME:
+ chipname = "855GME";
+ break;
+ case I852_GM:
+ chipname = "852GM";
+ break;
+ case I852_GME:
+ chipname = "852GME";
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Unknown 852GM/855GM variant: 0x%x)\n", pI830->variant);
+ chipname = "852GM/855GM (unknown variant)";
+ break;
+ }
+ break;
+ case PCI_CHIP_I865_G:
+ chipname = "865G";
+ break;
+ default:
+ chipname = "unknown chipset";
+ break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Integrated Graphics Chipset: Intel(R) %s\n", chipname);
+
+ pVbe = pI830->pVbe;
+
+ pI830->vbeInfo = VBEGetVBEInfo(pVbe);
+
+ /* Set the Chipset and ChipRev, allowing config file entries to override. */
+ if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) {
+ pScrn->chipset = pI830->pEnt->device->chipset;
+ from = X_CONFIG;
+ } else if (pI830->pEnt->device->chipID >= 0) {
+ pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
+ pI830->pEnt->device->chipID);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pI830->pEnt->device->chipID);
+ } else {
+ from = X_PROBED;
+ pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
+ pI830->PciInfo->chipType);
+ }
+
+ if (pI830->pEnt->device->chipRev >= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pI830->pEnt->device->chipRev);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
+ (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx");
+
+ if (pI830->pEnt->device->MemBase != 0) {
+ pI830->LinearAddr = pI830->pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else {
+ if (pI830->PciInfo->memBase[1] != 0) {
+ /* XXX Check mask. */
+ pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid FB address in PCI config space\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pI830->LinearAddr);
+
+ if (pI830->pEnt->device->IOBase != 0) {
+ pI830->MMIOAddr = pI830->pEnt->device->IOBase;
+ from = X_CONFIG;
+ } else {
+ if (pI830->PciInfo->memBase[1]) {
+ pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000;
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid MMIO address in PCI config space\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
+ (unsigned long)pI830->MMIOAddr);
+
+ /* Some of the probing needs MMIO access, so map it here. */
+ I830MapMMIO(pScrn);
+
+#if 1
+ pI830->saveSWF0 = INREG(SWF0);
+ pI830->saveSWF4 = INREG(SWF4);
+ pI830->swfSaved = TRUE;
+
+ /* Set "extended desktop" */
+ OUTREG(SWF0, pI830->saveSWF0 | (1 << 21));
+
+ /* Set "driver loaded", "OS unknown", "APM 1.2" */
+ OUTREG(SWF4, (pI830->saveSWF4 & ~((3 << 19) | (7 << 16))) |
+ (1 << 23) | (2 << 16));
+#endif
+
+ if (IS_I830(pI830) || IS_845G(pI830)) {
+ PCITAG bridge;
+ CARD16 gmch_ctrl;
+
+ bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+ if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
+ pI830->FbMapSize = 0x8000000;
+ } else {
+ pI830->FbMapSize = 0x4000000;
+ }
+ }
+ else {
+ /* 128MB aperture for later chips */
+ pI830->FbMapSize = 0x8000000;
+ }
+
+ /*
+ * Get the pre-allocated (stolen) memory size.
+ */
+ pI830->StolenMemory.Size = I830DetectMemory(pScrn);
+ pI830->StolenMemory.Start = 0;
+ pI830->StolenMemory.End = pI830->StolenMemory.Size;
+
+ /* Sanity check: compare with what the BIOS thinks. */
+ if (pI830->vbeInfo->TotalMemory != pI830->StolenMemory.Size / 1024 / 64) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Detected stolen memory (%d kB) doesn't match what the BIOS"
+ " reports (%d kB)\n",
+ ROUND_DOWN_TO(pI830->StolenMemory.Size / 1024, 64),
+ pI830->vbeInfo->TotalMemory * 64);
+ }
+
+ /* Find the maximum amount of agpgart memory available. */
+ mem = I830CheckAvailableMemory(pScrn);
+ pI830->StolenOnly = FALSE;
+
+ if (mem <= 0) {
+ if (pI830->StolenMemory.Size <= 0) {
+ /* Shouldn't happen. */
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "/dev/agpgart is either not available, or no memory "
+ "is available\nfor allocation, "
+ "and no pre-allocated memory is available.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "/dev/agpgart is either not available, or no memory "
+ "is available\nfor allocation. "
+ "Using pre-allocated memory only.\n");
+ mem = 0;
+ pI830->StolenOnly = TRUE;
+ }
+
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
+ pI830->noAccel = TRUE;
+ }
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
+ pI830->SWCursor = TRUE;
+ }
+
+ pI830->directRenderingDisabled =
+ !xf86ReturnOptValBool(pI830->Options, OPTION_DRI, TRUE);
+
+#ifdef XF86DRI
+ if (!pI830->directRenderingDisabled) {
+ if (pI830->noAccel || pI830->SWCursor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+ "needs HW cursor and 2D acceleration.\n");
+ pI830->directRenderingDisabled = TRUE;
+ } else if (pScrn->depth != 16 && pScrn->depth != 24) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+ "runs only at depths 16 and 24.\n");
+ pI830->directRenderingDisabled = TRUE;
+ }
+ }
+#endif
+
+ /*
+ * The "VideoRam" config file parameter specifies the total amount of
+ * memory that will be used/allocated. When agpgart support isn't
+ * available (StolenOnly == TRUE), this is limited to the amount of
+ * pre-allocated ("stolen") memory.
+ */
+
+ /*
+ * Default to I830_DEFAULT_VIDEOMEM_2D (8192KB) for 2D-only,
+ * or I830_DEFAULT_VIDEOMEM_3D (32768KB) for 3D. If the stolen memory
+ * amount is higher, default to it rounded up to the nearest MB. This
+ * guarantees that by default there will be at least some run-time
+ * space for things that need a physical address.
+ */
+ if (!pI830->pEnt->device->videoRam) {
+ from = X_DEFAULT;
+#ifdef XF86DRI
+ if (!pI830->directRenderingDisabled)
+ pScrn->videoRam = I830_DEFAULT_VIDEOMEM_3D;
+ else
+#endif
+ pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D;
+ if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam)
+ pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024);
+ } else {
+ from = X_CONFIG;
+ pScrn->videoRam = pI830->pEnt->device->videoRam;
+ }
+
+ DPRINTF(PFX,
+ "Available memory: %dk\n"
+ "Requested memory: %dk\n", mem, pScrn->videoRam);
+
+
+ if (mem + (pI830->StolenMemory.Size / 1024) < pScrn->videoRam) {
+ pScrn->videoRam = mem + (pI830->StolenMemory.Size / 1024);
+ from = X_PROBED;
+ if (mem + (pI830->StolenMemory.Size / 1024) <
+ pI830->pEnt->device->videoRam) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "VideoRAM reduced to %d kByte "
+ "(limited to available sysmem)\n", pScrn->videoRam);
+ }
+ }
+
+ if (pScrn->videoRam > pI830->FbMapSize / 1024) {
+ pScrn->videoRam = pI830->FbMapSize / 1024;
+ if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam)
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "VideoRam reduced to %d kByte (limited to aperture size)\n",
+ pScrn->videoRam);
+ }
+
+ if (mem > 0) {
+ /*
+ * If the reserved (BIOS accessible) memory is less than the desired
+ * amount, try to increase it. So far this is only implemented for
+ * the 845G and 830, but those details are handled in SetBIOSMemSize().
+ *
+ * The BIOS-accessible amount is only important for setting video
+ * modes. The maximum amount we try to set is limited to what would
+ * be enough for 1920x1440 with a 2048 pitch.
+ *
+ * If ALLOCATE_ALL_BIOSMEM is enabled in i830_memory.c, all of the
+ * BIOS-aware memory will get allocated. If it isn't then it may
+ * not be, and in that case there is an assumption that the video
+ * BIOS won't attempt to access memory beyond what is needed for
+ * modes that are actually used. ALLOCATE_ALL_BIOSMEM is enabled by
+ * default.
+ */
+
+ /* Try to keep HW cursor and Overlay amounts separate from this. */
+ int reserve = (HWCURSOR_SIZE + OVERLAY_SIZE) / 1024;
+
+ if (pScrn->videoRam - reserve >= I830_MAXIMUM_VBIOS_MEM)
+ pI830->newBIOSMemSize = KB(I830_MAXIMUM_VBIOS_MEM);
+ else
+ pI830->newBIOSMemSize =
+ KB(ROUND_DOWN_TO(pScrn->videoRam - reserve, 64));
+
+ if (pI830->vbeInfo->TotalMemory * 64 < pI830->newBIOSMemSize / 1024) {
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Will attempt to tell the BIOS that there is "
+ "%d kB VideoRAM\n", pI830->newBIOSMemSize / 1024);
+
+ if (SaveBIOSMemSize(pScrn)) {
+ pI830->overrideBIOSMemSize = TRUE;
+ SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ vbeFree(pI830->pVbe);
+ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+ pVbe = pI830->pVbe;
+ pI830->vbeInfo = VBEGetVBEInfo(pVbe);
+
+ pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS now sees %d kB VideoRAM\n",
+ pI830->BIOSMemorySize / 1024);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS view of memory size can't be changed "
+ "(this is not an error).\n");
+ }
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Pre-allocated VideoRAM: %d kByte\n",
+ pI830->StolenMemory.Size / 1024);
+ xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", pScrn->videoRam);
+ pI830->TotalVideoRam = KB(pScrn->videoRam);
+
+ /*
+ * If the requested videoRam amount is less than the stolen memory size,
+ * reduce the stolen memory size accordingly.
+ */
+ if (pI830->StolenMemory.Size > pI830->TotalVideoRam) {
+ pI830->StolenMemory.Size = pI830->TotalVideoRam;
+ pI830->StolenMemory.End = pI830->TotalVideoRam;
+ }
+
+ if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
+ &(pI830->CacheLines))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
+ pI830->CacheLines);
+ } else {
+ pI830->CacheLines = -1;
+ }
+
+ pI830->XvDisabled =
+ !xf86ReturnOptValBool(pI830->Options, OPTION_XVIDEO, TRUE);
+
+#ifdef I830_XV
+ if (xf86GetOptValInteger(pI830->Options, OPTION_VIDEO_KEY,
+ &(pI830->colorKey))) {
+ from = X_CONFIG;
+ } else if (xf86GetOptValInteger(pI830->Options, OPTION_COLOR_KEY,
+ &(pI830->colorKey))) {
+ from = X_CONFIG;
+ } else {
+ pI830->colorKey = (1 << pScrn->offset.red) |
+ (1 << pScrn->offset.green) |
+ (((pScrn->mask.blue >> pScrn->offset.blue) - 1) <<
+ pScrn->offset.blue);
+ from = X_DEFAULT;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "video overlay key set to 0x%x\n",
+ pI830->colorKey);
+#endif
+
+ pI830->allowPageFlip = FALSE;
+ enable = xf86ReturnOptValBool(pI830->Options, OPTION_PAGEFLIP, FALSE);
+#ifdef XF86DRI
+ if (!pI830->directRenderingDisabled) {
+ pI830->allowPageFlip = enable;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
+ enable ? "enabled" : "disabled");
+ }
+#endif
+
+ /* Check if the HW cursor needs physical address. */
+ if (IS_MOBILE(pI830))
+ pI830->CursorNeedsPhysical = TRUE;
+ else
+ pI830->CursorNeedsPhysical = FALSE;
+
+ /* Force ring buffer to be in low memory for the 845G. */
+ if (IS_845G(pI830))
+ pI830->NeedRingBufferLow = TRUE;
+
+ /*
+ * XXX If we knew the pre-initialised GTT format for certain, we could
+ * probably figure out the physical address even in the StolenOnly case.
+ */
+ if (pI830->StolenOnly && pI830->CursorNeedsPhysical && !pI830->SWCursor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "HW Cursor disabled because it needs agpgart memory.\n");
+ pI830->SWCursor = TRUE;
+ }
+
+ /*
+ * Reduce the maximum videoram available for video modes by the ring buffer,
+ * minimum scratch space and HW cursor amounts.
+ */
+ if (!pI830->SWCursor)
+ pScrn->videoRam -= (HWCURSOR_SIZE / 1024);
+ if (!pI830->XvDisabled)
+ pScrn->videoRam -= (OVERLAY_SIZE / 1024);
+ if (!pI830->noAccel) {
+ pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024);
+ pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
+
+ /*
+ * 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;
+ }
+
+ if (IS_MOBILE(pI830))
+ pI830->availablePipes = 2;
+ else
+ pI830->availablePipes = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
+ pI830->availablePipes, pI830->availablePipes > 1 ? "s" : "");
+
+ if (!I830DetectDisplayDevice(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't detect display devices.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if ((pI830->vesa->monitor = vbeDoEDID(pVbe, pDDCModule)) != NULL) {
+ xf86PrintEDID(pI830->vesa->monitor);
+ }
+ if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
+ xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
+ xf86UnloadSubModule(pDDCModule);
+
+ /* XXX Move this to a header. */
+#define VIDEO_BIOS_SCRATCH 0x18
+
+#if 1
+ /*
+ * XXX This should be in ScreenInit/EnterVT. PreInit should not leave the
+ * state changed.
+ */
+ /* Enable hot keys by writing the proper value to GR18 */
+ {
+ CARD8 gr18;
+
+ gr18 = pI830->readControl(pI830, GRX, VIDEO_BIOS_SCRATCH);
+ gr18 &= ~0x80; /*
+ * Clear Hot key bit so that Video
+ * BIOS performs the hot key
+ * servicing
+ */
+ pI830->writeControl(pI830, GRX, VIDEO_BIOS_SCRATCH, gr18);
+ }
+#endif
+
+ for (i = 0; i < pI830->availablePipes; i++) {
+ int pipe =
+ (pI830->configuredDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK;
+ if (pipe & ~PIPE_CRT_ACTIVE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "A non-CRT device is attached to pipe %c.\n"
+ "\tNo refresh rate overrides will be attempted.\n",
+ PIPE_NAME(i));
+ pI830->vesa->useDefaultRefresh = TRUE;
+ }
+ /*
+ * Some desktop platforms might not have 0x5f05, so useExtendedRefresh
+ * would need to be set to FALSE for those cases.
+ */
+ if (!pI830->vesa->useDefaultRefresh)
+ pI830->useExtendedRefresh = TRUE;
+ }
+
+ if (pI830->useExtendedRefresh) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n");
+ }
+
+ /*
+ * Calling 0x5f64 can reset the refresh rate, so only do this when
+ * using 0x5f05, or when not overriding the default refresh rate.
+ * Also, 0x5f64 doesn't work correctly in i830 platforms.
+ */
+ pI830->enableDisplays = !IS_I830(pI830) && pI830->useExtendedRefresh;
+
+ if (pI830->enableDisplays) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Will use BIOS call 0x5f64 to enable displays.\n");
+ }
+
+ /*
+ * Limit videoram available for mode selection to what the video
+ * BIOS can see.
+ */
+ if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
+ memsize = pI830->vbeInfo->TotalMemory * 64;
+ else
+ memsize = pScrn->videoRam;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Maximum space available for video modes: %d kByte\n", memsize);
+
+ /*
+ * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
+ * functions. For that reason it's important to set only
+ * V_MODETYPE_VGA in the flags for VBEGetModePool().
+ */
+ pScrn->modePool = VBEGetModePool(pScrn, pVbe, pI830->vbeInfo,
+ V_MODETYPE_VGA);
+
+ if (!pScrn->modePool) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No Video BIOS modes for chosen depth.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ VBESetModeNames(pScrn->modePool);
+
+ /*
+ * XXX DDC information: There's code in xf86ValidateModes
+ * (VBEValidateModes) to set monitor defaults based on DDC information
+ * where available. If we need something that does better than this,
+ * there's code in vesa/vesa.c.
+ */
+
+ /* XXX Need to get relevant modes and virtual parameters. */
+ /* Do the mode validation without regard to special scanline pitches. */
+ n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL,
+ NULL, 0, MAX_DISPLAY_PITCH, 1,
+ 0, MAX_DISPLAY_HEIGHT,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ memsize, LOOKUP_BEST_REFRESH);
+ if (n <= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ pScrn->currentMode = pScrn->modes;
+
+ if (pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+#ifndef USE_PITCHES
+#define USE_PITCHES 1
+#endif
+
+ /*
+ * If DRI is potentially usable, check if there is enough memory available
+ * for it, and if there's also enough to allow tiling to be enabled.
+ */
+#if defined(XF86DRI)
+ if (!pI830->directRenderingDisabled) {
+ int savedDisplayWidth = pScrn->displayWidth;
+ int memNeeded = 0;
+ /* Good pitches to allow tiling. Don't care about pitches < 256. */
+ static const int pitches[] = {
+ 128 * 2,
+ 128 * 4,
+ 128 * 8,
+ 128 * 16,
+ 128 * 32,
+ 128 * 64,
+ 0
+ };
+
+#ifdef I830_XV
+ /*
+ * Set this so that the overlay allocation is factored in when
+ * appropriate.
+ */
+ pI830->XvEnabled = !pI830->XvDisabled;
+#endif
+
+ for (i = 0; pitches[i] != 0; i++) {
+#if USE_PITCHES
+ if (pitches[i] >= pScrn->displayWidth) {
+ pScrn->displayWidth = pitches[i];
+ break;
+ }
+#else
+ if (pitches[i] == pScrn->displayWidth)
+ break;
+#endif
+ }
+
+ /*
+ * If the displayWidth is a tilable pitch, test if there's enough
+ * memory available to enable tiling.
+ */
+ if (pScrn->displayWidth == pitches[i]) {
+ I830ResetAllocations(pScrn, 0);
+ if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
+ I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN)) {
+ memNeeded = I830GetExcessMemoryAllocations(pScrn);
+ if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
+ if (memNeeded > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%d kBytes additional video memory is "
+ "required to\n\tenable tiling mode for DRI.\n",
+ (memNeeded + 1023) / 1024);
+ }
+ if (pI830->MemoryAperture.Size < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Allocation with DRI tiling enabled would "
+ "exceed the\n"
+ "\tmemory aperture size (%d kB) by %d kB.\n"
+ "\tReduce VideoRam amount to avoid this!\n",
+ pI830->FbMapSize / 1024,
+ -pI830->MemoryAperture.Size / 1024);
+ }
+ pScrn->displayWidth = savedDisplayWidth;
+ pI830->allowPageFlip = FALSE;
+ } else if (pScrn->displayWidth != savedDisplayWidth) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Increasing the scanline pitch to allow tiling mode "
+ "(%d -> %d).\n",
+ savedDisplayWidth, pScrn->displayWidth);
+ }
+ } else {
+ memNeeded = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Unexpected dry run allocation failure (1).\n");
+ }
+ }
+ if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
+ /*
+ * Tiling can't be enabled. Check if there's enough memory for DRI
+ * without tiling.
+ */
+ I830ResetAllocations(pScrn, 0);
+ if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
+ I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_NO_TILING)) {
+ memNeeded = I830GetExcessMemoryAllocations(pScrn);
+ if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
+ if (memNeeded > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%d kBytes additional video memory is required "
+ "to enable DRI.\n",
+ (memNeeded + 1023) / 1024);
+ }
+ if (pI830->MemoryAperture.Size < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Allocation with DRI enabled would "
+ "exceed the\n"
+ "\tmemory aperture size (%d kB) by %d kB.\n"
+ "\tReduce VideoRam amount to avoid this!\n",
+ pI830->FbMapSize / 1024,
+ -pI830->MemoryAperture.Size / 1024);
+ }
+ pI830->directRenderingDisabled = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Unexpected dry run allocation failure (2).\n");
+ }
+ }
+ }
+#endif
+
+ VBEPrintModes(pScrn);
+
+ if (!pI830->vesa->useDefaultRefresh) {
+ /*
+ * This sets the parameters for the VBE modes according to the best
+ * usable parameters from the Monitor sections modes (usually the
+ * default VESA modes), allowing for better than default refresh rates.
+ * This only works for VBE 3.0 and later. Also, we only do this
+ * if there are no non-CRT devices attached.
+ */
+ VBESetModeParameters(pScrn, pVbe);
+ }
+
+ /* PreInit shouldn't leave any state changes, so restore this. */
+ RestoreBIOSMemSize(pScrn);
+
+ /* Don't need MMIO access anymore. */
+ if (pI830->swfSaved) {
+ OUTREG(SWF0, pI830->saveSWF0);
+ OUTREG(SWF4, pI830->saveSWF4);
+ }
+ I830UnmapMMIO(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Load the required sub modules */
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ xf86LoaderReqSymLists(I810fbSymbols, NULL);
+
+ if (!pI830->noAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810xaaSymbols, NULL);
+ }
+
+ if (!pI830->SWCursor) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
+ }
+
+ /* We won't be using the VGA access after the probe. */
+ I830SetMMIOAccess(pI830);
+ xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr);
+ xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
+
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ vbeFree(pVbe);
+
+#if defined(XF86DRI)
+ if (!pI830->directRenderingDisabled) {
+ if (!xf86LoadSubModule(pScrn, "shadow")) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810shadowSymbols, NULL);
+ }
+#endif
+
+ return TRUE;
+}
+
+/*
+ * As the name says. Check that the initial state is reasonable.
+ * If any unrecoverable problems are found, bail out here.
+ */
+static Bool
+CheckInheritedState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int errors = 0, fatal = 0;
+ unsigned long temp, head, tail;
+
+ /* Check first for page table errors */
+ temp = INREG(PGE_ERR);
+ if (temp != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08x\n", temp);
+ errors++;
+ }
+ temp = INREG(PGETBL_CTL);
+ if (!(temp & 1)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PGTBL_CTL (0x%08x) indicates GTT is disabled\n", temp);
+ errors++;
+ }
+ temp = INREG(LP_RING + RING_LEN);
+ if (temp & 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PRB0_CTL (0x%08x) indicates ring buffer enabled\n", temp);
+ errors++;
+ }
+ head = INREG(LP_RING + RING_HEAD);
+ tail = INREG(LP_RING + RING_TAIL);
+ if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PRB0_HEAD (0x%08x) and PRB0_TAIL (0x%08x) indicate "
+ "ring buffer not flushed\n", head, tail);
+ errors++;
+ }
+#if 0
+ if (errors)
+ I830PrintErrorState(pScrn);
+#endif
+
+ if (fatal)
+ FatalError("CheckInheritedState: can't recover from the above\n");
+
+ return (errors != 0);
+}
+
+/*
+ * Reset registers that it doesn't make sense to save/restore to a sane state.
+ * This is basically the ring buffer and fence registers. Restoring these
+ * doesn't make sense without restoring GTT mappings. This is something that
+ * whoever gets control next should do.
+ */
+static void
+ResetState(ScrnInfoPtr pScrn, Bool flush)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ unsigned long temp;
+
+ DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
+
+ /* Reset the fence registers to 0 */
+ for (i = 0; i < 8; i++)
+ OUTREG(FENCE + i * 4, 0);
+
+ /* Flush the ring buffer (if enabled), then disable it. */
+ if (pI830->AccelInfoRec != NULL && flush) {
+ temp = INREG(LP_RING + RING_LEN);
+ if (temp & 1) {
+ I830RefreshRing(pScrn);
+ I830Sync(pScrn);
+ DO_RING_IDLE();
+ }
+ }
+ OUTREG(LP_RING + RING_LEN, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_START, 0);
+
+ if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
+ pI830->CursorInfoRec->HideCursor(pScrn);
+}
+
+static void
+SetFenceRegs(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+
+ DPRINTF(PFX, "SetFenceRegs\n");
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
+ }
+}
+
+static void
+SetRingRegs(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned int itemp;
+
+ DPRINTF(PFX, "SetRingRegs\n");
+
+ if (pI830->noAccel)
+ return;
+
+ OUTREG(LP_RING + RING_LEN, 0);
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ if ((pI830->LpRing.mem.Start & I830_RING_START_MASK) !=
+ pI830->LpRing.mem.Start) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I830SetRingRegs: Ring buffer start (%x) violates its "
+ "mask (%x)\n", pI830->LpRing.mem.Start, I830_RING_START_MASK);
+ }
+ /* Don't care about the old value. Reserved bits must be zero anyway. */
+ itemp = pI830->LpRing.mem.Start & I830_RING_START_MASK;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ if (((pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES) !=
+ pI830->LpRing.mem.Size - 4096) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I830SetRingRegs: Ring buffer size - 4096 (%x) violates its "
+ "mask (%x)\n", pI830->LpRing.mem.Size - 4096,
+ I830_RING_NR_PAGES);
+ }
+ /* Don't care about the old value. Reserved bits must be zero anyway. */
+ itemp = (pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES;
+ itemp |= (RING_NO_REPORT | RING_VALID);
+ OUTREG(LP_RING + RING_LEN, itemp);
+ I830RefreshRing(pScrn);
+}
+
+/*
+ * This should be called everytime the X server gains control of the screen,
+ * before any video modes are programmed (ScreenInit, EnterVT).
+ */
+static void
+SetHWOperatingState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "SetHWOperatingState\n");
+
+ if (!pI830->noAccel)
+ SetRingRegs(pScrn);
+ SetFenceRegs(pScrn);
+ if (!pI830->SWCursor)
+ I830InitHWCursor(pScrn);
+}
+
+static Bool
+SaveHWState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaReg = &hwp->SavedReg;
+ VbeModeInfoBlock *modeInfo;
+ VESAPtr pVesa;
+
+ DPRINTF(PFX, "SaveHWState\n");
+
+ pVesa = pI830->vesa;
+ /* Make sure we save at least this information in case of failure. */
+ VBEGetVBEMode(pVbe, &pVesa->stateMode);
+ modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
+ pVesa->savedScanlinePitch = 0;
+ if (modeInfo) {
+ if (VBE_MODE_GRAPHICS(modeInfo)) {
+ VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL);
+ }
+ VBEFreeModeInfo(modeInfo);
+ }
+
+ vgaHWUnlock(hwp);
+ vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
+
+#ifndef I845G_VBE_WORKAROUND
+#define I845G_VBE_WORKAROUND 1
+#endif
+
+ pVesa = pI830->vesa;
+ /* This save/restore method doesn't work for 845G BIOS */
+ /*
+ * XXX If it's fixed in production versions, this could be removed.
+ *
+ * KW: This may have been because of the behaviour I've found on my
+ * board: The 'save' command actually modifies the interrupt
+ * registers, turning off the irq & breaking the kernel module
+ * behaviour.
+ */
+ if (!I845G_VBE_WORKAROUND || !IS_845G(pI830)) {
+ CARD16 imr = INREG16(IMR);
+ CARD16 ier = INREG16(IER);
+ CARD16 hwstam = INREG16(HWSTAM);
+
+ if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize,
+ &pVesa->statePage)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n");
+ return FALSE;
+ }
+
+ OUTREG16(IMR, imr);
+ OUTREG16(IER, ier);
+ OUTREG16(HWSTAM, hwstam);
+ }
+
+ pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256,
+ NULL, FALSE, FALSE);
+ if (!pVesa->savedPal) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "SaveHWState: VBESetGetPaletteData(GET) failed.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+RestoreHWState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaReg = &hwp->SavedReg;
+ VESAPtr pVesa;
+ Bool restored = FALSE;
+
+ DPRINTF(PFX, "RestoreHWState\n");
+
+ pVesa = pI830->vesa;
+
+ /*
+ * Workaround for text mode restoration with some flat panels.
+ * Temporarily program a 640x480 mode before switching back to
+ * text mode.
+ */
+ if (pVesa->useDefaultRefresh) {
+ int mode = 0;
+
+ switch (pScrn->depth) {
+ case 8:
+ mode = 0x30;
+ break;
+ case 15:
+ mode = 0x40;
+ break;
+ case 16:
+ mode = 0x41;
+ break;
+ case 24:
+ mode = 0x50;
+ break;
+ }
+ mode |= (1 << 15) | (1 << 14);
+ I830VESASetVBEMode(pScrn, mode, NULL);
+ }
+
+ if (pVesa->state && pVesa->stateSize) {
+ CARD16 imr = INREG16(IMR);
+ CARD16 ier = INREG16(IER);
+ CARD16 hwstam = INREG16(HWSTAM);
+
+ /* Make a copy of the state. Don't rely on it not being touched. */
+ if (!pVesa->pstate) {
+ pVesa->pstate = xalloc(pVesa->stateSize);
+ if (pVesa->pstate)
+ memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
+ }
+ restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state,
+ &pVesa->stateSize, &pVesa->statePage);
+ if (!restored) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "RestoreHWState: VBESaveRestore failed.\n");
+ }
+ /* Copy back */
+ if (pVesa->pstate)
+ memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
+
+ OUTREG16(IMR, imr);
+ OUTREG16(IER, ier);
+ OUTREG16(HWSTAM, hwstam);
+ }
+ /* If that failed, restore the original mode. */
+ if (!restored) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Setting the original video mode instead of restoring\n\t"
+ "the saved state\n");
+ I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
+ }
+ if (pVesa->savedScanlinePitch)
+ VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
+
+ if (pVesa->savedPal)
+ VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
+
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
+ vgaHWLock(hwp);
+ return TRUE;
+}
+
+#ifndef USE_VBE
+#define USE_VBE 1
+#endif
+
+static Bool
+I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
+#if USE_VBE
+ return VBESetVBEMode(pI830->pVbe, mode, block);
+#else
+ {
+ vbeInfoPtr pVbe = pI830->pVbe;
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x80 | (mode & 0x7f);
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ pVbe->pInt10->ax = 0x0f00;
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if ((pVbe->pInt10->ax & 0x7f) == (mode & 0x7f))
+ return TRUE;
+ else
+ return FALSE;
+ }
+#endif
+}
+
+static Bool
+I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ VbeModeInfoData *data;
+ int mode, i;
+ CARD32 planeA, planeB, temp;
+ int refresh = 60;
+#ifdef XF86DRI
+ Bool didLock = FALSE;
+#endif
+
+ DPRINTF(PFX, "I830VESASetMode\n");
+
+ data = (VbeModeInfoData *) pMode->Private;
+
+ /* Always Enable Linear Addressing */
+ mode = data->mode | (1 << 15) | (1 << 14);
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled && !pI830->LockHeld) {
+ DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+ pI830->LockHeld = 1;
+ didLock = TRUE;
+ }
+#endif
+
+#ifndef MODESWITCH_RESET_STATE
+#define MODESWITCH_RESET_STATE 0
+#endif
+#if MODESWITCH_RESET_STATE
+ ResetState(pScrn, TRUE);
+#endif
+
+ /* XXX Add macros for the various mode parameter bits. */
+
+ if (pI830->vesa->useDefaultRefresh)
+ mode &= ~(1 << 11);
+
+ if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
+ if ((data->block && (mode & (1 << 11))) &&
+ I830VESASetVBEMode(pScrn, (mode & ~(1 << 11)), NULL) == TRUE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Set VBE Mode rejected this modeline.\n\t"
+ "Trying standard mode instead!\n");
+ DPRINTF(PFX, "OOPS!\n");
+ xfree(data->block);
+ data->block = NULL;
+ data->mode &= ~(1 << 11);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
+ return FALSE;
+ }
+ }
+
+ /*
+ * The BIOS may not set a scanline pitch that would require more video
+ * memory than it's aware of. We check for this later, and set it
+ * explicitly if necessary.
+ */
+ if (data->data->XResolution != pScrn->displayWidth)
+ VBESetLogicalScanline(pVbe, pScrn->displayWidth);
+
+ if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01)
+ VBESetGetDACPaletteFormat(pVbe, 8);
+
+ /*
+ * XXX This location of this isn't correct.
+ *
+ * Turn on the configured displays. This has the effect of resetting
+ * the default refresh rates to values that the configured displays
+ * can handle. This seems to be the safest way to make sure that this
+ * happens. When it's safe to set higher values, we do that after this.
+ *
+ * Note: When a DFP is connected to an 830, this causes the mode setting
+ * to be trashed. So, we don't do it on the 830.
+ *
+ * XXX Need to test an 830 with a LFP.
+ */
+ if (pI830->enableDisplays) {
+ if (!SetDisplayDevices(pScrn, pI830->configuredDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch to configured display devices\n");
+ }
+ }
+
+ /*
+ * When it's OK to set better than default refresh rates, set them here.
+ */
+ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
+ (mode & (1 << 11)) && data && data->data && data->block) {
+ refresh = SetRefreshRate(pScrn, mode, data->block->RefreshRate / 100);
+ if (!refresh) {
+ refresh = 60;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set refresh rate to %dHz.\n",
+ data->block->RefreshRate / 100);
+ }
+ }
+
+
+ /* XXX Fix plane A with pipe A, and plane B with pipe B. */
+ planeA = INREG(DSPACNTR);
+ planeB = INREG(DSPBCNTR);
+
+ pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0);
+ pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s.\n",
+ pI830->planeEnabled[0] ? "enabled" : "disabled");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s.\n",
+ pI830->planeEnabled[1] ? "enabled" : "disabled");
+
+ /*
+ * Sometimes it seems that no display planes are enabled at this point.
+ * For mobile platforms pick the plane(s) connected to enabled pipes.
+ * For others choose plane A.
+ */
+ if (!pI830->planeEnabled[0] && !pI830->planeEnabled[1]) {
+ if (IS_MOBILE(pI830)) {
+ if ((pI830->pipeEnabled[0] &&
+ ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
+ (pI830->pipeEnabled[1] &&
+ ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
+ pI830->planeEnabled[0] = TRUE;
+ }
+ if ((pI830->pipeEnabled[0] &&
+ ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
+ (pI830->pipeEnabled[1] &&
+ ((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
+ pI830->planeEnabled[1] = TRUE;
+ }
+ } else {
+ pI830->planeEnabled[0] = TRUE;
+ }
+ if (pI830->planeEnabled[0]) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
+ planeA |= DISPLAY_PLANE_ENABLE;
+ OUTREG(DSPACNTR, planeA);
+ /* flush the change. */
+ temp = INREG(DSPABASE);
+ OUTREG(DSPABASE, temp);
+ }
+ if (pI830->planeEnabled[1]) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n");
+ planeB |= DISPLAY_PLANE_ENABLE;
+ OUTREG(DSPBCNTR, planeB);
+ /* flush the change. */
+ temp = INREG(DSPBADDR);
+ OUTREG(DSPBADDR, temp);
+ }
+ }
+
+ /* XXX Plane C is ignored for now (overlay). */
+
+ /*
+ * Print out the PIPEACONF and PIPEBCONF registers.
+ */
+ temp = INREG(PIPEACONF);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08x\n", temp);
+ if (IS_MOBILE(pI830)) {
+ temp = INREG(PIPEBCONF);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08x\n", temp);
+ }
+
+#if PRINT_MODE_INFO
+ /* Print out some CRTC/display information. */
+ temp = INREG(HTOTAL_A);
+ ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(HBLANK_A);
+ ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(HSYNC_A);
+ ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VTOTAL_A);
+ ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VBLANK_A);
+ ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VSYNC_A);
+ ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(PIPEASRC);
+ ErrorF("Image size: %dx%d (%dx%d)\n",
+ (temp >> 16) & 0x7ff, temp & 0x7ff,
+ (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
+ ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
+ temp = INREG(DSPABASE);
+ ErrorF("Plane A start offset is %d\n", temp);
+ temp = INREG(DSPASTRIDE);
+ ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
+#endif
+
+ for (i = 0; i < MAX_DISPLAY_PIPES; i++) {
+ CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
+ CARD32 basereg = i ? DSPBBASE : DSPABASE;
+
+ if (!pI830->planeEnabled[i])
+ continue;
+
+ temp = INREG(stridereg);
+ if (temp / pI830->cpp != pScrn->displayWidth) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
+ temp / pI830->cpp, pScrn->displayWidth);
+ OUTREG(stridereg, pScrn->displayWidth * pI830->cpp);
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
+ pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
+
+ {
+ int maxBandwidth, bandwidthA, bandwidthB;
+
+ if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80,
+ &maxBandwidth, &bandwidthA, &bandwidthB)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, "
+ "pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n",
+ maxBandwidth, bandwidthA, bandwidthB);
+ }
+ }
+
+ {
+ int ret;
+
+ ret = GetLFPCompMode(pScrn);
+ if (ret != -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "LFP compensation mode: 0x%x\n", ret);
+ }
+ }
+
+#if MODESWITCH_RESET_STATE
+ ResetState(pScrn, TRUE);
+ SetHWOperatingState(pScrn);
+#endif
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled && didLock) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ pI830->LockHeld = 0;
+ }
+#endif
+
+ pScrn->vtSema = TRUE;
+ return TRUE;
+}
+
+static void
+InitRegisterRec(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr i830Reg = &pI830->ModeReg;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ i830Reg->Fence[i] = 0;
+}
+
+/* Famous last words
+ */
+void
+I830PrintErrorState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+ INREG(PGETBL_CTL), INREG(PGE_ERR));
+
+ ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
+
+ ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+ INREG(LP_RING + RING_TAIL),
+ INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+ INREG(LP_RING + RING_LEN), 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", INREG(MEMMODE), INREG(INST_PS));
+
+ ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
+ INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
+}
+
+#ifdef I830DEBUG
+static void
+dump_DSPACNTR(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned int tmp;
+
+ /* Display A Control */
+ tmp = INREG(0x70180);
+ ErrorF("Display A Plane Control Register (0x%.8x)\n", tmp);
+
+ if (tmp & BIT(31))
+ ErrorF(" Display Plane A (Primary) Enable\n");
+ else
+ ErrorF(" Display Plane A (Primary) Disabled\n");
+
+ if (tmp & BIT(30))
+ ErrorF(" Display A pixel data is gamma corrected\n");
+ else
+ ErrorF(" Display A pixel data bypasses gamma correction logic (default)\n");
+
+ switch ((tmp & 0x3c000000) >> 26) { /* bit 29:26 */
+ case 0x00:
+ case 0x01:
+ case 0x03:
+ ErrorF(" Reserved\n");
+ break;
+ case 0x02:
+ ErrorF(" 8-bpp Indexed\n");
+ break;
+ case 0x04:
+ ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n");
+ break;
+ case 0x05:
+ ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n");
+ break;
+ case 0x06:
+ ErrorF(" 32-bit format (X:8:8:8)\n");
+ break;
+ case 0x07:
+ ErrorF(" 32-bit format (8:8:8:8)\n");
+ break;
+ default:
+ ErrorF(" Unknown - Invalid register value maybe?\n");
+ }
+
+ if (tmp & BIT(25))
+ ErrorF(" Stereo Enable\n");
+ else
+ ErrorF(" Stereo Disable\n");
+
+ if (tmp & BIT(24))
+ ErrorF(" Display A, Pipe B Select\n");
+ else
+ ErrorF(" Display A, Pipe A Select\n");
+
+ if (tmp & BIT(22))
+ ErrorF(" Source key is enabled\n");
+ else
+ ErrorF(" Source key is disabled\n");
+
+ switch ((tmp & 0x00300000) >> 20) { /* bit 21:20 */
+ case 0x00:
+ ErrorF(" No line duplication\n");
+ break;
+ case 0x01:
+ ErrorF(" Line/pixel Doubling\n");
+ break;
+ case 0x02:
+ case 0x03:
+ ErrorF(" Reserved\n");
+ break;
+ }
+
+ if (tmp & BIT(18))
+ ErrorF(" Stereo output is high during second image\n");
+ else
+ ErrorF(" Stereo output is high during first image\n");
+}
+
+static void
+dump_DSPBCNTR(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned int tmp;
+
+ /* Display B/Sprite Control */
+ tmp = INREG(0x71180);
+ ErrorF("Display B/Sprite Plane Control Register (0x%.8x)\n", tmp);
+
+ if (tmp & BIT(31))
+ ErrorF(" Display B/Sprite Enable\n");
+ else
+ ErrorF(" Display B/Sprite Disable\n");
+
+ if (tmp & BIT(30))
+ ErrorF(" Display B pixel data is gamma corrected\n");
+ else
+ ErrorF(" Display B pixel data bypasses gamma correction logic (default)\n");
+
+ switch ((tmp & 0x3c000000) >> 26) { /* bit 29:26 */
+ case 0x00:
+ case 0x01:
+ case 0x03:
+ ErrorF(" Reserved\n");
+ break;
+ case 0x02:
+ ErrorF(" 8-bpp Indexed\n");
+ break;
+ case 0x04:
+ ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n");
+ break;
+ case 0x05:
+ ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n");
+ break;
+ case 0x06:
+ ErrorF(" 32-bit format (X:8:8:8)\n");
+ break;
+ case 0x07:
+ ErrorF(" 32-bit format (8:8:8:8)\n");
+ break;
+ default:
+ ErrorF(" Unknown - Invalid register value maybe?\n");
+ }
+
+ if (tmp & BIT(25))
+ ErrorF(" Stereo is enabled and both start addresses are used in a two frame sequence\n");
+ else
+ ErrorF(" Stereo disable and only a single start address is used\n");
+
+ if (tmp & BIT(24))
+ ErrorF(" Display B/Sprite, Pipe B Select\n");
+ else
+ ErrorF(" Display B/Sprite, Pipe A Select\n");
+
+ if (tmp & BIT(22))
+ ErrorF(" Sprite source key is enabled\n");
+ else
+ ErrorF(" Sprite source key is disabled (default)\n");
+
+ switch ((tmp & 0x00300000) >> 20) { /* bit 21:20 */
+ case 0x00:
+ ErrorF(" No line duplication\n");
+ break;
+ case 0x01:
+ ErrorF(" Line/pixel Doubling\n");
+ break;
+ case 0x02:
+ case 0x03:
+ ErrorF(" Reserved\n");
+ break;
+ }
+
+ if (tmp & BIT(18))
+ ErrorF(" Stereo output is high during second image\n");
+ else
+ ErrorF(" Stereo output is high during first image\n");
+
+ if (tmp & BIT(15))
+ ErrorF(" Alpha transfer mode enabled\n");
+ else
+ ErrorF(" Alpha transfer mode disabled\n");
+
+ if (tmp & BIT(0))
+ ErrorF(" Sprite is above overlay\n");
+ else
+ ErrorF(" Sprite is above display A (default)\n");
+}
+
+void
+I830_dump_registers(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned int i;
+
+ ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+
+ dump_DSPACNTR(pScrn);
+ dump_DSPBCNTR(pScrn);
+
+ ErrorF("0x71400 == 0x%.8x\n", INREG(0x71400));
+ ErrorF("0x70008 == 0x%.8x\n", INREG(0x70008));
+ for (i = 0x71410; i <= 0x71428; i += 4)
+ ErrorF("0x%x == 0x%.8x\n", i, INREG(i));
+
+ ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+}
+#endif
+
+static Bool
+I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ I830Ptr pI830;
+ VisualPtr visual;
+#ifdef XF86DRI
+ Bool driDisabled;
+#endif
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI830 = I830PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ pI830->starting = TRUE;
+
+ /*
+ * If we're changing the BIOS's view of the video memory size, do that
+ * first, then re-initialise the VBE information.
+ */
+ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+ SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+ if (!pI830->pVbe)
+ return FALSE;
+ pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+
+ miClearVisualTypes();
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return FALSE;
+ if (pScrn->bitsPerPixel > 8) {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
+ pScrn->rgbBits, TrueColor))
+ return FALSE;
+ } else {
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+ }
+ if (!miSetPixmapDepths())
+ return FALSE;
+
+#ifdef I830_XV
+ pI830->XvEnabled = !pI830->XvDisabled;
+ if (pI830->XvEnabled) {
+ if (pI830->noAccel || pI830->StolenOnly) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
+ "needs 2D accel and AGPGART.\n");
+ pI830->XvEnabled = FALSE;
+ }
+ }
+#else
+ pI830->XvEnabled = FALSE;
+#endif
+
+ I830ResetAllocations(pScrn, 0);
+
+ I830Allocate2DMemory(pScrn, ALLOC_INITIAL);
+
+ if (!pI830->noAccel) {
+ if (pI830->LpRing.mem.Size == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling acceleration because the ring buffer "
+ "allocation failed.\n");
+ pI830->noAccel = TRUE;
+ }
+ }
+
+ if (!pI830->SWCursor) {
+ if (pI830->CursorMem.Size == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling HW cursor because the cursor memory "
+ "allocation failed.\n");
+ pI830->SWCursor = TRUE;
+ }
+ }
+
+#ifdef I830_XV
+ if (pI830->XvEnabled) {
+ if (pI830->noAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
+ "needs 2D acceleration.\n");
+ pI830->XvEnabled = FALSE;
+ }
+ if (pI830->OverlayMem.Physical == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling Xv because the overlay register buffer "
+ "allocation failed.\n");
+ pI830->XvEnabled = FALSE;
+ }
+ }
+#endif
+
+ InitRegisterRec(pScrn);
+
+#ifdef XF86DRI
+ /*
+ * pI830->directRenderingDisabled is set once in PreInit. Reinitialise
+ * pI830->directRenderingEnabled based on it each generation.
+ */
+ pI830->directRenderingEnabled = !pI830->directRenderingDisabled;
+ /*
+ * Setup DRI after visuals have been established, but before fbScreenInit
+ * is called. fbScreenInit will eventually call into the drivers
+ * InitGLXVisuals call back.
+ */
+
+ if (pI830->directRenderingEnabled) {
+ if (pI830->noAccel || pI830->SWCursor || pI830->StolenOnly) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
+ "needs HW cursor, 2D accel and AGPGART.\n");
+ pI830->directRenderingEnabled = FALSE;
+ }
+ }
+
+ driDisabled = !pI830->directRenderingEnabled;
+
+ if (pI830->directRenderingEnabled)
+ pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
+
+ if (pI830->directRenderingEnabled)
+ if (!(pI830->directRenderingEnabled = I830Allocate3DMemory(pScrn, 0)))
+ I830DRICloseScreen(pScreen);
+
+#else
+ pI830->directRenderingEnabled = FALSE;
+#endif
+
+ /*
+ * After the 3D allocations have been done, see if there's any free space
+ * that can be added to the framebuffer allocation.
+ */
+ I830Allocate2DMemory(pScrn, 0);
+
+ DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n");
+ if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool)))
+ return FALSE;
+
+ DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n");
+ if (!I830FixupOffsets(pScrn))
+ return FALSE;
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ I830SetupMemoryTiling(pScrn);
+ pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
+ }
+#endif
+
+ DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
+ if (!I830MapMem(pScrn))
+ return FALSE;
+
+ pScrn->memPhysBase = (unsigned long)pI830->FbBase;
+ pScrn->fbOffset = pI830->FrontBuffer.Start;
+
+ vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
+ vgaHWGetIOBase(hwp);
+ DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
+ if (!vgaHWMapMem(pScrn))
+ return FALSE;
+
+ /* Clear SavedReg */
+ memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg));
+
+ DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n");
+ if (!I830BIOSEnterVT(scrnIndex, 0))
+ return FALSE;
+
+ DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
+ if (!fbScreenInit(pScreen, pI830->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, 0, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+#if 1
+ I830DGAInit(pScreen);
+#endif
+
+ DPRINTF(PFX,
+ "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
+ if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to init memory manager\n");
+ return FALSE;
+ }
+
+ if (!pI830->noAccel) {
+ if (!I830AccelInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware acceleration initialization failed\n");
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!pI830->SWCursor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
+ if (!I830CursorInit(pScreen))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ } else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
+
+ DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
+ if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, 0,
+ CMAP_RELOAD_ON_MODE_SWITCH)) {
+ return FALSE;
+ }
+
+#ifdef DPMSExtension
+ xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0);
+#endif
+
+#ifdef I830_XV
+ /* Init video */
+ if (pI830->XvEnabled)
+ I830InitVideo(pScreen);
+#endif
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
+ }
+#endif
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ pI830->directRenderingOpen = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
+ /* Setup 3D engine */
+ I830EmitInvarientState(pScrn);
+ } else {
+ if (driDisabled)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n");
+ }
+#else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n");
+#endif
+
+ pScreen->SaveScreen = I830BIOSSaveScreen;
+ pI830->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = I830BIOSCloseScreen;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+#if 0
+#ifdef I830DEBUG
+ I830_dump_registers(pScrn);
+#endif
+#endif
+
+ pI830->starting = FALSE;
+ pI830->closing = FALSE;
+ pI830->suspended = FALSE;
+ return TRUE;
+}
+
+static void
+I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn;
+ I830Ptr pI830;
+ vbeInfoPtr pVbe;
+ static int xoffset = 0, yoffset = 0;
+ static int adjustGeneration = -1;
+
+ pScrn = xf86Screens[scrnIndex];
+ pI830 = I830PTR(pScrn);
+ pVbe = pI830->pVbe;
+
+ DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
+ x, xoffset, y, yoffset);
+
+ /* Calculate the offsets once per server generation. */
+ if (adjustGeneration != serverGeneration) {
+ adjustGeneration = serverGeneration;
+ xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
+ yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
+ }
+
+ if (OffsetFrame) {
+ y = (pI830->FbMemBox.y2 - pScrn->currentMode->VDisplay);
+ ErrorF("AdjustFrame: OffsetFrame is set, setting y to %d\n", y);
+ }
+ x += xoffset;
+ y += yoffset;
+#if 0
+ x >>= 4;
+ x <<= 4;
+#endif
+ VBESetDisplayStart(pVbe, x, y, TRUE);
+}
+
+static void
+I830BIOSFreeScreen(int scrnIndex, int flags)
+{
+ I830BIOSFreeRec(xf86Screens[scrnIndex]);
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+}
+
+#ifndef SAVERESTORE_HWSTATE
+#define SAVERESTORE_HWSTATE 0
+#endif
+
+#if SAVERESTORE_HWSTATE
+static void
+SaveHWOperatingState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr save = &pI830->SavedReg;
+
+ DPRINTF(PFX, "SaveHWOperatingState\n");
+
+ return;
+}
+
+static void
+RestoreHWOperatingState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr save = &pI830->SavedReg;
+
+ DPRINTF(PFX, "RestoreHWOperatingState\n");
+
+ return;
+}
+#endif
+
+static void
+I830BIOSLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+#ifdef XF86DRI
+ I830Ptr pI830 = I830PTR(pScrn);
+#endif
+
+ DPRINTF(PFX, "Leave VT\n");
+
+#ifdef XF86DRI
+ if (pI830->directRenderingOpen) {
+ DPRINTF(PFX, "calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI830->LockHeld = 1;
+ }
+#endif
+
+#if SAVERESTORE_HWSTATE
+ if (!pI830->closing)
+ SaveHWOperatingState(pScrn);
+#endif
+
+ ResetState(pScrn, TRUE);
+ RestoreHWState(pScrn);
+ RestoreBIOSMemSize(pScrn);
+ I830UnbindGARTMemory(pScrn);
+}
+
+/*
+ * This gets called when gaining control of the VT, and from ScreenInit().
+ */
+static Bool
+I830BIOSEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ static int SaveGeneration = -1;
+
+ DPRINTF(PFX, "Enter VT\n");
+
+ if (!I830BindGARTMemory(pScrn))
+ return FALSE;
+
+ CheckInheritedState(pScrn);
+ SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+
+ /*
+ * Only save state once per server generation since that's what most
+ * drivers do. Could change this to save state at each VT enter.
+ */
+ if (SaveGeneration != serverGeneration) {
+ SaveGeneration = serverGeneration;
+ SaveHWState(pScrn);
+ }
+ ResetState(pScrn, FALSE);
+ SetHWOperatingState(pScrn);
+
+#if 1
+ /* Clear the framebuffer */
+ memset(pI830->FbBase + pScrn->fbOffset, 0,
+ pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
+#endif
+
+ if (!I830VESASetMode(pScrn, pScrn->currentMode))
+ return FALSE;
+#ifdef I830_XV
+ I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
+#endif
+
+ ResetState(pScrn, TRUE);
+ SetHWOperatingState(pScrn);
+
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+#if SAVERESTORE_HWSTATE
+ RestoreHWOperatingState(pScrn);
+#endif
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ if (!pI830->starting) {
+ I830EmitInvarientState(pScrn);
+ I830RefreshRing(pScrn);
+ I830Sync(pScrn);
+ DO_RING_IDLE();
+
+ DPRINTF(PFX, "calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ }
+ pI830->LockHeld = 0;
+ }
+#endif
+
+ return TRUE;
+}
+
+static Bool
+I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+
+ int _head;
+ int _tail;
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int ret = TRUE;
+
+ DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
+
+ /* Stops head pointer freezes for 845G */
+ if (!pI830->noAccel && (1 || IS_845G(pI830))) {
+ do {
+ _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+ _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK;
+ DELAY(1000);
+ } while (_head != _tail);
+ }
+
+#if 0
+ OffsetFrame = !OffsetFrame;
+ pScrn->AdjustFrame(scrnIndex, 0, 0, 0);
+#endif
+
+#ifndef BINDUNBIND
+#define BINDUNBIND 0
+#endif
+#if BINDUNBIND
+ I830UnbindGARTMemory(pScrn);
+#endif
+#ifdef I830_XV
+ /* Give the video overlay code a chance to see the new mode. */
+ I830VideoSwitchModeBefore(pScrn, mode);
+#endif
+ if (!I830VESASetMode(pScrn, mode))
+ ret = FALSE;
+#ifdef I830_XV
+ /* Give the video overlay code a chance to see the new mode. */
+ I830VideoSwitchModeAfter(pScrn, mode);
+#endif
+#if BINDUNBIND
+ I830BindGARTMemory(pScrn);
+#endif
+
+ return ret;
+}
+
+static Bool
+I830BIOSSaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool on = xf86IsUnblank(mode);
+ CARD32 temp, ctrl, base, i;
+
+ DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
+
+ for (i = 0; i < MAX_DISPLAY_PIPES; i++) {
+ if (i == 0) {
+ ctrl = DSPACNTR;
+ base = DSPABASE;
+ } else {
+ ctrl = DSPBCNTR;
+ base = DSPBADDR;
+ }
+ if (pI830->planeEnabled[i]) {
+ temp = INREG(ctrl);
+ if (on)
+ temp |= DISPLAY_PLANE_ENABLE;
+ else
+ temp &= ~DISPLAY_PLANE_ENABLE;
+ OUTREG(ctrl, temp);
+ /* Flush changes */
+ temp = INREG(base);
+ OUTREG(base, temp);
+ }
+ }
+
+ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
+ if (on)
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ else
+ pI830->CursorInfoRec->HideCursor(pScrn);
+ pI830->cursorOn = TRUE;
+ }
+
+ return TRUE;
+}
+
+/* Use the VBE version when available. */
+static void
+I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+
+ if (xf86LoaderCheckSymbol("VBEDPMSSet")) {
+ VBEDPMSSet(pVbe, PowerManagementMode);
+ } else {
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x4f10;
+ pVbe->pInt10->bx = 0x01;
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ break;
+ case DPMSModeStandby:
+ pVbe->pInt10->bx |= 0x0100;
+ break;
+ case DPMSModeSuspend:
+ pVbe->pInt10->bx |= 0x0200;
+ break;
+ case DPMSModeOff:
+ pVbe->pInt10->bx |= 0x0400;
+ break;
+ }
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ }
+}
+
+static Bool
+I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
+
+ pI830->closing = TRUE;
+#ifdef XF86DRI
+ if (pI830->directRenderingOpen) {
+ pI830->directRenderingOpen = FALSE;
+ I830DRICloseScreen(pScreen);
+ }
+#endif
+
+ if (pScrn->vtSema == TRUE) {
+ I830BIOSLeaveVT(scrnIndex, 0);
+ }
+
+ DPRINTF(PFX, "\nUnmapping memory\n");
+ I830UnmapMem(pScrn);
+ vgaHWUnmapMem(pScrn);
+
+ if (pI830->ScanlineColorExpandBuffers) {
+ xfree(pI830->ScanlineColorExpandBuffers);
+ pI830->ScanlineColorExpandBuffers = 0;
+ }
+
+ if (infoPtr) {
+ if (infoPtr->ScanlineColorExpandBuffers)
+ xfree(infoPtr->ScanlineColorExpandBuffers);
+ XAADestroyInfoRec(infoPtr);
+ pI830->AccelInfoRec = NULL;
+ }
+
+ if (pI830->CursorInfoRec) {
+ xf86DestroyCursorInfoRec(pI830->CursorInfoRec);
+ pI830->CursorInfoRec = 0;
+ }
+
+ xf86GARTCloseScreen(scrnIndex);
+
+ pScrn->vtSema = FALSE;
+ pI830->closing = FALSE;
+ pScreen->CloseScreen = pI830->CloseScreen;
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static int
+I830ValidMode(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;
+}
+
+#ifndef SUSPEND_SLEEP
+#define SUSPEND_SLEEP 0
+#endif
+#ifndef RESUME_SLEEP
+#define RESUME_SLEEP 0
+#endif
+
+/*
+ * This function is only required if we need to do anything differently from
+ * DoApmEvent() in common/xf86PM.c, including if we want to see events other
+ * than suspend/resume.
+ */
+static Bool
+I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo));
+
+ switch(event) {
+ case XF86_APM_SYS_SUSPEND:
+ case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/
+ case XF86_APM_USER_SUSPEND:
+ case XF86_APM_SYS_STANDBY:
+ case XF86_APM_USER_STANDBY:
+ if (!undo && !pI830->suspended) {
+ pScrn->LeaveVT(scrnIndex, 0);
+ pI830->suspended = TRUE;
+ sleep(SUSPEND_SLEEP);
+ } else if (undo && pI830->suspended) {
+ sleep(RESUME_SLEEP);
+ pScrn->EnterVT(scrnIndex, 0);
+ pI830->suspended = FALSE;
+ }
+ break;
+ case XF86_APM_STANDBY_RESUME:
+ case XF86_APM_NORMAL_RESUME:
+ case XF86_APM_CRITICAL_RESUME:
+ if (pI830->suspended) {
+ sleep(RESUME_SLEEP);
+ pScrn->EnterVT(scrnIndex, 0);
+ pI830->suspended = FALSE;
+ /*
+ * Turn the screen saver off when resuming. This seems to be
+ * needed to stop xscreensaver kicking in (when used).
+ *
+ * XXX DoApmEvent() should probably call this just like
+ * xf86VTSwitch() does. Maybe do it here only in 4.2
+ * compatibility mode.
+ */
+ SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
+ }
+ break;
+ default:
+ ErrorF("I830PMEvent: received APM event %d\n", event);
+ }
+ return TRUE;
+}
+
+void
+I830InitpScrn(ScrnInfoPtr pScrn)
+{
+ pScrn->PreInit = I830BIOSPreInit;
+ pScrn->ScreenInit = I830BIOSScreenInit;
+ pScrn->SwitchMode = I830BIOSSwitchMode;
+ pScrn->AdjustFrame = I830BIOSAdjustFrame;
+ pScrn->EnterVT = I830BIOSEnterVT;
+ pScrn->LeaveVT = I830BIOSLeaveVT;
+ pScrn->FreeScreen = I830BIOSFreeScreen;
+ pScrn->ValidMode = I830ValidMode;
+ pScrn->PMEvent = I830PMEvent;
+}
diff --git a/src/i830_memory.c b/src/i830_memory.c
new file mode 100644
index 00000000..16693d4a
--- /dev/null
+++ b/src/i830_memory.c
@@ -0,0 +1,1458 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c,v 1.6 2003/02/08 02:26:56 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright © 2002 by 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 THE COPYRIGHT HOLDERS AND/OR THEIR 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.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+
+#include "i830.h"
+#include "i810_reg.h"
+
+/*
+ * Allocate memory from the given pool. Grow the pool if needed and if
+ * possible.
+ */
+static unsigned long
+AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
+ unsigned long size, unsigned long alignment, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long needed, start, end;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+ if (!result || !pool || !size)
+ return 0;
+
+ /* Calculate how much space is needed. */
+ if (alignment <= GTT_PAGE_SIZE)
+ needed = size;
+ else {
+ if (flags & ALLOCATE_AT_BOTTOM) {
+ start = ROUND_TO(pool->Free.Start, alignment);
+ if (flags & ALIGN_BOTH_ENDS)
+ end = ROUND_TO(start + size, alignment);
+ else
+ end = start + size;
+ needed = end - pool->Free.Start;
+ } else { /* allocate at top */
+ if (flags & ALIGN_BOTH_ENDS)
+ end = ROUND_DOWN_TO(pool->Free.End, alignment);
+ else
+ end = pool->Free.End;
+
+ start = ROUND_DOWN_TO(end - size, alignment);
+ needed = pool->Free.End - start;
+ }
+ }
+ if (needed > pool->Free.Size) {
+ unsigned long extra;
+ /* See if the pool can be grown. */
+ if (pI830->StolenOnly && !dryrun)
+ return 0;
+ extra = needed - pool->Free.Size;
+ extra = ROUND_TO_PAGE(extra);
+ if (extra > pI830->FreeMemory) {
+ if (dryrun)
+ pI830->FreeMemory = extra;
+ else
+ return 0;
+ }
+
+ if (!dryrun && (extra > pI830->MemoryAperture.Size))
+ return 0;
+
+ pool->Free.Size += extra;
+ pool->Free.End += extra;
+ pool->Total.Size += extra;
+ pool->Total.End += extra;
+ pI830->FreeMemory -= extra;
+ pI830->MemoryAperture.Start += extra;
+ pI830->MemoryAperture.Size -= extra;
+ }
+ if (flags & ALLOCATE_AT_BOTTOM) {
+ result->Start = ROUND_TO(pool->Free.Start, alignment);
+ pool->Free.Start += needed;
+ result->End = pool->Free.Start;
+ } else {
+ result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment) -
+ pool->Total.End;
+ result->End = pool->Free.End - pool->Total.End;
+ pool->Free.End -= needed;
+ }
+ pool->Free.Size = pool->Free.End - pool->Free.Start;
+ result->Size = result->End - result->Start;
+ result->Pool = pool;
+ result->Alignment = alignment;
+ return needed;
+}
+
+static unsigned long
+AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, unsigned long size,
+ unsigned long alignment, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long start, end;
+ unsigned long newApStart, newApEnd;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+ if (!result || !size)
+ return 0;
+
+ if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "AllocFromAGP(): can't allocate from "
+ "bottom when there is stolen memory\n");
+ return 0;
+ }
+
+ if (size > pI830->FreeMemory) {
+ if (dryrun)
+ pI830->FreeMemory = size;
+ else
+ return 0;
+ }
+
+ /* Calculate offset */
+ if (flags & ALLOCATE_AT_BOTTOM) {
+ start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
+ if (flags & ALIGN_BOTH_ENDS)
+ end = ROUND_TO(start + size, alignment);
+ else
+ end = start + size;
+ newApStart = end;
+ newApEnd = pI830->MemoryAperture.End;
+ } else {
+ if (flags & ALIGN_BOTH_ENDS)
+ end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
+ else
+ end = pI830->MemoryAperture.End;
+ start = ROUND_DOWN_TO(end - size, alignment);
+ newApStart = pI830->MemoryAperture.Start;
+ newApEnd = start;
+ }
+
+ if (!dryrun) {
+ if (newApStart > newApEnd)
+ return 0;
+
+ if (flags & NEED_PHYSICAL_ADDR) {
+ result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
+ &(result->Physical));
+ } else {
+ result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
+ }
+ if (result->Key == -1)
+ return 0;
+ }
+
+ pI830->allocatedMemory += size;
+ pI830->MemoryAperture.Start = newApStart;
+ pI830->MemoryAperture.End = newApEnd;
+ pI830->MemoryAperture.Size = newApEnd - newApStart;
+ pI830->FreeMemory -= size;
+ result->Start = start;
+ result->End = start + size;
+ result->Size = size;
+ result->Offset = start;
+ result->Alignment = alignment;
+ result->Pool = NULL;
+
+ return size;
+}
+
+
+unsigned long
+I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
+ unsigned long size, unsigned long alignment, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+
+ if (!result)
+ return 0;
+
+ /* Make sure these are initialised. */
+ result->Size = 0;
+ result->Key = -1;
+
+ if (!size) {
+ return 0;
+ }
+
+ switch (flags & FROM_MASK) {
+ case FROM_POOL_ONLY:
+ return AllocFromPool(pScrn, result, pool, size, alignment, flags);
+ case FROM_NEW_ONLY:
+ if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0)))
+ return 0;
+ return AllocFromAGP(pScrn, result, size, alignment, flags);
+ case FROM_ANYWHERE:
+ if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) ||
+ (flags & NEED_PHYSICAL_ADDR))
+ return AllocFromAGP(pScrn, result, size, alignment, flags);
+ else
+ return AllocFromPool(pScrn, result, pool, size, alignment, flags);
+ default:
+ /* Shouldn't happen. */
+ return 0;
+ }
+}
+
+static Bool
+AllocateRingBuffer(ScrnInfoPtr pScrn, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long size, alloced;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+ int verbosity = dryrun ? 4 : 1;
+ const char *s = dryrun ? "[dryrun] " : "";
+
+ /* Clear ring buffer info */
+ memset(&(pI830->LpRing), 0, sizeof(pI830->LpRing));
+ pI830->LpRing.mem.Key = -1;
+
+ if (pI830->noAccel)
+ return TRUE;
+
+ /* Ring buffer */
+ size = PRIMARY_RINGBUFFER_SIZE;
+ if (flags & FORCE_LOW)
+ flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM;
+ else
+ flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP;
+
+ alloced = I830AllocVidMem(pScrn, &(pI830->LpRing.mem),
+ &(pI830->StolenPool), size,
+ GTT_PAGE_SIZE, flags);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate Ring Buffer space\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the ring buffer at 0x%x\n", s,
+ alloced / 1024, pI830->LpRing.mem.Start);
+ pI830->LpRing.tail_mask = pI830->LpRing.mem.Size - 1;
+ return TRUE;
+}
+
+#ifdef I830_XV
+/*
+ * Note, the FORCE_LOW flag is currently not used or supported.
+ */
+static Bool
+AllocateOverlay(ScrnInfoPtr pScrn, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long size, alloced;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+ int verbosity = dryrun ? 4 : 1;
+ const char *s = dryrun ? "[dryrun] " : "";
+
+ /* Clear overlay info */
+ memset(&(pI830->OverlayMem), 0, sizeof(pI830->OverlayMem));
+ pI830->OverlayMem.Key = -1;
+
+ if (!pI830->XvEnabled)
+ return TRUE;
+
+ /*
+ * The overlay register space needs a physical address in
+ * system memory. We get this from the agpgart module using
+ * a special memory type.
+ */
+
+ size = OVERLAY_SIZE;
+ if (flags & FORCE_LOW)
+ flags |= FROM_POOL_ONLY | ALLOCATE_AT_BOTTOM | NEED_PHYSICAL_ADDR;
+ else
+ flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR;
+
+ alloced = I830AllocVidMem(pScrn, &(pI830->OverlayMem),
+ &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags);
+
+ /*
+ * XXX For testing only. Don't enable this unless you know how to set
+ * physBase.
+ */
+ if (flags & FORCE_LOW) {
+ ErrorF("AllocateOverlay() doesn't support setting FORCE_LOW\n");
+ return FALSE;
+ }
+
+ if (!dryrun && (alloced < size)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate Overlay register space.\n");
+ /* This failure isn't fatal. */
+ } else {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for Overlay registers at 0x%x "
+ "(0x%08x).\n", s,
+ alloced / 1024, pI830->OverlayMem.Start,
+ pI830->OverlayMem.Physical);
+ }
+ return TRUE;
+}
+#endif
+
+static unsigned long
+GetFreeSpace(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long extra = 0;
+
+ /* First check for free space in StolenPool. */
+ if (pI830->StolenPool.Free.Size > 0)
+ extra = pI830->StolenPool.Free.Size;
+ /* Next check for unallocated space. */
+ if (pI830->FreeMemory > 0)
+ extra += pI830->FreeMemory;
+
+ return extra;
+}
+
+static Bool
+IsTileable(int pitch)
+{
+ /*
+ * Allow tiling for pitches that are a power of 2 multiple of 128 bytes,
+ * up to 64 * 128 (= 8192) bytes.
+ */
+ switch (pitch) {
+ case 128 * 1:
+ case 128 * 2:
+ case 128 * 4:
+ case 128 * 8:
+ case 128 * 16:
+ case 128 * 32:
+ case 128 * 64:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*
+ * Allocate memory for 2D operation. This includes the (front) framebuffer,
+ * ring buffer, scratch memory, HW cursor.
+ */
+
+Bool
+I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long size, alloced;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+ int verbosity = dryrun ? 4 : 1;
+ const char *s = dryrun ? "[dryrun] " : "";
+ Bool tileable;
+ int align, alignflags;
+
+ DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
+ BOOLTOSTRING(flags & ALLOC_INITIAL));
+
+ if (!pI830->StolenOnly &&
+ (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
+ if (!dryrun) {
+ 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;
+ }
+
+
+ /*
+ * The I830 is slightly different from the I830/I815, it has no
+ * dcache and it has stolen memory by default in its gtt. All
+ * additional memory must go after it.
+ */
+
+ DPRINTF(PFX,
+ "size == %luk (%lu bytes == pScrn->videoRam)\n"
+ "pI830->StolenSize == %luk (%lu bytes)\n",
+ pScrn->videoRam, pScrn->videoRam * 1024,
+ pI830->StolenPool.Free.Size / 1024,
+ pI830->StolenPool.Free.Size);
+
+ if (flags & ALLOC_INITIAL) {
+ unsigned long minspace, avail, lineSize;
+ int cacheLines, maxCacheLines;
+
+ if (pI830->NeedRingBufferLow)
+ AllocateRingBuffer(pScrn, flags | FORCE_LOW);
+
+ /* Clear everything first. */
+ memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox));
+ memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
+ pI830->FrontBuffer.Key = -1;
+
+ pI830->FbMemBox.x1 = 0;
+ pI830->FbMemBox.x2 = pScrn->displayWidth;
+ pI830->FbMemBox.y1 = 0;
+ pI830->FbMemBox.y2 = pScrn->virtualY;
+
+ /*
+ * Calculate how much framebuffer memory to allocate. For the
+ * initial allocation, calculate a reasonable minimum. This is
+ * enough for the virtual screen size, plus some pixmap cache
+ * space.
+ */
+
+ lineSize = pScrn->displayWidth * pI830->cpp;
+ minspace = lineSize * pScrn->virtualY;
+ avail = pScrn->videoRam * 1024;
+ maxCacheLines = (avail - minspace) / lineSize;
+ /* This shouldn't happen. */
+ if (maxCacheLines < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal Error: "
+ "maxCacheLines < 0 in I830Allocate2DMemory()\n");
+ maxCacheLines = 0;
+ }
+ if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY))
+ maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY;
+
+ if (pI830->CacheLines >= 0) {
+ cacheLines = pI830->CacheLines;
+ } else {
+#if 1
+ /* Make sure there is enough for two DVD sized YUV buffers */
+ cacheLines = (pScrn->depth == 24) ? 256 : 384;
+ if (pScrn->displayWidth <= 1024)
+ cacheLines *= 2;
+#else
+ /*
+ * Make sure there is enough for two DVD sized YUV buffers.
+ * Make that 1.5MB, which is around what was allocated with
+ * the old algorithm
+ */
+ cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth;
+#endif
+ }
+ if (cacheLines > maxCacheLines)
+ cacheLines = maxCacheLines;
+
+ pI830->FbMemBox.y2 += cacheLines;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocating at least %d scanlines for pixmap cache\n",
+ s, cacheLines);
+
+ tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+ IsTileable(pScrn->displayWidth * pI830->cpp);
+ if (tileable) {
+ align = KB(512);
+ alignflags = ALIGN_BOTH_ENDS;
+ } else {
+ align = KB(64);
+ alignflags = 0;
+ }
+
+ size = lineSize * (pScrn->virtualY + cacheLines);
+ size = ROUND_TO_PAGE(size);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sInitial framebuffer allocation size: %d kByte\n", s,
+ size / 1024);
+ alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+ &(pI830->StolenPool), size, align,
+ flags | alignflags |
+ FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate framebuffer.\n");
+ }
+ return FALSE;
+ }
+ } else {
+ unsigned long lineSize;
+ unsigned long extra = 0;
+ unsigned long maxFb = 0;
+
+ /*
+ * XXX Need to "free" up any 3D allocations if the DRI ended up
+ * and make them available for 2D. The best way to do this would
+ * be position all of those regions contiguously at the end of the
+ * StolenPool.
+ */
+ extra = GetFreeSpace(pScrn);
+
+ if (extra == 0)
+ return TRUE;
+
+ maxFb = pI830->FrontBuffer.Size + extra;
+ lineSize = pScrn->displayWidth * pI830->cpp;
+ maxFb = ROUND_DOWN_TO(maxFb, lineSize);
+ if (maxFb > lineSize * MAX_DISPLAY_HEIGHT)
+ maxFb = lineSize * MAX_DISPLAY_HEIGHT;
+ if (maxFb > pI830->FrontBuffer.Size) {
+ unsigned long oldsize;
+ /*
+ * Sanity check -- the fb should be the last thing allocated at
+ * the bottom of the stolen pool.
+ */
+ if (pI830->StolenPool.Free.Start != pI830->FrontBuffer.End) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal error in I830Allocate2DMemory():\n\t"
+ "Framebuffer isn't the last allocation at the bottom"
+ " of StolenPool\n\t(%x != %x).\n",
+ pI830->FrontBuffer.End,
+ pI830->StolenPool.Free.Start);
+ return FALSE;
+ }
+ /*
+ * XXX Maybe should have a "Free" function. This should be
+ * the only place where a region is resized, and we know that
+ * the fb is always at the bottom of the aperture/stolen pool,
+ * and is the only region that is allocated bottom-up.
+ * Allowing for more general realloction would require a smarter
+ * allocation system.
+ */
+ oldsize = pI830->FrontBuffer.Size;
+ pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size;
+ pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sUpdated framebuffer allocation size from %d "
+ "to %d kByte\n", s, oldsize / 1024, maxFb / 1024);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sUpdated pixmap cache from %d scanlines to %d "
+ "scanlines\n", s,
+ oldsize / lineSize - pScrn->virtualY,
+ maxFb / lineSize - pScrn->virtualY);
+ pI830->FbMemBox.y2 = maxFb / lineSize;
+ tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
+ IsTileable(pScrn->displayWidth * pI830->cpp);
+ if (tileable) {
+ align = KB(512);
+ alignflags = ALIGN_BOTH_ENDS;
+ } else {
+ align = KB(64);
+ alignflags = 0;
+ }
+ alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+ &(pI830->StolenPool), maxFb, align,
+ flags | alignflags |
+ FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+ if (alloced < maxFb) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to re-allocate framebuffer\n");
+ }
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+
+#if REMAP_RESERVED
+ /*
+ * Allocate a dummy page to pass when attempting to rebind the
+ * pre-allocated region.
+ */
+ if (!dryrun) {
+ memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
+ pI830->Dummy.Key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
+ pI830->Dummy.Offset = 0;
+ }
+#endif
+
+ /* Clear cursor info */
+ memset(&(pI830->CursorMem), 0, sizeof(pI830->CursorMem));
+ pI830->CursorMem.Key = -1;
+
+ if (!pI830->SWCursor) {
+ int cursFlags = 0;
+ /*
+ * Mouse cursor -- The i810-i830 need a physical address in system
+ * memory from which to upload the cursor. We get this from
+ * the agpgart module using a special memory type.
+ */
+
+ size = HWCURSOR_SIZE;
+ cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+ if (pI830->CursorNeedsPhysical)
+ cursFlags |= NEED_PHYSICAL_ADDR;
+
+ alloced = I830AllocVidMem(pScrn, &(pI830->CursorMem),
+ &(pI830->StolenPool), size,
+ GTT_PAGE_SIZE, flags | cursFlags);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate HW cursor space.\n");
+ }
+ } else {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for HW cursor at 0x%x", s,
+ alloced / 1024, pI830->CursorMem.Start);
+ if (pI830->CursorNeedsPhysical)
+ xf86ErrorFVerb(verbosity, " (0x%08x)", pI830->CursorMem.Physical);
+ xf86ErrorFVerb(verbosity, "\n");
+ }
+ }
+
+#ifdef I830_XV
+ AllocateOverlay(pScrn, flags);
+#endif
+
+ if (!pI830->NeedRingBufferLow)
+ AllocateRingBuffer(pScrn, flags);
+
+ /* Clear scratch info */
+ memset(&(pI830->Scratch), 0, sizeof(pI830->Scratch));
+ pI830->Scratch.Key = -1;
+
+ if (!pI830->noAccel) {
+ size = MAX_SCRATCH_BUFFER_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->Scratch), &(pI830->StolenPool),
+ size, GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ if (alloced < size) {
+ size = MIN_SCRATCH_BUFFER_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->Scratch),
+ &(pI830->StolenPool), size,
+ GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ }
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate scratch buffer space\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the scratch buffer at 0x%x\n", s,
+ alloced / 1024, pI830->Scratch.Start);
+ }
+ return TRUE;
+}
+
+#ifndef ALLOCATE_ALL_BIOSMEM
+#define ALLOCATE_ALL_BIOSMEM 1
+#endif
+
+void
+I830ResetAllocations(ScrnInfoPtr pScrn, const int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->MemoryAperture.Start = pI830->StolenMemory.End;
+ pI830->MemoryAperture.End = pI830->FbMapSize;
+ pI830->MemoryAperture.Size = pI830->FbMapSize - pI830->StolenMemory.Size;
+ pI830->StolenPool.Fixed = pI830->StolenMemory;
+ pI830->StolenPool.Total = pI830->StolenMemory;
+#if ALLOCATE_ALL_BIOSMEM
+ if (pI830->overrideBIOSMemSize &&
+ pI830->BIOSMemorySize > pI830->StolenMemory.Size) {
+ pI830->StolenPool.Total.End = pI830->BIOSMemorySize;
+ pI830->StolenPool.Total.Size = pI830->BIOSMemorySize;
+ }
+#endif
+ pI830->StolenPool.Free = pI830->StolenPool.Total;
+ pI830->FreeMemory = pI830->TotalVideoRam - pI830->StolenPool.Total.Size;
+ pI830->allocatedMemory = 0;
+}
+
+long
+I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long allocated;
+
+ allocated = pI830->StolenPool.Total.Size + pI830->allocatedMemory;
+ if (allocated > pI830->TotalVideoRam)
+ return allocated - pI830->TotalVideoRam;
+ else
+ return 0;
+}
+
+#ifdef XF86DRI
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+ unsigned long i;
+
+ for (i = KB(512); i < size; i <<= 1)
+ ;
+
+ if (i > MB(64))
+ i = MB(64);
+
+ return i;
+}
+
+static unsigned int
+myLog2(unsigned int n)
+{
+ unsigned int log2 = 1;
+
+ while (n > 1) {
+ n >>= 1;
+ log2++;
+ }
+ return log2;
+}
+
+Bool
+I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long size, alloced, align = 0;
+ int i;
+ Bool tileable;
+ Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+ int verbosity = dryrun ? 4 : 1;
+ const char *s = dryrun ? "[dryrun] " : "";
+ int lines;
+
+ DPRINTF(PFX, "I830Allocate3DMemory\n");
+
+ /* Back Buffer */
+ memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
+ pI830->BackBuffer.Key = -1;
+ tileable = !(flags & ALLOC_NO_TILING) &&
+ IsTileable(pScrn->displayWidth * pI830->cpp);
+ if (tileable) {
+ /* Make the height a multiple of the tile height (16) */
+ lines = (pScrn->virtualY + 15) / 16 * 16;
+ } else {
+ lines = pScrn->virtualY;
+ }
+
+ size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
+ /*
+ * Try to allocate on the best tile-friendly boundaries.
+ */
+ alloced = 0;
+ if (tileable) {
+ align = GetBestTileAlignment(size);
+ for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) {
+ alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
+ &(pI830->StolenPool), size, align,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+ ALIGN_BOTH_ENDS);
+ if (alloced >= size)
+ break;
+ }
+ }
+ if (alloced < size) {
+ /* Give up on trying to tile */
+ tileable = FALSE;
+ size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
+ align = GTT_PAGE_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
+ &(pI830->StolenPool), size, align,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ }
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate back buffer space.\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the back buffer at 0x%x.\n", s,
+ alloced / 1024, pI830->BackBuffer.Start);
+
+ /* Depth Buffer -- same size as the back buffer */
+ memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
+ pI830->DepthBuffer.Key = -1;
+ /*
+ * Try to allocate on the best tile-friendly boundaries.
+ */
+ alloced = 0;
+ if (tileable) {
+ /* Start with the previous align value. */
+ for (; align >= KB(512); align >>= 1) {
+ alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
+ &(pI830->StolenPool), size, align,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+ ALIGN_BOTH_ENDS);
+ if (alloced >= size)
+ break;
+ }
+ }
+ if (alloced < size) {
+ /* Give up on trying to tile */
+ tileable = FALSE;
+ size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
+ align = GTT_PAGE_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
+ &(pI830->StolenPool), size, align,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ }
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate depth buffer space.\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the depth buffer at 0x%x.\n", s,
+ alloced / 1024, pI830->DepthBuffer.Start);
+
+ /* Space for logical context. 32k is fine for right now. */
+ memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+ pI830->ContextMem.Key = -1;
+ size = KB(32);
+ alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
+ &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate logical context space.\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the logical context at 0x%x.\n", s,
+ alloced / 1024, pI830->ContextMem.Start);
+
+ /*
+ * Space for DMA buffers, only if there's enough free for at least 1MB
+ * of texture space.
+ */
+ memset(&(pI830->BufferMem), 0, sizeof(pI830->BufferMem));
+ pI830->BufferMem.Key = -1;
+ /* This should already be a page multiple */
+ size = I830_DMA_BUF_NR * I830_DMA_BUF_SZ;
+ if (dryrun || (GetFreeSpace(pScrn) >= size + MB(1))) {
+ alloced = I830AllocVidMem(pScrn, &(pI830->BufferMem),
+ &(pI830->StolenPool), size,
+ GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate DMA buffer space.\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for the DMA buffers at 0x%x.\n", s,
+ alloced / 1024, pI830->BufferMem.Start);
+ } else {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Not enough free space for DMA buffers.\n");
+ }
+ return FALSE;
+ }
+
+ /* Allocate the remaining space for textures. */
+ memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
+ pI830->TexMem.Key = -1;
+ size = GetFreeSpace(pScrn);
+ if (dryrun && (size < MB(1)))
+ size = MB(1);
+ i = myLog2(size / I830_NR_TEX_REGIONS);
+ if (i < I830_LOG_MIN_TEX_REGION_SIZE)
+ i = I830_LOG_MIN_TEX_REGION_SIZE;
+ pI830->TexGranularity = i;
+ /* Truncate size */
+ size >>= i;
+ size <<= i;
+ if (size < KB(512)) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Less than %d kBytes for texture space.\n", size / 1024);
+ }
+ return FALSE;
+ }
+ alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
+ &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate texture space.\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %d kB for textures at 0x%x\n", s,
+ alloced / 1024, pI830->TexMem.Start);
+
+ return TRUE;
+}
+#endif
+
+/* Allocate pool space that isn't pre-allocated */
+Bool
+I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830DoPoolAllocation\n");
+
+ if (!pool)
+ return FALSE;
+
+ /*
+ * Sanity check: there shouldn't be an allocation required when
+ * there is only stolen memory.
+ */
+ if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I830DoPoolAllocation(): pool size is greater than the "
+ "preallocated size,\n\t"
+ "and there is no allocatable memory.\n");
+ return FALSE;
+ }
+
+ if (pool->Total.Size > pool->Fixed.Size) {
+ pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
+ pool->Allocated.Key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, pool->Allocated.Size,
+ 0, NULL);
+ if (pool->Allocated.Key == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
+ return FALSE;
+ }
+ pool->Allocated.Start = pool->Fixed.End;
+ pool->Allocated.End = pool->Total.Size;
+ pool->Allocated.Offset = pool->Allocated.Start;
+ } else
+ pool->Allocated.Key = -1;
+ return TRUE;
+}
+
+static unsigned long topOfMem = 0;
+
+/*
+ * These modify the way memory is positioned within the aperture.
+ *
+ * By default, memory allocated from the bottom or specifically within
+ * the pool at the bottom gets allocated from the "stolen pool", which is
+ * actually the stolen memory plus any extra allocated to make it a larger
+ * contiguous region. Memory allocated from the AGP is allocated top-down
+ * from the end of the aperture space. Memory allocated "from top" defaults
+ * to AGP if there is enough "free space". The total allocation (stolen +
+ * extra) doesn't exceed the orignal pScrn->videoRam amount (this isn't true
+ * when memory allocated from AGP gets moved into the pool by one of the
+ * following options.
+ *
+ * XXX Write a better description.
+ *
+ */
+#define PACK_RANGES 0
+#define POOL_RANGES 0
+
+static Bool
+FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
+{
+#if POOL_RANGES
+ I830Ptr pI830 = I830PTR(pScrn);
+#endif
+
+ if (!mem)
+ return FALSE;
+
+ if (mem->Pool && mem->Key == -1 && mem->Start < 0) {
+ mem->Start = mem->Pool->Total.End + mem->Start;
+ mem->End = mem->Start + mem->Size;
+ }
+#if PACK_RANGES
+ /*
+ * Map AGP-allocated areas at the top of the stolen area, resulting in
+ * a contiguous region in the aperture. Normally most AGP-allocated areas
+ * will be at the top of the aperture, making alignment requirements
+ * easier to achieve. This optin is primarily for debugging purposes,
+ * and using this option can break any special alignment requirements.
+ */
+ if (!mem->Pool && mem->Start != 0 && mem->Key != -1 && mem->Physical == 0 &&
+ mem->Offset != 0) {
+ long diff;
+ if (mem->Offset != mem->Start)
+ ErrorF("mem %p, Offset != Start\n", mem);
+ diff = mem->Offset - topOfMem;
+ mem->Start -= diff;
+ mem->End -= diff;
+ mem->Offset -= diff;
+ topOfMem += mem->Size;
+ }
+#elif POOL_RANGES
+ /*
+ * Move AGP-allocated regions (that don't need a physical address) into
+ * the pre-allocated pool when there's enough space to do so. Note: the
+ * AGP-allocated areas aren't freed. This option is primarily for
+ * debugging purposes, and using it can break any special alignment
+ * requirements.
+ */
+ if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End &&
+ mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 &&
+ pI830->StolenPool.Free.Size >= mem->Size) {
+ long diff;
+ if (mem->Offset != mem->Start)
+ ErrorF("mem %p, Offset != Start\n", mem);
+ diff = mem->Offset - pI830->StolenPool.Free.Start;
+ mem->Start -= diff;
+ mem->End -= diff;
+ mem->Offset -= diff;
+ mem->Key = -1;
+ pI830->StolenPool.Free.Start += mem->Size;
+ pI830->StolenPool.Free.Size -= mem->Size;
+ }
+#endif
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%p: Memory at offset 0x%08x, size %d kBytes\n", mem,
+ mem->Start, mem->Size / 1024);
+ return TRUE;
+}
+
+Bool
+I830FixupOffsets(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830FixupOffsets\n");
+
+ topOfMem = pI830->StolenPool.Total.End;
+ FixOffset(pScrn, &(pI830->FrontBuffer));
+ FixOffset(pScrn, &(pI830->CursorMem));
+ FixOffset(pScrn, &(pI830->LpRing.mem));
+ FixOffset(pScrn, &(pI830->Scratch));
+#ifdef I830_XV
+ if (pI830->XvEnabled) {
+ FixOffset(pScrn, &(pI830->OverlayMem));
+ }
+#endif
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ FixOffset(pScrn, &(pI830->BackBuffer));
+ FixOffset(pScrn, &(pI830->DepthBuffer));
+ FixOffset(pScrn, &(pI830->ContextMem));
+ FixOffset(pScrn, &(pI830->BufferMem));
+ FixOffset(pScrn, &(pI830->TexMem));
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef XF86DRI
+/* 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'.
+ */
+static void
+SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch,
+ unsigned int size)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr i830Reg = &pI830->ModeReg;
+ CARD32 val;
+ CARD32 fence_mask = 0;
+
+ DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n",
+ nr, start, pitch, size / 1024);
+
+ if (nr < 0 || nr > 7) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: fence %d out of range\n");
+ return;
+ }
+
+ i830Reg->Fence[nr] = 0;
+
+ fence_mask = ~I830_FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: start (0x%08x) is not 512k aligned\n",
+ nr, start);
+ return;
+ }
+
+ if (start % size) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+ nr, start, size / 1024);
+ return;
+ }
+
+ if (pitch & 127) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+ 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;
+ case MB(64):
+ val |= FENCE_SIZE_64M;
+ break;
+ default:
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ 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;
+ case 64:
+ val |= FENCE_PITCH_64;
+ break;
+ default:
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+ return;
+ }
+
+ i830Reg->Fence[nr] = val;
+}
+
+static Bool
+MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int pitch, ntiles, i;
+ static int nextTile = 0;
+ static int tileGeneration = -1;
+
+#if 0
+ /* Hack to "improve" the alignment of the front buffer.
+ */
+ while (!(pMem->Start & ~pMem->Alignment) && pMem->Alignment < 0x00400000 )
+ pMem->Alignment <<= 1;
+#endif
+
+ if (tileGeneration != serverGeneration) {
+ tileGeneration = serverGeneration;
+ nextTile = 0;
+ }
+
+ pitch = pScrn->displayWidth * pI830->cpp;
+ /*
+ * Simply try to break the region up into at most four pieces of size
+ * equal to the alignment.
+ */
+ ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+ if (ntiles >= 4) {
+ return FALSE;
+ }
+
+ for (i = 0; i < ntiles; i++, nextTile++) {
+ SetFence(pScrn, nextTile, pMem->Start + i * pMem->Alignment,
+ pitch, pMem->Alignment);
+ }
+ return TRUE;
+}
+
+void
+I830SetupMemoryTiling(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* We currently only attempt to tile the back and depth buffers. */
+ if (!pI830->directRenderingEnabled)
+ return;
+
+ if (!IsTileable(pScrn->displayWidth * pI830->cpp)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "I830SetupMemoryTiling: Not tileable 0x%x\n",
+ pScrn->displayWidth * pI830->cpp);
+ pI830->allowPageFlip = FALSE;
+ return;
+ }
+
+ if (pI830->allowPageFlip) {
+ if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(pScrn, &(pI830->FrontBuffer))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Activating tiled memory for the FRONT buffer\n");
+ } else {
+ pI830->allowPageFlip = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MakeTiles failed for the FRONT buffer\n");
+ }
+ } else {
+ pI830->allowPageFlip = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Alignment bad for the FRONT buffer\n");
+ }
+ }
+
+ /*
+ * We tried to get the best alignment during the allocation. Check
+ * the alignment values to tell. If well-aligned allocations were
+ * successful, the address range reserved is a multiple of the align
+ * value.
+ */
+ if (pI830->BackBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(pScrn, &(pI830->BackBuffer))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Activating tiled memory for the back buffer.\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MakeTiles failed for the back buffer.\n");
+ pI830->allowPageFlip = FALSE;
+ }
+ }
+
+ if (pI830->DepthBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(pScrn, &(pI830->DepthBuffer))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Activating tiled memory for the depth buffer.\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "MakeTiles failed for the back buffer.\n");
+ }
+ }
+
+}
+#endif /* XF86DRI */
+
+static Bool
+BindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
+{
+ if (!mem)
+ return FALSE;
+
+ if (mem->Key == -1)
+ return TRUE;
+
+ return xf86BindGARTMemory(pScrn->scrnIndex, mem->Key, mem->Offset);
+}
+
+Bool
+I830BindGARTMemory(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX,
+ "I830BindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+ BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
+
+ if (pI830->StolenOnly == TRUE)
+ return TRUE;
+
+ if (xf86AgpGARTSupported() && !pI830->GttBound) {
+ if (!xf86AcquireGART(pScrn->scrnIndex))
+ return FALSE;
+
+#if REMAP_RESERVED
+ /* Rebind the pre-allocated region. */
+ BindMemRange(pScrn, &(pI830->Dummy));
+#endif
+
+ if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->CursorMem)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->LpRing.mem)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->Scratch)))
+ return FALSE;
+#ifdef I830_XV
+ if (!BindMemRange(pScrn, &(pI830->OverlayMem)))
+ return FALSE;
+#endif
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->ContextMem)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->BufferMem)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->TexMem)))
+ return FALSE;
+ }
+#endif
+ pI830->GttBound = 1;
+ }
+
+ return TRUE;
+}
+
+static Bool
+UnbindMemRange(ScrnInfoPtr pScrn, I830MemRange *mem)
+{
+ if (!mem)
+ return FALSE;
+
+ if (mem->Key == -1)
+ return TRUE;
+
+ return xf86UnbindGARTMemory(pScrn->scrnIndex, mem->Key);
+}
+
+
+Bool
+I830UnbindGARTMemory(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX,
+ "I830UnbindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+ BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
+
+ if (pI830->StolenOnly == TRUE)
+ return TRUE;
+
+ if (xf86AgpGARTSupported() && pI830->GttBound) {
+
+#if REMAP_RESERVED
+ /* "unbind" the pre-allocated region. */
+ UnbindMemRange(pScrn, &(pI830->Dummy));
+#endif
+
+ if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->CursorMem)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->LpRing.mem)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
+ return FALSE;
+#ifdef I830_XV
+ if (!UnbindMemRange(pScrn, &(pI830->OverlayMem)))
+ return FALSE;
+#endif
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->BufferMem)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->TexMem)))
+ return FALSE;
+ }
+#endif
+ if (!xf86ReleaseGART(pScrn->scrnIndex))
+ return FALSE;
+
+ pI830->GttBound = 0;
+ }
+
+ return TRUE;
+}
+
+long
+I830CheckAvailableMemory(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: %d kB available\n",
+ "I830CheckAvailableMemory", maxPages * 4);
+
+ return maxPages * 4;
+}
diff --git a/src/i830_video.c b/src/i830_video.c
new file mode 100644
index 00000000..25f9716b
--- /dev/null
+++ b/src/i830_video.c
@@ -0,0 +1,1840 @@
+#define VIDEO_DEBUG 0
+/***************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c,v 1.6 2003/02/06 04:18:05 dawes Exp $ */
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * i830_video.c: i830/i845 Xv driver.
+ *
+ * Copyright © 2002 by Alan Hourihane and David Dawes
+ *
+ * Authors:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ * David Dawes <dawes@tungstengraphics.com>
+ *
+ * Derived from i810 Xv driver:
+ *
+ * Authors of i810 code:
+ * Jonathan Bian <jonathan.bian@intel.com>
+ * Offscreen Images:
+ * Matt Sottek <matthew.j.sottek@intel.com>
+ */
+
+/*
+ * XXX Could support more formats.
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86fbman.h"
+#include "regionstr.h"
+
+#include "i830.h"
+#include "xf86xv.h"
+#include "Xv.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#ifndef USE_USLEEP_FOR_VIDEO
+#define USE_USLEEP_FOR_VIDEO 0
+#endif
+
+#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 I830InitOffscreenImages(ScreenPtr);
+
+static XF86VideoAdaptorPtr I830SetupImageVideo(ScreenPtr);
+static void I830StopVideo(ScrnInfoPtr, pointer, Bool);
+static int I830SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
+static void I830QueryBestSize(ScrnInfoPtr, Bool,
+ short, short, short, short, unsigned int *,
+ unsigned int *, pointer);
+static int I830PutImage(ScrnInfoPtr, short, short, short, short, short, short,
+ short, short, int, unsigned char *, short, short,
+ Bool, RegionPtr, pointer);
+static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
+ unsigned short *, int *, int *);
+
+static void I830BlockHandler(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_MAX_HEIGHT 1080
+#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
+
+#if !VIDEO_DEBUG
+#define ErrorF Edummy
+static void
+Edummy(const char *dummy, ...)
+{
+}
+#endif
+
+/*
+ * This is more or less the correct way to initalise, update, and shut down
+ * the overlay. Note OVERLAY_OFF should be used only after disabling the
+ * overlay in OCMD and calling OVERLAY_UPDATE.
+ *
+ * XXX Need to make sure that the overlay engine is cleanly shutdown in
+ * all modes of server exit.
+ */
+
+#define OVERLAY_UPDATE \
+ do { \
+ BEGIN_LP_RING(6); \
+ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \
+ OUT_RING(MI_NOOP); \
+ if (!pI830->overlayOn) { \
+ OUT_RING(MI_NOOP); \
+ OUT_RING(MI_NOOP); \
+ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON); \
+ ErrorF("Overlay goes from off to on\n"); \
+ pI830->overlayOn = TRUE; \
+ } else { \
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \
+ OUT_RING(MI_NOOP); \
+ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \
+ } \
+ OUT_RING(pI830->OverlayMem.Physical | 1); \
+ ADVANCE_LP_RING(); \
+ ErrorF("OVERLAY_UPDATE\n"); \
+ } while(0)
+
+#define OVERLAY_OFF \
+ do { \
+ if (pI830->overlayOn) { \
+ BEGIN_LP_RING(8); \
+ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \
+ OUT_RING(MI_NOOP); \
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \
+ OUT_RING(MI_NOOP); \
+ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \
+ OUT_RING(pI830->OverlayMem.Physical); \
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \
+ OUT_RING(MI_NOOP); \
+ ADVANCE_LP_RING(); \
+ pI830->overlayOn = FALSE; \
+ ErrorF("Overlay goes from on to off\n"); \
+ ErrorF("OVERLAY_OFF\n"); \
+ } \
+ } while(0)
+
+/*
+ * OCMD - Overlay Command Register
+ */
+#define MIRROR_MODE (0x3<<17)
+#define MIRROR_HORIZONTAL (0x1<<17)
+#define MIRROR_VERTICAL (0x2<<17)
+#define MIRROR_BOTH (0x3<<17)
+#define OV_BYTE_ORDER (0x3<<14)
+#define UV_SWAP (0x1<<14)
+#define Y_SWAP (0x2<<14)
+#define Y_AND_UV_SWAP (0x3<<14)
+#define SOURCE_FORMAT (0xf<<10)
+#define RGB_888 (0x1<<10)
+#define RGB_555 (0x2<<10)
+#define RGB_565 (0x3<<10)
+#define YUV_422 (0x8<<10)
+#define YUV_411 (0x9<<10)
+#define YUV_420 (0xc<<10)
+#define YUV_422_PLANAR (0xd<<10)
+#define YUV_410 (0xe<<10)
+#define TVSYNC_FLIP_PARITY (0x1<<9)
+#define TVSYNC_FLIP_ENABLE (0x1<<7)
+#define BUF_TYPE (0x1<<5)
+#define BUF_TYPE_FRAME (0x0<<5)
+#define BUF_TYPE_FIELD (0x1<<5)
+#define TEST_MODE (0x1<<4)
+#define BUFFER_SELECT (0x3<<2)
+#define BUFFER0 (0x0<<2)
+#define BUFFER1 (0x1<<2)
+#define FIELD_SELECT (0x1<<1)
+#define FIELD0 (0x0<<1)
+#define FIELD1 (0x1<<1)
+#define OVERLAY_ENABLE 0x1
+
+/* OCONFIG register */
+#define CC_OUT_8BIT (0x1<<3)
+#define OVERLAY_PIPE_MASK (0x1<<18)
+#define OVERLAY_PIPE_A (0x0<<18)
+#define OVERLAY_PIPE_B (0x1<<18)
+
+/* DCLRKM register */
+#define DEST_KEY_ENABLE (0x1<<31)
+
+/* Polyphase filter coefficients */
+#define N_HORIZ_Y_TAPS 5
+#define N_VERT_Y_TAPS 3
+#define N_HORIZ_UV_TAPS 3
+#define N_VERT_UV_TAPS 3
+#define N_PHASES 17
+#define MAX_TAPS 5
+
+/* Filter cutoff frequency limits. */
+#define MIN_CUTOFF_FREQ 1.0
+#define MAX_CUTOFF_FREQ 3.0
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+#define RGB15ToColorKey(c) \
+ (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
+
+/* 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 4
+
+static XF86ImageRec Images[NUM_IMAGES] = {
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+
+typedef struct {
+ CARD32 OBUF_0Y;
+ CARD32 OBUF_1Y;
+ CARD32 OBUF_0U;
+ CARD32 OBUF_0V;
+ CARD32 OBUF_1U;
+ CARD32 OBUF_1V;
+ CARD32 OSTRIDE;
+ CARD32 YRGB_VPH;
+ CARD32 UV_VPH;
+ CARD32 HORZ_PH;
+ CARD32 INIT_PHS;
+ CARD32 DWINPOS;
+ CARD32 DWINSZ;
+ CARD32 SWIDTH;
+ CARD32 SWIDTHSW;
+ CARD32 SHEIGHT;
+ CARD32 YRGBSCALE;
+ CARD32 UVSCALE;
+ CARD32 OCLRC0;
+ CARD32 OCLRC1;
+ CARD32 DCLRKV;
+ CARD32 DCLRKM;
+ CARD32 SCLRKVH;
+ CARD32 SCLRKVL;
+ CARD32 SCLRKEN;
+ CARD32 OCONFIG;
+ CARD32 OCMD;
+ CARD32 RESERVED1; /* 0x6C */
+ CARD32 AWINPOS;
+ CARD32 AWINSZ;
+ CARD32 RESERVED2; /* 0x78 */
+ CARD32 RESERVED3; /* 0x7C */
+ CARD32 RESERVED4; /* 0x80 */
+ CARD32 RESERVED5; /* 0x84 */
+ CARD32 RESERVED6; /* 0x88 */
+ CARD32 RESERVED7; /* 0x8C */
+ CARD32 RESERVED8; /* 0x90 */
+ CARD32 RESERVED9; /* 0x94 */
+ CARD32 RESERVEDA; /* 0x98 */
+ CARD32 RESERVEDB; /* 0x9C */
+ CARD32 FASTHSCALE; /* 0xA0 */
+ CARD32 UVSCALEV; /* 0xA4 */
+
+ CARD32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
+ CARD16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
+ CARD16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+ CARD16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
+ CARD16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+ CARD16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
+ CARD16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+ CARD16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
+ CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+} I830OverlayRegRec, *I830OverlayRegPtr;
+
+typedef struct {
+ CARD32 GAMC5;
+ CARD32 GAMC4;
+ CARD32 GAMC3;
+ CARD32 GAMC2;
+ CARD32 GAMC1;
+ CARD32 GAMC0;
+} I830OverlayStateRec, *I830OverlayStatePtr;
+
+typedef struct {
+ CARD32 YBuf0offset;
+ CARD32 UBuf0offset;
+ CARD32 VBuf0offset;
+
+ CARD32 YBuf1offset;
+ CARD32 UBuf1offset;
+ CARD32 VBuf1offset;
+
+ unsigned char currentBuf;
+
+ int brightness;
+ int contrast;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ FBLinearPtr linear;
+
+ I830OverlayStateRec hwstate;
+
+ Bool refreshOK;
+ int maxRate;
+} I830PortPrivRec, *I830PortPrivPtr;
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+
+static void
+CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size)
+{
+ int i;
+ CARD32 val;
+ int bad = 0;
+
+ for (i = 0; i < size; i += 4) {
+ val = INREG(0x30100 + i);
+ if (val != overlay[i / 4]) {
+ ErrorF("0x%05x value doesn't match (0x%08x != 0x%08x)\n",
+ 0x30100 + i, val, overlay[i / 4]);
+ bad++;
+ }
+ }
+ if (!bad)
+ ErrorF("CompareOverlay: no differences\n");
+}
+
+void
+I830InitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+ DPRINTF(PFX, "I830InitVideo\n");
+
+#if 0
+ {
+ I830OverlayRegRec tmp;
+
+ ErrorF("sizeof I830OverlayRegRec is 0x%x\n", sizeof(I830OverlayRegRec));
+ ErrorF("Reserved C, D, E, F, G are %x, %x, %x, %x, %x\n",
+ (unsigned long)&(tmp.RESERVEDC[0]) - (unsigned long)&tmp,
+ (unsigned long)&(tmp.RESERVEDD[0]) - (unsigned long)&tmp,
+ (unsigned long)&(tmp.RESERVEDE[0]) - (unsigned long)&tmp,
+ (unsigned long)&(tmp.RESERVEDF[0]) - (unsigned long)&tmp,
+ (unsigned long)&(tmp.RESERVEDG[0]) - (unsigned long)&tmp);
+ }
+#endif
+
+ if (pScrn->bitsPerPixel != 8) {
+ newAdaptor = I830SetupImageVideo(pScreen);
+ I830InitOffscreenImages(pScreen);
+ }
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if (newAdaptor) {
+ if (!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors = /* need to free this someplace */
+ xalloc((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)
+ xfree(newAdaptors);
+}
+
+static void
+I830ResetVideo(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+ I830OverlayStatePtr hwstate = &(pPriv->hwstate);
+
+ DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%08x, obase: %p\n",
+ pI830->FbBase, pI830->OverlayMem.Start, overlay);
+ /*
+ * Default to maximum image size in YV12
+ */
+
+ memset(overlay, 0, sizeof(*overlay));
+ overlay->YRGB_VPH = 0;
+ overlay->UV_VPH = 0;
+ overlay->HORZ_PH = 0;
+ overlay->INIT_PHS = 0;
+ overlay->DWINPOS = 0;
+ overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
+ overlay->SWIDTH = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 16);
+ overlay->SWIDTHSW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
+ overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
+ overlay->OCLRC0 = 0x01000000; /* brightness: 0 contrast: 1.0 */
+ overlay->OCLRC1 = 0x00000080; /* saturation: bypass */
+ overlay->AWINPOS = 0;
+ overlay->AWINSZ = 0;
+ overlay->FASTHSCALE = 0;
+
+ /*
+ * Enable destination color keying
+ */
+ switch (pScrn->depth) {
+ case 8:
+ overlay->DCLRKV = 0;
+ overlay->DCLRKM = 0xffffff | DEST_KEY_ENABLE;
+ break;
+ case 15:
+ overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x070707 | DEST_KEY_ENABLE;
+ break;
+ case 16:
+ overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ overlay->DCLRKM = 0x070307 | DEST_KEY_ENABLE;
+ break;
+ default:
+ overlay->DCLRKV = pPriv->colorKey;
+ overlay->DCLRKM = DEST_KEY_ENABLE;
+ break;
+ }
+
+ overlay->SCLRKVH = 0;
+ overlay->SCLRKVL = 0;
+ overlay->SCLRKEN = 0; /* source color key disable */
+ overlay->OCONFIG = CC_OUT_8BIT;
+
+ /*
+ * Select which pipe the overlay is enabled on. Give preference to
+ * pipe A.
+ */
+ if (pI830->pipeEnabled[0])
+ overlay->OCONFIG |= OVERLAY_PIPE_A;
+ else if (pI830->pipeEnabled[1])
+ overlay->OCONFIG |= OVERLAY_PIPE_B;
+
+ overlay->OCMD = YUV_420;
+
+ /* setup hwstate */
+ /* Default gamma correction values. */
+ hwstate->GAMC5 = 0xc0c0c0;
+ hwstate->GAMC4 = 0x808080;
+ hwstate->GAMC3 = 0x404040;
+ hwstate->GAMC2 = 0x202020;
+ hwstate->GAMC1 = 0x101010;
+ hwstate->GAMC0 = 0x080808;
+
+#if 0
+ /*
+ * XXX DUMP REGISTER CODE !!!
+ * This allows us to dump the complete i845 registers and compare
+ * with warm boot situations before we upload our first copy.
+ */
+ {
+ int i;
+ for (i = 0x30000; i < 0x31000; i += 4)
+ ErrorF("0x%x 0x%08x\n", i, INREG(i));
+ }
+#endif
+
+ OUTREG(OGAMC5, hwstate->GAMC5);
+ OUTREG(OGAMC4, hwstate->GAMC4);
+ OUTREG(OGAMC3, hwstate->GAMC3);
+ OUTREG(OGAMC2, hwstate->GAMC2);
+ OUTREG(OGAMC1, hwstate->GAMC1);
+ OUTREG(OGAMC0, hwstate->GAMC0);
+
+}
+
+/*
+ * Each chipset has a limit on the pixel rate that the video overlay can
+ * be used for. Enabling the overlay above that limit can result in a
+ * lockup. These two functions check the pixel rate for the new mode
+ * and turn the overlay off before switching to the new mode if it exceeds
+ * the limit, or turn it back on if the new mode is below the limit.
+ */
+
+/*
+ * Approximate pixel rate limits for the video overlay.
+ * The rate is calculated based on the mode resolution and refresh rate.
+ */
+#define I830_OVERLAY_RATE 79 /* 1024x768@85, 1280x1024@60 */
+#define I845_OVERLAY_RATE 120 /* 1280x1024@85, 1600x1200@60 */
+#define I852_OVERLAY_RATE 79 /* 1024x768@85, 1280x1024@60 */
+#define I855_OVERLAY_RATE 120 /* 1280x1024@85, 1600x1200@60 */
+#define I865_OVERLAY_RATE 170 /* 1600x1200@85, 1920x1440@60 */
+#define DEFAULT_OVERLAY_RATE 120
+
+static XF86VideoAdaptorPtr
+I830SetupImageVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ I830PortPrivPtr pPriv;
+
+ DPRINTF(PFX, "I830SetupImageVideo\n");
+
+ if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(I830PortPrivRec) + sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "Intel(R) 830M/845G/852GM/855GM/865G Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+
+ pPriv = (I830PortPrivPtr) (&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 = I830StopVideo;
+ adapt->SetPortAttribute = I830SetPortAttribute;
+ adapt->GetPortAttribute = I830GetPortAttribute;
+ adapt->QueryBestSize = I830QueryBestSize;
+ adapt->PutImage = I830PutImage;
+ adapt->QueryImageAttributes = I830QueryImageAttributes;
+
+ pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1);
+ pPriv->videoStatus = 0;
+ pPriv->brightness = 0;
+ pPriv->contrast = 64;
+ pPriv->linear = NULL;
+ pPriv->currentBuf = 0;
+
+ switch (pI830->PciInfo->chipType) {
+ case PCI_CHIP_I830_M:
+ pPriv->maxRate = I830_OVERLAY_RATE;
+ break;
+ case PCI_CHIP_845_G:
+ pPriv->maxRate = I845_OVERLAY_RATE;
+ break;
+ case PCI_CHIP_I855_GM:
+ switch (pI830->variant) {
+ case I852_GM:
+ case I852_GME:
+ pPriv->maxRate = I852_OVERLAY_RATE;
+ break;
+ default:
+ pPriv->maxRate = I855_OVERLAY_RATE;
+ break;
+ }
+ break;
+ case PCI_CHIP_I865_G:
+ pPriv->maxRate = I865_OVERLAY_RATE;
+ break;
+ default:
+ pPriv->maxRate = DEFAULT_OVERLAY_RATE;
+ break;
+ }
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+
+ pI830->adaptor = adapt;
+
+ /* Initialise pPriv->refreshOK */
+ I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
+
+ pI830->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = I830BlockHandler;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ I830ResetVideo(pScrn);
+
+ return adapt;
+}
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if (num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if ((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int *)REGION_RECTS(A);
+ dataB = (int *)REGION_RECTS(B);
+
+ while (num--) {
+ if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+static void
+I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+
+ DPRINTF(PFX, "I830StopVideo\n");
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if (shutdown) {
+ if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ overlay->OCMD &= ~OVERLAY_ENABLE;
+ OVERLAY_UPDATE;
+
+ OVERLAY_OFF;
+ }
+ 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
+I830SetPortAttribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 value, pointer data)
+{
+ I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+
+ if (attribute == xvBrightness) {
+ if ((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+ if (pPriv->refreshOK)
+ OVERLAY_UPDATE;
+ } else if (attribute == xvContrast) {
+ if ((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+ if (pPriv->refreshOK)
+ OVERLAY_UPDATE;
+ } 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;
+ }
+ if (pPriv->refreshOK)
+ OVERLAY_UPDATE;
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else
+ return BadMatch;
+
+ return Success;
+}
+
+static int
+I830GetPortAttribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 * value, pointer data)
+{
+ I830PortPrivPtr pPriv = (I830PortPrivPtr) 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
+I830QueryBestSize(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
+I830CopyPackedData(ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch, int top, int left, int h, int w)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ unsigned char *src, *dst;
+
+ DPRINTF(PFX, "I830CopyPackedData: (%d,%d) (%d,%d)\n"
+ "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch);
+
+ src = buf + (top * srcPitch) + (left << 1);
+
+ if (pPriv->currentBuf == 0)
+ dst = pI830->FbBase + pPriv->YBuf0offset;
+ else
+ dst = pI830->FbBase + pPriv->YBuf1offset;
+
+ w <<= 1;
+ while (h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch,
+ int dstPitch, int srcH, int top, int left,
+ int h, int w, int id)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ int i;
+ unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+
+ DPRINTF(PFX, "I830CopyPlanarData: srcPitch %d, dstPitch %d\n"
+ "nlines %d, npixels %d, top %d, left %d\n", srcPitch, dstPitch,
+ h, w, top, left);
+
+ /* Copy Y data */
+ src1 = buf + (top * srcPitch) + left;
+ ErrorF("src1 is %p, offset is %d\n", src1,
+ (unsigned long)src1 - (unsigned long)buf);
+ if (pPriv->currentBuf == 0)
+ dst1 = pI830->FbBase + pPriv->YBuf0offset;
+ else
+ dst1 = pI830->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);
+ ErrorF("src2 is %p, offset is %d\n", src2,
+ (unsigned long)src2 - (unsigned long)buf);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst2 = pI830->FbBase + pPriv->UBuf0offset;
+ else
+ dst2 = pI830->FbBase + pPriv->VBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst2 = pI830->FbBase + pPriv->UBuf1offset;
+ else
+ dst2 = pI830->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);
+ ErrorF("src3 is %p, offset is %d\n", src3,
+ (unsigned long)src3 - (unsigned long)buf);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst3 = pI830->FbBase + pPriv->VBuf0offset;
+ else
+ dst3 = pI830->FbBase + pPriv->UBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst3 = pI830->FbBase + pPriv->VBuf1offset;
+ else
+ dst3 = pI830->FbBase + pPriv->UBuf1offset;
+ }
+
+ for (i = 0; i < h / 2; i++) {
+ memcpy(dst3, src3, w / 2);
+ src3 += srcPitch >> 1;
+ dst3 += dstPitch;
+ }
+}
+
+typedef struct {
+ CARD8 sign;
+ CARD16 mantissa;
+ CARD8 exponent;
+} coeffRec, *coeffPtr;
+
+static Bool
+SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos)
+{
+ int maxVal, icoeff, res;
+ int sign;
+ double c;
+
+ sign = 0;
+ maxVal = 1 << mantSize;
+ c = *coeff;
+ if (c < 0.0) {
+ sign = 1;
+ c = -c;
+ }
+
+ res = 12 - mantSize;
+ if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 3;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(4 * maxVal);
+ } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 2;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(2 * maxVal);
+ } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 1;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(maxVal);
+ } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 0;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(maxVal / 2);
+ } else {
+ /* Coeff out of range */
+ return FALSE;
+ }
+
+ pCoeff[pos].sign = sign;
+ if (sign)
+ *coeff = -(*coeff);
+ return TRUE;
+}
+
+static void
+UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
+{
+ int i, j, j1, num, pos, mantSize;
+ double pi = 3.1415926535, val, sinc, window, sum;
+ double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
+ double diff;
+ int tapAdjust[MAX_TAPS], tap2Fix;
+ Bool isVertAndUV;
+
+ if (isHoriz)
+ mantSize = 7;
+ else
+ mantSize = 6;
+
+ isVertAndUV = !isHoriz && !isY;
+ num = taps * 16;
+ for (i = 0; i < num * 2; i++) {
+ val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
+ if (val == 0.0)
+ sinc = 1.0;
+ else
+ sinc = sin(val) / val;
+
+ /* Hamming window */
+ window = (0.5 - 0.5 * cos(i * pi / num));
+ rawCoeff[i] = sinc * window;
+ }
+
+ for (i = 0; i < N_PHASES; i++) {
+ /* Normalise the coefficients. */
+ sum = 0.0;
+ for (j = 0; j < taps; j++) {
+ pos = i + j * 32;
+ sum += rawCoeff[pos];
+ }
+ for (j = 0; j < taps; j++) {
+ pos = i + j * 32;
+ coeffs[i][j] = rawCoeff[pos] / sum;
+ }
+
+ /* Set the register values. */
+ for (j = 0; j < taps; j++) {
+ pos = j + i * taps;
+ if ((j == (taps - 1) / 2) && !isVertAndUV)
+ SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
+ else
+ SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
+ }
+
+ tapAdjust[0] = (taps - 1) / 2;
+ for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
+ tapAdjust[j1] = tapAdjust[0] - j;
+ tapAdjust[++j1] = tapAdjust[0] + j;
+ }
+
+ /* Adjust the coefficients. */
+ sum = 0.0;
+ for (j = 0; j < taps; j++)
+ sum += coeffs[i][j];
+ if (sum != 1.0) {
+ for (j1 = 0; j1 < taps; j1++) {
+ tap2Fix = tapAdjust[j1];
+ diff = 1.0 - sum;
+ coeffs[i][tap2Fix] += diff;
+ pos = tap2Fix + i * taps;
+ if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
+ SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
+ else
+ SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
+
+ sum = 0.0;
+ for (j = 0; j < taps; j++)
+ sum += coeffs[i][j];
+ if (sum == 1.0)
+ break;
+ }
+ }
+ }
+}
+
+static void
+I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height,
+ int dstPitch, int x1, int y1, int x2, int y2, BoxPtr dstBox,
+ short src_w, short src_h, short drw_w, short drw_h)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+ unsigned int swidth;
+
+ DPRINTF(PFX, "I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
+ dstPitch);
+
+ if (!pPriv->refreshOK)
+ return;
+
+ CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ swidth = (width + 1) & ~1 & 0xfff;
+ overlay->SWIDTH = swidth;
+ swidth /= 2;
+ overlay->SWIDTH |= (swidth & 0x7ff) << 16;
+
+ swidth = ((pPriv->YBuf0offset + width + 0x1f) >> 5) -
+ (pPriv->YBuf0offset >> 5) - 1;
+
+ ErrorF("Y width is %d, swidthsw is %d\n", width, swidth);
+
+ overlay->SWIDTHSW = swidth << 2;
+
+ swidth = ((pPriv->UBuf0offset + (width / 2) + 0x1f) >> 5) -
+ (pPriv->UBuf0offset >> 5) - 1;
+ ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth);
+
+ overlay->SWIDTHSW |= swidth << 18;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ /* XXX Check for i845 */
+
+ swidth = ((width + 31) & ~31) << 1;
+ overlay->SWIDTH = swidth;
+ overlay->SWIDTHSW = swidth >> 3;
+ break;
+ }
+
+ overlay->SHEIGHT = height | ((height / 2) << 16);
+
+ 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;
+
+ ErrorF("Buffers: Y0: 0x%08x, U0: 0x%08x, V0: 0x%08x\n", overlay->OBUF_0Y,
+ overlay->OBUF_0U, overlay->OBUF_0V);
+ ErrorF("Buffers: Y1: 0x%08x, U1: 0x%08x, V1: 0x%08x\n", overlay->OBUF_1Y,
+ overlay->OBUF_1U, overlay->OBUF_1V);
+
+#if 0
+ {
+ int i;
+
+ ErrorF("First 32 bytes of Y data:\n");
+ for (i = 0; i < 32; i++)
+ ErrorF(" %02x",
+ ((unsigned char *)pI830->FbBase + pPriv->YBuf0offset)[i]);
+ ErrorF("\n");
+ ErrorF("First 16 bytes of U data:\n");
+ for (i = 0; i < 16; i++)
+ ErrorF(" %02x",
+ ((unsigned char *)pI830->FbBase + pPriv->UBuf0offset)[i]);
+ ErrorF("\n");
+ ErrorF("First 16 bytes of V data:\n");
+ for (i = 0; i < 16; i++)
+ ErrorF(" %02x",
+ ((unsigned char *)pI830->FbBase + pPriv->VBuf0offset)[i]);
+ ErrorF("\n");
+ }
+#endif
+
+#if 1
+ overlay->OCMD = OVERLAY_ENABLE;
+#endif
+
+ ErrorF("pos: 0x%08x, size: 0x%08x\n", overlay->DWINPOS, overlay->DWINSZ);
+ ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
+
+ /*
+ * Calculate horizontal and vertical scaling factors and polyphase
+ * coefficients.
+ */
+
+ {
+ Bool scaleChanged = FALSE;
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV, xscaleFractUV;
+ int yscaleIntUV, yscaleFractUV;
+ /* UV is half the size of Y -- YUV420 */
+ int uvratio = 2;
+ CARD32 newval;
+ coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
+ coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
+ int i, j, pos;
+
+ /*
+ * Y down-scale factor as a multiple of 4096.
+ */
+ xscaleFract = (src_w << 12) / drw_w;
+ yscaleFract = (src_h << 12) / drw_h;
+
+ /* Calculate the UV scaling factor. */
+ xscaleFractUV = xscaleFract / uvratio;
+ yscaleFractUV = yscaleFract / uvratio;
+
+ /*
+ * To keep the relative Y and UV ratios exact, round the Y scales
+ * to a multiple of the Y/UV ratio.
+ */
+ xscaleFract = xscaleFractUV * uvratio;
+ yscaleFract = yscaleFractUV * uvratio;
+
+ /* Integer (un-multiplied) values. */
+ xscaleInt = xscaleFract >> 12;
+ yscaleInt = yscaleFract >> 12;
+
+ xscaleIntUV = xscaleFractUV >> 12;
+ yscaleIntUV = yscaleFractUV >> 12;
+
+ ErrorF("xscale: 0x%x.%03x, yscale: 0x%x.%03x\n", xscaleInt,
+ xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
+ ErrorF("UV xscale: 0x%x.%03x, UV yscale: 0x%x.%03x\n", xscaleIntUV,
+ xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
+
+ newval = (xscaleInt << 16) |
+ ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
+ if (newval != overlay->YRGBSCALE) {
+ scaleChanged = TRUE;
+ overlay->YRGBSCALE = newval;
+ }
+
+ newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ if (newval != overlay->UVSCALE) {
+ scaleChanged = TRUE;
+ overlay->UVSCALE = newval;
+ }
+
+ newval = yscaleInt << 16 | yscaleIntUV;
+ if (newval != overlay->UVSCALEV) {
+ scaleChanged = TRUE;
+ overlay->UVSCALEV = newval;
+ }
+
+ /* Recalculate coefficients if the scaling changed. */
+
+ /*
+ * Only Horizontal coefficients so far.
+ */
+ if (scaleChanged) {
+ double fCutoffY;
+ double fCutoffUV;
+
+ fCutoffY = xscaleFract / 4096.0;
+ fCutoffUV = xscaleFractUV / 4096.0;
+
+ /* Limit to between 1.0 and 3.0. */
+ if (fCutoffY < MIN_CUTOFF_FREQ)
+ fCutoffY = MIN_CUTOFF_FREQ;
+ if (fCutoffY > MAX_CUTOFF_FREQ)
+ fCutoffY = MAX_CUTOFF_FREQ;
+ if (fCutoffUV < MIN_CUTOFF_FREQ)
+ fCutoffUV = MIN_CUTOFF_FREQ;
+ if (fCutoffUV > MAX_CUTOFF_FREQ)
+ fCutoffUV = MAX_CUTOFF_FREQ;
+
+ UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
+ UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
+
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
+ pos = i * N_HORIZ_Y_TAPS + j;
+ overlay->Y_HCOEFS[pos] = xcoeffY[pos].sign << 15 |
+ xcoeffY[pos].exponent << 12 |
+ xcoeffY[pos].mantissa;
+ }
+ }
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
+ pos = i * N_HORIZ_UV_TAPS + j;
+ overlay->UV_HCOEFS[pos] = xcoeffUV[pos].sign << 15 |
+ xcoeffUV[pos].exponent << 12 |
+ xcoeffUV[pos].mantissa;
+ }
+ }
+ }
+ }
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ ErrorF("YUV420\n");
+#if 0
+ /* set UV vertical phase to -0.25 */
+ overlay->UV_VPH = 0x30003000;
+#endif
+ ErrorF("UV stride is %d, Y stride is %d\n", dstPitch, dstPitch * 2);
+ overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
+ overlay->OCMD &= ~SOURCE_FORMAT;
+ overlay->OCMD &= ~OV_BYTE_ORDER;
+ overlay->OCMD |= YUV_420;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ ErrorF("YUV422\n");
+ overlay->OSTRIDE = dstPitch;
+ overlay->OCMD &= ~SOURCE_FORMAT;
+ overlay->OCMD |= YUV_422;
+ overlay->OCMD &= ~OV_BYTE_ORDER;
+ if (id == FOURCC_UYVY)
+ overlay->OCMD |= Y_SWAP;
+ break;
+ }
+
+ overlay->OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
+ if (pPriv->currentBuf == 0)
+ overlay->OCMD |= BUFFER0;
+ else
+ overlay->OCMD |= BUFFER1;
+
+ ErrorF("OCMD is 0x%08x\n", overlay->OCMD);
+
+ OVERLAY_UPDATE;
+}
+
+static FBLinearPtr
+I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+{
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ DPRINTF(PFX, "I830AllocateMemory\n");
+ 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
+I830PutImage(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)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch;
+ int top, left, npixels, nlines, size, loops;
+ BoxRec dstBox;
+
+ DPRINTF(PFX, "I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
+ "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y,
+ drw_w, drw_h, width, height);
+
+ /* 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;
+
+ if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+ width, height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ dstPitch = ((width / 2) + 255) & ~255; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 255) & ~255;
+ size = dstPitch * height;
+ break;
+ }
+ ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
+
+ if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear,
+ size * 2 / pI830->cpp)))
+ return BadAlloc;
+
+ /* fixup pointers */
+ pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp;
+ pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+ pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
+
+ pPriv->YBuf1offset = pPriv->YBuf0offset + size;
+ pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+ pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
+
+ /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead
+ * of this code....*/
+
+ /* Make sure this buffer isn't in use */
+ loops = 0;
+ while (loops < 1000000) {
+#if USE_USLEEP_FOR_VIDEO
+ usleep(10);
+#endif
+ if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
+ break;
+ }
+ loops++;
+ }
+ if (loops >= 1000000) {
+ ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
+#if 0
+ pPriv->currentBuf = !pPriv->currentBuf;
+#endif
+ }
+
+ /* 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;
+ I830CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left,
+ nlines, npixels, id);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ I830CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ break;
+ }
+
+ /* update cliplist */
+ /*
+ * XXX Always draw the key. LinDVD seems to fill the window background
+ * with a colour different from the key. This works around that.
+ */
+ if (1 || !RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes);
+ }
+
+ I830DisplayVideo(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
+I830QueryImageAttributes(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets)
+{
+ int size, tmp;
+
+ DPRINTF(PFX, "I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
+
+ 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;
+#if 1
+ size = (*w + 3) & ~3;
+#else
+ size = (*w + 255) & ~255;
+#endif
+ if (pitches)
+ pitches[0] = size;
+ size *= *h;
+ if (offsets)
+ offsets[1] = size;
+#if 1
+ tmp = ((*w >> 1) + 3) & ~3;
+#else
+ tmp = ((*w >> 1) + 255) & ~255;
+#endif
+ if (pitches)
+ pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if (offsets)
+ offsets[2] = size;
+ size += tmp;
+ if (pitches)
+ ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0],
+ pitches[1], pitches[2]);
+ if (offsets)
+ ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], offsets[2]);
+ if (offsets)
+ ErrorF("size is %d\n", size);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if (pitches)
+ pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static void
+I830BlockHandler(int i,
+ pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+
+ pScreen->BlockHandler = pI830->BlockHandler;
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ pScreen->BlockHandler = I830BlockHandler;
+
+ if (pPriv->videoStatus & TIMER_MASK) {
+ UpdateCurrentTime();
+ if (pPriv->videoStatus & OFF_TIMER) {
+ if (pPriv->offTime < currentTime.milliseconds) {
+ /* Turn off the overlay */
+ overlay->OCMD &= ~OVERLAY_ENABLE;
+
+ OVERLAY_UPDATE;
+
+ OVERLAY_OFF;
+
+ 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
+I830AllocateSurface(ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h, XF86SurfacePtr surface)
+{
+ FBLinearPtr linear;
+ int pitch, fbpitch, size, bpp;
+ OffscreenPrivPtr pPriv;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830AllocateSurface\n");
+
+ if ((w > 1024) || (h > 1024))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ bpp = pScrn->bitsPerPixel >> 3;
+ fbpitch = bpp * pScrn->displayWidth;
+ size = ((pitch * h) + bpp - 1) / bpp;
+
+ if (!(linear = I830AllocateMemory(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if (!(surface->pitches = xalloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if (!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+
+ pPriv->linear = linear;
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = linear->offset * bpp;
+ surface->devPrivate.ptr = (pointer) pPriv;
+
+ memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size);
+
+ return Success;
+}
+
+static int
+I830StopSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
+ ScrnInfoPtr pScrn = surface->pScrn;
+
+ if (pPriv->isOn) {
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ I830OverlayRegPtr overlay =
+ (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start);
+
+ overlay->OCMD &= ~OVERLAY_ENABLE;
+
+ OVERLAY_UPDATE;
+
+ OVERLAY_OFF;
+
+ pPriv->isOn = FALSE;
+ }
+
+ return Success;
+}
+
+static int
+I830FreeSurface(XF86SurfacePtr surface)
+{
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr) surface->devPrivate.ptr;
+
+ if (pPriv->isOn) {
+ I830StopSurface(surface);
+ }
+ xf86FreeOffscreenLinear(pPriv->linear);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+I830GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value)
+{
+ return I830GetPortAttribute(pScrn, attribute, value, 0);
+}
+
+static int
+I830SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value)
+{
+ return I830SetPortAttribute(pScrn, attribute, value, 0);
+}
+
+static int
+I830DisplaySurface(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;
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
+
+ INT32 x1, y1, x2, y2;
+ INT32 loops = 0;
+ BoxRec dstBox;
+
+ DPRINTF(PFX, "I830DisplaySurface\n");
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+ surface->width, surface->height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ /* fixup pointers */
+ pI830Priv->YBuf0offset = surface->offsets[0];
+ pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
+
+ /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead
+ * of this code....*/
+
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOVSTA) & OC_BUF) >> 20) != pI830Priv->currentBuf) {
+#if USE_USLEEP_FOR_VIDEO
+ usleep(10);
+#endif
+ if (loops == 200000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
+ break;
+ }
+ loops++;
+ }
+
+ /* buffer swap */
+ if (pI830Priv->currentBuf == 0)
+ pI830Priv->currentBuf = 1;
+ else
+ pI830Priv->currentBuf = 0;
+
+ I830ResetVideo(pScrn);
+
+ I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+ surface->pitches[0], x1, y1, x2, y2, &dstBox,
+ src_w, src_h, drw_w, drw_h);
+
+ xf86XVFillKeyHelper(pScreen, pI830Priv->colorKey, clipBoxes);
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if (pI830Priv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, &pI830Priv->clip);
+ UpdateCurrentTime();
+ pI830Priv->videoStatus = FREE_TIMER;
+ pI830Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ pScrn->pScreen->BlockHandler = I830BlockHandler;
+ }
+
+ return Success;
+}
+
+static void
+I830InitOffscreenImages(ScreenPtr pScreen)
+{
+ XF86OffscreenImagePtr offscreenImages;
+
+ /* need to free this someplace */
+ if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
+ return;
+ }
+
+ offscreenImages[0].image = &Images[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = I830AllocateSurface;
+ offscreenImages[0].free_surface = I830FreeSurface;
+ offscreenImages[0].display = I830DisplaySurface;
+ offscreenImages[0].stop = I830StopSurface;
+ offscreenImages[0].setAttribute = I830SetSurfaceAttribute;
+ offscreenImages[0].getAttribute = I830GetSurfaceAttribute;
+ offscreenImages[0].max_width = 1024;
+ offscreenImages[0].max_height = 1024;
+ offscreenImages[0].num_attributes = 1;
+ offscreenImages[0].attributes = Attributes;
+
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
+
+void
+I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ I830PortPrivPtr pPriv;
+ int pixrate;
+
+ if (!I830PTR(pScrn)->adaptor) {
+ return;
+ }
+
+ pPriv = GET_PORT_PRIVATE(pScrn);
+
+ if (!pPriv) {
+ xf86ErrorF("pPriv isn't set\n");
+ return;
+ }
+
+ pixrate = mode->HDisplay * mode->VDisplay * mode->VRefresh;
+ if (pixrate > pPriv->maxRate && pPriv->refreshOK) {
+ I830StopVideo(pScrn, pPriv, TRUE);
+ pPriv->refreshOK = FALSE;
+ }
+}
+
+void
+I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ I830PortPrivPtr pPriv;
+ int pixrate;
+
+ if (!I830PTR(pScrn)->adaptor) {
+ return;
+ }
+ pPriv = GET_PORT_PRIVATE(pScrn);
+ if (!pPriv)
+ return;
+
+ /* If this isn't initialised, assume 60Hz. */
+ if (mode->VRefresh == 0)
+ mode->VRefresh = 60;
+
+ pixrate = (mode->HDisplay * mode->VDisplay * mode->VRefresh) / 1000000;
+ pPriv->refreshOK = (pixrate <= pPriv->maxRate);
+}
+
diff --git a/src/xvmc/I810XvMC.c b/src/xvmc/I810XvMC.c
new file mode 100644
index 00000000..e6731c62
--- /dev/null
+++ b/src/xvmc/I810XvMC.c
@@ -0,0 +1,4507 @@
+/***************************************************************************
+
+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>
+**
+**
+***************************************************************************/
+/* $XFree86: xc/lib/XvMC/hw/i810/I810XvMC.c,v 1.11 2002/11/19 09:35:49 alanh Exp $ */
+#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 <Xv.h>
+#include <Xvlib.h>
+#include <XvMC.h>
+#include <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
+***************************************************************************/
+Status XvMCCreateContext(Display *display, XvPortID port,
+ int surface_type_id, int width, int height, int flags,
+ XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+ char busIdString[10];
+ 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(busIdString);
+ 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 drmContext 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:
+ drmContext
+ 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
+***************************************************************************/
+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 drmContext */
+ _xvmc_destroy_context(display, context);
+
+ i810_free_privContext(pI810XvMC);
+ context->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateSurface
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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.
+***************************************************************************/
+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 */
+ 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 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[0] = mb->PMV[0][0][1]/2;
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1]/2;
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1]/2;
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1]/2;
+ 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[0];
+ *dy++ = *(uint *)&bmv[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++ = *(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[0];
+ *du++ = *(uint *)&bmv[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++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ 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++ = *(uint *)&fmv[0];
+ *dv++ = *(uint *)&bmv[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++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ 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 */
+ short fmv[4];
+ short bmv[4];
+ /* 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[0] = mb->PMV[0][0][1]/2;
+ fmv[1] = mb->PMV[0][0][0];
+ fmv[2] = mb->PMV[1][0][1]/2;
+ fmv[3] = mb->PMV[1][0][0];
+
+ bmv[0] = mb->PMV[0][1][1]/2;
+ bmv[1] = mb->PMV[0][1][0];
+ bmv[2] = mb->PMV[1][1][1]/2;
+ bmv[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++ = *(uint *)&fmv[0];
+ *dy++ = *(uint *)&bmv[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++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ 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[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[0];
+ *du++ = *(uint *)&bmv[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++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ 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++ = *(uint *)&fmv[0];
+ *dv++ = *(uint *)&bmv[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++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ 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 */
+ short fmv[2];
+ short bmv[2];
+ /* 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[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);
+ /* End U Block */
+
+ /* 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);
+ /* 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 */
+ short fmv[4];
+ short bmv[4];
+
+ 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[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];
+
+ /*
+ 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++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ 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[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: 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 */
+ 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 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[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[1][0][1];
+ bmv[1] = mb->PMV[1][0][0];
+
+ fmv[2] = mb->PMV[0][0][1];
+ fmv[3] = mb->PMV[0][0][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;
+ *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);
+
+ fmv[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ fmv[2] /= 2;
+ fmv[3] /= 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;
+ 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++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ 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++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ 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++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ 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 */
+ short fmv[4];
+ short bmv[4];
+ /* 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[0] = mb->PMV[0][0][1];
+ fmv[1] = mb->PMV[0][0][0];
+ bmv[0] = mb->PMV[1][0][1];
+ bmv[1] = mb->PMV[1][0][0];
+
+ fmv[2] = mb->PMV[0][0][1];
+ fmv[3] = mb->PMV[0][0][0];
+ bmv[2] = mb->PMV[1][1][1];
+ bmv[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++ = *(uint *)fmv;
+ *dy++ = *(uint *)bmv;
+ 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++ = *(uint *)&fmv[2];
+ *dy++ = *(uint *)&bmv[2];
+ 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[0] /= 2;
+ fmv[1] /= 2;
+ bmv[0] /= 2;
+ bmv[1] /= 2;
+
+ fmv[2] /= 2;
+ fmv[3] /= 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;
+ 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++ = *(uint *)&fmv[2];
+ *du++ = *(uint *)&bmv[2];
+ 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++ = *(uint *)fmv;
+ *dv++ = *(uint *)bmv;
+ 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++ = *(uint *)&fmv[2];
+ *dv++ = *(uint *)&bmv[2];
+ 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
+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.
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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.
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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.
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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
+***************************************************************************/
+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/xvmc/I810XvMC.h b/src/xvmc/I810XvMC.h
new file mode 100644
index 00000000..018c80e9
--- /dev/null
+++ b/src/xvmc/I810XvMC.h
@@ -0,0 +1,469 @@
+/***************************************************************************
+
+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>
+ *
+ *
+ ***************************************************************************/
+/* $XFree86: xc/lib/XvMC/hw/i810/I810XvMC.h,v 1.4 2002/11/19 09:35:49 alanh Exp $ */
+
+
+#ifndef I810XVMC_H
+#define I810XVMC_H
+
+/* #define XVMC_DEBUG(x) do {x; }while(0); */
+#define XVMC_DEBUG(x)
+
+#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 {
+ drmHandle 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 */
+ drmContext 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;
+ drmHandle 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;
+ drmHandle 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+