summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2007-04-04 20:17:58 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2007-04-04 20:17:58 +0000
commit567ff8cf7c7c999fc917b9fb413b9d839d6058e1 (patch)
tree9a327eed77b97809dea069822a8911fa8a0457d4 /driver
parentcd310311f583634f2be469b9bb090435500ac25c (diff)
Import the i810 driver version 1.4.1 plus OpenBSD patches,
that shipped with OpenBSD 3.9/4.0 and that actually works.
Diffstat (limited to 'driver')
-rw-r--r--driver/xf86-video-i810/.cvsignore20
-rw-r--r--driver/xf86-video-i810/COPYING12
-rw-r--r--driver/xf86-video-i810/ChangeLog49
-rw-r--r--driver/xf86-video-i810/Makefile.am29
-rw-r--r--driver/xf86-video-i810/Makefile.bsd-wrapper3
-rw-r--r--driver/xf86-video-i810/README166
-rw-r--r--driver/xf86-video-i810/README.sgml136
-rw-r--r--driver/xf86-video-i810/autogen.sh12
-rw-r--r--driver/xf86-video-i810/configure.ac116
-rw-r--r--driver/xf86-video-i810/man/.cvsignore2
-rw-r--r--driver/xf86-video-i810/man/Makefile.am59
-rw-r--r--driver/xf86-video-i810/man/i810.man214
-rw-r--r--driver/xf86-video-i810/src/.cvsignore6
-rw-r--r--driver/xf86-video-i810/src/Makefile.am65
-rw-r--r--driver/xf86-video-i810/src/common.h363
-rw-r--r--driver/xf86-video-i810/src/i810.h339
-rw-r--r--driver/xf86-video-i810/src/i810_accel.c631
-rw-r--r--driver/xf86-video-i810/src/i810_common.h192
-rw-r--r--driver/xf86-video-i810/src/i810_cursor.c281
-rw-r--r--driver/xf86-video-i810/src/i810_dga.c297
-rw-r--r--driver/xf86-video-i810/src/i810_dri.c1537
-rw-r--r--driver/xf86-video-i810/src/i810_dri.h128
-rw-r--r--driver/xf86-video-i810/src/i810_driver.c2594
-rw-r--r--driver/xf86-video-i810/src/i810_hwmc.c420
-rw-r--r--driver/xf86-video-i810/src/i810_io.c148
-rw-r--r--driver/xf86-video-i810/src/i810_memory.c443
-rw-r--r--driver/xf86-video-i810/src/i810_reg.h1019
-rw-r--r--driver/xf86-video-i810/src/i810_video.c1423
-rw-r--r--driver/xf86-video-i810/src/i810_wmark.c325
-rw-r--r--driver/xf86-video-i810/src/i830.h487
-rw-r--r--driver/xf86-video-i810/src/i830_accel.c797
-rw-r--r--driver/xf86-video-i810/src/i830_common.h168
-rw-r--r--driver/xf86-video-i810/src/i830_cursor.c437
-rw-r--r--driver/xf86-video-i810/src/i830_dga.c302
-rw-r--r--driver/xf86-video-i810/src/i830_dri.c1296
-rw-r--r--driver/xf86-video-i810/src/i830_dri.h67
-rw-r--r--driver/xf86-video-i810/src/i830_driver.c5857
-rw-r--r--driver/xf86-video-i810/src/i830_io.c35
-rw-r--r--driver/xf86-video-i810/src/i830_memory.c1634
-rw-r--r--driver/xf86-video-i810/src/i830_modes.c773
-rw-r--r--driver/xf86-video-i810/src/i830_shadow.c253
-rw-r--r--driver/xf86-video-i810/src/i830_video.c2128
-rw-r--r--driver/xf86-video-i810/src/xvmc/.cvsignore6
-rw-r--r--driver/xf86-video-i810/src/xvmc/I810XvMC.c4507
-rw-r--r--driver/xf86-video-i810/src/xvmc/I810XvMC.h469
-rw-r--r--driver/xf86-video-i810/src/xvmc/Makefile.am8
46 files changed, 30253 insertions, 0 deletions
diff --git a/driver/xf86-video-i810/.cvsignore b/driver/xf86-video-i810/.cvsignore
new file mode 100644
index 000000000..c7bcbee1a
--- /dev/null
+++ b/driver/xf86-video-i810/.cvsignore
@@ -0,0 +1,20 @@
+Makefile
+Makefile.in
+*.la
+*.lo
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+stamp-h1
diff --git a/driver/xf86-video-i810/COPYING b/driver/xf86-video-i810/COPYING
new file mode 100644
index 000000000..7f33cbfd2
--- /dev/null
+++ b/driver/xf86-video-i810/COPYING
@@ -0,0 +1,12 @@
+This is a stub file. This package has not yet had its complete licensing
+information compiled. Please see the individual source files for details on
+your rights to use and modify this software.
+
+Please submit updated COPYING files to the Xorg bugzilla:
+
+https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+All licensing questions regarding this software should be directed at the
+Xorg mailing list:
+
+http://lists.freedesktop.org/mailman/listinfo/xorg
diff --git a/driver/xf86-video-i810/ChangeLog b/driver/xf86-video-i810/ChangeLog
new file mode 100644
index 000000000..0d1f506d3
--- /dev/null
+++ b/driver/xf86-video-i810/ChangeLog
@@ -0,0 +1,49 @@
+2005-12-20 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update package version for X11R7 release.
+
+2005-12-14 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update package version number for final X11R7 release candidate.
+
+2005-12-06 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * man/Makefile.am:
+ Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
+
+2005-12-03 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update package version number for X11R7 RC3 release.
+
+2005-12-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Remove extraneous AC_MSG_RESULT.
+
+2005-11-30 Adam Jackson <ajax@freedesktop.org>
+
+ * configure.ac:
+ Bump libdrm dep to 2.0.
+
+2005-11-29 Adam Jackson <ajax@freedesktop.org>
+
+ * configure.ac:
+ Only build dlloader modules by default.
+
+2005-11-19 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update dependencies to work with separate build roots.
+
+2005-11-09 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update package version number for X11R7 RC2 release.
+
+2005-11-01 Kevin E. Martin <kem-at-freedesktop-dot-org>
+
+ * configure.ac:
+ Update pkgcheck dependencies to work with separate build roots.
diff --git a/driver/xf86-video-i810/Makefile.am b/driver/xf86-video-i810/Makefile.am
new file mode 100644
index 000000000..2b6c46aa1
--- /dev/null
+++ b/driver/xf86-video-i810/Makefile.am
@@ -0,0 +1,29 @@
+# Copyright 2005 Adam Jackson.
+#
+# 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
+# ADAM JACKSON 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.
+
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS = src man
+
+if BUILD_LINUXDOC
+README: README.sgml
+ $(MAKE_TEXT) README.sgml && mv README.txt README
+endif
+
+EXTRA_DIST = README.sgml
diff --git a/driver/xf86-video-i810/Makefile.bsd-wrapper b/driver/xf86-video-i810/Makefile.bsd-wrapper
new file mode 100644
index 000000000..ce45426e7
--- /dev/null
+++ b/driver/xf86-video-i810/Makefile.bsd-wrapper
@@ -0,0 +1,3 @@
+# $OpenBSD: Makefile.bsd-wrapper,v 1.1 2007/04/04 20:17:39 matthieu Exp $
+
+.include <bsd.xorg.mk>
diff --git a/driver/xf86-video-i810/README b/driver/xf86-video-i810/README
new file mode 100644
index 000000000..46d6747d0
--- /dev/null
+++ b/driver/xf86-video-i810/README
@@ -0,0 +1,166 @@
+ $XFree86:
+ xc/programs/Xserver/hw/xfree86/doc/sgml/i810.sgml,v 1.4
+ 2001/04/04 01:34:18 dawes Exp $ Information for i810 Users
+ Precision Insight, Inc.
+ 3 March 2000
+ ____________________________________________________________
+
+ Table of Contents
+
+
+ 1. Introduction
+ 2. Supported Hardware
+ 3. Features
+ 4. Technical Notes
+ 5. Reported Working Video Cards
+ 6. Configuration
+ 7. Driver Options
+ 8. Known Limitations
+ 9. Author
+
+
+ ______________________________________________________________________
+
+ 1. Introduction
+
+ This document provides a brief summary of the i810/i815 support
+ provided by the i810 driver. Support for later chipsets is not
+ covered here. More up to date information about the i810 driver can
+ be found in the i810(4) manual page.
+
+
+ 2. Supported Hardware
+
+
+ +o Intel 810 motherboards:
+
+ +o i810,
+
+ +o i810-dc100,
+
+ +o i810e
+
+ +o i815
+
+
+
+ 3. Features
+
+
+ +o Full support for 8, 15, 16, and 24 bit pixel depths.
+
+ +o Hardware cursor support to reduce sprite flicker.
+
+ +o Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24
+ bit pixel depths.
+
+ +o Support for high resolution video modes up to 1600x1200.
+
+ +o Fully programmable clock supported.
+
+ +o Robust text mode restore for VT switching.
+
+
+
+ 4. Technical Notes
+
+
+ +o Hardware acceleration is not possible when using the framebuffer in
+ 32 bit per pixel format, and this mode is not supported by this
+ driver.
+
+ +o Interlace modes cannot be supported.
+
+ +o 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.
+
+
+
+ 5. Reported Working Video Cards
+
+
+ +o Intel evaluation hardware - i810, i810-dc100, i810e and i815.
+
+ +o Tyan Tomcat Motherboard.
+
+ +o HappyPC set-top box.
+
+
+
+ 6. Configuration
+
+ The driver auto-detects all device information necessary to initialize
+ the card. The only lines you need in the "Device" section of your
+ xorg.conf file are:
+
+ Section "Device"
+ Identifier "Intel i810"
+ Driver "i810"
+ EndSection
+
+
+ or let xorgconfig do this for you.
+
+ However, if you have problems with auto-detection, you can specify:
+
+ +o DacSpeed - in MHz
+
+ +o MemBase - physical address of the linear framebuffer
+
+ +o IOBase - physical address of the memory mapped IO registers
+
+ In order to use most resolutions, it is necessary to install the (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.
+
+
+
+ 7. Driver Options
+
+
+ +o "NoAccel" - Turn off hardware acceleration
+
+
+ +o "SWCursor" - Request a software cursor (hardware is default)
+
+ +o "Dac6Bit" - Force the use of a 6 Bit Dac (8 Bit is the default)
+
+
+ 8. Known Limitations
+
+
+ +o No 3D support in this release.
+
+ +o Running two X servers on different VTs is not supported at this
+ time.
+
+
+
+ 9. Author
+
+
+ +o Keith Whitwell
+
+ The X11R6.8 version of this driver originally came from XFree86 4.4
+ rc2.
+
+ The XFree86 version of this driver was donated to The XFree86 Project
+ by:
+
+ Precision Insight, Inc.
+ Cedar Park, TX
+ USA
+
+
+
+ http://www.precisioninsight.com
+
+
+
diff --git a/driver/xf86-video-i810/README.sgml b/driver/xf86-video-i810/README.sgml
new file mode 100644
index 000000000..2aba95fd7
--- /dev/null
+++ b/driver/xf86-video-i810/README.sgml
@@ -0,0 +1,136 @@
+<!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.4 2001/04/04 01:34:18 dawes Exp $
+</ident>
+<toc>
+
+<sect>Introduction
+<p>
+This document provides a brief summary of the i810/i815 support provided
+by the i810 driver. Support for later chipsets is not covered here.
+More up to date information about the i810 driver can be found in the
+<htmlurl name="i810(4)" url="i810.4.html"> manual page.
+
+<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 xorg.conf file are:
+<verb>
+ Section "Device"
+ Identifier "Intel i810"
+ Driver "i810"
+ EndSection
+</verb>
+or let <tt>xorgconfig</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>
+
+The X11R&relvers; version of this driver originally came from XFree86 4.4 rc2.
+
+The XFree86 version of 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/driver/xf86-video-i810/autogen.sh b/driver/xf86-video-i810/autogen.sh
new file mode 100644
index 000000000..904cd6746
--- /dev/null
+++ b/driver/xf86-video-i810/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/driver/xf86-video-i810/configure.ac b/driver/xf86-video-i810/configure.ac
new file mode 100644
index 000000000..e50b3d18a
--- /dev/null
+++ b/driver/xf86-video-i810/configure.ac
@@ -0,0 +1,116 @@
+# Copyright 2005 Adam Jackson.
+#
+# 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
+# ADAM JACKSON 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.
+#
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ(2.57)
+AC_INIT([xf86-video-i810],
+ 1.4.1.3,
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+ xf86-video-i810)
+
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_AUX_DIR(.)
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_MAINTAINER_MODE
+
+# Checks for programs.
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_CC
+
+AH_TOP([#include "xorg-server.h"])
+
+AC_ARG_WITH(xorg-module-dir,
+ AC_HELP_STRING([--with-xorg-module-dir=DIR],
+ [Default xorg module directory [[default=$libdir/xorg/modules]]]),
+ [moduledir="$withval"],
+ [moduledir="$libdir/xorg/modules"])
+
+AC_ARG_ENABLE(dri, AC_HELP_STRING([--disable-dri],
+ [Disable DRI support [[default=auto]]]),
+ [DRI="$enableval"],
+ [DRI=auto])
+
+
+# Checks for extensions
+XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
+XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
+XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto x11)
+XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+
+# Checks for pkg-config packages
+PKG_CHECK_MODULES(XORG, [xorg-server xproto xvmc fontsproto $REQUIRED_MODULES])
+sdkdir=$(pkg-config --variable=sdkdir xorg-server)
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+
+if test "$DRI" != no; then
+ AC_CHECK_FILE([${sdkdir}/dri.h],
+ [have_dri_h="yes"], [have_dri_h="no"])
+ AC_CHECK_FILE([${sdkdir}/sarea.h],
+ [have_sarea_h="yes"], [have_sarea_h="no"])
+ AC_CHECK_FILE([${sdkdir}/dristruct.h],
+ [have_dristruct_h="yes"], [have_dristruct_h="no"])
+fi
+
+AC_MSG_CHECKING([whether to include DRI support])
+if test x$DRI = xauto; then
+ if test "$have_dri_h" = yes -a \
+ "$have_sarea_h" = yes -a \
+ "$have_dristruct_h" = yes; then
+ DRI="yes"
+ else
+ DRI="no"
+ fi
+fi
+AC_MSG_RESULT([$DRI])
+
+AM_CONDITIONAL(DRI, test x$DRI = xyes)
+if test "$DRI" = yes; then
+ PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto])
+ AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
+ AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
+fi
+
+AC_SUBST([DRI_CFLAGS])
+AC_SUBST([XORG_CFLAGS])
+AC_SUBST([moduledir])
+
+DRIVER_NAME=i810
+AC_SUBST([DRIVER_NAME])
+
+XORG_MANPAGE_SECTIONS
+XORG_RELEASE_VERSION
+
+XORG_CHECK_LINUXDOC
+
+AC_OUTPUT([
+ Makefile
+ src/Makefile
+ src/xvmc/Makefile
+ man/Makefile
+])
diff --git a/driver/xf86-video-i810/man/.cvsignore b/driver/xf86-video-i810/man/.cvsignore
new file mode 100644
index 000000000..282522db0
--- /dev/null
+++ b/driver/xf86-video-i810/man/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/driver/xf86-video-i810/man/Makefile.am b/driver/xf86-video-i810/man/Makefile.am
new file mode 100644
index 000000000..47f9ebef2
--- /dev/null
+++ b/driver/xf86-video-i810/man/Makefile.am
@@ -0,0 +1,59 @@
+# $Id: Makefile.am,v 1.1 2007/04/04 20:17:40 matthieu Exp $
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+#
+# 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.
+#
+# The above copyright notice and this permission notice 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 THE OPEN GROUP 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.
+#
+# Except as contained in this notice, the name of the copyright holders shall
+# not be used in advertising or otherwise to promote the sale, use or
+# other dealings in this Software without prior written authorization
+# from the copyright holders.
+#
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+CLEANFILES = $(driverman_DATA)
+
+SED = sed
+
+# Strings to replace in man pages
+XORGRELSTRING = @PACKAGE_STRING@
+ XORGMANNAME = X Version 11
+
+MAN_SUBSTS = \
+ -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+ -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+ -e 's|__xservername__|Xorg|g' \
+ -e 's|__xconfigfile__|xorg.conf|g' \
+ -e 's|__projectroot__|$(prefix)|g' \
+ -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
+ -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
+ -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
+ -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
+ -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+ sed $(MAN_SUBSTS) < $< > $@
diff --git a/driver/xf86-video-i810/man/i810.man b/driver/xf86-video-i810/man/i810.man
new file mode 100644
index 000000000..8c432efff
--- /dev/null
+++ b/driver/xf86-video-i810/man/i810.man
@@ -0,0 +1,214 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man,v 1.5 2003/10/18 02:27:07 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 __xservername__ driver for Intel integrated graphics chipsets.
+The driver supports depths 8, 15, 16 and 24. All visual types are
+supported in depth 8. For the i810/i815 other depths support the
+TrueColor and DirectColor visuals. For the 830M and later, only the
+TrueColor visual is supported for depths greater than 8. 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
+the 830M and later.
+.SH SUPPORTED HARDWARE
+.B i810
+supports the i810, i810-DC100, i810e, i815, 830M, 845G, 852GM, 855GM,
+865G, 915G and 915GM chipsets.
+
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__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. For the i810 and
+i815 family of chipset, operating system support for allocating system
+memory for video use is required in order to use this driver. For the
+830M and later, this is required in order for the driver to use more
+video ram than has been pre-allocated at boot time by the BIOS. This
+is usually achieved with an "agpgart" or "agp" kernel driver. Linux,
+and recent versions of FreeBSD, OpenBSD and NetBSD have such kernel
+drivers available.
+.PP
+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. It is advisable to check the
+__xservername__
+log file to check if any features have been disabled because of insufficient
+video memory. In particular, DRI support or tiling mode may be disabled
+with insufficient video memory. Either of these being disabled will
+reduce performance for 3D applications. Note however, that increasing
+this value too much will reduce the amount of system memory available
+for other applications.
+.PP
+The driver makes use of the video BIOS to program video modes for the 830M
+and later. This limits the video modes that can be used to those provided
+by the video BIOS, and to those that will fit into the amount of video memory
+that the video BIOS is aware of.
+.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 for configurations where the hardware cursor
+is available.
+.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: depends on the resolution, depth, and available video memory. The
+driver attempts to allocate at least enough to hold two DVD-sized YUV buffers
+by default. The default used for a specific configuration can be found
+by examining the __xservername__ log file.
+.TP
+.BI "Option \*qDRI\*q \*q" boolean \*q
+Disable or enable DRI support.
+Default: DRI is enabled for configurations where it is supported.
+
+.PP
+The following driver
+.B Options
+are supported for the i810 and i815 chipsets:
+.TP
+.BI "Option \*qDDC\*q \*q" boolean \*q
+Disable or enable DDC support.
+Default: enabled.
+.TP
+.BI "Option \*qDac6Bit\*q \*q" boolean \*q
+Enable or disable 6-bits per RGB for 8-bit modes.
+Default: 8-bits per RGB for 8-bit modes.
+.TP
+.BI "Option \*qXvMCSurfaces\*q \*q" integer \*q
+This option enables XvMC. The integer parameter specifies the number of
+surfaces to use. Valid values are 6 and 7.
+Default: XvMC is disabled.
+
+.PP
+The following driver
+.B Options
+are supported for the 830M and later chipsets:
+.TP
+.BI "Option \*qVBERestore\*q \*q" boolean \*q
+Enable or disable the use of VBE save/restore for saving and restoring
+the initial text mode. This is disabled by default because it causes
+lockups on some platforms. However, there are some cases where it must
+enabled for the correct restoration of the initial video mode. If you are
+having a problem with that, try enabling this option. Default: Disabled.
+.TP
+.BI "Option \*qVideoKey\*q \*q" integer \*q
+This is the same as the
+.B \*qColorKey\*q
+option described above. It is provided for compatibility with most
+other drivers.
+.TP
+.BI "Option \*qXVideo\*q \*q" boolean \*q
+Disable or enable XVideo support.
+Default: XVideo is enabled for configurations where it is supported.
+.TP
+.BI "Option \*qMonitorLayout\*q \*q" anystr \*q
+Allow different monitor configurations. e.g. \*qCRT,LFP\*q will
+configure a CRT on Pipe A and an LFP on Pipe B. Regardless of the
+primary heads' pipe it is always configured as \*q<PIPEA>,<PIPEB>\*q.
+Additionally you can add different configurations such as
+\*qCRT+DFP,LFP\*q which would put a digital flat panel and a CRT
+on pipe A, and a local flat panel on pipe B.
+For single pipe configurations you can just specify the monitors types
+on Pipe A, such as \*qCRT+DFP\*q which will enable the CRT and DFP
+on Pipe A.
+Valid monitors are CRT, LFP, DFP, TV, CRT2, LFP2, DFP2, TV2 and NONE.
+NOTE: Some configurations of monitor types may fail, this depends on
+the Video BIOS and system configuration.
+Default: Not configured, and will use the current head's pipe and monitor.
+.TP
+.BI "Option \*qClone\*q \*q" boolean \*q
+Enable Clone mode on pipe B. This will setup the second head as a complete
+mirror of the monitor attached to pipe A.
+NOTE: Video overlay functions will not work on the second head in this mode.
+If you require this, then use the MonitorLayout above and do (as an example)
+\*qCRT+DFP,NONE\*q to configure both a CRT and DFP on Pipe A to achieve
+local mirroring and disable the use of this option.
+Default: Clone mode on pipe B is disabled.
+.TP
+.BI "Option \*qCloneRefresh\*q \*q" integer \*q
+When the Clone option is specified we can drive the second monitor at a
+different refresh rate than the primary.
+Default: 60Hz.
+.TP
+.BI "Option \*qCheckLid\*q \*q" boolean \*q
+On mobile platforms it's desirable to monitor the lid status and switch
+the outputs accordingly when the lid is opened or closed. By default this
+option is on, but may incur a very minor performance penalty as we need
+to poll a register on the card to check for this activity. It can be
+turned off using this option. This only works with the 830M, 852GM and 855GM
+systems.
+Default: enabled.
+.TP
+.BI "Option \*qFlipPrimary\*q \*q" boolean \*q
+When using a dual pipe system, it may be preferable to switch the primary
+screen to the alternate pipe to display on the other monitor connection.
+NOTE: Using this option may cause text mode to be restored incorrectly,
+and thus should be used with caution.
+Default: disabled.
+.TP
+.BI "Option \*qDisplayInfo\*q \*q" boolean \*q
+It has been found that a certain BIOS call can lockup the Xserver because
+of a problem in the Video BIOS. The log file will identify if you are
+suffering from this problem and tell you to turn this option off.
+Default: enabled
+.TP
+.BI "Option \*qDevicePresence\*q \*q" boolean \*q
+Tell the driver to perform an active detect of the currently connected
+monitors. This option is useful if the monitor was not connected when
+the machine has booted, but unfortunately it doesn't always work and
+is extremely dependent upon the Video BIOS.
+Default: disabled
+.TP
+.BI "Option \*qRotate\*q \*qCW\*q"
+.TP
+.BI "Option \*qRotate\*q \*qCCW\*q"
+Rotate the desktop 90 degrees clockwise or counterclockwise. This option
+forces the ShadowFB option on, and disables acceleration.
+Default: no rotation.
+.TP
+.BI "Option \*qShadowFB\*q \*q" boolean \*q
+Enable or disable use of the shadow framebuffer layer. This option
+disables acceleration. Default: off.
+
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), 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.
+915G and 915GM support added by Alan Hourihane and Keith Whitwell.
+Dual Head, Clone and lid status support added by Alan Hourihane.
diff --git a/driver/xf86-video-i810/src/.cvsignore b/driver/xf86-video-i810/src/.cvsignore
new file mode 100644
index 000000000..9730646fd
--- /dev/null
+++ b/driver/xf86-video-i810/src/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
diff --git a/driver/xf86-video-i810/src/Makefile.am b/driver/xf86-video-i810/src/Makefile.am
new file mode 100644
index 000000000..fa695928d
--- /dev/null
+++ b/driver/xf86-video-i810/src/Makefile.am
@@ -0,0 +1,65 @@
+# Copyright 2005 Adam Jackson.
+#
+# 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
+# ADAM JACKSON 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.
+
+SUBDIRS = xvmc
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
+
+i810_drv_la_LTLIBRARIES = i810_drv.la
+i810_drv_la_LDFLAGS = -module -avoid-version
+i810_drv_ladir = @moduledir@/drivers
+
+i810_drv_la_SOURCES = \
+ common.h \
+ i810_accel.c \
+ i810_common.h \
+ i810_cursor.c \
+ i810_dga.c \
+ i810_driver.c \
+ i810.h \
+ i810_io.c \
+ i810_memory.c \
+ i810_reg.h \
+ i810_video.c \
+ i810_wmark.c \
+ i830_accel.c \
+ i830_common.h \
+ i830_cursor.c \
+ i830_dga.c \
+ i830_driver.c \
+ i830.h \
+ i830_io.c \
+ i830_memory.c \
+ i830_modes.c \
+ i830_video.c \
+ i830_shadow.c
+
+if DRI
+i810_drv_la_SOURCES += \
+ i810_dri.c \
+ i810_dri.h \
+ i830_dri.c \
+ i810_hwmc.c \
+ i830_dri.h
+endif
diff --git a/driver/xf86-video-i810/src/common.h b/driver/xf86-video-i810/src/common.h
new file mode 100644
index 000000000..85a24ab34
--- /dev/null
+++ b/driver/xf86-video-i810/src/common.h
@@ -0,0 +1,363 @@
+
+/**************************************************************************
+
+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.9 2003/09/24 02:43:23 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@xfree86.org>
+ *
+ */
+
+#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 *I810shadowFBSymbols[];
+#ifdef XF86DRI
+extern const char *I810driSymbols[];
+extern const char *I810drmSymbols[];
+extern const char *I810shadowSymbols[];
+#endif
+
+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 %lx: %x, (mask %x)\n", \
+ (unsigned long)(outring), (unsigned int)(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; \
+ 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; \
+ 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%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(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%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(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%lx, 0x%lx) in %s\n", (unsigned long)(addr), \
+ (unsigned long)(val), FUNCTION_NAME); \
+ } \
+} while (0)
+
+/* To remove all debugging, make sure I810_DEBUG is defined as a
+ * preprocessor symbol, and equal to zero.
+ */
+#if 1
+#define I810_DEBUG 0
+#endif
+#ifndef I810_DEBUG
+#warning "Debugging enabled - expect reduced performance"
+extern int I810_DEBUG;
+#endif
+
+#define DEBUG_VERBOSE_ACCEL 0x1
+#define DEBUG_VERBOSE_SYNC 0x2
+#define DEBUG_VERBOSE_VGA 0x4
+#define DEBUG_VERBOSE_RING 0x8
+#define DEBUG_VERBOSE_OUTREG 0x10
+#define DEBUG_VERBOSE_MEMORY 0x20
+#define DEBUG_VERBOSE_CURSOR 0x40
+#define DEBUG_ALWAYS_SYNC 0x80
+#define DEBUG_VERBOSE_DRI 0x100
+#define DEBUG_VERBOSE_BIOS 0x200
+
+/* Size of the mmio region.
+ */
+#define I810_REG_SIZE 0x80000
+
+#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
+
+#ifndef PCI_CHIP_I915_G
+#define PCI_CHIP_I915_G 0x2582
+#define PCI_CHIP_I915_G_BRIDGE 0x2580
+#endif
+
+#ifndef PCI_CHIP_I915_GM
+#define PCI_CHIP_I915_GM 0x2592
+#define PCI_CHIP_I915_GM_BRIDGE 0x2590
+#endif
+
+#ifndef PCI_CHIP_E7221_G
+#define PCI_CHIP_E7221_G 0x258A
+/* Same as I915_G_BRIDGE */
+#define PCI_CHIP_E7221_G_BRIDGE 0x2580
+#endif
+
+#ifndef PCI_CHIP_I945_G
+#define PCI_CHIP_I945_G 0x2772
+#define PCI_CHIP_I945_G_BRIDGE 0x2770
+#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_I852(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
+#define IS_I855(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
+#define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G)
+#define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
+#define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
+
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(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 HWCURSOR_SIZE_ARGB GTT_PAGE_SIZE * 4
+#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/driver/xf86-video-i810/src/i810.h b/driver/xf86-video-i810/src/i810.h
new file mode 100644
index 000000000..198f0eca8
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810.h
@@ -0,0 +1,339 @@
+
+/**************************************************************************
+
+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.41 2003/06/18 13:14:17 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@xfree86.org>
+ *
+ */
+
+#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 "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 4
+#define I810_PATCHLEVEL 1
+
+
+/* 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;
+
+ Bool CursorIsARGB;
+ int CursorOffset;
+ unsigned long CursorPhysical;
+ unsigned long CursorStart;
+ int CursorARGBOffset;
+ unsigned long CursorARGBPhysical;
+ unsigned long CursorARGBStart;
+ unsigned long OverlayPhysical;
+ unsigned long OverlayStart;
+ int colorKey;
+ unsigned int surfaceAllocation[I810_TOTAL_SURFACES];
+ int numSurfaces;
+
+ DGAModePtr DGAModes;
+ int numDGAModes;
+ Bool DGAactive;
+ int DGAViewportStatus;
+
+ int Chipset;
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+ IOADDRESS ioBase;
+ EntityInfoPtr pEnt;
+ 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 ARGBHwcursKey;
+ unsigned long ARGBHwcursOffset;
+
+ int GttBound;
+
+ I810MemRange DcacheMem;
+ I810MemRange SysMem;
+
+ I810MemRange SavedDcacheMem;
+ I810MemRange SavedSysMem;
+
+ unsigned char **ScanlineColorExpandBuffers;
+ int NumScanlineColorExpandBuffers;
+ int nextColorExpandBuf;
+
+ I810RegRec SavedReg;
+ I810RegRec ModeReg;
+
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ CloseScreenProcPtr CloseScreen;
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+ I810WriteIndexedByteFunc writeControl;
+ I810ReadIndexedByteFunc readControl;
+ I810WriteByteFunc writeStandard;
+ I810ReadByteFunc readStandard;
+
+ Bool directRenderingDisabled; /* DRI disabled in PreInit */
+ Bool directRenderingEnabled; /* false if XF86DRI not defined. */
+
+#ifdef XF86DRI
+ int LockHeld;
+ DRIInfoPtr pDRIInfo;
+ int drmSubFD;
+ int numVisualConfigs;
+ __GLXvisualConfig *pVisualConfigs;
+ I810ConfigPrivPtr pVisualConfigsPriv;
+ unsigned long dcacheHandle;
+ unsigned long backHandle;
+ unsigned long zHandle;
+ unsigned long cursorHandle;
+ unsigned long cursorARGBHandle;
+ unsigned long xvmcHandle;
+ unsigned long sysmemHandle;
+ Bool agpAcquired;
+ drm_handle_t buffer_map;
+ drm_handle_t ring_map;
+ drm_handle_t overlay_map;
+ drm_handle_t mc_map;
+ drm_handle_t xvmcContext;
+#endif
+ Bool agpAcquired2d;
+
+ XF86VideoAdaptorPtr adaptor;
+ OptionInfoPtr Options;
+
+ int configured_device;
+
+ Bool showCache;
+ Bool noAccel;
+ Bool allowPageFlip;
+ Bool have3DWindows;
+ int drmMinor;
+} I810Rec;
+
+#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
+
+#define I810_SELECT_FRONT 0
+#define I810_SELECT_BACK 1
+#define I810_SELECT_DEPTH 2
+
+#ifdef XF86DRI
+extern Bool I810DRIScreenInit(ScreenPtr pScreen);
+extern void I810DRICloseScreen(ScreenPtr pScreen);
+extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen);
+extern Bool I810DRILeave(ScrnInfoPtr pScrn);
+extern Bool I810DRIEnter(ScrnInfoPtr pScrn);
+#endif
+extern Bool I810InitDma(ScrnInfoPtr pScrn);
+extern Bool I810CleanupDma(ScrnInfoPtr pScrn);
+
+#define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
+#define I810REGPTR(p) (&(I810PTR(p)->ModeReg))
+
+extern Bool I810CursorInit(ScreenPtr pScreen);
+extern Bool I810AccelInit(ScreenPtr pScreen);
+extern void I810SetPIOAccess(I810Ptr pI810);
+extern void I810SetMMIOAccess(I810Ptr pI810);
+extern unsigned int I810CalcWatermark(ScrnInfoPtr pScrn, double freq,
+ Bool dcache);
+extern void I810PrintErrorState(ScrnInfoPtr pScrn);
+extern int I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
+extern void I810Sync(ScrnInfoPtr pScrn);
+extern unsigned long I810LocalToPhysical(ScrnInfoPtr pScrn,
+ unsigned long local);
+extern int I810AllocLow(I810MemRange * result, I810MemRange * pool,
+ int size);
+extern int I810AllocHigh(I810MemRange * result, I810MemRange * pool,
+ int size);
+extern Bool I810AllocateFront(ScrnInfoPtr pScrn);
+
+extern int I810AllocateGARTMemory(ScrnInfoPtr pScrn);
+extern void I810FreeGARTMemory(ScrnInfoPtr pScrn);
+
+extern Bool I810BindGARTMemory(ScrnInfoPtr pScrn);
+extern Bool I810UnbindGARTMemory(ScrnInfoPtr pScrn);
+
+extern int I810CheckAvailableMemory(ScrnInfoPtr pScrn);
+
+extern Bool I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+extern void I810AdjustFrame(int scrnIndex, int x, int y, int flags);
+
+extern void I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
+ int ydir, int rop,
+ unsigned int planemask,
+ int trans_color);
+extern void I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
+ int srcY, int dstX, int dstY,
+ int w, int h);
+extern void I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+extern void I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+
+extern void I810SelectBuffer(ScrnInfoPtr pScrn, int buffer);
+
+extern void I810RefreshRing(ScrnInfoPtr pScrn);
+extern void I810EmitFlush(ScrnInfoPtr pScrn);
+extern void I810EmitInvarientState(ScrnInfoPtr pScrn);
+
+extern Bool I810DGAInit(ScreenPtr pScreen);
+
+extern void I810InitVideo(ScreenPtr pScreen);
+extern void I810InitMC(ScreenPtr pScreen);
+
+extern const OptionInfoRec *I810AvailableOptions(int chipid, int busid);
+
+#endif /* _I810_H_ */
diff --git a/driver/xf86-video-i810/src/i810_accel.c b/driver/xf86-video-i810/src/i810_accel.c
new file mode 100644
index 000000000..f946ae2a2
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_accel.c
@@ -0,0 +1,631 @@
+
+/**************************************************************************
+
+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.21 2004/01/02 20:22:17 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * 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 "xaarop.h"
+#include "i810.h"
+
+static void I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
+ int pattx, int patty,
+ int x, int y, int w, int h);
+
+static void I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg,
+ int rop,
+ unsigned int mask);
+
+static void I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr
+ pScrn, int x,
+ int y, int w,
+ int h,
+ int skipleft);
+
+static void I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
+
+/* The following function sets up the supported acceleration. Call it
+ * from the FbInit() function in the SVGA driver, or before ScreenInit
+ * in a monolithic server.
+ */
+Bool
+I810AccelInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810AccelInit\n");
+
+ pI810->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ pI810->bufferOffset = 0;
+ infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
+ infoPtr->Flags |= PIXMAP_CACHE;
+
+ /* Sync
+ */
+ infoPtr->Sync = I810Sync;
+
+ /* Solid filled rectangles
+ */
+ {
+ infoPtr->SolidFillFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidFill = I810SetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = I810SubsequentSolidFillRect;
+ }
+
+ /* Screen to screen copy
+ * - the transparency op hangs the blit engine, disable for now.
+ */
+ {
+ infoPtr->ScreenToScreenCopyFlags = (0
+ | NO_PLANEMASK
+ | NO_TRANSPARENCY | 0);
+
+ infoPtr->SetupForScreenToScreenCopy = I810SetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy =
+ I810SubsequentScreenToScreenCopy;
+ }
+
+ /* 8x8 pattern fills
+ */
+ {
+ infoPtr->SetupForMono8x8PatternFill = I810SetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ I810SubsequentMono8x8PatternFillRect;
+
+ infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_SCREEN_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+ NO_PLANEMASK | 0);
+ }
+
+ /* 8x8 color fills - not considered useful for XAA.
+ */
+
+ /* Scanline color expansion - Use the same scheme as the 3.3 driver.
+ *
+ */
+ if (pI810->Scratch.Size != 0) {
+ int i;
+ int width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ int nr_buffers = pI810->Scratch.Size / width;
+ unsigned char *ptr = pI810->FbBase + pI810->Scratch.Start;
+
+ pI810->NumScanlineColorExpandBuffers = nr_buffers;
+ pI810->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(nr_buffers, sizeof(unsigned char *));
+
+ for (i = 0; i < nr_buffers; i++, ptr += width)
+ pI810->ScanlineColorExpandBuffers[i] = ptr;
+
+ infoPtr->ScanlineCPUToScreenColorExpandFillFlags = (NO_PLANEMASK |
+ ROP_NEEDS_SOURCE |
+ BIT_ORDER_IN_BYTE_MSBFIRST
+ | 0);
+
+ infoPtr->ScanlineColorExpandBuffers = (unsigned char **)
+ xnfcalloc(1, sizeof(unsigned char *));
+ infoPtr->NumScanlineColorExpandBuffers = 1;
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI810->ScanlineColorExpandBuffers[0];
+ pI810->nextColorExpandBuf = 0;
+
+ infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
+ I810SetupForScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ I810SubsequentScanlineCPUToScreenColorExpandFill;
+
+ infoPtr->SubsequentColorExpandScanline =
+ I810SubsequentColorExpandScanline;
+ }
+
+ /* Possible todo: Image writes w/ non-GXCOPY rop.
+ */
+
+ I810SelectBuffer(pScrn, I810_SELECT_FRONT);
+
+ return XAAInit(pScreen, infoPtr);
+}
+
+int
+I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RingBuffer *ring = pI810->LpRing;
+ int iters = 0;
+ int start = 0;
+ int now = 0;
+ int last_head = 0;
+ int first = 0;
+
+ /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
+ * call it crashed.
+ */
+ if (timeout_millis == 0)
+ timeout_millis = 2000;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
+ ErrorF("I810WaitLpRing %d\n", n);
+ first = GetTimeInMillis();
+ }
+
+ while (ring->space < n) {
+ ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring->space = ring->head - (ring->tail + 8);
+
+ if (ring->space < 0)
+ ring->space += ring->mem.Size;
+
+ iters++;
+ now = GetTimeInMillis();
+ if (start == 0 || now < start || ring->head != last_head) {
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ if (now > start)
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+ start = now;
+ last_head = ring->head;
+ } else if (now - start > timeout_millis) {
+ ErrorF("Error in I810WaitLpRing(), now is %d, start is %d\n", now,
+ start);
+ I810PrintErrorState(pScrn);
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ pI810->AccelInfoRec = NULL; /* Stops recursive behavior */
+ FatalError("lockup\n");
+ }
+
+ DELAY(10000);
+ }
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
+ now = GetTimeInMillis();
+ if (now - first) {
+ ErrorF("Elapsed %d ms\n", now - first);
+ ErrorF("space: %d wanted %d\n", ring->space, n);
+ }
+ }
+
+ return iters;
+}
+
+void
+I810Sync(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
+ ErrorF("I810Sync\n");
+
+#ifdef XF86DRI
+ /* VT switching tries to do this.
+ */
+ if (!pI810->LockHeld && pI810->directRenderingEnabled) {
+ return;
+ }
+#endif
+
+ /* Send a flush instruction and then wait till the ring is empty.
+ * This is stronger than waiting for the blitter to finish as it also
+ * flushes the internal graphics caches.
+ */
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ I810WaitLpRing(pScrn, pI810->LpRing->mem.Size - 8, 0);
+
+ pI810->LpRing->space = pI810->LpRing->mem.Size - 8;
+ pI810->nextColorExpandBuf = 0;
+}
+
+void
+I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForFillRectSolid color: %x rop: %x mask: %x\n",
+ color, rop, planemask);
+
+ /* Color blit, p166 */
+ pI810->BR[13] = (BR13_SOLID_PATTERN |
+ (XAAGetPatternROP(rop) << 16) |
+ (pScrn->displayWidth * pI810->cpp));
+ pI810->BR[16] = color;
+}
+
+void
+I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h);
+
+ {
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+ OUT_RING(pI810->BR[13]);
+ OUT_RING((h << 16) | (w * pI810->cpp));
+ OUT_RING(pI810->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI810->cpp);
+
+ OUT_RING(pI810->BR[16]);
+ OUT_RING(0); /* pad to quadword */
+
+ ADVANCE_LP_RING();
+ }
+}
+
+void
+I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int transparency_color)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForScreenToScreenCopy %d %d %x %x %d\n",
+ xdir, ydir, rop, planemask, transparency_color);
+
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+
+ if (ydir == -1)
+ pI810->BR[13] = (-pI810->BR[13]) & 0xFFFF;
+ if (xdir == -1)
+ pI810->BR[13] |= BR13_RIGHT_TO_LEFT;
+
+ pI810->BR[13] |= XAAGetCopyROP(rop) << 16;
+
+ pI810->BR[18] = 0;
+}
+
+void
+I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int src, dst;
+ int w_back = w;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF( "I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n",
+ x1,y1,x2,y2,w,h);
+ /*
+ * This works around a bug in the i810 drawing engine.
+ * This was developed empirically so it may not catch all
+ * cases.
+ */
+#define I810_MWIDTH 8
+
+ if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3
+ && (y2 - y1) >= 0 && (x2 - x1) <= (w + I810_MWIDTH)
+ && (w > I810_MWIDTH))
+ w = I810_MWIDTH;
+ do {
+
+ if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) {
+ src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp;
+ } else {
+ src = y1 * pScrn->displayWidth * pI810->cpp;
+ dst = y2 * pScrn->displayWidth * pI810->cpp;
+ }
+
+ if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) {
+ src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1;
+ } else {
+ src += x1 * pI810->cpp;
+ dst += x2 * pI810->cpp;
+ }
+
+
+ /* SRC_COPY_BLT, p169 */
+ {
+ BEGIN_LP_RING(6);
+ OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+ OUT_RING( pI810->BR[13]);
+
+ OUT_RING( (h << 16) | (w * pI810->cpp));
+ OUT_RING( pI810->bufferOffset + dst);
+
+ OUT_RING( pI810->BR[13] & 0xFFFF);
+ OUT_RING( pI810->bufferOffset + src);
+ ADVANCE_LP_RING();
+ }
+ w_back -= w;
+ if (w_back <= 0)
+ break;
+ x2 += w;
+ x1 += w;
+ if (w_back > I810_MWIDTH)
+ w = I810_MWIDTH;
+ else
+ w = w_back;
+ } while (1);
+}
+
+static void
+I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupFor8x8PatternColorExpand\n");
+
+ /* FULL_MONO_PAT_BLT, p176 */
+ pI810->BR[0] = (BR00_BITBLT_CLIENT | BR00_OP_MONO_PAT_BLT | 0x9);
+ pI810->BR[18] = bg;
+ pI810->BR[19] = fg;
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+ pI810->BR[13] |= XAAGetPatternROP(rop) << 16;
+ if (bg == -1)
+ pI810->BR[13] |= BR13_MONO_PATN_TRANS;
+}
+
+static void
+I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty,
+ int x, int y, int w, int h)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int addr =
+ pI810->bufferOffset + (y * pScrn->displayWidth + x) * pI810->cpp;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810Subsequent8x8PatternColorExpand\n");
+
+ {
+ BEGIN_LP_RING(12);
+ OUT_RING(pI810->BR[0] | ((y << 5) & BR00_PAT_VERT_ALIGN));
+ OUT_RING(pI810->BR[13]);
+ OUT_RING((h << 16) | (w * pI810->cpp));
+ OUT_RING(addr);
+ OUT_RING(pI810->BR[13] & 0xFFFF); /* src pitch */
+ OUT_RING(addr); /* src addr */
+ OUT_RING(0); /* transparency color */
+ OUT_RING(pI810->BR[18]); /* bg */
+ OUT_RING(pI810->BR[19]); /* fg */
+ OUT_RING(pattx); /* pattern data */
+ OUT_RING(patty);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I810GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
+
+ if (pI810->nextColorExpandBuf == pI810->NumScanlineColorExpandBuffers)
+ I810Sync(pScrn);
+
+ infoPtr->ScanlineColorExpandBuffers[0] =
+ pI810->ScanlineColorExpandBuffers[pI810->nextColorExpandBuf];
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("using color expand buffer %d\n", pI810->nextColorExpandBuf);
+
+ pI810->nextColorExpandBuf++;
+}
+
+static void
+I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n",
+ fg, bg, rop, planemask);
+
+ pI810->BR[13] = (pScrn->displayWidth * pI810->cpp);
+ pI810->BR[13] |= XAAGetCopyROP(rop) << 16;
+ pI810->BR[13] |= (1 << 27);
+ if (bg == -1)
+ pI810->BR[13] |= BR13_MONO_TRANSPCY;
+
+ pI810->BR[18] = bg;
+ pI810->BR[19] = fg;
+
+ I810GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+static void
+I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h, int skipleft)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentScanlineCPUToScreenColorExpandFill "
+ "%d,%d %dx%x %d\n", x, y, w, h, skipleft);
+
+ pI810->BR[0] = BR00_BITBLT_CLIENT | BR00_OP_MONO_SRC_COPY_BLT | 0x06;
+ pI810->BR[9] = (pI810->bufferOffset +
+ (y * pScrn->displayWidth + x) * pI810->cpp);
+ pI810->BR[14] = ((1 << 16) | (w * pI810->cpp));
+ pI810->BR[11] = ((w + 31) / 32) - 1;
+}
+
+static void
+I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pI810->BR[12] = (pI810->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI810->FbBase);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SubsequentColorExpandScanline %d (addr %x)\n",
+ bufno, pI810->BR[12]);
+
+ {
+ BEGIN_LP_RING(8);
+ OUT_RING(pI810->BR[0]);
+ OUT_RING(pI810->BR[13]);
+ OUT_RING(pI810->BR[14]);
+ OUT_RING(pI810->BR[9]);
+ OUT_RING(pI810->BR[11]);
+ OUT_RING(pI810->BR[12]); /* srcaddr */
+ OUT_RING(pI810->BR[18]);
+ OUT_RING(pI810->BR[19]);
+ ADVANCE_LP_RING();
+ }
+
+ /* Advance to next scanline.
+ */
+ pI810->BR[9] += pScrn->displayWidth * pI810->cpp;
+ I810GetNextScanlineColorExpandBuffer(pScrn);
+}
+
+void
+I810EmitFlush(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+}
+
+void
+I810SelectBuffer(ScrnInfoPtr pScrn, int buffer)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ switch (buffer) {
+ case I810_SELECT_BACK:
+ pI810->bufferOffset = pI810->BackBuffer.Start;
+ break;
+ case I810_SELECT_DEPTH:
+ pI810->bufferOffset = pI810->DepthBuffer.Start;
+ break;
+ default:
+ case I810_SELECT_FRONT:
+ pI810->bufferOffset = pI810->FrontBuffer.Start;
+ break;
+ }
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I810SelectBuffer %d --> offset %x\n",
+ buffer, pI810->bufferOffset);
+}
+
+void
+I810RefreshRing(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ pI810->LpRing->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ pI810->LpRing->tail = INREG(LP_RING + RING_TAIL);
+ pI810->LpRing->space = pI810->LpRing->head - (pI810->LpRing->tail + 8);
+ if (pI810->LpRing->space < 0)
+ pI810->LpRing->space += pI810->LpRing->mem.Size;
+
+ 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/driver/xf86-video-i810/src/i810_common.h b/driver/xf86-video-i810/src/i810_common.h
new file mode 100644
index 000000000..02e548be0
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_common.h
@@ -0,0 +1,192 @@
+/* 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
+#define DRM_I810_FLIP 0x0e
+
+#endif
+
+typedef enum _drmI810Initfunc {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02,
+ I810_INIT_DMA_1_4 = 0x03
+} drmI810Initfunc;
+
+typedef struct {
+ drmI810Initfunc func;
+ unsigned int mmio_offset;
+ unsigned int buffers_offset;
+ int sarea_priv_offset;
+ unsigned int ring_start;
+ unsigned int ring_end;
+ unsigned int ring_size;
+ unsigned int front_offset;
+ unsigned int back_offset;
+ unsigned int depth_offset;
+ unsigned int overlay_offset;
+ unsigned int overlay_physical;
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+ unsigned int pitch_bits;
+} drmI810Init;
+
+typedef struct {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drmI810DMA;
+
+/* Flags for clear ioctl
+ */
+#define I810_FRONT 0x1
+#define I810_BACK 0x2
+#define I810_DEPTH 0x4
+
+typedef struct {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drmI810Clear;
+
+typedef struct {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+} drmI810Vertex;
+
+/* Flags for vertex ioctl
+ */
+#define PR_TRIANGLES (0x0<<18)
+#define PR_TRISTRIP_0 (0x1<<18)
+#define PR_TRISTRIP_1 (0x2<<18)
+#define PR_TRIFAN (0x3<<18)
+#define PR_POLYGON (0x4<<18)
+#define PR_LINES (0x5<<18)
+#define PR_LINESTRIP (0x6<<18)
+#define PR_RECTS (0x7<<18)
+#define PR_MASK (0x7<<18)
+
+#endif
diff --git a/driver/xf86-video-i810/src/i810_cursor.c b/driver/xf86-video-i810/src/i810_cursor.c
new file mode 100644
index 000000000..85c4e254a
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_cursor.c
@@ -0,0 +1,281 @@
+
+/**************************************************************************
+
+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.6 2002/09/11 00:29:31 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * 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>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+#include "xf86fbman.h"
+
+#include "i810.h"
+
+static Bool I810UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
+static void I810LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
+static void I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void I810ShowCursor(ScrnInfoPtr pScrn);
+static void I810HideCursor(ScrnInfoPtr pScrn);
+static void I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
+static void I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static Bool I810UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
+
+Bool
+I810CursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ I810Ptr pI810;
+ xf86CursorInfoPtr infoPtr;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI810 = I810PTR(pScrn);
+ pI810->CursorInfoRec = infoPtr = xf86CreateCursorInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+ HARDWARE_CURSOR_INVERT_MASK |
+ HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 0);
+
+ infoPtr->SetCursorColors = I810SetCursorColors;
+ infoPtr->SetCursorPosition = I810SetCursorPosition;
+ infoPtr->LoadCursorImage = I810LoadCursorImage;
+ infoPtr->HideCursor = I810HideCursor;
+ infoPtr->ShowCursor = I810ShowCursor;
+ infoPtr->UseHWCursor = I810UseHWCursor;
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = FALSE;
+
+ if (!pI810->CursorARGBPhysical) {
+ infoPtr->UseHWCursorARGB = I810UseHWCursorARGB;
+ infoPtr->LoadCursorARGB = I810LoadCursorARGB;
+ }
+#endif
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+static Bool I810UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (!pI810->CursorARGBPhysical)
+ return FALSE;
+
+ if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void I810LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ CARD32 *pcurs = (CARD32 *) (pI810->FbBase + pI810->CursorStart);
+ CARD32 *image = (CARD32 *) pCurs->bits->argb;
+ int x, y, w, h;
+
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = TRUE;
+#endif
+
+ w = pCurs->bits->width;
+ h = pCurs->bits->height;
+
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ *pcurs++ = *image++;
+ for (; x < 64; x++)
+ *pcurs++ = 0;
+ }
+
+ for (; y < 64; y++)
+ for (x = 0; x < 64; x++)
+ *pcurs++ = 0;
+}
+#endif
+
+static Bool
+I810UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (!pI810->CursorPhysical)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static void
+I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ CARD8 *pcurs = (CARD8 *) (pI810->FbBase + pI810->CursorStart);
+ int x, y;
+
+#ifdef ARGB_CURSOR
+ pI810->CursorIsARGB = FALSE;
+#endif
+
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64 / 4; x++) {
+ *pcurs++ = *src++;
+ }
+ }
+}
+
+static void
+I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int flag;
+
+ x += pI810->CursorOffset;
+
+ if (x >= 0)
+ flag = CURSOR_X_POS;
+ else {
+ flag = CURSOR_X_NEG;
+ x = -x;
+ }
+
+ OUTREG8(CURSOR_X_LO, x & 0xFF);
+ OUTREG8(CURSOR_X_HI, (((x >> 8) & 0x07) | flag));
+
+ if (y >= 0)
+ flag = CURSOR_Y_POS;
+ else {
+ flag = CURSOR_Y_NEG;
+ y = -y;
+ }
+ OUTREG8(CURSOR_Y_LO, y & 0xFF);
+ OUTREG8(CURSOR_Y_HI, (((y >> 8) & 0x07) | flag));
+
+ if (pI810->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical);
+ else
+ OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical);
+}
+
+static void
+I810ShowCursor(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ unsigned char tmp;
+
+ if (pI810->CursorIsARGB) {
+ OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical);
+ OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_ARGB_AX);
+ } else {
+ OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical);
+ OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C);
+ }
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp |= HW_CURSOR_ENABLE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I810HideCursor(ScrnInfoPtr pScrn)
+{
+ unsigned char tmp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp &= ~HW_CURSOR_ENABLE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
+
+static void
+I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ int tmp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+#ifdef ARGB_CURSOR
+ if (pI810->CursorIsARGB)
+ return;
+#endif
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp |= EXTENDED_PALETTE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+
+ pI810->writeStandard(pI810, DACMASK, 0xFF);
+ pI810->writeStandard(pI810, DACWX, 0x04);
+
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x00FF0000) >> 16);
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x0000FF00) >> 8);
+ pI810->writeStandard(pI810, DACDATA, (bg & 0x000000FF));
+
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x00FF0000) >> 16);
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x0000FF00) >> 8);
+ pI810->writeStandard(pI810, DACDATA, (fg & 0x000000FF));
+
+ tmp = INREG8(PIXPIPE_CONFIG_0);
+ tmp &= ~EXTENDED_PALETTE;
+ OUTREG8(PIXPIPE_CONFIG_0, tmp);
+}
diff --git a/driver/xf86-video-i810/src/i810_dga.c b/driver/xf86-video-i810/src/i810_dga.c
new file mode 100644
index 000000000..e67133312
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_dga.c
@@ -0,0 +1,297 @@
+/*
+ * 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.5 2002/09/11 00:29:31 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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/driver/xf86-video-i810/src/i810_dri.c b/driver/xf86-video-i810/src/i810_dri.c
new file mode 100644
index 000000000..f9b95bdcf
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_dri.c
@@ -0,0 +1,1537 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v 1.41 2003/09/24 02:43:23 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 "shadowfb.h"
+
+#include "GL/glxtokens.h"
+
+#include "i810.h"
+#include "i810_dri.h"
+
+static char I810KernelDriverName[] = "i810";
+static char I810ClientDriverName[] = "i810";
+
+static Bool I810InitVisualConfigs(ScreenPtr pScreen);
+static Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore);
+static void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType readContextType,
+ void *readContextStore,
+ DRIContextType writeContextType,
+ void *writeContextStore);
+static void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
+static void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index);
+
+
+static void I810EnablePageFlip(ScreenPtr pScreen);
+static void I810DisablePageFlip(ScreenPtr pScreen);
+static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void I810DRITransitionTo3d(ScreenPtr pScreen);
+static void I810DRITransitionTo2d(ScreenPtr pScreen);
+
+static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+extern void GlxSetVisualConfigs(int nconfigs,
+ __GLXvisualConfig * configs,
+ void **configprivs);
+
+static int i810_pitches[] = {
+ 512,
+ 1024,
+ 2048,
+ 4096,
+ 0
+};
+
+static int i810_pitch_flags[] = {
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x3,
+ 0
+};
+
+static unsigned int i810_drm_version = 0;
+
+Bool
+I810CleanupDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ drmI810Init info;
+
+ memset(&info, 0, sizeof(drmI810Init));
+ info.func = I810_CLEANUP_DMA;
+
+ if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
+ &info, sizeof(drmI810Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[dri] I810 Dma Cleanup Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+I810InitDma(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RingBuffer *ring = pI810->LpRing;
+ I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
+ drmI810Init info;
+
+ memset(&info, 0, sizeof(drmI810Init));
+
+ info.ring_start = ring->mem.Start;
+ info.ring_end = ring->mem.End;
+ info.ring_size = ring->mem.Size;
+ info.mmio_offset = (unsigned int)pI810DRI->regs;
+ info.buffers_offset = (unsigned int)pI810->buffer_map;
+ info.sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+ info.front_offset = 0;
+ info.back_offset = pI810->BackBuffer.Start;
+ info.depth_offset = pI810->DepthBuffer.Start;
+ info.overlay_offset = pI810->OverlayStart;
+ info.overlay_physical = pI810->OverlayPhysical;
+ info.w = pScrn->virtualX;
+ info.h = pScrn->virtualY;
+ info.pitch = pI810->auxPitch;
+ info.pitch_bits = pI810->auxPitchBits;
+
+ /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility
+ * we created a new v1.4 that supports a new init function. Eventually the
+ * old init function will go away. If you change the drm interface, make a
+ * new init type too so that we can detect the new client.
+ */
+ switch(i810_drm_version) {
+ case ((1<<16) | 0):
+ case ((1<<16) | 1):
+ case ((1<<16) | 2):
+ case ((1<<16) | 3):
+ /* Use OLD drm < 1.4 init */
+ info.func = I810_INIT_DMA;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n");
+ break;
+ default:
+ case ((1<<16) | 4):
+ /* DRM version 1.3 or greater init */
+ info.func = I810_INIT_DMA_1_4;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n");
+ break;
+ }
+
+ if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
+ &info, sizeof(drmI810Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] I810 Dma Initialization failed.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I810InitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 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 = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ if (depth)
+ pConfigs[i].depthSize = 16;
+ else
+ pConfigs[i].depthSize = 0;
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (stencil || accum)
+ pConfigs[i].visualRating = GLX_SLOW_CONFIG;
+ else
+ pConfigs[i].visualRating = GLX_NONE;
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ assert(i == numConfigs);
+ break;
+ }
+ pI810->numVisualConfigs = numConfigs;
+ pI810->pVisualConfigs = pConfigs;
+ pI810->pVisualConfigsPriv = pI810Configs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI810ConfigPtrs);
+ return TRUE;
+}
+
+static unsigned int
+mylog2(unsigned int n)
+{
+ unsigned int log2 = 1;
+
+ while (n > 1)
+ n >>= 1, log2++;
+ return log2;
+}
+
+Bool
+I810DRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ I810DRIPtr pI810DRI;
+ unsigned long tom;
+ drm_handle_t agpHandle;
+ drm_handle_t dcacheHandle;
+ int sysmem_size = 0;
+ int back_size = 0;
+ unsigned int pitch_idx = 0;
+ int bufs;
+ int width = pScrn->displayWidth * pI810->cpp;
+ int i;
+
+ /* Hardware 3D rendering only implemented for 16bpp */
+ /* And it only works for 5:6:5 (Mark) */
+ if (pScrn->depth != 16)
+ return FALSE;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module. */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable"))
+ return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
+ "[dri] Disabling DRI.\n", major, minor, patch,
+ DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (!pDRIInfo) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRICreateInfoRec failed. Disabling DRI.\n");
+ return FALSE;
+ }
+
+/* pDRIInfo->wrap.ValidateTree = 0; */
+/* pDRIInfo->wrap.PostValidateTree = 0; */
+
+ pI810->pDRIInfo = pDRIInfo;
+ pI810->LockHeld = 0;
+
+ pDRIInfo->drmDriverName = I810KernelDriverName;
+ pDRIInfo->clientDriverName = I810ClientDriverName;
+ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+ pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
+ } else {
+ pDRIInfo->busIdString = 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->TransitionTo2d = I810DRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = I810DRITransitionTo3d;
+ pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d;
+ pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ /* This adds the framebuffer as a drm map *before* we have asked agp
+ * to allocate it. Scary stuff, hold on...
+ */
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+ 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) {
+ i810_drm_version = (version->version_major<<16) |
+ version->version_minor;
+ if (version->version_major != 1 || version->version_minor < 2) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
+ "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor, version->version_patchlevel);
+ I810DRICloseScreen(pScreen);
+ drmFreeVersion(version);
+ return FALSE;
+ }
+ pI810->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+ }
+
+ pI810DRI->regsSize = I810_REG_SIZE;
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
+ pI810DRI->regsSize, DRM_REGISTERS, 0, &pI810DRI->regs) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
+ pI810DRI->regs);
+
+ pI810->backHandle = DRM_AGP_NO_HANDLE;
+ pI810->zHandle = DRM_AGP_NO_HANDLE;
+ pI810->cursorHandle = DRM_AGP_NO_HANDLE;
+ pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
+ pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
+
+ /* Agp Support - Need this just to get the framebuffer.
+ */
+ if (drmAgpAcquire(pI810->drmSubFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ pI810->agpAcquired = TRUE;
+
+ if (drmAgpEnable(pI810->drmSubFD, 0) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
+ memset(&pI810->BackBuffer, 0, sizeof(I810MemRange));
+ memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange));
+ pI810->CursorPhysical = 0;
+ pI810->CursorARGBPhysical = 0;
+
+ /* Dcache - half the speed of normal ram, but has use as a Z buffer
+ * under the DRI.
+ */
+
+ drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, &dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\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 {
+ /* for tiled memory to work, the buffer needs to have the
+ * number of lines as a multiple of 16 (the tile size),
+ * - airlied */
+ int lines = (pScrn->virtualY + 15) / 16 * 16;
+ back_size = i810_pitches[pitch_idx] * lines;
+ back_size = ((back_size + 4096 - 1) / 4096) * 4096;
+ }
+
+ sysmem_size = pScrn->videoRam * 1024;
+ if (dcacheHandle != DRM_AGP_NO_HANDLE) {
+ if (back_size > 4 * 1024 * 1024) {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[dri] Backsize is larger then 4 meg\n");
+ sysmem_size = sysmem_size - 2 * back_size;
+ drmAgpFree(pI810->drmSubFD, dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
+ } else {
+ sysmem_size = sysmem_size - back_size;
+ }
+ } else {
+ sysmem_size = sysmem_size - 2 * back_size;
+ }
+
+ /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */
+ if (pI810->numSurfaces && (pI810->numSurfaces == 6)) {
+ if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) {
+ sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "User requested more memory then fits in the agp aperture\n"
+ "Truncating to %d bytes of memory\n", sysmem_size);
+ }
+ }
+ if (pI810->numSurfaces && (pI810->numSurfaces == 7)) {
+ if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) {
+ sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "User requested more memory then fits in the agp aperture\n"
+ "Truncating to %d bytes of memory\n", sysmem_size);
+ }
+ }
+
+ if (sysmem_size > pI810->FbMapSize) {
+ sysmem_size = pI810->FbMapSize;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] User requested more memory then fits in the agp"
+ " aperture\n\tTruncating to %d bytes of memory\n",
+ sysmem_size);
+ }
+
+ sysmem_size -= 4096; /* remove 4k for the hw cursor */
+ sysmem_size -= 16384; /* remove 16k for the ARGB hw cursor */
+
+ pI810->SysMem.Start = 0;
+ pI810->SysMem.Size = sysmem_size;
+ pI810->SysMem.End = sysmem_size;
+ tom = sysmem_size;
+
+ pI810->SavedSysMem = pI810->SysMem;
+
+ if (dcacheHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) {
+ memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Found 4096K Z buffer memory\n");
+ pI810->DcacheMem.Start = pI810->DepthOffset;
+ pI810->DcacheMem.Size = 1024 * 4096;
+ pI810->DcacheMem.End =
+ pI810->DcacheMem.Start + pI810->DcacheMem.Size;
+ if (!I810AllocLow
+ (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Depth buffer allocation failed\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: dcache bind failed\n");
+ drmAgpFree(pI810->drmSubFD, dcacheHandle);
+ pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: no dcache memory found\n");
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+ pI810->backHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound backbuffer memory\n");
+
+ pI810->BackBuffer.Start = pI810->BackOffset;
+ pI810->BackBuffer.Size = back_size;
+ pI810->BackBuffer.End = (pI810->BackBuffer.Start +
+ pI810->BackBuffer.Size);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to bind backbuffer. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ if (dcacheHandle == DRM_AGP_NO_HANDLE) {
+ drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+
+ pI810->zHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound depthbuffer memory\n");
+ pI810->DepthBuffer.Start = pI810->DepthOffset;
+ pI810->DepthBuffer.Size = back_size;
+ pI810->DepthBuffer.End = (pI810->DepthBuffer.Start +
+ pI810->DepthBuffer.Size);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to bind depthbuffer. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ }
+
+ /* Now allocate and bind the agp space. This memory will include the
+ * regular framebuffer as well as texture memory.
+ */
+ drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, &agpHandle);
+ pI810->sysmemHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] Bound System Texture Memory\n");
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled
+ regions and required surface pitches. (Numbers are adjusted if the
+ AGP region is only 32MB
+ For numSurfaces == 6
+ 44 - 48MB = 4MB Fence, 8 Tiles wide
+ 43 - 44MB = 1MB Fence, 8 Tiles wide
+ 42 - 43MB = 1MB Fence, 4 Tiles wide
+ 41 - 42MB = 1MB Fence, 4 Tiles wide
+ For numSurfaces == 7
+ 44 - 48MB = 4MB Fence, 8 Tiles wide
+ 43 - 44MB = 1MB Fence, 8 Tiles wide
+ 42.5 - 43MB = 0.5MB Fence, 8 Tiles wide
+ 42 - 42.5MB = 0.5MB Fence, 4 Tiles wide
+ 40 - 42MB = 2MB Fence, 4 Tiles wide
+ */
+ if (pI810->numSurfaces) {
+ if (pI810->numSurfaces == 6) {
+ pI810->MC.Size = 7 * 1024 * 1024;
+ pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024;
+
+ }
+ if (pI810->numSurfaces == 7) {
+ pI810->MC.Size = 8 * 1024 * 1024;
+ pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
+ }
+ drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL, &agpHandle);
+
+ pI810->xvmcHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "GART: Allocated 7MB for HWMC\n");
+ pI810->MC.End = pI810->MC.Start + pI810->MC.Size;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n");
+ pI810->MC.Start = 0;
+ pI810->MC.Size = 0;
+ pI810->MC.End = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n");
+ pI810->MC.Start = 0;
+ pI810->MC.Size = 0;
+ pI810->MC.End = 0;
+ }
+ pI810->xvmcContext = 0;
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, 4096, 2,
+ (unsigned long *)&pI810->CursorPhysical, &agpHandle);
+
+ pI810->cursorHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ tom = sysmem_size;
+
+ if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Allocated 4K for mouse cursor image\n");
+ pI810->CursorStart = tom;
+ tom += 4096;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: cursor bind failed\n");
+ pI810->CursorPhysical = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: cursor alloc failed\n");
+ pI810->CursorPhysical = 0;
+ }
+
+ drmAgpAlloc(pI810->drmSubFD, 16384, 2,
+ (unsigned long *)&pI810->CursorARGBPhysical, &agpHandle);
+
+ pI810->cursorARGBHandle = agpHandle;
+
+ if (agpHandle != DRM_AGP_NO_HANDLE) {
+ int r;
+
+ if ((r = drmAgpBind(pI810->drmSubFD, agpHandle, tom)) == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: Allocated 16K for ARGB mouse cursor image\n");
+ pI810->CursorARGBStart = tom;
+ tom += 16384;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: ARGB cursor bind failed\n");
+ pI810->CursorARGBPhysical = 0;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[agp] GART: ARGB cursor alloc failed\n");
+ pI810->CursorARGBPhysical = 0;
+ }
+
+ /* Steal some of the excess cursor space for the overlay regs.
+ */
+ pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
+ pI810->OverlayStart = pI810->CursorStart + 1024;
+
+ I810SetTiledMemory(pScrn, 1,
+ pI810->DepthBuffer.Start,
+ i810_pitches[pitch_idx], 8 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 2,
+ pI810->BackBuffer.Start,
+ i810_pitches[pitch_idx], 8 * 1024 * 1024);
+
+ /* These are for HWMC surfaces */
+ if (pI810->numSurfaces == 6) {
+ I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 4,
+ pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 5,
+ pI810->MC.Start + 1024 * 1024 * 2,
+ 1024, 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 6,
+ pI810->MC.Start + 1024 * 1024 * 3,
+ 1024, 4 * 1024 * 1024);
+ }
+ if (pI810->numSurfaces == 7) {
+ I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 4,
+ pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024);
+
+ I810SetTiledMemory(pScrn, 5,
+ pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024,
+ 1024, 512 * 1024);
+
+ I810SetTiledMemory(pScrn, 6,
+ pI810->MC.Start + 3 * 1024 * 1024,
+ 1024, 1 * 1024 * 1024);
+
+ I810SetTiledMemory(pScrn, 7,
+ pI810->MC.Start + 4 * 1024 * 1024,
+ 1024, 4 * 1024 * 1024);
+
+ }
+
+ pI810->auxPitch = i810_pitches[pitch_idx];
+ pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
+ pI810->SavedDcacheMem = pI810->DcacheMem;
+ pI810DRI->backbufferSize = pI810->BackBuffer.Size;
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
+ pI810->BackBuffer.Size, DRM_AGP, 0,
+ &pI810DRI->backbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
+ pI810->DepthBuffer.Size, DRM_AGP, 0,
+ &pI810DRI->depthbuffer) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Allocate FrontBuffer etc. */
+ if (!I810AllocateFront(pScrn)) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Allocate buffer memory */
+ I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem),
+ I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n",
+ pI810->BufferMem.Start);
+
+ if (pI810->BufferMem.Start == 0 ||
+ pI810->BufferMem.End - pI810->BufferMem.Start >
+ I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] Not enough memory for dma buffers. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
+ pI810->BufferMem.Size, DRM_AGP, 0, &pI810->buffer_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ pI810DRI->agp_buffers = pI810->buffer_map;
+ pI810DRI->agp_buf_size = pI810->BufferMem.Size;
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
+ pI810->LpRing->mem.Size, DRM_AGP, 0, &pI810->ring_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ /* Use the rest of memory for textures. */
+ pI810DRI->textureSize = pI810->SysMem.Size;
+
+ i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
+
+ if (i < I810_LOG_MIN_TEX_REGION_SIZE)
+ i = I810_LOG_MIN_TEX_REGION_SIZE;
+
+ pI810DRI->logTextureGranularity = i;
+ pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */
+
+ if (pI810DRI->textureSize < 512 * 1024) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Less then 512k memory left for textures. Disabling DRI.\n");
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize);
+
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
+ pI810->TexMem.Size, DRM_AGP, 0, &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);
+ I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
+
+ if (pI810DRI->irq) {
+ drmCtlUninstHandler(pI810->drmSubFD);
+ pI810DRI->irq = 0;
+ }
+
+ I810CleanupDma(pScrn);
+
+ if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
+ if (pI810->backHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->backHandle);
+ if (pI810->zHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->zHandle);
+ if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
+ if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
+ if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE)
+ drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
+
+ if (pI810->agpAcquired == TRUE)
+ drmAgpRelease(pI810->drmSubFD);
+
+ pI810->backHandle = DRM_AGP_NO_HANDLE;
+ pI810->zHandle = DRM_AGP_NO_HANDLE;
+ pI810->cursorHandle = DRM_AGP_NO_HANDLE;
+ pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
+ pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
+ pI810->agpAcquired = FALSE;
+ pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
+
+ DRICloseScreen(pScreen);
+
+ if (pI810->pDRIInfo) {
+ if (pI810->pDRIInfo->devPrivate) {
+ 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,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+I810DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr info = I810PTR(pScrn);
+
+ memset(sPriv, 0, sizeof(sPriv));
+
+ /* Have shadow run only while there is 3d active.
+ */
+ if (info->allowPageFlip && info->drmMinor >= 3) {
+ ShadowFBInit( pScreen, I810DRIRefreshArea );
+ }
+ else
+ info->allowPageFlip = 0;
+ return DRIFinishScreenInit(pScreen);
+}
+
+void
+I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (syncType == DRI_3D_SYNC &&
+ oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (in)\n");
+
+ if (!pScrn->vtSema)
+ return;
+ pI810->LockHeld = 1;
+ I810RefreshRing(pScrn);
+ } else if (syncType == DRI_2D_SYNC &&
+ oldContextType == DRI_NO_CONTEXT &&
+ newContextType == DRI_2D_CONTEXT) {
+ pI810->LockHeld = 0;
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (out)\n");
+ } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRISwapContext (other)\n");
+}
+
+static void
+I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ BoxPtr pbox = REGION_RECTS(prgn);
+ int nbox = REGION_NUM_RECTS(prgn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("I810DRIInitBuffers\n");
+
+ I810SetupForSolidFill(pScrn, 0, GXcopy, -1);
+ while (nbox--) {
+ I810SelectBuffer(pScrn, I810_SELECT_BACK);
+ I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ /* Clear the depth buffer - uses 0xffff rather than 0.
+ */
+ pbox = REGION_RECTS(prgn);
+ nbox = REGION_NUM_RECTS(prgn);
+ I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
+ I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
+ while (nbox--) {
+ I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+ I810SelectBuffer(pScrn, I810_SELECT_FRONT);
+ 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;
+}
+
+
+/* Use the miext/shadow module to maintain a list of dirty rectangles.
+ * These are blitted to the back buffer to keep both buffers clean
+ * during page-flipping when the 3d application isn't fullscreen.
+ *
+ * Unlike most use of the shadow code, both buffers are in video memory.
+ *
+ * An alternative to this would be to organize for all on-screen drawing
+ * operations to be duplicated for the two buffers. That might be
+ * faster, but seems like a lot more work...
+ */
+
+
+/* This should be done *before* XAA syncs or fires its buffer.
+ * Otherwise will have to fire it again???
+ */
+static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+ unsigned int br13;
+ int cpp=2;
+
+
+ /* Don't want to do this when no 3d is active and pages are
+ * right-way-round
+ */
+ if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+ return;
+
+ br13 = (pI810->auxPitch) | (0xcc << 16);
+
+ for (i = 0 ; i < num ; i++, pbox++) {
+ unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1;
+ unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1;
+ unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch);
+
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+ OUT_RING(br13);
+ OUT_RING( (h<<16) | (w*cpp) );
+ OUT_RING(pI810->BackBuffer.Start + dst);
+ OUT_RING(br13 & 0xffff);
+ OUT_RING(dst);
+
+ ADVANCE_LP_RING();
+ }
+
+}
+
+static void I810EnablePageFlip(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+ int cpp=2;
+ pSAREAPriv->pf_enabled = pI810->allowPageFlip;
+ pSAREAPriv->pf_active = 0;
+
+ if (pI810->allowPageFlip) {
+ unsigned int br13 = pI810->auxPitch | (0xcc << 16);
+
+ BEGIN_LP_RING(6);
+
+ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+ OUT_RING(br13);
+ OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp));
+ OUT_RING(pI810->BackBuffer.Start);
+ OUT_RING(br13 & 0xFFFF);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ pSAREAPriv->pf_active = 1;
+ }
+
+}
+
+static void I810DisablePageFlip(ScreenPtr pScreen)
+{
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ pSAREAPriv->pf_active=0;
+}
+
+static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen)
+{
+ /* Tell the clients not to pageflip. How?
+ * -- Field in sarea, plus bumping the window counters.
+ * -- DRM needs to cope with Front-to-Back swapbuffers.
+ */
+ I810DisablePageFlip(pScreen);
+}
+
+static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen)
+{
+ /* Let the remaining 3d app start page flipping again */
+ I810EnablePageFlip(pScreen);
+}
+
+static void I810DRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ I810EnablePageFlip(pScreen);
+ pI810->have3DWindows = 1;
+}
+
+static void I810DRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+
+ /* Try flipping back to the front page if necessary */
+ if (pSAREAPriv->pf_current_page == 1)
+ drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP);
+
+ /* Shut down shadowing if we've made it back to the front page */
+ if (pSAREAPriv->pf_current_page == 0) {
+ I810DisablePageFlip(pScreen);
+ }
+ pI810->have3DWindows = 0;
+}
+
+Bool
+I810DRILeave(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->directRenderingEnabled) {
+ if (pI810->dcacheHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->backHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->zHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->sysmemHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->xvmcHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->cursorHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->cursorARGBHandle != 0)
+ if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
+ return FALSE;
+ }
+ if (pI810->agpAcquired == TRUE)
+ drmAgpRelease(pI810->drmSubFD);
+ pI810->agpAcquired = FALSE;
+ }
+ return TRUE;
+}
+
+Bool
+I810DRIEnter(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (pI810->directRenderingEnabled) {
+
+ if (pI810->agpAcquired == FALSE)
+ drmAgpAcquire(pI810->drmSubFD);
+ pI810->agpAcquired = TRUE;
+ if (pI810->dcacheHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
+ pI810->DepthOffset) != 0)
+ return FALSE;
+ if (pI810->backHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
+ pI810->BackOffset) != 0)
+ return FALSE;
+ if (pI810->zHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
+ pI810->DepthOffset) != 0)
+ return FALSE;
+ if (pI810->sysmemHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0)
+ return FALSE;
+ if (pI810->xvmcHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
+ pI810->MC.Start) != 0)
+ return FALSE;
+ if (pI810->cursorHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
+ pI810->CursorStart) != 0)
+ return FALSE;
+ if (pI810->cursorARGBHandle != 0)
+ if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle,
+ pI810->CursorARGBStart) != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/driver/xf86-video-i810/src/i810_dri.h b/driver/xf86-video-i810/src/i810_dri.h
new file mode 100644
index 000000000..408a4ebb4
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_dri.h
@@ -0,0 +1,128 @@
+/* $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 {
+ drm_handle_t regs;
+ drmSize regsSize;
+
+ drmSize backbufferSize;
+ drm_handle_t backbuffer;
+
+ drmSize depthbufferSize;
+ drm_handle_t depthbuffer;
+
+ drm_handle_t textures;
+ int textureSize;
+
+ drm_handle_t agp_buffers;
+ drmSize agp_buf_size;
+
+ int deviceID;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+ int bitsPerPixel;
+ int fbOffset;
+ int fbStride;
+
+ int backOffset;
+ int depthOffset;
+
+ int auxPitch;
+ int auxPitchBits;
+
+ int logTextureGranularity;
+ int textureOffset;
+
+ /* For non-dma direct rendering.
+ */
+ int ringOffset;
+ int ringSize;
+
+ drmBufMapPtr drmBufs;
+ int irq;
+ unsigned int sarea_priv_offset;
+
+} I810DRIRec, *I810DRIPtr;
+
+/* WARNING: Do not change the SAREA structure without changing the kernel
+ * as well */
+
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_CTX 0x4
+#define I810_UPLOAD_BUFFERS 0x8
+#define I810_UPLOAD_TEX0 0x10
+#define I810_UPLOAD_TEX1 0x20
+#define I810_UPLOAD_CLIPRECTS 0x40
+
+typedef struct {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} I810TexRegionRec, *I810TexRegionPtr;
+
+typedef struct {
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+
+ /* Maintain an LRU of contiguous regions of texture space. If
+ * you think you own a region of texture memory, and it has an
+ * age different to the one you set, then you are mistaken and
+ * it has been stolen by another client. If global texAge
+ * hasn't changed, there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained
+ * texture information of other clients - by maintaining them
+ * in the same lru which is used to age their own textures,
+ * clients have an approximate lru for the whole of global
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+ * them all in LRU order.
+ */
+
+ drmTextureRegion texList[I810_NR_TEX_REGIONS + 1];
+
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+
+ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+ int last_quiescent; /* */
+
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active; /* is pageflipping active right now? */
+ int pf_current_page; /* which buffer is being displayed? */
+
+
+} I810SAREARec, *I810SAREAPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I810ConfigPrivRec, *I810ConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} I810DRIContextRec, *I810DRIContextPtr;
+
+#endif
diff --git a/driver/xf86-video-i810/src/i810_driver.c b/driver/xf86-video-i810/src/i810_driver.c
new file mode 100644
index 000000000..bfa1dae9a
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_driver.c
@@ -0,0 +1,2594 @@
+
+/**************************************************************************
+
+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.101 2004/01/02 20:15:47 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * 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>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ */
+
+/*
+ * This server does not support these XFree86 4.0 features yet
+ * shadowFb (if requested or acceleration is off)
+ * Overlay planes
+ * DGA
+ */
+
+/*
+ * 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 <X11/extensions/Xv.h>
+#include "vbe.h"
+
+#include "i810.h"
+#include "i830.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 ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flags);
+#endif /* I830_ONLY */
+
+
+_X_EXPORT 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"},
+ {PCI_CHIP_I915_G, "915G"},
+ {PCI_CHIP_E7221_G, "E7221 (i915)"},
+ {PCI_CHIP_I915_GM, "915GM"},
+ {PCI_CHIP_I945_G, "945G"},
+ {-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},
+ {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA},
+ {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA},
+ {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA},
+ {PCI_CHIP_I945_G, PCI_CHIP_I945_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,
+ OPTION_PAGEFLIP
+} I810Opts;
+
+static const OptionInfoRec I810Options[] = {
+ {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+/* *INDENT-ON* */
+#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",
+ "XAAInit",
+ "XAAGetCopyROP",
+ "XAAGetPatternROP",
+ NULL
+};
+
+const char *I810ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+const char *I810shadowFBSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+
+#ifdef XF86DRI
+const char *I810drmSymbols[] = {
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAgpAcquire",
+ "drmAgpAlloc",
+ "drmAgpBind",
+ "drmAgpEnable",
+ "drmAgpFree",
+ "drmAgpRelease",
+ "drmAgpUnbind",
+ "drmAuthMagic",
+ "drmCommandNone",
+ "drmCommandWrite",
+ "drmCreateContext",
+ "drmCtlInstHandler",
+ "drmCtlUninstHandler",
+ "drmDestroyContext",
+ "drmFreeVersion",
+ "drmGetInterruptFromBusID",
+ "drmGetLibVersion",
+ "drmGetVersion",
+ NULL
+};
+
+
+const char *I810driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ "DRICreatePCIBusID",
+ NULL
+};
+
+const char *I810shadowSymbols[] = {
+ "shadowInit",
+ "shadowSetup",
+ "shadowAdd",
+ NULL
+};
+
+#endif
+
+#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
+
+int I830EntityIndex = -1;
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(i810Setup);
+
+static XF86ModuleVersionInfo i810VersRec = {
+ "i810",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ I810_MAJOR_VERSION, I810_MINOR_VERSION, I810_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+_X_EXPORT 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
+ I810drmSymbols,
+ I810driSymbols,
+ I810shadowSymbols,
+ I810shadowFBSymbols,
+#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;
+ I830EntPtr pI830Ent = NULL;
+ DevUnion *pPriv;
+ 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_845_G:
+ case PCI_CHIP_I865_G:
+ I830InitpScrn(pScrn);
+ break;
+ case PCI_CHIP_I830_M:
+ case PCI_CHIP_I855_GM:
+ case PCI_CHIP_I915_G:
+ case PCI_CHIP_E7221_G:
+ case PCI_CHIP_I915_GM:
+ case PCI_CHIP_I945_G:
+ xf86SetEntitySharable(usedChips[i]);
+
+ /* Allocate an entity private if necessary */
+ if (I830EntityIndex < 0)
+ I830EntityIndex = xf86AllocateEntityPrivateIndex();
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ I830EntityIndex);
+ if (!pPriv->ptr) {
+ pPriv->ptr = xnfcalloc(sizeof(I830EntRec), 1);
+ pI830Ent = pPriv->ptr;
+ pI830Ent->lastInstance = -1;
+ } else {
+ pI830Ent = pPriv->ptr;
+ }
+
+ /*
+ * Set the entity instance for this instance of the driver.
+ * For dual head per card, instance 0 is the "master"
+ * instance, driving the primary head, and instance 1 is
+ * the "slave".
+ */
+ pI830Ent->lastInstance++;
+ xf86SetEntityInstanceForScreen(pScrn,
+ pScrn->entityList[0], pI830Ent->lastInstance);
+ 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;
+ Bool enable;
+
+ 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, 0, 0, 0, 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;
+ }
+
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
+ pI810->noAccel = TRUE;
+
+ if (!pI810->noAccel) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810xaaSymbols, NULL);
+ }
+
+#ifdef XF86DRI
+ pI810->directRenderingDisabled =
+ !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
+
+ if (!pI810->directRenderingDisabled) {
+ if (pI810->noAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+ "needs 2D acceleration.\n");
+ pI810->directRenderingDisabled=TRUE;
+ } else if (pScrn->depth!=16) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
+ "runs only at 16-bit depth.\n");
+ pI810->directRenderingDisabled=TRUE;
+ }
+ }
+#endif
+
+ /* Get DDC info from monitor */
+ /* after xf86ProcessOptions,
+ * because it is controlled by options [no]vbe and [no]ddc
+ */
+ 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).
+ */
+ mem = I810CheckAvailableMemory(pScrn);
+ if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */
+ pScrn->videoRam = 8192;
+ else if (mem < 196608)
+ pScrn->videoRam = 16384; /* < 192 MB */
+ else
+ pScrn->videoRam = 24576;
+
+ from = X_DEFAULT;
+
+ if (pI810->pEnt->device->videoRam) {
+ pScrn->videoRam = pI810->pEnt->device->videoRam;
+ from = X_CONFIG;
+ }
+
+ if (mem > 0 && mem < pScrn->videoRam) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
+ " but the\n\t maximum AGP memory available is %dk.\n",
+ pScrn->videoRam, mem);
+ from = X_PROBED;
+ if (mem > (6 * 1024)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Reducing video memory to 4MB\n");
+ pScrn->videoRam = 4096;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
+ " is available. Cannot proceed.\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam);
+
+ /* Calculate Fixed Offsets depending on graphics aperture size */
+ {
+ 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;
+ /* 9.4MHz appears to be the smallest that works. */
+ clockRanges->minClock = 9500;
+ clockRanges->maxClock = pI810->MaxClock;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = FALSE;
+
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+#ifndef XF86DRI
+ 0, 320, 1600, 64 * pScrn->bitsPerPixel,
+#else
+ i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel,
+#endif
+ 200, 1200,
+ pScrn->display->virtualX, pScrn->display->virtualY,
+ pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
+
+ if (i == -1) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (!i || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ pScrn->currentMode = pScrn->modes;
+
+ xf86PrintModes(pScrn);
+
+ xf86SetDpi(pScrn, 0, 0);
+
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ I810FreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810fbSymbols, 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);
+ }
+
+ pI810->allowPageFlip=FALSE;
+ enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
+
+#ifdef XF86DRI
+ if (!pI810->directRenderingDisabled) {
+ pI810->allowPageFlip = enable;
+ if (pI810->allowPageFlip == enable)
+ {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ pI810->allowPageFlip = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't load shadowfb module:\n");
+ }
+ else {
+ xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
+ enable ? "enabled" : "disabled");
+
+ }
+#endif
+
+ if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
+ &(pI810->numSurfaces))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
+ pI810->numSurfaces);
+ if (pI810->numSurfaces > 7) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using 7 XvMC Surfaces (Maximum Allowed).\n");
+ pI810->numSurfaces = 7;
+ }
+ if (pI810->numSurfaces < 6) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using 6 XvMC Surfaces (Minimum Allowed).\n");
+ pI810->numSurfaces = 6;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
+ pI810->numSurfaces = 0;
+ }
+
+#ifdef XF86DRI
+ /* Load the dri module if requested. */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
+ if (xf86LoadSubModule(pScrn, "dri")) {
+ xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
+ }
+ }
+#endif
+
+ /* 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);
+ long 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);
+ CARD32 TV_HTotal = INREG(LCD_TV_HTOTAL);
+ CARD32 ActiveStart, ActiveEnd;
+
+ if((LCD_TV_Control & LCD_TV_ENABLE)
+ && !(LCD_TV_Control & LCD_TV_VGAMOD)
+ && TV_HTotal) {
+ ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
+ ActiveEnd = (TV_HTotal & 0x3ff) - 31;
+ } else {
+ ActiveStart = i810Reg->OverlayActiveStart;
+ ActiveEnd = i810Reg->OverlayActiveEnd;
+ }
+ OUTREG(LCD_TV_OVRACT,
+ (ActiveEnd << 16) | ActiveStart);
+ }
+
+ /* Turn on DRAM Refresh */
+ temp = INREG8(DRAM_ROW_CNTL_HI);
+ temp &= ~DRAM_REFRESH_RATE;
+ temp |= DRAM_REFRESH_60HZ;
+ OUTREG8(DRAM_ROW_CNTL_HI, temp);
+
+ temp = INREG8(BITBLT_CNTL);
+ temp &= ~COLEXP_MODE;
+ temp |= i810Reg->BitBLTControl;
+ OUTREG8(BITBLT_CNTL, temp);
+
+ temp = INREG8(DISPLAY_CNTL);
+ temp &= ~(VGA_WRAP_MODE | GUI_MODE);
+ temp |= i810Reg->DisplayControl;
+ OUTREG8(DISPLAY_CNTL, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_0);
+ temp &= 0x64; /* Save reserved bits 6:5,2 */
+ temp |= i810Reg->PixelPipeCfg0;
+ OUTREG8(PIXPIPE_CONFIG_0, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_2);
+ temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
+ temp |= i810Reg->PixelPipeCfg2;
+ OUTREG8(PIXPIPE_CONFIG_2, temp);
+
+ temp = INREG8(PIXPIPE_CONFIG_1);
+ temp &= ~DISPLAY_COLOR_MODE;
+ temp &= 0xEF; /* Restore the CRT control bit */
+ temp |= i810Reg->PixelPipeCfg1;
+ OUTREG8(PIXPIPE_CONFIG_1, temp);
+
+ OUTREG16(EIR, 0);
+
+ itemp = INREG(FWATER_BLC);
+ itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
+ MM_BURST_LENGTH | MM_FIFO_WATERMARK);
+ itemp |= i810Reg->LMI_FIFO_Watermark;
+ OUTREG(FWATER_BLC, itemp);
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
+ if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
+ }
+
+ /* First disable the ring buffer (Need to wait for empty first?, if so
+ * should probably do it before entering this section)
+ */
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~RING_VALID_MASK;
+ OUTREG(LP_RING + RING_LEN, itemp);
+
+ /* Set up the low priority ring buffer.
+ */
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ pI810->LpRing->head = 0;
+ pI810->LpRing->tail = 0;
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= i810Reg->LprbStart;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= i810Reg->LprbLen;
+ OUTREG(LP_RING + RING_LEN, itemp);
+
+ if (!(vgaReg->Attribute[0x10] & 0x1)) {
+ usleep(50000);
+ if (restoreFonts)
+ vgaHWRestore(pScrn, vgaReg,
+ VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
+ else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+
+ temp = hwp->readCrtc(hwp, IO_CTNL);
+ temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+ temp |= i810Reg->IOControl;
+ hwp->writeCrtc(hwp, IO_CTNL, temp);
+}
+
+static void
+I810SetRingRegs(ScrnInfoPtr pScrn)
+{
+ unsigned int itemp;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ itemp = INREG(LP_RING + RING_START);
+ itemp &= ~(START_ADDR);
+ itemp |= pI810->LpRing->mem.Start;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ itemp = INREG(LP_RING + RING_LEN);
+ itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
+ itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
+ OUTREG(LP_RING + RING_LEN, itemp);
+}
+
+static void
+I810Restore(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+
+ DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
+}
+
+/*
+ * I810CalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+
+#define MAX_VCO_FREQ 600.0
+#define TARGET_MAX_N 30
+#define REF_FREQ 24.0
+
+#define CALC_VCLK(m,n,p) \
+ (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
+
+static void
+I810CalcVCLK(ScrnInfoPtr pScrn, double freq)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ int m, n, p;
+ double f_out, 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);
+ /* Make sure p is within range. */
+ if (p_best > 5) {
+ p_best = p = 5;
+ }
+
+ f_vco = f_target * (1 << p);
+
+ n = 2;
+ do {
+ n++;
+ m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
+ if (m < 3)
+ m = 3;
+ f_out = CALC_VCLK(m, n, p);
+ f_err = 1.0 - (f_target / f_out);
+ if (fabs(f_err) < err_max) {
+ m_best = m;
+ n_best = n;
+ 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 %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
+ "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
+ i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
+ i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
+}
+
+static Bool
+I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
+ double dclk = mode->Clock / 1000.0;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
+ i810Reg->ExtOffset = pScrn->displayWidth >> 11;
+ i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_8BPP;
+ break;
+ case 16:
+ if (pScrn->weight.green == 5) {
+ i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
+ } else {
+ i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
+ }
+ pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
+ i810Reg->ExtOffset = pScrn->displayWidth >> 10;
+ i810Reg->BitBLTControl = COLEXP_16BPP;
+
+ /* Enable Palette Programming for Direct Color visuals. -jens */
+ i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
+ break;
+ case 24:
+ pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
+ i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
+
+ i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
+ i810Reg->BitBLTControl = COLEXP_24BPP;
+
+ /* Enable Palette Programming for Direct Color visuals. -jens */
+ i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
+ break;
+ default:
+ break;
+ }
+
+ /* Turn on 8 bit dac if requested */
+ if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
+ i810Reg->PixelPipeCfg0 = DAC_6_BIT;
+ else
+ i810Reg->PixelPipeCfg0 = DAC_8_BIT;
+
+ /* Do not delay CRT Blank: needed for video overlay */
+ i810Reg->PixelPipeCfg1 |= 0x10;
+
+ /* Turn on Extended VGA Interpretation */
+ i810Reg->IOControl = EXTENDED_CRTC_CNTL;
+
+ /* Turn on linear and page mapping */
+ i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
+
+ /* Turn on GUI mode */
+ i810Reg->DisplayControl = HIRES_MODE;
+
+ /* Calculate the extended CRTC regs */
+ i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
+ i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
+ i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
+ i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
+ i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
+ i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
+
+ /*
+ * the KGA fix in vgaHW.c results in the first
+ * scanline and the first character clock (8 pixels)
+ * of each scanline thereafter on display with an i810
+ * to be blank. Restoring CRTC 3, 5, & 22 to their
+ * "theoretical" values corrects the problem. KAO.
+ */
+ pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
+ pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
+ | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
+ pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
+
+ i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
+ vgaHWVBlankKGA(mode, pVga, 8, 0);
+
+ /*
+ * The following workarounds are needed to get video overlay working
+ * at 1024x768 and 1280x1024 display resolutions.
+ */
+ if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
+ i810Reg->ExtVertBlankStart = 2;
+ }
+ if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
+ i810Reg->ExtVertBlankStart = 3;
+ }
+
+ /* OVRACT Register */
+ i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
+ i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
+
+ /* Turn on interlaced mode if necessary */
+ if (mode->Flags & V_INTERLACE) {
+ i810Reg->InterlaceControl = INTERLACE_ENABLE;
+ i810Reg->ExtVertDispEnd *= 2;
+ } else
+ i810Reg->InterlaceControl = INTERLACE_DISABLE;
+
+ /*
+ * Set the overscan color to 0.
+ * NOTE: This only affects >8bpp mode.
+ */
+ pVga->Attribute[0x11] = 0;
+
+ /*
+ * Calculate the VCLK that most closely matches the requested dot
+ * clock.
+ */
+ I810CalcVCLK(pScrn, dclk);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ pVga->MiscOutReg |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);
+
+ /* Setup the ring buffer */
+ i810Reg->LprbTail = 0;
+ i810Reg->LprbHead = 0;
+ i810Reg->LprbStart = pI810->LpRing->mem.Start;
+
+ if (i810Reg->LprbStart)
+ i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |
+ RING_NO_REPORT | RING_VALID);
+ else
+ i810Reg->LprbLen = RING_INVALID;
+
+ return TRUE;
+}
+
+static Bool
+I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp;
+ I810Ptr pI810;
+
+ hwp = VGAHWPTR(pScrn);
+ pI810 = I810PTR(pScrn);
+
+ vgaHWUnlock(hwp);
+
+ if (!vgaHWInit(pScrn, mode))
+ return FALSE;
+
+ pScrn->vtSema = TRUE;
+
+ if (!I810SetMode(pScrn, mode))
+ return FALSE;
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+#endif
+
+ DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+#endif
+
+ return TRUE;
+}
+
+static void
+I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ 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);
+
+ pI810->LpRing = xcalloc(sizeof(I810RingBuffer),1);
+ if (!pI810->LpRing) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Could not allocate lpring data structure.\n");
+ return FALSE;
+ }
+
+ miClearVisualTypes();
+
+ /* Re-implemented Direct Color support, -jens */
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths())
+ return FALSE;
+
+ {
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ i810Reg->Fence[i] = 0;
+ }
+
+ /* Have to init the DRM earlier than in other drivers to get agp
+ * memory. Wonder if this is going to be a problem...
+ */
+
+#ifdef XF86DRI
+ /*
+ * Setup DRI after visuals have been established, but before fbScreenInit
+ * is called. fbScreenInit will eventually call into the drivers
+ * InitGLXVisuals call back.
+ */
+ /*
+ * pI810->directRenderingDisabled is set once in PreInit. Reinitialise
+ * pI810->directRenderingEnabled based on it each generation.
+ */
+ pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
+
+ if (pI810->directRenderingEnabled==TRUE)
+ pI810->directRenderingEnabled = I810DRIScreenInit(pScreen);
+ else
+ driFrom = X_CONFIG;
+
+#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");
+ } else /* PK added 16.02.2004 */
+ I810EmitFlush(pScrn);
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!I810CursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ /* Use driver specific palette load routines for Direct Color support. -jens */
+ if (pScrn->bitsPerPixel == 16) {
+ if (pScrn->depth == 15) {
+ if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, 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, fb, drm and others have done their thing,
+ * complete the DRI setup.
+ */
+ pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
+ }
+#ifdef XvMCExtension
+ if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
+ /* Initialize the hardware motion compensation code */
+ I810InitMC(pScreen);
+ }
+#endif
+#endif
+
+ if (pI810->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
+ }
+
+ pScreen->SaveScreen = I810SaveScreen;
+ pI810->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = I810CloseScreen;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ return TRUE;
+}
+
+Bool
+I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+#if 0
+ I810Ptr pI810 = I810PTR(pScrn);
+#endif
+ if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags);
+
+#if 0
+/*
+ * This has been added to prevent lockups on mode switch by modeling
+ * it after I810Leave()/I810Enter() but the call to I810DRILeave()
+ * was missing so it caused the opposite.
+ * The version below works but it is doubtful it does any good.
+ * If lockups on mode switch are still seen revisit this code. (EE)
+ */
+
+# ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+# endif
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+
+# ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (!I810DRILeave(pScrn))
+ return FALSE;
+ if (!I810DRIEnter(pScrn))
+ return FALSE;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+# endif
+#endif
+ return I810ModeInit(pScrn, mode);
+}
+
+void
+I810AdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I810Ptr pI810 = I810PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int Base;
+
+#if 1
+ if (pI810->showCache) {
+ int lastline = pI810->FbMapSize /
+ ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
+ lastline -= pScrn->currentMode->VDisplay;
+ if (y > 0)
+ y += pScrn->currentMode->VDisplay;
+ if (y > lastline) y = lastline;
+ }
+#endif
+ Base = (y * pScrn->displayWidth + x) >> 2;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
+ ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags);
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ Base *= 2;
+ break;
+ case 24:
+ /* KW: Need to do 16-pixel alignment for i810, otherwise you
+ * get bad watermark problems. Need to fixup the mouse
+ * pointer positioning to take this into account.
+ */
+ pI810->CursorOffset = (Base & 0x3) * 4;
+ Base &= ~0x3;
+ Base *= 3;
+ break;
+ case 32:
+ Base *= 4;
+ break;
+ }
+
+ hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF);
+ hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8);
+ hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22);
+ hwp->writeCrtc(hwp, EXT_START_ADDR,
+ ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE));
+}
+
+/* These functions are usually called with the lock **not held**.
+ */
+static Bool
+I810EnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+#ifdef XF86DRI
+ I810Ptr pI810 = I810PTR(pScrn);
+#endif
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("\n\nENTER VT\n");
+
+ if (!I810BindGARTMemory(pScrn)) {
+ return FALSE;
+ }
+#ifdef XF86DRI
+ if (!I810DRIEnter(pScrn)) {
+ return FALSE;
+ }
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ pI810->LockHeld = 0;
+ }
+#endif
+
+ if (!I810ModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+ I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return TRUE;
+}
+
+static void
+I810LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("\n\n\nLeave VT\n");
+
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ if (I810_DEBUG & DEBUG_VERBOSE_DRI)
+ ErrorF("calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI810->LockHeld = 1;
+ }
+#endif
+
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+
+ if (!I810UnbindGARTMemory(pScrn))
+ return;
+#ifdef XF86DRI
+ if (!I810DRILeave(pScrn))
+ return;
+#endif
+
+ vgaHWLock(hwp);
+}
+
+static Bool
+I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ I810Ptr pI810 = I810PTR(pScrn);
+ XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
+
+ if (pScrn->vtSema == TRUE) {
+ if (pI810->AccelInfoRec != NULL) {
+ I810RefreshRing(pScrn);
+ I810Sync(pScrn);
+ pI810->AccelInfoRec->NeedToSync = FALSE;
+ }
+ I810Restore(pScrn);
+ vgaHWLock(hwp);
+ }
+#ifdef XF86DRI
+ if (pI810->directRenderingEnabled) {
+ I810DRICloseScreen(pScreen);
+ pI810->directRenderingEnabled = FALSE;
+ }
+#endif
+
+ if (pScrn->vtSema == TRUE) {
+ I810UnbindGARTMemory(pScrn);
+ I810Restore(pScrn);
+ vgaHWLock(hwp);
+ }
+
+ I810UnmapMem(pScrn);
+ vgaHWUnmapMem(pScrn);
+
+ if (pI810->ScanlineColorExpandBuffers) {
+ 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);
+
+ xfree(pI810->LpRing);
+ pI810->LpRing = NULL;
+
+ pScrn->vtSema = FALSE;
+ pScreen->CloseScreen = pI810->CloseScreen;
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static void
+I810FreeScreen(int scrnIndex, int flags)
+{
+ I810FreeRec(xf86Screens[scrnIndex]);
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+}
+
+static ModeStatus
+I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ if (mode->Flags & V_INTERLACE) {
+ if (verbose) {
+ xf86DrvMsg(scrnIndex, X_PROBED,
+ "Removing interlaced mode \"%s\"\n", mode->name);
+ }
+ return MODE_BAD;
+ }
+ return MODE_OK;
+}
+
+static Bool
+I810SaveScreen(ScreenPtr pScreen, Bool unblack)
+{
+ return vgaHWSaveScreen(pScreen, unblack);
+}
+
+static void
+I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ I810Ptr pI810;
+ unsigned char SEQ01 = 0;
+ int DPMSSyncSelect = 0;
+
+ pI810 = I810PTR(pScrn);
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ }
+
+ /* Turn the screen on/off */
+ SEQ01 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20;
+ pI810->writeControl(pI810, SRX, 0x01, SEQ01);
+
+ /* Set the DPMS mode */
+ OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
+}
+#endif /* I830_ONLY */
diff --git a/driver/xf86-video-i810/src/i810_hwmc.c b/driver/xf86-video-i810/src/i810_hwmc.c
new file mode 100644
index 000000000..5d2532369
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_hwmc.c
@@ -0,0 +1,420 @@
+/***************************************************************************
+
+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.3 2001/12/04 21:17:56 tsi Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <X11/extensions/Xv.h>
+#include <X11/extensions/XvMC.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
+ int *num_priv, long **priv );
+void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
+
+int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
+
+int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
+ int *num_priv, long **priv );
+void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
+
+
+typedef struct {
+ drm_context_t drmcontext;
+ unsigned int fbBase;
+ unsigned int OverlayOffset;
+ unsigned int OverlaySize;
+ unsigned int SurfacesOffset;
+ unsigned int SurfacesSize;
+ char busIdString[10];
+ char pad[2];
+} I810XvMCCreateContextRec;
+
+
+static int yv12_subpicture_index_list[2] =
+{
+ FOURCC_IA44,
+ FOURCC_AI44
+};
+
+static XF86MCImageIDList yv12_subpicture_list =
+{
+ 2,
+ yv12_subpicture_index_list
+};
+
+static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_2,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface =
+{
+ FOURCC_YV12,
+ XVMC_CHROMA_FORMAT_420,
+ 0,
+ 720,
+ 576,
+ 720,
+ 576,
+ XVMC_MPEG_1,
+ XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
+ XVMC_INTRA_UNSIGNED,
+ &yv12_subpicture_list
+};
+
+static XF86MCSurfaceInfoPtr ppSI[2] =
+{
+ (XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface,
+ (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
+};
+
+/* List of subpicture types that we support */
+static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
+static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
+
+static XF86ImagePtr i810_subpicture_list[2] =
+{
+ (XF86ImagePtr)&ia44_subpicture,
+ (XF86ImagePtr)&ai44_subpicture
+};
+
+/* Fill in the device dependent adaptor record.
+ * This is named "I810 Video Overlay" because this code falls under the
+ * XV extenstion, the name must match or it won't be used.
+ *
+ * Surface and Subpicture - see above
+ * Function pointers to functions below
+ */
+static XF86MCAdaptorRec pAdapt =
+{
+ "I810 Video Overlay", /* name */
+ 2, /* num_surfaces */
+ ppSI, /* surfaces */
+ 2, /* num_subpictures */
+ i810_subpicture_list, /* subpictures */
+ (xf86XvMCCreateContextProcPtr)I810XvMCCreateContext,
+ (xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext,
+ (xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface,
+ (xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface,
+ (xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture,
+ (xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture
+};
+
+static XF86MCAdaptorPtr ppAdapt[1] =
+{
+ (XF86MCAdaptorPtr)&pAdapt
+};
+
+/**************************************************************************
+ *
+ * I810InitMC
+ *
+ * Initialize the hardware motion compenstation extention for this
+ * hardware. The initialization routines want the address of the pointers
+ * to the structures, not the address of the structures. This means we
+ * allocate (or create static?) the pointer memory and pass that
+ * address. This seems a little convoluted.
+ *
+ * We need to allocate memory for the device depended adaptor record.
+ * This is what holds the pointers to all our device functions.
+ *
+ * We need to map the overlay registers into the drm.
+ *
+ * We need to map the surfaces into the drm.
+ *
+ * Inputs:
+ * Screen pointer
+ *
+ * Outputs:
+ * None, this calls the device independent screen initialization
+ * function.
+ *
+ * Revisions:
+ *
+ **************************************************************************/
+void I810InitMC(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I810Ptr pI810 = I810PTR(pScrn);
+ int i;
+
+ /* Clear the Surface Allocation */
+ for(i=0; i<I810_MAX_SURFACES; i++) {
+ pI810->surfaceAllocation[i] = 0;
+ }
+
+ /* Cursor is at a page boundary, Overlay regs are not, don't forget */
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->CursorStart,
+ 4096, DRM_AGP, 0, &pI810->overlay_map) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
+ return;
+ }
+ if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->MC.Start,
+ pI810->MC.Size, DRM_AGP, 0, &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/driver/xf86-video-i810/src/i810_io.c b/driver/xf86-video-i810/src/i810_io.c
new file mode 100644
index 000000000..8d097f218
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_io.c
@@ -0,0 +1,148 @@
+/**************************************************************************
+
+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.4 2002/01/25 21:56:04 tsi Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * 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/driver/xf86-video-i810/src/i810_memory.c b/driver/xf86-video-i810/src/i810_memory.c
new file mode 100644
index 000000000..816e5d801
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_memory.c
@@ -0,0 +1,443 @@
+/* $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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * 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 > (long)pool->Size)
+ return 0;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->Start = pool->Start;
+ result->End = pool->Start += size;
+
+ return 1;
+}
+
+int
+I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size)
+{
+ if (size > (long)pool->Size)
+ return 0;
+
+ pool->Size -= size;
+ result->Size = size;
+ result->End = pool->End;
+ result->Start = pool->End -= size;
+
+ return 1;
+}
+
+int
+I810AllocateGARTMemory(ScrnInfoPtr pScrn)
+{
+ unsigned long size = pScrn->videoRam * 1024;
+ I810Ptr pI810 = I810PTR(pScrn);
+ int key;
+ long tom = 0;
+ unsigned long physical;
+
+ if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "AGP GART support is either not available or cannot be used.\n"
+ "\tMake sure your kernel has agpgart support or has the\n"
+ "\tagpgart module loaded.\n");
+ return FALSE;
+ }
+
+ /* This allows the 2d only Xserver to regen */
+ pI810->agpAcquired2d = TRUE;
+
+ /*
+ * I810/I815
+ *
+ * Treat the gart like video memory - we assume we own all that is
+ * there, so ignore EBUSY errors. Don't try to remove it on
+ * failure, either, as other X server may be using it.
+ */
+
+ if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL)) == -1)
+ return FALSE;
+
+ pI810->VramOffset = 0;
+ pI810->VramKey = key;
+
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, 0))
+ return FALSE;
+
+ pI810->SysMem.Start = 0;
+ pI810->SysMem.Size = size;
+ pI810->SysMem.End = size;
+ pI810->SavedSysMem = pI810->SysMem;
+
+ tom = pI810->SysMem.End;
+
+ pI810->DcacheMem.Start = 0;
+ pI810->DcacheMem.End = 0;
+ pI810->DcacheMem.Size = 0;
+ pI810->CursorPhysical = 0;
+ pI810->CursorARGBPhysical = 0;
+
+ /*
+ * Dcache - half the speed of normal ram, so not really useful for
+ * a 2d server. Don't bother reporting its presence. This is
+ * mapped in addition to the requested amount of system ram.
+ */
+
+ size = 1024 * 4096;
+
+ /*
+ * Keep it 512K aligned for the sake of tiled regions.
+ */
+
+ tom += 0x7ffff;
+ tom &= ~0x7ffff;
+
+ if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
+ pI810->DcacheOffset = tom;
+ pI810->DcacheKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for DCACHE failed\n", size);
+ pI810->DcacheKey = -1;
+ } else {
+ pI810->DcacheMem.Start = tom;
+ pI810->DcacheMem.Size = size;
+ pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size;
+ tom = pI810->DcacheMem.End;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for %ld bytes of DCACHE\n",
+ size);
+ pI810->DcacheKey = -1;
+ }
+
+ /*
+ * Mouse cursor -- The i810 (crazy) needs a physical address in
+ * system memory from which to upload the cursor. We get this from
+ * the agpgart module using a special memory type.
+ */
+
+ /*
+ * 4k for the cursor is excessive, I'm going to steal 3k for
+ * overlay registers later
+ */
+
+ size = 4096;
+
+ if ((key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for HW cursor\n");
+ pI810->HwcursKey = -1;
+ pI810->CursorStart = 0;
+ } else {
+ pI810->HwcursOffset = tom;
+ pI810->HwcursKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for HW cursor failed\n", size);
+ pI810->HwcursKey = -1;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocated of %ld bytes for HW cursor\n", size);
+ pI810->CursorPhysical = physical;
+ pI810->CursorStart = tom;
+ tom += size;
+ }
+ }
+
+ /*
+ * 16k for the ARGB cursor
+ */
+
+ size = 16384;
+
+ if ((key =
+ xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No physical memory available for ARGB HW cursor\n");
+ pI810->ARGBHwcursKey = -1;
+ pI810->CursorARGBStart = 0;
+ } else {
+ pI810->ARGBHwcursOffset = tom;
+ pI810->ARGBHwcursKey = key;
+ if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocation of %ld bytes for ARGB HW cursor failed\n", size);
+ pI810->ARGBHwcursKey = -1;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Allocated of %ld bytes for ARGB HW cursor\n", size);
+ pI810->CursorARGBPhysical = physical;
+ pI810->CursorARGBStart = tom;
+ tom += size;
+ }
+ }
+
+ /*
+ * Overlay register buffer -- Just like the cursor, the i810 needs a
+ * physical address in system memory from which to upload the overlay
+ * registers.
+ */
+
+ if (pI810->CursorStart != 0) {
+ pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
+ pI810->OverlayStart = pI810->CursorStart + 1024;
+ }
+
+ pI810->GttBound = 1;
+
+ return TRUE;
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+void
+I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned int start,
+ unsigned int pitch, unsigned int size)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810RegPtr i810Reg = &pI810->ModeReg;
+ 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;
+
+ if (pI810->ARGBHwcursKey != -1
+ && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey,
+ pI810->ARGBHwcursOffset))
+ return FALSE;
+
+ pI810->GttBound = 1;
+ }
+
+ return TRUE;
+}
+
+Bool
+I810UnbindGARTMemory(ScrnInfoPtr pScrn)
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled
+ && pI810->GttBound) {
+ if (pI810->VramKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->VramKey))
+ return FALSE;
+
+ if (pI810->DcacheKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey))
+ return FALSE;
+
+ if (pI810->HwcursKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey))
+ return FALSE;
+
+ if (pI810->ARGBHwcursKey != -1
+ && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey))
+ return FALSE;
+
+ if (!xf86ReleaseGART(pScrn->scrnIndex))
+ return FALSE;
+
+ pI810->GttBound = 0;
+ }
+
+ return TRUE;
+}
+
+int
+I810CheckAvailableMemory(ScrnInfoPtr pScrn)
+{
+ AgpInfoPtr agpinf;
+ int maxPages;
+
+ if (!xf86AgpGARTSupported() ||
+ !xf86AcquireGART(pScrn->scrnIndex) ||
+ (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL ||
+ !xf86ReleaseGART(pScrn->scrnIndex))
+ return -1;
+
+ maxPages = agpinf->totalPages - agpinf->usedPages;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %dk available\n",
+ "I810CheckAvailableMemory", maxPages * 4);
+
+ return maxPages * 4;
+}
diff --git a/driver/xf86-video-i810/src/i810_reg.h b/driver/xf86-video-i810/src/i810_reg.h
new file mode 100644
index 000000000..e52375f82
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_reg.h
@@ -0,0 +1,1019 @@
+/* $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
+
+#define CURSOR_B_CONTROL 0x700C0
+#define CURSOR_B_BASE 0x700C4
+#define CURSOR_B_POSITION 0x700C8
+#define CURSOR_B_PALETTE0 0x700D0
+#define CURSOR_B_PALETTE1 0x700D4
+#define CURSOR_B_PALETTE2 0x700D8
+#define CURSOR_B_PALETTE3 0x700DC
+
+
+/* Similar registers exist in Device 0 on the i810 (pp55-65), but I'm
+ * not sure they refer to local (graphics) memory.
+ *
+ * These details are for the local memory control registers,
+ * (pp301-310). The test machines are not equiped with local memory,
+ * so nothing is tested. Only a single row seems to be supported.
+ */
+#define DRAM_ROW_TYPE 0x3000
+#define DRAM_ROW_0 0x01
+#define DRAM_ROW_0_SDRAM 0x01
+#define DRAM_ROW_0_EMPTY 0x00
+#define DRAM_ROW_CNTL_LO 0x3001
+#define DRAM_PAGE_MODE_CTRL 0x10
+#define DRAM_RAS_TO_CAS_OVRIDE 0x08
+#define DRAM_CAS_LATENCY 0x04
+#define DRAM_RAS_TIMING 0x02
+#define DRAM_RAS_PRECHARGE 0x01
+#define DRAM_ROW_CNTL_HI 0x3002
+#define DRAM_REFRESH_RATE 0x18
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x08
+#define DRAM_REFRESH_FAST_TEST 0x10
+#define DRAM_REFRESH_RESERVED 0x18
+#define DRAM_SMS 0x07
+#define DRAM_SMS_NORMAL 0x00
+#define DRAM_SMS_NOP_ENABLE 0x01
+#define DRAM_SMS_ABPCE 0x02
+#define DRAM_SMS_MRCE 0x03
+#define DRAM_SMS_CBRCE 0x04
+
+/* p307
+ */
+#define DPMS_SYNC_SELECT 0x5002
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+
+
+/* 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 I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define 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 0x03FFFFF8
+#define I830_RING_START_MASK 0xFFFFF000
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x001FF000
+#define I830_RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+
+
+/* BitBlt Instructions
+ *
+ * There are many more masks & ranges yet to add.
+ */
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR00_OP_FULL_BLT 0x11400000
+#define BR00_OP_MONO_SRC_BLT 0x11800000
+#define BR00_OP_MONO_SRC_COPY_BLT 0x11000000
+#define BR00_OP_MONO_PAT_BLT 0x11C00000
+#define BR00_OP_MONO_SRC_COPY_IMMEDIATE_BLT (0x61 << 22)
+#define BR00_OP_TEXT_IMMEDIATE_BLT 0xc000000
+
+
+#define BR00_TPCY_DISABLE 0x00000000
+#define BR00_TPCY_ENABLE 0x00000010
+
+#define BR00_TPCY_ROP 0x00000000
+#define BR00_TPCY_NO_ROP 0x00000020
+#define BR00_TPCY_EQ 0x00000000
+#define BR00_TPCY_NOT_EQ 0x00000040
+
+#define BR00_PAT_MSB_FIRST 0x00000000 /* ? */
+
+#define BR00_PAT_VERT_ALIGN 0x000000e0
+
+#define BR00_LENGTH 0x0000000F
+
+#define BR09_DEST_ADDR 0x03FFFFFF
+
+#define BR11_SOURCE_PITCH 0x00003FFF
+
+#define BR12_SOURCE_ADDR 0x03FFFFFF
+
+#define BR13_SOLID_PATTERN 0x80000000
+#define BR13_RIGHT_TO_LEFT 0x40000000
+#define BR13_LEFT_TO_RIGHT 0x00000000
+#define BR13_MONO_TRANSPCY 0x20000000
+#define BR13_MONO_PATN_TRANS 0x10000000
+#define BR13_USE_DYN_DEPTH 0x04000000
+#define BR13_DYN_8BPP 0x00000000
+#define BR13_DYN_16BPP 0x01000000
+#define BR13_DYN_24BPP 0x02000000
+#define BR13_ROP_MASK 0x00FF0000
+#define BR13_DEST_PITCH 0x0000FFFF
+#define BR13_PITCH_SIGN_BIT 0x00008000
+
+#define BR14_DEST_HEIGHT 0xFFFF0000
+#define BR14_DEST_WIDTH 0x0000FFFF
+
+#define BR15_PATTERN_ADDR 0x03FFFFFF
+
+#define BR16_SOLID_PAT_COLOR 0x00FFFFFF
+#define BR16_BACKGND_PAT_CLR 0x00FFFFFF
+
+#define BR17_FGND_PAT_CLR 0x00FFFFFF
+
+#define BR18_SRC_BGND_CLR 0x00FFFFFF
+#define BR19_SRC_FGND_CLR 0x00FFFFFF
+
+
+/* Instruction parser instructions
+ */
+
+#define INST_PARSER_CLIENT 0x00000000
+#define INST_OP_FLUSH 0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+
+#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+
+
+/* Registers in the i810 host-pci bridge pci config space which affect
+ * the i810 graphics operations.
+ */
+#define SMRAM_MISCC 0x70
+#define GMS 0x000000c0
+#define GMS_DISABLE 0x00000000
+#define GMS_ENABLE_BARE 0x00000040
+#define GMS_ENABLE_512K 0x00000080
+#define GMS_ENABLE_1M 0x000000c0
+#define USMM 0x00000030
+#define USMM_DISABLE 0x00000000
+#define USMM_TSEG_ZERO 0x00000010
+#define USMM_TSEG_512K 0x00000020
+#define USMM_TSEG_1M 0x00000030
+#define GFX_MEM_WIN_SIZE 0x00010000
+#define GFX_MEM_WIN_32M 0x00010000
+#define GFX_MEM_WIN_64M 0x00000000
+
+/* Overkill? I don't know. Need to figure out top of mem to make the
+ * SMRAM calculations come out. Linux seems to have problems
+ * detecting it all on its own, so this seems a reasonable double
+ * check to any user supplied 'mem=...' boot param.
+ *
+ * ... unfortunately this reg doesn't work according to spec on the
+ * test hardware.
+ */
+#define WHTCFG_PAMR_DRP 0x50
+#define SYS_DRAM_ROW_0_SHIFT 16
+#define SYS_DRAM_ROW_1_SHIFT 20
+#define DRAM_MASK 0x0f
+#define DRAM_VALUE_0 0
+#define DRAM_VALUE_1 8
+/* No 2 value defined */
+#define DRAM_VALUE_3 16
+#define DRAM_VALUE_4 16
+#define DRAM_VALUE_5 24
+#define DRAM_VALUE_6 32
+#define DRAM_VALUE_7 32
+#define DRAM_VALUE_8 48
+#define DRAM_VALUE_9 64
+#define DRAM_VALUE_A 64
+#define DRAM_VALUE_B 96
+#define DRAM_VALUE_C 128
+#define DRAM_VALUE_D 128
+#define DRAM_VALUE_E 192
+#define DRAM_VALUE_F 256 /* nice one, geezer */
+#define LM_FREQ_MASK 0x10
+#define LM_FREQ_133 0x10
+#define LM_FREQ_100 0x00
+
+
+
+
+/* These are 3d state registers, but the state is invarient, so we let
+ * the X server handle it:
+ */
+
+
+
+/* GFXRENDERSTATE_COLOR_CHROMA_KEY, p135
+ */
+#define GFX_OP_COLOR_CHROMA_KEY ((0x3<<29)|(0x1d<<24)|(0x2<<16)|0x1)
+#define CC1_UPDATE_KILL_WRITE (1<<28)
+#define CC1_ENABLE_KILL_WRITE (1<<27)
+#define CC1_DISABLE_KILL_WRITE 0
+#define CC1_UPDATE_COLOR_IDX (1<<26)
+#define CC1_UPDATE_CHROMA_LOW (1<<25)
+#define CC1_UPDATE_CHROMA_HI (1<<24)
+#define CC1_CHROMA_LOW_MASK ((1<<24)-1)
+#define CC2_COLOR_IDX_SHIFT 24
+#define CC2_COLOR_IDX_MASK (0xff<<24)
+#define CC2_CHROMA_HI_MASK ((1<<24)-1)
+
+
+#define GFX_CMD_CONTEXT_SEL ((0<<29)|(0x5<<23))
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_UPDATE_USE (1<<16)
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_LOAD_CTX0 0
+#define CS_LOAD_CTX1 (1<<8)
+#define CS_USE_CTX0 0
+#define CS_USE_CTX1 (1<<0)
+
+/* I810 LCD/TV registers */
+#define LCD_TV_HTOTAL 0x60000
+#define LCD_TV_C 0x60018
+#define LCD_TV_OVRACT 0x6001C
+
+#define LCD_TV_ENABLE (1 << 31)
+#define LCD_TV_VGAMOD (1 << 28)
+
+/* I830 CRTC registers */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+
+#define 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_DOUBLE_WIDE (1<<30)
+#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
+
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+
+/* 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 I915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 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/driver/xf86-video-i810/src/i810_video.c b/driver/xf86-video-i810/src/i810_video.c
new file mode 100644
index 000000000..f420d2f28
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_video.c
@@ -0,0 +1,1423 @@
+/***************************************************************************
+
+Copyright 2000 Intel Corporation. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_video.c,v 1.26 2003/11/10 18:22:22 tsi 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>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <X11/extensions/Xv.h>
+#include "xaa.h"
+#include "xaalocal.h"
+#include "dixstruct.h"
+#include "fourcc.h"
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+static void I810InitOffscreenImages(ScreenPtr);
+
+static XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr);
+static void I810StopVideo(ScrnInfoPtr, pointer, Bool);
+static int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static void I810QueryBestSize(ScrnInfoPtr, Bool,
+ short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int I810PutImage( ScrnInfoPtr,
+ short, short, short, short, short, short, short, short,
+ int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+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 6
+
+#define I810_RV15 0x35315652
+#define I810_RV16 0x36315652
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+ {
+ I810_RV15,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','5',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 15, 0x7C00, 0x03E0, 0x001F,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ {
+ I810_RV16,
+ XvRGB,
+ LSBFirst,
+ {'R','V','1','6',
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ 16,
+ XvPacked,
+ 1,
+ 16, 0xF800, 0x07E0, 0x001F,
+ 0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ {'R','V','B',0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ XvTopToBottom
+ },
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+/* *INDENT-ON* */
+
+typedef struct {
+ 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_NULL(pScreen, &pPriv->clip);
+
+ pI810->adaptor = adapt;
+
+ pI810->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = I810BlockHandler;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ I810ResetVideo(pScrn);
+
+ return adapt;
+}
+
+
+/* I810ClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (x1, y1
+ inclusive, x2, y2 exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+static void
+I810ClipVideo(
+ BoxPtr dst,
+ INT32 *x1,
+ INT32 *x2,
+ INT32 *y1,
+ INT32 *y2,
+ BoxPtr extents, /* extents of the clip region */
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ int diff;
+
+ hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
+
+ *x1 <<= 16; *x2 <<= 16;
+ *y1 <<= 16; *y2 <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *x1 += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *x2 -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *y1 += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *y2 -= diff * vscale;
+ }
+
+ if(*x1 < 0) {
+ diff = (- *x1 + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *x1 += diff * hscale;
+ }
+ delta = *x2 - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *x2 -= diff * hscale;
+ }
+ if(*y1 < 0) {
+ diff = (- *y1 + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *y1 += diff * vscale;
+ }
+ delta = *y2 - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *y2 -= diff * vscale;
+ }
+}
+
+static void
+I810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
+{
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ I810Ptr pI810 = I810PTR(pScrn);
+
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(shutdown) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ }
+ if(pPriv->linear) {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+
+}
+
+static int
+I810SetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ if(attribute == xvBrightness) {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPriv->brightness = value;
+ overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ } else
+ if(attribute == xvContrast) {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPriv->contrast = value;
+ overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff);
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ } else
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ switch(pScrn->depth) {
+ case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey);
+ break;
+ case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey);
+ break;
+ default: overlay->DCLRKV = pPriv->colorKey;
+ break;
+ }
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+I810GetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+
+ if(attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else
+ if(attribute == xvContrast) {
+ *value = pPriv->contrast;
+ } else
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else return BadMatch;
+
+ return Success;
+}
+
+static void
+I810QueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1;
+ if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+
+static void
+I810CopyPackedData(
+ ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch,
+ int top,
+ int left,
+ int h,
+ int w
+ )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ unsigned char *src, *dst;
+
+ src = buf + (top*srcPitch) + (left<<1);
+
+ if (pPriv->currentBuf == 0)
+ dst = pI810->FbBase + pPriv->YBuf0offset;
+ else
+ dst = pI810->FbBase + pPriv->YBuf1offset;
+
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+I810CopyPlanarData(
+ ScrnInfoPtr pScrn,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch, /* of chroma */
+ int srcH,
+ int top,
+ int left,
+ int h,
+ int w,
+ int id
+ )
+{
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ int i;
+ unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+
+ /* Copy Y data */
+ src1 = buf + (top*srcPitch) + left;
+ if (pPriv->currentBuf == 0)
+ dst1 = pI810->FbBase + pPriv->YBuf0offset;
+ else
+ dst1 = pI810->FbBase + pPriv->YBuf1offset;
+
+ for (i = 0; i < h; i++) {
+ memcpy(dst1, src1, w);
+ src1 += srcPitch;
+ dst1 += dstPitch << 1;
+ }
+
+ /* Copy V data for YV12, or U data for I420 */
+ src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst2 = pI810->FbBase + pPriv->UBuf0offset;
+ else
+ dst2 = pI810->FbBase + pPriv->VBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst2 = pI810->FbBase + pPriv->UBuf1offset;
+ else
+ dst2 = pI810->FbBase + pPriv->VBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst2, src2, w/2);
+ src2 += srcPitch>>1;
+ dst2 += dstPitch;
+ }
+
+ /* Copy U data for YV12, or V data for I420 */
+ src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPriv->currentBuf == 0) {
+ if (id == FOURCC_I420)
+ dst3 = pI810->FbBase + pPriv->VBuf0offset;
+ else
+ dst3 = pI810->FbBase + pPriv->UBuf0offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst3 = pI810->FbBase + pPriv->VBuf1offset;
+ else
+ dst3 = pI810->FbBase + pPriv->UBuf1offset;
+ }
+
+ for (i = 0; i < h/2; i++) {
+ memcpy(dst3, src3, w/2);
+ src3 += srcPitch>>1;
+ dst3 += dstPitch;
+ }
+}
+
+static void
+I810DisplayVideo(
+ ScrnInfoPtr pScrn,
+ int id,
+ short width, short height,
+ int dstPitch, /* of chroma for 4:2:0 */
+ int x1, int y1, int x2, int y2,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr;
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0;
+ unsigned int swidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ swidth = (width + 7) & ~7;
+ overlay->SWID = (swidth << 15) | swidth;
+ overlay->SWIDQW = (swidth << 12) | (swidth >> 3);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ swidth = ((width + 3) & ~3) << 1;
+ overlay->SWID = swidth;
+ overlay->SWIDQW = swidth >> 3;
+ break;
+ }
+
+ /* wide video formats (>720 pixels) are special */
+ if( swidth > IMAGE_FAST_WIDTH ) {
+ overlay->OV0CONF = 1; /* one 1440 pixel line buffer */
+ } else {
+ overlay->OV0CONF = 0; /* two 720 pixel line buffers */
+ }
+
+ overlay->SHEIGHT = height | (height << 15);
+ overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1);
+ overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
+ (dstBox->x2 - dstBox->x1);
+
+ /* buffer locations */
+ overlay->OBUF_0Y = pPriv->YBuf0offset;
+ overlay->OBUF_1Y = pPriv->YBuf1offset;
+ overlay->OBUF_0U = pPriv->UBuf0offset;
+ overlay->OBUF_0V = pPriv->VBuf0offset;
+ overlay->OBUF_1U = pPriv->UBuf1offset;
+ overlay->OBUF_1V = pPriv->VBuf1offset;
+
+ /*
+ * Calculate horizontal and vertical scaling factors, default to 1:1
+ */
+ overlay->YRGBSCALE = 0x80004000;
+ overlay->UVSCALE = 0x80004000;
+
+ /*
+ * Initially, YCbCr and Overlay Enable and
+ * vertical chrominance up interpolation and horozontal chrominance
+ * up interpolation
+ */
+ overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST |
+ OVERLAY_ENABLE;
+
+ if ((drw_w != src_w) || (drw_h != src_h))
+ {
+ xscaleInt = (src_w / drw_w) & 0x3;
+ xscaleFract = (src_w << 12) / drw_w;
+ yscaleInt = (src_h / drw_h) & 0x3;
+ yscaleFract = (src_h << 12) / drw_h;
+
+ overlay->YRGBSCALE = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) |
+ (yscaleInt) |
+ ((yscaleFract & 0xFFF) << 20);
+
+ if (drw_w > src_w)
+ {
+ /* horizontal up-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
+ }
+
+ if (drw_h > src_h)
+ {
+ /* vertical up-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
+ }
+
+ if (drw_w < src_w)
+ {
+ /* horizontal down-scaling */
+ overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
+ }
+
+ if (drw_h < src_h)
+ {
+ /* vertical down-scaling */
+ overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER;
+ overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER;
+ overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
+ }
+
+ /* now calculate the UV scaling factor */
+
+ if (xscaleFract)
+ {
+ xscaleFractUV = xscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= HC_UP_INTERPOLATION;
+ }
+
+ if (xscaleInt)
+ {
+ xscaleIntUV = xscaleInt >> MINUV_SCALE;
+ if (xscaleIntUV)
+ {
+ overlay->OV0CMD &= ~HC_UP_INTERPOLATION;
+ }
+ }
+
+ if (yscaleFract)
+ {
+ yscaleFractUV = yscaleFract >> MINUV_SCALE;
+ overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION;
+ overlay->OV0CMD |= VC_UP_INTERPOLATION;
+ }
+
+ if (yscaleInt)
+ {
+ yscaleIntUV = yscaleInt >> MINUV_SCALE;
+ if (yscaleIntUV)
+ {
+ overlay->OV0CMD &= ~VC_UP_INTERPOLATION;
+ overlay->OV0CMD |= VC_DOWN_INTERPOLATION;
+ }
+ }
+
+ overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ }
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ /* set UV vertical phase to -0.25 */
+ overlay->UV_VPH = 0x30003000;
+ overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1;
+ overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_420;
+ break;
+ case I810_RV15:
+ case I810_RV16:
+ overlay->UV_VPH = 0;
+ overlay->INIT_PH = 0;
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565);
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ overlay->UV_VPH = 0;
+ overlay->INIT_PH = 0;
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_422;
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ if (id == FOURCC_UYVY)
+ overlay->OV0CMD |= Y_SWAP;
+ break;
+ }
+
+ overlay->OV0CMD &= ~BUFFER_AND_FIELD;
+ if (pPriv->currentBuf == 0)
+ overlay->OV0CMD |= BUFFER0_FIELD0;
+ else
+ overlay->OV0CMD |= BUFFER1_FIELD0;
+
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+
+}
+
+static FBLinearPtr
+I810AllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBLinearPtr linear,
+ int size
+){
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+
+ xf86FreeOffscreenLinear(linear);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
+ NULL, NULL, NULL);
+
+ if(!new_linear) {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
+ PRIORITY_EXTREME);
+
+ if(max_size < size) return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
+ NULL, NULL, NULL);
+ }
+
+ return new_linear;
+}
+
+static int
+I810PutImage(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool sync,
+ RegionPtr clipBoxes, pointer data
+){
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch;
+ int top, left, npixels, nlines, size, loops;
+ BoxRec dstBox;
+
+
+ /* Clip */
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScrn->pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2))
+ return Success;
+ /*
+ * Fix for 4 pixel granularity of AdjustFrame
+ * unless boarder is clipped by frame
+ */
+ dstBox.x1 -= (pScrn->frameX0 &
+ ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
+ dstBox.x2 -= (pScrn->frameX0 & ~0x3);
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ dstPitch = ((width >> 1) + 7) & ~7; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 7) & ~7;
+ size = dstPitch * height;
+ break;
+ }
+
+ if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear,
+ (pScrn->bitsPerPixel == 16) ? size : (size >> 1))))
+ return BadAlloc;
+
+ /* fixup pointers */
+ pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp;
+ pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+ pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);
+
+ pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size;
+ pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+ pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);
+
+
+ /* Make sure this buffer isn't in use */
+ loops = 0;
+ while (loops < 1000000) {
+ if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) {
+ break;
+ }
+ loops++;
+ }
+ if(loops >= 1000000) {
+ pPriv->currentBuf = !pPriv->currentBuf;
+ }
+
+
+ /* buffer swap */
+ if (pPriv->currentBuf == 0)
+ pPriv->currentBuf = 1;
+ else
+ pPriv->currentBuf = 0;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left,
+ nlines, npixels, id);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ break;
+ }
+
+ /* update cliplist */
+ if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+ /* draw these */
+ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+ }
+
+ I810DisplayVideo(pScrn, id, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ return Success;
+}
+
+
+static int
+I810QueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH;
+ if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ /* IA44 is for XvMC only */
+ case FOURCC_IA44:
+ case FOURCC_AI44:
+ if(pitches) pitches[0] = *w;
+ size = *w * *h;
+ break;
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+static void
+I810BlockHandler (
+ int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ I810Ptr pI810 = I810PTR(pScrn);
+ I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
+ I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
+
+ pScreen->BlockHandler = pI810->BlockHandler;
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ pScreen->BlockHandler = I810BlockHandler;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ UpdateCurrentTime();
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < currentTime.milliseconds) {
+ /* Turn off the overlay */
+ overlay->OV0CMD &= 0xFFFFFFFE;
+ OVERLAY_UPDATE(pI810->OverlayPhysical);
+
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ } else { /* FREE_TIMER */
+ if(pPriv->freeTime < currentTime.milliseconds) {
+ if(pPriv->linear) {
+ xf86FreeOffscreenLinear(pPriv->linear);
+ pPriv->linear = NULL;
+ }
+ pPriv->videoStatus = 0;
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ * Offscreen Images
+ ***************************************************************************/
+
+typedef struct {
+ FBLinearPtr linear;
+ Bool isOn;
+} OffscreenPrivRec, * OffscreenPrivPtr;
+
+static int
+I810AllocateSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h,
+ XF86SurfacePtr surface
+){
+ FBLinearPtr linear;
+ int pitch, 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);
+
+ /*
+ * Fix for 4 pixel granularity of AdjustFrame
+ * unless boarder is clipped by frame
+ */
+ dstBox.x1 -= (pScrn->frameX0 &
+ ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));
+ dstBox.x2 -= (pScrn->frameX0 & ~0x3);
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ /* fixup pointers */
+ pI810Priv->YBuf0offset = surface->offsets[0];
+ pI810Priv->YBuf1offset = pI810Priv->YBuf0offset;
+
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) {
+ if(loops == 200000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
+ break;
+ }
+ loops++;
+ }
+
+ /* buffer swap */
+ if (pI810Priv->currentBuf == 0)
+ pI810Priv->currentBuf = 1;
+ else
+ pI810Priv->currentBuf = 0;
+
+ I810ResetVideo(pScrn);
+
+ I810DisplayVideo(pScrn, surface->id, surface->width, surface->height,
+ surface->pitches[0], x1, y1, x2, y2, &dstBox,
+ src_w, src_h, drw_w, drw_h);
+
+ xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes);
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip);
+ UpdateCurrentTime();
+ pI810Priv->videoStatus = FREE_TIMER;
+ pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ pScrn->pScreen->BlockHandler = I810BlockHandler;
+ }
+
+ return Success;
+}
+
+
+static void
+I810InitOffscreenImages(ScreenPtr pScreen)
+{
+ XF86OffscreenImagePtr offscreenImages;
+
+ /* need to free this someplace */
+ if(!(offscreenImages = 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/driver/xf86-video-i810/src/i810_wmark.c b/driver/xf86-video-i810/src/i810_wmark.c
new file mode 100644
index 000000000..6540cbba4
--- /dev/null
+++ b/driver/xf86-video-i810/src/i810_wmark.c
@@ -0,0 +1,325 @@
+
+/**************************************************************************
+
+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.7 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:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i810.h"
+
+struct wm_info {
+ double freq;
+ unsigned int wm;
+};
+
+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/driver/xf86-video-i810/src/i830.h b/driver/xf86-video-i810/src/i830.h
new file mode 100644
index 000000000..eef28e79a
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830.h
@@ -0,0 +1,487 @@
+
+/**************************************************************************
+
+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.12 2004/01/07 03:43:19 dawes Exp $ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * David Dawes <dawes@xfree86.org>
+ *
+ */
+
+#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 "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>.
+ */
+
+#define PIPE_NONE 0<<0
+#define PIPE_CRT 1<<0
+#define PIPE_TV 1<<1
+#define PIPE_DFP 1<<2
+#define PIPE_LFP 1<<3
+#define PIPE_CRT2 1<<4
+#define PIPE_TV2 1<<5
+#define PIPE_DFP2 1<<6
+#define PIPE_LFP2 1<<7
+
+typedef struct _VESARec {
+ /* SVGA state */
+ pointer state, pstate;
+ int statePage, stateSize, stateMode, stateRefresh;
+ CARD32 *savedPal;
+ int savedScanlinePitch;
+ xf86MonPtr monitor;
+ /* Don't try to set the refresh rate for any modes. */
+ Bool useDefaultRefresh;
+ /* display start */
+ int x, y;
+} 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 {
+ int lastInstance;
+ int refCount;
+ ScrnInfoPtr pScrn_1;
+ ScrnInfoPtr pScrn_2;
+ int RingRunning;
+#ifdef I830_XV
+ int XvInUse;
+#endif
+} I830EntRec, *I830EntPtr;
+
+typedef struct _I830Rec {
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+ int cpp;
+
+ unsigned int bios_version;
+
+ Bool newPipeSwitch;
+
+ Bool fakeSwitch;
+
+ int fixedPipe;
+
+ Bool Clone;
+ int CloneRefresh;
+ int CloneHDisplay;
+ int CloneVDisplay;
+
+ I830EntPtr entityPrivate;
+ int pipe, origPipe;
+ int init;
+
+ unsigned int bufferOffset; /* for I830SelectBuffer */
+ BoxRec FbMemBox;
+ BoxRec FbMemBox2;
+ int CacheLines;
+
+ /* These are set in PreInit and never changed. */
+ long FbMapSize;
+ long TotalVideoRam;
+ I830MemRange StolenMemory; /* pre-allocated memory */
+ long BIOSMemorySize; /* min stolen pool size */
+ int BIOSMemSizeLoc;
+
+ /* These change according to what has been allocated. */
+ long FreeMemory;
+ I830MemRange MemoryAperture;
+ I830MemPool StolenPool;
+ long allocatedMemory;
+
+ /* Regions allocated either from the above pools, or from agpgart. */
+ /* for single and dual head configurations */
+ I830MemRange FrontBuffer;
+ I830MemRange FrontBuffer2;
+ I830MemRange Scratch;
+ I830MemRange Scratch2;
+
+ /* Regions allocated either from the above pools, or from agpgart. */
+ I830MemRange *CursorMem;
+ I830MemRange *CursorMemARGB;
+ I830RingBuffer *LpRing;
+
+#if REMAP_RESERVED
+ I830MemRange Dummy;
+#endif
+
+#ifdef I830_XV
+ /* For Xvideo */
+ I830MemRange *OverlayMem;
+#endif
+
+#ifdef XF86DRI
+ I830MemRange BackBuffer;
+ I830MemRange DepthBuffer;
+ I830MemRange TexMem;
+ I830MemRange ContextMem;
+ int TexGranularity;
+ int drmMinor;
+ Bool have3DWindows;
+#endif
+
+ Bool NeedRingBufferLow;
+ Bool allowPageFlip;
+ Bool disableTiling;
+
+ int backPitch;
+
+ Bool CursorNeedsPhysical;
+ Bool CursorIsARGB;
+
+ int MonType1;
+ int MonType2;
+ Bool specifiedMonitor;
+
+ 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;
+
+ 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;
+ ScreenBlockHandlerProcPtr BlockHandler;
+ 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;
+ drm_handle_t buffer_map;
+ drm_handle_t ring_map;
+#endif
+
+ /* Broken-out options. */
+ OptionInfoPtr Options;
+ int rotate;
+ Bool shadowFB;
+
+ /* Support for shadowFB and rotation. */
+ unsigned char *shadowPtr;
+ int shadowPitch;
+ void (*PointerMoved)(int, int, int);
+
+ /* 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 0x5f05 to set the refresh rate. */
+ Bool useExtendedRefresh;
+
+ Bool checkDevices;
+ int monitorSwitch;
+ int operatingDevices;
+ int savedDevices;
+ int lastDevice1, lastDevice2;
+
+ /* 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 preinit;
+ Bool starting;
+ Bool closing;
+ Bool suspended;
+ Bool leaving;
+
+ /* fbOffset converted to (x, y). */
+ int xoffset;
+ int yoffset;
+
+ unsigned int SaveGeneration;
+ Bool vbeRestoreWorkaround;
+ Bool displayInfo;
+ Bool devicePresence;
+
+ OsTimerPtr devicesTimer;
+} 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 Bool I830DRIResume(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, 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);
+
+extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
+ VbeInfoBlock *vbe);
+extern void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
+extern void I830UnsetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe);
+extern void I830PrintModes(ScrnInfoPtr pScrn);
+extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
+extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
+extern void I830PointerMoved(int index, int x, int y);
+extern void I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern void I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+/*
+ * 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(32) / 1024)
+#define I830_DEFAULT_VIDEOMEM_3D (MB(64) / 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
+
+/* Chipset registers for VIDEO BIOS memory RW access */
+#define _855_DRAM_RW_CONTROL 0x58
+#define _845_DRAM_RW_CONTROL 0x90
+#define DRAM_WRITE 0x33330000
+
+#endif /* _I830_H_ */
diff --git a/driver/xf86-video-i810/src/i830_accel.c b/driver/xf86-video-i810/src/i830_accel.c
new file mode 100644
index 000000000..7211f4bd1
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_accel.c
@@ -0,0 +1,797 @@
+/*
+ * XXX So far, for GXxor this is about 40% of the speed of SW, but CPU
+ * utilisation falls from 95% to < 5%.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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.8 2003/04/24 18:00:24 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 "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+
+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
+
+ if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return;
+
+ /* 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 = pScrn->fbOffset;
+ 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
+static void I830RestoreAccelState(ScrnInfoPtr pScrn);
+
+
+/* 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);
+ int i;
+ int width = 0;
+ int nr_buffers = 0;
+ unsigned char *ptr = NULL;
+
+ 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);
+
+ }
+
+ /* On the primary screen */
+ if (pI830->init == 0) {
+ if (pI830->Scratch.Size != 0) {
+ width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ nr_buffers = pI830->Scratch.Size / width;
+ ptr = pI830->FbBase + pI830->Scratch.Start;
+ }
+ } else {
+ /* On the secondary screen */
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ if (pI8301->Scratch2.Size != 0) {
+ width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ nr_buffers = pI8301->Scratch2.Size / width;
+ /* We have to use the primary screen's FbBase, as that's where
+ * we allocated Scratch2, so we get the correct pointer */
+ ptr = pI8301->FbBase + pI8301->Scratch2.Start;
+ }
+ }
+
+ if (nr_buffers) {
+ 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
+ }
+
+ {
+ Bool shared_accel = FALSE;
+ int i;
+
+ for(i = 0; i < pScrn->numEntities; i++) {
+ if(xf86IsEntityShared(pScrn->entityList[i]))
+ shared_accel = TRUE;
+ }
+ if(shared_accel == TRUE)
+ infoPtr->RestoreAccelState = I830RestoreAccelState;
+ }
+
+ 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] = ((XAAGetPatternROP(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] |= XAAGetCopyROP(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] |= XAAGetPatternROP(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] |= XAAGetCopyROP(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);
+
+ if (pI830->init == 0) {
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI830->FbBase);
+ } else {
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+ /* We have to use the primary screen's FbBase, as that's where
+ * we allocated Scratch2, so we get the correct pointer */
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI8301->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] |= XAAGetCopyROP(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);
+
+ if (pI830->init == 0) {
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI830->FbBase);
+ } else {
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+ /* We have to use the primary screen's FbBase, as that's where
+ * we allocated Scratch2, so we get the correct pointer */
+ pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] -
+ pI8301->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
+
+/* Support for multiscreen */
+static void
+I830RestoreAccelState(ScrnInfoPtr pScrn)
+{
+#if 0
+ /* might be needed, but everything is on a ring, so I don't think so */
+ I830Sync(pScrn);
+#endif
+}
diff --git a/driver/xf86-video-i810/src/i830_common.h b/driver/xf86-video-i810/src/i830_common.h
new file mode 100644
index 000000000..a0a00ff4e
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_common.h
@@ -0,0 +1,168 @@
+/**************************************************************************
+
+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.1 2002/09/11 00:29:32 dawes Exp $ */
+
+#ifndef _I830_COMMON_H_
+#define _I830_COMMON_H_
+
+
+#define I830_NR_TEX_REGIONS 255 /* maximum due to use of chars for next/prev */
+#define I830_LOG_MIN_TEX_REGION_SIZE 14
+
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_I830_INIT 0x00
+#define DRM_I830_FLUSH 0x01
+#define DRM_I830_FLIP 0x02
+#define DRM_I830_BATCHBUFFER 0x03
+#define DRM_I830_IRQ_EMIT 0x04
+#define DRM_I830_IRQ_WAIT 0x05
+#define DRM_I830_GETPARAM 0x06
+#define DRM_I830_SETPARAM 0x07
+#define DRM_I830_ALLOC 0x08
+#define DRM_I830_FREE 0x09
+#define DRM_I830_INIT_HEAP 0x0a
+#define DRM_I830_CMDBUFFER 0x0b
+
+typedef struct {
+ enum {
+ I830_INIT_DMA = 0x01,
+ I830_CLEANUP_DMA = 0x02,
+ I830_RESUME_DMA = 0x03
+ } func;
+ unsigned int mmio_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;
+ unsigned int chipset;
+} drmI830Init;
+
+typedef struct {
+ drmTextureRegion texList[I830_NR_TEX_REGIONS+1];
+ int last_upload; /* 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 ctxOwner; /* last context to upload state */
+ int texAge;
+ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active;
+ int pf_current_page; /* which buffer is being displayed? */
+ int perf_boxes; /* performance boxes to be displayed */
+} drmI830Sarea;
+
+/* 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 */
+
+
+typedef struct {
+ int start; /* agp offset */
+ int used; /* nr bytes in use */
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+ drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
+} drmI830BatchBuffer;
+
+typedef struct {
+ char *buf; /* agp offset */
+ int sz; /* nr bytes in use */
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+ drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
+} drmI830CmdBuffer;
+
+typedef struct {
+ int *irq_seq;
+} drmI830IrqEmit;
+
+typedef struct {
+ int irq_seq;
+} drmI830IrqWait;
+
+typedef struct {
+ int param;
+ int *value;
+} drmI830GetParam;
+
+#define I830_PARAM_IRQ_ACTIVE 1
+#define I830_PARAM_ALLOW_BATCHBUFFER 2
+
+typedef struct {
+ int param;
+ int value;
+} drmI830SetParam;
+
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
+#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
+#define I830_SETPARAM_ALLOW_BATCHBUFFER 3
+
+
+/* A memory manager for regions of shared memory:
+ */
+#define I830_MEM_REGION_AGP 1
+
+typedef struct {
+ int region;
+ int alignment;
+ int size;
+ int *region_offset; /* offset from start of fb or agp */
+} drmI830MemAlloc;
+
+typedef struct {
+ int region;
+ int region_offset;
+} drmI830MemFree;
+
+typedef struct {
+ int region;
+ int size;
+ int start;
+} drmI830MemInitHeap;
+
+
+#endif /* _I830_DRM_H_ */
diff --git a/driver/xf86-video-i810/src/i830_cursor.c b/driver/xf86-video-i810/src/i830_cursor.c
new file mode 100644
index 000000000..241141920
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_cursor.c
@@ -0,0 +1,437 @@
+
+/**************************************************************************
+
+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@xfree86.org>
+ *
+ * Updated for Dual Head capabilities:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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);
+#ifdef ARGB_CURSOR
+static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
+static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
+#endif
+
+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) || IS_I915G(pI830) || IS_I945G(pI830)) {
+ temp = INREG(CURSOR_A_CONTROL);
+ temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
+ MCURSOR_PIPE_SELECT);
+ temp |= CURSOR_MODE_DISABLE;
+ temp |= (pI830->pipe << 28);
+ /* Need to set control, then address. */
+ OUTREG(CURSOR_A_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ temp &= ~MCURSOR_PIPE_SELECT;
+ temp |= (!pI830->pipe << 28);
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_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. */
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
+ else
+ 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;
+
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = FALSE;
+
+ if (pI830->CursorMemARGB->Start) {
+ /* Use ARGB if we were able to allocate the 16kb needed */
+ infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
+ infoPtr->LoadCursorARGB = I830LoadCursorARGB;
+ }
+#endif
+
+ 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");
+
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = FALSE;
+#endif
+
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64 / 4; x++) {
+ *pcurs++ = *src++;
+ }
+ }
+}
+
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830UseHWCursorARGB\n");
+ if (pScrn->bitsPerPixel == 8)
+ return FALSE;
+
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical)
+ return FALSE;
+
+ if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start);
+ CARD32 *image = (CARD32 *)pCurs->bits->argb;
+ int x, y, w, h;
+
+ DPRINTF(PFX, "I830LoadCursorARGB\n");
+
+ if (!image)
+ return; /* XXX can't happen */
+
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = TRUE;
+#endif
+
+ w = pCurs->bits->width;
+ h = pCurs->bits->height;
+
+ for(y = 0; y < h; y++) {
+ for(x = 0; x < w; x++)
+ *dst++ = *image++;
+ for(; x < 64; x++)
+ *dst++ = 0;
+ }
+
+ for(; y < 64; y++) {
+ for(x = 0; x < 64; x++)
+ *dst++ = 0;
+ }
+}
+#endif
+
+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->Clone)
+ OUTREG(CURSOR_B_POSITION, temp);
+
+ if (pI830->cursorOn) {
+ if (hide)
+ pI830->CursorInfoRec->HideCursor(pScrn);
+ else if (show)
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ pI830->cursorOn = TRUE;
+ }
+
+ /* have to upload the base for the new position */
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
+ }
+}
+
+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);
+ DPRINTF(PFX,
+ "Value of CursorMemARGB->Physical is %x, "
+ " Value of CursorMemARGB->Start is %x ",
+ pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
+
+ pI830->cursorOn = TRUE;
+ if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+ temp = INREG(CURSOR_A_CONTROL);
+ temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+ if (pI830->CursorIsARGB)
+ temp |= CURSOR_MODE_64_ARGB_AX;
+ else
+ temp |= CURSOR_MODE_64_4C_AX;
+ temp |= (pI830->pipe << 28); /* Connect to correct pipe */
+ /* Need to set mode, then address. */
+ OUTREG(CURSOR_A_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ temp &= ~MCURSOR_PIPE_SELECT;
+ temp |= (!pI830->pipe << 28);
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
+ } else {
+ temp = INREG(CURSOR_CONTROL);
+ temp &= ~(CURSOR_FORMAT_MASK);
+ temp |= CURSOR_ENABLE;
+ if (pI830->CursorIsARGB)
+ temp |= CURSOR_FORMAT_ARGB;
+ else
+ temp |= CURSOR_FORMAT_3C;
+ OUTREG(CURSOR_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
+ else
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
+ }
+}
+
+static void
+I830HideCursor(ScrnInfoPtr pScrn)
+{
+ CARD32 temp;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830HideCursor\n");
+
+ pI830->cursorOn = FALSE;
+ if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(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. */
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_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);
+
+#ifdef ARGB_CURSOR
+ /* Don't recolour cursors set with SetCursorARGB. */
+ if (pI830->CursorIsARGB)
+ return;
+#endif
+
+ 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);
+ if (pI830->Clone) {
+ OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff);
+ }
+}
diff --git a/driver/xf86-video-i810/src/i830_dga.c b/driver/xf86-video-i810/src/i830_dga.c
new file mode 100644
index 000000000..e1991db42
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_dga.c
@@ -0,0 +1,302 @@
+/*
+ * 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.2 2002/11/05 02:01:18 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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);
+ if (pI830->init == 0)
+ *size = pI830->FrontBuffer.Size;
+ else {
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ *size = pI8301->FrontBuffer2.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/driver/xf86-video-i810/src/i830_dri.c b/driver/xf86-video-i810/src/i830_dri.c
new file mode 100644
index 000000000..ade0c0ce9
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_dri.c
@@ -0,0 +1,1296 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v 1.15 2003/06/18 13:14:17 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@xfree86.org>
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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"
+
+static char I830KernelDriverName[] = "i915";
+static char I830ClientDriverName[] = "i915";
+
+static Bool I830InitVisualConfigs(ScreenPtr pScreen);
+static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void I830DestroyContext(ScreenPtr pScreen, drm_context_t 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 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.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->backPitch;
+ info.back_pitch = pI830->backPitch;
+ info.depth_pitch = pI830->backPitch;
+ 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
+I830ResumeDma(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ drmI830Init info;
+
+ memset(&info, 0, sizeof(drmI830Init));
+ info.func = I830_RESUME_DMA;
+
+ if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
+ &info, sizeof(drmI830Init))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Resume 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].alphaSize = 0;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0;
+ if (accum) {
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ if (depth)
+ pConfigs[i].depthSize = 16;
+ else
+ pConfigs[i].depthSize = 0;
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (stencil || accum)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = GLX_NONE_EXT;
+ 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 = 8;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+ pConfigs[i].alphaMask = 0xFF000000;
+ 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;
+ }
+ if (db) {
+ pConfigs[i].doubleBuffer = TRUE;
+ } else {
+ pConfigs[i].doubleBuffer = FALSE;
+ }
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 32;
+ 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 = GLX_NONE_EXT;
+ 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("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 != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] %s failed because of a version mismatch.\n"
+ "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ "I830DRIScreenInit", major, minor, patch,
+ DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (!pDRIInfo) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRICreateInfoRec failed. Disabling DRI.\n");
+ return FALSE;
+ }
+
+ pI830->pDRIInfo = pDRIInfo;
+ pI830->LockHeld = 0;
+
+ pDRIInfo->drmDriverName = I830KernelDriverName;
+ pDRIInfo->clientDriverName = I830ClientDriverName;
+ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+ pDRIInfo->busIdString = DRICreatePCIBusID(pI830->PciInfo);
+ } else {
+ 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(drmI830Sarea) > 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->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 i915 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 i915 DRM version */
+ version = drmGetVersion(pI830->drmSubFD);
+ if (version) {
+ if (version->version_major != 1 || version->version_minor < 1) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] %s failed because of a version mismatch.\n"
+ "[dri] i915 kernel module version is %d.%d.%d but version 1.1 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;
+ }
+ if (strncmp(version->name, I830KernelDriverName, strlen(I830KernelDriverName))) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "i830 Kernel module detected, Use the i915 Kernel module instead, aborting DRI init.\n");
+ 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;
+
+ DPRINTF(PFX, "I830DRIDoMappings\n");
+ pI830DRI->regsSize = I830_REG_SIZE;
+ if (drmAddMap(pI830->drmSubFD, (drm_handle_t)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%08x\n",
+ pI830DRI->regs);
+
+ /*
+ * The tile setup is now initiated from I830BIOSScreenInit().
+ */
+
+ pI830->backPitch = pScrn->displayWidth;
+
+ pI830DRI->backbufferSize = pI830->BackBuffer.Size;
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)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%08x\n",
+ pI830DRI->backbuffer);
+
+ pI830DRI->depthbufferSize = pI830->DepthBuffer.Size;
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)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%08x\n",
+ pI830DRI->depthbuffer);
+
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)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%08x\n",
+ pI830->ring_map);
+
+ pI830DRI->textureSize = pI830->TexMem.Size;
+ pI830DRI->logTextureGranularity = pI830->TexGranularity;
+
+ if (drmAddMap(pI830->drmSubFD,
+ (drm_handle_t)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%08x\n",
+ pI830DRI->textures);
+
+ if (!I830InitDma(pScrn)) {
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+
+ 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 */
+ {
+ pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->funcnum);
+
+ if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] failure adding irq handler\n");
+ pI830DRI->irq = 0;
+ DRICloseScreen(pScreen);
+ return FALSE;
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n",
+ pI830DRI->irq);
+ }
+
+ /* Start up the simple memory manager for agp space */
+ {
+ drmI830MemInitHeap drmHeap;
+ drmHeap.region = I830_MEM_REGION_AGP;
+ drmHeap.start = 0;
+ drmHeap.size = pI830DRI->textureSize;
+
+ if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP,
+ &drmHeap, sizeof(drmHeap))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[drm] Failed to initialized agp heap manager\n");
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Initialized kernel agp heap manager, %d\n",
+ pI830DRI->textureSize);
+
+ I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY,
+ pI830->TexGranularity);
+ }
+ }
+
+
+
+ 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->backPitch;
+
+ pI830DRI->bitsPerPixel = pScrn->bitsPerPixel;
+
+ pI830DRI->textureOffset = pI830->TexMem.Start;
+
+ pI830DRI->backOffset = pI830->BackBuffer.Start;
+ pI830DRI->depthOffset = pI830->DepthBuffer.Start;
+
+ pI830DRI->backPitch = pI830->backPitch;
+ pI830DRI->depthPitch = pI830->backPitch;
+ 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;
+}
+
+Bool
+I830DRIResume(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+
+ DPRINTF(PFX, "I830DRIResume\n");
+
+ I830ResumeDma(pScrn);
+
+ {
+ pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->busnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->devnum,
+ ((pciConfigPtr) pI830->
+ PciInfo->thisCard)->funcnum);
+
+ if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] failure adding irq handler\n");
+ pI830DRI->irq = 0;
+ return FALSE;
+ }
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "[drm] dma control initialized, using IRQ %d\n",
+ pI830DRI->irq);
+ }
+
+ return FALSE;
+}
+
+void
+I830DRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
+
+ DPRINTF(PFX, "I830DRICloseScreen\n");
+
+ if (pI830DRI->irq) {
+ drmCtlUninstHandler(pI830->drmSubFD);
+ pI830DRI->irq = 0;
+ }
+
+ 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,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+I830DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+I830DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ drmI830Sarea *sPriv = (drmI830Sarea *) 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 >= 1) {
+ 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");
+
+ if (!pScrn->vtSema)
+ return;
+ 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;
+}
+
+/* Initialize the first context */
+void
+I830EmitInvarientState(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 ctx_addr;
+
+
+ ctx_addr = pI830->ContextMem.Start;
+ /* Align to a 2k boundry */
+ ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
+
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_SET_CONTEXT);
+ OUT_RING(ctx_addr |
+ CTXT_NO_RESTORE |
+ CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
+ ADVANCE_LP_RING();
+ }
+}
+
+/* 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);
+ drmI830Sarea *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);
+ drmI830Sarea *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)
+{
+ drmI830Sarea *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);
+ drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+
+ /* Try flipping back to the front page if necessary */
+ if (sPriv->pf_current_page == 1)
+ drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP);
+
+ /* 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/driver/xf86-video-i810/src/i830_dri.h b/driver/xf86-video-i810/src/i830_dri.h
new file mode 100644
index 000000000..5ac99e5e8
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_dri.h
@@ -0,0 +1,67 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.6 2003/09/28 20:15:59 alanh 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 4
+#define I830_PATCHLEVEL 1
+
+#define I830_REG_SIZE 0x80000
+
+typedef struct _I830DRIRec {
+ drm_handle_t regs;
+ drmSize regsSize;
+
+ drmSize backbufferSize;
+ drm_handle_t backbuffer;
+
+ drmSize depthbufferSize;
+ drm_handle_t depthbuffer;
+
+ drm_handle_t textures;
+ int textureSize;
+
+ drm_handle_t agp_buffers;
+ drmSize agp_buf_size;
+
+ int deviceID;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+ int bitsPerPixel;
+
+ int fbOffset;
+ int fbStride;
+
+ int backOffset;
+ int backPitch;
+
+ int depthOffset;
+ int depthPitch;
+
+ int logTextureGranularity;
+ int textureOffset;
+
+ 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;
+
+
+#endif
diff --git a/driver/xf86-video-i810/src/i830_driver.c b/driver/xf86-video-i810/src/i830_driver.c
new file mode 100644
index 000000000..b281affd5
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_driver.c
@@ -0,0 +1,5857 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.50 2004/02/20 00:06:00 alanh 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@xfree86.org>
+ * Alan Hourihane <alanh@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.
+ *
+ *
+ * 01/2004 Alan Hourihane
+ * - Add Intel(R) 915G support.
+ * - Add Dual Head and Clone capabilities.
+ * - Add lid status checking
+ * - Fix Xvideo with high-res LFP's
+ * - Add ARGB HW cursor support
+ *
+ * 30/2005 Alan Hourihane
+ * - Add Intel(R) 945G support.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 "shadowfb.h"
+
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/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"},
+ {PCI_CHIP_I915_G, "915G"},
+ {PCI_CHIP_E7221_G, "E7221 (i915)"},
+ {PCI_CHIP_I915_GM, "915GM"},
+ {PCI_CHIP_I945_G, "945G"},
+ {-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},
+ {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA},
+ {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, RES_SHARED_VGA},
+ {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA},
+ {PCI_CHIP_I945_G, PCI_CHIP_I945_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_VBE_RESTORE,
+ OPTION_DISPLAY_INFO,
+ OPTION_DEVICE_PRESENCE,
+ OPTION_MONITOR_LAYOUT,
+ OPTION_CLONE,
+ OPTION_CLONE_REFRESH,
+ OPTION_CHECKDEVICES,
+ OPTION_FIXEDPIPE,
+ OPTION_SHADOW_FB,
+ OPTION_ROTATE
+} 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_VBE_RESTORE, "VBERestore", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_DISPLAY_INFO,"DisplayInfo", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0}, FALSE},
+ {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE},
+ {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE},
+ {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {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 CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
+static Bool SetPipeAccess(ScrnInfoPtr pScrn);
+static Bool IsPrimary(ScrnInfoPtr pScrn);
+
+extern int I830EntityIndex;
+
+
+#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.
+ * 100 and 120Hz aren't really supported, they work but only get close
+ * to the requested refresh, and really not close enough.
+ * I've seen 100Hz come out at 104Hz, and 120Hz come out at 128Hz */
+const int i830refreshes[] = {
+ 43, 56, 60, 70, 72, 75, 85 /* 100, 120 */
+};
+static const int nrefreshes = sizeof(i830refreshes) / sizeof(i830refreshes[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;
+ }
+}
+
+static int
+GetToggleList(ScrnInfoPtr pScrn, int toggle)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetToggleList\n");
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x500;
+
+ pVbe->pInt10->bx |= toggle;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Toggle (%d) 0x%x\n", toggle, pVbe->pInt10->cx);
+ return pVbe->pInt10->cx & 0xffff;
+ }
+
+ return 0;
+}
+
+static int
+BitToRefresh(int bits)
+{
+ int i;
+
+ for (i = 0; i < nrefreshes; i++)
+ if (bits & (1 << i))
+ return i830refreshes[i];
+ return 0;
+}
+
+static int
+GetRefreshRate(ScrnInfoPtr pScrn, int mode, 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;
+}
+
+struct panelid {
+ short hsize;
+ short vsize;
+ short fptype;
+ char redbpp;
+ char greenbpp;
+ char bluebpp;
+ char reservedbpp;
+ int rsvdoffscrnmemsize;
+ int rsvdoffscrnmemptr;
+ char reserved[14];
+};
+
+static void
+I830InterpretPanelID(int scrnIndex, unsigned char *tmp)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ struct panelid *block = (struct panelid *)tmp;
+
+#define PANEL_DEFAULT_HZ 60
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "PanelID returned panel resolution : %dx%d\n",
+ block->hsize, block->vsize);
+
+ /* If we get bogus values from this, don't accept it */
+ if (block->hsize == 0 || block->vsize == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Bad Panel resolution - ignoring panelID\n");
+
+ return;
+ }
+
+ /* If we have monitor timings then don't overwrite them */
+ if (pScrn->monitor->nHsync > 0 &&
+ pScrn->monitor->nVrefresh > 0)
+ return;
+
+ /* With panels, we're always assuming a refresh of 60Hz */
+
+ pScrn->monitor->nHsync = 1;
+ pScrn->monitor->nVrefresh = 1;
+
+ /* Give a little tolerance for the selected panel */
+ pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000;
+ pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000;
+ pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ;
+ pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ;
+}
+
+/* This should probably go into the VBE layer */
+static unsigned char *
+vbeReadPanelID(vbeInfoPtr pVbe)
+{
+ int RealOff = pVbe->real_mode_base;
+ pointer page = pVbe->memory;
+ unsigned char *tmp = NULL;
+ int screen = pVbe->pInt10->scrnIndex;
+
+ pVbe->pInt10->ax = 0x4F11;
+ pVbe->pInt10->bx = 0x01;
+ pVbe->pInt10->cx = 0;
+ pVbe->pInt10->dx = 0;
+ pVbe->pInt10->es = SEG_ADDR(RealOff);
+ pVbe->pInt10->di = SEG_OFF(RealOff);
+ pVbe->pInt10->num = 0x10;
+
+ xf86ExecX86int10(pVbe->pInt10);
+
+ if ((pVbe->pInt10->ax & 0xff) != 0x4f) {
+ xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n");
+ goto error;
+ }
+ switch (pVbe->pInt10->ax & 0xff00) {
+ case 0x0:
+ xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n");
+ tmp = (unsigned char *)xnfalloc(32);
+ memcpy(tmp,page,32);
+ break;
+ case 0x100:
+ xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n");
+ break;
+ default:
+ xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n",
+ pVbe->pInt10->ax & 0xff00);
+ break;
+ }
+
+ error:
+ return tmp;
+}
+
+static void
+vbeDoPanelID(vbeInfoPtr pVbe)
+{
+ unsigned char *PanelID_data;
+
+ if (!pVbe) return;
+
+ PanelID_data = vbeReadPanelID(pVbe);
+
+ if (!PanelID_data)
+ return;
+
+ I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data);
+}
+
+int
+I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh)
+{
+ int i;
+
+ for (i = nrefreshes - 1; i >= 0; i--) {
+ /*
+ * Look for the highest value that the requested (refresh + 2) is
+ * greater than or equal to.
+ */
+ if (i830refreshes[i] <= (refresh + 2))
+ break;
+ }
+ /* i can be 0 if the requested refresh was higher than the max. */
+ if (i == 0) {
+ if (refresh >= i830refreshes[nrefreshes - 1])
+ i = nrefreshes - 1;
+ }
+
+ return i;
+}
+
+static int
+SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+ int i = I830GetBestRefresh(pScrn, refresh);
+
+ DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
+
+ DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
+ i830refreshes[i], mode & 0xff);
+
+ /* 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;
+
+ pVbe->pInt10->cx = 1 << i;
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
+ return i830refreshes[i];
+ else
+ return 0;
+}
+
+static Bool
+SetPowerStatus(ScrnInfoPtr pScrn, int mode)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x0800 | mode;
+ pVbe->pInt10->cx = 0x0000;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+ return TRUE;
+
+ return FALSE;
+}
+
+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 FALSE;
+
+ 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 {
+ if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */
+ return PIPE_CRT;
+ else
+ return -1;
+ }
+}
+
+static int
+GetBIOSPipe(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ int pipe;
+
+ DPRINTF(PFX, "GetBIOSPipe:\n");
+
+ /* single pipe machines should always return Pipe A */
+ if (pI830->availablePipes == 1) return 0;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f1c;
+ pVbe->pInt10->bx = 0x100;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
+ if (pI830->newPipeSwitch) {
+ pipe = ((pVbe->pInt10->bx & 0x0001));
+ } else {
+ pipe = ((pVbe->pInt10->cx & 0x0100) >> 8);
+ }
+ return pipe;
+ }
+
+ /* failed, assume pipe A */
+ return 0;
+}
+
+static Bool
+SetBIOSPipe(ScrnInfoPtr pScrn, int pipe)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+
+ DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe);
+
+ /* single pipe machines should always return TRUE */
+ if (pI830->availablePipes == 1) return TRUE;
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f1c;
+ if (pI830->newPipeSwitch) {
+ pVbe->pInt10->bx = pipe;
+ pVbe->pInt10->cx = 0;
+ } else {
+ pVbe->pInt10->bx = 0x0;
+ pVbe->pInt10->cx = pipe << 8;
+ }
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+SetPipeAccess(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* Don't try messing with the pipe, unless we're dual head */
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) {
+ if (!SetBIOSPipe(pScrn, pI830->pipe))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830Set640x480(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int m = 0x30; /* 640x480 8bpp */
+
+ switch (pScrn->depth) {
+ case 15:
+ m = 0x40;
+ break;
+ case 16:
+ m = 0x41;
+ break;
+ case 24:
+ m = 0x50;
+ break;
+ }
+ m |= (1 << 15) | (1 << 14);
+ return VBESetVBEMode(pI830->pVbe, m, NULL);
+}
+
+/* This is needed for SetDisplayDevices to work correctly on I915G.
+ * Enable for all chipsets now as it has no bad side effects, apart
+ * from slightly longer startup time.
+ */
+#define I915G_WORKAROUND
+
+static Bool
+SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ CARD32 temp;
+ int singlepipe = 0;
+#ifdef I915G_WORKAROUND
+ int getmode1;
+ Bool setmode = FALSE;
+#endif
+
+ DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
+
+ if (!pI830->specifiedMonitor)
+ return TRUE;
+
+#ifdef I915G_WORKAROUND
+ if (pI830->preinit)
+ setmode = TRUE;
+ if (pI830->leaving)
+ setmode = FALSE;
+ if (pI830->closing)
+ setmode = FALSE;
+
+ if (setmode) {
+ VBEGetVBEMode(pVbe, &getmode1);
+ I830Set640x480(pScrn);
+ }
+#endif
+
+ 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)) {
+#ifdef I915G_WORKAROUND
+ if (setmode) {
+ VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
+ }
+#endif
+ pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
+ pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
+
+ return TRUE;
+ }
+
+#ifdef I915G_WORKAROUND
+ if (setmode)
+ VBESetVBEMode(pI830->pVbe, getmode1 | 1<<15, NULL);
+#endif
+
+ if (devices & 0xff) {
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x1;
+ pVbe->pInt10->cx = devices & 0xff;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set display devices to 0x%x.\n",devices & 0xff);
+ singlepipe = devices & 0xff00; /* set alternate */
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set display devices to 0x%x.\n",devices & 0xff);
+ singlepipe = devices;
+ }
+ } else
+ singlepipe = devices;
+
+ if (singlepipe == devices && devices & 0xff00) {
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f64;
+ pVbe->pInt10->bx = 0x1;
+ pVbe->pInt10->cx = devices & 0xff00;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set display devices to 0x%x.\n",devices & 0xff00);
+ singlepipe = devices & 0xff; /* set alternate */
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set display devices to 0x%x.\n",devices & 0xff00);
+ singlepipe = devices;
+ }
+ }
+
+ /* LVDS doesn't exist on these */
+ if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))
+ singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8));
+
+ if (pI830->availablePipes == 1)
+ singlepipe &= 0xFF;
+
+ /* Disable LVDS */
+ if (singlepipe & PIPE_LFP) {
+ /* LFP on PipeA is unlikely! */
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) & ~1<<30) | 0x80000300);
+ /* Enable LVDS */
+ OUTREG(0x61200, INREG(0x61200) | 0x80000000);
+ OUTREG(0x61204, INREG(0x61204) | 0x00000001);
+ while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling LVDS directly. Pipe A.\n");
+ } else
+ if (singlepipe & (PIPE_LFP << 8)) {
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) | 1<<30) | 0x80000300);
+ /* Enable LVDS */
+ OUTREG(0x61200, INREG(0x61200) | 0x80000000);
+ OUTREG(0x61204, INREG(0x61204) | 0x00000001);
+ while (!(INREG(0x61200) & 0x80000000) && !(INREG(0x61204) & 1));
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling LVDS directly. Pipe B.\n");
+ }
+ else if (!(IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830))) {
+ if (!(devices & (PIPE_LFP | PIPE_LFP<<8))) {
+ OUTREG(0x61200, INREG(0x61200) & ~0x80000000);
+ OUTREG(0x61204, INREG(0x61204) & ~0x00000001);
+ while ((INREG(0x61200) & 0x80000000) || (INREG(0x61204) & 1));
+ /* Fix up LVDS */
+ OUTREG(LVDS, (INREG(LVDS) | 1<<30) & ~0x80000300);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling LVDS directly.\n");
+ }
+ }
+
+ /* Now try to program the registers directly if the BIOS failed. */
+ temp = INREG(ADPA);
+ temp &= ~(ADPA_DAC_ENABLE | ADPA_PIPE_SELECT_MASK);
+ temp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
+ /* Turn on ADPA */
+ if (singlepipe & PIPE_CRT) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling ADPA directly. Pipe A.\n");
+ temp |= ADPA_DAC_ENABLE | ADPA_PIPE_A_SELECT;
+ OUTREG(ADPA, temp);
+ } else
+ if (singlepipe & (PIPE_CRT << 8)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Enabling ADPA directly. Pipe B.\n");
+ temp |= ADPA_DAC_ENABLE | ADPA_PIPE_B_SELECT;
+ OUTREG(ADPA, temp);
+ }
+ else {
+ if (!(devices & (PIPE_CRT | PIPE_CRT<<8))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling ADPA directly.\n");
+ temp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
+ OUTREG(ADPA, temp);
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,"Writing config directly to SWF0.\n");
+ temp = INREG(SWF0);
+ OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
+
+ if (GetDisplayDevices(pScrn) != devices) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n",
+ GetDisplayDevices(pScrn), devices);
+ return FALSE;
+ }
+
+ pI830->pipeEnabled[0] = (devices & 0xff) ? TRUE : FALSE;
+ pI830->pipeEnabled[1] = (devices & 0xff00) ? TRUE : FALSE;
+
+ return TRUE;
+}
+
+static Bool
+GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version)
+{
+ vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+
+ DPRINTF(PFX, "GetBIOSVersion\n");
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0x5f01;
+
+ xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+ if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) {
+ *version = pVbe->pInt10->bx;
+ return TRUE;
+ }
+
+ *version = 0;
+ return FALSE;
+}
+
+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;
+}
+
+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)",
+ "CRT2 (second CRT)",
+ "TV2 (second TV)",
+ "DFP2 (second digital flat panel)",
+ "LFP2 (second local flat panel)",
+ NULL
+};
+
+static const char *
+DeviceToString(int device)
+{
+ static int savedDevice = -1;
+ 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->operatingDevices;
+ 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->operatingDevices >> 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;
+
+ /* This seems to lockup some Dell BIOS'. So it's on option to turn on */
+ if (pI830->displayInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Broken BIOSes cause the system to hang here.\n"
+ "\t If you encounter this problem please add \n"
+ "\t\t Option \"DisplayInfo\" \"FALSE\"\n"
+ "\t to the Device section of your XF86Config file.\n");
+ 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);
+ }
+ }
+ }
+
+ /* Check for active devices connected to each display pipe. */
+ for (n = 0; n < pI830->availablePipes; n++) {
+ pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
+ if (pipe)
+ pI830->pipeEnabled[n] = TRUE;
+ else
+ pI830->pipeEnabled[n] = FALSE;
+ }
+
+ GetPipeSizes(pScrn);
+
+ return TRUE;
+}
+
+static int
+I830DetectMemory(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ PCITAG bridge;
+ CARD16 gmch_ctrl;
+ int memsize = 0;
+ int range;
+
+ bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
+
+ /* We need to reduce the stolen size, by the GTT and the popup.
+ * The GTT varying according the the FbMapSize and the popup is 4KB */
+ range = (pI830->FbMapSize / (1024*1024)) + 4;
+
+ if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I855_GMCH_GMS_STOLEN_1M:
+ memsize = MB(1) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_4M:
+ memsize = MB(4) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_8M:
+ memsize = MB(8) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_16M:
+ memsize = MB(16) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_32M:
+ memsize = MB(32) - KB(range);
+ break;
+ case I915G_GMCH_GMS_STOLEN_48M:
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+ memsize = MB(48) - KB(range);
+ break;
+ case I915G_GMCH_GMS_STOLEN_64M:
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+ memsize = MB(64) - KB(range);
+ break;
+ }
+ } else {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I830_GMCH_GMS_STOLEN_512:
+ memsize = KB(512) - KB(range);
+ break;
+ case I830_GMCH_GMS_STOLEN_1024:
+ memsize = MB(1) - KB(range);
+ break;
+ case I830_GMCH_GMS_STOLEN_8192:
+ memsize = MB(8) - KB(range);
+ 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);
+ long 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;
+
+ if (IsPrimary(pScrn))
+ 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;
+}
+
+/*
+ * TweakMemorySize() tweaks the BIOS image to set the correct size.
+ * Original implementation by Christian Zietz in a stand-alone tool.
+ */
+static CARD32
+TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit)
+{
+#define SIZE 0x10000
+#define _855_IDOFFSET (-23)
+#define _845_IDOFFSET (-19)
+
+ const char *MAGICstring = "Total time for VGA POST:";
+ const int len = strlen(MAGICstring);
+ I830Ptr pI830 = I830PTR(pScrn);
+ volatile char *position;
+ char *biosAddr;
+ CARD32 oldsize;
+ CARD32 oldpermission;
+ CARD32 ret = 0;
+ int i,j = 0;
+ int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL
+ : _855_DRAM_RW_CONTROL;
+
+ PCITAG tag =pciTag(0,0,0);
+
+ if(!pI830->PciInfo
+ || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830)))
+ return 0;
+
+ if (!pI830->pVbe)
+ return 0;
+
+ biosAddr = xf86int10Addr(pI830->pVbe->pInt10,
+ pI830->pVbe->pInt10->BIOSseg << 4);
+
+ if (!pI830->BIOSMemSizeLoc) {
+ if (!preinit)
+ return 0;
+
+ /* Search for MAGIC string */
+ for (i = 0; i < SIZE; i++) {
+ if (biosAddr[i] == MAGICstring[j]) {
+ if (++j == len)
+ break;
+ } else {
+ i -= j;
+ j = 0;
+ }
+ }
+ if (j < len) return 0;
+
+ pI830->BIOSMemSizeLoc = (i - j + 1 + (IS_845G(pI830)
+ ? _845_IDOFFSET : _855_IDOFFSET));
+ }
+
+ position = biosAddr + pI830->BIOSMemSizeLoc;
+ oldsize = *(CARD32 *)position;
+
+ ret = oldsize - 0x21000;
+
+ /* verify that register really contains current size */
+ if (preinit && ((ret >> 16) != pI830->vbeInfo->TotalMemory))
+ return 0;
+
+ oldpermission = pciReadLong(tag, reg);
+ pciWriteLong(tag, reg, DRAM_WRITE | (oldpermission & 0xffff));
+
+ *(CARD32 *)position = newsize + 0x21000;
+
+ if (preinit) {
+ /* reinitialize VBE for new size */
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ vbeFree(pI830->pVbe);
+ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+ pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+
+ /* verify that change was successful */
+ if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){
+ ret = 0;
+ *(CARD32 *)position = oldsize;
+ } else {
+ pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Tweak BIOS image to %d kB VideoRAM\n",
+ (int)(pI830->BIOSMemorySize / 1024));
+ }
+ }
+
+ pciWriteLong(tag, reg, oldpermission);
+
+ return ret;
+}
+
+static void
+RestoreBIOSMemSize(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 swf1;
+
+ DPRINTF(PFX, "RestoreBIOSMemSize\n");
+
+ if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE))
+ return;
+
+ 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);
+ unsigned long 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) {
+ unsigned long 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%08lx\n", swf1);
+ swf1 &= ~0x0f;
+ swf1 |= (newSWF1 & 0x0f);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1);
+ OUTREG(SWF1, swf1);
+ if (!mapped)
+ I830UnmapMMIO(pScrn);
+ }
+}
+
+static void
+I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ I830Ptr pI830;
+ int i,j, index;
+ unsigned char r, g, b;
+ CARD32 val, temp;
+ int palreg;
+ int dspreg, dspbase;
+
+ DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
+ pI830 = I830PTR(pScrn);
+
+ if (pI830->pipe == 0) {
+ palreg = PALETTE_A;
+ dspreg = DSPACNTR;
+ dspbase = DSPABASE;
+ } else {
+ palreg = PALETTE_B;
+ dspreg = DSPBCNTR;
+ dspbase = DSPBBASE;
+ }
+
+ /* To ensure gamma is enabled we need to turn off and on the plane */
+ temp = INREG(dspreg);
+ OUTREG(dspreg, temp & ~(1<<31));
+ OUTREG(dspbase, INREG(dspbase));
+ OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE);
+ OUTREG(dspbase, INREG(dspbase));
+
+ /* It seems that an initial read is needed. */
+ temp = INREG(palreg);
+
+ switch(pScrn->depth) {
+ case 15:
+ 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;
+ for (j = 0; j < 8; j++) {
+ OUTREG(palreg + index * 32 + (j * 4), val);
+ }
+ }
+ break;
+ case 16:
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ r = colors[index / 2].red;
+ g = colors[index].green;
+ b = colors[index / 2].blue;
+
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(palreg + index * 16, val);
+ OUTREG(palreg + index * 16 + 4, val);
+ OUTREG(palreg + index * 16 + 8, val);
+ OUTREG(palreg + index * 16 + 12, val);
+
+ if (index <= 31) {
+ r = colors[index].red;
+ g = colors[(index * 2) + 1].green;
+ b = colors[index].blue;
+
+ val = (r << 16) | (g << 8) | b;
+ OUTREG(palreg + index * 32, val);
+ OUTREG(palreg + index * 32 + 4, val);
+ OUTREG(palreg + index * 32 + 8, val);
+ OUTREG(palreg + index * 32 + 12, val);
+ }
+ }
+ break;
+ default:
+ 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(palreg + index * 4, val);
+ }
+ break;
+ }
+}
+
+static int
+I830UseDDC(ScrnInfoPtr pScrn)
+{
+ xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
+ struct detailed_monitor_section* detMon;
+ struct monitor_ranges *mon_range = NULL;
+ int i;
+
+ if (!DDC) return 0;
+
+ /* Now change the hsync/vrefresh values of the current monitor to
+ * match those of DDC */
+ for (i = 0; i < 4; i++) {
+ detMon = &DDC->det_mon[i];
+ if(detMon->type == DS_RANGES)
+ mon_range = &detMon->section.ranges;
+ }
+
+ if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 ||
+ mon_range->min_v == 0 || mon_range->max_v == 0)
+ return 0; /* bad ddc */
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using detected DDC timings\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tHorizSync %d-%d\n",
+ mon_range->min_h, mon_range->max_h);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tVertRefresh %d-%d\n",
+ mon_range->min_v, mon_range->max_v);
+#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE
+ if (pScrn->monitor->nHsync > 0) {
+ for (i = 0; i < pScrn->monitor->nHsync; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h >
+ pScrn->monitor->hsync[i].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h <
+ pScrn->monitor->hsync[i].hi) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "config file hsync range %g-%gkHz not within DDC "
+ "hsync range %d-%dkHz\n",
+ pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi,
+ mon_range->min_h, mon_range->max_h);
+ }
+ pScrn->monitor->hsync[i].lo = mon_range->min_h;
+ pScrn->monitor->hsync[i].hi = mon_range->max_h;
+ }
+ }
+
+ if (pScrn->monitor->nVrefresh > 0) {
+ for (i=0; i<pScrn->monitor->nVrefresh; i++) {
+ if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v >
+ pScrn->monitor->vrefresh[i].lo ||
+ (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v <
+ pScrn->monitor->vrefresh[i].hi) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "config file vrefresh range %g-%gHz not within DDC "
+ "vrefresh range %d-%dHz\n",
+ pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi,
+ mon_range->min_v, mon_range->max_v);
+ }
+ pScrn->monitor->vrefresh[i].lo = mon_range->min_v;
+ pScrn->monitor->vrefresh[i].hi = mon_range->max_v;
+ }
+ }
+
+ return mon_range->max_clock;
+}
+
+static void
+PreInitCleanup(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (IsPrimary(pScrn))
+ pI830->entityPrivate->pScrn_1 = NULL;
+ if (IsPrimary(pScrn) && pI830->LpRing) {
+ xfree(pI830->LpRing);
+ pI830->LpRing = NULL;
+ }
+ if (IsPrimary(pScrn) && pI830->CursorMem) {
+ xfree(pI830->CursorMem);
+ pI830->CursorMem = NULL;
+ }
+ if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
+ xfree(pI830->CursorMemARGB);
+ pI830->CursorMemARGB = NULL;
+ }
+ if (IsPrimary(pScrn) && pI830->OverlayMem) {
+ xfree(pI830->OverlayMem);
+ pI830->OverlayMem = NULL;
+ }
+ if (IsPrimary(pScrn) && pI830->overlayOn) {
+ xfree(pI830->overlayOn);
+ pI830->overlayOn = NULL;
+ }
+ if (!IsPrimary(pScrn) && pI830->entityPrivate)
+ pI830->entityPrivate->pScrn_2 = NULL;
+ RestoreBIOSMemSize(pScrn);
+ if (pI830->swfSaved) {
+ OUTREG(SWF0, pI830->saveSWF0);
+ OUTREG(SWF4, pI830->saveSWF4);
+ }
+ if (pI830->MMIOBase)
+ I830UnmapMMIO(pScrn);
+ I830BIOSFreeRec(pScrn);
+}
+
+static Bool
+IsPrimary(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (pI830->init == 0) return TRUE;
+ else return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ vgaHWPtr hwp;
+ I830Ptr pI830;
+ MessageType from;
+ rgb defaultWeight = { 0, 0, 0 };
+ EntityInfoPtr pEnt;
+ I830EntPtr pI830Ent = NULL;
+ int mem, memsize;
+ int flags24;
+ int defmon = 0;
+ int i, n;
+ int DDCclock = 0;
+ char *s;
+ DisplayModePtr p, pMon;
+ pointer pDDCModule = NULL, pVBEModule = NULL;
+ Bool enable;
+ const char *chipname;
+ unsigned int ver;
+ char v[5];
+
+ 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->SaveGeneration = -1;
+ 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);
+
+ /* Allocate an entity private if necessary */
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ pI830Ent = xf86GetEntityPrivate(pScrn->entityList[0],
+ I830EntityIndex)->ptr;
+ pI830->entityPrivate = pI830Ent;
+ } else
+ pI830->entityPrivate = NULL;
+
+ 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;
+
+ pI830->preinit = TRUE;
+
+ /* 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;
+ case PCI_CHIP_I915_G:
+ chipname = "915G";
+ break;
+ case PCI_CHIP_E7221_G:
+ chipname = "E7221 (i915)";
+ break;
+ case PCI_CHIP_I915_GM:
+ chipname = "915GM";
+ break;
+ case PCI_CHIP_I945_G:
+ chipname = "945G";
+ break;
+ default:
+ chipname = "unknown chipset";
+ break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Integrated Graphics Chipset: Intel(R) %s\n", chipname);
+
+ pI830->vbeInfo = VBEGetVBEInfo(pI830->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 (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000;
+ from = X_PROBED;
+ } 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 (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000;
+ from = X_PROBED;
+ } 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; /* 64MB - has this been tested ?? */
+ }
+ } else {
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ if (pI830->PciInfo->memBase[2] & 0x08000000)
+ pI830->FbMapSize = 0x8000000; /* 128MB aperture */
+ else
+ pI830->FbMapSize = 0x10000000; /* 256MB aperture */
+
+ if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
+ pI830->FbMapSize = 0x8000000; /* 128MB aperture */
+ } else
+ /* 128MB aperture for later chips */
+ pI830->FbMapSize = 0x8000000;
+ }
+
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (xf86IsPrimInitDone(pScrn->entityList[0])) {
+ pI830->init = 1;
+
+ if (!pI830Ent->pScrn_1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to setup second head due to primary head failure.\n");
+ return FALSE;
+ }
+
+ } else {
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ pI830->init = 0;
+ }
+ }
+
+ if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
+ pI830->availablePipes = 1;
+ else
+ if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(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" : "");
+
+ /*
+ * 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 (%ld 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. */
+ if (IsPrimary(pScrn)) {
+ mem = I830CheckAvailableMemory(pScrn);
+ pI830->StolenOnly = FALSE;
+ } else {
+ /* videoRam isn't used on the second head, but faked */
+ mem = pI830->entityPrivate->pScrn_1->videoRam;
+ pI830->StolenOnly = TRUE;
+ }
+
+ 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
+
+ pI830->fixedPipe = -1;
+ if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) &&
+ IsPrimary(pScrn)) {
+
+ if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0"))
+ pI830->fixedPipe = 0;
+ else if (strstr(s, "B") || strstr(s, "b") || strstr(s, "1"))
+ pI830->fixedPipe = 1;
+ }
+
+ pI830->MonType1 = PIPE_NONE;
+ pI830->MonType2 = PIPE_NONE;
+ pI830->specifiedMonitor = FALSE;
+
+ if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
+ IsPrimary(pScrn)) {
+ char *Mon1;
+ char *Mon2;
+ char *sub;
+
+ Mon1 = strtok(s, ",");
+ Mon2 = strtok(NULL, ",");
+
+ if (Mon1) {
+ sub = strtok(Mon1, "+");
+ do {
+ if (strcmp(sub, "NONE") == 0)
+ pI830->MonType1 |= PIPE_NONE;
+ else if (strcmp(sub, "CRT") == 0)
+ pI830->MonType1 |= PIPE_CRT;
+ else if (strcmp(sub, "TV") == 0)
+ pI830->MonType1 |= PIPE_TV;
+ else if (strcmp(sub, "DFP") == 0)
+ pI830->MonType1 |= PIPE_DFP;
+ else if (strcmp(sub, "LFP") == 0)
+ pI830->MonType1 |= PIPE_LFP;
+ else if (strcmp(sub, "CRT2") == 0)
+ pI830->MonType1 |= PIPE_CRT2;
+ else if (strcmp(sub, "TV2") == 0)
+ pI830->MonType1 |= PIPE_TV2;
+ else if (strcmp(sub, "DFP2") == 0)
+ pI830->MonType1 |= PIPE_DFP2;
+ else if (strcmp(sub, "LFP2") == 0)
+ pI830->MonType1 |= PIPE_LFP2;
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid Monitor type specified for Pipe A\n");
+
+ sub = strtok(NULL, "+");
+ } while (sub);
+ }
+
+ if (Mon2) {
+ sub = strtok(Mon2, "+");
+ do {
+ if (strcmp(sub, "NONE") == 0)
+ pI830->MonType2 |= PIPE_NONE;
+ else if (strcmp(sub, "CRT") == 0)
+ pI830->MonType2 |= PIPE_CRT;
+ else if (strcmp(sub, "TV") == 0)
+ pI830->MonType2 |= PIPE_TV;
+ else if (strcmp(sub, "DFP") == 0)
+ pI830->MonType2 |= PIPE_DFP;
+ else if (strcmp(sub, "LFP") == 0)
+ pI830->MonType2 |= PIPE_LFP;
+ else if (strcmp(sub, "CRT2") == 0)
+ pI830->MonType2 |= PIPE_CRT2;
+ else if (strcmp(sub, "TV2") == 0)
+ pI830->MonType2 |= PIPE_TV2;
+ else if (strcmp(sub, "DFP2") == 0)
+ pI830->MonType2 |= PIPE_DFP2;
+ else if (strcmp(sub, "LFP2") == 0)
+ pI830->MonType2 |= PIPE_LFP2;
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid Monitor type specified for Pipe B\n");
+
+ sub = strtok(NULL, "+");
+ } while (sub);
+ }
+
+ if (pI830->availablePipes == 1 && pI830->MonType2 != PIPE_NONE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Monitor 2 cannot be specified on single pipe devices\n");
+ return FALSE;
+ }
+
+ if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Monitor 1 and 2 cannot be type NONE\n");
+ return FALSE;
+ }
+
+ pI830->specifiedMonitor = TRUE;
+ }
+
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
+ if (pI830->availablePipes == 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't enable Clone Mode because this is a single pipe device\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ if (pI830->entityPrivate) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't enable Clone Mode because second head is configured\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n");
+ pI830->Clone = TRUE;
+ }
+
+ pI830->CloneRefresh = 60; /* default to 60Hz */
+ if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH,
+ &(pI830->CloneRefresh))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n",
+ pI830->CloneRefresh);
+ }
+
+ /* See above i830refreshes on why 120Hz is commented out */
+ if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 85 /* 120 */) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
+ if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
+ "defined for use in a DualHead or Clone setup.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 "
+ "cannot be type NONE in Dual or Clone setup.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ }
+
+ xf86GetOptValBool(pI830->Options, OPTION_SHADOW_FB, &pI830->shadowFB);
+ if (pI830->shadowFB) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n");
+ }
+
+ if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
+ if(!xf86NameCmp(s, "CW")) {
+ /* accel is disabled below for shadowFB */
+ pI830->shadowFB = TRUE;
+ pI830->rotate = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Rotating screen clockwise - acceleration disabled\n");
+ } else if(!xf86NameCmp(s, "CCW")) {
+ pI830->shadowFB = TRUE;
+ pI830->rotate = -1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen"
+ "counter clockwise - acceleration disabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
+ "value for Option \"Rotate\"\n", s);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Valid options are \"CW\" or \"CCW\"\n");
+ }
+ }
+
+ if (pI830->shadowFB && !pI830->noAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "HW acceleration not supported with \"shadowFB\".\n");
+ pI830->noAccel = TRUE;
+ }
+
+ /*
+ * Let's setup the mobile systems to check the lid status
+ */
+ if (IS_MOBILE(pI830)) {
+ pI830->checkDevices = TRUE;
+
+ if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) {
+ pI830->checkDevices = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
+ } else
+ if (pI830->entityPrivate && !IsPrimary(pScrn) &&
+ !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) {
+ /* If checklid is off, on the primary head, then
+ * turn it off on the secondary*/
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
+ pI830->checkDevices = FALSE;
+ } else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays enabled\n");
+ } else
+ pI830->checkDevices = FALSE;
+
+ /*
+ * 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.
+ * But, we double the amounts when dual head is enabled, and therefore
+ * for 2D-only we use 16384KB, and 3D we use 65536KB. The VideoRAM
+ * for the second head is never used, as the primary head does the
+ * allocation.
+ */
+ 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 (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (IsPrimary(pScrn))
+ pScrn->videoRam *= 2;
+ else
+ pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM;
+ }
+
+ 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 + HWCURSOR_SIZE_ARGB + 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);
+ pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+
+ pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS now sees %ld kB VideoRAM\n",
+ pI830->BIOSMemorySize / 1024);
+ } else if ((pI830->saveBIOSMemSize
+ = TweakMemorySize(pScrn, pI830->newBIOSMemSize,TRUE)) != 0)
+ pI830->overrideBIOSMemSize = TRUE;
+ 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: %ld 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
+
+ /*
+ * If the driver can do gamma correction, it should call xf86SetGamma() here.
+ */
+
+ {
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ }
+
+ GetBIOSVersion(pScrn, &ver);
+
+ v[0] = (ver & 0xff000000) >> 24;
+ v[1] = (ver & 0x00ff0000) >> 16;
+ v[2] = (ver & 0x0000ff00) >> 8;
+ v[3] = (ver & 0x000000ff) >> 0;
+ v[4] = 0;
+
+ pI830->bios_version = atoi(v);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version);
+
+ /* Great..
+ * Intel changed the BIOS version codes and started at 1200.
+ * We know that bios codes for 830M started around 2400.
+ * So we test those conditions to make this judgement. Ugh.
+ */
+ if (pI830->availablePipes == 2 && pI830->bios_version < 2000)
+ pI830->newPipeSwitch = TRUE;
+ else if (pI830->availablePipes == 2 && pI830->bios_version >= 3062)
+ /* BIOS build 3062 changed the pipe switching functionality */
+ pI830->newPipeSwitch = TRUE;
+ else
+ pI830->newPipeSwitch = FALSE;
+
+ if (pI830->newPipeSwitch)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
+
+ pI830->devicePresence = FALSE;
+ from = X_DEFAULT;
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_DEVICE_PRESENCE, FALSE)) {
+ pI830->devicePresence = TRUE;
+ from = X_CONFIG;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Device Presence: %s.\n",
+ pI830->devicePresence ? "enabled" : "disabled");
+
+ /* This performs an active detect of the currently attached monitors
+ * or, at least it's meant to..... alas it doesn't seem to always work.
+ */
+ if (pI830->devicePresence) {
+ int req, att, enc;
+ GetDevicePresence(pScrn, &req, &att, &enc);
+ for (i = 0; i < NumDisplayTypes; i++) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Display Presence: %s: attached: %s, encoder: %s\n",
+ displayDevices[i],
+ BOOLTOSTRING(((1<<i) & att)>>i),
+ BOOLTOSTRING(((1<<i) & enc)>>i));
+ }
+ }
+
+ /* Save old configuration of detected devices */
+ pI830->savedDevices = GetDisplayDevices(pScrn);
+
+ if (IsPrimary(pScrn)) {
+ pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn);
+
+ /* Override */
+ if (pI830->fixedPipe != -1) {
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
+ pI830->pipe = pI830->fixedPipe;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Fixed Pipe setting primary to pipe %s.\n",
+ pI830->fixedPipe ? "B" : "A");
+ }
+ }
+
+ /* If the monitors aren't setup, read from the current config */
+ if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) {
+ pI830->MonType1 = pI830->savedDevices & 0xff;
+ pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8;
+ } else {
+ /* Here, we've switched pipes from our primary */
+ if (pI830->MonType1 == PIPE_NONE && pI830->pipe == 0)
+ pI830->pipe = 1;
+ if (pI830->MonType2 == PIPE_NONE && pI830->pipe == 1)
+ pI830->pipe = 0;
+ }
+
+ pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1;
+
+ if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone) {
+ /* If we're not dual head or clone, turn off the second head,
+ * if monitorlayout is also specified. */
+
+ if (pI830->pipe == 0)
+ pI830->operatingDevices = pI830->MonType1;
+ else
+ pI830->operatingDevices = pI830->MonType2 << 8;
+ }
+
+ if (pI830->pipe != pI830->origPipe)
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Primary Pipe has been switched from original pipe (%s to %s)\n",
+ pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A");
+ } else {
+ I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
+ pI830->operatingDevices = pI8301->operatingDevices;
+ pI830->pipe = !pI8301->pipe;
+ pI830->MonType1 = pI8301->MonType1;
+ pI830->MonType2 = pI8301->MonType2;
+ }
+
+ /* Buggy BIOS 3066 is known to cause this, so turn this off */
+ if (pI830->bios_version == 3066) {
+ pI830->displayInfo = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected Broken Video BIOS, turning off displayInfo.\n");
+ } else
+ pI830->displayInfo = TRUE;
+ from = X_DEFAULT;
+ if (!xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, TRUE)) {
+ pI830->displayInfo = FALSE;
+ from = X_CONFIG;
+ }
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, FALSE)) {
+ pI830->displayInfo = TRUE;
+ from = X_CONFIG;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n",
+ pI830->displayInfo ? "enabled" : "disabled");
+
+ if (!I830DetectDisplayDevice(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't detect display devices.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ if (IsPrimary(pScrn)) {
+ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to switch to monitor configuration (0x%x)\n",
+ pI830->operatingDevices);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Please check the devices specified in your MonitorLayout\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "is configured correctly.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ }
+
+ PrintDisplayDeviceInfo(pScrn);
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (!IsPrimary(pScrn)) {
+ pI830Ent->pScrn_2 = pScrn;
+
+ /* This could be made to work with a little more fiddling */
+ pI830->directRenderingDisabled = TRUE;
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Secondary head is using Pipe %s\n",
+ pI830->pipe ? "B" : "A");
+ } else {
+ pI830Ent->pScrn_1 = pScrn;
+ pI830Ent->pScrn_2 = NULL;
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Primary head is using Pipe %s\n",
+ pI830->pipe ? "B" : "A");
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n",
+ pI830->pipe ? "B" : "A");
+ }
+
+ /* Alloc our pointers for the primary head */
+ if (IsPrimary(pScrn)) {
+ pI830->LpRing = xalloc(sizeof(I830RingBuffer));
+ pI830->CursorMem = xalloc(sizeof(I830MemRange));
+ pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
+ pI830->OverlayMem = xalloc(sizeof(I830MemRange));
+ pI830->overlayOn = xalloc(sizeof(Bool));
+ if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+ !pI830->OverlayMem || !pI830->overlayOn) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Could not allocate primary data structures.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ *pI830->overlayOn = FALSE;
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->XvInUse = -1;
+ }
+
+ /* Check if the HW cursor needs physical address. */
+ if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830))
+ pI830->CursorNeedsPhysical = TRUE;
+ else
+ pI830->CursorNeedsPhysical = FALSE;
+
+ /* Force ring buffer to be in low memory for all chipsets */
+ 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 (!IsPrimary(pScrn)) {
+ I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
+ if (!pI8301->SWCursor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using HW Cursor because it's enabled on primary head.\n");
+ pI830->SWCursor = FALSE;
+ }
+ } else
+ 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);
+ pScrn->videoRam -= (HWCURSOR_SIZE_ARGB / 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);
+
+ SetPipeAccess(pScrn);
+
+ /* Check we have an LFP connected, before trying to
+ * read PanelID information. */
+ if ( (pI830->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
+ (pI830->pipe == 0 && pI830->operatingDevices & PIPE_LFP) )
+ vbeDoPanelID(pI830->pVbe);
+
+ pDDCModule = xf86LoadSubModule(pScrn, "ddc");
+
+ pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
+
+ if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) {
+ xf86PrintEDID(pI830->vesa->monitor);
+ 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
+
+ pI830->useExtendedRefresh = FALSE;
+
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) {
+ int pipe =
+ (pI830->operatingDevices >> PIPE_SHIFT(pI830->pipe)) & 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(pI830->pipe));
+ 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;
+ } else {
+ for (i = 0; i < pI830->availablePipes; i++) {
+ int pipe =
+ (pI830->operatingDevices >> 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 && !pI830->vesa->useDefaultRefresh) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\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);
+
+ /* By now, we should have had some monitor settings, but if not, we
+ * need to setup some defaults. These are used in common/xf86Modes.c
+ * so we'll use them here for GetModePool, and that's all.
+ * We unset them after the call, so we can report 'defaults' as being
+ * used through the common layer.
+ */
+#define DEFAULT_HSYNC_LO 28
+#define DEFAULT_HSYNC_HI 33
+#define DEFAULT_VREFRESH_LO 43
+#define DEFAULT_VREFRESH_HI 72
+
+ if (pScrn->monitor->nHsync == 0) {
+ pScrn->monitor->hsync[0].lo = DEFAULT_HSYNC_LO;
+ pScrn->monitor->hsync[0].hi = DEFAULT_HSYNC_HI;
+ pScrn->monitor->nHsync = 1;
+ defmon |= 1;
+ }
+
+ if (pScrn->monitor->nVrefresh == 0) {
+ pScrn->monitor->vrefresh[0].lo = DEFAULT_VREFRESH_LO;
+ pScrn->monitor->vrefresh[0].hi = DEFAULT_VREFRESH_HI;
+ pScrn->monitor->nVrefresh = 1;
+ defmon |= 2;
+ }
+
+ DDCclock = I830UseDDC(pScrn);
+
+ /*
+ * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
+ * functions.
+ */
+ pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
+
+ if (!pScrn->modePool) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No Video BIOS modes for chosen depth.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ /* This may look a little weird, but to notify that we're using the
+ * default hsync/vrefresh we need to unset what we just set .....
+ */
+ if (defmon & 1) {
+ pScrn->monitor->hsync[0].lo = 0;
+ pScrn->monitor->hsync[0].hi = 0;
+ pScrn->monitor->nHsync = 0;
+ }
+
+ if (defmon & 2) {
+ pScrn->monitor->vrefresh[0].lo = 0;
+ pScrn->monitor->vrefresh[0].hi = 0;
+ pScrn->monitor->nVrefresh = 0;
+ }
+
+ SetPipeAccess(pScrn);
+ 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. */
+ SetPipeAccess(pScrn);
+ 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;
+ }
+
+ /* Only use this if we've got DDC available */
+ if (DDCclock > 0) {
+ p = pScrn->modes;
+ if (p == NULL)
+ return FALSE;
+ do {
+ int Clock = 100000000; /* incredible value */
+
+ if (p->status == MODE_OK) {
+ for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
+ if ((pMon->HDisplay != p->HDisplay) ||
+ (pMon->VDisplay != p->VDisplay) ||
+ (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+
+ /* Find lowest supported Clock for this resolution */
+ if (Clock > pMon->Clock)
+ Clock = pMon->Clock;
+ }
+
+ if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
+ ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
+ p->name, pScrn->monitor->id,
+ Clock/1000.0, DDCclock);
+ p->status = MODE_BAD;
+ }
+ }
+ p = p->next;
+ } while (p != NULL && p != pScrn->modes);
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+
+ /* Now we check the VESA BIOS's displayWidth and reset if necessary */
+ p = pScrn->modes;
+ do {
+ VbeModeInfoData *data = (VbeModeInfoData *) p->Private;
+ VbeModeInfoBlock *modeInfo;
+
+ /* Get BytesPerScanline so we can reset displayWidth */
+ if ((modeInfo = VBEGetModeInfo(pI830->pVbe, data->mode))) {
+ if (pScrn->displayWidth < modeInfo->BytesPerScanline / pI830->cpp) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Correcting stride (%d -> %d)\n", pScrn->displayWidth, modeInfo->BytesPerScanline);
+ pScrn->displayWidth = modeInfo->BytesPerScanline / pI830->cpp;
+ }
+ }
+ p = p->next;
+ } while (p != NULL && p != pScrn->modes);
+
+ pScrn->currentMode = pScrn->modes;
+
+#ifndef USE_PITCHES
+#define USE_PITCHES 1
+#endif
+ pI830->disableTiling = FALSE;
+
+ /*
+ * 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 (IsPrimary(pScrn) && !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 (%ld kB) by %ld 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.
+ */
+ pI830->disableTiling = TRUE;
+ 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 (%ld kB) by %ld 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
+
+ SetPipeAccess(pScrn);
+ I830PrintModes(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.
+ */
+ SetPipeAccess(pScrn);
+ I830SetModeParameters(pScrn, pI830->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);
+ }
+
+ /* 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);
+ }
+
+ I830UnmapMMIO(pScrn);
+
+ /* 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);
+
+ if (pI830->shadowFB) {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ I830BIOSFreeRec(pScrn);
+ vbeFree(pI830->pVbe);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
+ }
+
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ pI830->vbeInfo = NULL;
+ vbeFree(pI830->pVbe);
+ pI830->pVbe = NULL;
+
+ /* Use the VBE mode restore workaround by default. */
+ pI830->vbeRestoreWorkaround = TRUE;
+ from = X_DEFAULT;
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_VBE_RESTORE, FALSE)) {
+ pI830->vbeRestoreWorkaround = FALSE;
+ from = X_CONFIG;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "VBE Restore workaround: %s.\n",
+ pI830->vbeRestoreWorkaround ? "enabled" : "disabled");
+
+#if defined(XF86DRI)
+ /* Load the dri module if requested. */
+ if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) &&
+ !pI830->directRenderingDisabled) {
+ if (xf86LoadSubModule(pScrn, "dri")) {
+ xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
+ }
+ }
+
+ if (!pI830->directRenderingDisabled) {
+ if (!xf86LoadSubModule(pScrn, "shadow")) {
+ PreInitCleanup(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(I810shadowSymbols, NULL);
+ }
+#endif
+
+ pI830->preinit = FALSE;
+
+ 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;
+
+ if (!IsPrimary(pScrn)) return TRUE;
+
+ /* Check first for page table errors */
+ temp = INREG(PGE_ERR);
+ if (temp != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp);
+ errors++;
+ }
+ temp = INREG(PGETBL_CTL);
+ if (!(temp & 1)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp);
+ errors++;
+ }
+ temp = INREG(LP_RING + RING_LEN);
+ if (temp & 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PRB0_CTL (0x%08lx) 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%08lx) and PRB0_TAIL (0x%08lx) 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));
+
+ if (!IsPrimary(pScrn)) return;
+
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->RingRunning = 0;
+
+ /* 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");
+
+ if (!IsPrimary(pScrn)) return;
+
+ 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;
+
+ if (!IsPrimary(pScrn)) return;
+
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->RingRunning = 1;
+
+ OUTREG(LP_RING + RING_LEN, 0);
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
+ pI830->LpRing->mem.Start) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "I830SetRingRegs: Ring buffer start (%lx) 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 (%lx) 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");
+
+ if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+ SetBIOSPipe(pScrn, pI830->origPipe);
+ else
+ SetPipeAccess(pScrn);
+
+ pVesa = pI830->vesa;
+
+ /* Make sure we save at least this information in case of failure. */
+ VBEGetVBEMode(pVbe, &pVesa->stateMode);
+ pVesa->stateRefresh = GetRefreshRate(pScrn, pVesa->stateMode, NULL);
+ 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);
+
+ pVesa = pI830->vesa;
+ /*
+ * This save/restore method doesn't work for 845G BIOS, or for some
+ * other platforms. Enable it in all cases.
+ */
+ /*
+ * 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 (!pI830->vbeRestoreWorkaround) {
+ 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;
+ }
+
+ VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y);
+
+ 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");
+
+ if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+ SetBIOSPipe(pScrn, pI830->origPipe);
+ else
+ SetPipeAccess(pScrn);
+
+ 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)
+ I830Set640x480(pScrn);
+
+ 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->useDefaultRefresh && pI830->useExtendedRefresh) {
+ SetRefreshRate(pScrn, pVesa->stateMode, pVesa->stateRefresh);
+ }
+ }
+ if (pVesa->savedScanlinePitch)
+ VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
+
+ if (pVesa->savedPal)
+ VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
+
+ VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE);
+
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
+ vgaHWLock(hwp);
+
+ return TRUE;
+}
+
+static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ DisplayModePtr p = NULL;
+ int RefreshRate;
+ int clock;
+
+ /* Search for our mode and get a refresh to match */
+ for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
+ if ((p->HDisplay != pI830->CloneHDisplay) ||
+ (p->VDisplay != pI830->CloneVDisplay) ||
+ (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+ RefreshRate = ((double)(p->Clock * 1000) /
+ (double)(p->HTotal * p->VTotal)) * 100;
+ /* we could probably do better here that 2Hz boundaries */
+ if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) {
+ block->HorizontalTotal = p->HTotal;
+ block->HorizontalSyncStart = p->HSyncStart;
+ block->HorizontalSyncEnd = p->HSyncEnd;
+ block->VerticalTotal = p->VTotal;
+ block->VerticalSyncStart = p->VSyncStart;
+ block->VerticalSyncEnd = p->VSyncEnd;
+ block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
+ ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
+ block->PixelClock = p->Clock * 1000;
+ /* XXX May not have this. */
+ clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock);
+#ifdef DEBUG
+ ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
+ (double)data->block->PixelClock / 1000000.0,
+ (double)clock / 1000000.0);
+#endif
+ if (clock)
+ block->PixelClock = clock;
+ block->RefreshRate = RefreshRate;
+ return;
+ }
+ }
+}
+
+static Bool
+I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool ret = FALSE;
+ int Mon;
+
+ DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
+
+ if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
+ !pI830->preinit && !pI830->closing) {
+ VbeCRTCInfoBlock newblock;
+ int newmode = mode;
+
+ if (pI830->pipe == 1)
+ Mon = pI830->MonType1;
+ else
+ Mon = pI830->MonType2;
+
+ SetBIOSPipe(pScrn, !pI830->pipe);
+
+ /* Now recheck refresh operations we can use */
+ pI830->useExtendedRefresh = FALSE;
+ pI830->vesa->useDefaultRefresh = FALSE;
+
+ if (Mon != PIPE_CRT) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "A non-CRT device is attached to Clone pipe %c.\n"
+ "\tNo refresh rate overrides will be attempted (0x%x).\n",
+ PIPE_NAME(!pI830->pipe), newmode);
+ 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;
+
+ newmode |= 1 << 11;
+ if (pI830->vesa->useDefaultRefresh)
+ newmode &= ~(1 << 11);
+
+ if (!SetRefreshRate(pScrn, newmode, 60)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS call 0x5f05 not supported on Clone Head, "
+ "setting refresh with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
+ }
+
+ if (!pI830->vesa->useDefaultRefresh) {
+ I830SetCloneVBERefresh(pScrn, newmode, &newblock, pI830->CloneRefresh * 100);
+
+ if (!VBESetVBEMode(pI830->pVbe, newmode, &newblock)) {
+ if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set mode for Clone head.\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Setting refresh on clone head with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
+ }
+ } else {
+ if (!VBESetVBEMode(pI830->pVbe, (newmode & ~(1 << 11)), NULL))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set mode for Clone head.\n");
+ }
+
+ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) {
+ if (!SetRefreshRate(pScrn, newmode, pI830->CloneRefresh))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set refresh rate to %dHz on Clone head.\n",
+ pI830->CloneRefresh);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Set refresh rate to %dHz on Clone head.\n",
+ pI830->CloneRefresh);
+ }
+
+ SetPipeAccess(pScrn);
+ }
+
+ if (pI830->pipe == 0)
+ Mon = pI830->MonType1;
+ else
+ Mon = pI830->MonType2;
+
+ /* Now recheck refresh operations we can use */
+ pI830->useExtendedRefresh = FALSE;
+ pI830->vesa->useDefaultRefresh = FALSE;
+
+ if (Mon != PIPE_CRT)
+ pI830->vesa->useDefaultRefresh = TRUE;
+
+ mode |= 1 << 11;
+ if (pI830->vesa->useDefaultRefresh)
+ mode &= ~(1 << 11);
+ /*
+ * 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 (!SetRefreshRate(pScrn, mode, 60)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS call 0x5f05 not supported, "
+ "setting refresh with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
+ }
+
+ if (!pI830->vesa->useDefaultRefresh && block) {
+ ret = VBESetVBEMode(pI830->pVbe, mode, block);
+ if (!ret)
+ ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Setting refresh with VBE 3 method.\n");
+ pI830->useExtendedRefresh = FALSE;
+ }
+ } else {
+ ret = VBESetVBEMode(pI830->pVbe, (mode & ~(1 << 11)), NULL);
+ }
+
+ /* Might as well bail now if we've failed */
+ if (!ret) return FALSE;
+
+ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && block) {
+ if (!SetRefreshRate(pScrn, mode, block->RefreshRate / 100)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to set refresh rate to %dHz.\n",
+ block->RefreshRate / 100);
+ pI830->useExtendedRefresh = FALSE;
+ }
+ }
+
+ return ret;
+}
+
+static Bool
+I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ vbeInfoPtr pVbe = pI830->pVbe;
+ VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private;
+ int mode, i;
+ CARD32 planeA, planeB, temp;
+ int refresh = 60;
+#ifdef XF86DRI
+ Bool didLock = FALSE;
+#endif
+
+ DPRINTF(PFX, "I830VESASetMode\n");
+
+ /* 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
+
+ if (pI830->Clone) {
+ pI830->CloneHDisplay = pMode->HDisplay;
+ pI830->CloneVDisplay = pMode->VDisplay;
+ }
+
+#ifndef MODESWITCH_RESET_STATE
+#define MODESWITCH_RESET_STATE 0
+#endif
+#if MODESWITCH_RESET_STATE
+ ResetState(pScrn, TRUE);
+#endif
+
+ SetPipeAccess(pScrn);
+
+ if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
+ 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) {
+ if (pI830->Clone) {
+ SetBIOSPipe(pScrn, !pI830->pipe);
+ VBESetLogicalScanline(pVbe, pScrn->displayWidth);
+ }
+ SetPipeAccess(pScrn);
+ VBESetLogicalScanline(pVbe, pScrn->displayWidth);
+ }
+
+ if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) {
+ if (pI830->Clone) {
+ SetBIOSPipe(pScrn, !pI830->pipe);
+ VBESetGetDACPaletteFormat(pVbe, 8);
+ }
+ SetPipeAccess(pScrn);
+ VBESetGetDACPaletteFormat(pVbe, 8);
+ }
+
+ /* 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 and connected to %s.\n",
+ pI830->planeEnabled[0] ? "enabled" : "disabled",
+ planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+ if (pI830->availablePipes == 2)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n",
+ pI830->planeEnabled[1] ? "enabled" : "disabled",
+ planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+
+ if (pI830->operatingDevices & 0xff) {
+ pI830->planeEnabled[0] = 1;
+ } else {
+ pI830->planeEnabled[0] = 0;
+ }
+
+ if (pI830->operatingDevices & 0xff00) {
+ pI830->planeEnabled[1] = 1;
+ } else {
+ pI830->planeEnabled[1] = 0;
+ }
+
+ if (pI830->planeEnabled[0]) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
+ planeA |= DISPLAY_PLANE_ENABLE;
+ planeA &= ~DISPPLANE_SEL_PIPE_MASK;
+ planeA |= DISPPLANE_SEL_PIPE_A;
+ 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;
+ planeB &= ~DISPPLANE_SEL_PIPE_MASK;
+ planeB |= DISPPLANE_SEL_PIPE_B;
+ OUTREG(DSPBCNTR, planeB);
+ /* flush the change. */
+ temp = INREG(DSPBADDR);
+ OUTREG(DSPBADDR, temp);
+ }
+
+ planeA = INREG(DSPACNTR);
+ planeB = INREG(DSPBCNTR);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n",
+ pI830->planeEnabled[0] ? "enabled" : "disabled",
+ planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+ if (pI830->availablePipes == 2)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n",
+ pI830->planeEnabled[1] ? "enabled" : "disabled",
+ planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A");
+
+ /* 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%08lx\n", temp);
+ if (pI830->availablePipes == 2) {
+ temp = INREG(PIPEBCONF);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
+ }
+
+
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ /* Clean this up !! */
+ if (IsPrimary(pScrn)) {
+ CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
+ CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
+ CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+ temp = INREG(stridereg);
+ if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
+ (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth);
+ OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp);
+ }
+ OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+ I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+ stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
+ basereg = pI830->pipe ? DSPABASE : DSPBBASE;
+ sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
+
+ temp = INREG(stridereg);
+ if (temp / pI8302->cpp != (CARD32)(pI830->entityPrivate->pScrn_2->displayWidth)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
+ (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth);
+ OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp);
+ }
+ OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16));
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+ }
+ } else {
+ CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
+ CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE;
+ CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+
+ temp = INREG(stridereg);
+ if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
+ (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth);
+ OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp);
+ }
+ OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16));
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+
+ stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
+ basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
+ sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
+
+ temp = INREG(stridereg);
+ if (temp / pI8302->cpp != ((CARD32)pI830->entityPrivate->pScrn_2->displayWidth)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
+ (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth);
+ OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp);
+ }
+ OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+ }
+ } else {
+ for (i = 0; i < pI830->availablePipes; i++) {
+ CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
+ CARD32 basereg = i ? DSPBBASE : DSPABASE;
+ CARD32 sizereg = i ? DSPBSIZE : DSPASIZE;
+
+ if (!pI830->planeEnabled[i])
+ continue;
+
+ temp = INREG(stridereg);
+ if (temp / pI830->cpp != (CARD32)pScrn->displayWidth) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
+ (int)(temp / pI830->cpp), pScrn->displayWidth);
+ OUTREG(stridereg, pScrn->displayWidth * pI830->cpp);
+ }
+ OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
+ /* Trigger update */
+ temp = INREG(basereg);
+ OUTREG(basereg, temp);
+ }
+ }
+
+#if 0
+ /* 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);
+ temp = INREG(DSPAPOS);
+ ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
+ temp = INREG(DSPASIZE);
+ ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
+
+ /* Print out some CRTC/display information. */
+ temp = INREG(HTOTAL_B);
+ ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(HBLANK_B);
+ ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(HSYNC_B);
+ ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VTOTAL_B);
+ ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VBLANK_B);
+ ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(VSYNC_B);
+ ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
+ (temp >> 16) & 0xfff);
+ temp = INREG(PIPEBSRC);
+ 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(DSPBBASE);
+ ErrorF("Plane B start offset is %d\n", temp);
+ temp = INREG(DSPBSTRIDE);
+ ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
+ temp = INREG(DSPBPOS);
+ ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
+ temp = INREG(DSPBSIZE);
+ ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16);
+#endif
+
+ 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);
+ }
+ }
+
+#if 0
+ {
+ int ret;
+
+ ret = GetLFPCompMode(pScrn);
+ if (ret != -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "LFP compensation mode: 0x%x\n", ret);
+ }
+ }
+#endif
+
+#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;
+
+ if (!IsPrimary(pScrn)) return;
+
+ 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;
+ I830EntPtr pI830Ent = NULL;
+ I830Ptr pI8301 = NULL;
+ int width, height, displayWidth;
+ unsigned char *fbbase;
+#ifdef XF86DRI
+ Bool driDisabled;
+#endif
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pI830 = I830PTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ pI830Ent = pI830->entityPrivate;
+ pI8301 = I830PTR(pI830Ent->pScrn_1);
+
+ /* PreInit failed on the second head, so make sure we turn it off */
+ if (IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) {
+ if (pI830->pipe == 0) {
+ pI830->operatingDevices &= 0xFF;
+ } else {
+ pI830->operatingDevices &= 0xFF00;
+ }
+ }
+ }
+
+ pI830->starting = TRUE;
+
+ /* Alloc our pointers for the primary head */
+ if (IsPrimary(pScrn)) {
+ if (!pI830->LpRing)
+ pI830->LpRing = xalloc(sizeof(I830RingBuffer));
+ if (!pI830->CursorMem)
+ pI830->CursorMem = xalloc(sizeof(I830MemRange));
+ if (!pI830->CursorMemARGB)
+ pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
+ if (!pI830->OverlayMem)
+ pI830->OverlayMem = xalloc(sizeof(I830MemRange));
+ if (!pI830->overlayOn)
+ pI830->overlayOn = xalloc(sizeof(Bool));
+ if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+ !pI830->OverlayMem || !pI830->overlayOn) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Could not allocate primary data structures.\n");
+ return FALSE;
+ }
+ *pI830->overlayOn = FALSE;
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->XvInUse = -1;
+ }
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ /* Make our second head point to the first heads structures */
+ if (!IsPrimary(pScrn)) {
+ pI830->LpRing = pI8301->LpRing;
+ pI830->CursorMem = pI8301->CursorMem;
+ pI830->CursorMemARGB = pI8301->CursorMemARGB;
+ pI830->OverlayMem = pI8301->OverlayMem;
+ pI830->overlayOn = pI8301->overlayOn;
+ }
+ }
+
+ /*
+ * If we're changing the BIOS's view of the video memory size, do that
+ * first, then re-initialise the VBE information.
+ */
+ if (pI830->pVbe)
+ vbeFree(pI830->pVbe);
+ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+ if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
+ SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+ if (!pI830->pVbe)
+ return FALSE;
+ if (pI830->vbeInfo)
+ VBEFreeVBEInfo(pI830->vbeInfo);
+ pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+
+ miClearVisualTypes();
+ 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 (!IsPrimary(pScrn)) {
+ if (!pI8301->XvEnabled || pI830->noAccel) {
+ pI830->XvEnabled = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
+ }
+ } else
+ 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
+
+ if (IsPrimary(pScrn)) {
+ I830ResetAllocations(pScrn, 0);
+
+ if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL))
+ return FALSE;
+ }
+
+ 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 && IsPrimary(pScrn))) {
+ 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) {
+ pI830->directRenderingEnabled =
+ I830Allocate3DMemory(pScrn,
+ pI830->disableTiling ? ALLOC_NO_TILING : 0);
+ if (!pI830->directRenderingEnabled)
+ 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.
+ */
+ if (IsPrimary(pScrn)) {
+ 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;
+
+ if (IsPrimary(pScrn)) {
+ pScrn->fbOffset = pI830->FrontBuffer.Start;
+ } else {
+ I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
+ pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+ }
+
+ pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
+ pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
+
+ 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 (pI830->rotate) {
+ height = pScrn->virtualX;
+ width = pScrn->virtualY;
+ } else {
+ width = pScrn->virtualX;
+ height = pScrn->virtualY;
+ }
+ if (pI830->shadowFB) {
+ pI830->shadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+ pI830->shadowPtr = xalloc(pI830->shadowPitch * height);
+ displayWidth = pI830->shadowPitch / (pScrn->bitsPerPixel >> 3);
+ fbbase = pI830->shadowPtr;
+ } else {
+ pI830->shadowPtr = NULL;
+ fbbase = pI830->FbBase;
+ displayWidth = pScrn->displayWidth;
+ }
+ if (!fbScreenInit(pScreen, fbbase + pScrn->fbOffset, width, height,
+ pScrn->xDpi, pScrn->yDpi,
+ 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 (!pI830->shadowFB)
+ I830DGAInit(pScreen);
+
+ DPRINTF(PFX,
+ "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
+ if (IsPrimary(pScrn)) {
+ if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to init memory manager\n");
+ return FALSE;
+ }
+ } else {
+ if (!xf86InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
+ 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");
+
+ if (pI830->shadowFB) {
+ RefreshAreaFuncPtr refreshArea = I830RefreshArea;
+ if (pI830->rotate) {
+ if (!pI830->PointerMoved) {
+ pI830->PointerMoved = pScrn->PointerMoved;
+ pScrn->PointerMoved = I830PointerMoved;
+ }
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ refreshArea = I830RefreshArea8;
+ break;
+ case 16:
+ refreshArea = I830RefreshArea16;
+ break;
+ case 24:
+ refreshArea = I830RefreshArea24;
+ break;
+ case 32:
+ refreshArea = I830RefreshArea32;
+ break;
+ }
+ }
+ ShadowFBInit(pScreen, refreshArea);
+ }
+
+ 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 |
+ CMAP_PALETTED_TRUECOLOR)) {
+ return FALSE;
+ }
+
+ xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0);
+
+#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);
+
+#ifdef I830DEBUG
+ I830_dump_registers(pScrn);
+#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;
+
+ pScrn = xf86Screens[scrnIndex];
+ pI830 = I830PTR(pScrn);
+ pVbe = pI830->pVbe;
+
+ DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
+ x, pI830->xoffset, y, pI830->yoffset);
+
+ /* Sync the engine before adjust frame */
+ if (!pI830->noAccel && pI830->AccelInfoRec)
+ (*pI830->AccelInfoRec->Sync)(pScrn);
+
+ /* The i830M just happens to have some problems programming offsets via
+ * this VESA BIOS call. Especially in dual head configurations which
+ * have high resolutions which cause the DSP{A,B}BASE registers to be
+ * programmed incorrectly. Thus, it warrants bypassing the BIOS for i830M
+ * and hitting the DSP{A,B}BASE registers directly.
+ *
+ * We could probably do this for other platforms too, but we don't
+ * know what else the Video BIOS may do when calling it. It seems safe
+ * though for i830M during testing......
+ *
+ * Also note, calling the Video BIOS version first and then fixing the
+ * registers fail on i830M and eventually cause a lockup of the hardware
+ * in my testing.
+ */
+
+ if (pI830->Clone) {
+ if (!IS_I830(pI830)) {
+ SetBIOSPipe(pScrn, !pI830->pipe);
+ VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE);
+ } else {
+ if (!pI830->pipe == 0) {
+ OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ } else {
+ OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ }
+ }
+ }
+
+ if (!IS_I830(pI830)) {
+ SetPipeAccess(pScrn);
+ VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE);
+ } else {
+ if (pI830->pipe == 0) {
+ OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ } else {
+ OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ }
+ }
+}
+
+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];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "Leave VT\n");
+
+ pI830->leaving = TRUE;
+
+ if (pI830->devicesTimer)
+ TimerCancel(pI830->devicesTimer);
+ pI830->devicesTimer = NULL;
+
+#ifdef I830_XV
+ /* Give the video overlay code a chance to shutdown. */
+ I830VideoSwitchModeBefore(pScrn, NULL);
+#endif
+
+ if (pI830->Clone) {
+ /* Ensure we don't try and setup modes on a clone head */
+ pI830->CloneHDisplay = 0;
+ pI830->CloneVDisplay = 0;
+ }
+
+ if (!IsPrimary(pScrn)) {
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ if (!pI8301->GttBound) {
+ return;
+ }
+ }
+
+#ifdef XF86DRI
+ if (pI830->directRenderingOpen) {
+ DPRINTF(PFX, "calling dri lock\n");
+ DRILock(screenInfo.screens[scrnIndex], 0);
+ pI830->LockHeld = 1;
+
+ drmCtlUninstHandler(pI830->drmSubFD);
+ }
+#endif
+
+#if SAVERESTORE_HWSTATE
+ if (!pI830->closing)
+ SaveHWOperatingState(pScrn);
+#endif
+
+ if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
+ pI830->CursorInfoRec->HideCursor(pScrn);
+
+ ResetState(pScrn, TRUE);
+
+ if (IsPrimary(pScrn)) {
+ if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch back to original display devices (0x%x)\n",
+ pI830->savedDevices);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set original devices\n");
+ }
+ }
+
+ RestoreHWState(pScrn);
+ RestoreBIOSMemSize(pScrn);
+ if (IsPrimary(pScrn))
+ I830UnbindGARTMemory(pScrn);
+ if (pI830->AccelInfoRec)
+ pI830->AccelInfoRec->NeedToSync = FALSE;
+
+ /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
+ if (IsPrimary(pScrn)) {
+ if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch back to original display devices (0x%x) (2)\n",
+ pI830->savedDevices);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Successfully set original devices (2)\n");
+ }
+ }
+}
+
+static Bool
+I830DetectMonitorChange(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ pointer pDDCModule = NULL;
+ DisplayModePtr p, pMon;
+ int memsize;
+ int DDCclock = 0;
+ int displayWidth = pScrn->displayWidth;
+ int curHDisplay = pScrn->currentMode->HDisplay;
+ int curVDisplay = pScrn->currentMode->VDisplay;
+
+ DPRINTF(PFX, "Detect Monitor Change\n");
+
+ SetPipeAccess(pScrn);
+
+ /* Re-read EDID */
+ pDDCModule = xf86LoadSubModule(pScrn, "ddc");
+ if (pI830->vesa->monitor)
+ xfree(pI830->vesa->monitor);
+ pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule);
+ xf86UnloadSubModule(pDDCModule);
+ if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) {
+ xf86PrintEDID(pI830->vesa->monitor);
+ xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
+ } else
+ /* No DDC, so get out of here, and continue to use the current settings */
+ return FALSE;
+
+ if (!(DDCclock = I830UseDDC(pScrn)))
+ return FALSE;
+
+ /* Revalidate the modes */
+
+ /*
+ * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS
+ * functions.
+ */
+ pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo);
+
+ if (!pScrn->modePool) {
+ /* This is bad, which would cause the Xserver to exit, maybe
+ * we should default to a 640x480 @ 60Hz mode here ??? */
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No Video BIOS modes for chosen depth.\n");
+ return FALSE;
+ }
+
+ SetPipeAccess(pScrn);
+ VBESetModeNames(pScrn->modePool);
+
+ if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
+ memsize = pI830->vbeInfo->TotalMemory * 64;
+ else
+ memsize = pScrn->videoRam;
+
+ VBEValidateModes(pScrn, pScrn->monitor->Modes, 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 (DDCclock > 0) {
+ p = pScrn->modes;
+ if (p == NULL)
+ return FALSE;
+ do {
+ int Clock = 100000000; /* incredible value */
+
+ if (p->status == MODE_OK) {
+ for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) {
+ if ((pMon->HDisplay != p->HDisplay) ||
+ (pMon->VDisplay != p->VDisplay) ||
+ (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+
+ /* Find lowest supported Clock for this resolution */
+ if (Clock > pMon->Clock)
+ Clock = pMon->Clock;
+ }
+
+ if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
+ ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
+ p->name, pScrn->monitor->id,
+ Clock/1000.0, DDCclock);
+ p->status = MODE_BAD;
+ }
+ }
+ p = p->next;
+ } while (p != NULL && p != pScrn->modes);
+ }
+
+ pScrn->displayWidth = displayWidth; /* restore old displayWidth */
+
+ xf86PruneDriverModes(pScrn);
+ I830PrintModes(pScrn);
+
+ if (!pI830->vesa->useDefaultRefresh)
+ I830SetModeParameters(pScrn, pI830->pVbe);
+
+ /* Now check if the previously used mode is o.k. for the current monitor.
+ * This allows VT switching to continue happily when not disconnecting
+ * and reconnecting monitors */
+
+ pScrn->currentMode = pScrn->modes;
+ p = pScrn->modes;
+ if (p == NULL)
+ return FALSE;
+ do {
+ if ((p->HDisplay == curHDisplay) &&
+ (p->VDisplay == curVDisplay) &&
+ (!(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))) {
+ pScrn->currentMode = p; /* previous mode is o.k. */
+ }
+ p = p->next;
+ } while (p != NULL && p != pScrn->modes);
+
+ /* Now readjust for panning if necessary */
+ {
+ pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2;
+
+ if (pScrn->frameX0 < 0)
+ pScrn->frameX0 = 0;
+
+ pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
+ if (pScrn->frameX1 >= pScrn->virtualX) {
+ pScrn->frameX0 = pScrn->virtualX - pScrn->currentMode->HDisplay;
+ pScrn->frameX1 = pScrn->virtualX - 1;
+ }
+
+ pScrn->frameY0 = (pScrn->frameY0 + pScrn->frameY1 + 1 - pScrn->currentMode->VDisplay) / 2;
+
+ if (pScrn->frameY0 < 0)
+ pScrn->frameY0 = 0;
+
+ pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
+ if (pScrn->frameY1 >= pScrn->virtualY) {
+ pScrn->frameY0 = pScrn->virtualY - pScrn->currentMode->VDisplay;
+ pScrn->frameY1 = pScrn->virtualY - 1;
+ }
+ }
+
+ return TRUE;
+}
+
+Bool
+I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool ret = TRUE;
+
+ if (pI830->Clone) {
+ if (pI830->pipeDisplaySize[0].x2 != 0) {
+ if (x > pI830->pipeDisplaySize[0].x2 ||
+ y > pI830->pipeDisplaySize[0].y2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
+ return FALSE;
+ }
+ }
+ if (pI830->pipeDisplaySize[1].x2 != 0) {
+ if (x > pI830->pipeDisplaySize[1].x2 ||
+ y > pI830->pipeDisplaySize[1].y2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad Clone Mode removing\n");
+ return FALSE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * 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);
+
+ DPRINTF(PFX, "Enter VT\n");
+
+ /*
+ * 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 (pI830->SaveGeneration != serverGeneration) {
+ pI830->SaveGeneration = serverGeneration;
+ SaveHWState(pScrn);
+ }
+
+ pI830->leaving = FALSE;
+
+ if (IsPrimary(pScrn)) {
+ /*
+ * This is needed for restoring from ACPI modes (especially S3)
+ * so that we warmboot the Video BIOS. Some platforms have problems,
+ * warm booting when we don't need to, so check that we can call
+ * the Video BIOS with our saved devices, and only when that fails,
+ * we'll warm boot it.
+ */
+ /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
+ CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
+ if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) {
+ xf86Int10InfoPtr pInt;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected resume, re-POSTing.\n");
+
+ pInt = xf86InitInt10(pI830->pEnt->index);
+
+ /* Now perform our warm boot */
+ if (pInt) {
+ pInt->num = 0xe6;
+ xf86ExecX86int10 (pInt);
+ xf86FreeInt10 (pInt);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Re-POSTing via int10.\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Re-POSTing via int10 failed, trying to continue.\n");
+ }
+ }
+
+ /* Finally, re-setup the display devices */
+ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to switch to configured display devices\n");
+ return FALSE;
+ }
+ }
+
+ /* Setup for device monitoring status */
+ pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF;
+
+ if (IsPrimary(pScrn))
+ if (!I830BindGARTMemory(pScrn))
+ return FALSE;
+
+ CheckInheritedState(pScrn);
+ if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
+ SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+
+ ResetState(pScrn, FALSE);
+ SetHWOperatingState(pScrn);
+
+#if 1
+ /* Clear the framebuffer */
+ memset(pI830->FbBase + pScrn->fbOffset, 0,
+ pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
+#endif
+
+ /* Detect monitor change and switch to suitable mode */
+ if (!pI830->starting)
+ I830DetectMonitorChange(pScrn);
+
+ 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) {
+ I830DRIResume(screenInfo.screens[scrnIndex]);
+
+ I830EmitInvarientState(pScrn);
+ I830RefreshRing(pScrn);
+ I830Sync(pScrn);
+ DO_RING_IDLE();
+
+ DPRINTF(PFX, "calling dri unlock\n");
+ DRIUnlock(screenInfo.screens[scrnIndex]);
+ }
+ pI830->LockHeld = 0;
+ }
+#endif
+
+ if (pI830->checkDevices)
+ pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
+
+ return TRUE;
+}
+
+static Bool
+I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int ret = TRUE;
+
+ DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
+
+ /* Sync the engine before mode switch */
+ if (!pI830->noAccel && pI830->AccelInfoRec)
+ (*pI830->AccelInfoRec->Sync)(pScrn);
+
+#ifndef BINDUNBIND
+#define BINDUNBIND 0
+#endif
+#if BINDUNBIND
+ if (IsPrimary(pScrn))
+ 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
+ if (IsPrimary(pScrn))
+ 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;
+
+ DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
+
+ if (pScrn->vtSema) {
+ if (pI830->pipe == 0) {
+ ctrl = DSPACNTR;
+ base = DSPABASE;
+ } else {
+ ctrl = DSPBCNTR;
+ base = DSPBADDR;
+ }
+ if (pI830->planeEnabled[pI830->pipe]) {
+ 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 (pI830->Clone) {
+ SetBIOSPipe(pScrn, !pI830->pipe);
+ 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);
+ }
+ }
+
+ SetPipeAccess(pScrn);
+
+ 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);
+ }
+
+ if (pI830->devicesTimer)
+ TimerCancel(pI830->devicesTimer);
+ pI830->devicesTimer = NULL;
+
+ 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;
+ }
+
+ if (IsPrimary(pScrn)) {
+ xf86GARTCloseScreen(scrnIndex);
+
+ xfree(pI830->LpRing);
+ pI830->LpRing = NULL;
+ xfree(pI830->CursorMem);
+ pI830->CursorMem = NULL;
+ xfree(pI830->CursorMemARGB);
+ pI830->CursorMemARGB = NULL;
+ xfree(pI830->OverlayMem);
+ pI830->OverlayMem = NULL;
+ xfree(pI830->overlayOn);
+ pI830->overlayOn = NULL;
+ }
+
+ pScrn->vtSema = FALSE;
+ pI830->closing = FALSE;
+ pScreen->CloseScreen = pI830->CloseScreen;
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static ModeStatus
+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;
+}
+
+static int CountBits(int a)
+{
+ int i;
+ int b = 0;
+
+ for (i=0;i<8;i++) {
+ if (a & (1<<i))
+ b+=1;
+ }
+
+ return b;
+}
+
+static CARD32
+I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ ScrnInfoPtr pScrn = (ScrnInfoPtr) arg;
+ I830Ptr pI830 = I830PTR(pScrn);
+ int cloned = 0;
+
+ if (pScrn->vtSema) {
+ /* Check for monitor lid being closed/opened and act accordingly */
+ CARD32 adjust;
+ CARD32 temp = INREG(SWF0) & 0x0000FFFF;
+ int fixup = 0;
+
+ /* this avoids a BIOS call if possible */
+ if (pI830->monitorSwitch != temp) {
+ I830Ptr pI8301;
+ I830Ptr pI8302 = NULL;
+ unsigned int toggle = GetToggleList(pScrn, 1);
+
+ GetToggleList(pScrn, 2);
+ GetToggleList(pScrn, 3);
+ GetToggleList(pScrn, 4);
+
+ if (IsPrimary(pScrn))
+ pI8301 = pI830;
+ else
+ pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+ if (xf86IsEntityShared(pScrn->entityList[0]))
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+
+ pI8301->lastDevice1 = pI8301->lastDevice2;
+ pI8301->lastDevice2 = pI8301->monitorSwitch;
+
+ if (CountBits(temp & 0xff) > 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected cloned pipe mode (A).\n");
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ } else
+ if (CountBits((temp & 0xff00) >> 8) > 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected cloned pipe mode (B).\n");
+ if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ } else
+ if (pI8301->lastDevice1 && pI8301->lastDevice2) {
+ if ( ((pI8301->lastDevice1 & 0xFF00) == 0) &&
+ ((pI8301->lastDevice2 & 0x00FF) == 0) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected last devices (1).\n");
+ cloned = 1;
+ } else if ( ((pI8301->lastDevice2 & 0xFF00) == 0) &&
+ ((pI8301->lastDevice1 & 0x00FF) == 0) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected last devices (2).\n");
+ cloned = 1;
+ } else
+ cloned = 0;
+ }
+
+ if (cloned &&
+ ((CountBits(pI830->lastDevice1 & 0xff) > 1) ||
+ ((CountBits((pI830->lastDevice1 & 0xff00) >> 8) > 1))) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate (1).\n");
+ cloned = 0;
+ } else
+ if (cloned &&
+ ((CountBits(pI830->lastDevice2 & 0xff) > 1) ||
+ ((CountBits((pI830->lastDevice2 & 0xff00) >> 8) > 1))) ) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate (2).\n");
+ cloned = 0;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Requested display devices 0x%lx.\n", temp);
+
+
+ /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake
+ * it here as it seems some just flip between CRT and LFP. Ugh!
+ *
+ * So this pushes them onto Pipe B and clones the displays, which
+ * is what most BIOS' should be doing.
+ *
+ * Cloned pipe mode should only be done when running single head.
+ */
+ if (xf86IsEntityShared(pScrn->entityList[0]))
+ cloned = 0;
+
+ if (cloned) {
+ if (pI830->Clone)
+ temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+ else if (pI8301->lastDevice1 & 0xFF)
+ temp = pI8301->lastDevice1 << 8 | pI8301->lastDevice2;
+ else
+ temp = pI8301->lastDevice2 << 8 | pI8301->lastDevice1;
+ }
+
+ /* Jump to our next mode if we detect we've been here before */
+ if (temp == pI830->lastDevice1 || temp == pI830->lastDevice2) {
+ temp = toggle;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected duplicate devices. Toggling (0x%lx)\n", temp);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected display change operation (0x%x, 0x%x, 0x%lx).\n",
+ pI8301->lastDevice1, pI8301->lastDevice2, temp);
+
+ /* So that if we close on the wrong config, we restore correctly */
+ pI830->specifiedMonitor = TRUE;
+
+ /* double check the display devices are what's configured and try
+ * not to do it twice because of dual heads with the code above */
+ if (!SetDisplayDevices(pScrn, temp)) {
+ if ( cloned &&
+ ((CountBits(temp & 0xff) > 1) ||
+ (CountBits((temp & 0xff00) >> 8) > 1)) ) {
+ temp = pI8301->lastDevice2 | pI8301->lastDevice1;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, "
+ "trying dual pipe clone mode (0x%lx)\n", temp);
+ if (!SetDisplayDevices(pScrn, temp))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
+ "to configured display devices (0x%lx).\n", temp);
+ else
+ pI830->Clone = TRUE;
+ }
+ }
+ pI8301->monitorSwitch = temp;
+ pI8301->operatingDevices = temp;
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ pI8302->operatingDevices = temp;
+ pI8302->monitorSwitch = temp;
+ }
+
+ fixup = 1;
+ } else {
+ int offset = pScrn->fbOffset + ((pScrn->frameY0 * pScrn->displayWidth + pScrn->frameX0) * pI830->cpp);
+
+ if (pI830->pipe == 0)
+ adjust = INREG(DSPABASE);
+ else
+ adjust = INREG(DSPBBASE);
+
+ if (adjust != offset) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Fixing display offsets.\n");
+
+ I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+ }
+ }
+
+ if (fixup) {
+ ScreenPtr pCursorScreen;
+ int x = 0, y = 0;
+
+ pCursorScreen = miPointerCurrentScreen();
+ if (pScrn->pScreen == pCursorScreen)
+ miPointerPosition(&x, &y);
+
+ /* Now, when we're single head, make sure we switch pipes */
+ if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) || cloned) {
+ if (temp & 0xFF00)
+ pI830->pipe = 1;
+ else
+ pI830->pipe = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A");
+ }
+
+ I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
+ I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ ScrnInfoPtr pScrn2;
+ I830Ptr pI8302;
+
+ if (IsPrimary(pScrn)) {
+ pScrn2 = pI830->entityPrivate->pScrn_2;
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+ } else {
+ pScrn2 = pI830->entityPrivate->pScrn_1;
+ pI8302 = I830PTR(pI830->entityPrivate->pScrn_1);
+ }
+
+ I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
+ I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
+ if (pScrn2->pScreen == pCursorScreen) {
+ int sigstate = xf86BlockSIGIO ();
+ miPointerWarpCursor(pScrn2->pScreen,x,y);
+
+ /* xf86Info.currentScreen = pScrn->pScreen; */
+ xf86UnblockSIGIO (sigstate);
+ if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) {
+ pI8302->CursorInfoRec->HideCursor(pScrn);
+ pI8302->CursorInfoRec->ShowCursor(pScrn);
+ pI8302->cursorOn = TRUE;
+ }
+ }
+ }
+
+ if (pScrn->pScreen == pCursorScreen) {
+ int sigstate = xf86BlockSIGIO ();
+ miPointerWarpCursor(pScrn->pScreen,x,y);
+
+ /* xf86Info.currentScreen = pScrn->pScreen; */
+ xf86UnblockSIGIO (sigstate);
+ if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
+ pI830->CursorInfoRec->HideCursor(pScrn);
+ pI830->CursorInfoRec->ShowCursor(pScrn);
+ pI830->cursorOn = TRUE;
+ }
+ }
+ }
+ }
+
+ return 1000;
+}
+
+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/driver/xf86-video-i810/src/i830_io.c b/driver/xf86-video-i810/src/i830_io.c
new file mode 100644
index 000000000..8006789d2
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_io.c
@@ -0,0 +1,35 @@
+/**************************************************************************
+
+Copyright 2005 Red Hat, Inc.
+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 RED HAT, INC 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:
+ * Kristian Høgsberg <krh@redhat.com>
+ *
+ */
+
+#define BUILD_FOR_I830 1
+#include "i810_io.c"
diff --git a/driver/xf86-video-i810/src/i830_memory.c b/driver/xf86-video-i810/src/i830_memory.c
new file mode 100644
index 000000000..27cf01781
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_memory.c
@@ -0,0 +1,1634 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c,v 1.9 2003/09/24 03:16:54 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@xfree86.org>
+ *
+ * Updated for Dual Head capabilities:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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,
+ long size, unsigned long alignment, int flags)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ 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 = end - start;
+ }
+ }
+ if (needed > pool->Free.Size) {
+ 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 && ((long)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->Free.End -= needed;
+ result->End = result->Start + 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, 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,
+ 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(I830RingBuffer));
+ 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 %ld kB for the ring buffer at 0x%lx\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(I830MemRange));
+ 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 %ld kB for Overlay registers at 0x%lx "
+ "(0x%08lx).\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);
+ 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);
+
+ /* Unfortunately this doesn't run on the DRY_RUN pass because our
+ * second head hasn't been created yet..... */
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+ I830EntPtr pI830Ent = pI830->entityPrivate;
+ I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+
+ /* Clear everything first. */
+ memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2));
+ memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2));
+ pI830->FrontBuffer2.Key = -1;
+
+ pI830->FbMemBox2.x1 = 0;
+ pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth;
+ pI830->FbMemBox2.y1 = 0;
+ pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->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 = pI830Ent->pScrn_2->displayWidth * pI8302->cpp;
+ minspace = lineSize * pI830Ent->pScrn_2->virtualY;
+ avail = pI830Ent->pScrn_2->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 - pI830Ent->pScrn_2->virtualY))
+ maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY;
+
+ if (pI8302->CacheLines >= 0) {
+ cacheLines = pI8302->CacheLines;
+ } else {
+#if 1
+ /* Make sure there is enough for two DVD sized YUV buffers */
+ cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384;
+ if (pI830Ent->pScrn_2->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)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth;
+#endif
+ }
+ if (cacheLines > maxCacheLines)
+ cacheLines = maxCacheLines;
+
+ pI830->FbMemBox2.y2 += cacheLines;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocating at least %d scanlines for pixmap cache\n",
+ s, cacheLines);
+
+ tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip &&
+ IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
+ if (tileable) {
+ align = KB(512);
+ alignflags = ALIGN_BOTH_ENDS;
+ } else {
+ align = KB(64);
+ alignflags = 0;
+ }
+
+ size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines);
+ size = ROUND_TO_PAGE(size);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sSecondary framebuffer allocation size: %ld kByte\n", s,
+ size / 1024);
+ alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2),
+ &(pI830->StolenPool), size, align,
+ flags | alignflags |
+ FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR,
+ "Failed to allocate secondary framebuffer.\n");
+ }
+ return FALSE;
+ }
+ }
+
+ /* 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: %ld 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. Is your VideoRAM set too low ??\n");
+ }
+ return FALSE;
+ }
+ } else {
+ long lineSize;
+ long extra = 0;
+ 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(%lx != %lx).\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 %ld "
+ "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sUpdated pixmap cache from %ld scanlines to %ld "
+ "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(I830MemRange));
+ pI830->CursorMem->Key = -1;
+ memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange));
+ pI830->CursorMemARGB->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 %ld kB for HW cursor at 0x%lx", s,
+ alloced / 1024, pI830->CursorMem->Start);
+ if (pI830->CursorNeedsPhysical)
+ xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical);
+ xf86ErrorFVerb(verbosity, "\n");
+ }
+
+ size = HWCURSOR_SIZE_ARGB;
+ cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+ if (pI830->CursorNeedsPhysical)
+ cursFlags |= NEED_PHYSICAL_ADDR;
+
+ alloced = I830AllocVidMem(pScrn, pI830->CursorMemARGB,
+ &(pI830->StolenPool), size,
+ GTT_PAGE_SIZE, flags | cursFlags);
+ if (alloced < size) {
+ if (!dryrun) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate HW (ARGB) cursor space.\n");
+ }
+ } else {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
+ alloced / 1024, pI830->CursorMemARGB->Start);
+ if (pI830->CursorNeedsPhysical)
+ xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMemARGB->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(I830MemRange));
+ pI830->Scratch.Key = -1;
+ memset(&(pI830->Scratch2), 0, sizeof(I830MemRange));
+ pI830->Scratch2.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 %ld kB for the scratch buffer at 0x%lx\n", s,
+ alloced / 1024, pI830->Scratch.Start);
+
+ /* Let's allocate another scratch buffer for the second head */
+ /* Again, this code won't execute on the dry run pass */
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) {
+ size = MAX_SCRATCH_BUFFER_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
+ &(pI830->StolenPool),
+ size, GTT_PAGE_SIZE,
+ flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+ if (alloced < size) {
+ size = MIN_SCRATCH_BUFFER_SIZE;
+ alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2),
+ &(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 second scratch buffer space\n");
+ }
+ return FALSE;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ "%sAllocated %ld kB for the second scratch buffer at 0x%lx\n", s,
+ alloced / 1024, pI830->Scratch2.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);
+ 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 %ld kB for the back buffer at 0x%lx.\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 %ld kB for the depth buffer at 0x%lx.\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 %ld kB for the logical context at 0x%lx.\n", s,
+ alloced / 1024, pI830->ContextMem.Start);
+
+
+ /* 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 512 kBytes for texture space (real %ld kBytes).\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 %ld kB for textures at 0x%lx\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%08lx, size %ld kBytes\n", (void *)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;
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ FixOffset(pScrn, &(pI830->FrontBuffer2));
+ FixOffset(pScrn, &(pI830->FrontBuffer));
+ FixOffset(pScrn, pI830->CursorMem);
+ FixOffset(pScrn, pI830->CursorMemARGB);
+ FixOffset(pScrn, &(pI830->LpRing->mem));
+ FixOffset(pScrn, &(pI830->Scratch));
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ FixOffset(pScrn, &(pI830->Scratch2));
+#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->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;
+ unsigned int fence_pitch;
+
+ 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",nr);
+ return;
+ }
+
+ i830Reg->Fence[nr] = 0;
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+ fence_mask = ~I915G_FENCE_START_MASK;
+ else
+ fence_mask = ~I830_FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: start (0x%08x) is not %s aligned\n",
+ nr, start, (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) ? "1MB" : "512k");
+ 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);
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ switch (size) {
+ case MB(1):
+ val |= I915G_FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= I915G_FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= I915G_FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= I915G_FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= I915G_FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= I915G_FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= I915G_FENCE_SIZE_64M;
+ break;
+ default:
+ xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+ fence_pitch = pitch / 512;
+ else
+ fence_pitch = pitch / 128;
+
+ switch (fence_pitch) {
+ 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 unsigned 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 (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ if (!BindMemRange(pScrn, &(pI830->FrontBuffer2)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
+ return FALSE;
+ if (!BindMemRange(pScrn, pI830->CursorMem))
+ return FALSE;
+ if (!BindMemRange(pScrn, pI830->CursorMemARGB))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
+ return FALSE;
+ if (!BindMemRange(pScrn, &(pI830->Scratch)))
+ return FALSE;
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ if (!BindMemRange(pScrn, &(pI830->Scratch2)))
+ 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->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 (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, pI830->CursorMem))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, pI830->CursorMemARGB))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
+ return FALSE;
+ if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
+ return FALSE;
+ if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
+ if (!UnbindMemRange(pScrn, &(pI830->Scratch2)))
+ 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->TexMem)))
+ return FALSE;
+ }
+#endif
+ if (!xf86ReleaseGART(pScrn->scrnIndex))
+ return FALSE;
+
+ pI830->GttBound = 0;
+ }
+
+ return TRUE;
+}
+
+long
+I830CheckAvailableMemory(ScrnInfoPtr pScrn)
+{
+ AgpInfoPtr agpinf;
+ long 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,
+ "Checking Available AGP Memory: %ld kB available (total %ld kB, used %ld kB)\n",
+ maxPages * 4, agpinf->totalPages * 4, agpinf->usedPages * 4);
+
+ return maxPages * 4;
+}
diff --git a/driver/xf86-video-i810/src/i830_modes.c b/driver/xf86-video-i810/src/i830_modes.c
new file mode 100644
index 000000000..457b583e7
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_modes.c
@@ -0,0 +1,773 @@
+#define DEBUG_VERB 2
+/*
+ * Copyright © 2002 David Dawes
+ *
+ * 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 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
+ * THE AUTHOR(S) 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.
+ *
+ * Except as contained in this notice, the name of the author(s) shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * the author(s).
+ *
+ * Authors: David Dawes <dawes@xfree86.org>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $
+ */
+/*
+ * Modified by Alan Hourihane <alanh@tungstengraphics.com>
+ * to support extended BIOS modes for the Intel chipsets
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "vbe.h"
+#include "vbeModes.h"
+#include "i830.h"
+
+#include <math.h>
+
+#define rint(x) floor(x)
+
+#define MARGIN_PERCENT 1.8 /* % of active vertical image */
+#define CELL_GRAN 8.0 /* assumed character cell granularity */
+#define MIN_PORCH 1 /* minimum front porch */
+#define V_SYNC_RQD 3 /* width of vsync in lines */
+#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */
+#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
+#define M 600.0 /* blanking formula gradient */
+#define C 40.0 /* blanking formula offset */
+#define K 128.0 /* blanking formula scaling factor */
+#define J 20.0 /* blanking formula scaling factor */
+
+/* C' and M' are part of the Blanking Duty Cycle computation */
+
+#define C_PRIME (((C - J) * K/256.0) + J)
+#define M_PRIME (K/256.0 * M)
+
+extern const int i830refreshes[];
+
+static DisplayModePtr
+I830GetGTF (int h_pixels, int v_lines, float freq,
+ int interlaced, int margins)
+{
+ float h_pixels_rnd;
+ float v_lines_rnd;
+ float v_field_rate_rqd;
+ float top_margin;
+ float bottom_margin;
+ float interlace;
+ float h_period_est;
+ float vsync_plus_bp;
+ float v_back_porch;
+ float total_v_lines;
+ float v_field_rate_est;
+ float h_period;
+ float v_field_rate;
+ float v_frame_rate;
+ float left_margin;
+ float right_margin;
+ float total_active_pixels;
+ float ideal_duty_cycle;
+ float h_blank;
+ float total_pixels;
+ float pixel_freq;
+ float h_freq;
+
+ float h_sync;
+ float h_front_porch;
+ float v_odd_front_porch_lines;
+ char modename[20];
+ DisplayModePtr m;
+
+ m = xnfcalloc(sizeof(DisplayModeRec), 1);
+
+
+ /* 1. In order to give correct results, the number of horizontal
+ * pixels requested is first processed to ensure that it is divisible
+ * by the character size, by rounding it to the nearest character
+ * cell boundary:
+ *
+ * [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
+ */
+
+ h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
+
+
+ /* 2. If interlace is requested, the number of vertical lines assumed
+ * by the calculation must be halved, as the computation calculates
+ * the number of vertical lines per field. In either case, the
+ * number of lines is rounded to the nearest integer.
+ *
+ * [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
+ * ROUND([V LINES],0))
+ */
+
+ v_lines_rnd = interlaced ?
+ rint((float) v_lines) / 2.0 :
+ rint((float) v_lines);
+
+ /* 3. Find the frame rate required:
+ *
+ * [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
+ * [I/P FREQ RQD])
+ */
+
+ v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
+
+ /* 4. Find number of lines in Top margin:
+ *
+ * [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
+ * ROUND(([MARGIN%]/100*[V LINES RND]),0),
+ * 0)
+ */
+
+ top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
+
+ /* 5. Find number of lines in Bottom margin:
+ *
+ * [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
+ * ROUND(([MARGIN%]/100*[V LINES RND]),0),
+ * 0)
+ */
+
+ bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0);
+
+ /* 6. If interlace is required, then set variable [INTERLACE]=0.5:
+ *
+ * [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
+ */
+
+ interlace = interlaced ? 0.5 : 0.0;
+
+ /* 7. Estimate the Horizontal period
+ *
+ * [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
+ * ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
+ * [MIN PORCH RND]+[INTERLACE]) * 1000000
+ */
+
+ h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0))
+ / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace)
+ * 1000000.0);
+
+ /* 8. Find the number of lines in V sync + back porch:
+ *
+ * [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
+ */
+
+ vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est);
+
+ /* 9. Find the number of lines in V back porch alone:
+ *
+ * [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
+ *
+ * XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
+ */
+
+ v_back_porch = vsync_plus_bp - V_SYNC_RQD;
+
+ /* 10. Find the total number of lines in Vertical field period:
+ *
+ * [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
+ * [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
+ * [MIN PORCH RND]
+ */
+
+ total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp +
+ interlace + MIN_PORCH;
+
+ /* 11. Estimate the Vertical field frequency:
+ *
+ * [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
+ */
+
+ v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
+
+ /* 12. Find the actual horizontal period:
+ *
+ * [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
+ */
+
+ h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
+
+ /* 13. Find the actual Vertical field frequency:
+ *
+ * [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
+ */
+
+ v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
+
+ /* 14. Find the Vertical frame frequency:
+ *
+ * [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
+ */
+
+ v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
+
+ /* 15. Find number of pixels in left margin:
+ *
+ * [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
+ * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
+ * [CELL GRAN RND]),0)) * [CELL GRAN RND],
+ * 0))
+ */
+
+ left_margin = margins ?
+ rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
+ 0.0;
+
+ /* 16. Find number of pixels in right margin:
+ *
+ * [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
+ * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
+ * [CELL GRAN RND]),0)) * [CELL GRAN RND],
+ * 0))
+ */
+
+ right_margin = margins ?
+ rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN :
+ 0.0;
+
+ /* 17. Find total number of active pixels in image and left and right
+ * margins:
+ *
+ * [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
+ * [RIGHT MARGIN (PIXELS)]
+ */
+
+ total_active_pixels = h_pixels_rnd + left_margin + right_margin;
+
+ /* 18. Find the ideal blanking duty cycle from the blanking duty cycle
+ * equation:
+ *
+ * [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
+ */
+
+ ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
+
+ /* 19. Find the number of pixels in the blanking time to the nearest
+ * double character cell:
+ *
+ * [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
+ * [IDEAL DUTY CYCLE] /
+ * (100-[IDEAL DUTY CYCLE]) /
+ * (2*[CELL GRAN RND])), 0))
+ * * (2*[CELL GRAN RND])
+ */
+
+ h_blank = rint(total_active_pixels *
+ ideal_duty_cycle /
+ (100.0 - ideal_duty_cycle) /
+ (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
+
+ /* 20. Find total number of pixels:
+ *
+ * [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
+ */
+
+ total_pixels = total_active_pixels + h_blank;
+
+ /* 21. Find pixel clock frequency:
+ *
+ * [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
+ */
+
+ pixel_freq = total_pixels / h_period;
+
+ /* 22. Find horizontal frequency:
+ *
+ * [H FREQ] = 1000 / [H PERIOD]
+ */
+
+ h_freq = 1000.0 / h_period;
+
+
+ /* Stage 1 computations are now complete; I should really pass
+ the results to another function and do the Stage 2
+ computations, but I only need a few more values so I'll just
+ append the computations here for now */
+
+
+
+ /* 17. Find the number of pixels in the horizontal sync period:
+ *
+ * [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
+ * [CELL GRAN RND]),0))*[CELL GRAN RND]
+ */
+
+ h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
+
+ /* 18. Find the number of pixels in the horizontal front porch period:
+ *
+ * [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
+ */
+
+ h_front_porch = (h_blank / 2.0) - h_sync;
+
+ /* 36. Find the number of lines in the odd front porch period:
+ *
+ * [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
+ */
+
+ v_odd_front_porch_lines = MIN_PORCH + interlace;
+
+ /* finally, pack the results in the DisplayMode struct */
+
+ m->HDisplay = (int) (h_pixels_rnd);
+ m->HSyncStart = (int) (h_pixels_rnd + h_front_porch);
+ m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync);
+ m->HTotal = (int) (total_pixels);
+
+ m->VDisplay = (int) (v_lines_rnd);
+ m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines);
+ m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
+ m->VTotal = (int) (total_v_lines);
+
+ m->Clock = (int)(pixel_freq * 1000);
+ m->SynthClock = m->Clock;
+ m->HSync = h_freq;
+ m->VRefresh = freq;
+
+ snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
+ m->name = xnfstrdup(modename);
+
+ return (m);
+}
+
+static DisplayModePtr
+CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id,
+ int flags)
+{
+ CARD16 major, minor;
+ VbeModeInfoBlock *mode;
+ DisplayModePtr p = NULL, pMode = NULL;
+ VbeModeInfoData *data;
+ Bool modeOK = FALSE;
+ ModeStatus status = MODE_OK;
+
+ major = (unsigned)(vbe->VESAVersion >> 8);
+ minor = vbe->VESAVersion & 0xff;
+
+ if ((mode = VBEGetModeInfo(pVbe, id)) == NULL)
+ return NULL;
+
+ /* Does the mode match the depth/bpp? */
+ /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */
+ if (VBE_MODE_USABLE(mode, flags) &&
+ ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) ||
+ (mode->BitsPerPixel > 8 &&
+ (mode->RedMaskSize + mode->GreenMaskSize +
+ mode->BlueMaskSize) == pScrn->depth &&
+ mode->BitsPerPixel == pScrn->bitsPerPixel) ||
+ (mode->BitsPerPixel == 15 && pScrn->depth == 15) ||
+ (mode->BitsPerPixel <= 8 &&
+ mode->BitsPerPixel == pScrn->bitsPerPixel))) {
+ modeOK = TRUE;
+ xf86ErrorFVerb(DEBUG_VERB, "*");
+ }
+
+ if (mode->XResolution && mode->YResolution &&
+ !I830CheckModeSupport(pScrn, mode->XResolution, mode->YResolution, id))
+ modeOK = FALSE;
+
+
+ /*
+ * Check if there's a valid monitor mode that this one can be matched
+ * up with from the 'specified' modes list.
+ */
+ if (modeOK) {
+ for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
+ if ((p->type != 0) ||
+ (p->HDisplay != mode->XResolution) ||
+ (p->VDisplay != mode->YResolution) ||
+ (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+ status = xf86CheckModeForMonitor(p, pScrn->monitor);
+ if (status == MODE_OK) {
+ modeOK = TRUE;
+ break;
+ }
+ }
+ if (p) {
+ pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
+ memcpy((char*)pMode,(char*)p,sizeof(DisplayModeRec));
+ pMode->name = xnfstrdup(p->name);
+ }
+ }
+
+ /*
+ * Now, check if there's a valid monitor mode that this one can be matched
+ * up with from the default modes list. i.e. VESA modes in xf86DefModes.c
+ */
+ if (modeOK && !pMode) {
+ int refresh = 0, calcrefresh = 0;
+ DisplayModePtr newMode = NULL;
+
+ for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
+ calcrefresh = (int)(((double)(p->Clock * 1000) /
+ (double)(p->HTotal * p->VTotal)) * 100);
+ if ((p->type != M_T_DEFAULT) ||
+ (p->HDisplay != mode->XResolution) ||
+ (p->VDisplay != mode->YResolution) ||
+ (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+ continue;
+ status = xf86CheckModeForMonitor(p, pScrn->monitor);
+ if (status == MODE_OK) {
+ if (calcrefresh > refresh) {
+ refresh = calcrefresh;
+ newMode = p;
+ }
+ modeOK = TRUE;
+ }
+ }
+ if (newMode) {
+ pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
+ memcpy((char*)pMode,(char*)newMode,sizeof(DisplayModeRec));
+ pMode->name = xnfstrdup(newMode->name);
+ }
+ }
+
+ /*
+ * Check if there's a valid monitor mode that this one can be matched
+ * up with. The actual matching is done later.
+ */
+ if (modeOK && !pMode) {
+ float vrefresh = 0.0f;
+ int i;
+
+ for (i=0;i<pScrn->monitor->nVrefresh;i++) {
+
+ for (vrefresh = pScrn->monitor->vrefresh[i].hi;
+ vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) {
+
+ if (vrefresh != (float)0.0f) {
+ float best_vrefresh;
+ int int_vrefresh;
+
+ /* Find the best refresh for the Intel chipsets */
+ int_vrefresh = I830GetBestRefresh(pScrn, (int)vrefresh);
+ best_vrefresh = (float)i830refreshes[int_vrefresh];
+
+ /* Now, grab the best mode from the available refresh */
+ pMode = I830GetGTF(mode->XResolution, mode->YResolution,
+ best_vrefresh, 0, 0);
+
+ pMode->type = M_T_BUILTIN;
+
+ status = xf86CheckModeForMonitor(pMode, pScrn->monitor);
+ if (status == MODE_OK) {
+ if (major >= 3) {
+ if (pMode->Clock * 1000 <= mode->MaxPixelClock)
+ modeOK = TRUE;
+ else
+ modeOK = FALSE;
+ } else
+ modeOK = TRUE;
+ } else
+ modeOK = FALSE;
+ pMode->status = status;
+ } else {
+ modeOK = FALSE;
+ }
+ if (modeOK) break;
+ }
+ if (modeOK) break;
+ }
+ }
+
+ xf86ErrorFVerb(DEBUG_VERB,
+ "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " ModeAttributes: 0x%x\n", mode->ModeAttributes);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinAAttributes: 0x%x\n", mode->WinAAttributes);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinBAttributes: 0x%x\n", mode->WinBAttributes);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinGranularity: %d\n", mode->WinGranularity);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinSize: %d\n", mode->WinSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinASegment: 0x%x\n", mode->WinASegment);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinBSegment: 0x%x\n", mode->WinBSegment);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " WinFuncPtr: 0x%lx\n", mode->WinFuncPtr);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BytesPerScanline: %d\n", mode->BytesPerScanline);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " XResolution: %d\n", mode->XResolution);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " YResolution: %d\n", mode->YResolution);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " XCharSize: %d\n", mode->XCharSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " YCharSize: %d\n", mode->YCharSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " NumberOfPlanes: %d\n", mode->NumberOfPlanes);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BitsPerPixel: %d\n", mode->BitsPerPixel);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " NumberOfBanks: %d\n", mode->NumberOfBanks);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " MemoryModel: %d\n", mode->MemoryModel);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BankSize: %d\n", mode->BankSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " NumberOfImages: %d\n", mode->NumberOfImages);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " RedMaskSize: %d\n", mode->RedMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " RedFieldPosition: %d\n", mode->RedFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " GreenMaskSize: %d\n", mode->GreenMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " GreenFieldPosition: %d\n", mode->GreenFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BlueMaskSize: %d\n", mode->BlueMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BlueFieldPosition: %d\n", mode->BlueFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " RsvdMaskSize: %d\n", mode->RsvdMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
+ if (major >= 2) {
+ xf86ErrorFVerb(DEBUG_VERB,
+ " PhysBasePtr: 0x%lx\n", mode->PhysBasePtr);
+ if (major >= 3) {
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinRedMaskSize: %d\n", mode->LinRedMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
+ xf86ErrorFVerb(DEBUG_VERB,
+ " MaxPixelClock: %ld\n", mode->MaxPixelClock);
+ }
+ }
+
+ if (!modeOK) {
+ VBEFreeModeInfo(mode);
+ if (pMode)
+ xfree(pMode);
+ return NULL;
+ }
+
+ pMode->status = MODE_OK;
+ pMode->type = M_T_BUILTIN;
+
+ /* for adjust frame */
+ pMode->HDisplay = mode->XResolution;
+ pMode->VDisplay = mode->YResolution;
+
+ data = xnfcalloc(sizeof(VbeModeInfoData), 1);
+ data->mode = id;
+ data->data = mode;
+ pMode->PrivSize = sizeof(VbeModeInfoData);
+ pMode->Private = (INT32*)data;
+ pMode->next = NULL;
+ return pMode;
+}
+
+/*
+ * Check the available BIOS modes, and extract those that match the
+ * requirements into the modePool. Note: modePool is a NULL-terminated
+ * list.
+ */
+
+DisplayModePtr
+I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe)
+{
+ DisplayModePtr pMode, p = NULL, modePool = NULL;
+ int i = 0;
+
+ for (i = 0; i < 0x7F; i++) {
+ if ((pMode = CheckMode(pScrn, pVbe, vbe, i, V_MODETYPE_VGA)) != NULL) {
+ ModeStatus status = MODE_OK;
+
+ /* Check the mode against a specified virtual size (if any) */
+ if (pScrn->display->virtualX > 0 &&
+ pMode->HDisplay > pScrn->display->virtualX) {
+ status = MODE_VIRTUAL_X;
+ }
+ if (pScrn->display->virtualY > 0 &&
+ pMode->VDisplay > pScrn->display->virtualY) {
+ status = MODE_VIRTUAL_Y;
+ }
+ if (status != MODE_OK) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Not using mode \"%dx%d\" (%s)\n",
+ pMode->HDisplay, pMode->VDisplay,
+ xf86ModeStatusToString(status));
+ } else {
+ if (p == NULL) {
+ modePool = pMode;
+ } else {
+ p->next = pMode;
+ }
+ pMode->prev = NULL;
+ p = pMode;
+ }
+ }
+ }
+ return modePool;
+}
+
+/*
+ * Go through the monitor modes and selecting the best set of
+ * parameters for each BIOS mode. Note: This is only supported in
+ * VBE version 3.0 or later.
+ */
+void
+I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe)
+{
+ DisplayModePtr pMode;
+ VbeModeInfoData *data;
+
+ pMode = pScrn->modes;
+ do {
+ int clock;
+
+ data = (VbeModeInfoData*)pMode->Private;
+ data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1);
+ data->block->HorizontalTotal = pMode->HTotal;
+ data->block->HorizontalSyncStart = pMode->HSyncStart;
+ data->block->HorizontalSyncEnd = pMode->HSyncEnd;
+ data->block->VerticalTotal = pMode->VTotal;
+ data->block->VerticalSyncStart = pMode->VSyncStart;
+ data->block->VerticalSyncEnd = pMode->VSyncEnd;
+ data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
+ ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
+ data->block->PixelClock = pMode->Clock * 1000;
+ /* XXX May not have this. */
+ clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
+ if (clock)
+ data->block->PixelClock = clock;
+#ifdef DEBUG
+ ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n",
+ (double)data->block->PixelClock / 1000000.0,
+ (double)clock / 1000000.0);
+#endif
+ data->mode |= (1 << 11);
+ if (pMode->VRefresh != 0) {
+ data->block->RefreshRate = pMode->VRefresh * 100;
+ } else {
+ data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/
+ (double)(pMode->HTotal * pMode->VTotal)) * 100);
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n",
+ (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode);
+#ifdef DEBUG
+ ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - "
+ " %i %i %i %i %.2f MHz Refresh: %.2f Hz\n",
+ data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart,
+ pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay,
+ pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal,
+ (double)data->block->PixelClock/1000000.0,
+ (double)data->block->RefreshRate/100);
+#endif
+ pMode = pMode->next;
+ } while (pMode != pScrn->modes);
+}
+
+void
+I830PrintModes(ScrnInfoPtr scrp)
+{
+ DisplayModePtr p;
+ float hsync, refresh = 0;
+ char *desc, *desc2, *prefix, *uprefix;
+
+ if (scrp == NULL)
+ return;
+
+ xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d "
+ "(pitch %d)\n", scrp->virtualX, scrp->virtualY,
+ scrp->displayWidth);
+
+ p = scrp->modes;
+ if (p == NULL)
+ return;
+
+ do {
+ desc = desc2 = "";
+ if (p->HSync > 0.0)
+ hsync = p->HSync;
+ else if (p->HTotal > 0)
+ hsync = (float)p->Clock / (float)p->HTotal;
+ else
+ hsync = 0.0;
+ if (p->VTotal > 0)
+ refresh = hsync * 1000.0 / p->VTotal;
+ if (p->Flags & V_INTERLACE) {
+ refresh *= 2.0;
+ desc = " (I)";
+ }
+ if (p->Flags & V_DBLSCAN) {
+ refresh /= 2.0;
+ desc = " (D)";
+ }
+ if (p->VScan > 1) {
+ refresh /= p->VScan;
+ desc2 = " (VScan)";
+ }
+ if (p->VRefresh > 0.0)
+ refresh = p->VRefresh;
+ if (p->type & M_T_BUILTIN)
+ prefix = "Built-in mode";
+ else if (p->type & M_T_DEFAULT)
+ prefix = "Default mode";
+ else
+ prefix = "Mode";
+ if (p->type & M_T_USERDEF)
+ uprefix = "*";
+ else
+ uprefix = " ";
+ if (p->name)
+ xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
+ "%s%s \"%s\"\n", uprefix, prefix, p->name);
+ else
+ xf86DrvMsg(scrp->scrnIndex, X_PROBED,
+ "%s%s %dx%d (unnamed)\n",
+ uprefix, prefix, p->HDisplay, p->VDisplay);
+ p = p->next;
+ } while (p != NULL && p != scrp->modes);
+}
diff --git a/driver/xf86-video-i810/src/i830_shadow.c b/driver/xf86-video-i810/src/i830_shadow.c
new file mode 100644
index 000000000..93c72c591
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_shadow.c
@@ -0,0 +1,253 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_shadow.c,v 1.3 2000/03/31 20:13:33 dawes Exp $ */
+
+/*
+ Copyright (c) 1999,2000 The XFree86 Project Inc.
+ based on code written by Mark Vojkovich <markv@valinux.com>
+*/
+
+/*
+ * Ported from the savage driver to the I830 by
+ * Helmar Spangenberg <hspangenberg@frey.de> and Dima Dorfman
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "shadowfb.h"
+#include "servermd.h"
+
+
+void
+I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int width, height, Bpp, FBPitch;
+ unsigned char *src, *dst;
+
+ Bpp = pScrn->bitsPerPixel >> 3;
+ FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+
+ while(num--) {
+ width = (pbox->x2 - pbox->x1) * Bpp;
+ height = pbox->y2 - pbox->y1;
+ src = pI830->shadowPtr + (pbox->y1 * pI830->shadowPitch) +
+ (pbox->x1 * Bpp);
+ dst = pI830->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
+
+ while(height--) {
+ memcpy(dst, src, width);
+ dst += FBPitch;
+ src += pI830->shadowPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+void
+I830PointerMoved(int index, int x, int y)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int newX, newY;
+
+ if(pI830->rotate == 1) {
+ newX = pScrn->pScreen->height - y - 1;
+ newY = x;
+ } else {
+ newX = y;
+ newY = pScrn->pScreen->width - x - 1;
+ }
+
+ (*pI830->PointerMoved)(index, newX, newY);
+}
+
+void
+I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pI830->rotate * pI830->shadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* in dwords */
+
+ if(pI830->rotate == 1) {
+ dstPtr = pI830->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = pI830->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = pI830->shadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[srcPitch * 3] << 24);
+ src += srcPitch * 4;
+ }
+ srcPtr += pI830->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+void
+I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD16 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pI830->rotate * pI830->shadowPitch >> 1;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~1;
+ y2 = (pbox->y2 + 1) & ~1;
+ height = (y2 - y1) >> 1; /* in dwords */
+
+ if(pI830->rotate == 1) {
+ dstPtr = (CARD16*)pI830->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = (CARD16*)pI830->shadowPtr +
+ ((1 - y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD16*)pI830->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
+ srcPtr = (CARD16*)pI830->shadowPtr +
+ (y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 16);
+ src += srcPitch * 2;
+ }
+ srcPtr += pI830->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+
+/* this one could be faster */
+void
+I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int count, width, height, y1, y2, dstPitch, srcPitch;
+ CARD8 *dstPtr, *srcPtr, *src;
+ CARD32 *dst;
+
+ dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
+ srcPitch = -pI830->rotate * pI830->shadowPitch;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ y1 = pbox->y1 & ~3;
+ y2 = (pbox->y2 + 3) & ~3;
+ height = (y2 - y1) >> 2; /* blocks of 3 dwords */
+
+ if(pI830->rotate == 1) {
+ dstPtr = pI830->FbBase +
+ (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
+ srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
+ } else {
+ dstPtr = pI830->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
+ srcPtr = pI830->shadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
+ (src[srcPitch] << 24);
+ dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[(srcPitch * 2) + 1] << 24);
+ dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
+ (src[(srcPitch * 3) + 1] << 16) |
+ (src[(srcPitch * 3) + 2] << 24);
+ dst += 3;
+ src += srcPitch * 4;
+ }
+ srcPtr += pI830->rotate * 3;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
+
+void
+I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int count, width, height, dstPitch, srcPitch;
+ CARD32 *dstPtr, *srcPtr, *src, *dst;
+
+ dstPitch = pScrn->displayWidth;
+ srcPitch = -pI830->rotate * pI830->shadowPitch >> 2;
+
+ while(num--) {
+ width = pbox->x2 - pbox->x1;
+ height = pbox->y2 - pbox->y1;
+
+ if(pI830->rotate == 1) {
+ dstPtr = (CARD32*)pI830->FbBase +
+ (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
+ srcPtr = (CARD32*)pI830->shadowPtr +
+ ((1 - pbox->y2) * srcPitch) + pbox->x1;
+ } else {
+ dstPtr = (CARD32*)pI830->FbBase +
+ ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
+ srcPtr = (CARD32*)pI830->shadowPtr +
+ (pbox->y1 * srcPitch) + pbox->x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = *src;
+ src += srcPitch;
+ }
+ srcPtr += pI830->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
+ }
+}
diff --git a/driver/xf86-video-i810/src/i830_video.c b/driver/xf86-video-i810/src/i830_video.c
new file mode 100644
index 000000000..12c25e054
--- /dev/null
+++ b/driver/xf86-video-i810/src/i830_video.c
@@ -0,0 +1,2128 @@
+#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.11tsi 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@xfree86.org>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 <X11/extensions/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, xvPipe;
+static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
+
+#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 CLONE_ATTRIBUTES 1
+static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = {
+ {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
+};
+
+#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 GAMMA_ATTRIBUTES 6
+static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = {
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
+ {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
+};
+
+#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 YBuf0offset;
+ CARD32 UBuf0offset;
+ CARD32 VBuf0offset;
+
+ CARD32 YBuf1offset;
+ CARD32 UBuf1offset;
+ CARD32 VBuf1offset;
+
+ unsigned char currentBuf;
+
+ int brightness;
+ int contrast;
+ int pipe;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ CARD32 gamma0;
+ CARD32 gamma1;
+ CARD32 gamma2;
+ CARD32 gamma3;
+ CARD32 gamma4;
+ CARD32 gamma5;
+
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ FBLinearPtr linear;
+
+ Bool overlayOK;
+ int oneLineMode;
+ int scaleRatio;
+} I830PortPrivRec, *I830PortPrivPtr;
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr)
+
+#if VIDEO_DEBUG
+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");
+}
+#endif
+
+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);
+
+ 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 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
+ 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.
+ */
+ overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
+ if (pPriv->pipe == 0)
+ overlay->OCONFIG |= OVERLAY_PIPE_A;
+ else
+ overlay->OCONFIG |= OVERLAY_PIPE_B;
+
+ overlay->OCMD = YUV_420;
+
+#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
+}
+
+#define PFIT_CONTROLS 0x61230
+#define PFIT_AUTOVSCALE_MASK 0x200
+#define PFIT_ON_MASK 0x80000000
+#define PFIT_AUTOSCALE_RATIO 0x61238
+#define PFIT_PROGRAMMED_SCALE_RATIO 0x61234
+
+static void
+I830SetOneLineModeRatio(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+ CARD32 panelFitControl = INREG(PFIT_CONTROLS);
+ int vertScale;
+
+ pPriv->scaleRatio = 0x10000;
+
+ if (panelFitControl & PFIT_ON_MASK) {
+ if (panelFitControl & PFIT_AUTOVSCALE_MASK) {
+ vertScale = INREG(PFIT_AUTOSCALE_RATIO) >> 16;
+ } else {
+ vertScale = INREG(PFIT_PROGRAMMED_SCALE_RATIO) >> 16;
+ }
+
+ if (vertScale != 0)
+ pPriv->scaleRatio = ((double) 0x10000 / (double)vertScale) * 0x10000;
+
+ pPriv->oneLineMode = TRUE;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Xvideo one-line mode\n");
+ }
+
+ if (pPriv->scaleRatio == 0x10000)
+ pPriv->oneLineMode = FALSE;
+}
+
+static void
+I830UpdateGamma(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
+
+ OUTREG(OGAMC5, pPriv->gamma5);
+ OUTREG(OGAMC4, pPriv->gamma4);
+ OUTREG(OGAMC3, pPriv->gamma3);
+ OUTREG(OGAMC2, pPriv->gamma2);
+ OUTREG(OGAMC1, pPriv->gamma1);
+ OUTREG(OGAMC0, pPriv->gamma0);
+}
+
+static XF86VideoAdaptorPtr
+I830SetupImageVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ I830PortPrivPtr pPriv;
+ XF86AttributePtr att;
+
+ 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) 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->nAttributes = NUM_ATTRIBUTES;
+ if (pI830->Clone)
+ adapt->nAttributes += CLONE_ATTRIBUTES;
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+ adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
+ adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
+ /* Now copy the attributes */
+ att = adapt->pAttributes;
+ memcpy((char *)att, (char*)Attributes, sizeof(XF86AttributeRec)* NUM_ATTRIBUTES);
+ att+=NUM_ATTRIBUTES;
+ if (pI830->Clone) {
+ memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
+ att+=CLONE_ATTRIBUTES;
+ }
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
+ att+=GAMMA_ATTRIBUTES;
+ }
+ adapt->nImages = NUM_IMAGES;
+ 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->pipe = pI830->pipe; /* default to current pipe */
+ pPriv->linear = NULL;
+ pPriv->currentBuf = 0;
+ pPriv->gamma5 = 0xc0c0c0;
+ pPriv->gamma4 = 0x808080;
+ pPriv->gamma3 = 0x404040;
+ pPriv->gamma2 = 0x202020;
+ pPriv->gamma1 = 0x101010;
+ pPriv->gamma0 = 0x080808;
+
+ /* gotta uninit this someplace */
+ REGION_NULL(pScreen, &pPriv->clip);
+
+ pI830->adaptor = adapt;
+
+ /* With LFP's we need to detect whether we're in One Line Mode, which
+ * essentially means a resolution greater than 1024x768, and fix up
+ * the scaler accordingly. */
+ pPriv->scaleRatio = 0x10000;
+ pPriv->oneLineMode = FALSE;
+
+ /*
+ * Initialise pPriv->overlayOK. Set it to TRUE here so that a warning will
+ * be generated if I830VideoSwitchModeAfter() sets it to FALSE.
+ */
+ pPriv->overlayOK = TRUE;
+ 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");
+
+ /* Allow the pipe to be switched from pipe A to B when in clone mode */
+ if (pI830->Clone)
+ xvPipe = MAKE_ATOM("XV_PIPE");
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ xvGamma0 = MAKE_ATOM("XV_GAMMA0");
+ xvGamma1 = MAKE_ATOM("XV_GAMMA1");
+ xvGamma2 = MAKE_ATOM("XV_GAMMA2");
+ xvGamma3 = MAKE_ATOM("XV_GAMMA3");
+ xvGamma4 = MAKE_ATOM("XV_GAMMA4");
+ xvGamma5 = MAKE_ATOM("XV_GAMMA5");
+ }
+
+ I830ResetVideo(pScrn);
+
+ I830UpdateGamma(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 (pI830->entityPrivate)
+ pI830->entityPrivate->XvInUse = -1;
+ }
+ 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->overlayOK)
+ 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->overlayOK)
+ OVERLAY_UPDATE;
+ } else if (pI830->Clone && attribute == xvPipe) {
+ if ((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->pipe = value;
+ /*
+ * Select which pipe the overlay is enabled on.
+ */
+ overlay->OCONFIG &= ~OVERLAY_PIPE_MASK;
+ if (pPriv->pipe == 0)
+ overlay->OCONFIG |= OVERLAY_PIPE_A;
+ else
+ overlay->OCONFIG |= OVERLAY_PIPE_B;
+ if (pPriv->overlayOK)
+ OVERLAY_UPDATE;
+ } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ /* Avoid video anomalies, so set gamma registers when overlay is off */
+ /* We also clamp the values if they are outside the ranges */
+ if (!*pI830->overlayOn) {
+ pPriv->gamma0 = value;
+ if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
+ pPriv->gamma1 = pPriv->gamma0 + 0x7d;
+ } else
+ return BadRequest;
+ } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ if (!*pI830->overlayOn) {
+ pPriv->gamma1 = value;
+ if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
+ pPriv->gamma0 = pPriv->gamma1 - 0x7d;
+ } else
+ return BadRequest;
+ } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ if (!*pI830->overlayOn) {
+ pPriv->gamma2 = value;
+ if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
+ pPriv->gamma3 = pPriv->gamma2 + 0x7d;
+ } else
+ return BadRequest;
+ } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ if (!*pI830->overlayOn) {
+ pPriv->gamma3 = value;
+ if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
+ pPriv->gamma2 = pPriv->gamma3 - 0x7d;
+ } else
+ return BadRequest;
+ } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ if (!*pI830->overlayOn) {
+ pPriv->gamma4 = value;
+ if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
+ pPriv->gamma5 = pPriv->gamma4 + 0x7d;
+ } else
+ return BadRequest;
+ } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ if (!*pI830->overlayOn) {
+ pPriv->gamma5 = value;
+ if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
+ pPriv->gamma4 = pPriv->gamma5 - 0x7d;
+ } else
+ return BadRequest;
+ } 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->overlayOK)
+ OVERLAY_UPDATE;
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else
+ return BadMatch;
+
+ /* We've already confirmed that the overlay is off, ready for updating */
+ if ((attribute == xvGamma0 ||
+ attribute == xvGamma1 ||
+ attribute == xvGamma2 ||
+ attribute == xvGamma3 ||
+ attribute == xvGamma4 ||
+ attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ I830UpdateGamma(pScrn);
+ }
+
+ return Success;
+}
+
+static int
+I830GetPortAttribute(ScrnInfoPtr pScrn,
+ Atom attribute, INT32 * value, pointer data)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
+
+ if (attribute == xvBrightness) {
+ *value = pPriv->brightness;
+ } else if (attribute == xvContrast) {
+ *value = pPriv->contrast;
+ } else if (pI830->Clone && attribute == xvPipe) {
+ *value = pPriv->pipe;
+ } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma0;
+ } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma1;
+ } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma2;
+ } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma3;
+ } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma4;
+ } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+ *value = pPriv->gamma5;
+ } 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 srcPitch2, 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;
+
+ ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
+ "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, 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 += srcPitch2;
+ dst2 += dstPitch;
+ }
+
+ /* Copy U data for YV12, or V data for I420 */
+ src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) +
+ ((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 += srcPitch2;
+ 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;
+ unsigned int mask, shift, offsety, offsetu;
+
+ ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
+ dstPitch);
+
+ if (!pPriv->overlayOK)
+ return;
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830)) {
+ shift = 6;
+ mask = 0x3f;
+ } else {
+ shift = 5;
+ mask = 0x1f;
+ }
+
+ if (pPriv->currentBuf == 0) {
+ offsety = pPriv->YBuf0offset;
+ offsetu = pPriv->UBuf0offset;
+ } else {
+ offsety = pPriv->YBuf1offset;
+ offsetu = pPriv->UBuf1offset;
+ }
+
+#if VIDEO_DEBUG
+ CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
+#endif
+
+ /* When in dual head with different bpp setups we need to refresh the
+ * color key, so let's reset the video parameters and refresh here */
+#if 0
+ if (pI830->entityPrivate)
+#endif
+ I830ResetVideo(pScrn);
+
+ switch (id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ swidth = width;
+
+ overlay->SWIDTH = swidth;
+ swidth /= 2;
+ overlay->SWIDTH |= (swidth & 0x7ff) << 16;
+
+ swidth = ((offsety + width + mask) >> shift) -
+ (offsety >> shift);
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830))
+ swidth <<= 1;
+
+ swidth -= 1;
+
+ ErrorF("Y width is %d, swidth is %d\n", width, swidth);
+
+ overlay->SWIDTHSW = swidth << 2;
+
+ swidth = ((offsetu + (width / 2) + mask) >> shift) -
+ (offsetu >> shift);
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830))
+ swidth <<= 1;
+
+ swidth -= 1;
+
+ ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth);
+
+ overlay->SWIDTHSW |= swidth << 18;
+
+ ErrorF("HEIGHT is %d\n",height);
+
+ overlay->SHEIGHT = height | ((height / 2) << 16);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ swidth = width;
+ overlay->SWIDTH = swidth;
+
+ ErrorF("Y width is %d\n", swidth);
+
+ swidth = ((offsety + (width << 1) + mask) >> shift) -
+ (offsety >> shift);
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830))
+ swidth <<= 1;
+
+ swidth -= 1;
+
+ ErrorF("swidthsw is %d\n", swidth);
+
+ overlay->SWIDTHSW = swidth << 2;
+
+ ErrorF("HEIGHT is %d\n",height);
+
+ overlay->SHEIGHT = height;
+ break;
+ }
+
+ if (pPriv->oneLineMode) {
+ /* change the coordinates with panel fitting active */
+ dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
+ dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
+
+ /* Now, alter the height, so we scale to the correct size */
+ drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
+
+ /* Keep the engine happy */
+ if (dstBox->y1 < 0) dstBox->y1 = 0;
+ if (dstBox->y2 < 0) dstBox->y2 = 0;
+ }
+
+
+ overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
+
+ overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) |
+ (dstBox->x2 - dstBox->x1);
+
+ ErrorF("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", dstBox->x1, dstBox->y1,
+ dstBox->x2, dstBox->y2);
+
+ /* buffer locations */
+ overlay->OBUF_0Y = pPriv->YBuf0offset;
+ overlay->OBUF_0U = pPriv->UBuf0offset;
+ overlay->OBUF_0V = pPriv->VBuf0offset;
+
+ overlay->OBUF_1Y = pPriv->YBuf1offset;
+ 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 - 1) << 12) / drw_w;
+ yscaleFract = ((src_h - 1) << 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: %x.%03x, yscale: %x.%03x\n", xscaleInt,
+ xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF);
+ ErrorF("UV xscale: %x.%03x, UV yscale: %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, srcPitch2 = 0, 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);
+
+ if (pI830->entityPrivate) {
+ if (pI830->entityPrivate->XvInUse != -1 &&
+ pI830->entityPrivate->XvInUse != pPriv->pipe) {
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ return Success; /* faked for trying to share it */
+ } else
+#endif
+ {
+ return BadAlloc;
+ }
+ }
+
+ pI830->entityPrivate->XvInUse = pPriv->pipe;
+ }
+
+ /* overlay limits */
+ if(src_w > (drw_w * 7))
+ drw_w = src_w * 7;
+
+ if(src_h > (drw_h * 7))
+ drw_h = src_h * 7;
+
+ /* 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;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ dstPitch = ((width / 2) + 63) & ~63; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = width << 1;
+ dstPitch = (srcPitch + 63) & ~63; /* of chroma */
+ size = dstPitch * height;
+ break;
+ }
+ ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
+
+ /* size is multiplied by 2 because we have two buffers that are flipping */
+ 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, srcPitch2, 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 */
+ if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->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;
+ 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;
+ 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;
+
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->XvInUse = -1;
+ }
+ } 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;
+
+ if (pI830->entityPrivate)
+ pI830->entityPrivate->XvInUse = -1;
+
+ 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");
+
+ if (pI830->entityPrivate) {
+ if (pI830->entityPrivate->XvInUse != -1 &&
+ pI830->entityPrivate->XvInUse != pI830Priv->pipe) {
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ return Success; /* faked for trying to share it */
+ } else
+#endif
+ {
+ return BadAlloc;
+ }
+ }
+
+ pI830->entityPrivate->XvInUse = pI830Priv->pipe;
+ }
+
+ 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;
+
+ 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;
+
+ if (!I830PTR(pScrn)->adaptor) {
+ return;
+ }
+
+ pPriv = GET_PORT_PRIVATE(pScrn);
+
+ if (!pPriv) {
+ xf86ErrorF("pPriv isn't set\n");
+ return;
+ }
+
+ /* We stop the video when mode switching, just so we don't lockup
+ * the engine. The overlayOK will determine whether we can re-enable
+ * with the current video on completion of the mode switch.
+ */
+ I830StopVideo(pScrn, pPriv, TRUE);
+
+ pPriv->oneLineMode = FALSE;
+}
+
+void
+I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830PortPrivPtr pPriv;
+ int size, hsize, vsize, active;
+
+ if (!pI830->adaptor) {
+ return;
+ }
+ pPriv = GET_PORT_PRIVATE(pScrn);
+ if (!pPriv)
+ return;
+
+ if (pPriv->pipe == 0) {
+ if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling XVideo output because Pipe A is in double-wide mode.\n");
+ pPriv->overlayOK = FALSE;
+ } else if (!pPriv->overlayOK) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n");
+ pPriv->overlayOK = TRUE;
+ }
+ }
+
+ if (pPriv->pipe == 1) {
+ if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Disabling XVideo output because Pipe B is in double-wide mode.\n");
+ pPriv->overlayOK = FALSE;
+ } else if (!pPriv->overlayOK) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n");
+ pPriv->overlayOK = TRUE;
+ }
+ }
+
+ /* Check we have an LFP connected */
+ if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) ||
+ (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) {
+ size = pI830->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
+ hsize = (size >> 16) & 0x7FF;
+ vsize = size & 0x7FF;
+ active = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+
+ if (vsize < active && hsize > 1024)
+ I830SetOneLineModeRatio(pScrn);
+
+ if (pPriv->scaleRatio & 0xFFFE0000) {
+ /* Possible bogus ratio, using in-accurate fallback */
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Bogus panel fit register, Xvideo positioning may not be accurate.\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Using fallback ratio - was 0x%x, now 0x%x\n", pPriv->scaleRatio, (int)(((float)active * 65536)/(float)vsize));
+
+
+ pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize);
+ }
+ }
+}
diff --git a/driver/xf86-video-i810/src/xvmc/.cvsignore b/driver/xf86-video-i810/src/xvmc/.cvsignore
new file mode 100644
index 000000000..9730646fd
--- /dev/null
+++ b/driver/xf86-video-i810/src/xvmc/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
diff --git a/driver/xf86-video-i810/src/xvmc/I810XvMC.c b/driver/xf86-video-i810/src/xvmc/I810XvMC.c
new file mode 100644
index 000000000..89aa3ea4b
--- /dev/null
+++ b/driver/xf86-video-i810/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.10 2002/10/30 12:52:01 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 <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/XvMClib.h>
+#include "I810XvMC.h"
+
+static int error_base;
+static int event_base;
+
+/***************************************************************************
+// Function: i810_get_free_buffer
+// Description: Allocates a free dma page using kernel ioctls, then
+// programs the data into the already allocated dma buffer list.
+// Arguments: pI810XvMC private data structure from the current context.
+// Notes: We faked the drmMapBufs for the i810's security so now we have
+// to insert an allocated page into the correct spot in the faked
+// list to keep up appearences.
+// Concept for this function was taken from Mesa sources.
+// Returns: drmBufPtr containing the information about the allocated page.
+***************************************************************************/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) {
+ drmI810DMA dma;
+ drmBufPtr buf;
+
+ dma.granted = 0;
+ dma.request_size = 4096;
+ while(!dma.granted) {
+ if(GET_BUFFER(pI810XvMC, dma) || !dma.granted)
+ FLUSH(pI810XvMC);
+ } /* No DMA granted */
+
+ buf = &(pI810XvMC->dmabufs->list[dma.request_idx]);
+ buf->idx = dma.request_idx;
+ buf->used = 0;
+ buf->total = dma.request_size;
+ buf->address = (drmAddress)dma.virtual;
+ return buf;
+}
+
+/***************************************************************************
+// Function: free_privContext
+// Description: Free's the private context structure if the reference
+// count is 0.
+***************************************************************************/
+void i810_free_privContext(i810XvMCContext *pI810XvMC) {
+
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+
+ pI810XvMC->ref--;
+ if(!pI810XvMC->ref) {
+ drmUnmapBufs(pI810XvMC->dmabufs);
+ drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size);
+ drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size);
+ drmClose(pI810XvMC->fd);
+
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ }
+
+ I810_UNLOCK(pI810XvMC);
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateContext
+// Description: Create a XvMC context for the given surface parameters.
+// Arguments:
+// display - Connection to the X server.
+// port - XvPortID to use as avertised by the X connection.
+// surface_type_id - Unique identifier for the Surface type.
+// width - Width of the surfaces.
+// height - Height of the surfaces.
+// flags - one or more of the following
+// XVMC_DIRECT - A direct rendered context is requested.
+//
+// Notes: surface_type_id and width/height parameters must match those
+// returned by XvMCListSurfaceTypes.
+// Returns: Status
+***************************************************************************/
+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 drm_context_t for us and
+ validate the with/height and flags.
+ */
+ if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
+ printf("Unable to create XvMC Context.\n");
+ return ret;
+ }
+
+ /*
+ X server returns a structure like this:
+ drm_context_t
+ fbBase
+ OverlayOffset
+ OverlaySize
+ SurfacesOffset
+ SurfacesSize
+ busIdString = 9 char + 1
+ */
+ if(priv_count != 9) {
+ printf("_xvmc_create_context() returned incorrect data size!\n");
+ printf("\tExpected 9, got %d\n",priv_count);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ }
+ pI810XvMC->drmcontext = priv_data[0];
+ pI810XvMC->fb_base = priv_data[1];
+ pI810XvMC->overlay.offset = priv_data[2] + priv_data[1];
+ pI810XvMC->overlay.size = priv_data[3];
+ pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1];
+ pI810XvMC->surfaces.size = priv_data[5];
+ strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9);
+ pI810XvMC->busIdString[9] = '\0';
+
+ /* Must free the private data we were passed from X */
+ free(priv_data);
+
+ /* Initialize private context values */
+ pI810XvMC->current = 0;
+ pI810XvMC->lock = 0;
+ pI810XvMC->last_flip = 0;
+ pI810XvMC->dual_prime = 0;
+
+ /*
+ Map dma Buffers: Not really, this would be a drmMapBufs
+ but due to the i810 security model we have to just create an
+ empty data structure to fake it.
+ */
+ pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap));
+ if(pI810XvMC->dmabufs == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs == NULL */
+ memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap));
+ pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) *
+ I810_DMA_BUF_NR);
+ if(pI810XvMC->dmabufs->list == NULL) {
+ printf("Dma Bufs could not be mapped.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* pI810XvMC->dmabufs->list == NULL */
+ memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
+
+ /* Map the Overlay memory */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset,
+ pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) {
+ printf("Unable to map Overlay at offset 0x%x and size 0x%x\n",
+ (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size);
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /* Overlay Regs are offset 1024 into Overlay Map */
+ pI810XvMC->oregs = (i810OverlayRec *)
+ ((unsigned char *)pI810XvMC->overlay.address + 1024);
+
+ /* Map Surfaces */
+ if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset,
+ pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) {
+ printf("Unable to map XvMC Surfaces.\n");
+ _xvmc_destroy_context(display, context);
+ free(pI810XvMC->dmabufs->list);
+ free(pI810XvMC);
+ return BadAlloc;
+ } /* drmMap() < 0 */
+
+ /*
+ There is a tiny chance that someone was using the overlay and
+ issued a flip that hasn't finished. To be 100% sure I'll just
+ take the lock and sleep for the worst case time for a flip.
+ */
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+ usleep(20000); /* 1/50th Sec for 50hz refresh */
+
+ /* Set up Overlay regs with Initial Values */
+ pI810XvMC->oregs->YRGB_VPH = 0;
+ pI810XvMC->oregs->UV_VPH = 0;
+ pI810XvMC->oregs->HORZ_PH = 0;
+ pI810XvMC->oregs->INIT_PH = 0;
+ pI810XvMC->oregs->DWINPOS = 0;
+ pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) |
+ I810_XVMC_MAXWIDTH;
+ pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15);
+ pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) |
+ (I810_XVMC_MAXWIDTH << 12);
+ pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT |
+ (I810_XVMC_MAXHEIGHT << 15);
+ pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->UVSCALE = 0x80004000; /* scale factor 1 */
+ pI810XvMC->oregs->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */
+ pI810XvMC->oregs->OV0CLRC1 = 0x80; /* saturation: bypass */
+
+ /* Destination Colorkey Setup */
+ pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
+ pI810XvMC->oregs->DCLRKM = 0x80070307;
+
+
+ pI810XvMC->oregs->SCLRKVH = 0;
+ pI810XvMC->oregs->SCLRKVL = 0;
+ pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */
+ pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST | YUV_420;
+
+ pI810XvMC->ref = 1;
+
+ I810_UNLOCK(pI810XvMC);
+
+ return Success;
+
+}
+
+/***************************************************************************
+// Function: XvMCDestroyContext
+// Description: Destorys the specified context.
+//
+// Arguments:
+// display - Specifies the connection to the server.
+// context - The context to be destroyed.
+//
+// Returns: Status
+***************************************************************************/
+Status XvMCDestroyContext(Display *display, XvMCContext *context) {
+ i810XvMCContext *pI810XvMC;
+
+ if(context == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ if(context->privData == NULL) {
+ return (error_base + XvMCBadContext);
+ }
+ pI810XvMC = (i810XvMCContext *)context->privData;
+
+ /* Turn off the overlay */
+ if(pI810XvMC->last_flip) {
+ I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
+
+ /* Make sure last flip is done */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
+ Y_ADJUST;
+ pI810XvMC->current = !pI810XvMC->current;
+ if(pI810XvMC->current == 1) {
+ pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
+ }
+ else {
+ pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
+ }
+ OVERLAY_FLIP(pI810XvMC);
+ pI810XvMC->last_flip++;
+
+ /* Wait for the flip */
+ BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
+
+ I810_UNLOCK(pI810XvMC);
+ }
+
+ /* Pass Control to the X server to destroy the drm_context_t */
+ _xvmc_destroy_context(display, context);
+
+ i810_free_privContext(pI810XvMC);
+ context->privData = NULL;
+
+ return Success;
+}
+
+
+/***************************************************************************
+// Function: XvMCCreateSurface
+***************************************************************************/
+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/driver/xf86-video-i810/src/xvmc/I810XvMC.h b/driver/xf86-video-i810/src/xvmc/I810XvMC.h
new file mode 100644
index 000000000..ba8c792d0
--- /dev/null
+++ b/driver/xf86-video-i810/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.3 2002/10/30 12:52:02 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 {
+ drm_handle_t offset;
+ drmAddress address;
+ unsigned int size;
+} i810XvMCDrmMap, *i810XvMCDrmMapPtr;
+
+/***************************************************************************
+// i810XvMCContext: Private Context data referenced via the privData
+// pointer in the XvMCContext structure.
+***************************************************************************/
+typedef struct _i810XvMCContext {
+ int fd; /* File descriptor for /dev/dri */
+ i810XvMCDrmMap overlay;
+ i810XvMCDrmMap surfaces;
+ drmBufMapPtr dmabufs; /* Data structure to hold available dma buffers */
+ drm_context_t drmcontext;
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned short ref;
+ unsigned short current;
+ int lock; /* Lightweight lock to avoid locking twice */
+ char busIdString[10]; /* PCI:0:1:0 or PCI:0:2:0 */
+ i810OverlayRecPtr oregs;
+ unsigned int dual_prime; /* Flag to identify when dual prime is in use. */
+ unsigned int fb_base;
+ Atom xv_colorkey;
+ Atom xv_brightness;
+ Atom xv_contrast;
+ Atom xv_saturation;
+ int brightness;
+ int saturation;
+ int contrast;
+ int colorkey;
+} i810XvMCContext;
+
+/***************************************************************************
+// i810XvMCSurface: Private data structure for each XvMCSurface. This
+// structure is referenced by the privData pointer in the XvMCSurface
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSurface {
+ unsigned int pitch;
+ unsigned int dbi1y; /* Destination buffer info command word 1 for Y */
+ unsigned int dbi1u; /* Destination buffer info command word 1 for U */
+ unsigned int dbi1v; /* Destination buffer info command word 1 for V */
+ unsigned int dbv1; /* Destination buffer variables command word 1 */
+ unsigned int mi1y; /* Map Info command word 1 (Minus bit 28) for Y */
+ unsigned int mi1u; /* Map Info command word 1 (Minus bit 28) for U */
+ unsigned int mi1v; /* Map Info command word 1 (Minus bit 28) for V */
+ unsigned int mi2y; /* Map info command word 2 for y */
+ unsigned int mi2u; /* Map info command word 2 for y */
+ unsigned int mi2v; /* Map info command word 2 for y */
+ unsigned int mi3y; /* Map info command word 3 */
+ unsigned int mi3u; /* Map info command word 3 */
+ unsigned int mi3v; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ unsigned int second_field; /* Flags a surface that is only half done */
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[3];
+ i810XvMCContext *privContext;
+} i810XvMCSurface;
+
+/***************************************************************************
+// i810XvMCSubpicture: Private data structure for each XvMCSubpicture. This
+// structure is referenced by the privData pointer in the XvMCSubpicture
+// structure.
+***************************************************************************/
+typedef struct _i810XvMCSubpicture {
+ unsigned int pitch;
+ unsigned int dbi1; /* Destination buffer info command word 1 */
+ unsigned int dbv1; /* Destination buffer variables command word */
+ unsigned int mi1; /* Map Info command word 1 (Minus bit 28) */
+ unsigned int mi2; /* Map info command word 2 */
+ unsigned int mi3; /* Map info command word 3 */
+ unsigned int last_render;
+ unsigned int last_flip;
+ drmAddress data;
+ drm_handle_t offset;
+ unsigned int offsets[1];
+ unsigned char palette[3][16];
+ i810XvMCContext *privContext;
+} i810XvMCSubpicture;
+
+typedef struct _Box {
+ int x1,y1,x2,y2;
+} Box, *BoxPtr;
+
+/***************************************************************************
+// drm_i810_overlay_t: Structure returned by overlay info ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_overlay_t {
+ unsigned int offset;
+ unsigned int physical;
+} drm_i810_overlay_t;
+
+/***************************************************************************
+// drm_i810_dma_t: Structure used by dma allocation ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
+/***************************************************************************
+// drm_i810_mc_t: Structure used by mc dispatch ioctl.
+// NOTE: If you change this structure you will have to change the equiv.
+// structure in the kernel.
+***************************************************************************/
+typedef struct _drm_i810_mc {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int num_blocks; /* number of GFXBlocks */
+ int *length; /* List of lengths for GFXBlocks */
+ unsigned int last_render; /* Last render request */
+} drm_i810_mc_t;
+
+/* Subpicture fourcc */
+#define FOURCC_IA44 0x34344149
+
+/* Static Parameters */
+#define I810_XVMC_MAXWIDTH 720
+#define I810_XVMC_MAXHEIGHT 576
+#define I810_DEFAULT16_COLORKEY 31
+#define I810_DMA_BUF_NR 256
+
+/* COMMANDS */
+#define CMD_FLUSH ((4<<23) | 0x1)
+#define BOOLEAN_ENA_1 ((3<<29) | (3<<24) | (3<<2))
+#define BOOLEAN_ENA_2 ((3<<29) | (4<<24) | (3<<16) | (1<<3) | (1<<2))
+#define DEST_BUFFER_INFO (0x15<<23)
+#define DEST_BUFFER_VAR ((0x3<<29) | (0x1d<<24) | (0x85<<16))
+#define DRAWING_RECT_INFO ((3<<29) | (0x1d<<24) | (0x80<<16) | 3)
+#define GFXBLOCK ((0x3<<29) | (0x1e<<24))
+#define CMD_MAP_INFO ((0x3<<29) | (0x1d<<24) | 0x2)
+#define MAP_PALETTE_LOAD ((3<<29) | (0x1d<<24) | (0x82<<16) | 0xff)
+#define VERTEX_FORMAT ((3<<29) | (0x5<<24))
+#define SRC_DEST_BLEND_MONO ((3<<29) | (8<<24))
+
+/* Bit Patterns */
+
+/*
+ * OV0CMD - Overlay Command Register
+ */
+#define VERTICAL_CHROMINANCE_FILTER 0x70000000
+#define VC_SCALING_OFF 0x00000000
+#define VC_LINE_REPLICATION 0x10000000
+#define VC_UP_INTERPOLATION 0x20000000
+#define VC_PIXEL_DROPPING 0x50000000
+#define VC_DOWN_INTERPOLATION 0x60000000
+#define VERTICAL_LUMINANCE_FILTER 0x0E000000
+#define VL_SCALING_OFF 0x00000000
+#define VL_LINE_REPLICATION 0x02000000
+#define VL_UP_INTERPOLATION 0x04000000
+#define VL_PIXEL_DROPPING 0x0A000000
+#define VL_DOWN_INTERPOLATION 0x0C000000
+#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000
+#define HC_SCALING_OFF 0x00000000
+#define HC_LINE_REPLICATION 0x00400000
+#define HC_UP_INTERPOLATION 0x00800000
+#define HC_PIXEL_DROPPING 0x01400000
+#define HC_DOWN_INTERPOLATION 0x01800000
+#define HORIZONTAL_LUMINANCE_FILTER 0x00380000
+#define HL_SCALING_OFF 0x00000000
+#define HL_LINE_REPLICATION 0x00080000
+#define HL_UP_INTERPOLATION 0x00100000
+#define HL_PIXEL_DROPPING 0x00280000
+#define HL_DOWN_INTERPOLATION 0x00300000
+
+#define Y_ADJUST 0x00010000
+#define OV_BYTE_ORDER 0x0000C000
+#define UV_SWAP 0x00004000
+#define Y_SWAP 0x00008000
+#define Y_AND_UV_SWAP 0x0000C000
+#define SOURCE_FORMAT 0x00003C00
+#define RGB_555 0x00000800
+#define RGB_565 0x00000C00
+#define YUV_422 0x00002000
+#define YUV_411 0x00002400
+#define YUV_420 0x00003000
+#define YUV_410 0x00003800
+#define VERTICAL_PHASE_BOTH 0x00000020
+#define FLIP_TYPE_FIELD 0x00000020
+#define FLIP_TYPE_FRAME 0x00000000
+#define BUFFER_AND_FIELD 0x00000006
+#define BUFFER0_FIELD0 0x00000000
+#define BUFFER0_FIELD1 0x00000002
+#define BUFFER1_FIELD0 0x00000004
+#define BUFFER1_FIELD1 0x00000006
+#define OVERLAY_ENABLE 0x00000001
+
+/*
+ * DOV0STA - Display/Overlay 0 Status Register
+ */
+#define DOV0STA 0x30008
+#define OV0ADD 0x30000
+#define MINUV_SCALE 0x1
+
+#define RGB16ToColorKey(c) \
+ (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+
+/* Locking Macros lightweight lock used to prevent relocking */
+#define I810_LOCK(c,f) \
+ if(!c->lock) { \
+ drmGetLock(c->fd, c->drmcontext, f); \
+ } \
+ c->lock++;
+
+#define I810_UNLOCK(c) \
+ c->lock--; \
+ if(!c->lock) { \
+ drmUnlock(c->fd, c->drmcontext); \
+ }
+
+/*
+ Block until the passed in value (n) is the active
+ buffer on the overlay.
+*/
+#define BLOCK_OVERLAY(c,n) \
+ do { \
+ int temp,i=0; \
+ while(i < 100000) { \
+ temp = GET_FSTATUS(c); \
+ if(((temp & (1<<20))>>20) == n) { \
+ break; \
+ } \
+ usleep(10); \
+ } \
+ if(i == 100000) { \
+ printf("Overlay Lockup.\n"); \
+ return BadAlloc; \
+ } \
+ }while(0);
+
+#define OVERLAY_INFO(c,i) drmCommandRead(c->fd, DRM_I810_OV0INFO, &i, sizeof(i))
+#define OVERLAY_FLIP(c) drmCommandNone(c->fd, DRM_I810_OV0FLIP)
+#define GET_FSTATUS(c) drmCommandNone(c->fd, DRM_I810_FSTATUS)
+#define I810_MC(c,mc) drmCommandWrite(c->fd, DRM_I810_MC, &mc, sizeof(mc))
+#define GET_RSTATUS(c) drmCommandNone(c->fd, DRM_I810_RSTATUS)
+#define GET_BUFFER(c,dma) drmCommandWriteRead(c->fd, DRM_I810_GETBUF, &dma, sizeof(drmI810DMA))
+#define FLUSH(c) drmCommandNone(c->fd, DRM_I810_FLUSH)
+
+/*
+ Definitions for temporary wire protocol hooks to be replaced
+ when a HW independent libXvMC is created.
+*/
+extern Status _xvmc_create_context(Display *dpy, XvMCContext *context,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context);
+
+extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context,
+ XvMCSurface *surface, int *priv_count,
+ uint **priv_data);
+
+extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface);
+
+extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ int *priv_count, uint **priv_data);
+
+extern Status _xvmc_destroy_subpicture(Display *dpy,
+ XvMCSubpicture *subpicture);
+
+/*
+ Prototypes
+*/
+drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC);
+void i810_free_privContext(i810XvMCContext *pI810XvMC);
+void dp(unsigned int *address, unsigned int i);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/driver/xf86-video-i810/src/xvmc/Makefile.am b/driver/xf86-video-i810/src/xvmc/Makefile.am
new file mode 100644
index 000000000..5cd5b25cd
--- /dev/null
+++ b/driver/xf86-video-i810/src/xvmc/Makefile.am
@@ -0,0 +1,8 @@
+if DRI
+lib_LTLIBRARIES=libI810XvMC.la
+libI810XvMC_la_SOURCES = I810XvMC.c \
+ I810XvMC.h
+
+libI810XvMC_la_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0
+libI810XvMC_la_LDFLAGS = -version-number 1:0:0
+endif \ No newline at end of file