summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2007-11-24 19:45:09 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2007-11-24 19:45:09 +0000
commit621df55ad49646572010dd46760717472a2cf8f4 (patch)
treea225c44e797ed935a3730d1c30fa22fffc997cea /driver
parent1411a42453b397a8d9010bb67204759600520dcd (diff)
xf86-video-intel 2.2.0
Diffstat (limited to 'driver')
-rw-r--r--driver/xf86-video-intel/man/intel.man217
-rw-r--r--driver/xf86-video-intel/src/bios_reader/Makefile.am13
-rw-r--r--driver/xf86-video-intel/src/bios_reader/Makefile.in495
-rw-r--r--driver/xf86-video-intel/src/bios_reader/bios_dumper.c99
-rw-r--r--driver/xf86-video-intel/src/bios_reader/bios_reader.c158
-rw-r--r--driver/xf86-video-intel/src/ch7017/Makefile.am15
-rw-r--r--driver/xf86-video-intel/src/ch7017/Makefile.in512
-rw-r--r--driver/xf86-video-intel/src/ch7017/ch7017.c325
-rw-r--r--driver/xf86-video-intel/src/ch7017/ch7017_module.c36
-rw-r--r--driver/xf86-video-intel/src/ch7017/ch7017_reg.h162
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/Makefile.am16
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/Makefile.in513
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/ch7xxx.c318
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/ch7xxx.h31
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/ch7xxx_module.c35
-rw-r--r--driver/xf86-video-intel/src/ch7xxx/ch7xxx_reg.h80
-rw-r--r--driver/xf86-video-intel/src/exa_sf.g4a45
-rw-r--r--driver/xf86-video-intel/src/exa_sf_mask.g4a78
-rw-r--r--driver/xf86-video-intel/src/exa_sf_mask_prog.h25
-rw-r--r--driver/xf86-video-intel/src/exa_sf_prog.h17
-rw-r--r--driver/xf86-video-intel/src/exa_sf_rotation.g4a55
-rw-r--r--driver/xf86-video-intel/src/exa_sf_rotation_prog.h20
-rw-r--r--driver/xf86-video-intel/src/exa_wm_maskca.g4a228
-rw-r--r--driver/xf86-video-intel/src/exa_wm_maskca_prog.h95
-rw-r--r--driver/xf86-video-intel/src/exa_wm_maskca_srcalpha.g4a228
-rw-r--r--driver/xf86-video-intel/src/exa_wm_maskca_srcalpha_prog.h95
-rw-r--r--driver/xf86-video-intel/src/exa_wm_masknoca.g4a228
-rw-r--r--driver/xf86-video-intel/src/exa_wm_masknoca_prog.h95
-rw-r--r--driver/xf86-video-intel/src/exa_wm_nomask.g4a169
-rw-r--r--driver/xf86-video-intel/src/exa_wm_nomask_prog.h70
-rw-r--r--driver/xf86-video-intel/src/exa_wm_rotation.g4a184
-rw-r--r--driver/xf86-video-intel/src/exa_wm_rotation_prog.h70
-rw-r--r--driver/xf86-video-intel/src/i2c_vid.h136
-rw-r--r--driver/xf86-video-intel/src/i830_bios.c298
-rw-r--r--driver/xf86-video-intel/src/i830_bios.h157
-rw-r--r--driver/xf86-video-intel/src/i830_crt.c434
-rw-r--r--driver/xf86-video-intel/src/i830_debug.c1012
-rw-r--r--driver/xf86-video-intel/src/i830_debug.h34
-rw-r--r--driver/xf86-video-intel/src/i830_display.c1732
-rw-r--r--driver/xf86-video-intel/src/i830_display.h42
-rw-r--r--driver/xf86-video-intel/src/i830_dvo.c524
-rw-r--r--driver/xf86-video-intel/src/i830_exa.c621
-rw-r--r--driver/xf86-video-intel/src/i830_i2c.c387
-rw-r--r--driver/xf86-video-intel/src/i830_lvds.c1025
-rw-r--r--driver/xf86-video-intel/src/i830_quirks.c104
-rw-r--r--driver/xf86-video-intel/src/i830_render.c638
-rw-r--r--driver/xf86-video-intel/src/i830_sdvo.c1335
-rw-r--r--driver/xf86-video-intel/src/i830_sdvo.h35
-rw-r--r--driver/xf86-video-intel/src/i830_sdvo_regs.h329
-rw-r--r--driver/xf86-video-intel/src/i830_tv.c1740
-rw-r--r--driver/xf86-video-intel/src/i830_xaa.c888
-rw-r--r--driver/xf86-video-intel/src/i915_render.c481
-rw-r--r--driver/xf86-video-intel/src/i965_render.c1190
-rw-r--r--driver/xf86-video-intel/src/i965_video.c855
-rw-r--r--driver/xf86-video-intel/src/ivch/Makefile.am15
-rw-r--r--driver/xf86-video-intel/src/ivch/Makefile.in511
-rw-r--r--driver/xf86-video-intel/src/ivch/ivch.c369
-rw-r--r--driver/xf86-video-intel/src/ivch/ivch_module.c64
-rw-r--r--driver/xf86-video-intel/src/ivch/ivch_reg.h291
-rw-r--r--driver/xf86-video-intel/src/local_xf86Rename.h23
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Crtc.c2264
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Crtc.h788
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Cursors.c646
-rw-r--r--driver/xf86-video-intel/src/modes/xf86DiDGA.c286
-rw-r--r--driver/xf86-video-intel/src/modes/xf86EdidModes.c491
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Modes.c661
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Modes.h98
-rw-r--r--driver/xf86-video-intel/src/modes/xf86RandR12.c1139
-rw-r--r--driver/xf86-video-intel/src/modes/xf86RandR12.h41
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Rename.h93
-rw-r--r--driver/xf86-video-intel/src/modes/xf86Rotate.c660
-rw-r--r--driver/xf86-video-intel/src/modes/xf86cvt.c308
-rw-r--r--driver/xf86-video-intel/src/parser/xf86Optrec.h112
-rw-r--r--driver/xf86-video-intel/src/parser/xf86Parser.h484
-rw-r--r--driver/xf86-video-intel/src/reg_dumper/Makefile.am12
-rw-r--r--driver/xf86-video-intel/src/reg_dumper/Makefile.in522
-rw-r--r--driver/xf86-video-intel/src/reg_dumper/main.c111
-rw-r--r--driver/xf86-video-intel/src/reg_dumper/reg_dumper.h89
-rw-r--r--driver/xf86-video-intel/src/reg_dumper/xprintf.c60
-rw-r--r--driver/xf86-video-intel/src/sil164/Makefile.am16
-rw-r--r--driver/xf86-video-intel/src/sil164/Makefile.in512
-rw-r--r--driver/xf86-video-intel/src/sil164/sil164.c249
-rw-r--r--driver/xf86-video-intel/src/sil164/sil164.h31
-rw-r--r--driver/xf86-video-intel/src/sil164/sil164_module.c38
-rw-r--r--driver/xf86-video-intel/src/sil164/sil164_reg.h75
-rw-r--r--driver/xf86-video-intel/src/tfp410/Makefile.am16
-rw-r--r--driver/xf86-video-intel/src/tfp410/Makefile.in512
-rw-r--r--driver/xf86-video-intel/src/tfp410/tfp410.c271
-rw-r--r--driver/xf86-video-intel/src/tfp410/tfp410.h33
-rw-r--r--driver/xf86-video-intel/src/tfp410/tfp410_module.c38
-rw-r--r--driver/xf86-video-intel/src/tfp410/tfp410_reg.h106
91 files changed, 30759 insertions, 0 deletions
diff --git a/driver/xf86-video-intel/man/intel.man b/driver/xf86-video-intel/man/intel.man
new file mode 100644
index 000000000..6245736b7
--- /dev/null
+++ b/driver/xf86-video-intel/man/intel.man
@@ -0,0 +1,217 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel __drivermansuffix__ __vendorversion__
+.SH NAME
+intel \- Intel integrated graphics chipsets
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qintel\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B intel
+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 i830M 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 intel
+supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM,
+865G, 915G, 915GM, 945G, 945GM, 965G, 965Q, 946GZ, 965GM, 945GME,
+G33, Q33, and Q35 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 and 9xx families of integrated graphics chipsets have 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, FreeBSD, OpenBSD,
+NetBSD, and Solaris have such kernel drivers available.
+.PP
+By default, the i810 will use 8 megabytes
+of system memory for graphics. For the 830M and later, the driver will
+automatically size its memory allocation according to the features it will
+support. The
+.B VideoRam
+option, which in the past had been necessary to allow more than some small
+amount of memory to be allocated, is now ignored.
+.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 when XAA acceleration is enabled. 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 space for at 3 screenfuls of pixmaps plus an
+HD-sized XV video. The default used for a specific configuration can be found
+by examining the __xservername__ log file.
+.TP
+.BI "Option \*qFramebufferCompression\*q \*q" boolean \*q
+This option controls whether the framebuffer compression feature is enabled.
+If possible, the front buffer will be allocated in a tiled format and compressed
+periodically to save memory bandwidth and power.
+This option is only available on mobile chipsets.
+Default: enabled on supported configurations.
+.TP
+.BI "Option \*qTiling\*q \*q" boolean \*q
+This option controls whether memory buffers are allocated in tiled mode. In
+many cases (especially for complex rendering), tiling can improve performance.
+Default: enabled.
+.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 \*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 \*qLegacy3D\*q \*q" boolean \*q
+Enable support for the legacy i915_dri.so 3D driver.
+This will, among other things, make the 2D driver tell libGL to
+load the 3D driver i915_dri.so instead of the newer i915tex_dri.so.
+This option is only used for chipsets in the range i830-i945.
+Default for i830-i945 series: Enabled.
+Default for i810: The option is not used.
+Default for i965: The option is always true.
+.TP
+.BI "Option \*qAperTexSize\*q \*q" integer \*q
+Give the size in kiB of the AGP aperture area that is reserved for the
+DRM memory manager present in i915 drm from version 1.7.0 and upwards,
+and that is used with the 3D driver in Mesa from version 6.5.2 and
+upwards. If the size is set too high to make room for pre-allocated
+VideoRam, the driver will try to reduce it automatically. If you use only
+older Mesa or DRM versions, you may set this value to zero, and
+activate the legacy texture pool (see
+.B "Option \*qLegacy3D\*q"
+). If you run 3D programs with large texture memory requirements, you might
+gain some performance by increasing this value.
+Default: 32768.
+.TP
+.BI "Option \*qPageFlip\*q \*q" boolean \*q
+Enable support for page flipping. This should improve 3D performance at the
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+the full benefit without triple buffering (see
+.B "Option \*qTripleBuffer\*q"
+).
+Default for i810: The option is not used.
+Default for i830 and above: Disabled (This option is currently unstable).
+.TP
+.BI "Option \*qTripleBuffer\*q \*q" boolean \*q
+Enable support for triple buffering. This should improve 3D performance at the
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+any benefit without page flipping either (see
+.B "Option \*qPageFlip\*q"
+).
+Default for i810: The option is not used.
+Default for i830 and above: Disabled.
+.TP
+.BI "Option \*qAccelMethod\*q \*q" string \*q
+Choose acceleration architecture, either "XAA" or "EXA". XAA is the old
+XFree86 based acceleration architecture. EXA is a newer and simpler
+acceleration architecture designed to better accelerate the X Render extension.
+Default: "EXA".
+.TP
+.BI "Option \*qModeDebug\*q \*q" boolean \*q
+Enable printing of additional debugging information about modesetting to
+the server log.
+
+.PP
+The 830M and newer driver supports the following outputs through RandR 1.2:
+.PP
+.TP
+.BI "VGA"
+Analog VGA output
+.TP
+.BI "LVDS"
+Laptop panel. Properties:
+ BACKLIGHT - set backlight level
+ BACKLIGHT_CONTROL - set backlight level control method (i.e. use kernel interfaces, native LVDS power register, legacy register, or combination)
+.TP
+.BI "TV"
+Integrated TV output
+.TP
+.BI "TMDS-1"
+First DVI SDVO output
+.TP
+.BI "TMDS-2"
+Second DVI SDVO output
+.PP
+SDVO and DVO TV outputs are not supported by the driver at this time.
+.PP
+See __xconfigfile__(__filemansuffix__) for information on associating Monitor
+sections with these outputs for configuration.
+
+.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,
+915GM, 945G, 945GM, 965G, 965Q and 946GZ support added by Alan Hourihane and
+Keith Whitwell. Lid status support added by Alan Hourihane. Textured video
+support for 915G and later chips, RandR 1.2 and hardware modesetting added
+by Eric Anholt and Keith Packard. EXA and Render acceleration added by Wang
+Zhenyu. TV out support added by Zou Nan Hai and Keith Packard. 965GM, G33,
+Q33, and Q35 support added by Wang Zhenyu.
diff --git a/driver/xf86-video-intel/src/bios_reader/Makefile.am b/driver/xf86-video-intel/src/bios_reader/Makefile.am
new file mode 100644
index 000000000..76ad15f7f
--- /dev/null
+++ b/driver/xf86-video-intel/src/bios_reader/Makefile.am
@@ -0,0 +1,13 @@
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @XMODES_CFLAGS@
+
+noinst_PROGRAMS = bios_reader $(BIOS_DUMPER)
+
+if LIBPCIACCESS
+BIOS_DUMPER = bios_dumper
+
+bios_dumper_SOURCES = bios_dumper.c
+
+bios_dumper_CFLAGS = $(PCIACCESS_CFLAGS)
+bios_dumper_LDADD = $(PCIACCESS_LIBS)
+
+endif
diff --git a/driver/xf86-video-intel/src/bios_reader/Makefile.in b/driver/xf86-video-intel/src/bios_reader/Makefile.in
new file mode 100644
index 000000000..32beb0b5c
--- /dev/null
+++ b/driver/xf86-video-intel/src/bios_reader/Makefile.in
@@ -0,0 +1,495 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = bios_reader$(EXEEXT) $(am__EXEEXT_1)
+subdir = src/bios_reader
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+@LIBPCIACCESS_TRUE@am__EXEEXT_1 = bios_dumper$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am__bios_dumper_SOURCES_DIST = bios_dumper.c
+@LIBPCIACCESS_TRUE@am_bios_dumper_OBJECTS = \
+@LIBPCIACCESS_TRUE@ bios_dumper-bios_dumper.$(OBJEXT)
+bios_dumper_OBJECTS = $(am_bios_dumper_OBJECTS)
+am__DEPENDENCIES_1 =
+@LIBPCIACCESS_TRUE@bios_dumper_DEPENDENCIES = $(am__DEPENDENCIES_1)
+bios_dumper_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(bios_dumper_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+bios_reader_SOURCES = bios_reader.c
+bios_reader_OBJECTS = bios_reader.$(OBJEXT)
+bios_reader_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(bios_dumper_SOURCES) bios_reader.c
+DIST_SOURCES = $(am__bios_dumper_SOURCES_DIST) bios_reader.c
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @XMODES_CFLAGS@
+@LIBPCIACCESS_TRUE@BIOS_DUMPER = bios_dumper
+@LIBPCIACCESS_TRUE@bios_dumper_SOURCES = bios_dumper.c
+@LIBPCIACCESS_TRUE@bios_dumper_CFLAGS = $(PCIACCESS_CFLAGS)
+@LIBPCIACCESS_TRUE@bios_dumper_LDADD = $(PCIACCESS_LIBS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/bios_reader/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/bios_reader/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+bios_dumper$(EXEEXT): $(bios_dumper_OBJECTS) $(bios_dumper_DEPENDENCIES)
+ @rm -f bios_dumper$(EXEEXT)
+ $(bios_dumper_LINK) $(bios_dumper_OBJECTS) $(bios_dumper_LDADD) $(LIBS)
+bios_reader$(EXEEXT): $(bios_reader_OBJECTS) $(bios_reader_DEPENDENCIES)
+ @rm -f bios_reader$(EXEEXT)
+ $(LINK) $(bios_reader_OBJECTS) $(bios_reader_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_dumper-bios_dumper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_reader.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+bios_dumper-bios_dumper.o: bios_dumper.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bios_dumper_CFLAGS) $(CFLAGS) -MT bios_dumper-bios_dumper.o -MD -MP -MF $(DEPDIR)/bios_dumper-bios_dumper.Tpo -c -o bios_dumper-bios_dumper.o `test -f 'bios_dumper.c' || echo '$(srcdir)/'`bios_dumper.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/bios_dumper-bios_dumper.Tpo $(DEPDIR)/bios_dumper-bios_dumper.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bios_dumper.c' object='bios_dumper-bios_dumper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bios_dumper_CFLAGS) $(CFLAGS) -c -o bios_dumper-bios_dumper.o `test -f 'bios_dumper.c' || echo '$(srcdir)/'`bios_dumper.c
+
+bios_dumper-bios_dumper.obj: bios_dumper.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bios_dumper_CFLAGS) $(CFLAGS) -MT bios_dumper-bios_dumper.obj -MD -MP -MF $(DEPDIR)/bios_dumper-bios_dumper.Tpo -c -o bios_dumper-bios_dumper.obj `if test -f 'bios_dumper.c'; then $(CYGPATH_W) 'bios_dumper.c'; else $(CYGPATH_W) '$(srcdir)/bios_dumper.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/bios_dumper-bios_dumper.Tpo $(DEPDIR)/bios_dumper-bios_dumper.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bios_dumper.c' object='bios_dumper-bios_dumper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bios_dumper_CFLAGS) $(CFLAGS) -c -o bios_dumper-bios_dumper.obj `if test -f 'bios_dumper.c'; then $(CYGPATH_W) 'bios_dumper.c'; else $(CYGPATH_W) '$(srcdir)/bios_dumper.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/bios_reader/bios_dumper.c b/driver/xf86-video-intel/src/bios_reader/bios_dumper.c
new file mode 100644
index 000000000..6f163d56b
--- /dev/null
+++ b/driver/xf86-video-intel/src/bios_reader/bios_dumper.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pciaccess.h>
+#include <err.h>
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: bios_dumper <filename>\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev;
+ void *bios;
+ int err, fd;
+
+ if (argc != 2)
+ usage();
+
+ err = pci_system_init();
+ if (err != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ err = pci_device_probe(dev);
+ if (err != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ bios = malloc(dev->rom_size);
+ if (bios == NULL)
+ errx(1, "Couldn't allocate memory for BIOS data\n");
+
+ err = pci_device_read_rom(dev, bios);
+ if (err != 0) {
+ fprintf(stderr, "Couldn't read graphics card ROM: %s\n",
+ strerror(err));
+ exit(1);
+ }
+
+ fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open output: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (write(fd, bios, dev->rom_size) < dev->rom_size) {
+ fprintf(stderr, "Couldn't write BIOS data: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ close(fd);
+ pci_system_cleanup();
+
+ return 0;
+}
diff --git a/driver/xf86-video-intel/src/bios_reader/bios_reader.c b/driver/xf86-video-intel/src/bios_reader/bios_reader.c
new file mode 100644
index 000000000..9ec73c132
--- /dev/null
+++ b/driver/xf86-video-intel/src/bios_reader/bios_reader.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "../i830_bios.h"
+
+#define _PARSE_EDID_
+#include "edid.h"
+
+
+/* Make a fake pI830 so we can easily pull i830_bios.c code in here. */
+struct _fake_i830 {
+ CARD8 *VBIOS;
+};
+struct _fake_i830 I830;
+struct _fake_i830 *pI830 = &I830;
+
+#define INTEL_BIOS_8(_addr) (pI830->VBIOS[_addr])
+#define INTEL_BIOS_16(_addr) (pI830->VBIOS[_addr] | \
+ (pI830->VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr) (pI830->VBIOS[_addr] | \
+ (pI830->VBIOS[_addr + 1] << 8) \
+ (pI830->VBIOS[_addr + 2] << 16) \
+ (pI830->VBIOS[_addr + 3] << 24))
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int bios_size = 65536;
+ struct vbt_header *vbt;
+ struct bdb_header *bdb;
+ int vbt_off, bdb_off, bdb_block_off, block_size;
+ int panel_type = -1, i;
+ char *filename = "bios";
+
+ if (argc == 2)
+ filename = argv[1];
+
+ f = fopen(filename, "r");
+ if (!f) {
+ printf("Couldn't open %s\n", filename);
+ return 1;
+ }
+
+ pI830->VBIOS = calloc(1, bios_size);
+ if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size)
+ return 1;
+
+ vbt_off = INTEL_BIOS_16(0x1a);
+ printf("VBT offset: %08x\n", vbt_off);
+ vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
+ printf("VBT sig: %20s\n", vbt->signature);
+ printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
+
+ bdb_off = vbt_off + vbt->bdb_offset;
+ bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
+ printf("BDB sig: %16s\n", bdb->signature);
+ printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100);
+ for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
+ bdb_block_off += block_size)
+ {
+ int start = bdb_off + bdb_block_off;
+ int id;
+ struct lvds_bdb_1 *lvds1;
+ struct lvds_bdb_2 *lvds2;
+ struct lvds_bdb_2_fp_params *fpparam;
+ struct lvds_bdb_2_fp_edid_dtd *fptiming;
+ CARD8 *timing_ptr;
+
+ id = INTEL_BIOS_8(start);
+ block_size = INTEL_BIOS_16(start + 1) + 3;
+ printf("BDB block type %03d size %d\n", id, block_size);
+ switch (id) {
+ case 40:
+ lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
+ panel_type = lvds1->panel_type;
+ printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps);
+ break;
+ case 41:
+ if (panel_type == -1) {
+ printf("Found panel block with no panel type\n");
+ break;
+ }
+
+ lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
+
+ printf("Entries per table: %d\n", lvds2->table_size);
+ for (i = 0; i < 16; i++) {
+ char marker;
+ fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_params_offset);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_edid_dtd_offset);
+ timing_ptr = pI830->VBIOS + bdb_off +
+ lvds2->panels[i].fp_edid_dtd_offset;
+ if (fpparam->terminator != 0xffff) {
+ /* Apparently the offsets are wrong for some BIOSes, so we
+ * try the other offsets if we find a bad terminator.
+ */
+ fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_params_offset + 8);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
+ bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8);
+ timing_ptr = pI830->VBIOS + bdb_off +
+ lvds2->panels[i].fp_edid_dtd_offset + 8;
+
+ if (fpparam->terminator != 0xffff)
+ continue;
+ }
+ if (i == panel_type)
+ marker = '*';
+ else
+ marker = ' ';
+ printf("%c Panel index %02i xres %d yres %d clock %d\n", marker,
+ i, fpparam->x_res, fpparam->y_res,
+ _PIXEL_CLOCK(timing_ptr));
+ printf(" %d %d %d %d %d %d %d %d\n",
+ _H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr),
+ _H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr),
+ _V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr),
+ _V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr));
+ }
+
+ printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res);
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/driver/xf86-video-intel/src/ch7017/Makefile.am b/driver/xf86-video-intel/src/ch7017/Makefile.am
new file mode 100644
index 000000000..71c508538
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7017/Makefile.am
@@ -0,0 +1,15 @@
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ch7017_la_LTLIBRARIES = ch7017.la
+ch7017_la_LDFLAGS = -module -avoid-version
+ch7017_ladir = @moduledir@/drivers
+
+ch7017_la_SOURCES = \
+ ch7017.c \
+ ch7017_module.c \
+ ch7017_reg.h
diff --git a/driver/xf86-video-intel/src/ch7017/Makefile.in b/driver/xf86-video-intel/src/ch7017/Makefile.in
new file mode 100644
index 000000000..243aca457
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7017/Makefile.in
@@ -0,0 +1,512 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/ch7017
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(ch7017_ladir)"
+ch7017_laLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(ch7017_la_LTLIBRARIES)
+ch7017_la_LIBADD =
+am_ch7017_la_OBJECTS = ch7017.lo ch7017_module.lo
+ch7017_la_OBJECTS = $(am_ch7017_la_OBJECTS)
+ch7017_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ch7017_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(ch7017_la_SOURCES)
+DIST_SOURCES = $(ch7017_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+ch7017_la_LTLIBRARIES = ch7017.la
+ch7017_la_LDFLAGS = -module -avoid-version
+ch7017_ladir = @moduledir@/drivers
+ch7017_la_SOURCES = \
+ ch7017.c \
+ ch7017_module.c \
+ ch7017_reg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ch7017/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/ch7017/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-ch7017_laLTLIBRARIES: $(ch7017_la_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(ch7017_ladir)" || $(MKDIR_P) "$(DESTDIR)$(ch7017_ladir)"
+ @list='$(ch7017_la_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(ch7017_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(ch7017_ladir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(ch7017_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(ch7017_ladir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-ch7017_laLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ch7017_la_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(ch7017_ladir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(ch7017_ladir)/$$p"; \
+ done
+
+clean-ch7017_laLTLIBRARIES:
+ -test -z "$(ch7017_la_LTLIBRARIES)" || rm -f $(ch7017_la_LTLIBRARIES)
+ @list='$(ch7017_la_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+ch7017.la: $(ch7017_la_OBJECTS) $(ch7017_la_DEPENDENCIES)
+ $(ch7017_la_LINK) -rpath $(ch7017_ladir) $(ch7017_la_OBJECTS) $(ch7017_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ch7017.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ch7017_module.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(ch7017_ladir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-ch7017_laLTLIBRARIES clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ch7017_laLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ch7017_laLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean \
+ clean-ch7017_laLTLIBRARIES clean-generic clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am \
+ install-ch7017_laLTLIBRARIES install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-ch7017_laLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/ch7017/ch7017.c b/driver/xf86-video-intel/src/ch7017/ch7017.c
new file mode 100644
index 000000000..6fc34223a
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7017/ch7017.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "ch7017_reg.h"
+
+struct ch7017_priv {
+ I2CDevRec d;
+
+ CARD8 save_hapi;
+ CARD8 save_vali;
+ CARD8 save_valo;
+ CARD8 save_ailo;
+ CARD8 save_lvds_pll_vco;
+ CARD8 save_feedback_div;
+ CARD8 save_lvds_control_2;
+ CARD8 save_outputs_enable;
+ CARD8 save_lvds_power_down;
+ CARD8 save_power_management;
+};
+
+static void
+ch7017_dump_regs(I2CDevPtr d);
+static void
+ch7017_dpms(I2CDevPtr d, int mode);
+
+static Bool
+ch7017_read(struct ch7017_priv *priv, int addr, CARD8 *val)
+{
+ if (!xf86I2CReadByte(&priv->d, addr, val)) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to read from %s Slave %d.\n",
+ priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+ch7017_write(struct ch7017_priv *priv, int addr, CARD8 val)
+{
+ if (!xf86I2CWriteByte(&priv->d, addr, val)) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave %d.\n",
+ priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Probes for a CH7017 on the given bus and slave address. */
+static void *
+ch7017_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+ struct ch7017_priv *priv;
+ CARD8 val;
+
+ priv = xcalloc(1, sizeof(struct ch7017_priv));
+ if (priv == NULL)
+ return NULL;
+
+ priv->d.DevName = "CH7017/7018/7019 LVDS Controller";
+ priv->d.SlaveAddr = addr;
+ priv->d.pI2CBus = b;
+ priv->d.StartTimeout = b->StartTimeout;
+ priv->d.BitTimeout = b->BitTimeout;
+ priv->d.AcknTimeout = b->AcknTimeout;
+ priv->d.ByteTimeout = b->ByteTimeout;
+ priv->d.DriverPrivate.ptr = priv;
+
+ if (!xf86I2CReadByte(&priv->d, CH7017_DEVICE_ID, &val))
+ goto fail;
+
+ if (val != CH7017_DEVICE_ID_VALUE &&
+ val != CH7018_DEVICE_ID_VALUE &&
+ val != CH7019_DEVICE_ID_VALUE) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "ch701x not detected, got %d: from %s Slave %d.\n",
+ val, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+ goto fail;
+ }
+
+ if (!xf86I2CDevInit(&(priv->d)))
+ goto fail;
+
+ return priv;
+
+fail:
+ xfree(priv);
+ return NULL;
+}
+
+static xf86OutputStatus
+ch7017_detect(I2CDevPtr d)
+{
+ return XF86OutputStatusUnknown;
+}
+
+static ModeStatus
+ch7017_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+ if (mode->Clock > 160000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static void
+ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ struct ch7017_priv *priv = d->DriverPrivate.ptr;
+ CARD8 lvds_pll_feedback_div, lvds_pll_vco_control;
+ CARD8 outputs_enable, lvds_control_2, lvds_power_down;
+ CARD8 horizontal_active_pixel_input;
+ CARD8 horizontal_active_pixel_output, vertical_active_line_output;
+ CARD8 active_input_line_output;
+
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,
+ "Registers before mode setting\n");
+ ch7017_dump_regs(d);
+
+ /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
+ if (mode->Clock < 100000) {
+ outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW;
+ lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
+ (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
+ (13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
+ lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+ (2 << CH7017_LVDS_PLL_VCO_SHIFT) |
+ (3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
+ lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
+ (0 << CH7017_PHASE_DETECTOR_SHIFT);
+ } else {
+ outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH;
+ lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
+ (2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
+ (3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
+ lvds_pll_feedback_div = 35;
+ lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) |
+ (0 << CH7017_PHASE_DETECTOR_SHIFT);
+ if (1) { /* XXX: dual channel panel detection. Assume yes for now. */
+ outputs_enable |= CH7017_LVDS_CHANNEL_B;
+ lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+ (2 << CH7017_LVDS_PLL_VCO_SHIFT) |
+ (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
+ } else {
+ lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
+ (1 << CH7017_LVDS_PLL_VCO_SHIFT) |
+ (13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
+ }
+ }
+
+ horizontal_active_pixel_input = mode->HDisplay & 0x00ff;
+
+ vertical_active_line_output = mode->VDisplay & 0x00ff;
+ horizontal_active_pixel_output = mode->HDisplay & 0x00ff;
+
+ active_input_line_output = ((mode->HDisplay & 0x0700) >> 8) |
+ (((mode->VDisplay & 0x0700) >> 8) << 3);
+
+ lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
+ (mode->HDisplay & 0x0700) >> 8;
+
+ ch7017_dpms(d, DPMSModeOff);
+ ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
+ horizontal_active_pixel_input);
+ ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
+ horizontal_active_pixel_output);
+ ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
+ vertical_active_line_output);
+ ch7017_write(priv, CH7017_ACTIVE_INPUT_LINE_OUTPUT,
+ active_input_line_output);
+ ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control);
+ ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div);
+ ch7017_write(priv, CH7017_LVDS_CONTROL_2, lvds_control_2);
+ ch7017_write(priv, CH7017_OUTPUTS_ENABLE, outputs_enable);
+
+ /* Turn the LVDS back on with new settings. */
+ ch7017_write(priv, CH7017_LVDS_POWER_DOWN, lvds_power_down);
+
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO,
+ "Registers after mode setting\n");
+ ch7017_dump_regs(d);
+}
+
+/* set the CH7017 power state */
+static void
+ch7017_dpms(I2CDevPtr d, int mode)
+{
+ struct ch7017_priv *priv = d->DriverPrivate.ptr;
+ CARD8 val;
+
+ ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &val);
+
+ /* Turn off TV/VGA, and never turn it on since we don't support it. */
+ ch7017_write(priv, CH7017_POWER_MANAGEMENT,
+ CH7017_DAC0_POWER_DOWN |
+ CH7017_DAC1_POWER_DOWN |
+ CH7017_DAC2_POWER_DOWN |
+ CH7017_DAC3_POWER_DOWN |
+ CH7017_TV_POWER_DOWN_EN);
+
+ if (mode == DPMSModeOn) {
+ /* Turn on the LVDS */
+ ch7017_write(priv, CH7017_LVDS_POWER_DOWN,
+ val & ~CH7017_LVDS_POWER_DOWN_EN);
+ } else {
+ /* Turn off the LVDS */
+ ch7017_write(priv, CH7017_LVDS_POWER_DOWN,
+ val | CH7017_LVDS_POWER_DOWN_EN);
+ }
+
+ /* XXX: Should actually wait for update power status somehow */
+ usleep(50000);
+}
+
+static void
+ch7017_dump_regs(I2CDevPtr d)
+{
+ struct ch7017_priv *priv = d->DriverPrivate.ptr;
+ CARD8 val;
+
+#define DUMP(reg) \
+do { \
+ ch7017_read(priv, reg, &val); \
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, \
+ #reg ": %02x\n", val); \
+} while (0)
+
+ DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
+ DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
+ DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
+ DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT);
+ DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
+ DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
+ DUMP(CH7017_LVDS_CONTROL_2);
+ DUMP(CH7017_OUTPUTS_ENABLE);
+ DUMP(CH7017_LVDS_POWER_DOWN);
+}
+
+static void
+ch7017_save(I2CDevPtr d)
+{
+ struct ch7017_priv *priv = d->DriverPrivate.ptr;
+
+ ch7017_read(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi);
+ ch7017_read(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo);
+ ch7017_read(priv, CH7017_ACTIVE_INPUT_LINE_OUTPUT, &priv->save_ailo);
+ ch7017_read(priv, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco);
+ ch7017_read(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div);
+ ch7017_read(priv, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2);
+ ch7017_read(priv, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable);
+ ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down);
+ ch7017_read(priv, CH7017_POWER_MANAGEMENT, &priv->save_power_management);
+}
+
+static void
+ch7017_restore(I2CDevPtr d)
+{
+ struct ch7017_priv *priv = d->DriverPrivate.ptr;
+
+ /* Power down before changing mode */
+ ch7017_dpms(d, DPMSModeOff);
+
+ ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi);
+ ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo);
+ ch7017_write(priv, CH7017_ACTIVE_INPUT_LINE_OUTPUT, priv->save_ailo);
+ ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco);
+ ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div);
+ ch7017_write(priv, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2);
+ ch7017_write(priv, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable);
+ ch7017_write(priv, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down);
+ ch7017_write(priv, CH7017_POWER_MANAGEMENT, priv->save_power_management);
+}
+
+I830I2CVidOutputRec ch7017_methods = {
+ .init = ch7017_init,
+ .detect = ch7017_detect,
+ .mode_valid = ch7017_mode_valid,
+ .mode_set = ch7017_mode_set,
+ .dpms = ch7017_dpms,
+ .dump_regs = ch7017_dump_regs,
+ .save = ch7017_save,
+ .restore = ch7017_restore,
+};
diff --git a/driver/xf86-video-intel/src/ch7017/ch7017_module.c b/driver/xf86-video-intel/src/ch7017/ch7017_module.c
new file mode 100644
index 000000000..135f3c656
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7017/ch7017_module.c
@@ -0,0 +1,36 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ch7017Setup);
+
+static XF86ModuleVersionInfo ch7017VersRec =
+ {
+ "ch7017",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ { 0,0,0,0 }
+ };
+
+_X_EXPORT XF86ModuleData ch7017ModuleData = {
+ &ch7017VersRec,
+ ch7017Setup,
+ NULL
+};
+
+static pointer
+ch7017Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
+ return (pointer)1;
+}
diff --git a/driver/xf86-video-intel/src/ch7017/ch7017_reg.h b/driver/xf86-video-intel/src/ch7017/ch7017_reg.h
new file mode 100644
index 000000000..7b536bdb2
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7017/ch7017_reg.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef CH7017_REG_H
+#define CH7017_REG_H
+
+#define CH7017_TV_DISPLAY_MODE 0x00
+#define CH7017_FLICKER_FILTER 0x01
+#define CH7017_VIDEO_BANDWIDTH 0x02
+#define CH7017_TEXT_ENHANCEMENT 0x03
+#define CH7017_START_ACTIVE_VIDEO 0x04
+#define CH7017_HORIZONTAL_POSITION 0x05
+#define CH7017_VERTICAL_POSITION 0x06
+#define CH7017_BLACK_LEVEL 0x07
+#define CH7017_CONTRAST_ENHANCEMENT 0x08
+#define CH7017_TV_PLL 0x09
+#define CH7017_TV_PLL_M 0x0a
+#define CH7017_TV_PLL_N 0x0b
+#define CH7017_SUB_CARRIER_0 0x0c
+#define CH7017_CIV_CONTROL 0x10
+#define CH7017_CIV_0 0x11
+#define CH7017_CHROMA_BOOST 0x14
+#define CH7017_CLOCK_MODE 0x1c
+#define CH7017_INPUT_CLOCK 0x1d
+#define CH7017_GPIO_CONTROL 0x1e
+#define CH7017_INPUT_DATA_FORMAT 0x1f
+#define CH7017_CONNECTION_DETECT 0x20
+#define CH7017_DAC_CONTROL 0x21
+#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22
+#define CH7017_DEFEAT_VSYNC 0x47
+#define CH7017_TEST_PATTERN 0x48
+
+#define CH7017_POWER_MANAGEMENT 0x49
+/** Enables the TV output path. */
+#define CH7017_TV_EN (1 << 0)
+#define CH7017_DAC0_POWER_DOWN (1 << 1)
+#define CH7017_DAC1_POWER_DOWN (1 << 2)
+#define CH7017_DAC2_POWER_DOWN (1 << 3)
+#define CH7017_DAC3_POWER_DOWN (1 << 4)
+/** Powers down the TV out block, and DAC0-3 */
+#define CH7017_TV_POWER_DOWN_EN (1 << 5)
+
+#define CH7017_VERSION_ID 0x4a
+
+#define CH7017_DEVICE_ID 0x4b
+#define CH7017_DEVICE_ID_VALUE 0x1b
+#define CH7018_DEVICE_ID_VALUE 0x1a
+#define CH7019_DEVICE_ID_VALUE 0x19
+
+#define CH7017_XCLK_D2_ADJUST 0x53
+#define CH7017_UP_SCALER_COEFF_0 0x55
+#define CH7017_UP_SCALER_COEFF_1 0x56
+#define CH7017_UP_SCALER_COEFF_2 0x57
+#define CH7017_UP_SCALER_COEFF_3 0x58
+#define CH7017_UP_SCALER_COEFF_4 0x59
+#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a
+#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b
+#define CH7017_GPIO_INVERT 0x5c
+#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d
+#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e
+
+#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f
+/**< Low bits of horizontal active pixel input */
+
+#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60
+/** High bits of horizontal active pixel input */
+#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0)
+/** High bits of vertical active line output */
+#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3)
+
+#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61
+/**< Low bits of vertical active line output */
+
+#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62
+/**< Low bits of horizontal active pixel output */
+
+#define CH7017_LVDS_POWER_DOWN 0x63
+/** High bits of horizontal active pixel output */
+#define CH7017_LVDS_HAP_HIGH_MASK (0x7 << 0)
+/** Enables the LVDS power down state transition */
+#define CH7017_LVDS_POWER_DOWN_EN (1 << 6)
+/** Enables the LVDS upscaler */
+#define CH7017_LVDS_UPSCALER_EN (1 << 7)
+#define CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED 0x08
+
+#define CH7017_LVDS_ENCODING 0x64
+#define CH7017_LVDS_DITHER_2D (1 << 2)
+#define CH7017_LVDS_DITHER_DIS (1 << 3)
+#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4)
+#define CH7017_LVDS_24_BIT (1 << 5)
+
+#define CH7017_LVDS_ENCODING_2 0x65
+
+#define CH7017_LVDS_PLL_CONTROL 0x66
+/** Enables the LVDS panel output path */
+#define CH7017_LVDS_PANEN (1 << 0)
+/** Enables the LVDS panel backlight */
+#define CH7017_LVDS_BKLEN (1 << 3)
+
+#define CH7017_POWER_SEQUENCING_T1 0x67
+#define CH7017_POWER_SEQUENCING_T2 0x68
+#define CH7017_POWER_SEQUENCING_T3 0x69
+#define CH7017_POWER_SEQUENCING_T4 0x6a
+#define CH7017_POWER_SEQUENCING_T5 0x6b
+#define CH7017_GPIO_DRIVER_TYPE 0x6c
+#define CH7017_GPIO_DATA 0x6d
+#define CH7017_GPIO_DIRECTION_CONTROL 0x6e
+
+#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71
+# define CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT 4
+# define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0
+# define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80
+
+#define CH7017_LVDS_PLL_VCO_CONTROL 0x72
+# define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80
+# define CH7017_LVDS_PLL_VCO_SHIFT 4
+# define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0
+
+#define CH7017_OUTPUTS_ENABLE 0x73
+# define CH7017_CHARGE_PUMP_LOW 0x0
+# define CH7017_CHARGE_PUMP_HIGH 0x3
+# define CH7017_LVDS_CHANNEL_A (1 << 3)
+# define CH7017_LVDS_CHANNEL_B (1 << 4)
+# define CH7017_TV_DAC_A (1 << 5)
+# define CH7017_TV_DAC_B (1 << 6)
+# define CH7017_DDC_SELECT_DC2 (1 << 7)
+
+#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74
+#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75
+#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76
+
+#define CH7017_LVDS_CONTROL_2 0x78
+# define CH7017_LOOP_FILTER_SHIFT 5
+# define CH7017_PHASE_DETECTOR_SHIFT 0
+
+#define CH7017_BANG_LIMIT_CONTROL 0x7f
+
+#endif /* CH7017_REG_H */
diff --git a/driver/xf86-video-intel/src/ch7xxx/Makefile.am b/driver/xf86-video-intel/src/ch7xxx/Makefile.am
new file mode 100644
index 000000000..fdf6e9e5b
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/Makefile.am
@@ -0,0 +1,16 @@
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ch7xxx_la_LTLIBRARIES = ch7xxx.la
+ch7xxx_la_LDFLAGS = -module -avoid-version
+ch7xxx_ladir = @moduledir@/drivers
+
+ch7xxx_la_SOURCES = \
+ ch7xxx.c \
+ ch7xxx_module.c \
+ ch7xxx.h \
+ ch7xxx_reg.h
diff --git a/driver/xf86-video-intel/src/ch7xxx/Makefile.in b/driver/xf86-video-intel/src/ch7xxx/Makefile.in
new file mode 100644
index 000000000..eccc3e6af
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/Makefile.in
@@ -0,0 +1,513 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/ch7xxx
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(ch7xxx_ladir)"
+ch7xxx_laLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(ch7xxx_la_LTLIBRARIES)
+ch7xxx_la_LIBADD =
+am_ch7xxx_la_OBJECTS = ch7xxx.lo ch7xxx_module.lo
+ch7xxx_la_OBJECTS = $(am_ch7xxx_la_OBJECTS)
+ch7xxx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ch7xxx_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(ch7xxx_la_SOURCES)
+DIST_SOURCES = $(ch7xxx_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+ch7xxx_la_LTLIBRARIES = ch7xxx.la
+ch7xxx_la_LDFLAGS = -module -avoid-version
+ch7xxx_ladir = @moduledir@/drivers
+ch7xxx_la_SOURCES = \
+ ch7xxx.c \
+ ch7xxx_module.c \
+ ch7xxx.h \
+ ch7xxx_reg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ch7xxx/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/ch7xxx/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-ch7xxx_laLTLIBRARIES: $(ch7xxx_la_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(ch7xxx_ladir)" || $(MKDIR_P) "$(DESTDIR)$(ch7xxx_ladir)"
+ @list='$(ch7xxx_la_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(ch7xxx_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(ch7xxx_ladir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(ch7xxx_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(ch7xxx_ladir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-ch7xxx_laLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ch7xxx_la_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(ch7xxx_ladir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(ch7xxx_ladir)/$$p"; \
+ done
+
+clean-ch7xxx_laLTLIBRARIES:
+ -test -z "$(ch7xxx_la_LTLIBRARIES)" || rm -f $(ch7xxx_la_LTLIBRARIES)
+ @list='$(ch7xxx_la_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+ch7xxx.la: $(ch7xxx_la_OBJECTS) $(ch7xxx_la_DEPENDENCIES)
+ $(ch7xxx_la_LINK) -rpath $(ch7xxx_ladir) $(ch7xxx_la_OBJECTS) $(ch7xxx_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ch7xxx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ch7xxx_module.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(ch7xxx_ladir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-ch7xxx_laLTLIBRARIES clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ch7xxx_laLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ch7xxx_laLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean \
+ clean-ch7xxx_laLTLIBRARIES clean-generic clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am \
+ install-ch7xxx_laLTLIBRARIES install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-ch7xxx_laLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/ch7xxx/ch7xxx.c b/driver/xf86-video-intel/src/ch7xxx/ch7xxx.c
new file mode 100644
index 000000000..3c58165d1
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/ch7xxx.c
@@ -0,0 +1,318 @@
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+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 AUTHOR 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
+
+#include <string.h>
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "ch7xxx.h"
+#include "ch7xxx_reg.h"
+
+/** @file
+ * driver for the Chrontel 7xxx DVI chip over DVO.
+ */
+
+static struct ch7xxx_id_struct {
+ int vid;
+ char *name;
+} ch7xxx_ids[] = {
+ { CH7011_VID, "CH7011" },
+ { CH7009A_VID, "CH7009A" },
+ { CH7009B_VID, "CH7009B" },
+ { CH7301_VID, "CH7301" },
+};
+
+#define ID_ARRAY_SIZE (sizeof(ch7xxx_ids) / sizeof(ch7xxx_ids[0]))
+
+struct ch7xxx_reg_state {
+ CARD8 regs[CH7xxx_NUM_REGS];
+};
+
+struct ch7xxx_priv {
+ I2CDevRec d;
+ Bool quiet;
+
+ struct ch7xxx_reg_state SavedReg;
+ struct ch7xxx_reg_state ModeReg;
+ CARD8 save_TCTL, save_TPCP, save_TPD, save_TPVT;
+ CARD8 save_TLPF, save_TCT, save_PM, save_IDF;
+};
+
+static void ch7xxx_save(I2CDevPtr d);
+
+static char *ch7xxx_get_id(int vid)
+{
+ int i;
+
+ for (i = 0; i < ID_ARRAY_SIZE; i++) {
+ if (ch7xxx_ids[i].vid == vid)
+ return ch7xxx_ids[i].name;
+ }
+
+ return NULL;
+}
+
+/** Reads an 8 bit register */
+static Bool
+ch7xxx_read(struct ch7xxx_priv *dev_priv, int addr, unsigned char *ch)
+{
+ if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
+ if (!dev_priv->quiet) {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex,
+ X_ERROR, "Unable to read from %s Slave %d.\n",
+ dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Writes an 8 bit register */
+static Bool
+ch7xxx_write(struct ch7xxx_priv *dev_priv, int addr, unsigned char ch)
+{
+ if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
+ if (!dev_priv->quiet) {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave %d.\n",
+ dev_priv->d.pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void *
+ch7xxx_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+ /* this will detect the CH7xxx chip on the specified i2c bus */
+ struct ch7xxx_priv *dev_priv;
+ CARD8 vendor, device;
+ char *name;
+
+ dev_priv = xcalloc(1, sizeof(struct ch7xxx_priv));
+ if (dev_priv == NULL)
+ return NULL;
+
+ dev_priv->d.DevName = "CH7xxx TMDS Controller";
+ dev_priv->d.SlaveAddr = addr;
+ dev_priv->d.pI2CBus = b;
+ dev_priv->d.StartTimeout = b->StartTimeout;
+ dev_priv->d.BitTimeout = b->BitTimeout;
+ dev_priv->d.AcknTimeout = b->AcknTimeout;
+ dev_priv->d.ByteTimeout = b->ByteTimeout;
+ dev_priv->d.DriverPrivate.ptr = dev_priv;
+
+ dev_priv->quiet = TRUE;
+ if (!ch7xxx_read(dev_priv, CH7xxx_REG_VID, &vendor))
+ goto out;
+
+ name = ch7xxx_get_id(vendor);
+ if (!name) {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+ "ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+ vendor, dev_priv->d.pI2CBus->BusName,
+ dev_priv->d.SlaveAddr);
+ goto out;
+ }
+
+
+ if (!ch7xxx_read(dev_priv, CH7xxx_REG_DID, &device))
+ goto out;
+
+ if (device != CH7xxx_DID) {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+ "ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+ device, dev_priv->d.pI2CBus->BusName,
+ dev_priv->d.SlaveAddr);
+ goto out;
+ }
+ dev_priv->quiet = FALSE;
+
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+ "Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
+ name, vendor, device);
+
+ if (!xf86I2CDevInit(&dev_priv->d)) {
+ goto out;
+ }
+
+ return dev_priv;
+
+out:
+ xfree(dev_priv);
+ return NULL;
+}
+
+static xf86OutputStatus
+ch7xxx_detect(I2CDevPtr d)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+ CARD8 cdet, orig_pm, pm;
+
+ ch7xxx_read(dev_priv, CH7xxx_PM, &orig_pm);
+
+ pm = orig_pm;
+ pm &= ~CH7xxx_PM_FPD;
+ pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
+
+ ch7xxx_write(dev_priv, CH7xxx_PM, pm);
+
+ ch7xxx_read(dev_priv, CH7xxx_CONNECTION_DETECT, &cdet);
+
+ ch7xxx_write(dev_priv, CH7xxx_PM, orig_pm);
+
+ if (cdet & CH7xxx_CDET_DVI)
+ return XF86OutputStatusConnected;
+ return XF86OutputStatusDisconnected;
+}
+
+static ModeStatus
+ch7xxx_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+ if (mode->Clock > 165000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static void
+ch7xxx_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+ CARD8 tvco, tpcp, tpd, tlpf, idf;
+
+ if (mode->Clock <= 65000) {
+ tvco = 0x23;
+ tpcp = 0x08;
+ tpd = 0x16;
+ tlpf = 0x60;
+ } else {
+ tvco = 0x2d;
+ tpcp = 0x06;
+ tpd = 0x26;
+ tlpf = 0xa0;
+ }
+
+ ch7xxx_write(dev_priv, CH7xxx_TCTL, 0x00);
+ ch7xxx_write(dev_priv, CH7xxx_TVCO, tvco);
+ ch7xxx_write(dev_priv, CH7xxx_TPCP, tpcp);
+ ch7xxx_write(dev_priv, CH7xxx_TPD, tpd);
+ ch7xxx_write(dev_priv, CH7xxx_TPVT, 0x30);
+ ch7xxx_write(dev_priv, CH7xxx_TLPF, tlpf);
+ ch7xxx_write(dev_priv, CH7xxx_TCT, 0x00);
+
+ ch7xxx_read(dev_priv, CH7xxx_IDF, &idf);
+
+ idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
+ if (mode->Flags & V_PHSYNC)
+ idf |= CH7xxx_IDF_HSP;
+
+ if (mode->Flags & V_PVSYNC)
+ idf |= CH7xxx_IDF_HSP;
+
+ ch7xxx_write(dev_priv, CH7xxx_IDF, idf);
+}
+
+/* set the CH7xxx power state */
+static void
+ch7xxx_dpms(I2CDevPtr d, int mode)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+
+ if (mode == DPMSModeOn)
+ ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
+ else
+ ch7xxx_write(dev_priv, CH7xxx_PM, CH7xxx_PM_FPD);
+}
+
+static void
+ch7xxx_dump_regs(I2CDevPtr d)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+ int i;
+
+ for (i = 0; i < CH7xxx_NUM_REGS; i++) {
+ if (( i % 8 ) == 0 )
+ ErrorF("\n %02X: ", i);
+ ErrorF("%02X ", dev_priv->ModeReg.regs[i]);
+ }
+}
+
+static void
+ch7xxx_save(I2CDevPtr d)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+
+ ch7xxx_read(dev_priv, CH7xxx_TCTL, &dev_priv->save_TCTL);
+ ch7xxx_read(dev_priv, CH7xxx_TPCP, &dev_priv->save_TPCP);
+ ch7xxx_read(dev_priv, CH7xxx_TPD, &dev_priv->save_TPD);
+ ch7xxx_read(dev_priv, CH7xxx_TPVT, &dev_priv->save_TPVT);
+ ch7xxx_read(dev_priv, CH7xxx_TLPF, &dev_priv->save_TLPF);
+ ch7xxx_read(dev_priv, CH7xxx_PM, &dev_priv->save_PM);
+ ch7xxx_read(dev_priv, CH7xxx_IDF, &dev_priv->save_IDF);
+}
+
+static void
+ch7xxx_restore(I2CDevPtr d)
+{
+ struct ch7xxx_priv *dev_priv = d->DriverPrivate.ptr;
+
+ ch7xxx_write(dev_priv, CH7xxx_TCTL, dev_priv->save_TCTL);
+ ch7xxx_write(dev_priv, CH7xxx_TPCP, dev_priv->save_TPCP);
+ ch7xxx_write(dev_priv, CH7xxx_TPD, dev_priv->save_TPD);
+ ch7xxx_write(dev_priv, CH7xxx_TPVT, dev_priv->save_TPVT);
+ ch7xxx_write(dev_priv, CH7xxx_TLPF, dev_priv->save_TLPF);
+ ch7xxx_write(dev_priv, CH7xxx_IDF, dev_priv->save_IDF);
+ ch7xxx_write(dev_priv, CH7xxx_PM, dev_priv->save_PM);
+}
+
+I830I2CVidOutputRec CH7xxxVidOutput = {
+ .init = ch7xxx_init,
+ .detect = ch7xxx_detect,
+ .mode_valid = ch7xxx_mode_valid,
+ .mode_set = ch7xxx_mode_set,
+ .dpms = ch7xxx_dpms,
+ .dump_regs = ch7xxx_dump_regs,
+ .save = ch7xxx_save,
+ .restore = ch7xxx_restore,
+};
diff --git a/driver/xf86-video-intel/src/ch7xxx/ch7xxx.h b/driver/xf86-video-intel/src/ch7xxx/ch7xxx.h
new file mode 100644
index 000000000..679c5313e
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/ch7xxx.h
@@ -0,0 +1,31 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+#ifndef CH7xxx_H
+#define CH7xxx_H
+
+#define CH7xxx_ADDR_1 0x76
+
+#endif
diff --git a/driver/xf86-video-intel/src/ch7xxx/ch7xxx_module.c b/driver/xf86-video-intel/src/ch7xxx/ch7xxx_module.c
new file mode 100644
index 000000000..2613d9e79
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/ch7xxx_module.c
@@ -0,0 +1,35 @@
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ch7xxxSetup);
+
+static XF86ModuleVersionInfo ch7xxxVersRec = {
+ "ch7xxx",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ { 0,0,0,0 }
+};
+
+_X_EXPORT XF86ModuleData ch7xxxModuleData = {
+ &ch7xxxVersRec,
+ ch7xxxSetup,
+ NULL
+};
+
+static pointer
+ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
+ return (pointer)1;
+}
diff --git a/driver/xf86-video-intel/src/ch7xxx/ch7xxx_reg.h b/driver/xf86-video-intel/src/ch7xxx/ch7xxx_reg.h
new file mode 100644
index 000000000..328b65334
--- /dev/null
+++ b/driver/xf86-video-intel/src/ch7xxx/ch7xxx_reg.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+#ifndef CH7xxx_REG_H
+#define CH7xxx_REG_H
+
+#define CH7xxx_REG_VID 0x4a
+#define CH7xxx_REG_DID 0x4b
+
+#define CH7011_VID 0x83 /* 7010 as well */
+#define CH7009A_VID 0x84
+#define CH7009B_VID 0x85
+#define CH7301_VID 0x95
+
+#define CH7xxx_VID 0x84
+#define CH7xxx_DID 0x17
+
+#define CH7xxx_NUM_REGS 0x4c
+
+#define CH7xxx_CM 0x1C
+#define CH7xxx_CM_XCM (1<<0)
+#define CH7xxx_CM_MCP (1<<2)
+#define CH7xxx_INPUT_CLOCK 0x1D
+#define CH7xxx_GPIO 0x1E
+#define CH7xxx_GPIO_HPIR (1<<3)
+#define CH7xxx_IDF 0x1F
+
+#define CH7xxx_IDF_HSP (1<<3)
+#define CH7xxx_IDF_VSP (1<<4)
+
+#define CH7xxx_CONNECTION_DETECT 0x20
+#define CH7xxx_CDET_DVI (1<<5)
+
+#define CH7301_DAC_CNTL 0x21
+#define CH7301_HOTPLUG 0x23
+#define CH7xxx_TCTL 0x31
+#define CH7xxx_TVCO 0x32
+#define CH7xxx_TPCP 0x33
+#define CH7xxx_TPD 0x34
+#define CH7xxx_TPVT 0x35
+#define CH7xxx_TLPF 0x36
+#define CH7xxx_TCT 0x37
+#define CH7301_TEST_PATTERN 0x48
+#define CH7xxx_PM 0x49
+
+#define CH7xxx_PM_FPD (1<<0)
+#define CH7301_PM_DACPD0 (1<<1)
+#define CH7301_PM_DACPD1 (1<<2)
+#define CH7301_PM_DACPD2 (1<<3)
+#define CH7xxx_PM_DVIL (1<<6)
+#define CH7xxx_PM_DVIP (1<<7)
+
+#define CH7301_SYNC_POLARITY 0x56
+
+#define CH7301_SYNC_RGB_YUV (1<<0)
+#define CH7301_SYNC_POL_DVI (1<<5)
+
+#endif
diff --git a/driver/xf86-video-intel/src/exa_sf.g4a b/driver/xf86-video-intel/src/exa_sf.g4a
new file mode 100644
index 000000000..5a023992f
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf.g4a
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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 Packard <keithp@keithp.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_sf_mask.g4a b/driver/xf86-video-intel/src/exa_sf_mask.g4a
new file mode 100644
index 000000000..a0d6efc4f
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf_mask.g4a
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/* FIXME how to setup second coeffient for mask tex coord */
+
+/*
+ g3 (v0) { u0, v0, 1.0, 1.0 } ==> {u0, v0, 1.0, 1.0, mu0, mv0, 1.0, 1.0} Co[0](u0) Co[1](v0) Co[2](mu0) Co[3](mv0)
+ g4 (v1) { u1, v1, 1.0, 1.0 } ==> {u1, v1, 1.0, 1.0, mu1, mv1, 1.0, 1.0}
+ g5 (v2) { u2, v2 } ==> (u2, v2, mu2, mv2}
+ g6 { 1/(x1-x0), 1/(y1-y0) }
+ g7 { u1-u0, v1-v0, 0, 0} ==>{u1-u0, v1-v0,0, 0, mu1-mu0, mv1-mv0, 0, 0}
+ -> { (u1-u0)/(x1-x0), (v1-v0)/(y1-y0) } ==>{(u1-u0)/(x1-x0), (v1-v0)/(y1-y0),(mu1-mu0)/(x1-x0), (mv1-mv0)/(y1-y0)
+ Cx, Cy Cx[0], Cy[0], Cx[1], Cy[1]
+ */
+
+/* assign Cx[0], Cx[1] to src, same to Cy, Co
+ Cx[2], Cx[3] to mask, same to Cy, Co */
+
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+add (8) g7<1>F g4<8,8,1>F -g3<8,8,1>F { align1 };
+/* Cx[0] */
+mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 };
+/* Cy[0] */
+mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 };
+/* Cx[2] */
+mul (1) g7.8<1>F g7.8<0,1,0>F g6<0,1,0>F { align1 };
+/* Cy[2] */
+mul (1) g7.12<1>F g7.12<0,1,0>F g6.4<0,1,0>F { align1 };
+
+/* src Cx[0], Cx[1] */
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+/* mask Cx[2], Cx[3] */
+mov (1) m1.8<1>F g7.8<0,1,0>F { align1 };
+mov (1) m1.12<1>F g7.8<0,1,0>F { align1 };
+/* src Cy[0], Cy[1] */
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+/* mask Cy[2], Cy[3] */
+mov (1) m2.8<1>F g7.12<0,1,0>F { align1 };
+mov (1) m2.12<1>F g7.12<0,1,0>F { align1 };
+/* src Co[0], Co[1] */
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+/* mask Co[2], Co[3] */
+mov (1) m3.8<1>F g3.8<0,1,0>F { align1 };
+mov (1) m3.12<1>F g3.12<0,1,0>F { align1 };
+
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_sf_mask_prog.h b/driver/xf86-video-intel/src/exa_sf_mask_prog.h
new file mode 100644
index 000000000..4e9114d61
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf_mask_prog.h
@@ -0,0 +1,25 @@
+ { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+ { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+ { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+ { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+ { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+ { 0x00000041, 0x20e877bd, 0x000000e8, 0x000000c0 },
+ { 0x00000041, 0x20ec77bd, 0x000000ec, 0x000000c4 },
+ { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+ { 0x00000001, 0x202803be, 0x000000e8, 0x00000000 },
+ { 0x00000001, 0x202c03be, 0x000000e8, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+ { 0x00000001, 0x204803be, 0x000000ec, 0x00000000 },
+ { 0x00000001, 0x204c03be, 0x000000ec, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+ { 0x00000001, 0x206803be, 0x00000068, 0x00000000 },
+ { 0x00000001, 0x206c03be, 0x0000006c, 0x00000000 },
+ { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_sf_prog.h b/driver/xf86-video-intel/src/exa_sf_prog.h
new file mode 100644
index 000000000..830d1760d
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf_prog.h
@@ -0,0 +1,17 @@
+ { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+ { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+ { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 },
+ { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 },
+ { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 },
+ { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+ { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_sf_rotation.g4a b/driver/xf86-video-intel/src/exa_sf_rotation.g4a
new file mode 100644
index 000000000..59d40d47b
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf_rotation.g4a
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/* 1/dx */
+send (1) 0 g6<1>F g1.12<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+/* 1/dy */
+send (1) 0 g6.4<1>F g1.20<0,1,0>F math inv scalar mlen 1 rlen 1 { align1 };
+/* du, dv */
+mul (1) g7<1>F g3<0,1,0>F -1.0F { align1 };
+mul (1) g7.4<1>F g3.4<0,1,0>F -1.0F { align1 };
+add (1) g7<1>F g4<0,1,0>F g7<0,1,0>F { align1 };
+add (1) g7.4<1>F g4.4<0,1,0>F g7.4<0,1,0>F { align1 };
+
+/* du/dy */
+mul (1) g7<1>F g7<0,1,0>F g6.4<0,1,0>F { align1 };
+/* dv/dx */
+mul (1) g7.4<1>F g7.4<0,1,0>F g6<0,1,0>F { align1 };
+/* Cx */
+mov (8) m1<1>F g7<0,1,0>F { align1 };
+/* Cy */
+mov (8) m2<1>F g7.4<0,1,0>F { align1 };
+/* Co */
+mov (8) m3<1>F g3<8,8,1>F { align1 };
+send (8) 0 null g0<8,8,1>F urb 0 transpose used complete mlen 4 rlen 0 { align1 EOT };
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_sf_rotation_prog.h b/driver/xf86-video-intel/src/exa_sf_rotation_prog.h
new file mode 100644
index 000000000..958913053
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_sf_rotation_prog.h
@@ -0,0 +1,20 @@
+ { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 },
+ { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 },
+ { 0x00000041, 0x20e07fbd, 0x00000060, 0xbf800000 },
+ { 0x00000041, 0x20e47fbd, 0x00000064, 0xbf800000 },
+ { 0x00000040, 0x20e077bd, 0x00000080, 0x000000e0 },
+ { 0x00000040, 0x20e477bd, 0x00000084, 0x000000e4 },
+ { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c4 },
+ { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c0 },
+ { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
+ { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_wm_maskca.g4a b/driver/xf86-video-intel/src/exa_wm_maskca.g4a
new file mode 100644
index 000000000..0e96aa04c
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_maskca.g4a
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+ as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ As mask texture coeffient needs extra setup urb starting from g4, we should
+ shift this location.
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+ * X0: {ss0.x, ss0.x+1, ss0.x, ss0.x+1, ss1.x, ss1.x+1, ss1.x, ss1.x+y}
+ * Y0: {ss0.y, ss0.y, ss0.y+1, ss0.y+1, ss1.y, ss1.y, ss1.y+1, ss1.y+1}
+ * X1: {ss2.x, ss2.x+1, ss2.x, ss2.x+1, ss3.x, ss3.x+1, ss3.x, ss3.x+y}
+ * Y1: {ss2.y, ss2.y, ss2.y+1, ss2.y+1, ss3.y, ss3.y, ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+ /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+ /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+ /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+ /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.x coordinates */
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+ /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 /* msg reg index */
+ g14<1>UW /* readback */
+ g0<8,8,1>UW /* copy to msg start reg*/
+ sampler (1,0,F) /* sampler message description,
+ (binding_table,sampler_index,datatype).
+ here(src->dst) we should use src_sampler and
+ src_surface */
+ mlen 5 rlen 8 { align1 }; /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 };
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* mul mask's channel to src, then write out src */
+mul (8) g14<1>F g14<8,8,1>F g22<8,8,1>F { align1 };
+mul (8) g15<1>F g15<8,8,1>F g23<8,8,1>F { align1 };
+mul (8) g16<1>F g16<8,8,1>F g24<8,8,1>F { align1 };
+mul (8) g17<1>F g17<8,8,1>F g25<8,8,1>F { align1 };
+mul (8) g18<1>F g18<8,8,1>F g26<8,8,1>F { align1 };
+mul (8) g19<1>F g19<8,8,1>F g27<8,8,1>F { align1 };
+mul (8) g20<1>F g20<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g21<1>F g21<8,8,1>F g29<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+ 0, /* binding_table */
+ 8, /* pixel scordboard clear, msg type simd16 single source */
+ 4, /* render target write */
+ 0 /* no write commit message */
+ )
+ mlen 10
+ rlen 0
+ { align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_wm_maskca_prog.h b/driver/xf86-video-intel/src/exa_wm_maskca_prog.h
new file mode 100644
index 000000000..d936412c4
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_maskca_prog.h
@@ -0,0 +1,95 @@
+ { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+ { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+ { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+ { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+ { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+ { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+ { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+ { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+ { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+ { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+ { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+ { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+ { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+ { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+ { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+ { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+ { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+ { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+ { 0x00600041, 0x21c077bd, 0x008d01c0, 0x008d02c0 },
+ { 0x00600041, 0x21e077bd, 0x008d01e0, 0x008d02e0 },
+ { 0x00600041, 0x220077bd, 0x008d0200, 0x008d0300 },
+ { 0x00600041, 0x222077bd, 0x008d0220, 0x008d0320 },
+ { 0x00600041, 0x224077bd, 0x008d0240, 0x008d0340 },
+ { 0x00600041, 0x226077bd, 0x008d0260, 0x008d0360 },
+ { 0x00600041, 0x228077bd, 0x008d0280, 0x008d0380 },
+ { 0x00600041, 0x22a077bd, 0x008d02a0, 0x008d03a0 },
+ { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+ { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+ { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha.g4a b/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha.g4a
new file mode 100644
index 000000000..a92c9e4f5
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha.g4a
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+ as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ As mask texture coeffient needs extra setup urb starting from g4, we should
+ shift this location.
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+ * X0: {ss0.x, ss0.x+1, ss0.x, ss0.x+1, ss1.x, ss1.x+1, ss1.x, ss1.x+y}
+ * Y0: {ss0.y, ss0.y, ss0.y+1, ss0.y+1, ss1.y, ss1.y, ss1.y+1, ss1.y+1}
+ * X1: {ss2.x, ss2.x+1, ss2.x, ss2.x+1, ss3.x, ss3.x+1, ss3.x, ss3.x+y}
+ * Y1: {ss2.y, ss2.y, ss2.y+1, ss2.y+1, ss3.y, ss3.y, ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+ /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+ /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+ /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+ /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.x coordinates */
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+ /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 /* msg reg index */
+ g14<1>UW /* readback */
+ g0<8,8,1>UW /* copy to msg start reg*/
+ sampler (1,0,F) /* sampler message description,
+ (binding_table,sampler_index,datatype).
+ here(src->dst) we should use src_sampler and
+ src_surface */
+ mlen 5 rlen 8 { align1 }; /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 };
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* src channel has no more use, src.A * mask.C */
+mul (8) g14<1>F g22<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g15<1>F g23<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g16<1>F g24<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g17<1>F g25<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g18<1>F g26<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g19<1>F g27<8,8,1>F g21<8,8,1>F { align1 };
+mul (8) g20<1>F g28<8,8,1>F g20<8,8,1>F { align1 };
+mul (8) g21<1>F g29<8,8,1>F g21<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+ 0, /* binding_table */
+ 8, /* pixel scordboard clear, msg type simd16 single source */
+ 4, /* render target write */
+ 0 /* no write commit message */
+ )
+ mlen 10
+ rlen 0
+ { align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha_prog.h b/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha_prog.h
new file mode 100644
index 000000000..d83b119f2
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_maskca_srcalpha_prog.h
@@ -0,0 +1,95 @@
+ { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+ { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+ { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+ { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+ { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+ { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+ { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+ { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+ { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+ { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+ { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+ { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+ { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+ { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+ { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+ { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+ { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+ { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+ { 0x00600041, 0x21c077bd, 0x008d02c0, 0x008d0280 },
+ { 0x00600041, 0x21e077bd, 0x008d02e0, 0x008d02a0 },
+ { 0x00600041, 0x220077bd, 0x008d0300, 0x008d0280 },
+ { 0x00600041, 0x222077bd, 0x008d0320, 0x008d02a0 },
+ { 0x00600041, 0x224077bd, 0x008d0340, 0x008d0280 },
+ { 0x00600041, 0x226077bd, 0x008d0360, 0x008d02a0 },
+ { 0x00600041, 0x228077bd, 0x008d0380, 0x008d0280 },
+ { 0x00600041, 0x22a077bd, 0x008d03a0, 0x008d02a0 },
+ { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+ { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+ { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_wm_masknoca.g4a b/driver/xf86-video-intel/src/exa_wm_masknoca.g4a
new file mode 100644
index 000000000..2e9e3c9ab
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_masknoca.g4a
@@ -0,0 +1,228 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ * XXX: This is still experimental, and should be fixed to support multiple texture
+ * map, and conditional mul actions.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+ as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ As mask texture coeffient needs extra setup urb starting from g4, we should
+ shift this location.
+
+ * X0_R is g4->g6
+ * X1_R is g5->g7
+ * Y0_R is g6->g8
+ * Y1_R is g7->g9
+
+ * X0: {ss0.x, ss0.x+1, ss0.x, ss0.x+1, ss1.x, ss1.x+1, ss1.x, ss1.x+y}
+ * Y0: {ss0.y, ss0.y, ss0.y+1, ss0.y+1, ss1.y, ss1.y, ss1.y+1, ss1.y+1}
+ * X1: {ss2.x, ss2.x+1, ss2.x, ss2.x+1, ss3.x, ss3.x+1, ss3.x, ss3.x+y}
+ * Y1: {ss2.y, ss2.y, ss2.y+1, ss2.y+1, ss3.y, ss3.y, ss3.y+1, ss3.y+1}
+ */
+
+/* multitexture program with src and mask texture */
+/* - load src texture */
+/* - load mask texture */
+/* - mul src.X with mask's alpha */
+/* - write out src.X */
+
+ /* Set up ss0.x coordinates*/
+mov (1) g6<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g6.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g6.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+ /* Set up ss0.y coordinates */
+mov (1) g8<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g8.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g8.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g8.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+ /* set up ss1.x coordinates */
+mov (1) g6.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g6.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g6.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+ /* set up ss1.y coordinates */
+mov (1) g8.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g8.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g8.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g8.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.x coordinates */
+mov (1) g7<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g7.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g7.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.y coordinates */
+mov (1) g9<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g9.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g9.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g9.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.x coordinates */
+mov (1) g7.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g7.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g7.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.y coordinates */
+mov (1) g9.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g9.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g9.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g9.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+ /* Now, map these screen space coordinates into texture coordinates. */
+/* This is for src texture */
+/* I don't want to change origin ssX coords, as it will be used later in mask */
+/* so store tex coords in g10, g11, g12, g13 */
+
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[0] */
+mul (8) g10<1>F g10<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g3<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[0] */
+add (8) g10<1>F g10<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g3.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[0] */
+mul (8) g12<1>F g12<8,8,1>F g3.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g3.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[1] */
+add (8) g12<1>F g12<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* src texture readback: g14-g21 */
+send (16) 0 /* msg reg index */
+ g14<1>UW /* readback */
+ g0<8,8,1>UW /* copy to msg start reg*/
+ sampler (1,0,F) /* sampler message description,
+ (binding_table,sampler_index,datatype).
+ here(src->dst) we should use src_sampler and
+ src_surface */
+ mlen 5 rlen 8 { align1 }; /* required message len 5, readback len 8 */
+
+mov (8) g21<1>UD g21<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* sampler mask texture, use g10, g11, g12, g13 */
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g10<1>F g6<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g11<1>F g7<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+/* Cx[2] */
+mul (8) g10<1>F g10<8,8,1>F g4<0,1,0>F { align1 };
+mul (8) g11<1>F g11<8,8,1>F g4<0,1,0>F { align1 };
+ /* add in texture X offset */
+/* Co[2] */
+add (8) g10<1>F g10<8,8,1>F g4.12<0,1,0>F { align1 };
+add (8) g11<1>F g11<8,8,1>F g4.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g12<1>F g8<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g13<1>F g9<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+/* Cy[2] */
+mul (8) g12<1>F g12<8,8,1>F g4.4<0,1,0>F { align1 };
+mul (8) g13<1>F g13<8,8,1>F g4.4<0,1,0>F { align1 };
+ /* add in texture Y offset */
+/* Co[3] */
+add (8) g12<1>F g12<8,8,1>F g4.28<0,1,0>F { align1 };
+add (8) g13<1>F g13<8,8,1>F g4.28<0,1,0>F { align1 };
+
+mov (8) m1<1>F g10<8,8,1>F { align1 };
+mov (8) m2<1>F g11<8,8,1>F { align1 };
+mov (8) m3<1>F g12<8,8,1>F { align1 };
+mov (8) m4<1>F g13<8,8,1>F { align1 };
+
+/* mask sampler g22-g29 */
+/* binding_table (2), sampler (1) */
+send (16) 0 g22<1>UW g0<8,8,1>UW sampler (2,1,F) mlen 5 rlen 8 { align1 };
+mov (8) g29<1>UD g29<8,8,1>UD { align1 }; /* wait sampler return */
+
+/* mul mask's alpha channel g28,g29 to src (g14-g21), then write out src */
+mul (8) g14<1>F g14<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g15<1>F g15<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g16<1>F g16<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g17<1>F g17<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g18<1>F g18<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g19<1>F g19<8,8,1>F g29<8,8,1>F { align1 };
+mul (8) g20<1>F g20<8,8,1>F g28<8,8,1>F { align1 };
+mul (8) g21<1>F g21<8,8,1>F g29<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+mov (8) m2<1>F g14<8,8,1>F { align1 };
+mov (8) m3<1>F g16<8,8,1>F { align1 };
+mov (8) m4<1>F g18<8,8,1>F { align1 };
+mov (8) m5<1>F g20<8,8,1>F { align1 };
+mov (8) m6<1>F g15<8,8,1>F { align1 };
+mov (8) m7<1>F g17<8,8,1>F { align1 };
+mov (8) m8<1>F g19<8,8,1>F { align1 };
+mov (8) m9<1>F g21<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+ 0, /* binding_table */
+ 8, /* pixel scordboard clear, msg type simd16 single source */
+ 4, /* render target write */
+ 0 /* no write commit message */
+ )
+ mlen 10
+ rlen 0
+ { align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_wm_masknoca_prog.h b/driver/xf86-video-intel/src/exa_wm_masknoca_prog.h
new file mode 100644
index 000000000..5fcf3b52d
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_masknoca_prog.h
@@ -0,0 +1,95 @@
+ { 0x00000001, 0x20c0013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20c40d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x20c8013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20cc0d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x2100013d, 0x0000002a, 0x00000000 },
+ { 0x00000001, 0x2104013d, 0x0000002a, 0x00000000 },
+ { 0x00000040, 0x21080d3d, 0x0000002a, 0x00000001 },
+ { 0x00000040, 0x210c0d3d, 0x0000002a, 0x00000001 },
+ { 0x00000001, 0x20d0013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20d40d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x20d8013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20dc0d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x2110013d, 0x0000002e, 0x00000000 },
+ { 0x00000001, 0x2114013d, 0x0000002e, 0x00000000 },
+ { 0x00000040, 0x21180d3d, 0x0000002e, 0x00000001 },
+ { 0x00000040, 0x211c0d3d, 0x0000002e, 0x00000001 },
+ { 0x00000001, 0x20e0013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20e40d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20e8013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20ec0d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x2120013d, 0x00000032, 0x00000000 },
+ { 0x00000001, 0x2124013d, 0x00000032, 0x00000000 },
+ { 0x00000040, 0x21280d3d, 0x00000032, 0x00000001 },
+ { 0x00000040, 0x212c0d3d, 0x00000032, 0x00000001 },
+ { 0x00000001, 0x20f0013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20f40d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20f8013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20fc0d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x2130013d, 0x00000036, 0x00000000 },
+ { 0x00000001, 0x2134013d, 0x00000036, 0x00000000 },
+ { 0x00000040, 0x21380d3d, 0x00000036, 0x00000001 },
+ { 0x00000040, 0x213c0d3d, 0x00000036, 0x00000001 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000060 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000060 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000006c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000006c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000064 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000064 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000007c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000007c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x21c01d29, 0x008d0000, 0x02580001 },
+ { 0x00600001, 0x22a00021, 0x008d02a0, 0x00000000 },
+ { 0x00600040, 0x214077bd, 0x008d00c0, 0x00004020 },
+ { 0x00600040, 0x216077bd, 0x008d00e0, 0x00004020 },
+ { 0x00600041, 0x214077bd, 0x008d0140, 0x00000080 },
+ { 0x00600041, 0x216077bd, 0x008d0160, 0x00000080 },
+ { 0x00600040, 0x214077bd, 0x008d0140, 0x0000008c },
+ { 0x00600040, 0x216077bd, 0x008d0160, 0x0000008c },
+ { 0x00600040, 0x218077bd, 0x008d0100, 0x00004024 },
+ { 0x00600040, 0x21a077bd, 0x008d0120, 0x00004024 },
+ { 0x00600041, 0x218077bd, 0x008d0180, 0x00000084 },
+ { 0x00600041, 0x21a077bd, 0x008d01a0, 0x00000084 },
+ { 0x00600040, 0x218077bd, 0x008d0180, 0x0000009c },
+ { 0x00600040, 0x21a077bd, 0x008d01a0, 0x0000009c },
+ { 0x00600001, 0x202003be, 0x008d0140, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0160, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d01a0, 0x00000000 },
+ { 0x00800031, 0x22c01d29, 0x008d0000, 0x02580102 },
+ { 0x00600001, 0x23a00021, 0x008d03a0, 0x00000000 },
+ { 0x00600041, 0x21c077bd, 0x008d01c0, 0x008d0380 },
+ { 0x00600041, 0x21e077bd, 0x008d01e0, 0x008d03a0 },
+ { 0x00600041, 0x220077bd, 0x008d0200, 0x008d0380 },
+ { 0x00600041, 0x222077bd, 0x008d0220, 0x008d03a0 },
+ { 0x00600041, 0x224077bd, 0x008d0240, 0x008d0380 },
+ { 0x00600041, 0x226077bd, 0x008d0260, 0x008d03a0 },
+ { 0x00600041, 0x228077bd, 0x008d0280, 0x008d0380 },
+ { 0x00600041, 0x22a077bd, 0x008d02a0, 0x008d03a0 },
+ { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+ { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+ { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_wm_nomask.g4a b/driver/xf86-video-intel/src/exa_wm_nomask.g4a
new file mode 100644
index 000000000..f92dc1a68
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_nomask.g4a
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+ as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+ /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+ /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+ /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+ /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+ /* Now, map these screen space coordinates into texture coordinates. */
+ /* subtract screen-space X origin of vertex 0. */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 };
+ /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 };
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 };
+ /* add in texture Y offset */
+add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g4<8,8,1>F { align1 };
+mov (8) m2<1>F g5<8,8,1>F { align1 }; /* param 0 u in m1, m2 */
+mov (8) m3<1>F g6<8,8,1>F { align1 };
+mov (8) m4<1>F g7<8,8,1>F { align1 }; /* param 1 v in m3, m4 */
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+send (16) 0 /* msg reg index */
+ g12<1>UW /* readback */
+ g0<8,8,1>UW /* copy to msg start reg*/
+ sampler (1,0,F) /* sampler message description, (binding_table,sampler_index,datatype)
+ /* here(src->dst) we should use src_sampler and src_surface */
+ mlen 5 rlen 8 { align1 }; /* required message len 5, readback len 8 */
+
+mov (8) g19<1>UD g19<8,8,1>UD { align1 }; /* wait sampler return */
+/* if we set up read-back reg correctly, emit dataport write 'send' cmd with EOT */
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>F g1<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+/* g12 -> m2
+ g13 -> m6
+ g14 -> m3
+ g15 -> m7
+ g16 -> m4
+ g17 -> m8
+ g18 -> m5
+ g19 -> m9
+*/
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+ 0, /* binding_table */
+ 8, /* pixel scordboard clear, msg type simd16 single source */
+ 4, /* render target write */
+ 0 /* no write commit message */
+ )
+ mlen 10
+ rlen 0
+ { align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_wm_nomask_prog.h b/driver/xf86-video-intel/src/exa_wm_nomask_prog.h
new file mode 100644
index 000000000..7870b3b71
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_nomask_prog.h
@@ -0,0 +1,70 @@
+ { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+ { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+ { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+ { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+ { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+ { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+ { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+ { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+ { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+ { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+ { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+ { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+ { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+ { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+ { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+ { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+ { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+ { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+ { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 },
+ { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 },
+ { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c },
+ { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c },
+ { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+ { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+ { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 },
+ { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 },
+ { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c },
+ { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c },
+ { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 },
+ { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+ { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x202003be, 0x008d0020, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+ { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+ { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/exa_wm_rotation.g4a b/driver/xf86-video-intel/src/exa_wm_rotation.g4a
new file mode 100644
index 000000000..613a5cb2e
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_rotation.g4a
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ */
+
+/*
+ * This's for exa composite operation in no mask picture case.
+ * The simplest case is just sending what src picture has to dst picture.
+ */
+
+/* I think this should be same as in g4a program for texture video,
+ as we also use 16-pixel dispatch. and SF scale in g3 is useful for us. */
+
+/* The initial payload of the thread is always g0.
+ * WM_URB (incoming URB entries) is g3
+ * X0_R is g4
+ * X1_R is g5
+ * Y0_R is g6
+ * Y1_R is g7
+ */
+
+ /* Set up the X/Y screen coordinates of the pixels in our 4 subspans. Each
+ * subspan is a 2x2 rectangle, and the screen x/y of the upper left of each
+ * subspan are given in GRF register 1.2 through 1.5 (which, with the word
+ * addressing below, are 1.4 through 1.11).
+ *
+ * The result is WM_X*_R and WM_Y*R being:
+ *
+ * X0: {ss0.x, ss0.x+1, ss0.x, ss0.x+1, ss1.x, ss1.x+1, ss1.x, ss1.x+y}
+ * Y0: {ss0.y, ss0.y, ss0.y+1, ss0.y+1, ss1.y, ss1.y, ss1.y+1, ss1.y+1}
+ * X1: {ss2.x, ss2.x+1, ss2.x, ss2.x+1, ss3.x, ss3.x+1, ss3.x, ss3.x+y}
+ * Y1: {ss2.y, ss2.y, ss2.y+1, ss2.y+1, ss3.y, ss3.y, ss3.y+1, ss3.y+1}
+ */
+ /* Set up ss0.x coordinates*/
+mov (1) g4<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.4<1>F g1.8<0,1,0>UW 1UB { align1 };
+mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 };
+add (1) g4.12<1>F g1.8<0,1,0>UW 1UB { align1 };
+ /* Set up ss0.y coordinates */
+mov (1) g6<1>F g1.10<0,1,0>UW { align1 };
+mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 };
+add (1) g6.8<1>F g1.10<0,1,0>UW 1UB { align1 };
+add (1) g6.12<1>F g1.10<0,1,0>UW 1UB { align1 };
+ /* set up ss1.x coordinates */
+mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.20<1>F g1.12<0,1,0>UW 1UB { align1 };
+mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 };
+add (1) g4.28<1>F g1.12<0,1,0>UW 1UB { align1 };
+ /* set up ss1.y coordinates */
+mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 };
+mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 };
+add (1) g6.24<1>F g1.14<0,1,0>UW 1UB { align1 };
+add (1) g6.28<1>F g1.14<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.x coordinates */
+mov (1) g5<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.4<1>F g1.16<0,1,0>UW 1UB { align1 };
+mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 };
+add (1) g5.12<1>F g1.16<0,1,0>UW 1UB { align1 };
+ /* Set up ss2.y coordinates */
+mov (1) g7<1>F g1.18<0,1,0>UW { align1 };
+mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 };
+add (1) g7.8<1>F g1.18<0,1,0>UW 1UB { align1 };
+add (1) g7.12<1>F g1.18<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.x coordinates */
+mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.20<1>F g1.20<0,1,0>UW 1UB { align1 };
+mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 };
+add (1) g5.28<1>F g1.20<0,1,0>UW 1UB { align1 };
+ /* Set up ss3.y coordinates */
+mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 };
+mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 };
+add (1) g7.24<1>F g1.22<0,1,0>UW 1UB { align1 };
+add (1) g7.28<1>F g1.22<0,1,0>UW 1UB { align1 };
+
+ /* Now, map these screen space coordinates into texture coordinates. */
+ /* subtract screen-space X origin of vertex 0. */
+/* for rotation, texture y is from ssX.x, so g4,g5 will be Y */
+add (8) g4<1>F g4<8,8,1>F -g1<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F -g1<0,1,0>F { align1 };
+ /* scale by texture X increment */
+mul (8) g4<1>F g4<8,8,1>F g3.20<0,1,0>F { align1 };
+mul (8) g5<1>F g5<8,8,1>F g3.20<0,1,0>F { align1 };
+ /* add in texture X offset */
+add (8) g4<1>F g4<8,8,1>F g3.28<0,1,0>F { align1 };
+add (8) g5<1>F g5<8,8,1>F g3.28<0,1,0>F { align1 };
+
+/* texture Y is from ssX.x */
+ /* subtract screen-space Y origin of vertex 0. */
+add (8) g6<1>F g6<8,8,1>F -g1.4<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F -g1.4<0,1,0>F { align1 };
+ /* scale by texture Y increment */
+mul (8) g6<1>F g6<8,8,1>F g3.16<0,1,0>F { align1 };
+mul (8) g7<1>F g7<8,8,1>F g3.16<0,1,0>F { align1 };
+ /* add in texture Y offset */
+add (8) g6<1>F g6<8,8,1>F g3.12<0,1,0>F { align1 };
+add (8) g7<1>F g7<8,8,1>F g3.12<0,1,0>F { align1 };
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+mov (8) m1<1>F g6<8,8,1>F { align1 };
+mov (8) m2<1>F g7<8,8,1>F { align1 };
+mov (8) m3<1>F g4<8,8,1>F { align1 };
+mov (8) m4<1>F g5<8,8,1>F { align1 };
+
+/* m0 will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+send (16) 0 /* msg reg index */
+ g12<1>UW /* readback */
+ g0<8,8,1>UW /* copy to msg start reg*/
+ sampler (1,0,F) /* sampler message description, (binding_table,sampler_index,datatype)
+ /* here(src->dst) we should use src_sampler and src_surface */
+ mlen 5 rlen 8 { align1 }; /* required message len 5, readback len 8 */
+
+mov (8) g19<1>UD g19<8,8,1>UD { align1 }; /* wait sampler return */
+/* if we set up read-back reg correctly, emit dataport write 'send' cmd with EOT */
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>F g1<8,8,1>F { align1 };
+
+/* prepare data in m2-m5 for subspan(1,0), m6-m9 for subspan(3,2), then it's ready to write */
+/* g12 -> m2
+ g13 -> m6
+ g14 -> m3
+ g15 -> m7
+ g16 -> m4
+ g17 -> m8
+ g18 -> m5
+ g19 -> m9
+*/
+mov (8) m2<1>F g12<8,8,1>F { align1 };
+mov (8) m3<1>F g14<8,8,1>F { align1 };
+mov (8) m4<1>F g16<8,8,1>F { align1 };
+mov (8) m5<1>F g18<8,8,1>F { align1 };
+mov (8) m6<1>F g13<8,8,1>F { align1 };
+mov (8) m7<1>F g15<8,8,1>F { align1 };
+mov (8) m8<1>F g17<8,8,1>F { align1 };
+mov (8) m9<1>F g19<8,8,1>F { align1 };
+
+/* m0, m1 are all direct passed by PS thread payload */
+mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable };
+
+/* write */
+send (16) 0 acc0<1>UW g0<8,8,1>UW write (
+ 0, /* binding_table */
+ 8, /* pixel scordboard clear, msg type simd16 single source */
+ 4, /* render target write */
+ 0 /* no write commit message */
+ )
+ mlen 10
+ rlen 0
+ { align1 EOT };
+
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
+nop;
diff --git a/driver/xf86-video-intel/src/exa_wm_rotation_prog.h b/driver/xf86-video-intel/src/exa_wm_rotation_prog.h
new file mode 100644
index 000000000..890d2cf03
--- /dev/null
+++ b/driver/xf86-video-intel/src/exa_wm_rotation_prog.h
@@ -0,0 +1,70 @@
+ { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 },
+ { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 },
+ { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 },
+ { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 },
+ { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 },
+ { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 },
+ { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 },
+ { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 },
+ { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 },
+ { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 },
+ { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 },
+ { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 },
+ { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 },
+ { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 },
+ { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 },
+ { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 },
+ { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 },
+ { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 },
+ { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 },
+ { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 },
+ { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 },
+ { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 },
+ { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 },
+ { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 },
+ { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 },
+ { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 },
+ { 0x00600041, 0x208077bd, 0x008d0080, 0x00000074 },
+ { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000074 },
+ { 0x00600040, 0x208077bd, 0x008d0080, 0x0000007c },
+ { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000007c },
+ { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 },
+ { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 },
+ { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000070 },
+ { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000070 },
+ { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000006c },
+ { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000006c },
+ { 0x00600001, 0x202003be, 0x008d00c0, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d00e0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d0080, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d00a0, 0x00000000 },
+ { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 },
+ { 0x00600001, 0x22600021, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x202003be, 0x008d0020, 0x00000000 },
+ { 0x00600001, 0x204003be, 0x008d0180, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d01a0, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d0260, 0x00000000 },
+ { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
+ { 0x00800031, 0x24001d28, 0x008d0000, 0x85a04800 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
diff --git a/driver/xf86-video-intel/src/i2c_vid.h b/driver/xf86-video-intel/src/i2c_vid.h
new file mode 100644
index 000000000..6c4e95dfc
--- /dev/null
+++ b/driver/xf86-video-intel/src/i2c_vid.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2006 Eric Anholt
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef I2C_VID_H
+#define I2C_VID_H
+#include <randrstr.h>
+
+typedef struct _I830I2CVidOutputRec {
+ /**
+ * Initialize the device at startup time.
+ * Returns NULL if the device does not exist.
+ */
+ void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
+
+ /**
+ * Called to allow the output a chance to create properties after the
+ * RandR objects have been created.
+ */
+ void
+ (*create_resources)(I2CDevPtr d);
+
+ /**
+ * Turns the output on/off, or sets intermediate power levels if available.
+ *
+ * Unsupported intermediate modes drop to the lower power setting. If the
+ * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
+ * disabled afterwards.
+ */
+ void (*dpms)(I2CDevPtr d, int mode);
+
+ /**
+ * Saves the output's state for restoration on VT switch.
+ */
+ void (*save)(I2CDevPtr d);
+
+ /**
+ * Restore's the output's state at VT switch.
+ */
+ void (*restore)(I2CDevPtr d);
+
+ /**
+ * Callback for testing a video mode for a given output.
+ *
+ * This function should only check for cases where a mode can't be supported
+ * on the output specifically, and not represent generic CRTC limitations.
+ *
+ * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+ */
+ int (*mode_valid)(I2CDevPtr d, DisplayModePtr mode);
+
+ /**
+ * Callback to adjust the mode to be set in the CRTC.
+ *
+ * This allows an output to adjust the clock or even the entire set of
+ * timings, which is used for panels with fixed timings or for
+ * buses with clock limitations.
+ */
+ Bool (*mode_fixup)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+ /**
+ * Callback for preparing mode changes on an output
+ */
+ void (*prepare)(I2CDevPtr d);
+
+ /**
+ * Callback for committing mode changes on an output
+ */
+ void (*commit)(I2CDevPtr d);
+
+ /**
+ * Callback for setting up a video mode after fixups have been made.
+ *
+ * This is only called while the output is disabled. The dpms callback
+ * must be all that's necessary for the output, to turn the output on
+ * after this function is called.
+ */
+ void (*mode_set)(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
+ /**
+ * Probe for a connected output, and return detect_status.
+ */
+ xf86OutputStatus (*detect)(I2CDevPtr d);
+
+ /**
+ * Query the device for the modes it provides.
+ *
+ * This function may also update MonInfo, mm_width, and mm_height.
+ *
+ * \return singly-linked list of modes or NULL if no modes found.
+ */
+ DisplayModePtr
+ (*get_modes)(I2CDevPtr d);
+
+#ifdef RANDR_12_INTERFACE
+ /**
+ * Callback when an output's property has changed.
+ */
+ Bool
+ (*set_property)(I2CDevPtr d, Atom property, RRPropertyValuePtr value);
+#endif
+
+ /**
+ * Clean up driver-specific bits of the output
+ */
+ void (*destroy) (I2CDevPtr d);
+
+ /**
+ * Debugging hook to dump device registers to log file
+ */
+ void (*dump_regs)(I2CDevPtr d);
+} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
+
+/* XXX change this name to avoid driver-specific prefix */
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output);
+
+#endif
diff --git a/driver/xf86-video-intel/src/i830_bios.c b/driver/xf86-video-intel/src/i830_bios.c
new file mode 100644
index 000000000..7ed791e67
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_bios.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#undef VERSION /* XXX edid.h has a VERSION too */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#define _PARSE_EDID_
+#include "xf86.h"
+#include "i830.h"
+#include "i830_bios.h"
+#include "edid.h"
+
+#define INTEL_BIOS_8(_addr) (bios[_addr])
+#define INTEL_BIOS_16(_addr) (bios[_addr] | \
+ (bios[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr) (bios[_addr] | \
+ (bios[_addr + 1] << 8) \
+ (bios[_addr + 2] << 16) \
+ (bios[_addr + 3] << 24))
+
+/* XXX */
+#define INTEL_VBIOS_SIZE (64 * 1024)
+
+static void
+i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios)
+{
+ const char *filename = "/tmp/xf86-video-intel-VBIOS";
+ FILE *f;
+
+ f = fopen(filename, "w");
+ if (f == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename);
+ return;
+ }
+ if (fwrite(bios, INTEL_VBIOS_SIZE, 1, f) != 1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n");
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Wrote BIOS contents to %s\n",
+ filename);
+ fclose(f);
+}
+
+/**
+ * Loads the Video BIOS and checks that the VBT exists.
+ *
+ * VBT existence is a sanity check that is relied on by other i830_bios.c code.
+ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
+ * feed an updated VBT back through that, compared to what we'll fetch using
+ * this method of groping around in the BIOS data.
+ */
+unsigned char *
+i830_bios_get (ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ struct vbt_header *vbt;
+ int vbt_off;
+ unsigned char *bios;
+ vbeInfoPtr pVbe;
+
+ bios = xalloc(INTEL_VBIOS_SIZE);
+ if (bios == NULL)
+ return NULL;
+
+ pVbe = VBEInit (NULL, pI830->pEnt->index);
+ if (pVbe != NULL) {
+ memcpy(bios, xf86int10Addr(pVbe->pInt10,
+ pVbe->pInt10->BIOSseg << 4),
+ INTEL_VBIOS_SIZE);
+ vbeFree (pVbe);
+ } else {
+#if XSERVER_LIBPCIACCESS
+ pci_device_read_rom (pI830->PciInfo, bios);
+#else
+ xf86ReadPciBIOS(0, pI830->PciTag, 0, bios, INTEL_VBIOS_SIZE);
+#endif
+ }
+
+ if (0)
+ i830DumpBIOSToFile(pScrn, bios);
+
+ vbt_off = INTEL_BIOS_16(0x1a);
+ if (vbt_off >= INTEL_VBIOS_SIZE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
+ vbt_off);
+ xfree(bios);
+ return NULL;
+ }
+
+ vbt = (struct vbt_header *)(bios + vbt_off);
+
+ if (memcmp(vbt->signature, "$VBT", 4) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n");
+ xfree(bios);
+ return NULL;
+ }
+
+ return bios;
+}
+
+/**
+ * Returns the BIOS's fixed panel mode.
+ *
+ * Note that many BIOSes will have the appropriate tables for a panel even when
+ * a panel is not attached. Additionally, many BIOSes adjust table sizes or
+ * offsets, such that this parsing fails. Thus, almost any other method for
+ * detecting the panel mode is preferable.
+ */
+DisplayModePtr
+i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ struct vbt_header *vbt;
+ struct bdb_header *bdb;
+ int vbt_off, bdb_off, bdb_block_off, block_size;
+ int panel_type = -1;
+ unsigned char *bios;
+
+ bios = i830_bios_get (pScrn);
+
+ if (bios == NULL)
+ return NULL;
+
+ vbt_off = INTEL_BIOS_16(0x1a);
+ vbt = (struct vbt_header *)(bios + vbt_off);
+ bdb_off = vbt_off + vbt->bdb_offset;
+ bdb = (struct bdb_header *)(bios + bdb_off);
+
+ if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n");
+ xfree(bios);
+ return NULL;
+ }
+
+ *wants_dither = FALSE;
+ for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
+ bdb_block_off += block_size)
+ {
+ int start = bdb_off + bdb_block_off;
+ int id;
+ struct lvds_bdb_1 *lvds1;
+ struct lvds_bdb_2 *lvds2;
+ struct lvds_bdb_2_fp_params *fpparam;
+ struct lvds_bdb_2_fp_edid_dtd *fptiming;
+ DisplayModePtr fixed_mode;
+ CARD8 *timing_ptr;
+
+ id = INTEL_BIOS_8(start);
+ block_size = INTEL_BIOS_16(start + 1) + 3;
+ switch (id) {
+ case 40:
+ lvds1 = (struct lvds_bdb_1 *)(bios + start);
+ panel_type = lvds1->panel_type;
+ if (lvds1->caps & LVDS_CAP_DITHER)
+ *wants_dither = TRUE;
+ break;
+ case 41:
+ if (panel_type == -1)
+ break;
+
+ lvds2 = (struct lvds_bdb_2 *)(bios + start);
+ fpparam = (struct lvds_bdb_2_fp_params *)(bios +
+ bdb_off + lvds2->panels[panel_type].fp_params_offset);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
+ bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset);
+ timing_ptr = bios + bdb_off +
+ lvds2->panels[panel_type].fp_edid_dtd_offset;
+
+ if (fpparam->terminator != 0xffff) {
+ /* Apparently the offsets are wrong for some BIOSes, so we
+ * try the other offsets if we find a bad terminator.
+ */
+ fpparam = (struct lvds_bdb_2_fp_params *)(bios +
+ bdb_off + lvds2->panels[panel_type].fp_params_offset + 8);
+ fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios +
+ bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8);
+ timing_ptr = bios + bdb_off +
+ lvds2->panels[panel_type].fp_edid_dtd_offset + 8;
+
+ if (fpparam->terminator != 0xffff)
+ continue;
+ }
+
+ fixed_mode = xnfalloc(sizeof(DisplayModeRec));
+ memset(fixed_mode, 0, sizeof(*fixed_mode));
+
+ /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
+ * block, pull the contents out using EDID macros.
+ */
+ fixed_mode->HDisplay = _H_ACTIVE(timing_ptr);
+ fixed_mode->VDisplay = _V_ACTIVE(timing_ptr);
+ fixed_mode->HSyncStart = fixed_mode->HDisplay +
+ _H_SYNC_OFF(timing_ptr);
+ fixed_mode->HSyncEnd = fixed_mode->HSyncStart +
+ _H_SYNC_WIDTH(timing_ptr);
+ fixed_mode->HTotal = fixed_mode->HDisplay +
+ _H_BLANK(timing_ptr);
+ fixed_mode->VSyncStart = fixed_mode->VDisplay +
+ _V_SYNC_OFF(timing_ptr);
+ fixed_mode->VSyncEnd = fixed_mode->VSyncStart +
+ _V_SYNC_WIDTH(timing_ptr);
+ fixed_mode->VTotal = fixed_mode->VDisplay +
+ _V_BLANK(timing_ptr);
+ fixed_mode->Clock = _PIXEL_CLOCK(timing_ptr) / 1000;
+ fixed_mode->type = M_T_PREFERRED;
+
+ xf86SetModeDefaultName(fixed_mode);
+
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Found panel mode in BIOS VBT tables:\n");
+ xf86PrintModeline(pScrn->scrnIndex, fixed_mode);
+ }
+
+ xfree(bios);
+ return fixed_mode;
+ }
+ }
+
+ xfree(bios);
+ return NULL;
+}
+
+unsigned char *
+i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block)
+{
+ unsigned char *bios;
+ int bdb_off;
+ int vbt_off;
+ int aim_off;
+ struct vbt_header *vbt;
+ struct aimdb_header *aimdb;
+ struct aimdb_block *aimdb_block;
+
+ bios = i830_bios_get (pScrn);
+ if (!bios)
+ return NULL;
+
+ vbt_off = INTEL_BIOS_16(0x1a);
+ vbt = (struct vbt_header *)(bios + vbt_off);
+
+ aim_off = vbt->aim_offset[aim];
+ if (!aim_off)
+ {
+ free (bios);
+ return NULL;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "aim_off %d\n", aim_off);
+ aimdb = (struct aimdb_header *) (bios + vbt_off + aim_off);
+ bdb_off = aimdb->aimdb_header_size;
+ while (bdb_off < aimdb->aimdb_size)
+ {
+ aimdb_block = (struct aimdb_block *) (bios + vbt_off + aim_off + bdb_off);
+ if (aimdb_block->aimdb_id == data_block)
+ {
+ unsigned char *aim = malloc (aimdb_block->aimdb_size + sizeof (struct aimdb_block));
+ if (!aim)
+ {
+ free (bios);
+ return NULL;
+ }
+ memcpy (aim, aimdb_block, aimdb_block->aimdb_size + sizeof (struct aimdb_block));
+ free (bios);
+ return aim;
+ }
+ bdb_off += aimdb_block->aimdb_size + sizeof (struct aimdb_block);
+ }
+ free (bios);
+ return NULL;
+}
diff --git a/driver/xf86-video-intel/src/i830_bios.h b/driver/xf86-video-intel/src/i830_bios.h
new file mode 100644
index 000000000..9e8356a11
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_bios.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _I830_BIOS_H_
+#define _I830_BIOS_H_
+
+#include <xf86str.h>
+
+struct vbt_header {
+ char signature[20]; /**< Always starts with 'VBT$' */
+ CARD16 version; /**< decimal */
+ CARD16 header_size; /**< in bytes */
+ CARD16 vbt_size; /**< in bytes */
+ CARD8 vbt_checksum;
+ CARD8 reserved0;
+ CARD32 bdb_offset; /**< from beginning of VBT */
+ CARD32 aim_offset[4]; /**< from beginning of VBT */
+} __attribute__((packed));
+
+struct bdb_header {
+ char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
+ CARD16 version; /**< decimal */
+ CARD16 header_size; /**< in bytes */
+ CARD16 bdb_size; /**< in bytes */
+} __attribute__((packed));
+
+#define LVDS_CAP_EDID (1 << 6)
+#define LVDS_CAP_DITHER (1 << 5)
+#define LVDS_CAP_PFIT_AUTO_RATIO (1 << 4)
+#define LVDS_CAP_PFIT_GRAPHICS_MODE (1 << 3)
+#define LVDS_CAP_PFIT_TEXT_MODE (1 << 2)
+#define LVDS_CAP_PFIT_GRAPHICS (1 << 1)
+#define LVDS_CAP_PFIT_TEXT (1 << 0)
+struct lvds_bdb_1 {
+ CARD8 id; /**< 40 */
+ CARD16 size;
+ CARD8 panel_type;
+ CARD8 reserved0;
+ CARD16 caps;
+} __attribute__((packed));
+
+struct lvds_bdb_2_fp_params {
+ CARD16 x_res;
+ CARD16 y_res;
+ CARD32 lvds_reg;
+ CARD32 lvds_reg_val;
+ CARD32 pp_on_reg;
+ CARD32 pp_on_reg_val;
+ CARD32 pp_off_reg;
+ CARD32 pp_off_reg_val;
+ CARD32 pp_cycle_reg;
+ CARD32 pp_cycle_reg_val;
+ CARD32 pfit_reg;
+ CARD32 pfit_reg_val;
+ CARD16 terminator;
+} __attribute__((packed));
+
+struct lvds_bdb_2_fp_edid_dtd {
+ CARD16 dclk; /**< In 10khz */
+ CARD8 hactive;
+ CARD8 hblank;
+ CARD8 high_h; /**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */
+ CARD8 vactive;
+ CARD8 vblank;
+ CARD8 high_v; /**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */
+ CARD8 hsync_off;
+ CARD8 hsync_pulse_width;
+ CARD8 vsync_off;
+ CARD8 high_hsync_off; /**< 7:6 = hsync off 9:8 */
+ CARD8 h_image;
+ CARD8 v_image;
+ CARD8 max_hv;
+ CARD8 h_border;
+ CARD8 v_border;
+ CARD8 flags;
+#define FP_EDID_FLAG_VSYNC_POSITIVE (1 << 2)
+#define FP_EDID_FLAG_HSYNC_POSITIVE (1 << 1)
+} __attribute__((packed));
+
+struct lvds_bdb_2_entry {
+ CARD16 fp_params_offset; /**< From beginning of BDB */
+ CARD8 fp_params_size;
+ CARD16 fp_edid_dtd_offset;
+ CARD8 fp_edid_dtd_size;
+ CARD16 fp_edid_pid_offset;
+ CARD8 fp_edid_pid_size;
+} __attribute__((packed));
+
+struct lvds_bdb_2 {
+ CARD8 id; /**< 41 */
+ CARD16 size;
+ CARD8 table_size; /* not sure on this one */
+ struct lvds_bdb_2_entry panels[16];
+} __attribute__((packed));
+
+struct aimdb_header {
+ char signature[16];
+ char oem_device[20];
+ CARD16 aimdb_version;
+ CARD16 aimdb_header_size;
+ CARD16 aimdb_size;
+} __attribute__((packed));
+
+struct aimdb_block {
+ CARD8 aimdb_id;
+ CARD16 aimdb_size;
+} __attribute__((packed));
+
+struct vch_panel_data {
+ CARD16 fp_timing_offset;
+ CARD8 fp_timing_size;
+ CARD16 dvo_timing_offset;
+ CARD8 dvo_timing_size;
+ CARD16 text_fitting_offset;
+ CARD8 text_fitting_size;
+ CARD16 graphics_fitting_offset;
+ CARD8 graphics_fitting_size;
+} __attribute__((packed));
+
+struct vch_bdb_22 {
+ struct aimdb_block aimdb_block;
+ struct vch_panel_data panels[16];
+} __attribute__((packed));
+
+unsigned char *
+i830_bios_get (ScrnInfoPtr pScrn);
+
+DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither);
+
+unsigned char *
+i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block);
+
+#endif /* _I830_BIOS_H_ */
diff --git a/driver/xf86-video-intel/src/i830_crt.c b/driver/xf86-video-intel/src/i830_crt.c
new file mode 100644
index 000000000..d7762a070
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_crt.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "xf86Modes.h"
+#include "i830_display.h"
+
+static void
+i830_crt_dpms(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp;
+
+ temp = INREG(ADPA);
+ temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+ temp &= ~ADPA_DAC_ENABLE;
+
+ switch(mode) {
+ case DPMSModeOn:
+ temp |= ADPA_DAC_ENABLE;
+ break;
+ case DPMSModeStandby:
+ temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
+ break;
+ case DPMSModeSuspend:
+ temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
+ break;
+ case DPMSModeOff:
+ temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
+ break;
+ }
+
+ OUTREG(ADPA, temp);
+}
+
+static void
+i830_crt_save (xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->saveADPA = INREG(ADPA);
+}
+
+static void
+i830_crt_restore (xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ OUTREG(ADPA, pI830->saveADPA);
+}
+
+static int
+i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+{
+ if (pMode->Flags & V_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ if (pMode->Clock > 400000 || pMode->Clock < 25000)
+ return MODE_CLOCK_RANGE;
+
+ return MODE_OK;
+}
+
+static Bool
+i830_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+static void
+i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86CrtcPtr crtc = output->crtc;
+ I830CrtcPrivatePtr i830_crtc = crtc->driver_private;
+ int dpll_md_reg;
+ CARD32 adpa, dpll_md;
+
+ if (i830_crtc->pipe == 0)
+ dpll_md_reg = DPLL_A_MD;
+ else
+ dpll_md_reg = DPLL_B_MD;
+ /*
+ * Disable separate mode multiplier used when cloning SDVO to CRT
+ * XXX this needs to be adjusted when we really are cloning
+ */
+ if (IS_I965G(pI830))
+ {
+ dpll_md = INREG(dpll_md_reg);
+ OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
+ }
+
+ adpa = 0;
+ if (adjusted_mode->Flags & V_PHSYNC)
+ adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+ if (adjusted_mode->Flags & V_PVSYNC)
+ adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+
+ if (i830_crtc->pipe == 0)
+ {
+ adpa |= ADPA_PIPE_A_SELECT;
+ OUTREG(BCLRPAT_A, 0);
+ }
+ else
+ {
+ adpa |= ADPA_PIPE_B_SELECT;
+ OUTREG(BCLRPAT_B, 0);
+ }
+
+ OUTREG(ADPA, adpa);
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
+ *
+ * Only for I945G/GM.
+ *
+ * \return TRUE if CRT is connected.
+ * \return FALSE if CRT is disconnected.
+ */
+static Bool
+i830_crt_detect_hotplug(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp;
+ const int timeout_ms = 1000;
+ int starttime, curtime;
+
+ temp = INREG(PORT_HOTPLUG_EN);
+
+ OUTREG(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
+
+ for (curtime = starttime = GetTimeInMillis();
+ (curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
+ {
+ if ((INREG(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
+ break;
+ }
+
+ if ((INREG(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
+ CRT_HOTPLUG_MONITOR_COLOR)
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ * Detects CRT presence by checking for load.
+ *
+ * Requires that the current pipe's DPLL is active. This will cause flicker
+ * on the CRT, so it should not be used while the display is being used. Only
+ * color (not monochrome) displays are detected.
+ *
+ * \return TRUE if CRT is connected.
+ * \return FALSE if CRT is disconnected.
+ */
+static Bool
+i830_crt_detect_load (xf86CrtcPtr crtc,
+ xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr i830_crtc = I830CrtcPrivate(crtc);
+ CARD32 save_bclrpat;
+ CARD32 save_vtotal;
+ CARD32 vtotal, vactive;
+ CARD32 vsample;
+ CARD32 vblank, vblank_start, vblank_end;
+ CARD32 dsl;
+ CARD8 st00;
+ int bclrpat_reg, pipeconf_reg, pipe_dsl_reg;
+ int vtotal_reg, vblank_reg, vsync_reg;
+ int pipe = i830_crtc->pipe;
+ Bool present;
+
+ if (pipe == 0)
+ {
+ bclrpat_reg = BCLRPAT_A;
+ vtotal_reg = VTOTAL_A;
+ vblank_reg = VBLANK_A;
+ vsync_reg = VSYNC_A;
+ pipeconf_reg = PIPEACONF;
+ pipe_dsl_reg = PIPEA_DSL;
+ }
+ else
+ {
+ bclrpat_reg = BCLRPAT_B;
+ vtotal_reg = VTOTAL_B;
+ vblank_reg = VBLANK_B;
+ vsync_reg = VSYNC_B;
+ pipeconf_reg = PIPEBCONF;
+ pipe_dsl_reg = PIPEB_DSL;
+ }
+
+ save_bclrpat = INREG(bclrpat_reg);
+ save_vtotal = INREG(vtotal_reg);
+ vblank = INREG(vblank_reg);
+
+ vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
+ vactive = (save_vtotal & 0x7ff) + 1;
+
+ vblank_start = (vblank & 0xfff) + 1;
+ vblank_end = ((vblank >> 16) & 0xfff) + 1;
+
+ /* Set the border color to purple. */
+ OUTREG(bclrpat_reg, 0x500050);
+
+ if (IS_I9XX (pI830))
+ {
+ CARD32 pipeconf = INREG(pipeconf_reg);
+ OUTREG(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
+
+ st00 = pI830->readStandard (pI830, 0x3c2);
+ present = (st00 & (1 << 4)) != 0;
+ OUTREG(pipeconf_reg, pipeconf);
+ }
+ else
+ {
+ Bool restore_vblank = FALSE;
+ int count, detect;
+
+ /*
+ * If there isn't any border, add some.
+ * Yes, this will flicker
+ */
+ if (vblank_start <= vactive && vblank_end >= vtotal)
+ {
+ CARD32 vsync = INREG(vsync_reg);
+ CARD32 vsync_start = (vsync & 0xffff) + 1;
+
+ vblank_start = vsync_start;
+ OUTREG(vblank_reg, (vblank_start - 1) | ((vblank_end - 1) << 16));
+ restore_vblank = TRUE;
+ }
+
+ /* sample in the vertical border, selecting the larger one */
+ if (vblank_start - vactive >= vtotal - vblank_end)
+ vsample = (vblank_start + vactive) >> 1;
+ else
+ vsample = (vtotal + vblank_end) >> 1;
+
+ /*
+ * Wait for the border to be displayed
+ */
+ while (INREG(pipe_dsl_reg) >= vactive)
+ ;
+ while ((dsl = INREG(pipe_dsl_reg)) <= vsample)
+ ;
+ /*
+ * Watch ST00 for an entire scanline
+ */
+ detect = 0;
+ count = 0;
+ do {
+ count++;
+ /* Read the ST00 VGA status register */
+ st00 = pI830->readStandard(pI830, 0x3c2);
+ if (st00 & (1 << 4))
+ detect++;
+ } while ((INREG(pipe_dsl_reg) == dsl));
+
+ /* restore vblank if necessary */
+ if (restore_vblank)
+ OUTREG(vblank_reg, vblank);
+ /*
+ * If more than 3/4 of the scanline detected a monitor,
+ * then it is assumed to be present. This works even on i830,
+ * where there isn't any way to force the border color across
+ * the screen
+ */
+ present = detect * 4 > count * 3;
+ }
+
+ /* Restore previous settings */
+ OUTREG(bclrpat_reg, save_bclrpat);
+
+ return present;
+}
+
+/**
+ * Detects CRT presence by probing for a response on the DDC address.
+ *
+ * This takes approximately 5ms in testing on an i915GM, with CRT connected or
+ * not.
+ *
+ * \return TRUE if the CRT is connected and responded to DDC.
+ * \return FALSE if no DDC response was detected.
+ */
+static Bool
+i830_crt_detect_ddc(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr i830_output = output->driver_private;
+
+ /* CRT should always be at 0, but check anyway */
+ if (i830_output->type != I830_OUTPUT_ANALOG)
+ return FALSE;
+
+ return xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
+}
+
+/**
+ * Attempts to detect CRT presence through any method available.
+ *
+ * @param allow_disturb enables detection methods that may cause flickering
+ * on active displays.
+ */
+static xf86OutputStatus
+i830_crt_detect(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86CrtcPtr crtc;
+ int dpms_mode;
+
+ if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830) ||
+ IS_G33CLASS(pI830)) {
+ if (i830_crt_detect_hotplug(output))
+ return XF86OutputStatusConnected;
+ else
+ return XF86OutputStatusDisconnected;
+ }
+
+ if (i830_crt_detect_ddc(output))
+ return XF86OutputStatusConnected;
+
+ /* Use the load-detect method if we have no other way of telling. */
+ crtc = i830GetLoadDetectPipe (output, NULL, &dpms_mode);
+
+ if (crtc)
+ {
+ Bool connected;
+
+ connected = i830_crt_detect_load (crtc, output);
+ i830ReleaseLoadDetectPipe (output, dpms_mode);
+ if (connected)
+ return XF86OutputStatusConnected;
+ else
+ return XF86OutputStatusDisconnected;
+ }
+
+ return XF86OutputStatusUnknown;
+}
+
+static void
+i830_crt_destroy (xf86OutputPtr output)
+{
+ if (output->driver_private)
+ xfree (output->driver_private);
+}
+
+static const xf86OutputFuncsRec i830_crt_output_funcs = {
+ .dpms = i830_crt_dpms,
+ .save = i830_crt_save,
+ .restore = i830_crt_restore,
+ .mode_valid = i830_crt_mode_valid,
+ .mode_fixup = i830_crt_mode_fixup,
+ .prepare = i830_output_prepare,
+ .mode_set = i830_crt_mode_set,
+ .commit = i830_output_commit,
+ .detect = i830_crt_detect,
+ .get_modes = i830_ddc_get_modes,
+ .destroy = i830_crt_destroy
+};
+
+void
+i830_crt_init(ScrnInfoPtr pScrn)
+{
+ xf86OutputPtr output;
+ I830OutputPrivatePtr i830_output;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ output = xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
+ if (!output)
+ return;
+ i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+ if (!i830_output)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+ i830_output->type = I830_OUTPUT_ANALOG;
+ /* i830 (almador) cannot place the analog adaptor on pipe B */
+ if (IS_I830(pI830))
+ i830_output->pipe_mask = (1 << 0);
+ else
+ i830_output->pipe_mask = ((1 << 0) | (1 << 1));
+ i830_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+ (1 << I830_OUTPUT_DVO_TMDS));
+
+ output->driver_private = i830_output;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+
+ /* Set up the DDC bus. */
+ I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
+}
diff --git a/driver/xf86-video-intel/src/i830_debug.c b/driver/xf86-video-intel/src/i830_debug.c
new file mode 100644
index 000000000..8f8ef9bbb
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_debug.c
@@ -0,0 +1,1012 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef REG_DUMPER
+#include "reg_dumper/reg_dumper.h"
+
+#else
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_debug.h"
+#include <strings.h>
+
+#endif
+
+#include "i810_reg.h"
+
+#define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
+
+DEBUGSTRING(i830_debug_xyminus1)
+{
+ return XNFprintf("%d, %d", (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_yxminus1)
+{
+ return XNFprintf("%d, %d", ((val & 0xffff0000) >> 16) + 1,
+ (val & 0xffff) + 1);
+}
+
+DEBUGSTRING(i830_debug_xy)
+{
+ return XNFprintf("%d, %d", (val & 0xffff),
+ ((val & 0xffff0000) >> 16));
+}
+
+DEBUGSTRING(i830_debug_dspstride)
+{
+ return XNFprintf("%d bytes", val);
+}
+
+DEBUGSTRING(i830_debug_dspcntr)
+{
+ char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+ char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+ return XNFprintf("%s, pipe %c", enabled, plane);
+}
+
+DEBUGSTRING(i830_debug_pipeconf)
+{
+ char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+ char *bit30;
+ if (IS_I965G(pI830))
+ bit30 = val & I965_PIPECONF_ACTIVE ? "active" : "inactive";
+ else
+ bit30 = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+ return XNFprintf("%s, %s", enabled, bit30);
+}
+
+DEBUGSTRING(i830_debug_hvtotal)
+{
+ return XNFprintf("%d active, %d total", (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_hvsyncblank)
+{
+ return XNFprintf("%d start, %d end", (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_vgacntrl)
+{
+ return XNFprintf("%s", val & VGA_DISP_DISABLE ? "disabled" : "enabled");
+}
+
+DEBUGSTRING(i830_debug_fp)
+{
+ return XNFprintf("n = %d, m1 = %d, m2 = %d",
+ ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
+ ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
+}
+
+DEBUGSTRING(i830_debug_vga_pd)
+{
+ int vga0_p1, vga0_p2, vga1_p1, vga1_p2;
+
+ /* XXX: i9xx version */
+
+ if (val & VGA0_PD_P1_DIV_2)
+ vga0_p1 = 2;
+ else
+ vga0_p1 = ((val & VGA0_PD_P1_MASK) >> VGA0_PD_P1_SHIFT) + 2;
+ vga0_p2 = (val & VGA0_PD_P2_DIV_4) ? 4 : 2;
+
+ if (val & VGA1_PD_P1_DIV_2)
+ vga1_p1 = 2;
+ else
+ vga1_p1 = ((val & VGA1_PD_P1_MASK) >> VGA1_PD_P1_SHIFT) + 2;
+ vga1_p2 = (val & VGA1_PD_P2_DIV_4) ? 4 : 2;
+
+ return XNFprintf("vga0 p1 = %d, p2 = %d, vga1 p1 = %d, p2 = %d",
+ vga0_p1, vga0_p2, vga1_p1, vga1_p2);
+}
+
+DEBUGSTRING(i830_debug_pp_status)
+{
+ char *status = val & PP_ON ? "on" : "off";
+ char *ready = val & PP_READY ? "ready" : "not ready";
+ char *seq = "unknown";
+
+ switch (val & PP_SEQUENCE_MASK) {
+ case PP_SEQUENCE_NONE:
+ seq = "idle";
+ break;
+ case PP_SEQUENCE_ON:
+ seq = "on";
+ break;
+ case PP_SEQUENCE_OFF:
+ seq = "off";
+ break;
+ }
+
+ return XNFprintf("%s, %s, sequencing %s", status, ready, seq);
+}
+
+DEBUGSTRING(i830_debug_pp_control)
+{
+ return XNFprintf("power target: %s",
+ val & POWER_TARGET_ON ? "on" : "off");
+}
+
+DEBUGSTRING(i830_debug_dpll)
+{
+ char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
+ char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
+ char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
+ char *mode = "unknown";
+ char *clock = "unknown";
+ char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
+ char sdvoextra[20];
+ int p1, p2 = 0;
+
+ if (IS_I9XX(pI830)) {
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+ switch (val & DPLL_MODE_MASK) {
+ case DPLLB_MODE_DAC_SERIAL:
+ mode = "DAC/serial";
+ p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+ break;
+ case DPLLB_MODE_LVDS:
+ mode = "LVDS";
+ p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+ break;
+ }
+ } else {
+ Bool is_lvds = (INREG(LVDS) & LVDS_PORT_EN) && (reg == DPLL_B);
+
+ if (is_lvds) {
+ mode = "LVDS";
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+ p2 = 14;
+ } else {
+ mode = "DAC/serial";
+ if (val & PLL_P1_DIVIDE_BY_TWO) {
+ p1 = 2;
+ } else {
+ /* Map the number in the field to (3, 33) */
+ p1 = ((val & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+ }
+ if (val & PLL_P2_DIVIDE_BY_4)
+ p2 = 4;
+ else
+ p2 = 2;
+ }
+ }
+
+ switch (val & PLL_REF_INPUT_MASK) {
+ case PLL_REF_INPUT_DREFCLK:
+ clock = "default";
+ break;
+ case PLL_REF_INPUT_TVCLKINA:
+ clock = "TV A";
+ break;
+ case PLL_REF_INPUT_TVCLKINBC:
+ clock = "TV B/C";
+ break;
+ case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+ if (reg == DPLL_B)
+ clock = "spread spectrum";
+ break;
+ }
+
+ if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_MULTIPLIER_MASK) >>
+ SDVO_MULTIPLIER_SHIFT_HIRES) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ return XNFprintf("%s, %s%s, %s clock, %s mode, p1 = %d, "
+ "p2 = %d%s%s",
+ enabled, dvomode, vgamode, clock, mode, p1, p2,
+ fpextra, sdvoextra);
+}
+
+DEBUGSTRING(i830_debug_dpll_test)
+{
+ char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : "";
+ char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : "";
+ char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLA input buffer disabled";
+ char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : "";
+ char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : "";
+ char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLB input buffer disabled";
+
+ return XNFprintf("%s%s%s%s%s%s",
+ dpllandiv, dpllamdiv, dpllainput,
+ dpllbndiv, dpllbmdiv, dpllbinput);
+}
+
+DEBUGSTRING(i830_debug_adpa)
+{
+ char pipe = (val & ADPA_PIPE_B_SELECT) ? 'B' : 'A';
+ char *enable = (val & ADPA_DAC_ENABLE) ? "enabled" : "disabled";
+ char hsync = (val & ADPA_HSYNC_ACTIVE_HIGH) ? '+' : '-';
+ char vsync = (val & ADPA_VSYNC_ACTIVE_HIGH) ? '+' : '-';
+
+ return XNFprintf("%s, pipe %c, %chsync, %cvsync",
+ enable, pipe, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_lvds)
+{
+ char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
+ char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+ int depth;
+ char *channels;
+
+ if ((val & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+ depth = 24;
+ else
+ depth = 18;
+ if ((val & LVDS_B0B3_POWER_MASK) == LVDS_B0B3_POWER_UP)
+ channels = "2 channels";
+ else
+ channels = "1 channel";
+
+
+ return XNFprintf("%s, pipe %c, %d bit, %s",
+ enable, pipe, depth, channels);
+}
+
+DEBUGSTRING(i830_debug_dvo)
+{
+ char *enable = val & DVO_ENABLE ? "enabled" : "disabled";
+ char pipe = val & DVO_PIPE_B_SELECT ? 'B' : 'A';
+ char *stall;
+ char hsync = val & DVO_HSYNC_ACTIVE_HIGH ? '+' : '-';
+ char vsync = val & DVO_VSYNC_ACTIVE_HIGH ? '+' : '-';
+
+ switch (val & DVO_PIPE_STALL_MASK) {
+ case DVO_PIPE_STALL_UNUSED:
+ stall = "no stall";
+ break;
+ case DVO_PIPE_STALL:
+ stall = "stall";
+ break;
+ case DVO_PIPE_STALL_TV:
+ stall = "TV stall";
+ break;
+ default:
+ stall = "unknown stall";
+ break;
+ }
+
+ return XNFprintf("%s, pipe %c, %s, %chsync, %cvsync",
+ enable, pipe, stall, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_sdvo)
+{
+ char *enable = val & SDVO_ENABLE ? "enabled" : "disabled";
+ char pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A';
+ char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled";
+ char *detected = val & SDVO_DETECTED ? "" : "not ";
+ char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : "";
+ char sdvoextra[20];
+
+ if (IS_I915G(pI830) || IS_I915GM(pI830)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_PORT_MULTIPLY_MASK) >>
+ SDVO_PORT_MULTIPLY_SHIFT) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ return XNFprintf("%s, pipe %c, stall %s, %sdetected%s%s",
+ enable, pipe, stall, detected, sdvoextra, gang);
+}
+
+#if 0
+DEBUGSTRING(i810_debug_fence_new)
+{
+ char *enable = (val & FENCE_VALID) ? "enabled" : "disabled";
+ char format = (val & I965_FENCE_Y_MAJOR) ? 'Y' : 'X';
+ int pitch = ((val & 0xffc) >> 2) * 128;
+ unsigned int offset = val & 0xfffff000;
+
+ return XNFprintf("%s, %c tile walk, %d pitch, 0x%08x offset",
+ enable, format, pitch, offset);
+}
+#endif
+
+#define DEFINEREG(reg) \
+ { reg, #reg, NULL, 0 }
+#define DEFINEREG2(reg, func) \
+ { reg, #reg, func, 0 }
+
+static struct i830SnapshotRec {
+ int reg;
+ char *name;
+ char *(*debug_output)(I830Ptr pI830, int reg, CARD32 val);
+ CARD32 val;
+} i830_snapshot[] = {
+ DEFINEREG2(VCLK_DIVISOR_VGA0, i830_debug_fp),
+ DEFINEREG2(VCLK_DIVISOR_VGA1, i830_debug_fp),
+ DEFINEREG2(VCLK_POST_DIV, i830_debug_vga_pd),
+ DEFINEREG2(DPLL_TEST, i830_debug_dpll_test),
+ DEFINEREG(D_STATE),
+ DEFINEREG(DSPCLK_GATE_D),
+ DEFINEREG(RENCLK_GATE_D1),
+ DEFINEREG(RENCLK_GATE_D2),
+/* DEFINEREG(RAMCLK_GATE_D), CRL only */
+ DEFINEREG2(SDVOB, i830_debug_sdvo),
+ DEFINEREG2(SDVOC, i830_debug_sdvo),
+/* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
+/* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
+ DEFINEREG(SDVOUDI),
+ DEFINEREG(DSPARB),
+ DEFINEREG(DSPFW1),
+ DEFINEREG(DSPFW2),
+ DEFINEREG(DSPFW3),
+
+ DEFINEREG2(ADPA, i830_debug_adpa),
+ DEFINEREG2(LVDS, i830_debug_lvds),
+ DEFINEREG2(DVOA, i830_debug_dvo),
+ DEFINEREG2(DVOB, i830_debug_dvo),
+ DEFINEREG2(DVOC, i830_debug_dvo),
+ DEFINEREG(DVOA_SRCDIM),
+ DEFINEREG(DVOB_SRCDIM),
+ DEFINEREG(DVOC_SRCDIM),
+
+ DEFINEREG2(PP_CONTROL, i830_debug_pp_control),
+ DEFINEREG2(PP_STATUS, i830_debug_pp_status),
+ DEFINEREG(PFIT_CONTROL),
+ DEFINEREG(PFIT_PGM_RATIOS),
+ DEFINEREG(PORT_HOTPLUG_EN),
+ DEFINEREG(PORT_HOTPLUG_STAT),
+
+ DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPASTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPAPOS, i830_debug_xy),
+ DEFINEREG2(DSPASIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPABASE),
+ DEFINEREG(DSPASURF),
+ DEFINEREG(DSPATILEOFF),
+ DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
+
+ DEFINEREG(FBC_CFB_BASE),
+ DEFINEREG(FBC_LL_BASE),
+ DEFINEREG(FBC_CONTROL),
+ DEFINEREG(FBC_COMMAND),
+ DEFINEREG(FBC_STATUS),
+ DEFINEREG(FBC_CONTROL2),
+ DEFINEREG(FBC_FENCE_OFF),
+ DEFINEREG(FBC_MOD_NUM),
+
+ DEFINEREG2(FPA0, i830_debug_fp),
+ DEFINEREG2(FPA1, i830_debug_fp),
+ DEFINEREG2(DPLL_A, i830_debug_dpll),
+ DEFINEREG(DPLL_A_MD),
+ DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_A),
+ DEFINEREG(VSYNCSHIFT_A),
+
+ DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPBPOS, i830_debug_xy),
+ DEFINEREG2(DSPBSIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPBBASE),
+ DEFINEREG(DSPBSURF),
+ DEFINEREG(DSPBTILEOFF),
+ DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
+
+ DEFINEREG2(FPB0, i830_debug_fp),
+ DEFINEREG2(FPB1, i830_debug_fp),
+ DEFINEREG2(DPLL_B, i830_debug_dpll),
+ DEFINEREG(DPLL_B_MD),
+ DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_B),
+ DEFINEREG(VSYNCSHIFT_B),
+
+ DEFINEREG(VCLK_DIVISOR_VGA0),
+ DEFINEREG(VCLK_DIVISOR_VGA1),
+ DEFINEREG(VCLK_POST_DIV),
+ DEFINEREG2(VGACNTRL, i830_debug_vgacntrl),
+
+ DEFINEREG(TV_CTL),
+ DEFINEREG(TV_DAC),
+ DEFINEREG(TV_CSC_Y),
+ DEFINEREG(TV_CSC_Y2),
+ DEFINEREG(TV_CSC_U),
+ DEFINEREG(TV_CSC_U2),
+ DEFINEREG(TV_CSC_V),
+ DEFINEREG(TV_CSC_V2),
+ DEFINEREG(TV_CLR_KNOBS),
+ DEFINEREG(TV_CLR_LEVEL),
+ DEFINEREG(TV_H_CTL_1),
+ DEFINEREG(TV_H_CTL_2),
+ DEFINEREG(TV_H_CTL_3),
+ DEFINEREG(TV_V_CTL_1),
+ DEFINEREG(TV_V_CTL_2),
+ DEFINEREG(TV_V_CTL_3),
+ DEFINEREG(TV_V_CTL_4),
+ DEFINEREG(TV_V_CTL_5),
+ DEFINEREG(TV_V_CTL_6),
+ DEFINEREG(TV_V_CTL_7),
+ DEFINEREG(TV_SC_CTL_1),
+ DEFINEREG(TV_SC_CTL_2),
+ DEFINEREG(TV_SC_CTL_3),
+ DEFINEREG(TV_WIN_POS),
+ DEFINEREG(TV_WIN_SIZE),
+ DEFINEREG(TV_FILTER_CTL_1),
+ DEFINEREG(TV_FILTER_CTL_2),
+ DEFINEREG(TV_FILTER_CTL_3),
+ DEFINEREG(TV_CC_CONTROL),
+ DEFINEREG(TV_CC_DATA),
+ DEFINEREG(TV_H_LUMA_0),
+ DEFINEREG(TV_H_LUMA_59),
+ DEFINEREG(TV_H_CHROMA_0),
+ DEFINEREG(TV_H_CHROMA_59),
+
+#if 0
+ DEFINEREG2(FENCE_NEW + 0, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 8, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 16, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 24, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 32, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 40, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 48, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 56, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 64, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 72, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 80, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 88, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 96, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 104, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 112, i810_debug_fence_new),
+ DEFINEREG2(FENCE_NEW + 120, i810_debug_fence_new),
+#endif
+};
+#undef DEFINEREG
+#define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
+
+#ifndef REG_DUMPER
+void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+
+ for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+ i830_snapshot[i].val = INREG(i830_snapshot[i].reg);
+ }
+}
+
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Comparing regs from server start up to %s\n", where);
+ for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+ CARD32 val = INREG(i830_snapshot[i].reg);
+ if (i830_snapshot[i].val == val)
+ continue;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
+ i830_snapshot[i].reg, i830_snapshot[i].name,
+ (int)i830_snapshot[i].val, (int)val);
+
+ if (i830_snapshot[i].debug_output != NULL) {
+ char *before, *after;
+
+ before = i830_snapshot[i].debug_output(pI830,
+ i830_snapshot[i].reg,
+ i830_snapshot[i].val);
+ after = i830_snapshot[i].debug_output(pI830,
+ i830_snapshot[i].reg,
+ val);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s before: %s\n", i830_snapshot[i].name, before);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s after: %s\n", i830_snapshot[i].name, after);
+
+ }
+ }
+}
+#endif /* !REG_DUMPER */
+
+static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+
+ for (i = min; i <= max; i++) {
+ OUTREG8 (id, i);
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%18.18s%02x: 0x%02x\n",
+ name, i, INREG8(val));
+ }
+}
+
+static void i830DumpAR(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ uint16_t st01;
+ unsigned char orig_arx, msr;
+
+ msr = INREG8(0x3cc);
+ if (msr & 1)
+ st01 = 0x3da;
+ else
+ st01 = 0x3ba;
+
+ INREG8(st01); /* make sure index/write register is in index mode */
+ orig_arx = INREG8(0x3c0);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%19.19sX: 0x%02x\n",
+ "AR", orig_arx);
+
+ for (i = 0; i <= 0x14; i++) {
+ INREG8(st01);
+ OUTREG8(0x3c0, i);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%18.18s%02x: 0x%02x\n",
+ "AR", i, INREG8(0x3c1));
+ }
+ INREG8(st01);
+ OUTREG8(0x3c0, orig_arx);
+}
+
+void i830DumpRegs (ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ int fp, dpll;
+ int pipe;
+ int n, m1, m2, m, p1, p2;
+ int ref;
+ int dot;
+ int phase;
+ int msr;
+ int crt;
+
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
+ for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+ CARD32 val = INREG(i830_snapshot[i].reg);
+
+ if (i830_snapshot[i].debug_output != NULL) {
+ char *debug = i830_snapshot[i].debug_output(pI830,
+ i830_snapshot[i].reg,
+ val);
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x (%s)\n",
+ i830_snapshot[i].name, (unsigned int)val, debug);
+ xfree(debug);
+ } else {
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
+ i830_snapshot[i].name, (unsigned int)val);
+ }
+ }
+ i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
+ msr = INREG8(0x3cc);
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%02x\n",
+ "MSR", (unsigned int) msr);
+
+ i830DumpAR (pScrn);
+ if (msr & 1)
+ crt = 0x3d0;
+ else
+ crt = 0x3b0;
+ i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
+ for (pipe = 0; pipe <= 1; pipe++)
+ {
+ fp = INREG(pipe == 0 ? FPA0 : FPB0);
+ dpll = INREG(pipe == 0 ? DPLL_A : DPLL_B);
+ if (IS_I9XX(pI830))
+ {
+ CARD32 lvds = INREG(LVDS);
+ if ((lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+ {
+ if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ }
+ else
+ {
+ switch ((dpll >> 24) & 0x3) {
+ case 0:
+ p2 = 10;
+ break;
+ case 1:
+ p2 = 5;
+ break;
+ default:
+ p2 = 1;
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p2 out of range\n");
+ break;
+ }
+ }
+ switch ((dpll >> 16) & 0xff) {
+ case 1:
+ p1 = 1; break;
+ case 2:
+ p1 = 2; break;
+ case 4:
+ p1 = 3; break;
+ case 8:
+ p1 = 4; break;
+ case 16:
+ p1 = 5; break;
+ case 32:
+ p1 = 6; break;
+ case 64:
+ p1 = 7; break;
+ case 128:
+ p1 = 8; break;
+ default:
+ p1 = 1;
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "p1 out of range\n");
+ break;
+ }
+ }
+ else
+ {
+ CARD32 lvds = INREG(LVDS);
+ if (IS_I85X (pI830) &&
+ (lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (pipe << 30))
+ {
+ if ((lvds & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ switch ((dpll >> 16) & 0x3f) {
+ case 0x01: p1 = 1; break;
+ case 0x02: p1 = 2; break;
+ case 0x04: p1 = 3; break;
+ case 0x08: p1 = 4; break;
+ case 0x10: p1 = 5; break;
+ case 0x20: p1 = 6; break;
+ default:
+ p1 = 1;
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "LVDS P1 0x%x invalid encoding\n",
+ (dpll >> 16) & 0x3f);
+ break;
+ }
+ }
+ else
+ {
+ if (dpll & (1 << 23))
+ p2 = 4;
+ else
+ p2 = 2;
+ if (dpll & PLL_P1_DIVIDE_BY_TWO)
+ p1 = 2;
+ else
+ p1 = ((dpll >> 16) & 0x3f) + 2;
+ }
+ }
+ switch ((dpll >> 13) & 0x3) {
+ case 0:
+ ref = 96000;
+ break;
+ case 3:
+ ref = 100000;
+ break;
+ default:
+ ref = 0;
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "ref out of range\n");
+ break;
+ }
+ if (IS_I965G(pI830)) {
+ phase = (dpll >> 9) & 0xf;
+ switch (phase) {
+ case 6:
+ break;
+ default:
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+ "SDVO phase shift %d out of range -- probobly not "
+ "an issue.\n", phase);
+ break;
+ }
+ }
+ switch ((dpll >> 8) & 1) {
+ case 0:
+ break;
+ default:
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+ "fp select out of range\n");
+ break;
+ }
+ n = ((fp >> 16) & 0x3f);
+ m1 = ((fp >> 8) & 0x3f);
+ m2 = ((fp >> 0) & 0x3f);
+ m = 5 * (m1 + 2) + (m2 + 2);
+ dot = (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 * p2);
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
+ pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
+ }
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n");
+}
+
+#ifndef REG_DUMPER
+
+#define NUM_RING_DUMP 64
+
+static void
+i830_dump_ring(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned int head, tail, ring, mask;
+ volatile unsigned char *virt;
+
+ head = (INREG (LP_RING + RING_HEAD)) & I830_HEAD_MASK;
+ tail = INREG (LP_RING + RING_TAIL) & I830_TAIL_MASK;
+ mask = pI830->LpRing->tail_mask;
+
+ virt = pI830->LpRing->virtual_start;
+ ErrorF ("Ring at virtual 0x%x head 0x%x tail 0x%x count %d\n",
+ (unsigned int) virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2);
+ for (ring = (head - 128) & mask; ring != ((head + 4) & mask);
+ ring = (ring + 4) & mask)
+ {
+ ErrorF ("\t%08x: %08x\n", ring, *(volatile unsigned int *) (virt + ring));
+ }
+ ErrorF ("Ring end\n");
+}
+
+/* Famous last words
+ */
+void
+i830_dump_error_state(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
+ (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR));
+
+ ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR),
+ (unsigned long)INREG(IPEHR));
+
+ ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
+ (unsigned long)INREG(LP_RING + RING_TAIL),
+ (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+ (unsigned long)INREG(LP_RING + RING_LEN),
+ (unsigned long)INREG(LP_RING + RING_START));
+
+ ErrorF("eir: %x esr: %x emr: %x\n",
+ INREG16(EIR), INREG16(ESR), INREG16(EMR));
+
+ ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
+
+ ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE),
+ (unsigned long)INREG(INST_PS));
+
+ ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
+ INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
+ i830_dump_ring (pScrn);
+}
+
+void
+i965_dump_error_state(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_I965), INREG(IPEHR_I965));
+
+ 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("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n",
+ (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR));
+
+ ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965),
+ (int)INREG(INST_DONE_1));
+ ErrorF("instpm: %x\n", (int)INREG(INST_PM));
+
+ ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965));
+
+ ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x "
+ "imr: %x iir: %x\n",
+ (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR),
+ (int)INREG(IIR));
+
+ ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P));
+ ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC));
+
+ ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0),
+ (int)INREG(CACHE_MODE_1));
+ ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE));
+
+ ErrorF("IA_VERTICES_COUNT_QW %x/%x\n",
+ (int)INREG(IA_VERTICES_COUNT_QW),
+ (int)INREG(IA_VERTICES_COUNT_QW+4));
+ ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n",
+ (int)INREG(IA_PRIMITIVES_COUNT_QW),
+ (int)INREG(IA_PRIMITIVES_COUNT_QW+4));
+
+ ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n",
+ (int)INREG(VS_INVOCATION_COUNT_QW),
+ (int)INREG(VS_INVOCATION_COUNT_QW+4));
+
+ ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n",
+ (int)INREG(GS_INVOCATION_COUNT_QW),
+ (int)INREG(GS_INVOCATION_COUNT_QW+4));
+ ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n",
+ (int)INREG(GS_PRIMITIVES_COUNT_QW),
+ (int)INREG(GS_PRIMITIVES_COUNT_QW+4));
+
+ ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n",
+ (int)INREG(CL_INVOCATION_COUNT_QW),
+ (int)INREG(CL_INVOCATION_COUNT_QW+4));
+ ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n",
+ (int)INREG(CL_PRIMITIVES_COUNT_QW),
+ (int)INREG(CL_PRIMITIVES_COUNT_QW+4));
+
+ ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n",
+ (int)INREG(PS_INVOCATION_COUNT_QW),
+ (int)INREG(PS_INVOCATION_COUNT_QW+4));
+ ErrorF("PS_DEPTH_COUNT_QW %x/%x\n",
+ (int)INREG(PS_DEPTH_COUNT_QW),
+ (int)INREG(PS_DEPTH_COUNT_QW+4));
+
+ ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL));
+ ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL),
+ (int)INREG(TS_DEBUG_DATA));
+ ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2));
+}
+
+/**
+ * Checks the hardware error state bits.
+ *
+ * \return TRUE if any errors were found.
+ */
+Bool
+i830_check_error_state(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int errors = 0;
+ unsigned long temp, head, tail;
+
+ if (!I830IsPrimary(pScrn)) return TRUE;
+
+ temp = INREG16(ESR);
+ if (temp != 0) {
+ Bool vertex_max = !IS_I965G(pI830) && (temp & ERR_VERTEX_MAX);
+ Bool pgtbl = temp & ERR_PGTBL_ERROR;
+ Bool underrun = !IS_I965G(pI830) &&
+ (temp & ERR_DISPLAY_OVERLAY_UNDERRUN);
+ Bool instruction = !IS_I965G(pI830) && (temp & ERR_INSTRUCTION_ERROR);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "ESR is 0x%08lx%s%s%s%s\n", temp,
+ vertex_max ? ", max vertices exceeded" : "",
+ pgtbl ? ", page table error" : "",
+ underrun ? ", display/overlay underrun" : "",
+ instruction ? ", instruction error" : "");
+ errors++;
+ }
+ /* Check first for page table errors */
+ if (!IS_I9XX(pI830)) {
+ temp = INREG(PGE_ERR);
+ if (temp != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PGTBL_ER is 0x%08lx\n", temp);
+ errors++;
+ }
+ } else {
+ temp = INREG(PGTBL_ER);
+ if (temp != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "PGTBL_ER is 0x%08lx"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", temp,
+ temp & PGTBL_ERR_HOST_GTT_PTE ? ", host gtt pte" : "",
+ temp & PGTBL_ERR_HOST_PTE_DATA ? ", host pte data" : "",
+ temp & PGTBL_ERR_DISPA_GTT_PTE ? ", display A pte" : "",
+ temp & PGTBL_ERR_DISPA_TILING ?
+ ", display A tiling" : "",
+ temp & PGTBL_ERR_DISPB_GTT_PTE ? ", display B pte" : "",
+ temp & PGTBL_ERR_DISPB_TILING ?
+ ", display B tiling" : "",
+ temp & PGTBL_ERR_DISPC_GTT_PTE ? ", display C pte" : "",
+ temp & PGTBL_ERR_DISPC_TILING ?
+ ", display C tiling" : "",
+ temp & PGTBL_ERR_OVERLAY_GTT_PTE ?
+ ", overlay GTT PTE" : "",
+ temp & PGTBL_ERR_OVERLAY_TILING ?
+ ", overlay tiling" : "",
+ temp & PGTBL_ERR_CS_GTT ? ", CS GTT" : "",
+ temp & PGTBL_ERR_CS_INSTRUCTION_GTT_PTE ?
+ ", CS instruction GTT PTE" : "",
+ temp & PGTBL_ERR_CS_VERTEXDATA_GTT_PTE ?
+ ", CS vertex data GTT PTE" : "",
+ temp & PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE ?
+ ", BIN instruction GTT PTE" : "",
+ temp & PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE ?
+ ", BIN vertex data GTT PTE" : "",
+ temp & PGTBL_ERR_LC_GTT_PTE ? ", LC pte" : "",
+ temp & PGTBL_ERR_LC_TILING ? ", LC tiling" : "",
+ temp & PGTBL_ERR_MT_GTT_PTE ? ", MT pte" : "",
+ temp & PGTBL_ERR_MT_TILING ? ", MT tiling" : "");
+ 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) {
+ if (IS_I965G(pI830))
+ i965_dump_error_state(pScrn);
+ else
+ i830_dump_error_state(pScrn);
+ }
+#endif
+
+ return (errors != 0);
+}
+#endif /* !REG_DUMPER */
diff --git a/driver/xf86-video-intel/src/i830_debug.h b/driver/xf86-video-intel/src/i830_debug.h
new file mode 100644
index 000000000..2d2e72bf1
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_debug.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+void i830TakeRegSnapshot(ScrnInfoPtr pScrn);
+void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where);
+void i830DumpRegs (ScrnInfoPtr pScrn);
+void i830_dump_error_state(ScrnInfoPtr pScrn);
+void i965_dump_error_state(ScrnInfoPtr pScrn);
+Bool i830_check_error_state(ScrnInfoPtr pScrn);
+
diff --git a/driver/xf86-video-intel/src/i830_display.c b/driver/xf86-video-intel/src/i830_display.c
new file mode 100644
index 000000000..0e4262498
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_display.c
@@ -0,0 +1,1732 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_bios.h"
+#include "i830_display.h"
+#include "i830_debug.h"
+#include "xf86Modes.h"
+
+typedef struct {
+ /* given values */
+ int n;
+ int m1, m2;
+ int p1, p2;
+ /* derived values */
+ int dot;
+ int vco;
+ int m;
+ int p;
+} intel_clock_t;
+
+typedef struct {
+ int min, max;
+} intel_range_t;
+
+typedef struct {
+ int dot_limit;
+ int p2_slow, p2_fast;
+} intel_p2_t;
+
+#define INTEL_P2_NUM 2
+
+typedef struct {
+ intel_range_t dot, vco, n, m, m1, m2, p, p1;
+ intel_p2_t p2;
+} intel_limit_t;
+
+#define I8XX_DOT_MIN 25000
+#define I8XX_DOT_MAX 350000
+#define I8XX_VCO_MIN 930000
+#define I8XX_VCO_MAX 1400000
+#define I8XX_N_MIN 3
+#define I8XX_N_MAX 16
+#define I8XX_M_MIN 96
+#define I8XX_M_MAX 140
+#define I8XX_M1_MIN 18
+#define I8XX_M1_MAX 26
+#define I8XX_M2_MIN 6
+#define I8XX_M2_MAX 16
+#define I8XX_P_MIN 4
+#define I8XX_P_MAX 128
+#define I8XX_P1_MIN 2
+#define I8XX_P1_MAX 33
+#define I8XX_P1_LVDS_MIN 1
+#define I8XX_P1_LVDS_MAX 6
+#define I8XX_P2_SLOW 4
+#define I8XX_P2_FAST 2
+#define I8XX_P2_LVDS_SLOW 14
+#define I8XX_P2_LVDS_FAST 7
+#define I8XX_P2_SLOW_LIMIT 165000
+
+#define I9XX_DOT_MIN 20000
+#define I9XX_DOT_MAX 400000
+#define I9XX_VCO_MIN 1400000
+#define I9XX_VCO_MAX 2800000
+
+/* Haven't found any reason to go this fast, but newer chips support it */
+#define I96X_VCO_MAX 3200000
+
+/*
+ * These values are taken from the broadwater/crestline PLL spreadsheet.
+ * All of the defines here are for the programmed register value, not
+ * the 'counter' value (e.g. Ncounter = Nregister + 2)
+ */
+#define I9XX_N_MIN 1
+#define I9XX_N_MAX 6
+#define I9XX_M_MIN 70
+#define I9XX_M_MAX 120
+
+/* these two come from the calm1 macro */
+#define I9XX_M1_MIN 10
+#define I9XX_M1_MAX 22
+#define I9XX_M2_MIN 5
+#define I9XX_M2_MAX 9
+
+#define I9XX_P_SDVO_DAC_MIN 5
+#define I9XX_P_SDVO_DAC_MAX 80
+#define I9XX_P_LVDS_MIN 7
+#define I9XX_P_LVDS_MAX 98
+#define I9XX_P1_MIN 1
+#define I9XX_P1_MAX 8
+#define I9XX_P2_SDVO_DAC_SLOW 10
+#define I9XX_P2_SDVO_DAC_FAST 5
+#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000
+#define I9XX_P2_LVDS_SLOW 14
+#define I9XX_P2_LVDS_FAST 7
+#define I9XX_P2_LVDS_SLOW_LIMIT 112000
+
+#define INTEL_LIMIT_I8XX_DVO_DAC 0
+#define INTEL_LIMIT_I8XX_LVDS 1
+#define INTEL_LIMIT_I9XX_SDVO_DAC 2
+#define INTEL_LIMIT_I9XX_LVDS 3
+
+static const intel_limit_t intel_limits[] = {
+ { /* INTEL_LIMIT_I8XX_DVO_DAC */
+ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
+ .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
+ .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
+ .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX },
+ .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX },
+ .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX },
+ .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX },
+ .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX },
+ .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+ .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
+ },
+ { /* INTEL_LIMIT_I8XX_LVDS */
+ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
+ .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
+ .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
+ .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX },
+ .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX },
+ .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX },
+ .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX },
+ .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX },
+ .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+ .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
+ },
+ { /* INTEL_LIMIT_I9XX_SDVO_DAC */
+ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
+ .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
+ .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
+ .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX },
+ .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX },
+ .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX },
+ .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX },
+ .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
+ .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
+ .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
+ },
+ { /* INTEL_LIMIT_I9XX_LVDS */
+ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
+ .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
+ .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
+ .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX },
+ .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX },
+ .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX },
+ .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX },
+ .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
+ /* The single-channel range is 25-112Mhz, and dual-channel
+ * is 80-224Mhz. Prefer single channel as much as possible.
+ */
+ .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
+ .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
+ },
+};
+
+static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ const intel_limit_t *limit;
+
+ if (IS_I9XX(pI830)) {
+ if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+ limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+ else
+ limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+ } else {
+ if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+ limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+ else
+ limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+ }
+
+ return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+static void i8xx_clock(int refclk, intel_clock_t *clock)
+{
+ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+ clock->p = clock->p1 * clock->p2;
+ clock->vco = refclk * clock->m / (clock->n + 2);
+ clock->dot = clock->vco / clock->p;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
+
+static void i9xx_clock(int refclk, intel_clock_t *clock)
+{
+ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+ clock->p = clock->p1 * clock->p2;
+ clock->vco = refclk * clock->m / (clock->n + 2);
+ clock->dot = clock->vco / clock->p;
+}
+
+static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock)
+{
+ if (IS_I9XX(pI830))
+ i9xx_clock (refclk, clock);
+ else
+ i8xx_clock (refclk, clock);
+}
+
+static void
+i830PrintPll(char *prefix, intel_clock_t *clock)
+{
+ ErrorF("%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, (p %d, p1 %d, p2 %d))\n",
+ prefix, clock->dot, clock->vco,
+ clock->m, clock->m1, clock->m2,
+ clock->n,
+ clock->p, clock->p1, clock->p2);
+}
+
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+Bool
+i830PipeHasType (xf86CrtcPtr crtc, int type)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ {
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ if (intel_output->type == type)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#define i830PllInvalid(s) { /* ErrorF (s) */; return FALSE; }
+/**
+ * Returns whether the given set of divisors are valid for a given refclk with
+ * the given outputs.
+ */
+
+static Bool
+i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
+{
+ const intel_limit_t *limit = intel_limit (crtc);
+
+ if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+ i830PllInvalid ("p1 out of range\n");
+ if (clock->p < limit->p.min || limit->p.max < clock->p)
+ i830PllInvalid ("p out of range\n");
+ if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
+ i830PllInvalid ("m2 out of range\n");
+ if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
+ i830PllInvalid ("m1 out of range\n");
+ if (clock->m1 <= clock->m2)
+ i830PllInvalid ("m1 <= m2\n");
+ if (clock->m < limit->m.min || limit->m.max < clock->m)
+ i830PllInvalid ("m out of range\n");
+ if (clock->n < limit->n.min || limit->n.max < clock->n)
+ i830PllInvalid ("n out of range\n");
+ if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+ i830PllInvalid ("vco out of range\n");
+ /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
+ * output, etc., rather than just a single range.
+ */
+ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+ i830PllInvalid ("dot out of range\n");
+
+ return TRUE;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE. The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
+static Bool
+i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk, intel_clock_t *best_clock)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ intel_clock_t clock;
+ const intel_limit_t *limit = intel_limit (crtc);
+ int err = target;
+
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
+ {
+ /* For LVDS, if the panel is on, just rely on its current settings for
+ * dual-channel. We haven't figured out how to reliably set up
+ * different single/dual channel state, if we even can.
+ */
+ if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+ clock.p2 = limit->p2.p2_fast;
+ else
+ clock.p2 = limit->p2.p2_slow;
+ } else {
+ if (target < limit->p2.dot_limit)
+ clock.p2 = limit->p2.p2_slow;
+ else
+ clock.p2 = limit->p2.p2_fast;
+ }
+
+ memset (best_clock, 0, sizeof (*best_clock));
+
+ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++)
+ {
+ for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; clock.m2++)
+ {
+ for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++)
+ {
+ for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++)
+ {
+ int this_err;
+
+ intel_clock (pI830, refclk, &clock);
+
+ if (!i830PllIsValid(crtc, &clock))
+ continue;
+
+ this_err = abs(clock.dot - target);
+ if (this_err < err) {
+ *best_clock = clock;
+ err = this_err;
+ }
+ }
+ }
+ }
+ }
+ return (err != target);
+}
+
+void
+i830WaitForVblank(ScrnInfoPtr pScreen)
+{
+ /* Wait for 20ms, i.e. one cycle at 50hz. */
+ usleep(30000);
+}
+
+void
+i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int plane = intel_crtc->plane;
+ unsigned long Start, Offset;
+ int dspbase = (plane == 0 ? DSPABASE : DSPBBASE);
+ int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
+ int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
+
+ Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
+ if (pI830->front_buffer == NULL) {
+ /* During startup we may be called as part of monitor detection while
+ * there is no memory allocation done, so just supply a dummy base
+ * address.
+ */
+ Start = 0;
+ } else if (crtc->rotatedData != NULL) {
+ /* offset is done by shadow painting code, not here */
+ Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
+ Offset = 0;
+ } else if (I830IsPrimary(pScrn)) {
+ Start = pI830->front_buffer->offset;
+ } else {
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ Start = pI8301->front_buffer_2->offset;
+ }
+
+ if (IS_I965G(pI830)) {
+ OUTREG(dspbase, Offset);
+ POSTING_READ(dspbase);
+ OUTREG(dspsurf, Start);
+ POSTING_READ(dspsurf);
+ OUTREG(dsptileoff, (y << 16) | x);
+ } else {
+ OUTREG(dspbase, Start + Offset);
+ POSTING_READ(dspbase);
+ }
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+
+ if (!sPriv)
+ return;
+
+ switch (plane) {
+ case 0:
+ sPriv->planeA_x = x;
+ sPriv->planeA_y = y;
+ break;
+ case 1:
+ sPriv->planeB_x = x;
+ sPriv->planeB_y = y;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't update pipe %d in SAREA\n", pipe);
+ break;
+ }
+ }
+#endif
+}
+
+/*
+ * Both crtc activation and video overlay enablement on pipe B
+ * will fail on i830 if pipe A is not running. This function
+ * makes sure pipe A is active for these cases
+ */
+
+int
+i830_crtc_pipe (xf86CrtcPtr crtc)
+{
+ if (crtc == NULL)
+ return 0;
+ return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
+}
+
+static xf86CrtcPtr
+i830_crtc_for_pipe (ScrnInfoPtr scrn, int pipe)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ if (i830_crtc_pipe (crtc) == pipe)
+ return crtc;
+ }
+ return NULL;
+}
+
+Bool
+i830_pipe_a_require_activate (ScrnInfoPtr scrn)
+{
+ xf86CrtcPtr crtc = i830_crtc_for_pipe (scrn, 0);
+ /* VESA 640x480x72Hz mode to set on the pipe */
+ static DisplayModeRec mode = {
+ NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+ 31500,
+ 640, 664, 704, 832, 0,
+ 480, 489, 491, 520, 0,
+ V_NHSYNC | V_NVSYNC,
+ 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+ };
+
+ if (!crtc)
+ return FALSE;
+ if (crtc->enabled)
+ return FALSE;
+ xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+ return TRUE;
+}
+
+void
+i830_pipe_a_require_deactivate (ScrnInfoPtr scrn)
+{
+ xf86CrtcPtr crtc = i830_crtc_for_pipe (scrn, 0);
+
+ if (!crtc)
+ return;
+ if (crtc->enabled)
+ return;
+ crtc->funcs->dpms (crtc, DPMSModeOff);
+ return;
+}
+
+/* FIXME: use pixmap private instead if possible */
+static Bool
+i830_display_tiled(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* Rotated data is currently linear, allocated either via XAA or EXA */
+ if (crtc->rotatedData)
+ return FALSE;
+
+ if (pI830->front_buffer && pI830->front_buffer->tiling != TILE_NONE)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool
+i830_use_fb_compression(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+
+ if (!pI830->fb_compression)
+ return FALSE;
+
+ if (!i830_display_tiled(crtc))
+ return FALSE;
+
+ /* Pre-965 only supports plane A */
+ if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
+ return FALSE;
+
+ /* Need 15, 16, or 32 (w/alpha) pixel format */
+ if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
+ pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
+ return FALSE;
+
+ /*
+ * No checks for pixel multiply, incl. horizontal, or interlaced modes
+ * since they're currently unused.
+ */
+ return TRUE;
+}
+
+/*
+ * Several restrictions:
+ * - DSP[AB]CNTR - no line duplication && no pixel multiplier
+ * - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
+ * - no alpha buffer discard
+ * - no dual wide display
+ * - progressive mode only (DSP[AB]CNTR)
+ * - uncompressed fb is <= 2048 in width, 0 mod 8
+ * - uncompressed fb is <= 1536 in height, 0 mod 2
+ * - SR display watermarks must be equal between 16bpp and 32bpp?
+ *
+ * FIXME: verify above conditions are true
+ */
+static void
+i830_enable_fb_compression(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ uint32_t fbc_ctl = 0;
+ unsigned long compressed_stride;
+ int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
+ unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
+ unsigned long interval = 1000;
+
+ if (INREG(FBC_CONTROL) & FBC_CTL_EN) {
+ char cur_plane = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "fbc already enabled on "
+ "plane %c, not enabling on plane %c\n", cur_plane,
+ plane ? 'b' : 'a');
+ return;
+ }
+
+ compressed_stride = pI830->compressed_front_buffer->size /
+ FBC_LL_SIZE;
+
+ if (uncompressed_stride < compressed_stride)
+ compressed_stride = uncompressed_stride;
+
+ /* FBC_CTL wants 64B units */
+ compressed_stride = (compressed_stride / 64) - 1;
+
+ /* Set it up... */
+ /* Wait for compressing bit to clear */
+ while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
+ ; /* nothing */
+ i830WaitForVblank(pScrn);
+ OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
+ OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + 6);
+ OUTREG(FBC_CONTROL2, FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_FULL |
+ FBC_CTL_CPU_FENCE | plane);
+
+ /* Zero buffers */
+ memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
+ pI830->compressed_front_buffer->size);
+ memset(pI830->FbBase + pI830->compressed_ll_buffer->offset, 0,
+ pI830->compressed_ll_buffer->size);
+
+ /* enable it... */
+ fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
+ fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
+ fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
+ fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE;
+ fbc_ctl |= pI830->front_buffer->fence_nr;
+ OUTREG(FBC_CONTROL, fbc_ctl);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc enabled on plane %c\n", plane ?
+ 'b' : 'a');
+}
+
+static void
+i830_disable_fb_compression(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ uint32_t fbc_ctl;
+ char plane = (INREG(FBC_CONTROL2) & 1) ? 'b' : 'a';
+
+ /* Disable compression */
+ fbc_ctl = INREG(FBC_CONTROL);
+ fbc_ctl &= ~FBC_CTL_EN;
+ OUTREG(FBC_CONTROL, fbc_ctl);
+
+ /* Wait for compressing bit to clear */
+ while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
+ ; /* nothing */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "fbc disabled on plane %c\n", plane);
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void
+i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int plane = intel_crtc->plane;
+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+ int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
+ CARD32 temp;
+
+ /* XXX: When our outputs are all unaware of DPMS modes other than off and
+ * on, we should map those modes to DPMSModeOff in the CRTC.
+ */
+ switch (mode) {
+ case DPMSModeOn:
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ /* Enable the DPLL */
+ temp = INREG(dpll_reg);
+ if ((temp & DPLL_VCO_ENABLE) == 0)
+ {
+ OUTREG(dpll_reg, temp);
+ POSTING_READ(dpll_reg);
+ /* Wait for the clocks to stabilize. */
+ usleep(150);
+ OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+ POSTING_READ(dpll_reg);
+ /* Wait for the clocks to stabilize. */
+ usleep(150);
+ OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+ POSTING_READ(dpll_reg);
+ /* Wait for the clocks to stabilize. */
+ usleep(150);
+ }
+
+ /* Enable the pipe */
+ temp = INREG(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) == 0)
+ OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+
+ /* Enable the plane */
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) == 0)
+ {
+ OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ }
+
+ i830_crtc_load_lut(crtc);
+
+ /* Give the overlay scaler a chance to enable if it's on this pipe */
+ i830_crtc_dpms_video(crtc, TRUE);
+
+ /* Reenable compression if needed */
+ if (i830_use_fb_compression(crtc))
+ i830_enable_fb_compression(crtc);
+ break;
+ case DPMSModeOff:
+ /* Shut off compression if in use */
+ if (i830_use_fb_compression(crtc))
+ i830_disable_fb_compression(crtc);
+
+ /* Give the overlay scaler a chance to disable if it's on this pipe */
+ i830_crtc_dpms_video(crtc, FALSE);
+
+ /* Disable the VGA plane that we never use */
+ OUTREG(VGACNTRL, VGA_DISP_DISABLE);
+
+ /* Disable display plane */
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+ {
+ OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ POSTING_READ(dspbase_reg);
+ }
+
+ if (!IS_I9XX(pI830)) {
+ /* Wait for vblank for the disable to take effect */
+ i830WaitForVblank(pScrn);
+ }
+
+ /* Next, disable display pipes */
+ temp = INREG(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+ POSTING_READ(pipeconf_reg);
+ }
+
+ /* Wait for vblank for the disable to take effect. */
+ i830WaitForVblank(pScrn);
+
+ temp = INREG(dpll_reg);
+ if ((temp & DPLL_VCO_ENABLE) != 0) {
+ OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+ POSTING_READ(dpll_reg);
+ }
+
+ /* Wait for the clocks to turn off. */
+ usleep(150);
+ break;
+ }
+
+ intel_crtc->dpms_mode = mode;
+
+#ifdef XF86DRI
+ if (pI830->directRenderingEnabled) {
+ drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+ Bool enabled = crtc->enabled && mode != DPMSModeOff;
+
+ I830DRISetVBlankInterrupt (pScrn, TRUE);
+
+ if (!sPriv)
+ return;
+
+ switch (plane) {
+ case 0:
+ sPriv->planeA_w = enabled ? crtc->mode.HDisplay : 0;
+ sPriv->planeA_h = enabled ? crtc->mode.VDisplay : 0;
+ break;
+ case 1:
+ sPriv->planeB_w = enabled ? crtc->mode.HDisplay : 0;
+ sPriv->planeB_h = enabled ? crtc->mode.VDisplay : 0;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't update pipe %d in SAREA\n", pipe);
+ break;
+ }
+ }
+#endif
+}
+
+static Bool
+i830_crtc_lock (xf86CrtcPtr crtc)
+{
+ /* Sync the engine before mode switch */
+ i830WaitSync(crtc->scrn);
+
+#ifdef XF86DRI
+ return I830DRILock(crtc->scrn);
+#else
+ return FALSE;
+#endif
+}
+
+static void
+i830_crtc_unlock (xf86CrtcPtr crtc)
+{
+#ifdef XF86DRI
+ I830DRIUnlock (crtc->scrn);
+#endif
+}
+
+static void
+i830_crtc_prepare (xf86CrtcPtr crtc)
+{
+ /* Temporarily turn off FB compression during modeset */
+ if (i830_use_fb_compression(crtc))
+ i830_disable_fb_compression(crtc);
+ crtc->funcs->dpms (crtc, DPMSModeOff);
+}
+
+static void
+i830_crtc_commit (xf86CrtcPtr crtc)
+{
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ Bool deactivate = FALSE;
+
+ if (!intel_crtc->enabled && intel_crtc->pipe != 0)
+ deactivate = i830_pipe_a_require_activate (crtc->scrn);
+
+ intel_crtc->enabled = TRUE;
+
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+ if (crtc->scrn->pScreen != NULL)
+ xf86_reload_cursors (crtc->scrn->pScreen);
+ if (deactivate)
+ i830_pipe_a_require_deactivate (crtc->scrn);
+
+ /* Reenable FB compression if possible */
+ if (i830_use_fb_compression(crtc))
+ i830_enable_fb_compression(crtc);
+}
+
+void
+i830_output_prepare (xf86OutputPtr output)
+{
+ output->funcs->dpms (output, DPMSModeOff);
+}
+
+void
+i830_output_commit (xf86OutputPtr output)
+{
+ output->funcs->dpms (output, DPMSModeOn);
+}
+
+static Bool
+i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+/** Returns the core display clock speed for i830 - i945 */
+static int
+i830_get_core_clock_speed(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ /* Core clock values taken from the published datasheets.
+ * The 830 may go up to 166 Mhz, which we should check.
+ */
+ if (IS_I945G(pI830) || IS_G33CLASS(pI830))
+ return 400000;
+ else if (IS_I915G(pI830))
+ return 333000;
+ else if (IS_I945GM(pI830) || IS_845G(pI830))
+ return 200000;
+ else if (IS_I915GM(pI830)) {
+ uint16_t gcfgc;
+
+#if XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u16 (pI830->PciInfo, &gcfgc, I915_GCFGC);
+#else
+ gcfgc = pciReadWord(pI830->PciTag, I915_GCFGC);
+#endif
+ if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
+ return 133000;
+ else {
+ switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
+ case I915_DISPLAY_CLOCK_333_MHZ:
+ return 333000;
+ default:
+ case I915_DISPLAY_CLOCK_190_200_MHZ:
+ return 190000;
+ }
+ }
+ } else if (IS_I865G(pI830))
+ return 266000;
+ else if (IS_I855(pI830)) {
+#if XSERVER_LIBPCIACCESS
+ struct pci_device *bridge = intel_host_bridge ();
+ uint16_t hpllcc;
+ pci_device_cfg_read_u16 (bridge, &hpllcc, I855_HPLLCC);
+#else
+ PCITAG bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+ CARD16 hpllcc = pciReadWord(bridge, I855_HPLLCC);
+#endif
+
+ /* Assume that the hardware is in the high speed state. This
+ * should be the default.
+ */
+ switch (hpllcc & I855_CLOCK_CONTROL_MASK) {
+ case I855_CLOCK_133_200:
+ case I855_CLOCK_100_200:
+ return 200000;
+ case I855_CLOCK_166_250:
+ return 250000;
+ case I855_CLOCK_100_133:
+ return 133000;
+ }
+ } else /* 852, 830 */
+ return 133000;
+
+ return 0; /* Silence gcc warning */
+}
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int
+i830_panel_fitter_pipe(I830Ptr pI830)
+{
+ CARD32 pfit_control;
+
+ /* i830 doesn't have a panel fitter */
+ if (IS_I830(pI830))
+ return -1;
+
+ pfit_control = INREG(PFIT_CONTROL);
+
+ /* See if the panel fitter is in use */
+ if ((pfit_control & PFIT_ENABLE) == 0)
+ return -1;
+
+ /* 965 can place panel fitter on either pipe */
+ if (IS_I965G(pI830))
+ return (pfit_control & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
+
+ /* older chips can only use pipe 1 */
+ return 1;
+}
+
+/**
+ * Sets up registers for the given mode/adjusted_mode pair.
+ *
+ * The clocks, CRTCs and outputs attached to this CRTC must be off.
+ *
+ * This shouldn't enable any clocks, CRTCs, or outputs, but they should
+ * be easily turned on/off after this.
+ */
+static void
+i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int plane = intel_crtc->plane;
+ int fp_reg = (pipe == 0) ? FPA0 : FPB0;
+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+ int dpll_md_reg = (pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+ int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+ int dspstride_reg = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
+ int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
+ int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
+ int i;
+ int refclk;
+ intel_clock_t clock;
+ CARD32 dpll = 0, fp = 0, dspcntr, pipeconf;
+ Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
+ Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
+
+ /* Set up some convenient bools for what outputs are connected to
+ * our pipe, used in DPLL setup.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ I830OutputPrivatePtr intel_output = output->driver_private;
+
+ if (output->crtc != crtc)
+ continue;
+
+ switch (intel_output->type) {
+ case I830_OUTPUT_LVDS:
+ is_lvds = TRUE;
+ break;
+ case I830_OUTPUT_SDVO:
+ is_sdvo = TRUE;
+ break;
+ case I830_OUTPUT_DVO_TMDS:
+ case I830_OUTPUT_DVO_LVDS:
+ case I830_OUTPUT_DVO_TVOUT:
+ is_dvo = TRUE;
+ break;
+ case I830_OUTPUT_TVOUT:
+ is_tv = TRUE;
+ break;
+ case I830_OUTPUT_ANALOG:
+ is_crt = TRUE;
+ break;
+ }
+ }
+
+ if (IS_I9XX(pI830)) {
+ refclk = 96000;
+ } else {
+ refclk = 48000;
+ }
+
+ ok = i830FindBestPLL(crtc, adjusted_mode->Clock, refclk, &clock);
+ if (!ok)
+ FatalError("Couldn't find PLL settings for mode!\n");
+
+ if (fabs(adjusted_mode->Clock - clock.dot) / clock.dot > .02) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Chosen PLL clock of %.1f Mhz more than 2%% away from "
+ "desired %.1f Mhz\n",
+ (float)clock.dot / 1000,
+ (float)adjusted_mode->Clock / 1000);
+ }
+
+ fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+
+ dpll = DPLL_VGA_MODE_DIS;
+ if (IS_I9XX(pI830)) {
+ if (is_lvds)
+ dpll |= DPLLB_MODE_LVDS;
+ else
+ dpll |= DPLLB_MODE_DAC_SERIAL;
+ if (is_sdvo)
+ {
+ dpll |= DPLL_DVO_HIGH_SPEED;
+ if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ {
+ int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+ dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+ }
+ }
+
+ /* compute bitmask from p1 value */
+ dpll |= (1 << (clock.p1 - 1)) << 16;
+ switch (clock.p2) {
+ case 5:
+ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+ break;
+ case 7:
+ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+ break;
+ case 10:
+ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+ break;
+ case 14:
+ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+ break;
+ }
+ if (IS_I965G(pI830))
+ dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
+ } else {
+ if (is_lvds) {
+ dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+ } else {
+ if (clock.p1 == 2)
+ dpll |= PLL_P1_DIVIDE_BY_TWO;
+ else
+ dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+ if (clock.p2 == 4)
+ dpll |= PLL_P2_DIVIDE_BY_4;
+ }
+ }
+
+ if (is_tv)
+ {
+ /* XXX: just matching BIOS for now */
+/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
+ dpll |= 3;
+ }
+#if 0
+ else if (is_lvds)
+ dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+#endif
+ else
+ dpll |= PLL_REF_INPUT_DREFCLK;
+
+ /* Set up the display plane register */
+ dspcntr = DISPPLANE_GAMMA_ENABLE;
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ dspcntr |= DISPPLANE_8BPP;
+ break;
+ case 16:
+ if (pScrn->depth == 15)
+ dspcntr |= DISPPLANE_15_16BPP;
+ else
+ dspcntr |= DISPPLANE_16BPP;
+ break;
+ case 32:
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+ break;
+ default:
+ FatalError("unknown display bpp\n");
+ }
+
+ if (pipe == 0)
+ dspcntr |= DISPPLANE_SEL_PIPE_A;
+ else
+ dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+ if (IS_I965G(pI830) && i830_display_tiled(crtc))
+ dspcntr |= DISPLAY_PLANE_TILED;
+
+ pipeconf = INREG(pipeconf_reg);
+ if (pipe == 0 && !IS_I965G(pI830))
+ {
+ /* Enable pixel doubling when the dot clock is > 90% of the (display)
+ * core speed.
+ *
+ * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
+ * pipe == 0 check?
+ */
+ if (mode->Clock > i830_get_core_clock_speed(pScrn) * 9 / 10)
+ pipeconf |= PIPEACONF_DOUBLE_WIDE;
+ else
+ pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
+ }
+ /*
+ * This "shouldn't" be needed as the dpms on code
+ * will be run after the mode is set. On 9xx, it helps.
+ * On 855, it can lock up the chip (and the entire machine)
+ */
+ if (!IS_I85X (pI830))
+ {
+ dspcntr |= DISPLAY_PLANE_ENABLE;
+ pipeconf |= PIPEACONF_ENABLE;
+ dpll |= DPLL_VCO_ENABLE;
+ }
+
+ /* Disable the panel fitter if it was on our pipe */
+ if (i830_panel_fitter_pipe (pI830) == pipe)
+ OUTREG(PFIT_CONTROL, 0);
+
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+ xf86PrintModeline(pScrn->scrnIndex, mode);
+ if (!xf86ModesEqual(mode, adjusted_mode)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+ xf86PrintModeline(pScrn->scrnIndex, mode);
+ }
+ i830PrintPll("chosen", &clock);
+ }
+
+ if (dpll & DPLL_VCO_ENABLE)
+ {
+ OUTREG(fp_reg, fp);
+ OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+ POSTING_READ(dpll_reg);
+ usleep(150);
+ }
+
+ /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+ * This is an exception to the general rule that mode_set doesn't turn
+ * things on.
+ */
+ if (is_lvds)
+ {
+ CARD32 lvds = INREG(LVDS);
+
+ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+ /* Set the B0-B3 data pairs corresponding to whether we're going to
+ * set the DPLLs for dual-channel mode or not.
+ */
+ if (clock.p2 == I9XX_P2_LVDS_FAST)
+ lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+ else
+ lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+ /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+ * appropriately here, but we need to look more thoroughly into how
+ * panels behave in the two modes.
+ */
+
+ /* Enable dithering if we're in 18-bit mode. */
+ if (IS_I965G(pI830))
+ {
+ if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+ lvds &= ~LVDS_DITHER_ENABLE;
+ else
+ lvds |= LVDS_DITHER_ENABLE;
+ }
+
+ OUTREG(LVDS, lvds);
+ POSTING_READ(LVDS);
+ }
+
+ OUTREG(fp_reg, fp);
+ OUTREG(dpll_reg, dpll);
+ POSTING_READ(dpll_reg);
+ /* Wait for the clocks to stabilize. */
+ usleep(150);
+
+ if (IS_I965G(pI830)) {
+ int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+ OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+ ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+ } else {
+ /* write it again -- the BIOS does, after all */
+ OUTREG(dpll_reg, dpll);
+ }
+ POSTING_READ(dpll_reg);
+ /* Wait for the clocks to stabilize. */
+ usleep(150);
+
+ OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
+ ((adjusted_mode->CrtcHTotal - 1) << 16));
+ OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
+ ((adjusted_mode->CrtcHBlankEnd - 1) << 16));
+ OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
+ ((adjusted_mode->CrtcHSyncEnd - 1) << 16));
+ OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
+ ((adjusted_mode->CrtcVTotal - 1) << 16));
+
+ OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
+ ((adjusted_mode->CrtcVBlankEnd - 1) << 16));
+ OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
+ ((adjusted_mode->CrtcVSyncEnd - 1) << 16));
+ OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
+ /* pipesrc and dspsize control the size that is scaled from, which should
+ * always be the user's requested size.
+ */
+ OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
+ OUTREG(dsppos_reg, 0);
+ OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+ OUTREG(pipeconf_reg, pipeconf);
+ POSTING_READ(pipeconf_reg);
+ i830WaitForVblank(pScrn);
+
+ OUTREG(dspcntr_reg, dspcntr);
+ /* Flush the plane changes */
+ i830PipeSetBase(crtc, x, y);
+#ifdef XF86DRI
+ I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
+
+ i830WaitForVblank(pScrn);
+}
+
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void
+i830_crtc_load_lut(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+ int i;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->enabled)
+ return;
+
+ for (i = 0; i < 256; i++) {
+ OUTREG(palreg + 4 * i,
+ (intel_crtc->lut_r[i] << 16) |
+ (intel_crtc->lut_g[i] << 8) |
+ intel_crtc->lut_b[i]);
+ }
+}
+
+/** Sets the color ramps on behalf of RandR */
+static void
+i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size)
+{
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int i;
+
+ assert(size == 256);
+
+ for (i = 0; i < 256; i++) {
+ intel_crtc->lut_r[i] = red[i] >> 8;
+ intel_crtc->lut_g[i] = green[i] >> 8;
+ intel_crtc->lut_b[i] = blue[i] >> 8;
+ }
+
+ i830_crtc_load_lut(crtc);
+}
+
+/**
+ * Allocates memory for a locked-in-framebuffer shadow of the given
+ * width and height for this CRTC's rotated shadow framebuffer.
+ */
+
+static void *
+i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ unsigned long rotate_pitch;
+ int align = KB(4), size;
+
+ rotate_pitch = pScrn->displayWidth * pI830->cpp;
+ size = rotate_pitch * height;
+
+ assert(intel_crtc->rotate_mem == NULL);
+ intel_crtc->rotate_mem = i830_allocate_memory(pScrn, "rotated crtc",
+ size, align, 0);
+ if (intel_crtc->rotate_mem == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate shadow memory for rotated CRTC\n");
+ return NULL;
+ }
+
+ return pI830->FbBase + intel_crtc->rotate_mem->offset;
+}
+
+/**
+ * Creates a pixmap for this CRTC's rotated shadow framebuffer.
+ */
+static PixmapPtr
+i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long rotate_pitch;
+ PixmapPtr rotate_pixmap;
+
+ if (!data)
+ data = i830_crtc_shadow_allocate (crtc, width, height);
+
+ rotate_pitch = pScrn->displayWidth * pI830->cpp;
+
+ rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+ width, height,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ rotate_pitch,
+ data);
+
+ if (rotate_pixmap == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate shadow pixmap for rotated CRTC\n");
+ }
+ return rotate_pixmap;
+}
+
+static void
+i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (rotate_pixmap)
+ FreeScratchPixmapHeader(rotate_pixmap);
+
+ if (data) {
+ /* Be sure to sync acceleration before the memory gets unbound. */
+ I830Sync(pScrn);
+ i830_free_memory(pScrn, intel_crtc->rotate_mem);
+ intel_crtc->rotate_mem = NULL;
+ }
+}
+
+
+void
+i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
+
+ for (i = 0; i < xf86_config->num_crtc; i++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
+ I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
+ CARD32 dspcntr = intel_crtc->plane == 0 ? INREG(DSPACNTR) :
+ INREG(DSPBCNTR);
+ CARD32 pipeconf = i == 0 ? INREG(PIPEACONF) :
+ INREG(PIPEBCONF);
+ Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
+ Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ " Pipe %c is %s\n",
+ 'A' + i, crtc->enabled ? "on" : "off");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ " Display plane %c is now %s and connected to pipe %c.\n",
+ 'A' + intel_crtc->plane,
+ hw_plane_enable ? "enabled" : "disabled",
+ dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
+ if (hw_pipe_enable != crtc->enabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ " Hardware claims pipe %c is %s while software "
+ "believes it is %s\n",
+ 'A' + i, hw_pipe_enable ? "on" : "off",
+ crtc->enabled ? "on" : "off");
+ }
+ if (hw_plane_enable != crtc->enabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ " Hardware claims plane %c is %s while software "
+ "believes it is %s\n",
+ 'A' + i, hw_plane_enable ? "on" : "off",
+ crtc->enabled ? "on" : "off");
+ }
+ }
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ xf86CrtcPtr crtc = output->crtc;
+ I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ " Output %s is connected to pipe %s\n",
+ output->name, intel_crtc == NULL ? "none" :
+ (intel_crtc->pipe == 0 ? "A" : "B"));
+ }
+}
+
+/**
+ * Get a pipe with a simple mode set on it for doing load-based monitor
+ * detection.
+ *
+ * It will be up to the load-detect code to adjust the pipe as appropriate for
+ * its requirements. The pipe will be connected to no other outputs.
+ *
+ * Currently this code will only succeed if there is a pipe with no outputs
+ * configured for it. In the future, it could choose to temporarily disable
+ * some outputs to free up a pipe for its use.
+ *
+ * \return crtc, or NULL if no pipes are available.
+ */
+
+/* VESA 640x480x72Hz mode to set on the pipe */
+static DisplayModeRec load_detect_mode = {
+ NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+ 31500,
+ 640, 664, 704, 832, 0,
+ 480, 489, 491, 520, 0,
+ V_NHSYNC | V_NVSYNC,
+ 0, 0,
+
+ 640, 640, 664, 704, 832, 832, 0,
+ 480, 489, 489, 491, 520, 520,
+ FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+};
+
+xf86CrtcPtr
+i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I830CrtcPrivatePtr intel_crtc;
+ xf86CrtcPtr supported_crtc =NULL;
+ xf86CrtcPtr crtc = NULL;
+ int i;
+
+ if (output->crtc)
+ {
+ crtc = output->crtc;
+ /*
+ * Make sure the crtc and output are running
+ */
+ intel_crtc = crtc->driver_private;
+ *dpms_mode = intel_crtc->dpms_mode;
+ if (intel_crtc->dpms_mode != DPMSModeOn)
+ {
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+ output->funcs->dpms (output, DPMSModeOn);
+ }
+ return crtc;
+ }
+
+ for (i = 0; i < xf86_config->num_crtc; i++)
+ {
+ xf86CrtcPtr possible_crtc;
+ if (!(output->possible_crtcs & (1 << i)))
+ continue;
+ possible_crtc = xf86_config->crtc[i];
+ if (!possible_crtc->enabled)
+ {
+ crtc = possible_crtc;
+ break;
+ }
+ if (!supported_crtc)
+ supported_crtc = possible_crtc;
+ }
+ if (!crtc)
+ {
+ crtc = supported_crtc;
+ if (!crtc)
+ return NULL;
+ }
+
+ output->crtc = crtc;
+ intel_output->load_detect_temp = TRUE;
+
+ intel_crtc = crtc->driver_private;
+ *dpms_mode = intel_crtc->dpms_mode;
+
+ if (!crtc->enabled)
+ {
+ if (!mode)
+ mode = &load_detect_mode;
+ xf86CrtcSetMode (crtc, mode, RR_Rotate_0, 0, 0);
+ }
+ else
+ {
+ if (intel_crtc->dpms_mode != DPMSModeOn)
+ crtc->funcs->dpms (crtc, DPMSModeOn);
+
+ /* Add this output to the crtc */
+ output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
+ output->funcs->commit (output);
+ }
+ /* let the output get through one full cycle before testing */
+ i830WaitForVblank (pScrn);
+
+ return crtc;
+}
+
+void
+i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (intel_output->load_detect_temp)
+ {
+ output->crtc = NULL;
+ intel_output->load_detect_temp = FALSE;
+ crtc->enabled = xf86CrtcInUse (crtc);
+ xf86DisableUnusedFunctions(pScrn);
+ }
+ /*
+ * Switch crtc and output back off if necessary
+ */
+ if (crtc->enabled && dpms_mode != DPMSModeOn)
+ {
+ if (output->crtc == crtc)
+ output->funcs->dpms (output, dpms_mode);
+ crtc->funcs->dpms (crtc, dpms_mode);
+ }
+}
+
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int
+i830_crtc_clock_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ CARD32 dpll = INREG((pipe == 0) ? DPLL_A : DPLL_B);
+ CARD32 fp;
+ intel_clock_t clock;
+
+ if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+ fp = INREG((pipe == 0) ? FPA0 : FPB0);
+ else
+ fp = INREG((pipe == 0) ? FPA1 : FPB1);
+
+ clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+ clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+ clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+ if (IS_I9XX(pI830)) {
+ clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+
+ switch (dpll & DPLL_MODE_MASK) {
+ case DPLLB_MODE_DAC_SERIAL:
+ clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+ break;
+ case DPLLB_MODE_LVDS:
+ clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Unknown DPLL mode %08x in programmed mode\n",
+ (int)(dpll & DPLL_MODE_MASK));
+ return 0;
+ }
+
+ /* XXX: Handle the 100Mhz refclk */
+ i9xx_clock(96000, &clock);
+ } else {
+ Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
+
+ if (is_lvds) {
+ clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+ clock.p2 = 14;
+
+ if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
+ i8xx_clock(66000, &clock); /* XXX: might not be 66MHz */
+ else
+ i8xx_clock(48000, &clock);
+ } else {
+ if (dpll & PLL_P1_DIVIDE_BY_TWO) {
+ clock.p1 = 2;
+ } else {
+ clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+ }
+ if (dpll & PLL_P2_DIVIDE_BY_4)
+ clock.p2 = 4;
+ else
+ clock.p2 = 2;
+
+ i8xx_clock(48000, &clock);
+ }
+ }
+
+ /* XXX: It would be nice to validate the clocks, but we can't reuse
+ * i830PllIsValid() because it relies on the xf86_config output
+ * configuration being accurate, which it isn't necessarily.
+ */
+ if (0)
+ i830PrintPll("probed", &clock);
+
+ return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+DisplayModePtr
+i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ DisplayModePtr mode;
+ int htot = INREG((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+ int hsync = INREG((pipe == 0) ? HSYNC_A : HSYNC_B);
+ int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+ int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
+
+ mode = xcalloc(1, sizeof(DisplayModeRec));
+ if (mode == NULL)
+ return NULL;
+
+ mode->Clock = i830_crtc_clock_get(pScrn, crtc);
+ mode->HDisplay = (htot & 0xffff) + 1;
+ mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
+ mode->HSyncStart = (hsync & 0xffff) + 1;
+ mode->HSyncEnd = ((hsync & 0xffff0000) >> 16) + 1;
+ mode->VDisplay = (vtot & 0xffff) + 1;
+ mode->VTotal = ((vtot & 0xffff0000) >> 16) + 1;
+ mode->VSyncStart = (vsync & 0xffff) + 1;
+ mode->VSyncEnd = ((vsync & 0xffff0000) >> 16) + 1;
+ xf86SetModeDefaultName(mode);
+ xf86SetModeCrtc(mode, 0);
+
+ return mode;
+}
+
+static const xf86CrtcFuncsRec i830_crtc_funcs = {
+ .dpms = i830_crtc_dpms,
+ .save = NULL, /* XXX */
+ .restore = NULL, /* XXX */
+ .lock = i830_crtc_lock,
+ .unlock = i830_crtc_unlock,
+ .mode_fixup = i830_crtc_mode_fixup,
+ .prepare = i830_crtc_prepare,
+ .mode_set = i830_crtc_mode_set,
+ .commit = i830_crtc_commit,
+ .gamma_set = i830_crtc_gamma_set,
+ .shadow_create = i830_crtc_shadow_create,
+ .shadow_allocate = i830_crtc_shadow_allocate,
+ .shadow_destroy = i830_crtc_shadow_destroy,
+ .set_cursor_colors = i830_crtc_set_cursor_colors,
+ .set_cursor_position = i830_crtc_set_cursor_position,
+ .show_cursor = i830_crtc_show_cursor,
+ .hide_cursor = i830_crtc_hide_cursor,
+/* .load_cursor_image = i830_crtc_load_cursor_image, */
+ .load_cursor_argb = i830_crtc_load_cursor_argb,
+ .destroy = NULL, /* XXX */
+};
+
+void
+i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
+{
+ xf86CrtcPtr crtc;
+ I830CrtcPrivatePtr intel_crtc;
+ int i;
+
+ crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
+ if (crtc == NULL)
+ return;
+
+ intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
+ intel_crtc->pipe = pipe;
+ intel_crtc->dpms_mode = DPMSModeOff;
+ intel_crtc->plane = pipe;
+
+ /* Initialize the LUTs for when we turn on the CRTC. */
+ for (i = 0; i < 256; i++) {
+ intel_crtc->lut_r[i] = i;
+ intel_crtc->lut_g[i] = i;
+ intel_crtc->lut_b[i] = i;
+ }
+ crtc->driver_private = intel_crtc;
+}
+
diff --git a/driver/xf86-video-intel/src/i830_display.h b/driver/xf86-video-intel/src/i830_display.h
new file mode 100644
index 000000000..1eeb7f15f
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_display.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "xorgVersion.h"
+
+/* i830_display.c */
+void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
+void i830WaitForVblank(ScrnInfoPtr pScrn);
+void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
+
+xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode);
+void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
+void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
+void i830_crtc_load_lut(xf86CrtcPtr crtc);
+DisplayModePtr i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc);
+void i830_output_prepare (xf86OutputPtr output);
+void i830_output_commit (xf86OutputPtr output);
+
diff --git a/driver/xf86-video-intel/src/i830_dvo.c b/driver/xf86-video-intel/src/i830_dvo.c
new file mode 100644
index 000000000..e6ff6af6c
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_dvo.c
@@ -0,0 +1,524 @@
+/**************************************************************************
+
+Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+******
+********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_display.h"
+#include "i810_reg.h"
+
+#include "sil164/sil164.h"
+#include "ch7xxx/ch7xxx.h"
+#include "tfp410/tfp410.h"
+
+static const char *SIL164Symbols[] = {
+ "Sil164VidOutput",
+ NULL
+};
+static const char *TFP410Symbols[] = {
+ "Tfp410VidOutput",
+ NULL
+};
+static const char *CH7xxxSymbols[] = {
+ "CH7xxxVidOutput",
+ NULL
+};
+static const char *ivch_symbols[] = {
+ "ivch_methods",
+ NULL
+};
+
+static const char *ch7017_symbols[] = {
+ "ch7017_methods",
+ NULL
+};
+
+/* driver list */
+struct _I830DVODriver i830_dvo_drivers[] =
+{
+ {
+ .type = I830_OUTPUT_DVO_TMDS,
+ .modulename = "sil164",
+ .fntablename = "SIL164VidOutput",
+ .dvo_reg = DVOC,
+ .address = (SIL164_ADDR_1<<1),
+ .symbols = SIL164Symbols
+ },
+ {
+ .type = I830_OUTPUT_DVO_TMDS,
+ .modulename = "ch7xxx",
+ .fntablename = "CH7xxxVidOutput",
+ .dvo_reg = DVOC,
+ .address = (CH7xxx_ADDR_1<<1),
+ .symbols = CH7xxxSymbols
+ },
+ {
+ .type = I830_OUTPUT_DVO_LVDS,
+ .modulename = "ivch",
+ .fntablename = "ivch_methods",
+ .dvo_reg = DVOA,
+ .address = 0x04, /* Might also be 0x44, 0x84, 0xc4 */
+ .symbols = ivch_symbols
+ },
+ {
+ .type = I830_OUTPUT_DVO_TMDS,
+ .modulename = "tfp410",
+ .fntablename = "TFP410VidOutput",
+ .dvo_reg = DVOC,
+ .address = (TFP410_ADDR_1<<1),
+ .symbols = TFP410Symbols
+ },
+ {
+ .type = I830_OUTPUT_DVO_LVDS,
+ .modulename = "ch7017",
+ .fntablename = "ch7017_methods",
+ .dvo_reg = DVOC,
+ .address = 0xea,
+ .symbols = ch7017_symbols,
+ .gpio = GPIOE,
+ }
+};
+
+#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
+
+static void
+i830_dvo_dpms(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ void * dev_priv = drv->dev_priv;
+ unsigned int dvo_reg = drv->dvo_reg;
+
+ if (mode == DPMSModeOn) {
+ OUTREG(dvo_reg, INREG(dvo_reg) | DVO_ENABLE);
+ POSTING_READ(dvo_reg);
+ (*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
+ } else {
+ (*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
+ OUTREG(dvo_reg, INREG(dvo_reg) & ~DVO_ENABLE);
+ POSTING_READ(dvo_reg);
+ }
+}
+
+static void
+i830_dvo_save(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ void * dev_priv = intel_output->i2c_drv->dev_priv;
+
+ /* Each output should probably just save the registers it touches, but for
+ * now, use more overkill.
+ */
+ pI830->saveDVOA = INREG(DVOA);
+ pI830->saveDVOB = INREG(DVOB);
+ pI830->saveDVOC = INREG(DVOC);
+
+ (*intel_output->i2c_drv->vid_rec->save)(dev_priv);
+}
+
+static void
+i830_dvo_restore(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ void * dev_priv = intel_output->i2c_drv->dev_priv;
+
+ (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
+
+ OUTREG(DVOA, pI830->saveDVOA);
+ OUTREG(DVOB, pI830->saveDVOB);
+ OUTREG(DVOC, pI830->saveDVOC);
+}
+
+static int
+i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ void *dev_priv = intel_output->i2c_drv->dev_priv;
+
+ if (pMode->Flags & V_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ /* XXX: Validate clock range */
+
+ if (drv->panel_fixed_mode) {
+ if (pMode->HDisplay > drv->panel_fixed_mode->HDisplay)
+ return MODE_PANEL;
+ if (pMode->VDisplay > drv->panel_fixed_mode->VDisplay)
+ return MODE_PANEL;
+ }
+
+ return intel_output->i2c_drv->vid_rec->mode_valid(dev_priv, pMode);
+}
+
+static Bool
+i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+
+ /* If we have timings from the BIOS for the panel, put them in
+ * to the adjusted mode. The CRTC will be set up for this mode,
+ * with the panel scaling set up to source from the H/VDisplay
+ * of the original mode.
+ */
+ if (drv->panel_fixed_mode != NULL) {
+ adjusted_mode->HDisplay = drv->panel_fixed_mode->HDisplay;
+ adjusted_mode->HSyncStart = drv->panel_fixed_mode->HSyncStart;
+ adjusted_mode->HSyncEnd = drv->panel_fixed_mode->HSyncEnd;
+ adjusted_mode->HTotal = drv->panel_fixed_mode->HTotal;
+ adjusted_mode->VDisplay = drv->panel_fixed_mode->VDisplay;
+ adjusted_mode->VSyncStart = drv->panel_fixed_mode->VSyncStart;
+ adjusted_mode->VSyncEnd = drv->panel_fixed_mode->VSyncEnd;
+ adjusted_mode->VTotal = drv->panel_fixed_mode->VTotal;
+ adjusted_mode->Clock = drv->panel_fixed_mode->Clock;
+ xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+ }
+
+ if (intel_output->i2c_drv->vid_rec->mode_fixup)
+ return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
+ mode, adjusted_mode);
+ return TRUE;
+}
+
+static void
+i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86CrtcPtr crtc = output->crtc;
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ int pipe = intel_crtc->pipe;
+ CARD32 dvo;
+ unsigned int dvo_reg = drv->dvo_reg, dvo_srcdim_reg;
+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+
+ switch (dvo_reg) {
+ case DVOA:
+ default:
+ dvo_srcdim_reg = DVOA_SRCDIM;
+ break;
+ case DVOB:
+ dvo_srcdim_reg = DVOB_SRCDIM;
+ break;
+ case DVOC:
+ dvo_srcdim_reg = DVOC_SRCDIM;
+ break;
+ }
+
+ intel_output->i2c_drv->vid_rec->mode_set(intel_output->i2c_drv->dev_priv,
+ mode, adjusted_mode);
+
+ /* Save the data order, since I don't know what it should be set to. */
+ dvo = INREG(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
+ dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
+
+ if (pipe == 1)
+ dvo |= DVO_PIPE_B_SELECT;
+ dvo |= DVO_PIPE_STALL;
+ if (adjusted_mode->Flags & V_PHSYNC)
+ dvo |= DVO_HSYNC_ACTIVE_HIGH;
+ if (adjusted_mode->Flags & V_PVSYNC)
+ dvo |= DVO_VSYNC_ACTIVE_HIGH;
+
+ OUTREG(dpll_reg, INREG(dpll_reg) | DPLL_DVO_HIGH_SPEED);
+
+ /*OUTREG(DVOB_SRCDIM,
+ (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+ (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
+ OUTREG(dvo_srcdim_reg,
+ (adjusted_mode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
+ (adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
+ /*OUTREG(DVOB, dvo);*/
+ OUTREG(dvo_reg, dvo);
+}
+
+/**
+ * Detect the output connection on our DVO device.
+ *
+ * Unimplemented.
+ */
+static xf86OutputStatus
+i830_dvo_detect(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ void *dev_priv = intel_output->i2c_drv->dev_priv;
+
+ return intel_output->i2c_drv->vid_rec->detect(dev_priv);
+}
+
+static DisplayModePtr
+i830_dvo_get_modes(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ DisplayModePtr modes;
+
+ /* We should probably have an i2c driver get_modes function for those
+ * devices which will have a fixed set of modes determined by the chip
+ * (TV-out, for example), but for now with just TMDS and LVDS, that's not
+ * the case.
+ */
+ modes = i830_ddc_get_modes(output);
+ if (modes != NULL)
+ return modes;
+
+ if (intel_output->i2c_drv->vid_rec->get_modes)
+ {
+ modes = intel_output->i2c_drv->vid_rec->get_modes (intel_output->i2c_drv->dev_priv);
+ if (modes != NULL)
+ return modes;
+ }
+
+ if (drv->panel_fixed_mode != NULL)
+ return xf86DuplicateMode(drv->panel_fixed_mode);
+
+ return NULL;
+}
+
+static void
+i830_dvo_destroy (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+
+ if (intel_output)
+ {
+ if (intel_output->i2c_drv->vid_rec->destroy)
+ intel_output->i2c_drv->vid_rec->destroy (intel_output->i2c_drv->dev_priv);
+ if (intel_output->pI2CBus)
+ xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
+ if (intel_output->pDDCBus)
+ xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
+ xfree (intel_output);
+ }
+}
+
+static const xf86OutputFuncsRec i830_dvo_output_funcs = {
+ .dpms = i830_dvo_dpms,
+ .save = i830_dvo_save,
+ .restore = i830_dvo_restore,
+ .mode_valid = i830_dvo_mode_valid,
+ .mode_fixup = i830_dvo_mode_fixup,
+ .prepare = i830_output_prepare,
+ .mode_set = i830_dvo_mode_set,
+ .commit = i830_output_commit,
+ .detect = i830_dvo_detect,
+ .get_modes = i830_dvo_get_modes,
+ .destroy = i830_dvo_destroy
+};
+
+/**
+ * Attempts to get a fixed panel timing for LVDS (currently only the i830).
+ *
+ * Other chips with DVO LVDS will need to extend this to deal with the LVDS
+ * chip being on DVOB/C and having multiple pipes.
+ */
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I830Ptr pI830 = I830PTR(pScrn);
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ unsigned int dvo_reg = drv->dvo_reg;
+ CARD32 dvo = INREG(dvo_reg);
+ DisplayModePtr mode = NULL;
+
+ /* If the DVO port is active, that'll be the LVDS, so we can pull out
+ * its timings to get how the BIOS set up the panel.
+ */
+ if (dvo & DVO_ENABLE)
+ {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int pipe = (dvo & DVO_PIPE_B_SELECT) ? 1 : 0;
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (intel_crtc->pipe == pipe)
+ {
+ mode = i830_crtc_mode_get(pScrn, crtc);
+
+ if (mode)
+ {
+ mode->type |= M_T_PREFERRED;
+
+ if (dvo & DVO_HSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PHSYNC;
+ if (dvo & DVO_VSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PVSYNC;
+ }
+ break;
+ }
+ }
+ }
+ return mode;
+}
+
+void
+i830_dvo_init(ScrnInfoPtr pScrn)
+{
+ I830OutputPrivatePtr intel_output;
+ int ret;
+ int i;
+ void *ret_ptr;
+ struct _I830DVODriver *drv;
+ int gpio_inited = 0;
+ I2CBusPtr pI2CBus = NULL;
+
+ intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+ if (!intel_output)
+ return;
+
+ /* Set up the DDC bus */
+ ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
+ if (!ret) {
+ xfree(intel_output);
+ return;
+ }
+
+ /* Now, try to find a controller */
+ for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
+ int gpio;
+
+ drv = &i830_dvo_drivers[i];
+ drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+ if (drv->modhandle == NULL)
+ continue;
+
+ xf86LoaderReqSymLists(drv->symbols, NULL);
+
+ ret_ptr = NULL;
+ drv->vid_rec = LoaderSymbol(drv->fntablename);
+
+ /* Allow the I2C driver info to specify the GPIO to be used in
+ * special cases, but otherwise default to what's defined in the spec.
+ */
+ if (drv->gpio != 0)
+ gpio = drv->gpio;
+ else if (drv->type == I830_OUTPUT_DVO_LVDS)
+ gpio = GPIOB;
+ else
+ gpio = GPIOE;
+
+ /* Set up the I2C bus necessary for the chip we're probing. It appears
+ * that everything is on GPIOE except for panels on i830 laptops, which
+ * are on GPIOB (DVOA).
+ */
+ if (gpio_inited != gpio) {
+ if (pI2CBus != NULL)
+ xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+ if (!I830I2CInit(pScrn, &pI2CBus, gpio,
+ gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) {
+ continue;
+ }
+ }
+
+ if (drv->vid_rec != NULL)
+ ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
+
+ if (ret_ptr != NULL) {
+ xf86OutputPtr output = NULL;
+
+ intel_output->type = drv->type;
+ switch (drv->type) {
+ case I830_OUTPUT_DVO_TMDS:
+ intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+ intel_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+ (1 << I830_OUTPUT_DVO_TMDS));
+ output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+ "TMDS");
+ break;
+ case I830_OUTPUT_DVO_LVDS:
+ intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+ intel_output->clone_mask = (1 << I830_OUTPUT_DVO_LVDS);
+ output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+ "LVDS");
+ break;
+ case I830_OUTPUT_DVO_TVOUT:
+ intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+ intel_output->clone_mask = (1 << I830_OUTPUT_DVO_TVOUT);
+ output = xf86OutputCreate(pScrn, &i830_dvo_output_funcs,
+ "TV");
+ break;
+ }
+ if (output == NULL) {
+ xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+ xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+ xfree(intel_output);
+ xf86UnloadSubModule(drv->modhandle);
+ return;
+ }
+
+ output->driver_private = intel_output;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+
+ drv->dev_priv = ret_ptr;
+ intel_output->i2c_drv = drv;
+ intel_output->pI2CBus = pI2CBus;
+
+ if (intel_output->type == I830_OUTPUT_DVO_LVDS) {
+ /* For our LVDS chipsets, we should hopefully be able to
+ * dig the fixed panel mode out of the BIOS data. However,
+ * it's in a different format from the BIOS data on chipsets
+ * with integrated LVDS (stored in AIM headers, liekly),
+ * so for now, just get the current mode being output through
+ * DVO.
+ */
+ drv->panel_fixed_mode = i830_dvo_get_current_mode(output);
+ drv->panel_wants_dither = TRUE;
+ }
+
+ return;
+ }
+ xf86UnloadSubModule(drv->modhandle);
+ }
+
+ /* Didn't find a chip, so tear down. */
+ if (pI2CBus != NULL)
+ xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+ xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+ xfree(intel_output);
+}
diff --git a/driver/xf86-video-intel/src/i830_exa.c b/driver/xf86-video-intel/src/i830_exa.c
new file mode 100644
index 000000000..32c55dd0a
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_exa.c
@@ -0,0 +1,621 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
+ Based on code from i830_xaa.c.
+
+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
+
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+#include <string.h>
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#define ALWAYS_SYNC 0
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...) \
+do { \
+ DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \
+ return FALSE; \
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) \
+do { \
+ return FALSE; \
+} while(0)
+#endif
+
+const int I830CopyROP[16] =
+{
+ ROP_0, /* GXclear */
+ ROP_DSa, /* GXand */
+ ROP_SDna, /* GXandReverse */
+ ROP_S, /* GXcopy */
+ ROP_DSna, /* GXandInverted */
+ ROP_D, /* GXnoop */
+ ROP_DSx, /* GXxor */
+ ROP_DSo, /* GXor */
+ ROP_DSon, /* GXnor */
+ ROP_DSxn, /* GXequiv */
+ ROP_Dn, /* GXinvert*/
+ ROP_SDno, /* GXorReverse */
+ ROP_Sn, /* GXcopyInverted */
+ ROP_DSno, /* GXorInverted */
+ ROP_DSan, /* GXnand */
+ ROP_1 /* GXset */
+};
+
+const int I830PatternROP[16] =
+{
+ ROP_0,
+ ROP_DPa,
+ ROP_PDna,
+ ROP_P,
+ ROP_DPna,
+ ROP_D,
+ ROP_DPx,
+ ROP_DPo,
+ ROP_DPon,
+ ROP_PDxn,
+ ROP_Dn,
+ ROP_PDno,
+ ROP_Pn,
+ ROP_DPno,
+ ROP_DPan,
+ ROP_1
+};
+
+/**
+ * Returns whether a given pixmap is tiled or not.
+ *
+ * Currently, we only have one pixmap that might be tiled, which is the front
+ * buffer. At the point where we are tiling some pixmaps managed by the
+ * general allocator, we should move this to using pixmap privates.
+ */
+Bool
+i830_pixmap_tiled(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long offset;
+
+ offset = intel_get_pixmap_offset(pPixmap);
+ if (offset == pI830->front_buffer->offset &&
+ pI830->front_buffer->tiling != TILE_NONE)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+i830_exa_pixmap_is_offscreen(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if ((void *)pPixmap->devPrivate.ptr >= (void *)pI830->FbBase &&
+ (void *)pPixmap->devPrivate.ptr <
+ (void *)(pI830->FbBase + pI830->FbMapSize))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ * I830EXASync - wait for a command to finish
+ * @pScreen: current screen
+ * @marker: marker command to wait for
+ *
+ * Wait for the command specified by @marker to finish, then return. We don't
+ * actually do marker waits, though we might in the future. For now, just
+ * wait for a full idle.
+ */
+static void
+I830EXASync(ScreenPtr pScreen, int marker)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ I830Sync(pScrn);
+}
+
+/**
+ * I830EXAPrepareSolid - prepare for a Solid operation, if possible
+ */
+static Bool
+I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long offset, pitch;
+
+ if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
+ I830FALLBACK("planemask is not solid");
+
+ if (pPixmap->drawable.bitsPerPixel == 24)
+ I830FALLBACK("solid 24bpp unsupported!\n");
+
+ offset = exaGetPixmapOffset(pPixmap);
+ pitch = exaGetPixmapPitch(pPixmap);
+
+ if (offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
+ I830FALLBACK("pixmap offset not aligned");
+ if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
+ I830FALLBACK("pixmap pitch not aligned");
+
+ pI830->BR[13] = (I830PatternROP[alu] & 0xff) << 16 ;
+ switch (pPixmap->drawable.bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ /* RGB565 */
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ /* RGB8888 */
+ pI830->BR[13] |= ((1 << 24) | (1 << 25));
+ break;
+ }
+ pI830->BR[16] = fg;
+ return TRUE;
+}
+
+static void
+I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned long offset, pitch;
+ uint32_t cmd;
+
+ offset = exaGetPixmapOffset(pPixmap);
+ pitch = exaGetPixmapPitch(pPixmap);
+
+ {
+ BEGIN_LP_RING(6);
+
+ cmd = XY_COLOR_BLT_CMD;
+
+ if (pPixmap->drawable.bitsPerPixel == 32)
+ cmd |= XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
+
+ if (IS_I965G(pI830) && i830_pixmap_tiled(pPixmap)) {
+ assert((pitch % 512) == 0);
+ pitch >>= 2;
+ cmd |= XY_COLOR_BLT_TILED;
+ }
+
+ OUT_RING(cmd);
+
+ OUT_RING(pI830->BR[13] | pitch);
+ OUT_RING((y1 << 16) | (x1 & 0xffff));
+ OUT_RING((y2 << 16) | (x2 & 0xffff));
+ OUT_RING(offset);
+ OUT_RING(pI830->BR[16]);
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830EXADoneSolid(PixmapPtr pPixmap)
+{
+#if ALWAYS_SYNC
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+
+ I830Sync(pScrn);
+#endif
+}
+
+/**
+ * TODO:
+ * - support planemask using FULL_BLT_CMD?
+ */
+static Bool
+I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
+ int ydir, int alu, Pixel planemask)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))
+ I830FALLBACK("planemask is not solid");
+
+ pI830->pSrcPixmap = pSrcPixmap;
+
+ pI830->BR[13] = I830CopyROP[alu] << 16;
+
+ switch (pSrcPixmap->drawable.bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+ return TRUE;
+}
+
+static void
+I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
+ int dst_y1, int w, int h)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ uint32_t cmd;
+ int dst_x2, dst_y2;
+ unsigned int dst_off, dst_pitch, src_off, src_pitch;
+
+ dst_x2 = dst_x1 + w;
+ dst_y2 = dst_y1 + h;
+
+ dst_off = exaGetPixmapOffset(pDstPixmap);
+ dst_pitch = exaGetPixmapPitch(pDstPixmap);
+ src_off = exaGetPixmapOffset(pI830->pSrcPixmap);
+ src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
+
+ {
+ BEGIN_LP_RING(8);
+
+ cmd = XY_SRC_COPY_BLT_CMD;
+
+ if (pDstPixmap->drawable.bitsPerPixel == 32)
+ cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
+
+ if (IS_I965G(pI830)) {
+ if (i830_pixmap_tiled(pDstPixmap)) {
+ assert((dst_pitch % 512) == 0);
+ dst_pitch >>= 2;
+ cmd |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ if (i830_pixmap_tiled(pI830->pSrcPixmap)) {
+ assert((src_pitch % 512) == 0);
+ src_pitch >>= 2;
+ cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+ }
+ }
+
+ OUT_RING(cmd);
+
+ OUT_RING(pI830->BR[13] | dst_pitch);
+ OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+ OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+ OUT_RING(dst_off);
+ OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+ OUT_RING(src_pitch);
+ OUT_RING(src_off);
+
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830EXADoneCopy(PixmapPtr pDstPixmap)
+{
+#if ALWAYS_SYNC
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+
+ I830Sync(pScrn);
+#endif
+}
+
+#define xFixedToFloat(val) \
+ ((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
+
+/**
+ * Returns the floating-point coordinates transformed by the given transform.
+ *
+ * transform may be null.
+ */
+void
+i830_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
+ float *x_out, float *y_out)
+{
+ if (transform == NULL) {
+ *x_out = x;
+ *y_out = y;
+ } else {
+ PictVector v;
+
+ v.vector[0] = IntToxFixed(x);
+ v.vector[1] = IntToxFixed(y);
+ v.vector[2] = xFixed1;
+ PictureTransformPoint(transform, &v);
+ *x_out = xFixedToFloat(v.vector[0]);
+ *y_out = xFixedToFloat(v.vector[1]);
+ }
+}
+
+/**
+ * Uploads data from system memory to the framebuffer using a series of
+ * 8x8 pattern blits.
+ */
+static Bool
+i830_upload_to_screen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
+ int src_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ const int uts_width_max = 16, uts_height_max = 16;
+ int cpp = pDst->drawable.bitsPerPixel / 8;
+ int sub_x, sub_y;
+ CARD32 br13;
+ CARD32 offset;
+
+ if (w > uts_width_max || h > uts_height_max)
+ I830FALLBACK("too large for upload to screen (%d,%d)", w, h);
+
+ offset = exaGetPixmapOffset(pDst);
+
+ br13 = exaGetPixmapPitch(pDst);
+ br13 |= ((I830PatternROP[GXcopy] & 0xff) << 16);
+ switch (pDst->drawable.bitsPerPixel) {
+ case 16:
+ br13 |= 1 << 24;
+ break;
+ case 32:
+ br13 |= 3 << 24;
+ break;
+ }
+
+ for (sub_y = 0; sub_y < uts_height_max && sub_y < h; sub_y += 8) {
+ int sub_height;
+
+ if (sub_y + 8 > h)
+ sub_height = h - sub_y;
+ else
+ sub_height = 8;
+
+ for (sub_x = 0; sub_x < uts_width_max && sub_x < w; sub_x += 8) {
+ int sub_width, line;
+ char *src_line = src + sub_y * src_pitch + sub_x * cpp;
+
+ if (sub_x + 8 > w)
+ sub_width = w - sub_x;
+ else
+ sub_width = 8;
+
+ BEGIN_LP_RING(6 + (cpp * 8 * 8 / 4));
+
+ /* XXX We may need a pattern offset here for {x,y} % 8 != 0*/
+ OUT_RING(XY_PAT_BLT_IMMEDIATE |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ (3 + cpp * 8 * 8 / 4));
+ OUT_RING(br13);
+ OUT_RING(((y + sub_y) << 16) | (x + sub_x));
+ OUT_RING(((y + sub_y + sub_height) << 16) |
+ (x + sub_x + sub_width));
+ OUT_RING(offset);
+
+ /* Write out the lines with valid data, followed by any needed
+ * padding
+ */
+ for (line = 0; line < sub_height; line++) {
+ OUT_RING_COPY(sub_width * cpp, src_line);
+ src_line += src_pitch;
+ if (sub_width != 8)
+ OUT_RING_PAD((8 - sub_width) * cpp);
+ }
+ /* Write out any full padding lines to follow */
+ if (sub_height != 8)
+ OUT_RING_PAD(8 * cpp * (8 - sub_height));
+
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+ }
+
+ exaMarkSync(pDst->drawable.pScreen);
+ /* exaWaitSync(pDst->drawable.pScreen); */
+
+ return TRUE;
+}
+
+
+/*
+ * TODO:
+ * - Dual head?
+ */
+Bool
+I830EXAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ pI830->EXADriverPtr = exaDriverAlloc();
+ if (pI830->EXADriverPtr == NULL) {
+ pI830->noAccel = TRUE;
+ return FALSE;
+ }
+ memset(pI830->EXADriverPtr, 0, sizeof(*pI830->EXADriverPtr));
+
+ pI830->bufferOffset = 0;
+ pI830->EXADriverPtr->exa_major = 2;
+ /* If compiled against EXA 2.2, require 2.2 so we can use the
+ * PixmapIsOffscreen hook.
+ */
+#if EXA_VERSION_MINOR >= 2
+ pI830->EXADriverPtr->exa_minor = 2;
+#else
+ pI830->EXADriverPtr->exa_minor = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "EXA compatibility mode. Output rotation rendering "
+ "performance may suffer\n");
+#endif
+ pI830->EXADriverPtr->memoryBase = pI830->FbBase;
+ if (pI830->exa_offscreen) {
+ pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
+ pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
+ pI830->exa_offscreen->size;
+ } else {
+ pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
+ pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
+ }
+ pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
+
+ DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, "
+ "memorySize 0x%x\n",
+ pI830->EXADriverPtr->memoryBase,
+ pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
+ pI830->EXADriverPtr->offScreenBase,
+ pI830->EXADriverPtr->memorySize);
+
+
+ /* Limits are described in the BLT engine chapter under Graphics Data Size
+ * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
+ * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
+ *
+ * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
+ *
+ * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
+ * i965 limits 3D surface to 4kB-aligned offset if tiled.
+ * i965 limits 3D surfaces to w,h of ?,8192.
+ * i965 limits 3D surface to pitch of 1B - 128kB.
+ * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
+ * i965 limits 3D surface pitch alignment to 512B if tiled.
+ * i965 limits 3D destination drawing rect to w,h of 8192,8192.
+ *
+ * i915 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i915 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i915 limits 3D textures to width,height of 2048,2048.
+ * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
+ * i915 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
+ * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
+ * i915 limits 3D destination to POT aligned pitch if tiled.
+ * i915 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * i845 limits 3D textures to 4B-aligned offset if un-tiled.
+ * i845 limits 3D textures to ~4kB-aligned offset if tiled.
+ * i845 limits 3D textures to width,height of 2048,2048.
+ * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
+ * i845 limits 3D destination to 4B-aligned offset if un-tiled.
+ * i845 limits 3D destination to ~4kB-aligned offset if tiled.
+ * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
+ * i845 limits 3D destination drawing rect to w,h of 2048,2048.
+ *
+ * For the tiled issues, the only tiled buffer we draw to should be
+ * the front, which will have an appropriate pitch/offset already set up,
+ * so EXA doesn't need to worry.
+ */
+ if (IS_I965G(pI830)) {
+ pI830->EXADriverPtr->pixmapOffsetAlign = 4 * 2;
+ pI830->EXADriverPtr->pixmapPitchAlign = 16;
+ pI830->EXADriverPtr->maxX = 8192;
+ pI830->EXADriverPtr->maxY = 8192;
+ } else {
+ pI830->EXADriverPtr->pixmapOffsetAlign = 4;
+ pI830->EXADriverPtr->pixmapPitchAlign = 16;
+ pI830->EXADriverPtr->maxX = 2048;
+ pI830->EXADriverPtr->maxY = 2048;
+ }
+
+ /* Sync */
+ pI830->EXADriverPtr->WaitMarker = I830EXASync;
+
+ /* Solid fill */
+ pI830->EXADriverPtr->PrepareSolid = I830EXAPrepareSolid;
+ pI830->EXADriverPtr->Solid = I830EXASolid;
+ pI830->EXADriverPtr->DoneSolid = I830EXADoneSolid;
+
+ /* Copy */
+ pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy;
+ pI830->EXADriverPtr->Copy = I830EXACopy;
+ pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
+
+ /* Composite */
+ if (!IS_I9XX(pI830)) {
+ pI830->EXADriverPtr->CheckComposite = i830_check_composite;
+ pI830->EXADriverPtr->PrepareComposite = i830_prepare_composite;
+ pI830->EXADriverPtr->Composite = i830_composite;
+ pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+ } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+ IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ {
+ pI830->EXADriverPtr->CheckComposite = i915_check_composite;
+ pI830->EXADriverPtr->PrepareComposite = i915_prepare_composite;
+ pI830->EXADriverPtr->Composite = i830_composite;
+ pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+ } else {
+ pI830->EXADriverPtr->CheckComposite = i965_check_composite;
+ pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
+ pI830->EXADriverPtr->Composite = i965_composite;
+ pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+ }
+#if EXA_VERSION_MINOR >= 2
+ pI830->EXADriverPtr->PixmapIsOffscreen = i830_exa_pixmap_is_offscreen;
+#endif
+
+ /* UploadToScreen/DownloadFromScreen */
+ if (0)
+ pI830->EXADriverPtr->UploadToScreen = i830_upload_to_screen;
+
+ if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "EXA initialization failed; trying older version\n");
+ pI830->EXADriverPtr->exa_minor = 0;
+ if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+ xfree(pI830->EXADriverPtr);
+ pI830->noAccel = TRUE;
+ return FALSE;
+ }
+ }
+
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+ return TRUE;
+}
+
+#ifdef XF86DRI
+
+#ifndef ExaOffscreenMarkUsed
+extern void ExaOffscreenMarkUsed(PixmapPtr);
+#endif
+
+unsigned long long
+I830TexOffsetStart(PixmapPtr pPix)
+{
+ exaMoveInPixmap(pPix);
+ ExaOffscreenMarkUsed(pPix);
+
+ return exaGetPixmapOffset(pPix);
+}
+#endif
diff --git a/driver/xf86-video-intel/src/i830_i2c.c b/driver/xf86-video-intel/src/i830_i2c.c
new file mode 100644
index 000000000..da8f38e63
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_i2c.c
@@ -0,0 +1,387 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.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 <X11/extensions/randr.h>
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "shadow.h"
+#include "i830.h"
+
+#define AIRLIED_I2C 0
+
+#if AIRLIED_I2C
+
+#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */
+#define I2C_TRACE(x) /*(x)*/ /* Report progress */
+
+static void i830_setscl(I2CBusPtr b, int state)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 val;
+
+ OUTREG(b->DriverPrivate.uval,
+ (state ? GPIO_CLOCK_VAL_OUT : 0) | GPIO_CLOCK_DIR_OUT |
+ GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK);
+ val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_setsda(I2CBusPtr b, int state)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 val;
+
+ OUTREG(b->DriverPrivate.uval,
+ (state ? GPIO_DATA_VAL_OUT : 0) | GPIO_DATA_DIR_OUT |
+ GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK);
+ val = INREG(b->DriverPrivate.uval);
+}
+
+static void i830_getscl(I2CBusPtr b, int *state)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 val;
+
+ OUTREG(b->DriverPrivate.uval, GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK);
+ OUTREG(b->DriverPrivate.uval, 0);
+ val = INREG(b->DriverPrivate.uval);
+ *state = ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static int i830_getsda(I2CBusPtr b)
+ {
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 val;
+
+ OUTREG(b->DriverPrivate.uval, GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK);
+ OUTREG(b->DriverPrivate.uval, 0);
+ val = INREG(b->DriverPrivate.uval);
+ return ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static inline void sdalo(I2CBusPtr b)
+{
+ i830_setsda(b, 0);
+ b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void sdahi(I2CBusPtr b)
+{
+ i830_setsda(b, 1);
+ b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline void scllo(I2CBusPtr b)
+{
+ i830_setscl(b, 0);
+ b->I2CUDelay(b, b->RiseFallTime);
+}
+
+static inline int sclhi(I2CBusPtr b, int timeout)
+{
+ int scl = 0;
+ int i;
+
+ i830_setscl(b, 1);
+ b->I2CUDelay(b, b->RiseFallTime);
+
+ for (i = timeout; i > 0; i -= b->RiseFallTime) {
+ i830_getscl(b, &scl);
+ if (scl) break;
+ b->I2CUDelay(b, b->RiseFallTime);
+ }
+
+ if (i <= 0) {
+ I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d) timeout]",
+ b->BusName, timeout));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+I830I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)
+{
+ I2CBusPtr b = d->pI2CBus;
+ int i, sda;
+ unsigned char indata = 0;
+
+ sdahi(b);
+
+ for (i = 0; i < 8; i++) {
+ if (sclhi(b, d->BitTimeout) == FALSE) {
+ I2C_TRACE(ErrorF("timeout at bit #%d\n", 7-i));
+ return FALSE;
+ };
+ indata *= 2;
+ if (i830_getsda(b))
+ indata |= 0x01;
+ scllo(b);
+ }
+
+ if (last) {
+ sdahi(b);
+ } else {
+ sdalo(b);
+ }
+
+ if (sclhi(b, d->BitTimeout) == FALSE) {
+ sdahi(b);
+ return FALSE;
+ };
+
+ scllo(b);
+ sdahi(b);
+
+ *data = indata & 0xff;
+ I2C_TRACE(ErrorF("R%02x ", (int) *data));
+
+ return TRUE;
+}
+
+static Bool
+I830I2CPutByte(I2CDevPtr d, I2CByte c)
+{
+ Bool r;
+ int i, scl, sda;
+ int sb, ack;
+ I2CBusPtr b = d->pI2CBus;
+
+ for (i = 7; i >= 0; i--) {
+ sb = c & (1 << i);
+ i830_setsda(b, sb);
+ b->I2CUDelay(b, b->RiseFallTime);
+
+ if (sclhi(b, d->ByteTimeout) == FALSE) {
+ sdahi(b);
+ return FALSE;
+ }
+
+ i830_setscl(b, 0);
+ b->I2CUDelay(b, b->RiseFallTime);
+ }
+ sdahi(b);
+ if (sclhi(b, d->ByteTimeout) == FALSE) {
+ I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]",
+ b->BusName, c, d->BitTimeout,
+ d->ByteTimeout, d->AcknTimeout));
+ return FALSE;
+ }
+ ack = i830_getsda(b);
+ I2C_TRACE(ErrorF("Put byte 0x%02x , getsda() = %d\n", c & 0xff, ack));
+
+ scllo(b);
+ return (0 == ack);
+}
+
+static Bool
+I830I2CStart(I2CBusPtr b, int timeout)
+{
+ if (sclhi(b, timeout) == FALSE)
+ return FALSE;
+
+ sdalo(b);
+ scllo(b);
+
+ return TRUE;
+}
+
+static void
+I830I2CStop(I2CDevPtr d)
+{
+ I2CBusPtr b = d->pI2CBus;
+
+ sdalo(b);
+ sclhi(b, d->ByteTimeout);
+ sdahi(b);
+}
+
+static Bool
+I830I2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
+{
+ if (I830I2CStart(d->pI2CBus, d->StartTimeout)) {
+ if (I830I2CPutByte(d, addr & 0xFF)) {
+ if ((addr & 0xF8) != 0xF0 &&
+ (addr & 0xFE) != 0x00)
+ return TRUE;
+
+ if (I830I2CPutByte(d, (addr >> 8) & 0xFF))
+ return TRUE;
+ }
+
+ I830I2CStop(d);
+ }
+
+ return FALSE;
+}
+
+#else
+
+#define I2C_DEBUG 0
+
+#if I2C_DEBUG
+static Bool first = TRUE;
+#endif
+
+static void
+i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 val;
+
+ val = INREG(b->DriverPrivate.uval);
+
+ /*
+ * to read valid data, we must have written a 1 to
+ * the associated bit. Writing a 1 is done by
+ * tri-stating the bus in PutBits, so we needn't make
+ * sure that is true here
+ */
+ *data = (val & GPIO_DATA_VAL_IN) != 0;
+ *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
+
+#if I2C_DEBUG
+ ErrorF("Getting %s: %c %c\n", b->BusName,
+ *clock ? '^' : 'v',
+ *data ? '^' : 'v');
+#endif
+}
+
+static void
+i830I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ CARD32 reserved = 0;
+ CARD32 data_bits, clock_bits;
+
+#if I2C_DEBUG
+ int cur_clock, cur_data;
+#endif
+
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+#if I2C_DEBUG
+ i830I2CGetBits(b, &cur_clock, &cur_data);
+
+ if (first) {
+ ErrorF("%s Debug: C D C D\n", b->BusName);
+ first = FALSE;
+ }
+
+ ErrorF("Setting %s 0x%08x to: %c %c\n", b->BusName,
+ (int)b->DriverPrivate.uval,
+ clock ? '^' : 'v',
+ data ? '^' : 'v');
+#endif
+
+ if (!IS_I830(pI830) && !IS_845G(pI830)) {
+ /* On most chips, these bits must be preserved in software. */
+ reserved = INREG(b->DriverPrivate.uval) &
+ (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
+ }
+
+ /* data or clock == 1 means to tristate the bus. otherwise, drive it low */
+ if (data)
+ data_bits = GPIO_DATA_DIR_IN|GPIO_DATA_DIR_MASK;
+ else
+ data_bits = GPIO_DATA_DIR_OUT|GPIO_DATA_DIR_MASK|GPIO_DATA_VAL_MASK;
+ if (clock)
+ clock_bits = GPIO_CLOCK_DIR_IN|GPIO_CLOCK_DIR_MASK;
+ else
+ clock_bits = GPIO_CLOCK_DIR_OUT|GPIO_CLOCK_DIR_MASK|GPIO_CLOCK_VAL_MASK;
+
+ OUTREG(b->DriverPrivate.uval, reserved | data_bits | clock_bits);
+ POSTING_READ(b->DriverPrivate.uval);
+}
+
+#endif
+
+/* the i830 has a number of I2C Buses */
+Bool
+I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
+{
+ I2CBusPtr pI2CBus;
+
+ pI2CBus = xf86CreateI2CBusRec();
+
+ if (!pI2CBus)
+ return FALSE;
+
+ pI2CBus->BusName = name;
+ pI2CBus->scrnIndex = pScrn->scrnIndex;
+#if AIRLIED_I2C
+ pI2CBus->I2CGetByte = I830I2CGetByte;
+ pI2CBus->I2CPutByte = I830I2CPutByte;
+ pI2CBus->I2CStart = I830I2CStart;
+ pI2CBus->I2CStop = I830I2CStop;
+ pI2CBus->I2CAddress = I830I2CAddress;
+#else
+ pI2CBus->I2CGetBits = i830I2CGetBits;
+ pI2CBus->I2CPutBits = i830I2CPutBits;
+#endif
+ pI2CBus->DriverPrivate.uval = i2c_reg;
+
+ /* Assume all busses are used for DDCish stuff */
+
+ /*
+ * These were set incorrectly in the server pre-1.3, Having
+ * duplicate settings is sub-optimal, but this lets the driver
+ * work with older servers
+ */
+ pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+ pI2CBus->StartTimeout = 550;
+ pI2CBus->BitTimeout = 40;
+ pI2CBus->AcknTimeout = 40;
+ pI2CBus->RiseFallTime = 20;
+
+ if (!xf86I2CBusInit(pI2CBus))
+ return FALSE;
+
+ *bus_ptr = pI2CBus;
+ return TRUE;
+}
diff --git a/driver/xf86-video-intel/src/i830_lvds.c b/driver/xf86-video-intel/src/i830_lvds.c
new file mode 100644
index 000000000..a3a56f7b1
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_lvds.c
@@ -0,0 +1,1025 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_bios.h"
+#include "i830_display.h"
+#include "X11/Xatom.h"
+
+struct i830_lvds_priv {
+ /* The BIOS's fixed timings for the LVDS */
+ DisplayModePtr panel_fixed_mode;
+
+ /* The panel needs dithering enabled */
+ Bool panel_wants_dither;
+
+ /* restore backlight to this value */
+ int backlight_duty_cycle;
+
+ void (*set_backlight)(xf86OutputPtr output, int level);
+ int (*get_backlight)(xf86OutputPtr output);
+ int backlight_max;
+};
+
+#define BACKLIGHT_CLASS "/sys/class/backlight"
+
+/*
+ * List of available kernel interfaces in priority order
+ */
+static char *backlight_interfaces[] = {
+ "thinkpad_screen",
+ "acpi_video1",
+ "acpi_video0",
+ NULL,
+};
+
+/*
+ * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table +
+ * '/' + "max_backlight"
+ */
+#define BACKLIGHT_PATH_LEN 80
+/* Enough for 8 digits of backlight + '\n' + '\0' */
+#define BACKLIGHT_VALUE_LEN 10
+
+static int backlight_index;
+
+static Bool
+i830_kernel_backlight_available(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ struct stat buf;
+ char path[BACKLIGHT_PATH_LEN];
+ int i;
+
+ for (i = 0; backlight_interfaces[i] != NULL; i++) {
+ sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]);
+ if (!stat(path, &buf)) {
+ backlight_index = i;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "found backlight control "
+ "method %s\n", path);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Try to figure out which backlight control method to use */
+static void
+i830_set_lvds_backlight_method(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 blc_pwm_ctl, blc_pwm_ctl2;
+ enum backlight_control method = NATIVE; /* Default to native */
+
+ if (i830_kernel_backlight_available(output)) {
+ method = KERNEL;
+ } else if (IS_I965GM(pI830)) {
+ blc_pwm_ctl2 = INREG(BLC_PWM_CTL2);
+ if (blc_pwm_ctl2 & BLM_LEGACY_MODE2)
+ method = COMBO;
+ } else {
+ blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ if (blc_pwm_ctl & BLM_LEGACY_MODE)
+ method = COMBO;
+ }
+
+ pI830->backlight_control_method = method;
+}
+
+/*
+ * Native methods
+ */
+static void
+i830_lvds_set_backlight_native(xf86OutputPtr output, int level)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 blc_pwm_ctl;
+
+ blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+ OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+}
+
+static int
+i830_lvds_get_backlight_native(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 blc_pwm_ctl;
+
+ blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
+ return blc_pwm_ctl;
+}
+
+static int
+i830_lvds_get_backlight_max_native(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 pwm_ctl = INREG(BLC_PWM_CTL);
+ int val;
+
+ if (IS_I965GM(pI830)) {
+ val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT2);
+ } else {
+ val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+ }
+
+ return val;
+}
+
+/*
+ * Legacy methods
+ */
+static void
+i830_lvds_set_backlight_legacy(xf86OutputPtr output, int level)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+#if XSERVER_LIBPCIACCESS
+ pci_device_cfg_write_u8(pI830->PciInfo, level,
+ LEGACY_BACKLIGHT_BRIGHTNESS);
+#else
+ pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, level);
+#endif
+}
+
+static int
+i830_lvds_get_backlight_legacy(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD8 lbb;
+
+#if XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(pI830->PciInfo, &lbb, LEGACY_BACKLIGHT_BRIGHTNESS);
+#else
+ lbb = pciReadByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS);
+#endif
+
+ return lbb;
+}
+
+/*
+ * Combo methods
+ */
+static void
+i830_lvds_set_backlight_combo(xf86OutputPtr output, int level)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 blc_pwm_ctl;
+ CARD8 lbb;
+
+#if XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(pI830->PciInfo, &lbb, LEGACY_BACKLIGHT_BRIGHTNESS);
+#else
+ lbb = pciReadByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS);
+#endif
+ /*
+ * If LBB is zero and we're shooting for a non-zero brightness level,
+ * we have to increase LBB by at least 1.
+ */
+ if (!lbb && level) {
+#if XSERVER_LIBPCIACCESS
+ pci_device_cfg_write_u8(pI830->PciInfo, 1,
+ LEGACY_BACKLIGHT_BRIGHTNESS);
+#else
+ pciWriteByte(pI830->PciTag, LEGACY_BACKLIGHT_BRIGHTNESS, 1);
+#endif
+ }
+
+ blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+ OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+}
+
+static int
+i830_lvds_get_backlight_combo(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 blc_pwm_ctl;
+
+ blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ blc_pwm_ctl &= BACKLIGHT_DUTY_CYCLE_MASK;
+ return blc_pwm_ctl;
+}
+
+/*
+ * Kernel methods
+ */
+static void
+i830_lvds_set_backlight_kernel(xf86OutputPtr output, int level)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
+ int fd, len, ret;
+
+ len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level);
+ if (len > BACKLIGHT_VALUE_LEN) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "backlight value too large: %d\n",
+ level);
+ return;
+ }
+
+ sprintf(path, "%s/%s/brightness", BACKLIGHT_CLASS,
+ backlight_interfaces[backlight_index]);
+ fd = open(path, O_RDWR);
+ if (fd == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to open %s for backlight "
+ "control: %s\n", path, strerror(errno));
+ return;
+ }
+
+ ret = write(fd, val, len);
+ if (ret == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "write to %s for backlight "
+ "control failed: %s\n", path, strerror(errno));
+ }
+
+ close(fd);
+}
+
+static int
+i830_lvds_get_backlight_kernel(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
+ int fd;
+
+ sprintf(path, "%s/%s/actual_brightness", BACKLIGHT_CLASS,
+ backlight_interfaces[backlight_index]);
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to open %s for backlight "
+ "control: %s\n", path, strerror(errno));
+ return 0;
+ }
+
+ if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1)
+ goto out_err;
+
+ close(fd);
+ return atoi(val);
+
+out_err:
+ close(fd);
+ return 0;
+}
+
+static int
+i830_lvds_get_backlight_max_kernel(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
+ int fd, max = 0;
+
+ sprintf(path, "%s/%s/max_brightness", BACKLIGHT_CLASS,
+ backlight_interfaces[backlight_index]);
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "failed to open %s for backlight "
+ "control: %s\n", path, strerror(errno));
+ return 0;
+ }
+
+ if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1)
+ goto out_err;
+
+ close(fd);
+
+ max = atoi(val);
+
+ return max;
+
+out_err:
+ close(fd);
+ return 0;
+}
+
+/**
+ * Sets the power state for the panel.
+ */
+static void
+i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 pp_status;
+
+ if (on) {
+ OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+ do {
+ pp_status = INREG(PP_STATUS);
+ } while ((pp_status & PP_ON) == 0);
+
+ dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle);
+ } else {
+ dev_priv->set_backlight(output, 0);
+
+ OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+ do {
+ pp_status = INREG(PP_STATUS);
+ } while (pp_status & PP_ON);
+ }
+}
+
+static void
+i830_lvds_dpms (xf86OutputPtr output, int mode)
+{
+ if (mode == DPMSModeOn)
+ i830SetLVDSPanelPower(output, TRUE);
+ else
+ i830SetLVDSPanelPower(output, FALSE);
+
+ /* XXX: We never power down the LVDS pairs. */
+}
+
+static void
+i830_lvds_save (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (IS_I965GM(pI830))
+ pI830->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2);
+ pI830->savePP_ON = INREG(LVDSPP_ON);
+ pI830->savePP_OFF = INREG(LVDSPP_OFF);
+ pI830->savePP_CONTROL = INREG(PP_CONTROL);
+ pI830->savePP_CYCLE = INREG(PP_CYCLE);
+ pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
+ dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
+
+ /*
+ * If the light is off at server startup, just make it full brightness
+ */
+ if (dev_priv->backlight_duty_cycle == 0)
+ dev_priv->backlight_duty_cycle = dev_priv->backlight_max;
+}
+
+static void
+i830_lvds_restore(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (IS_I965GM(pI830))
+ OUTREG(BLC_PWM_CTL2, pI830->saveBLC_PWM_CTL2);
+ OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
+ OUTREG(LVDSPP_ON, pI830->savePP_ON);
+ OUTREG(LVDSPP_OFF, pI830->savePP_OFF);
+ OUTREG(PP_CYCLE, pI830->savePP_CYCLE);
+ OUTREG(PP_CONTROL, pI830->savePP_CONTROL);
+ if (pI830->savePP_CONTROL & POWER_TARGET_ON)
+ i830SetLVDSPanelPower(output, TRUE);
+ else
+ i830SetLVDSPanelPower(output, FALSE);
+}
+
+static int
+i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ DisplayModePtr pFixedMode = dev_priv->panel_fixed_mode;
+
+ if (pFixedMode)
+ {
+ if (pMode->HDisplay > pFixedMode->HDisplay)
+ return MODE_PANEL;
+ if (pMode->VDisplay > pFixedMode->VDisplay)
+ return MODE_PANEL;
+ }
+
+ return MODE_OK;
+}
+
+static Bool
+i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
+ int i;
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr other_output = xf86_config->output[i];
+
+ if (other_output != output && other_output->crtc == output->crtc) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't enable LVDS and another output on the same "
+ "pipe\n");
+ return FALSE;
+ }
+ }
+
+ if (intel_crtc->pipe == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't support LVDS on pipe A\n");
+ return FALSE;
+ }
+
+ /* If we have timings from the BIOS for the panel, put them in
+ * to the adjusted mode. The CRTC will be set up for this mode,
+ * with the panel scaling set up to source from the H/VDisplay
+ * of the original mode.
+ */
+ if (dev_priv->panel_fixed_mode != NULL) {
+ adjusted_mode->HDisplay = dev_priv->panel_fixed_mode->HDisplay;
+ adjusted_mode->HSyncStart = dev_priv->panel_fixed_mode->HSyncStart;
+ adjusted_mode->HSyncEnd = dev_priv->panel_fixed_mode->HSyncEnd;
+ adjusted_mode->HTotal = dev_priv->panel_fixed_mode->HTotal;
+ adjusted_mode->VDisplay = dev_priv->panel_fixed_mode->VDisplay;
+ adjusted_mode->VSyncStart = dev_priv->panel_fixed_mode->VSyncStart;
+ adjusted_mode->VSyncEnd = dev_priv->panel_fixed_mode->VSyncEnd;
+ adjusted_mode->VTotal = dev_priv->panel_fixed_mode->VTotal;
+ adjusted_mode->Clock = dev_priv->panel_fixed_mode->Clock;
+ xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
+ }
+
+ /* XXX: It would be nice to support lower refresh rates on the
+ * panels to reduce power consumption, and perhaps match the
+ * user's requested refresh rate.
+ */
+
+ return TRUE;
+}
+
+static void
+i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private;
+ CARD32 pfit_control;
+
+ /* The LVDS pin pair will already have been turned on in
+ * i830_crtc_mode_set since it has a large impact on the DPLL settings.
+ */
+
+ /* Enable automatic panel scaling for non-native modes so that they fill
+ * the screen. Should be enabled before the pipe is enabled, according to
+ * register description and PRM.
+ */
+ if (mode->HDisplay != adjusted_mode->HDisplay ||
+ mode->VDisplay != adjusted_mode->VDisplay)
+ {
+ pfit_control = PFIT_ENABLE |
+ VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+ VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR;
+ } else {
+ pfit_control = 0;
+ }
+
+ if (!IS_I965G(pI830)) {
+ if (dev_priv->panel_wants_dither)
+ pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+ } else {
+ pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
+ }
+
+ OUTREG(PFIT_CONTROL, pfit_control);
+}
+
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns OUTPUT_STATUS_CONNECTED. This output should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static xf86OutputStatus
+i830_lvds_detect(xf86OutputPtr output)
+{
+ return XF86OutputStatusConnected;
+}
+
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static DisplayModePtr
+i830_lvds_get_modes(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ xf86MonPtr edid_mon;
+ DisplayModePtr modes;
+
+ edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+ xf86OutputSetEDID (output, edid_mon);
+
+ modes = xf86OutputGetEDIDModes (output);
+ if (modes != NULL)
+ return modes;
+
+ if (!output->MonInfo)
+ {
+ edid_mon = xcalloc (1, sizeof (xf86Monitor));
+ if (edid_mon)
+ {
+ /* Set wide sync ranges so we get all modes
+ * handed to valid_mode for checking
+ */
+ edid_mon->det_mon[0].type = DS_RANGES;
+ edid_mon->det_mon[0].section.ranges.min_v = 0;
+ edid_mon->det_mon[0].section.ranges.max_v = 200;
+ edid_mon->det_mon[0].section.ranges.min_h = 0;
+ edid_mon->det_mon[0].section.ranges.max_h = 200;
+
+ output->MonInfo = edid_mon;
+ }
+ }
+
+ if (dev_priv->panel_fixed_mode != NULL)
+ return xf86DuplicateMode(dev_priv->panel_fixed_mode);
+
+ return NULL;
+}
+
+static void
+i830_lvds_destroy (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+
+ if (intel_output)
+ {
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+
+ xf86DeleteMode (&dev_priv->panel_fixed_mode, dev_priv->panel_fixed_mode);
+ xfree (intel_output);
+ }
+}
+
+#ifdef RANDR_12_INTERFACE
+#define BACKLIGHT_NAME "BACKLIGHT"
+static Atom backlight_atom;
+
+/*
+ * Backlight control lets the user select how the driver should manage
+ * backlight changes: using the legacy interface, the native interface,
+ * or not at all.
+ */
+#define BACKLIGHT_CONTROL_NAME "BACKLIGHT_CONTROL"
+#define NUM_BACKLIGHT_CONTROL_METHODS 4
+static char *backlight_control_names[] = {
+ "native",
+ "legacy",
+ "combination",
+ "kernel",
+};
+static Atom backlight_control_atom;
+static Atom backlight_control_name_atoms[NUM_BACKLIGHT_CONTROL_METHODS];
+
+static int
+i830_backlight_control_lookup(char *name)
+{
+ int i;
+
+ for (i = 0; i < NUM_BACKLIGHT_CONTROL_METHODS; i++)
+ if (!strcmp(name, backlight_control_names[i]))
+ return i;
+
+ return -1;
+}
+
+static Bool
+i830_lvds_set_backlight_control(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+
+ switch (pI830->backlight_control_method) {
+ case NATIVE:
+ dev_priv->set_backlight = i830_lvds_set_backlight_native;
+ dev_priv->get_backlight = i830_lvds_get_backlight_native;
+ dev_priv->backlight_max =
+ i830_lvds_get_backlight_max_native(output);
+ break;
+ case LEGACY:
+ dev_priv->set_backlight = i830_lvds_set_backlight_legacy;
+ dev_priv->get_backlight = i830_lvds_get_backlight_legacy;
+ dev_priv->backlight_max = 0xff;
+ break;
+ case COMBO:
+ dev_priv->set_backlight = i830_lvds_set_backlight_combo;
+ dev_priv->get_backlight = i830_lvds_get_backlight_combo;
+ dev_priv->backlight_max =
+ i830_lvds_get_backlight_max_native(output);
+ break;
+ case KERNEL:
+ dev_priv->set_backlight = i830_lvds_set_backlight_kernel;
+ dev_priv->get_backlight = i830_lvds_get_backlight_kernel;
+ dev_priv->backlight_max =
+ i830_lvds_get_backlight_max_kernel(output);
+ break;
+ default:
+ /*
+ * Should be impossible to get here unless the caller set a bogus
+ * backlight_control_method
+ */
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "error: bad backlight control "
+ "method\n");
+ break;
+ }
+
+ return Success;
+}
+#endif /* RANDR_12_INTERFACE */
+
+static void
+i830_lvds_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+ INT32 backlight_range[2];
+ int data, err, i;
+
+ /* Set up the backlight property, which takes effect immediately
+ * and accepts values only within the backlight_range.
+ *
+ * XXX: Currently, RandR doesn't verify that properties set are
+ * within the backlight_range.
+ */
+ backlight_atom = MakeAtom(BACKLIGHT_NAME, sizeof(BACKLIGHT_NAME) - 1,
+ TRUE);
+
+ backlight_range[0] = 0;
+ backlight_range[1] = dev_priv->backlight_max;
+ err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
+ FALSE, TRUE, FALSE, 2, backlight_range);
+ if (err != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ /* Set the current value of the backlight property */
+ data = dev_priv->backlight_duty_cycle;
+ err = RRChangeOutputProperty(output->randr_output, backlight_atom,
+ XA_INTEGER, 32, PropModeReplace, 1, &data,
+ FALSE, TRUE);
+ if (err != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+
+ /*
+ * Now setup the control selection property
+ */
+ backlight_control_atom = MakeAtom(BACKLIGHT_CONTROL_NAME,
+ sizeof(BACKLIGHT_CONTROL_NAME) - 1, TRUE);
+ for (i = 0; i < NUM_BACKLIGHT_CONTROL_METHODS; i++) {
+ backlight_control_name_atoms[i] =
+ MakeAtom(backlight_control_names[i],
+ strlen(backlight_control_names[i]), TRUE);
+ }
+ err = RRConfigureOutputProperty(output->randr_output,
+ backlight_control_atom, TRUE, FALSE, FALSE,
+ NUM_BACKLIGHT_CONTROL_METHODS,
+ (INT32 *)backlight_control_name_atoms);
+ if (err != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ err = RRChangeOutputProperty(output->randr_output, backlight_control_atom,
+ XA_ATOM, 32, PropModeReplace, 1,
+ &backlight_control_name_atoms[pI830->backlight_control_method],
+ FALSE, TRUE);
+ if (err != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "failed to set backlight control, %d\n", err);
+ }
+#endif /* RANDR_12_INTERFACE */
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+i830_lvds_set_property(xf86OutputPtr output, Atom property,
+ RRPropertyValuePtr value)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
+
+ if (property == backlight_atom) {
+ INT32 val;
+
+ if (value->type != XA_INTEGER || value->format != 32 ||
+ value->size != 1)
+ {
+ return FALSE;
+ }
+
+ val = *(INT32 *)value->data;
+ if (val < 0 || val > dev_priv->backlight_max)
+ return FALSE;
+
+ if (val != dev_priv->backlight_duty_cycle) {
+ dev_priv->set_backlight(output, val);
+ dev_priv->backlight_duty_cycle = val;
+ }
+ return TRUE;
+ } else if (property == backlight_control_atom) {
+ INT32 backlight_range[2];
+ Atom atom;
+ char *name;
+ int ret, data;
+
+ if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+ return FALSE;
+
+ memcpy(&atom, value->data, 4);
+ name = NameForAtom(atom);
+
+ ret = i830_backlight_control_lookup(name);
+ if (ret < 0)
+ return FALSE;
+
+ pI830->backlight_control_method = ret;
+ i830_lvds_set_backlight_control(output);
+
+ /*
+ * Update the backlight atom since the range and value may have changed
+ */
+ backlight_range[0] = 0;
+ backlight_range[1] = dev_priv->backlight_max;
+ ret = RRConfigureOutputProperty(output->randr_output, backlight_atom,
+ FALSE, TRUE, FALSE, 2, backlight_range);
+ if (ret != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", ret);
+ }
+ /* Set the current value of the backlight property */
+ data = dev_priv->get_backlight(output);
+ ret = RRChangeOutputProperty(output->randr_output, backlight_atom,
+ XA_INTEGER, 32, PropModeReplace, 1, &data,
+ FALSE, TRUE);
+ if (ret != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", ret);
+ }
+ return TRUE;
+ }
+
+ return TRUE;
+}
+#endif /* RANDR_12_INTERFACE */
+
+static const xf86OutputFuncsRec i830_lvds_output_funcs = {
+ .create_resources = i830_lvds_create_resources,
+ .dpms = i830_lvds_dpms,
+ .save = i830_lvds_save,
+ .restore = i830_lvds_restore,
+ .mode_valid = i830_lvds_mode_valid,
+ .mode_fixup = i830_lvds_mode_fixup,
+ .prepare = i830_output_prepare,
+ .mode_set = i830_lvds_mode_set,
+ .commit = i830_output_commit,
+ .detect = i830_lvds_detect,
+ .get_modes = i830_lvds_get_modes,
+#ifdef RANDR_12_INTERFACE
+ .set_property = i830_lvds_set_property,
+#endif
+ .destroy = i830_lvds_destroy
+};
+
+void
+i830_lvds_init(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86OutputPtr output;
+ I830OutputPrivatePtr intel_output;
+ DisplayModePtr modes, scan, bios_mode;
+ struct i830_lvds_priv *dev_priv;
+
+ if (pI830->quirk_flag & QUIRK_IGNORE_LVDS)
+ return;
+
+ output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS");
+ if (!output)
+ return;
+ intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+ sizeof (struct i830_lvds_priv), 1);
+ if (!intel_output)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+ intel_output->type = I830_OUTPUT_LVDS;
+ intel_output->pipe_mask = (1 << 1);
+ intel_output->clone_mask = (1 << I830_OUTPUT_LVDS);
+
+ output->driver_private = intel_output;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+
+ dev_priv = (struct i830_lvds_priv *) (intel_output + 1);
+ intel_output->dev_priv = dev_priv;
+
+ /* Set up the LVDS DDC channel. Most panels won't support it, but it can
+ * be useful if available.
+ */
+ I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
+
+ /* Attempt to get the fixed panel mode from DDC. Assume that the preferred
+ * mode is the right one.
+ */
+ modes = i830_ddc_get_modes(output);
+ for (scan = modes; scan != NULL; scan = scan->next) {
+ if (scan->type & M_T_PREFERRED)
+ break;
+ }
+ if (scan != NULL) {
+ /* Pull our chosen mode out and make it the fixed mode */
+ if (modes == scan)
+ modes = modes->next;
+ if (scan->prev != NULL)
+ scan->prev = scan->next;
+ if (scan->next != NULL)
+ scan->next = scan->prev;
+ dev_priv->panel_fixed_mode = scan;
+ }
+ /* Delete the mode list */
+ while (modes != NULL)
+ xf86DeleteMode(&modes, modes);
+
+ /* If we didn't get EDID, try checking if the panel is already turned on.
+ * If so, assume that whatever is currently programmed is the correct mode.
+ */
+ if (dev_priv->panel_fixed_mode == NULL) {
+ CARD32 lvds = INREG(LVDS);
+ int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc = xf86_config->crtc[pipe];
+
+ if (lvds & LVDS_PORT_EN) {
+ dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
+ if (dev_priv->panel_fixed_mode != NULL)
+ dev_priv->panel_fixed_mode->type |= M_T_PREFERRED;
+ }
+ }
+
+ /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with
+ * the BIOS being unavailable or broken, but lack the configuration options
+ * for now.
+ */
+ bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither);
+ if (bios_mode != NULL) {
+ if (dev_priv->panel_fixed_mode != NULL) {
+ /* Fixup for a 1280x768 panel with the horizontal trimmed
+ * down to 1024 for text mode.
+ */
+ if (!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode) &&
+ dev_priv->panel_fixed_mode->HDisplay == 1024 &&
+ dev_priv->panel_fixed_mode->HSyncStart == 1200 &&
+ dev_priv->panel_fixed_mode->HSyncEnd == 1312 &&
+ dev_priv->panel_fixed_mode->HTotal == 1688 &&
+ dev_priv->panel_fixed_mode->VDisplay == 768)
+ {
+ dev_priv->panel_fixed_mode->HDisplay = 1280;
+ dev_priv->panel_fixed_mode->HSyncStart = 1328;
+ dev_priv->panel_fixed_mode->HSyncEnd = 1440;
+ dev_priv->panel_fixed_mode->HTotal = 1688;
+ }
+
+ if (pI830->debug_modes &&
+ !xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "BIOS panel mode data doesn't match probed data, "
+ "continuing with probed.\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n");
+ xf86PrintModeline(pScrn->scrnIndex, bios_mode);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n");
+ xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode);
+ xfree(bios_mode->name);
+ xfree(bios_mode);
+ }
+ } else {
+ dev_priv->panel_fixed_mode = bios_mode;
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Couldn't detect panel mode. Disabling panel\n");
+ goto disable_exit;
+ }
+
+ /* Blacklist machines with BIOSes that list an LVDS panel without actually
+ * having one.
+ */
+ if (pI830->quirk_flag & QUIRK_IGNORE_MACMINI_LVDS) {
+ /* It's a Mac Mini or Macbook Pro.
+ *
+ * Apple hardware is out to get us. The macbook pro has a real
+ * LVDS panel, but the mac mini does not, and they have the same
+ * device IDs. We'll distinguish by panel size, on the assumption
+ * that Apple isn't about to make any machines with an 800x600
+ * display.
+ */
+
+ if (dev_priv->panel_fixed_mode != NULL &&
+ dev_priv->panel_fixed_mode->HDisplay == 800 &&
+ dev_priv->panel_fixed_mode->VDisplay == 600)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Suspected Mac Mini, ignoring the LVDS\n");
+ goto disable_exit;
+ }
+ }
+
+ i830_set_lvds_backlight_method(output);
+
+ switch (pI830->backlight_control_method) {
+ case NATIVE:
+ dev_priv->set_backlight = i830_lvds_set_backlight_native;
+ dev_priv->get_backlight = i830_lvds_get_backlight_native;
+ dev_priv->backlight_max = i830_lvds_get_backlight_max_native(output);
+ break;
+ case LEGACY:
+ dev_priv->set_backlight = i830_lvds_set_backlight_legacy;
+ dev_priv->get_backlight = i830_lvds_get_backlight_legacy;
+ dev_priv->backlight_max = 0xff;
+ break;
+ case COMBO:
+ dev_priv->set_backlight = i830_lvds_set_backlight_combo;
+ dev_priv->get_backlight = i830_lvds_get_backlight_combo;
+ dev_priv->backlight_max = i830_lvds_get_backlight_max_native(output);
+ break;
+ case KERNEL:
+ dev_priv->set_backlight = i830_lvds_set_backlight_kernel;
+ dev_priv->get_backlight = i830_lvds_get_backlight_kernel;
+ dev_priv->backlight_max = i830_lvds_get_backlight_max_kernel(output);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "bad backlight control method\n");
+ break;
+ }
+
+ dev_priv->backlight_duty_cycle = dev_priv->backlight_max;
+
+ return;
+
+disable_exit:
+ xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+ xf86OutputDestroy(output);
+}
diff --git a/driver/xf86-video-intel/src/i830_quirks.c b/driver/xf86-video-intel/src/i830_quirks.c
new file mode 100644
index 000000000..1ed6503da
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_quirks.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Zhenyu Wang <zhenyu.z.wang@intel.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "i830.h"
+
+#define SUBSYS_ANY (~0)
+
+typedef struct {
+ int chipType;
+ int subsysVendor;
+ int subsysCard;
+ void (*hook)(I830Ptr);
+} i830_quirk, *i830_quirk_ptr;
+
+static void quirk_ignore_tv (I830Ptr pI830)
+{
+ pI830->quirk_flag |= QUIRK_IGNORE_TV;
+}
+
+static void quirk_ignore_lvds (I830Ptr pI830)
+{
+ pI830->quirk_flag |= QUIRK_IGNORE_LVDS;
+}
+
+static void quirk_mac_mini (I830Ptr pI830)
+{
+ pI830->quirk_flag |= QUIRK_IGNORE_MACMINI_LVDS;
+}
+
+/* keep this list sorted by OEM, then by chip ID */
+static i830_quirk i830_quirk_list[] = {
+ /* Aopen mini pc */
+ { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
+ { PCI_CHIP_I965_GM, 0x8086, 0x1999, quirk_ignore_lvds },
+
+ /* Apple Mac mini has no lvds, but macbook pro does */
+ { PCI_CHIP_I945_GM, 0x8086, 0x7270, quirk_mac_mini },
+
+ /* Dell Latitude X1 */
+ { PCI_CHIP_I945_GM, 0x1028, 0x01a3, quirk_ignore_tv },
+ /* Dell XPS 1330 */
+ { PCI_CHIP_I965_GM, 0x1028, 0x0209, quirk_ignore_tv },
+
+ /* Lenovo X60s has no TV output */
+ { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_ignore_tv },
+ /* Lenovo T61 has no TV output */
+ { PCI_CHIP_I965_GM, 0x17aa, 0x20b5, quirk_ignore_tv },
+ /* Lenovo 3000 v200 */
+ { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
+
+ /* Panasonic Toughbook CF-Y4 has no TV output */
+ { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
+ /* Panasonic Toughbook CF-Y7 has no TV output */
+ { PCI_CHIP_I965_GM, 0x10f7, 0x8338, quirk_ignore_tv },
+
+ /* Toshiba Satellite U300 has no TV output */
+ { PCI_CHIP_I965_GM, 0x1179, 0xff50, quirk_ignore_tv },
+
+ /* Samsung Q35 has no TV output */
+ { PCI_CHIP_I945_GM, 0x144d, 0xc504, quirk_ignore_tv },
+ { 0, 0, 0, NULL },
+};
+
+void i830_fixup_devices(ScrnInfoPtr scrn)
+{
+ I830Ptr pI830 = I830PTR(scrn);
+ i830_quirk_ptr p = i830_quirk_list;
+
+ while (p && p->chipType != 0) {
+ if (DEVICE_ID(pI830->PciInfo) == p->chipType &&
+ SUBVENDOR_ID(pI830->PciInfo) == p->subsysVendor &&
+ (SUBSYS_ID(pI830->PciInfo) == p->subsysCard ||
+ p->subsysCard == SUBSYS_ANY))
+ p->hook(pI830);
+ ++p;
+ }
+}
diff --git a/driver/xf86-video-intel/src/i830_render.c b/driver/xf86-video-intel/src/i830_render.c
new file mode 100644
index 000000000..22e09c846
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_render.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...) \
+do { \
+ DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \
+ return FALSE; \
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) \
+do { \
+ return FALSE; \
+} while(0)
+#endif
+
+struct blendinfo {
+ Bool dst_alpha;
+ Bool src_alpha;
+ CARD32 src_blend;
+ CARD32 dst_blend;
+};
+
+struct formatinfo {
+ int fmt;
+ CARD32 card_fmt;
+};
+
+#define TB0C_LAST_STAGE (1 << 31)
+#define TB0C_RESULT_SCALE_1X (0 << 29)
+#define TB0C_RESULT_SCALE_2X (1 << 29)
+#define TB0C_RESULT_SCALE_4X (2 << 29)
+#define TB0C_OP_MODULE (3 << 25)
+#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24)
+#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24)
+#define TB0C_ARG3_REPLICATE_ALPHA (1<<23)
+#define TB0C_ARG3_INVERT (1<<22)
+#define TB0C_ARG3_SEL_XXX
+#define TB0C_ARG2_REPLICATE_ALPHA (1<<17)
+#define TB0C_ARG2_INVERT (1<<16)
+#define TB0C_ARG2_SEL_ONE (0 << 12)
+#define TB0C_ARG2_SEL_FACTOR (1 << 12)
+#define TB0C_ARG2_SEL_TEXEL0 (6 << 12)
+#define TB0C_ARG2_SEL_TEXEL1 (7 << 12)
+#define TB0C_ARG2_SEL_TEXEL2 (8 << 12)
+#define TB0C_ARG2_SEL_TEXEL3 (9 << 12)
+#define TB0C_ARG1_REPLICATE_ALPHA (1<<11)
+#define TB0C_ARG1_INVERT (1<<10)
+#define TB0C_ARG1_SEL_ONE (0 << 6)
+#define TB0C_ARG1_SEL_TEXEL0 (6 << 6)
+#define TB0C_ARG1_SEL_TEXEL1 (7 << 6)
+#define TB0C_ARG1_SEL_TEXEL2 (8 << 6)
+#define TB0C_ARG1_SEL_TEXEL3 (9 << 6)
+#define TB0C_ARG0_REPLICATE_ALPHA (1<<5)
+#define TB0C_ARG0_SEL_XXX
+
+#define TB0A_CTR_STAGE_ENABLE (1<<31)
+#define TB0A_RESULT_SCALE_1X (0 << 29)
+#define TB0A_RESULT_SCALE_2X (1 << 29)
+#define TB0A_RESULT_SCALE_4X (2 << 29)
+#define TB0A_OP_MODULE (3 << 25)
+#define TB0A_OUTPUT_WRITE_CURRENT (0<<24)
+#define TB0A_OUTPUT_WRITE_ACCUM (1<<24)
+#define TB0A_CTR_STAGE_SEL_BITS_XXX
+#define TB0A_ARG3_SEL_XXX
+#define TB0A_ARG3_INVERT (1<<17)
+#define TB0A_ARG2_INVERT (1<<16)
+#define TB0A_ARG2_SEL_ONE (0 << 12)
+#define TB0A_ARG2_SEL_TEXEL0 (6 << 12)
+#define TB0A_ARG2_SEL_TEXEL1 (7 << 12)
+#define TB0A_ARG2_SEL_TEXEL2 (8 << 12)
+#define TB0A_ARG2_SEL_TEXEL3 (9 << 12)
+#define TB0A_ARG1_INVERT (1<<10)
+#define TB0A_ARG1_SEL_ONE (0 << 6)
+#define TB0A_ARG1_SEL_TEXEL0 (6 << 6)
+#define TB0A_ARG1_SEL_TEXEL1 (7 << 6)
+#define TB0A_ARG1_SEL_TEXEL2 (8 << 6)
+#define TB0A_ARG1_SEL_TEXEL3 (9 << 6)
+
+static struct blendinfo i830_blend_op[] = {
+ /* Clear */
+ {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
+ /* Src */
+ {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO},
+ /* Dst */
+ {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE},
+ /* Over */
+ {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA},
+ /* OverReverse */
+ {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE},
+ /* In */
+ {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO},
+ /* InReverse */
+ {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA},
+ /* Out */
+ {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO},
+ /* OutReverse */
+ {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA},
+ /* Atop */
+ {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
+ /* AtopReverse */
+ {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA},
+ /* Xor */
+ {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
+ /* Add */
+ {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
+};
+
+static struct formatinfo i830_tex_formats[] = {
+ {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+ {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
+ {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+ {PICT_x8b8g8r8, MT_32BIT_XBGR8888 },
+ {PICT_r5g6b5, MT_16BIT_RGB565 },
+ {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+ {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+ {PICT_a8, MT_8BIT_A8 },
+};
+
+static Bool i830_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+ switch (pDstPicture->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ *dst_format = COLR_BUF_ARGB8888;
+ break;
+ case PICT_r5g6b5:
+ *dst_format = COLR_BUF_RGB565;
+ break;
+ case PICT_a1r5g5b5:
+ case PICT_x1r5g5b5:
+ *dst_format = COLR_BUF_ARGB1555;
+ break;
+ /*
+ case PICT_a8:
+ *dst_format = COLR_BUF_8BIT;
+ break;
+ */
+ case PICT_a4r4g4b4:
+ case PICT_x4r4g4b4:
+ *dst_format = COLR_BUF_ARGB4444;
+ break;
+ default:
+ I830FALLBACK("Unsupported dest format 0x%x\n",
+ (int)pDstPicture->format);
+ }
+
+ return TRUE;
+}
+
+
+static CARD32 i830_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+ CARD32 sblend, dblend;
+
+ sblend = i830_blend_op[op].src_blend;
+ dblend = i830_blend_op[op].dst_blend;
+
+ /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+ * it as always 1.
+ */
+ if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) {
+ if (sblend == BLENDFACTOR_DST_ALPHA)
+ sblend = BLENDFACTOR_ONE;
+ else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
+ sblend = BLENDFACTOR_ZERO;
+ }
+
+ /* If the source alpha is being used, then we should only be in a case
+ * where the source blend factor is 0, and the source blend value is the
+ * mask channels multiplied by the source picture's alpha.
+ */
+ if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format)
+ && i830_blend_op[op].src_alpha) {
+ if (dblend == BLENDFACTOR_SRC_ALPHA) {
+ dblend = BLENDFACTOR_SRC_COLR;
+ } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
+ dblend = BLENDFACTOR_INV_SRC_COLR;
+ }
+ }
+
+ return (sblend << S8_SRC_BLEND_FACTOR_SHIFT) |
+ (dblend << S8_DST_BLEND_FACTOR_SHIFT);
+}
+
+static Bool i830_check_composite_texture(PicturePtr pPict, int unit)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int w = pPict->pDrawable->width;
+ int h = pPict->pDrawable->height;
+ int i;
+
+ if ((w > 0x7ff) || (h > 0x7ff))
+ I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+ for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+ i++)
+ {
+ if (i830_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]))
+ I830FALLBACK("Unsupported picture format 0x%x\n",
+ (int)pPict->format);
+
+ if (IS_I830(pI830) || IS_845G(pI830)) {
+ if (pPict->format == PICT_x8r8g8b8 ||
+ pPict->format == PICT_x8b8g8r8 ||
+ pPict->format == PICT_a8)
+ I830FALLBACK("830/845G don't support a8, x8r8g8b8, x8b8g8r8\n");
+ }
+
+ if (pPict->repeat && pPict->repeatType != RepeatNormal)
+ I830FALLBACK("unsupport repeat type\n");
+
+ if (pPict->filter != PictFilterNearest &&
+ pPict->filter != PictFilterBilinear)
+ {
+ I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+ }
+
+ return TRUE;
+}
+
+static CARD32
+i8xx_get_card_format(PicturePtr pPict)
+{
+ int i;
+ for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+ i++)
+ {
+ if (i830_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ return i830_tex_formats[i].card_fmt;
+}
+
+static Bool
+i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+
+ ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 format, offset, pitch, filter;
+ CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
+
+ offset = intel_get_pixmap_offset(pPix);
+ pitch = intel_get_pixmap_pitch(pPix);
+ pI830->scale_units[unit][0] = pPix->drawable.width;
+ pI830->scale_units[unit][1] = pPix->drawable.height;
+ pI830->transform[unit] = pPict->transform;
+
+ format = i8xx_get_card_format(pPict);
+
+ if (pPict->repeat)
+ wrap_mode = TEXCOORDMODE_WRAP;
+
+ switch (pPict->filter) {
+ case PictFilterNearest:
+ filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) |
+ (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
+ break;
+ case PictFilterBilinear:
+ filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) |
+ (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
+ break;
+ default:
+ filter = 0;
+ I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+ }
+ filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
+
+ {
+ if (pPix->drawable.bitsPerPixel == 8)
+ format |= MAPSURF_8BIT;
+ else if (pPix->drawable.bitsPerPixel == 16)
+ format |= MAPSURF_16BIT;
+ else
+ format |= MAPSURF_32BIT;
+
+ BEGIN_LP_RING(10);
+ OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
+ OUT_RING((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE);
+ OUT_RING(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
+ ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
+ OUT_RING((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
+ OUT_RING(filter);
+ OUT_RING(0); /* default color */
+ OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
+ ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
+ TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL |
+ TEXCOORD_ADDR_V_MODE(wrap_mode) |
+ ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+ /* map texel stream */
+ OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
+ if (unit == 0)
+ OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+ TEXBIND_SET1(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET3(TEXCOORDSRC_KEEP));
+ else
+ OUT_RING(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+ TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+ TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET3(TEXCOORDSRC_KEEP));
+ OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(unit) |
+ ENABLE_TEX_STREAM_MAP_IDX |
+ TEX_STREAM_MAP_IDX(unit));
+ ADVANCE_LP_RING();
+ }
+
+#ifdef I830DEBUG
+ ErrorF("try to sync to show any errors...");
+ I830Sync(pScrn);
+#endif
+
+ return TRUE;
+}
+
+Bool
+i830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ CARD32 tmp1;
+
+ /* Check for unsupported compositing operations. */
+ if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0]))
+ I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+
+ if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i830_blend_op[op].src_alpha &&
+ (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO))
+ I830FALLBACK("Component alpha not supported with source "
+ "alpha and source value blending.\n");
+ }
+
+ if (!i830_check_composite_texture(pSrcPicture, 0))
+ I830FALLBACK("Check Src picture texture\n");
+ if (pMaskPicture != NULL && !i830_check_composite_texture(pMaskPicture, 1))
+ I830FALLBACK("Check Mask picture texture\n");
+
+ if (!i830_get_dest_format(pDstPicture, &tmp1))
+ I830FALLBACK("Get Color buffer format\n");
+
+ return TRUE;
+}
+
+Bool
+i830_prepare_composite(int op, PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 dst_format, dst_offset, dst_pitch;
+
+ IntelEmitInvarientState(pScrn);
+ *pI830->last_3d = LAST_3D_RENDER;
+
+ i830_get_dest_format(pDstPicture, &dst_format);
+ dst_offset = intel_get_pixmap_offset(pDst);
+ dst_pitch = intel_get_pixmap_pitch(pDst);
+
+ if (!i830_texture_setup(pSrcPicture, pSrc, 0))
+ I830FALLBACK("fail to setup src texture\n");
+ if (pMask != NULL) {
+ if (!i830_texture_setup(pMaskPicture, pMask, 1))
+ I830FALLBACK("fail to setup mask texture\n");
+ } else {
+ pI830->transform[1] = NULL;
+ pI830->scale_units[1][0] = -1;
+ pI830->scale_units[1][1] = -1;
+ }
+
+ {
+ CARD32 cblend, ablend, blendctl, vf2;
+
+ BEGIN_LP_RING(30);
+
+ /* color buffer */
+ OUT_RING(_3DSTATE_BUF_INFO_CMD);
+ OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
+ BUF_3D_PITCH(dst_pitch));
+ OUT_RING(BUF_3D_ADDR(dst_offset));
+ OUT_RING(MI_NOOP);
+
+ OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_RING(dst_format);
+
+ /* defaults */
+ OUT_RING(_3DSTATE_DFLT_Z_CMD);
+ OUT_RING(0);
+
+ OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+ OUT_RING(0);
+
+ OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+ OUT_RING(0);
+
+ OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+ OUT_RING(0);
+ OUT_RING(0); /* ymin, xmin */
+ OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+ DRAW_XMAX(pDst->drawable.width - 1));
+ OUT_RING(0); /* yorig, xorig */
+
+ OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
+ I1_LOAD_S(3) | 1);
+ if (pMask)
+ vf2 = 2 << 12; /* 2 texture coord sets */
+ else
+ vf2 = 1 << 12;
+ OUT_RING(vf2); /* TEXCOORDFMT_2D */
+ OUT_RING(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
+
+ /* We use two pipes for color and alpha, and do (src In mask)
+ in one stage. Arg1 is from src pict, and arg2 is from mask pict.
+ Be sure to force 1.0 when src or mask pict has no alpha channel.
+ */
+ cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
+ TB0C_OUTPUT_WRITE_CURRENT;
+ ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
+ TB0A_OUTPUT_WRITE_CURRENT;
+
+ if (PICT_FORMAT_A(pSrcPicture->format) != 0) {
+ ablend |= TB0A_ARG1_SEL_TEXEL0;
+ cblend |= TB0C_ARG1_SEL_TEXEL0;
+ } else {
+ ablend |= TB0A_ARG1_SEL_ONE;
+ if (pMask && pMaskPicture->componentAlpha
+ && PICT_FORMAT_RGB(pMaskPicture->format)
+ && i830_blend_op[op].src_alpha)
+ cblend |= TB0C_ARG1_SEL_ONE;
+ else
+ cblend |= TB0C_ARG1_SEL_TEXEL0;
+ }
+
+ if (pMask) {
+ if (pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ if (i830_blend_op[op].src_alpha)
+ cblend |= (TB0C_ARG2_SEL_TEXEL1 |
+ TB0C_ARG1_REPLICATE_ALPHA);
+ else
+ cblend |= TB0C_ARG2_SEL_TEXEL1;
+ } else {
+ if (PICT_FORMAT_A(pMaskPicture->format) != 0)
+ cblend |= (TB0C_ARG2_SEL_TEXEL1 |
+ TB0C_ARG2_REPLICATE_ALPHA);
+ else
+ cblend |= TB0C_ARG2_SEL_ONE;
+ }
+ if (PICT_FORMAT_A(pMaskPicture->format) != 0)
+ ablend |= TB0A_ARG2_SEL_TEXEL1;
+ else
+ ablend |= TB0A_ARG2_SEL_ONE;
+ } else {
+ cblend |= TB0C_ARG2_SEL_ONE;
+ ablend |= TB0A_ARG2_SEL_ONE;
+ }
+
+ OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ LOAD_TEXTURE_BLEND_STAGE(0)|1);
+ OUT_RING(cblend);
+ OUT_RING(ablend);
+ OUT_RING(0);
+
+ blendctl = i830_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
+ OUT_RING(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
+ OUT_RING(MI_NOOP);
+ OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
+ OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | blendctl |
+ S8_ENABLE_COLOR_BUFFER_WRITE);
+
+ OUT_RING(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP |
+ DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS |
+ DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST |
+ ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
+ /* We have to explicitly say we don't want write disabled */
+ OUT_RING(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK |
+ DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE |
+ DISABLE_DITHER | ENABLE_COLOR_WRITE |
+ DISABLE_DEPTH_WRITE);
+ ADVANCE_LP_RING();
+ }
+
+#ifdef I830DEBUG
+ Error("try to sync to show any errors...");
+ I830Sync(pScrn);
+#endif
+
+ return TRUE;
+}
+
+
+/**
+ * Do a single rectangle composite operation.
+ *
+ * This function is shared between i830 and i915 generation code.
+ */
+void
+i830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int w, int h)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool has_mask;
+ float src_x[3], src_y[3], mask_x[3], mask_y[3];
+
+ i830_get_transformed_coordinates(srcX, srcY,
+ pI830->transform[0],
+ &src_x[0], &src_y[0]);
+ i830_get_transformed_coordinates(srcX, srcY + h,
+ pI830->transform[0],
+ &src_x[1], &src_y[1]);
+ i830_get_transformed_coordinates(srcX + w, srcY + h,
+ pI830->transform[0],
+ &src_x[2], &src_y[2]);
+
+ if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
+ has_mask = FALSE;
+ } else {
+ has_mask = TRUE;
+ i830_get_transformed_coordinates(maskX, maskY,
+ pI830->transform[1],
+ &mask_x[0], &mask_y[0]);
+ i830_get_transformed_coordinates(maskX, maskY + h,
+ pI830->transform[1],
+ &mask_x[1], &mask_y[1]);
+ i830_get_transformed_coordinates(maskX + w, maskY + h,
+ pI830->transform[1],
+ &mask_x[2], &mask_y[2]);
+ }
+
+ {
+ int vertex_count;
+
+ if (has_mask)
+ vertex_count = 3*6;
+ else
+ vertex_count = 3*4;
+
+ BEGIN_LP_RING(6+vertex_count);
+
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+
+ OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | (vertex_count-1));
+
+ OUT_RING_F(-0.125 + dstX + w);
+ OUT_RING_F(-0.125 + dstY + h);
+ OUT_RING_F(src_x[2] / pI830->scale_units[0][0]);
+ OUT_RING_F(src_y[2] / pI830->scale_units[0][1]);
+ if (has_mask) {
+ OUT_RING_F(mask_x[2] / pI830->scale_units[1][0]);
+ OUT_RING_F(mask_y[2] / pI830->scale_units[1][1]);
+ }
+
+ OUT_RING_F(-0.125 + dstX);
+ OUT_RING_F(-0.125 + dstY + h);
+ OUT_RING_F(src_x[1] / pI830->scale_units[0][0]);
+ OUT_RING_F(src_y[1] / pI830->scale_units[0][1]);
+ if (has_mask) {
+ OUT_RING_F(mask_x[1] / pI830->scale_units[1][0]);
+ OUT_RING_F(mask_y[1] / pI830->scale_units[1][1]);
+ }
+
+ OUT_RING_F(-0.125 + dstX);
+ OUT_RING_F(-0.125 + dstY);
+ OUT_RING_F(src_x[0] / pI830->scale_units[0][0]);
+ OUT_RING_F(src_y[0] / pI830->scale_units[0][1]);
+ if (has_mask) {
+ OUT_RING_F(mask_x[0] / pI830->scale_units[1][0]);
+ OUT_RING_F(mask_y[0] / pI830->scale_units[1][1]);
+ }
+ ADVANCE_LP_RING();
+ }
+}
+
+/**
+ * Do any cleanup from the Composite operation.
+ *
+ * This is shared between i830 through i965.
+ */
+void
+i830_done_composite(PixmapPtr pDst)
+{
+ /* NO-OP */
+}
diff --git a/driver/xf86-video-intel/src/i830_sdvo.c b/driver/xf86-video-intel/src/i830_sdvo.c
new file mode 100644
index 000000000..27677152e
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_sdvo.c
@@ -0,0 +1,1335 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+/** @file
+ * SDVO support for i915 and newer chipsets.
+ *
+ * The SDVO outputs send digital display data out over the PCIE bus to display
+ * cards implementing a defined interface. These cards may have DVI, TV, CRT,
+ * or other outputs on them.
+ *
+ * The system has two SDVO channels, which may be used for SDVO chips on the
+ * motherboard, or in the external cards. The two channels may also be used
+ * in a ganged mode to provide higher bandwidth to a single output. Currently,
+ * this code doesn't deal with either ganged mode or more than one SDVO output.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "i830.h"
+#include "i830_display.h"
+#include "i810_reg.h"
+#include "i830_sdvo_regs.h"
+
+/** SDVO driver private structure. */
+struct i830_sdvo_priv {
+ /** SDVO device on SDVO I2C bus. */
+ I2CDevRec d;
+
+ /** Register for the SDVO device: SDVOB or SDVOC */
+ int output_device;
+
+ /** Active outputs controlled by this SDVO output */
+ CARD16 active_outputs;
+
+ /**
+ * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities()
+ */
+ struct i830_sdvo_caps caps;
+
+ /** Pixel clock limitations reported by the SDVO device, in kHz */
+ int pixel_clock_min, pixel_clock_max;
+
+ /** State for save/restore */
+ /** @{ */
+ int save_sdvo_mult;
+ CARD16 save_active_outputs;
+ struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+ struct i830_sdvo_dtd save_output_dtd[16];
+ CARD32 save_SDVOX;
+ /** @} */
+};
+
+/**
+ * Writes the SDVOB or SDVOC with the given value, but always writes both
+ * SDVOB and SDVOC to work around apparent hardware issues (according to
+ * comments in the BIOS).
+ */
+static void i830_sdvo_write_sdvox(xf86OutputPtr output, CARD32 val)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 bval = val, cval = val;
+ int i;
+
+ if (dev_priv->output_device == SDVOB)
+ cval = INREG(SDVOC);
+ else
+ bval = INREG(SDVOB);
+
+ /*
+ * Write the registers twice for luck. Sometimes,
+ * writing them only once doesn't appear to 'stick'.
+ * The BIOS does this too. Yay, magic
+ */
+ for (i = 0; i < 2; i++)
+ {
+ OUTREG(SDVOB, bval);
+ POSTING_READ(SDVOB);
+ OUTREG(SDVOC, cval);
+ POSTING_READ(SDVOC);
+ }
+}
+
+/** Read a single byte from the given address on the SDVO device. */
+static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
+ unsigned char *ch)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
+ "Unable to read from %s slave 0x%02x.\n",
+ intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Read a single byte from the given address on the SDVO device. */
+static Bool i830_sdvo_read_byte_quiet(xf86OutputPtr output, int addr,
+ unsigned char *ch)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ return xf86I2CReadByte(&dev_priv->d, addr, ch);
+}
+
+/** Write a single byte to the given address on the SDVO device. */
+static Bool i830_sdvo_write_byte(xf86OutputPtr output,
+ int addr, unsigned char ch)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave 0x%02x.\n",
+ intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
+/** Mapping of command numbers to names, for debug output */
+const static struct _sdvo_cmd_name {
+ CARD8 cmd;
+ char *name;
+} sdvo_cmd_names[] = {
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODER_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+};
+
+static I2CSlaveAddr slaveAddr;
+
+#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVO" : "SDVO")
+#define SDVO_PRIV(output) ((struct i830_sdvo_priv *) (output)->dev_priv)
+
+/**
+ * Writes out the data given in args (up to 8 bytes), followed by the opcode.
+ */
+static void
+i830_sdvo_write_cmd(xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
+{
+ I830Ptr pI830 = I830PTR(output->scrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ int i;
+
+ if (slaveAddr && slaveAddr != dev_priv->d.SlaveAddr)
+ ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr);
+
+ /* Write the SDVO command logging */
+ if (pI830->debug_modes) {
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ",
+ SDVO_NAME(dev_priv), cmd);
+ for (i = 0; i < args_len; i++)
+ LogWrite(1, "%02X ", ((CARD8 *)args)[i]);
+ for (; i < 8; i++)
+ LogWrite(1, " ");
+ for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
+ i++)
+ {
+ if (cmd == sdvo_cmd_names[i].cmd) {
+ LogWrite(1, "(%s)", sdvo_cmd_names[i].name);
+ break;
+ }
+ }
+ if (i == sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
+ LogWrite(1, "(%02X)", cmd);
+ LogWrite(1, "\n");
+ }
+
+ /* send the output regs */
+ for (i = 0; i < args_len; i++) {
+ i830_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((CARD8 *)args)[i]);
+ }
+ /* blast the command reg */
+ i830_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd);
+}
+
+static const char *cmd_status_names[] = {
+ "Power on",
+ "Success",
+ "Not supported",
+ "Invalid arg",
+ "Pending",
+ "Target not specified",
+ "Scaling not supported"
+};
+
+/**
+ * Reads back response_len bytes from the SDVO device, and returns the status.
+ */
+static CARD8
+i830_sdvo_read_response(xf86OutputPtr output, void *response, int response_len)
+{
+ I830Ptr pI830 = I830PTR(output->scrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ int i;
+ CARD8 status;
+ CARD8 retry = 50;
+
+ while (retry--) {
+ /* Read the command response */
+ for (i = 0; i < response_len; i++) {
+ i830_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i,
+ &((CARD8 *)response)[i]);
+ }
+
+ /* Read the return status */
+ i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
+
+ /* Write the SDVO command logging */
+ if (pI830->debug_modes) {
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO,
+ "%s: R: ", SDVO_NAME(SDVO_PRIV(intel_output)));
+ for (i = 0; i < response_len; i++)
+ LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
+ for (; i < 8; i++)
+ LogWrite(1, " ");
+ if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) {
+ LogWrite(1, "(%s)", cmd_status_names[status]);
+ } else {
+ LogWrite(1, "(??? %d)", status);
+ }
+ LogWrite(1, "\n");
+ }
+
+ if (status != SDVO_CMD_STATUS_PENDING)
+ return status;
+
+ intel_output->pI2CBus->I2CUDelay(intel_output->pI2CBus, 50);
+ }
+
+ return status;
+}
+
+int
+i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode)
+{
+ if (pMode->Clock >= 100000)
+ return 1;
+ else if (pMode->Clock >= 50000)
+ return 2;
+ else
+ return 4;
+}
+
+/* Sets the control bus switch to either point at one of the DDC buses or the
+ * PROM. It resets from the DDC bus back to internal registers at the next I2C
+ * STOP. PROM access is terminated by accessing an internal register.
+ */
+static void
+i830_sdvo_set_control_bus_switch(xf86OutputPtr output, CARD8 target)
+{
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
+}
+
+static Bool
+i830_sdvo_set_target_input(xf86OutputPtr output, Bool target_0, Bool target_1)
+{
+ struct i830_sdvo_set_target_input_args targets = {0};
+ CARD8 status;
+
+ if (target_0 && target_1)
+ return SDVO_CMD_STATUS_NOTSUPP;
+
+ if (target_1)
+ targets.target_1 = 1;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets,
+ sizeof(targets));
+
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+/**
+ * Return whether each input is trained.
+ *
+ * This function is making an assumption about the layout of the response,
+ * which should be checked against the docs.
+ */
+static Bool
+i830_sdvo_get_trained_inputs(xf86OutputPtr output, Bool *input_1, Bool *input_2)
+{
+ struct i830_sdvo_get_trained_inputs_response response;
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
+
+ status = i830_sdvo_read_response(output, &response, sizeof(response));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ *input_1 = response.input0_trained;
+ *input_2 = response.input1_trained;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_get_active_outputs(xf86OutputPtr output,
+ CARD16 *outputs)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
+ status = i830_sdvo_read_response(output, outputs, sizeof(*outputs));
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static Bool
+i830_sdvo_set_active_outputs(xf86OutputPtr output,
+ CARD16 outputs)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
+ sizeof(outputs));
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static Bool
+i830_sdvo_set_encoder_power_state(xf86OutputPtr output, int mode)
+{
+ CARD8 status;
+ CARD8 state;
+
+ switch (mode) {
+ case DPMSModeOn:
+ state = SDVO_ENCODER_STATE_ON;
+ break;
+ case DPMSModeStandby:
+ state = SDVO_ENCODER_STATE_STANDBY;
+ break;
+ case DPMSModeSuspend:
+ state = SDVO_ENCODER_STATE_SUSPEND;
+ break;
+ case DPMSModeOff:
+ state = SDVO_ENCODER_STATE_OFF;
+ break;
+ }
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
+ sizeof(state));
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+/**
+ * Returns the pixel clock range limits of the current target input in kHz.
+ */
+static Bool
+i830_sdvo_get_input_pixel_clock_range(xf86OutputPtr output, int *clock_min,
+ int *clock_max)
+{
+ struct i830_sdvo_pixel_clock_range clocks;
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, 0);
+
+ status = i830_sdvo_read_response(output, &clocks, sizeof(clocks));
+
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ /* Convert the values from units of 10 kHz to kHz. */
+ *clock_min = clocks.min * 10;
+ *clock_max = clocks.max * 10;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_set_target_output(xf86OutputPtr output, CARD16 outputs)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
+ sizeof(outputs));
+
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+/** Fetches either input or output timings to *dtd, depending on cmd. */
+static Bool
+i830_sdvo_get_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, cmd, NULL, 0);
+
+ status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ i830_sdvo_write_cmd(output, cmd + 1, NULL, 0);
+
+ status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_get_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+{
+ return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
+}
+
+static Bool
+i830_sdvo_get_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+{
+ return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
+}
+
+/** Sets either input or output timings from *dtd, depending on cmd. */
+static Bool
+i830_sdvo_set_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1));
+ status = i830_sdvo_read_response(output, NULL, 0);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ i830_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
+ status = i830_sdvo_read_response(output, NULL, 0);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_set_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+{
+ return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
+}
+
+static Bool
+i830_sdvo_set_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+{
+ return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
+}
+
+#if 0
+static Bool
+i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, CARD16 clock,
+ CARD16 width, CARD16 height)
+{
+ struct i830_sdvo_priv *dev_priv = output->dev_priv;
+ struct i830_sdvo_preferred_input_timing_args args;
+
+ args.clock = clock;
+ args.width = width;
+ args.height = height;
+ i830_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
+ &args, sizeof(args));
+ status = i830_sdvo_read_response(output, NULL, 0);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
+ struct i830_sdvo_dtd *dtd)
+{
+ struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
+ NULL, 0);
+
+ status = i830_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
+ NULL, 0);
+
+ status = i830_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+/** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
+static int
+i830_sdvo_get_clock_rate_mult(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ CARD8 response;
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
+ status = i830_sdvo_read_response(output, &response, 1);
+
+ if (status != SDVO_CMD_STATUS_SUCCESS) {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "Couldn't get SDVO clock rate multiplier\n");
+ return SDVO_CLOCK_RATE_MULT_1X;
+ } else {
+ xf86DrvMsg(dev_priv->d.pI2CBus->scrnIndex, X_INFO,
+ "Current clock rate multiplier: %d\n", response);
+ }
+
+ return response;
+}
+
+/**
+ * Sets the current clock multiplier.
+ *
+ * This has to match with the settings in the DPLL/SDVO reg when the output
+ * is actually turned on.
+ */
+static Bool
+i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, CARD8 val)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
+ status = i830_sdvo_read_response(output, NULL, 0);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO
+ * device will be told of the multiplier during mode_set.
+ */
+ adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+
+ return TRUE;
+}
+
+static void
+i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ xf86CrtcPtr crtc = output->crtc;
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ CARD32 sdvox;
+ int sdvo_pixel_multiply;
+ CARD16 width, height;
+ CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+ CARD16 h_sync_offset, v_sync_offset;
+ struct i830_sdvo_dtd output_dtd;
+ CARD16 no_outputs;
+
+ no_outputs = 0;
+
+ if (!mode)
+ return;
+ width = mode->CrtcHDisplay;
+ height = mode->CrtcVDisplay;
+
+ /* do some mode translations */
+ h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
+ h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
+
+ v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart;
+ v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
+
+ h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
+ v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
+
+ output_dtd.part1.clock = mode->Clock / 10;
+ output_dtd.part1.h_active = width & 0xff;
+ output_dtd.part1.h_blank = h_blank_len & 0xff;
+ output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
+ ((h_blank_len >> 8) & 0xf);
+ output_dtd.part1.v_active = height & 0xff;
+ output_dtd.part1.v_blank = v_blank_len & 0xff;
+ output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
+ ((v_blank_len >> 8) & 0xf);
+
+ output_dtd.part2.h_sync_off = h_sync_offset;
+ output_dtd.part2.h_sync_width = h_sync_len & 0xff;
+ output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+ (v_sync_len & 0xf);
+ output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
+ ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
+ ((v_sync_len & 0x30) >> 4);
+
+ output_dtd.part2.dtd_flags = 0x18;
+ if (mode->Flags & V_PHSYNC)
+ output_dtd.part2.dtd_flags |= 0x2;
+ if (mode->Flags & V_PVSYNC)
+ output_dtd.part2.dtd_flags |= 0x4;
+
+ output_dtd.part2.sdvo_flags = 0;
+ output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
+ output_dtd.part2.reserved = 0;
+
+ /* Set the output timing to the screen */
+ i830_sdvo_set_target_output(output, dev_priv->active_outputs);
+ i830_sdvo_set_output_timing(output, &output_dtd);
+
+ /* Set the input timing to the screen. Assume always input 0. */
+ i830_sdvo_set_target_input(output, TRUE, FALSE);
+
+ /* We would like to use i830_sdvo_create_preferred_input_timing() to
+ * provide the device with a timing it can support, if it supports that
+ * feature. However, presumably we would need to adjust the CRTC to output
+ * the preferred timing, and we don't support that currently.
+ */
+#if 0
+ success = i830_sdvo_create_preferred_input_timing(output, clock,
+ width, height);
+ if (success) {
+ struct i830_sdvo_dtd *input_dtd;
+
+ i830_sdvo_get_preferred_input_timing(output, &input_dtd);
+ i830_sdvo_set_input_timing(output, &input_dtd);
+ }
+#else
+ i830_sdvo_set_input_timing(output, &output_dtd);
+#endif
+
+ switch (i830_sdvo_get_pixel_multiplier(mode)) {
+ case 1:
+ i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_1X);
+ break;
+ case 2:
+ i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_2X);
+ break;
+ case 4:
+ i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_4X);
+ break;
+ }
+
+ /* Set the SDVO control regs. */
+ if (IS_I965GM(pI830)) {
+ sdvox = SDVO_BORDER_ENABLE;
+ } else {
+ sdvox = INREG(dev_priv->output_device);
+ switch (dev_priv->output_device) {
+ case SDVOB:
+ sdvox &= SDVOB_PRESERVE_MASK;
+ break;
+ case SDVOC:
+ sdvox &= SDVOC_PRESERVE_MASK;
+ break;
+ }
+ sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
+ }
+ if (intel_crtc->pipe == 1)
+ sdvox |= SDVO_PIPE_B_SELECT;
+
+ sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
+ if (IS_I965G(pI830)) {
+ /* done in crtc_mode_set as the dpll_md reg must be written early */
+ } else if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) {
+ /* done in crtc_mode_set as it lives inside the dpll register */
+ } else {
+ sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+ }
+
+ i830_sdvo_write_sdvox(output, sdvox);
+}
+
+static void
+i830_sdvo_dpms(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 temp;
+
+ if (mode != DPMSModeOn) {
+ i830_sdvo_set_active_outputs(output, 0);
+ if (0)
+ i830_sdvo_set_encoder_power_state(output, mode);
+
+ if (mode == DPMSModeOff) {
+ temp = INREG(dev_priv->output_device);
+ if ((temp & SDVO_ENABLE) != 0) {
+ i830_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
+ }
+ }
+ } else {
+ Bool input1, input2;
+ int i;
+ CARD8 status;
+
+ temp = INREG(dev_priv->output_device);
+ if ((temp & SDVO_ENABLE) == 0)
+ i830_sdvo_write_sdvox(output, temp | SDVO_ENABLE);
+ for (i = 0; i < 2; i++)
+ i830WaitForVblank(pScrn);
+
+ status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
+
+ /* Warn if the device reported failure to sync. */
+ if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "First %s output reported failure to sync\n",
+ SDVO_NAME(dev_priv));
+ }
+
+ if (0)
+ i830_sdvo_set_encoder_power_state(output, mode);
+ i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
+ }
+}
+
+static void
+i830_sdvo_save(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ I830Ptr pI830 = I830PTR(pScrn);
+ int o;
+
+ /* XXX: We should save the in/out mapping. */
+
+ dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output);
+ i830_sdvo_get_active_outputs(output, &dev_priv->save_active_outputs);
+
+ if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
+ i830_sdvo_set_target_input(output, TRUE, FALSE);
+ i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1);
+ }
+
+ if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
+ i830_sdvo_set_target_input(output, FALSE, TRUE);
+ i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2);
+ }
+
+ for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+ {
+ CARD16 this_output = (1 << o);
+ if (dev_priv->caps.output_flags & this_output)
+ {
+ i830_sdvo_set_target_output(output, this_output);
+ i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd[o]);
+ }
+ }
+
+ dev_priv->save_SDVOX = INREG(dev_priv->output_device);
+}
+
+static void
+i830_sdvo_restore(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ int o;
+ int i;
+ Bool input1, input2;
+ CARD8 status;
+
+ i830_sdvo_set_active_outputs(output, 0);
+
+ for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+ {
+ CARD16 this_output = (1 << o);
+ if (dev_priv->caps.output_flags & this_output)
+ {
+ i830_sdvo_set_target_output(output, this_output);
+ i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]);
+ }
+ }
+
+ if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
+ i830_sdvo_set_target_input(output, TRUE, FALSE);
+ i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1);
+ }
+
+ if (dev_priv->caps.sdvo_inputs_mask & 0x2) {
+ i830_sdvo_set_target_input(output, FALSE, TRUE);
+ i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
+ }
+
+ i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
+
+ i830_sdvo_write_sdvox(output, dev_priv->save_SDVOX);
+
+ if (dev_priv->save_SDVOX & SDVO_ENABLE)
+ {
+ for (i = 0; i < 2; i++)
+ i830WaitForVblank(pScrn);
+ status = i830_sdvo_get_trained_inputs(output, &input1, &input2);
+ if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "First %s output reported failure to sync\n",
+ SDVO_NAME(dev_priv));
+ }
+
+ i830_sdvo_set_active_outputs(output, dev_priv->save_active_outputs);
+}
+
+static int
+i830_sdvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ if (pMode->Flags & V_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ if (dev_priv->pixel_clock_min > pMode->Clock)
+ return MODE_CLOCK_HIGH;
+
+ if (dev_priv->pixel_clock_max < pMode->Clock)
+ return MODE_CLOCK_LOW;
+
+ return MODE_OK;
+}
+
+static Bool
+i830_sdvo_get_capabilities(xf86OutputPtr output, struct i830_sdvo_caps *caps)
+{
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
+ status = i830_sdvo_read_response(output, caps, sizeof(*caps));
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+/** Forces the device over to the real I2C bus and uses its GetByte */
+static Bool
+i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
+{
+ xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
+ Bool ret;
+
+ savebus = d->pI2CBus;
+ d->pI2CBus = i2cbus;
+ ret = i2cbus->I2CGetByte(d, data, last);
+ d->pI2CBus = savebus;
+
+ return ret;
+}
+
+/** Forces the device over to the real I2C bus and uses its PutByte */
+static Bool
+i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
+{
+ xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
+ Bool ret;
+
+ savebus = d->pI2CBus;
+ d->pI2CBus = i2cbus;
+ ret = i2cbus->I2CPutByte(d, c);
+ d->pI2CBus = savebus;
+
+ return ret;
+}
+
+/**
+ * Sets the control bus over to DDC before sending the start on the real I2C
+ * bus.
+ *
+ * The control bus will flip back at the stop following the start executed
+ * here.
+ */
+static Bool
+i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
+{
+ xf86OutputPtr output = b->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I2CBusPtr i2cbus = intel_output->pI2CBus;
+
+ i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
+ return i2cbus->I2CStart(i2cbus, timeout);
+}
+
+/** Forces the device over to the real SDVO bus and sends a stop to it. */
+static void
+i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
+{
+ xf86OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
+
+ savebus = d->pI2CBus;
+ d->pI2CBus = i2cbus;
+ i2cbus->I2CStop(d);
+ d->pI2CBus = savebus;
+}
+
+/**
+ * Mirrors xf86i2c I2CAddress, using the bus's (wrapped) methods rather than
+ * the default methods.
+ *
+ * This ensures that our start commands always get wrapped with control bus
+ * switches. xf86i2c should probably be fixed to do this.
+ */
+static Bool
+i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr)
+{
+ if (d->pI2CBus->I2CStart(d->pI2CBus, d->StartTimeout)) {
+ if (d->pI2CBus->I2CPutByte(d, addr & 0xFF)) {
+ if ((addr & 0xF8) != 0xF0 &&
+ (addr & 0xFE) != 0x00)
+ return TRUE;
+
+ if (d->pI2CBus->I2CPutByte(d, (addr >> 8) & 0xFF))
+ return TRUE;
+ }
+
+ d->pI2CBus->I2CStop(d);
+ }
+
+ return FALSE;
+}
+
+static void
+i830_sdvo_dump_cmd(xf86OutputPtr output, int opcode)
+{
+ CARD8 response[8];
+
+ i830_sdvo_write_cmd(output, opcode, NULL, 0);
+ i830_sdvo_read_response(output, response, 8);
+}
+
+static void
+i830_sdvo_dump_device(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ ErrorF("Dump %s\n", dev_priv->d.DevName);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_FIRMWARE_REV);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_IN_OUT_MAP);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_TIMINGS_PART2);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART2);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_TV_FORMATS);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TV_FORMAT);
+}
+
+void
+i830_sdvo_dump(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ I830OutputPrivatePtr intel_output = output->driver_private;
+
+ if (intel_output->type == I830_OUTPUT_SDVO)
+ i830_sdvo_dump_device(output);
+ }
+}
+
+/**
+ * Asks the SDVO device if any displays are currently connected.
+ *
+ * This interface will need to be augmented, since we could potentially have
+ * multiple displays connected, and the caller will also probably want to know
+ * what type of display is connected. But this is enough for the moment.
+ *
+ * Takes 14ms on average on my i945G.
+ */
+static xf86OutputStatus
+i830_sdvo_detect(xf86OutputPtr output)
+{
+ CARD8 response[2];
+ CARD8 status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+ status = i830_sdvo_read_response(output, &response, 2);
+
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return XF86OutputStatusUnknown;
+
+ if (response[0] != 0 || response[1] != 0)
+ return XF86OutputStatusConnected;
+ else
+ return XF86OutputStatusDisconnected;
+}
+
+static DisplayModePtr
+i830_sdvo_get_modes(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ DisplayModePtr modes;
+ xf86OutputPtr crt;
+
+ modes = i830_ddc_get_modes(output);
+ if (modes != NULL)
+ return modes;
+
+ /* Mac mini hack. On this device, I get DDC through the analog, which
+ * load-detects as disconnected. I fail to DDC through the SDVO DDC,
+ * but it does load-detect as connected. So, just steal the DDC bits from
+ * analog when we fail at finding it the right way.
+ */
+ crt = xf86_config->output[0];
+ if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
+ return crt->funcs->get_modes(crt);
+ }
+
+ return NULL;
+}
+
+static void
+i830_sdvo_destroy (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+
+ if (intel_output)
+ {
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ xf86DestroyI2CBusRec (intel_output->pDDCBus, FALSE, FALSE);
+ xf86DestroyI2CDevRec (&dev_priv->d, FALSE);
+ xf86DestroyI2CBusRec (dev_priv->d.pI2CBus, TRUE, TRUE);
+ xfree (intel_output);
+ }
+}
+
+static const xf86OutputFuncsRec i830_sdvo_output_funcs = {
+ .dpms = i830_sdvo_dpms,
+ .save = i830_sdvo_save,
+ .restore = i830_sdvo_restore,
+ .mode_valid = i830_sdvo_mode_valid,
+ .mode_fixup = i830_sdvo_mode_fixup,
+ .prepare = i830_output_prepare,
+ .mode_set = i830_sdvo_mode_set,
+ .commit = i830_output_commit,
+ .detect = i830_sdvo_detect,
+ .get_modes = i830_sdvo_get_modes,
+ .destroy = i830_sdvo_destroy
+};
+
+void
+i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
+{
+ xf86OutputPtr output;
+ I830OutputPrivatePtr intel_output;
+ struct i830_sdvo_priv *dev_priv;
+ int i;
+ unsigned char ch[0x40];
+ I2CBusPtr i2cbus = NULL, ddcbus;
+ char name[60];
+ char *name_prefix;
+ char *name_suffix;
+
+ output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
+ if (!output)
+ return;
+ intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+ sizeof (struct i830_sdvo_priv), 1);
+ if (!intel_output)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+ output->driver_private = intel_output;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+
+ dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
+ intel_output->type = I830_OUTPUT_SDVO;
+ intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+ intel_output->clone_mask = (1 << I830_OUTPUT_SDVO);
+
+ /* While it's the same bus, we just initialize a new copy to avoid trouble
+ * with tracking refcounting ourselves, since the XFree86 DDX bits don't.
+ */
+ if (output_device == SDVOB)
+ I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOB");
+ else
+ I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
+
+ if (i2cbus == NULL)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+
+ if (output_device == SDVOB) {
+ dev_priv->d.DevName = "SDVO Controller B";
+ dev_priv->d.SlaveAddr = 0x70;
+ name_suffix="-1";
+ } else {
+ dev_priv->d.DevName = "SDVO Controller C";
+ dev_priv->d.SlaveAddr = 0x72;
+ name_suffix="-2";
+ }
+ dev_priv->d.pI2CBus = i2cbus;
+ dev_priv->d.DriverPrivate.ptr = output;
+ dev_priv->output_device = output_device;
+
+ if (!xf86I2CDevInit(&dev_priv->d))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize %s I2C device\n",
+ SDVO_NAME(dev_priv));
+ xf86OutputDestroy (output);
+ return;
+ }
+
+ intel_output->pI2CBus = i2cbus;
+ intel_output->dev_priv = dev_priv;
+
+ /* Read the regs to test if we can talk to the device */
+ for (i = 0; i < 0x40; i++) {
+ if (!i830_sdvo_read_byte_quiet(output, i, &ch[i])) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No SDVO device found on SDVO%c\n",
+ output_device == SDVOB ? 'B' : 'C');
+ xf86OutputDestroy (output);
+ return;
+ }
+ }
+
+ /* Set up our wrapper I2C bus for DDC. It acts just like the regular I2C
+ * bus, except that it does the control bus switch to DDC mode before every
+ * Start. While we only need to do it at Start after every Stop after a
+ * Start, extra attempts should be harmless.
+ */
+ ddcbus = xf86CreateI2CBusRec();
+ if (ddcbus == NULL)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+ if (output_device == SDVOB)
+ ddcbus->BusName = "SDVOB DDC Bus";
+ else
+ ddcbus->BusName = "SDVOC DDC Bus";
+ ddcbus->scrnIndex = i2cbus->scrnIndex;
+ ddcbus->I2CGetByte = i830_sdvo_ddc_i2c_get_byte;
+ ddcbus->I2CPutByte = i830_sdvo_ddc_i2c_put_byte;
+ ddcbus->I2CStart = i830_sdvo_ddc_i2c_start;
+ ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop;
+ ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address;
+ ddcbus->DriverPrivate.ptr = output;
+
+ if (!xf86I2CBusInit(ddcbus))
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+
+ intel_output->pI2CBus = i2cbus;
+ intel_output->pDDCBus = ddcbus;
+ intel_output->dev_priv = dev_priv;
+
+ i830_sdvo_get_capabilities(output, &dev_priv->caps);
+
+ memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
+ if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+ {
+ dev_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="TMDS";
+ }
+ else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+ {
+ dev_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="TMDS";
+ }
+ else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
+ {
+ dev_priv->active_outputs = SDVO_OUTPUT_RGB0;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="VGA";
+ }
+ else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
+ {
+ dev_priv->active_outputs = SDVO_OUTPUT_RGB1;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="VGA";
+ }
+ else
+ {
+ unsigned char bytes[2];
+
+ memcpy (bytes, &dev_priv->caps.output_flags, 2);
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
+ "%s: No active TMDS outputs (0x%02x%02x)\n",
+ SDVO_NAME(dev_priv),
+ bytes[0], bytes[1]);
+ name_prefix="Unknown";
+ }
+ strcpy (name, name_prefix);
+ strcat (name, name_suffix);
+ if (!xf86OutputRename (output, name))
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+
+
+ /* Set the input timing to the screen. Assume always input 0. */
+ i830_sdvo_set_target_input(output, TRUE, FALSE);
+
+ i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
+ &dev_priv->pixel_clock_max);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%s device VID/DID: %02X:%02X.%02X, "
+ "clock range %.1fMHz - %.1fMHz, "
+ "input 1: %c, input 2: %c, "
+ "output 1: %c, output 2: %c\n",
+ SDVO_NAME(dev_priv),
+ dev_priv->caps.vendor_id, dev_priv->caps.device_id,
+ dev_priv->caps.device_rev_id,
+ dev_priv->pixel_clock_min / 1000.0,
+ dev_priv->pixel_clock_max / 1000.0,
+ (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+ (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+ dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_TMDS0) ? 'Y' : 'N',
+ dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB1 | SDVO_OUTPUT_TMDS1) ? 'Y' : 'N');
+}
diff --git a/driver/xf86-video-intel/src/i830_sdvo.h b/driver/xf86-video-intel/src/i830_sdvo.h
new file mode 100644
index 000000000..1368e43b3
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_sdvo.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+void
+i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
+
+int
+i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode);
+
+void
+i830_sdvo_dump(ScrnInfoPtr pScrn);
diff --git a/driver/xf86-video-intel/src/i830_sdvo_regs.h b/driver/xf86-video-intel/src/i830_sdvo_regs.h
new file mode 100644
index 000000000..72e58a00c
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_sdvo_regs.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * @file SDVO command definitions and structures.
+ */
+
+#define SDVO_OUTPUT_FIRST (0)
+#define SDVO_OUTPUT_TMDS0 (1 << 0)
+#define SDVO_OUTPUT_RGB0 (1 << 1)
+#define SDVO_OUTPUT_CVBS0 (1 << 2)
+#define SDVO_OUTPUT_SVID0 (1 << 3)
+#define SDVO_OUTPUT_YPRPB0 (1 << 4)
+#define SDVO_OUTPUT_SCART0 (1 << 5)
+#define SDVO_OUTPUT_LVDS0 (1 << 6)
+#define SDVO_OUTPUT_TMDS1 (1 << 8)
+#define SDVO_OUTPUT_RGB1 (1 << 9)
+#define SDVO_OUTPUT_CVBS1 (1 << 10)
+#define SDVO_OUTPUT_SVID1 (1 << 11)
+#define SDVO_OUTPUT_YPRPB1 (1 << 12)
+#define SDVO_OUTPUT_SCART1 (1 << 13)
+#define SDVO_OUTPUT_LVDS1 (1 << 14)
+#define SDVO_OUTPUT_LAST (14)
+
+struct i830_sdvo_caps {
+ CARD8 vendor_id;
+ CARD8 device_id;
+ CARD8 device_rev_id;
+ CARD8 sdvo_version_major;
+ CARD8 sdvo_version_minor;
+ unsigned int sdvo_inputs_mask:2;
+ unsigned int smooth_scaling:1;
+ unsigned int sharp_scaling:1;
+ unsigned int up_scaling:1;
+ unsigned int down_scaling:1;
+ unsigned int stall_support:1;
+ unsigned int pad:1;
+ CARD16 output_flags;
+} __attribute__((packed));
+
+/** This matches the EDID DTD structure, more or less */
+struct i830_sdvo_dtd {
+ struct {
+ CARD16 clock; /**< pixel clock, in 10kHz units */
+ CARD8 h_active; /**< lower 8 bits (pixels) */
+ CARD8 h_blank; /**< lower 8 bits (pixels) */
+ CARD8 h_high; /**< upper 4 bits each h_active, h_blank */
+ CARD8 v_active; /**< lower 8 bits (lines) */
+ CARD8 v_blank; /**< lower 8 bits (lines) */
+ CARD8 v_high; /**< upper 4 bits each v_active, v_blank */
+ } part1;
+
+ struct {
+ CARD8 h_sync_off; /**< lower 8 bits, from hblank start */
+ CARD8 h_sync_width; /**< lower 8 bits (pixels) */
+ /** lower 4 bits each vsync offset, vsync width */
+ CARD8 v_sync_off_width;
+ /**
+ * 2 high bits of hsync offset, 2 high bits of hsync width,
+ * bits 4-5 of vsync offset, and 2 high bits of vsync width.
+ */
+ CARD8 sync_off_width_high;
+ CARD8 dtd_flags;
+ CARD8 sdvo_flags;
+ /** bits 6-7 of vsync offset at bits 6-7 */
+ CARD8 v_sync_off_high;
+ CARD8 reserved;
+ } part2;
+} __attribute__((packed));
+
+struct i830_sdvo_pixel_clock_range {
+ CARD16 min; /**< pixel clock, in 10kHz units */
+ CARD16 max; /**< pixel clock, in 10kHz units */
+} __attribute__((packed));
+
+struct i830_sdvo_preferred_input_timing_args {
+ CARD16 clock;
+ CARD16 width;
+ CARD16 height;
+} __attribute__((packed));
+
+/* I2C registers for SDVO */
+#define SDVO_I2C_ARG_0 0x07
+#define SDVO_I2C_ARG_1 0x06
+#define SDVO_I2C_ARG_2 0x05
+#define SDVO_I2C_ARG_3 0x04
+#define SDVO_I2C_ARG_4 0x03
+#define SDVO_I2C_ARG_5 0x02
+#define SDVO_I2C_ARG_6 0x01
+#define SDVO_I2C_ARG_7 0x00
+#define SDVO_I2C_OPCODE 0x08
+#define SDVO_I2C_CMD_STATUS 0x09
+#define SDVO_I2C_RETURN_0 0x0a
+#define SDVO_I2C_RETURN_1 0x0b
+#define SDVO_I2C_RETURN_2 0x0c
+#define SDVO_I2C_RETURN_3 0x0d
+#define SDVO_I2C_RETURN_4 0x0e
+#define SDVO_I2C_RETURN_5 0x0f
+#define SDVO_I2C_RETURN_6 0x10
+#define SDVO_I2C_RETURN_7 0x11
+#define SDVO_I2C_VENDOR_BEGIN 0x20
+
+/* Status results */
+#define SDVO_CMD_STATUS_POWER_ON 0x0
+#define SDVO_CMD_STATUS_SUCCESS 0x1
+#define SDVO_CMD_STATUS_NOTSUPP 0x2
+#define SDVO_CMD_STATUS_INVALID_ARG 0x3
+#define SDVO_CMD_STATUS_PENDING 0x4
+#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5
+#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
+
+/* SDVO commands, argument/result registers */
+
+#define SDVO_CMD_RESET 0x01
+
+/** Returns a struct i830_sdvo_caps */
+#define SDVO_CMD_GET_DEVICE_CAPS 0x02
+
+#define SDVO_CMD_GET_FIRMWARE_REV 0x86
+# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2
+
+/**
+ * Reports which inputs are trained (managed to sync).
+ *
+ * Devices must have trained within 2 vsyncs of a mode change.
+ */
+#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
+struct i830_sdvo_get_trained_inputs_response {
+ unsigned int input0_trained:1;
+ unsigned int input1_trained:1;
+ unsigned int pad:6;
+} __attribute__((packed));
+
+/** Returns a struct i830_sdvo_output_flags of active outputs. */
+#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
+
+/**
+ * Sets the current set of active outputs.
+ *
+ * Takes a struct i830_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP
+ * on multi-output devices.
+ */
+#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
+
+/**
+ * Returns the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Returns two struct i830_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_GET_IN_OUT_MAP 0x06
+
+/**
+ * Sets the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Takes two struct i380_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_SET_IN_OUT_MAP 0x07
+
+/**
+ * Returns a struct i830_sdvo_output_flags of attached displays.
+ */
+#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
+
+/**
+ * Returns a struct i830_sdvo_ouptut_flags of displays supporting hot plugging.
+ */
+#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
+
+/**
+ * Takes a struct i830_sdvo_output_flags.
+ */
+#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
+
+/**
+ * Returns a struct i830_sdvo_output_flags of displays with hot plug
+ * interrupts enabled.
+ */
+#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
+
+#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
+struct i830_sdvo_get_interrupt_event_source_response {
+ CARD16 interrupt_status;
+ unsigned int ambient_light_interrupt:1;
+ unsigned int pad:7;
+} __attribute__((packed));
+
+/**
+ * Selects which input is affected by future input commands.
+ *
+ * Commands affected include SET_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
+ */
+#define SDVO_CMD_SET_TARGET_INPUT 0x10
+struct i830_sdvo_set_target_input_args {
+ unsigned int target_1:1;
+ unsigned int pad:7;
+} __attribute__((packed));
+
+/**
+ * Takes a struct i830_sdvo_output_flags of which outputs are targetted by
+ * future output commands.
+ *
+ * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
+ * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
+ */
+#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
+
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
+/* Part 1 */
+# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
+# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
+# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
+# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
+# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
+# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
+# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
+# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
+/* Part 2 */
+# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
+# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
+# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
+# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
+# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
+# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
+# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
+# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
+# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
+# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
+# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
+# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6)
+# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6)
+# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4)
+# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
+
+/**
+ * Generates a DTD based on the given width, height, and flags.
+ *
+ * This will be supported by any device supporting scaling or interlaced
+ * modes.
+ */
+#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
+
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
+
+/** Returns a struct i830_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
+/** Returns a struct i830_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
+
+/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
+#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
+
+/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
+/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
+# define SDVO_CLOCK_RATE_MULT_1X (1 << 0)
+# define SDVO_CLOCK_RATE_MULT_2X (1 << 1)
+# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
+
+#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
+
+#define SDVO_CMD_GET_TV_FORMAT 0x28
+
+#define SDVO_CMD_SET_TV_FORMAT 0x29
+
+#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a
+#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b
+#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c
+# define SDVO_ENCODER_STATE_ON (1 << 0)
+# define SDVO_ENCODER_STATE_STANDBY (1 << 1)
+# define SDVO_ENCODER_STATE_SUSPEND (1 << 2)
+# define SDVO_ENCODER_STATE_OFF (1 << 3)
+
+#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
+
+#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
+# define SDVO_CONTROL_BUS_PROM 0x0
+# define SDVO_CONTROL_BUS_DDC1 0x1
+# define SDVO_CONTROL_BUS_DDC2 0x2
+# define SDVO_CONTROL_BUS_DDC3 0x3
+
diff --git a/driver/xf86-video-intel/src/i830_tv.c b/driver/xf86-video-intel/src/i830_tv.c
new file mode 100644
index 000000000..524a0d3b3
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_tv.c
@@ -0,0 +1,1740 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file
+ * Integrated TV-out support for the 915GM and 945GM.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_display.h"
+#include "X11/Xatom.h"
+#include <string.h>
+
+enum tv_type {
+ TV_TYPE_NONE,
+ TV_TYPE_UNKNOWN,
+ TV_TYPE_COMPOSITE,
+ TV_TYPE_SVIDEO,
+ TV_TYPE_COMPONENT
+};
+
+enum tv_margin {
+ TV_MARGIN_LEFT, TV_MARGIN_TOP,
+ TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
+};
+
+/** Private structure for the integrated TV support */
+struct i830_tv_priv {
+ int type;
+ char *tv_format;
+ int margin[4];
+ CARD32 save_TV_H_CTL_1;
+ CARD32 save_TV_H_CTL_2;
+ CARD32 save_TV_H_CTL_3;
+ CARD32 save_TV_V_CTL_1;
+ CARD32 save_TV_V_CTL_2;
+ CARD32 save_TV_V_CTL_3;
+ CARD32 save_TV_V_CTL_4;
+ CARD32 save_TV_V_CTL_5;
+ CARD32 save_TV_V_CTL_6;
+ CARD32 save_TV_V_CTL_7;
+ CARD32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
+
+ CARD32 save_TV_CSC_Y;
+ CARD32 save_TV_CSC_Y2;
+ CARD32 save_TV_CSC_U;
+ CARD32 save_TV_CSC_U2;
+ CARD32 save_TV_CSC_V;
+ CARD32 save_TV_CSC_V2;
+ CARD32 save_TV_CLR_KNOBS;
+ CARD32 save_TV_CLR_LEVEL;
+ CARD32 save_TV_WIN_POS;
+ CARD32 save_TV_WIN_SIZE;
+ CARD32 save_TV_FILTER_CTL_1;
+ CARD32 save_TV_FILTER_CTL_2;
+ CARD32 save_TV_FILTER_CTL_3;
+
+ CARD32 save_TV_H_LUMA[60];
+ CARD32 save_TV_H_CHROMA[60];
+ CARD32 save_TV_V_LUMA[43];
+ CARD32 save_TV_V_CHROMA[43];
+
+ CARD32 save_TV_DAC;
+ CARD32 save_TV_CTL;
+};
+
+typedef struct {
+ int blank, black, burst;
+} video_levels_t;
+
+typedef struct {
+ float ry, gy, by, ay;
+ float ru, gu, bu, au;
+ float rv, gv, bv, av;
+} color_conversion_t;
+
+static const CARD32 filter_table[] = {
+ 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+ 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+ 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+ 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+ 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+ 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+ 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+ 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+ 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+ 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+ 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+ 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+ 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+ 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+ 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+ 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
+ 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
+ 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
+ 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
+ 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
+ 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
+ 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
+ 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
+ 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
+ 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
+ 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
+ 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
+ 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
+ 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
+ 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
+ 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
+ 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+ 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+ 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+ 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+ 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+ 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+ 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+ 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+ 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+ 0x28003100, 0x28002F00, 0x00003100, 0x36403000,
+ 0x2D002CC0, 0x30003640, 0x2D0036C0,
+ 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
+ 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
+ 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
+ 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
+ 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
+ 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
+ 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
+ 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
+ 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
+ 0x28003100, 0x28002F00, 0x00003100,
+};
+
+typedef struct {
+ char *name;
+ int clock;
+ double refresh;
+ CARD32 oversample;
+ int hsync_end, hblank_start, hblank_end, htotal;
+ Bool progressive, trilevel_sync, component_only;
+ int vsync_start_f1, vsync_start_f2, vsync_len;
+ Bool veq_ena;
+ int veq_start_f1, veq_start_f2, veq_len;
+ int vi_end_f1, vi_end_f2, nbr_end;
+ Bool burst_ena;
+ int hburst_start, hburst_len;
+ int vburst_start_f1, vburst_end_f1;
+ int vburst_start_f2, vburst_end_f2;
+ int vburst_start_f3, vburst_end_f3;
+ int vburst_start_f4, vburst_end_f4;
+ /*
+ * subcarrier programming
+ */
+ int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
+ CARD32 sc_reset;
+ Bool pal_burst;
+ /*
+ * blank/black levels
+ */
+ video_levels_t composite_levels, svideo_levels;
+ color_conversion_t composite_color, svideo_color;
+ const CARD32 *filter_table;
+ int max_srcw;
+} tv_mode_t;
+
+
+/*
+ * Sub carrier DDA
+ *
+ * I think this works as follows:
+ *
+ * subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
+ *
+ * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
+ *
+ * So,
+ * dda1_ideal = subcarrier/pixel * 4096
+ * dda1_inc = floor (dda1_ideal)
+ * dda2 = dda1_ideal - dda1_inc
+ *
+ * then pick a ratio for dda2 that gives the closest approximation. If
+ * you can't get close enough, you can play with dda3 as well. This
+ * seems likely to happen when dda2 is small as the jumps would be larger
+ *
+ * To invert this,
+ *
+ * pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
+ *
+ * The constants below were all computed using a 107.520MHz clock
+ */
+
+/**
+ * Register programming values for TV modes.
+ *
+ * These values account for -1s required.
+ */
+
+const static tv_mode_t tv_modes[] = {
+ {
+ .name = "NTSC-M",
+ .clock = 107520,
+ .refresh = 29.97,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+ /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+
+ .hsync_end = 64, .hblank_end = 124,
+ .hblank_start = 836, .htotal = 857,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 6, .vsync_start_f2 = 7,
+ .vsync_len = 6,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 18,
+
+ .vi_end_f1 = 20, .vi_end_f2 = 21,
+ .nbr_end = 240,
+
+ .burst_ena = TRUE,
+ .hburst_start = 72, .hburst_len = 34,
+ .vburst_start_f1 = 9, .vburst_end_f1 = 240,
+ .vburst_start_f2 = 10, .vburst_end_f2 = 240,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 240,
+ .vburst_start_f4 = 10, .vburst_end_f4 = 240,
+
+ /* desired 3.5800000 actual 3.5800000 clock 107.52 */
+ .dda1_inc = 136,
+ .dda2_inc = 7624, .dda2_size = 20013,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_4,
+ .pal_burst = FALSE,
+
+ .composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+ .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+ .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 266, .black = 316, .burst = 133 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+ .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+ .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ .name = "NTSC-443",
+ .clock = 107520,
+ .refresh = 29.97,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+ /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
+ .hsync_end = 64, .hblank_end = 124,
+ .hblank_start = 836, .htotal = 857,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 6, .vsync_start_f2 = 7,
+ .vsync_len = 6,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 18,
+
+ .vi_end_f1 = 20, .vi_end_f2 = 21,
+ .nbr_end = 240,
+
+ .burst_ena = 8,
+ .hburst_start = 72, .hburst_len = 34,
+ .vburst_start_f1 = 9, .vburst_end_f1 = 240,
+ .vburst_start_f2 = 10, .vburst_end_f2 = 240,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 240,
+ .vburst_start_f4 = 10, .vburst_end_f4 = 240,
+
+ /* desired 4.4336180 actual 4.4336180 clock 107.52 */
+ .dda1_inc = 168,
+ .dda2_inc = 18557, .dda2_size = 20625,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_8,
+ .pal_burst = TRUE,
+
+ .composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+ .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+ .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 266, .black = 316, .burst = 133 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+ .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+ .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ .name = "NTSC-J",
+ .clock = 107520,
+ .refresh = 29.97,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+
+ /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+ .hsync_end = 64, .hblank_end = 124,
+ .hblank_start = 836, .htotal = 857,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 6, .vsync_start_f2 = 7,
+ .vsync_len = 6,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 18,
+
+ .vi_end_f1 = 20, .vi_end_f2 = 21,
+ .nbr_end = 240,
+
+ .burst_ena = TRUE,
+ .hburst_start = 72, .hburst_len = 34,
+ .vburst_start_f1 = 9, .vburst_end_f1 = 240,
+ .vburst_start_f2 = 10, .vburst_end_f2 = 240,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 240,
+ .vburst_start_f4 = 10, .vburst_end_f4 = 240,
+
+ /* desired 3.5800000 actual 3.5800000 clock 107.52 */
+ .dda1_inc = 136,
+ .dda2_inc = 7624, .dda2_size = 20013,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_4,
+ .pal_burst = FALSE,
+
+ .composite_levels = { .blank = 225, .black = 225, .burst = 113 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5495,
+ .ru =-0.0810, .gu =-0.1590, .bu = 0.2400, .au = 1.0000,
+ .rv = 0.3378, .gv =-0.2829, .bv =-0.0549, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 266, .black = 266, .burst = 133 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6494,
+ .ru =-0.0957, .gu =-0.1879, .bu = 0.2836, .au = 1.0000,
+ .rv = 0.3992, .gv =-0.3343, .bv =-0.0649, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ .name = "PAL-M",
+ .clock = 107520,
+ .refresh = 29.97,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+
+ /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
+ .hsync_end = 64, .hblank_end = 124,
+ .hblank_start = 836, .htotal = 857,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 6, .vsync_start_f2 = 7,
+ .vsync_len = 6,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 18,
+
+ .vi_end_f1 = 20, .vi_end_f2 = 21,
+ .nbr_end = 240,
+
+ .burst_ena = TRUE,
+ .hburst_start = 72, .hburst_len = 34,
+ .vburst_start_f1 = 9, .vburst_end_f1 = 240,
+ .vburst_start_f2 = 10, .vburst_end_f2 = 240,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 240,
+ .vburst_start_f4 = 10, .vburst_end_f4 = 240,
+
+ /* desired 3.5800000 actual 3.5800000 clock 107.52 */
+ .dda1_inc = 136,
+ .dda2_inc = 7624, .dda2_size = 20013,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_4,
+ .pal_burst = FALSE,
+
+ .composite_levels = { .blank = 225, .black = 267, .burst = 113 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+ .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+ .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 266, .black = 316, .burst = 133 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+ .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+ .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+ .name = "PAL-N",
+ .clock = 107520,
+ .refresh = 25.0,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+
+ .hsync_end = 64, .hblank_end = 128,
+ .hblank_start = 844, .htotal = 863,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+
+ .vsync_start_f1 = 6, .vsync_start_f2 = 7,
+ .vsync_len = 6,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 18,
+
+ .vi_end_f1 = 24, .vi_end_f2 = 25,
+ .nbr_end = 286,
+
+ .burst_ena = TRUE,
+ .hburst_start = 73, .hburst_len = 34,
+ .vburst_start_f1 = 8, .vburst_end_f1 = 285,
+ .vburst_start_f2 = 8, .vburst_end_f2 = 286,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 286,
+ .vburst_start_f4 = 9, .vburst_end_f4 = 285,
+
+
+ /* desired 4.4336180 actual 4.4336180 clock 107.52 */
+ .dda1_inc = 168,
+ .dda2_inc = 18557, .dda2_size = 20625,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_8,
+ .pal_burst = TRUE,
+
+ .composite_levels = { .blank = 225, .black = 267, .burst = 118 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5082,
+ .ru =-0.0749, .gu =-0.1471, .bu = 0.2220, .au = 1.0000,
+ .rv = 0.3125, .gv =-0.2616, .bv =-0.0508, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 266, .black = 316, .burst = 139 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6006,
+ .ru =-0.0885, .gu =-0.1738, .bu = 0.2624, .au = 1.0000,
+ .rv = 0.3693, .gv =-0.3092, .bv =-0.0601, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
+ .name = "PAL",
+ .clock = 107520,
+ .refresh = 25.0,
+ .oversample = TV_OVERSAMPLE_8X,
+ .component_only = 0,
+
+ .hsync_end = 64, .hblank_end = 128,
+ .hblank_start = 844, .htotal = 863,
+
+ .progressive = FALSE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 5, .vsync_start_f2 = 6,
+ .vsync_len = 5,
+
+ .veq_ena = TRUE, .veq_start_f1 = 0,
+ .veq_start_f2 = 1, .veq_len = 15,
+
+ .vi_end_f1 = 24, .vi_end_f2 = 25,
+ .nbr_end = 286,
+
+ .burst_ena = TRUE,
+ .hburst_start = 73, .hburst_len = 32,
+ .vburst_start_f1 = 8, .vburst_end_f1 = 285,
+ .vburst_start_f2 = 8, .vburst_end_f2 = 286,
+ .vburst_start_f3 = 9, .vburst_end_f3 = 286,
+ .vburst_start_f4 = 9, .vburst_end_f4 = 285,
+
+ /* desired 4.4336180 actual 4.4336180 clock 107.52 */
+ .dda1_inc = 168,
+ .dda2_inc = 18557, .dda2_size = 20625,
+ .dda3_inc = 0, .dda3_size = 0,
+ .sc_reset = TV_SC_RESET_EVERY_8,
+ .pal_burst = TRUE,
+
+ .composite_levels = { .blank = 237, .black = 237, .burst = 118 },
+ .composite_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.5379,
+ .ru =-0.0793, .gu =-0.1557, .bu = 0.2350, .au = 1.0000,
+ .rv = 0.3307, .gv =-0.2769, .bv =-0.0538, .av = 1.0000,
+ },
+
+ .svideo_levels = { .blank = 280, .black = 280, .burst = 139 },
+ .svideo_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6357,
+ .ru =-0.0937, .gu =-0.1840, .bu = 0.2777, .au = 1.0000,
+ .rv = 0.3908, .gv =-0.3273, .bv =-0.0636, .av = 1.0000,
+ },
+ .filter_table = filter_table,
+ },
+ {
+ .name = "480p@59.94Hz",
+ .clock = 107520,
+ .refresh = 59.94,
+ .oversample = TV_OVERSAMPLE_4X,
+ .component_only = 1,
+
+ .hsync_end = 64, .hblank_end = 122,
+ .hblank_start = 842, .htotal = 857,
+
+ .progressive = TRUE,.trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 12, .vsync_start_f2 = 12,
+ .vsync_len = 12,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 44, .vi_end_f2 = 44,
+ .nbr_end = 496,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "480p@60Hz",
+ .clock = 107520,
+ .refresh = 60.0,
+ .oversample = TV_OVERSAMPLE_4X,
+ .component_only = 1,
+
+ .hsync_end = 64, .hblank_end = 122,
+ .hblank_start = 842, .htotal = 856,
+
+ .progressive = TRUE,.trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 12, .vsync_start_f2 = 12,
+ .vsync_len = 12,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 44, .vi_end_f2 = 44,
+ .nbr_end = 496,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "576p",
+ .clock = 107520,
+ .refresh = 59.94,
+ .oversample = TV_OVERSAMPLE_4X,
+ .component_only = 1,
+
+ .hsync_end = 64, .hblank_end = 139,
+ .hblank_start = 859, .htotal = 863,
+
+ .progressive = TRUE, .trilevel_sync = FALSE,
+
+ .vsync_start_f1 = 10, .vsync_start_f2 = 10,
+ .vsync_len = 10,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 48, .vi_end_f2 = 48,
+ .nbr_end = 575,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "720p@60Hz",
+ .clock = 148800,
+ .refresh = 60.0,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 80, .hblank_end = 300,
+ .hblank_start = 1580, .htotal = 1649,
+
+ .progressive = TRUE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 10, .vsync_start_f2 = 10,
+ .vsync_len = 10,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 29, .vi_end_f2 = 29,
+ .nbr_end = 719,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "720p@59.94Hz",
+ .clock = 148800,
+ .refresh = 59.94,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 80, .hblank_end = 300,
+ .hblank_start = 1580, .htotal = 1651,
+
+ .progressive = TRUE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 10, .vsync_start_f2 = 10,
+ .vsync_len = 10,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 29, .vi_end_f2 = 29,
+ .nbr_end = 719,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "720p@50Hz",
+ .clock = 148800,
+ .refresh = 50.0,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 80, .hblank_end = 300,
+ .hblank_start = 1580, .htotal = 1979,
+
+ .progressive = TRUE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 10, .vsync_start_f2 = 10,
+ .vsync_len = 10,
+
+ .veq_ena = FALSE,
+
+ .vi_end_f1 = 29, .vi_end_f2 = 29,
+ .nbr_end = 719,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ .max_srcw = 800
+ },
+ {
+ .name = "1080i@50Hz",
+ .clock = 148800,
+ .refresh = 25.0,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 88, .hblank_end = 235,
+ .hblank_start = 2155, .htotal = 2639,
+
+ .progressive = FALSE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 4, .vsync_start_f2 = 5,
+ .vsync_len = 10,
+
+ .veq_ena = TRUE, .veq_start_f1 = 4,
+ .veq_start_f2 = 4, .veq_len = 10,
+
+
+ .vi_end_f1 = 21, .vi_end_f2 = 22,
+ .nbr_end = 539,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "1080i@60Hz",
+ .clock = 148800,
+ .refresh = 30.0,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 88, .hblank_end = 235,
+ .hblank_start = 2155, .htotal = 2199,
+
+ .progressive = FALSE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 4, .vsync_start_f2 = 5,
+ .vsync_len = 10,
+
+ .veq_ena = TRUE, .veq_start_f1 = 4,
+ .veq_start_f2 = 4, .veq_len = 10,
+
+
+ .vi_end_f1 = 21, .vi_end_f2 = 22,
+ .nbr_end = 539,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+ {
+ .name = "1080i@59.94Hz",
+ .clock = 148800,
+ .refresh = 29.97,
+ .oversample = TV_OVERSAMPLE_2X,
+ .component_only = 1,
+
+ .hsync_end = 88, .hblank_end = 235,
+ .hblank_start = 2155, .htotal = 2200,
+
+ .progressive = FALSE, .trilevel_sync = TRUE,
+
+ .vsync_start_f1 = 4, .vsync_start_f2 = 5,
+ .vsync_len = 10,
+
+ .veq_ena = TRUE, .veq_start_f1 = 4,
+ .veq_start_f2 = 4, .veq_len = 10,
+
+
+ .vi_end_f1 = 21, .vi_end_f2 = 22,
+ .nbr_end = 539,
+
+ .burst_ena = FALSE,
+
+ .filter_table = filter_table,
+ },
+};
+
+#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0])
+
+static const video_levels_t component_level = {
+ .blank = 279, .black = 279
+};
+
+static const color_conversion_t sdtv_component_color = {
+ .ry = 0.2990, .gy = 0.5870, .by = 0.1140, .ay = 0.6364,
+ .ru =-0.1687, .gu =-0.3313, .bu = 0.5000, .au = 1.0000,
+ .rv = 0.5000, .gv =-0.4187, .bv =-0.0813, .av = 1.0000,
+};
+
+static const color_conversion_t hdtv_component_color = {
+ .ry = 0.2126, .gy = 0.7152, .by = 0.0722, .ay = 0.6364,
+ .ru =-0.1146, .gu =-0.3854, .bu = 0.5000, .au = 1.0000,
+ .rv = 0.5000, .gv =-0.4542, .bv =-0.0458, .av = 1.0000,
+};
+
+static void
+i830_tv_dpms(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ switch(mode) {
+ case DPMSModeOn:
+ OUTREG(TV_CTL, INREG(TV_CTL) | TV_ENC_ENABLE);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE);
+ break;
+ }
+}
+
+static void
+i830_tv_save(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ int i;
+
+ dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1);
+ dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2);
+ dev_priv->save_TV_H_CTL_3 = INREG(TV_H_CTL_3);
+ dev_priv->save_TV_V_CTL_1 = INREG(TV_V_CTL_1);
+ dev_priv->save_TV_V_CTL_2 = INREG(TV_V_CTL_2);
+ dev_priv->save_TV_V_CTL_3 = INREG(TV_V_CTL_3);
+ dev_priv->save_TV_V_CTL_4 = INREG(TV_V_CTL_4);
+ dev_priv->save_TV_V_CTL_5 = INREG(TV_V_CTL_5);
+ dev_priv->save_TV_V_CTL_6 = INREG(TV_V_CTL_6);
+ dev_priv->save_TV_V_CTL_7 = INREG(TV_V_CTL_7);
+ dev_priv->save_TV_SC_CTL_1 = INREG(TV_SC_CTL_1);
+ dev_priv->save_TV_SC_CTL_2 = INREG(TV_SC_CTL_2);
+ dev_priv->save_TV_SC_CTL_3 = INREG(TV_SC_CTL_3);
+
+ dev_priv->save_TV_CSC_Y = INREG(TV_CSC_Y);
+ dev_priv->save_TV_CSC_Y2 = INREG(TV_CSC_Y2);
+ dev_priv->save_TV_CSC_U = INREG(TV_CSC_U);
+ dev_priv->save_TV_CSC_U2 = INREG(TV_CSC_U2);
+ dev_priv->save_TV_CSC_V = INREG(TV_CSC_V);
+ dev_priv->save_TV_CSC_V2 = INREG(TV_CSC_V2);
+ dev_priv->save_TV_CLR_KNOBS = INREG(TV_CLR_KNOBS);
+ dev_priv->save_TV_CLR_LEVEL = INREG(TV_CLR_LEVEL);
+ dev_priv->save_TV_WIN_POS = INREG(TV_WIN_POS);
+ dev_priv->save_TV_WIN_SIZE = INREG(TV_WIN_SIZE);
+ dev_priv->save_TV_FILTER_CTL_1 = INREG(TV_FILTER_CTL_1);
+ dev_priv->save_TV_FILTER_CTL_2 = INREG(TV_FILTER_CTL_2);
+ dev_priv->save_TV_FILTER_CTL_3 = INREG(TV_FILTER_CTL_3);
+
+ for (i = 0; i < 60; i++)
+ dev_priv->save_TV_H_LUMA[i] = INREG(TV_H_LUMA_0 + (i <<2));
+ for (i = 0; i < 60; i++)
+ dev_priv->save_TV_H_CHROMA[i] = INREG(TV_H_CHROMA_0 + (i <<2));
+ for (i = 0; i < 43; i++)
+ dev_priv->save_TV_V_LUMA[i] = INREG(TV_V_LUMA_0 + (i <<2));
+ for (i = 0; i < 43; i++)
+ dev_priv->save_TV_V_CHROMA[i] = INREG(TV_V_CHROMA_0 + (i <<2));
+
+ dev_priv->save_TV_DAC = INREG(TV_DAC);
+ dev_priv->save_TV_CTL = INREG(TV_CTL);
+}
+
+static void
+i830_tv_restore(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ int i;
+
+ xf86CrtcPtr crtc = output->crtc;
+ I830CrtcPrivatePtr intel_crtc;
+ if (!crtc)
+ return;
+ intel_crtc = crtc->driver_private;
+ OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
+ OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
+ OUTREG(TV_H_CTL_3, dev_priv->save_TV_H_CTL_3);
+ OUTREG(TV_V_CTL_1, dev_priv->save_TV_V_CTL_1);
+ OUTREG(TV_V_CTL_2, dev_priv->save_TV_V_CTL_2);
+ OUTREG(TV_V_CTL_3, dev_priv->save_TV_V_CTL_3);
+ OUTREG(TV_V_CTL_4, dev_priv->save_TV_V_CTL_4);
+ OUTREG(TV_V_CTL_5, dev_priv->save_TV_V_CTL_5);
+ OUTREG(TV_V_CTL_6, dev_priv->save_TV_V_CTL_6);
+ OUTREG(TV_V_CTL_7, dev_priv->save_TV_V_CTL_7);
+ OUTREG(TV_SC_CTL_1, dev_priv->save_TV_SC_CTL_1);
+ OUTREG(TV_SC_CTL_2, dev_priv->save_TV_SC_CTL_2);
+ OUTREG(TV_SC_CTL_3, dev_priv->save_TV_SC_CTL_3);
+
+ OUTREG(TV_CSC_Y, dev_priv->save_TV_CSC_Y);
+ OUTREG(TV_CSC_Y2, dev_priv->save_TV_CSC_Y2);
+ OUTREG(TV_CSC_U, dev_priv->save_TV_CSC_U);
+ OUTREG(TV_CSC_U2, dev_priv->save_TV_CSC_U2);
+ OUTREG(TV_CSC_V, dev_priv->save_TV_CSC_V);
+ OUTREG(TV_CSC_V2, dev_priv->save_TV_CSC_V2);
+ OUTREG(TV_CLR_KNOBS, dev_priv->save_TV_CLR_KNOBS);
+ OUTREG(TV_CLR_LEVEL, dev_priv->save_TV_CLR_LEVEL);
+
+ {
+ int pipeconf_reg = (intel_crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int dspcntr_reg = (intel_crtc->plane == 0) ? DSPACNTR : DSPBCNTR;
+ int pipeconf = INREG(pipeconf_reg);
+ int dspcntr = INREG(dspcntr_reg);
+ int dspbase_reg = (intel_crtc->plane == 0) ? DSPABASE : DSPBBASE;
+ /* Pipe must be off here */
+ OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+
+ if (!IS_I9XX(pI830)) {
+ /* Wait for vblank for the disable to take effect */
+ i830WaitForVblank(pScrn);
+ }
+
+ OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
+ /* Wait for vblank for the disable to take effect. */
+ i830WaitForVblank(pScrn);
+
+ /* Filter ctl must be set before TV_WIN_SIZE */
+ OUTREG(TV_FILTER_CTL_1, dev_priv->save_TV_FILTER_CTL_1);
+ OUTREG(TV_FILTER_CTL_2, dev_priv->save_TV_FILTER_CTL_2);
+ OUTREG(TV_FILTER_CTL_3, dev_priv->save_TV_FILTER_CTL_3);
+ OUTREG(TV_WIN_POS, dev_priv->save_TV_WIN_POS);
+ OUTREG(TV_WIN_SIZE, dev_priv->save_TV_WIN_SIZE);
+ OUTREG(pipeconf_reg, pipeconf);
+ OUTREG(dspcntr_reg, dspcntr);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ }
+
+ for (i = 0; i < 60; i++)
+ OUTREG(TV_H_LUMA_0 + (i <<2), dev_priv->save_TV_H_LUMA[i]);
+ for (i = 0; i < 60; i++)
+ OUTREG(TV_H_CHROMA_0 + (i <<2), dev_priv->save_TV_H_CHROMA[i]);
+ for (i = 0; i < 43; i++)
+ OUTREG(TV_V_LUMA_0 + (i <<2), dev_priv->save_TV_V_LUMA[i]);
+ for (i = 0; i < 43; i++)
+ OUTREG(TV_V_CHROMA_0 + (i <<2), dev_priv->save_TV_V_CHROMA[i]);
+
+ OUTREG(TV_DAC, dev_priv->save_TV_DAC);
+ OUTREG(TV_CTL, dev_priv->save_TV_CTL);
+}
+
+static const tv_mode_t *
+i830_tv_mode_lookup (char *tv_format)
+{
+ int i;
+
+ for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++)
+ {
+ const tv_mode_t *tv_mode = &tv_modes[i];
+
+ if (xf86nameCompare (tv_format, tv_mode->name) == 0)
+ return tv_mode;
+ }
+ return NULL;
+}
+
+static const tv_mode_t *
+i830_tv_mode_find (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+
+ return i830_tv_mode_lookup (dev_priv->tv_format);
+}
+
+static int
+i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
+{
+ const tv_mode_t *tv_mode = i830_tv_mode_find (output);
+
+ if (tv_mode && fabs (tv_mode->refresh - xf86ModeVRefresh (mode)) < 1.0)
+ return MODE_OK;
+ return MODE_CLOCK_RANGE;
+}
+
+
+static Bool
+i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+ const tv_mode_t *tv_mode = i830_tv_mode_find (output);
+
+ if (!tv_mode)
+ return FALSE;
+
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr other_output = xf86_config->output[i];
+
+ if (other_output != output && other_output->crtc == output->crtc)
+ return FALSE;
+ }
+
+ adjusted_mode->Clock = tv_mode->clock;
+ return TRUE;
+}
+
+static CARD32
+i830_float_to_csc (float fin)
+{
+ CARD32 exp;
+ CARD32 mant;
+ CARD32 ret;
+ float f = fin;
+
+ /* somehow the color conversion knows the signs of all the values */
+ if (f < 0) f = -f;
+
+ if (f >= 1)
+ {
+ exp = 0x7;
+ mant = 1 << 8;
+ }
+ else
+ {
+ for (exp = 0; exp < 3 && f < 0.5; exp++)
+ f *= 2.0;
+ mant = (f * (1 << 9) + 0.5);
+ if (mant >= (1 << 9))
+ mant = (1 << 9) - 1;
+ }
+ ret = (exp << 9) | mant;
+ return ret;
+}
+
+static CARD16
+i830_float_to_luma (float f)
+{
+ CARD16 ret;
+
+ ret = (f * (1 << 9));
+ return ret;
+}
+
+static void
+i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86CrtcPtr crtc = output->crtc;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ const tv_mode_t *tv_mode = i830_tv_mode_find (output);
+ CARD32 tv_ctl;
+ CARD32 hctl1, hctl2, hctl3;
+ CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
+ CARD32 scctl1, scctl2, scctl3;
+ int i, j;
+ const video_levels_t *video_levels;
+ const color_conversion_t *color_conversion;
+ Bool burst_ena;
+
+ if (!tv_mode)
+ return; /* can't happen (mode_prepare prevents this) */
+
+ tv_ctl = 0;
+
+ switch (dev_priv->type) {
+ default:
+ case TV_TYPE_UNKNOWN:
+ case TV_TYPE_COMPOSITE:
+ tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
+ video_levels = &tv_mode->composite_levels;
+ color_conversion = &tv_mode->composite_color;
+ burst_ena = tv_mode->burst_ena;
+ break;
+ case TV_TYPE_COMPONENT:
+ tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
+ video_levels = &component_level;
+ if (tv_mode->burst_ena)
+ color_conversion = &sdtv_component_color;
+ else
+ color_conversion = &hdtv_component_color;
+ burst_ena = FALSE;
+ break;
+ case TV_TYPE_SVIDEO:
+ tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
+ video_levels = &tv_mode->svideo_levels;
+ color_conversion = &tv_mode->svideo_color;
+ burst_ena = tv_mode->burst_ena;
+ break;
+ }
+ hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
+ (tv_mode->htotal << TV_HTOTAL_SHIFT);
+
+ hctl2 = (tv_mode->hburst_start << 16) |
+ (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
+
+ if (burst_ena)
+ hctl2 |= TV_BURST_ENA;
+
+ hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
+ (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
+
+ vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
+ (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
+ (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
+
+ vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
+ (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
+ (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
+
+ vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
+ (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
+ (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
+
+ if (tv_mode->veq_ena)
+ vctl3 |= TV_EQUAL_ENA;
+
+ vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
+ (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
+
+ vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
+ (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
+
+ vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
+ (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
+
+ vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
+ (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
+
+ if (intel_crtc->pipe == 1)
+ tv_ctl |= TV_ENC_PIPEB_SELECT;
+ tv_ctl |= tv_mode->oversample;
+
+ if (tv_mode->progressive)
+ tv_ctl |= TV_PROGRESSIVE;
+ if (tv_mode->trilevel_sync)
+ tv_ctl |= TV_TRILEVEL_SYNC;
+ if (tv_mode->pal_burst)
+ tv_ctl |= TV_PAL_BURST;
+ scctl1 = 0;
+ if (tv_mode->dda1_inc)
+ scctl1 |= TV_SC_DDA1_EN;
+
+ if (tv_mode->dda2_inc)
+ scctl1 |= TV_SC_DDA2_EN;
+
+ if (tv_mode->dda3_inc)
+ scctl1 |= TV_SC_DDA3_EN;
+
+ scctl1 |= tv_mode->sc_reset;
+ scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
+ scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
+
+ scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
+ tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
+
+ scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
+ tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
+
+ /* Enable two fixes for the chips that need them. */
+ if (DEVICE_ID(pI830->PciInfo) < PCI_CHIP_I945_G)
+ tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
+
+ OUTREG(TV_H_CTL_1, hctl1);
+ OUTREG(TV_H_CTL_2, hctl2);
+ OUTREG(TV_H_CTL_3, hctl3);
+ OUTREG(TV_V_CTL_1, vctl1);
+ OUTREG(TV_V_CTL_2, vctl2);
+ OUTREG(TV_V_CTL_3, vctl3);
+ OUTREG(TV_V_CTL_4, vctl4);
+ OUTREG(TV_V_CTL_5, vctl5);
+ OUTREG(TV_V_CTL_6, vctl6);
+ OUTREG(TV_V_CTL_7, vctl7);
+ OUTREG(TV_SC_CTL_1, scctl1);
+ OUTREG(TV_SC_CTL_2, scctl2);
+ OUTREG(TV_SC_CTL_3, scctl3);
+
+ OUTREG(TV_CSC_Y,
+ (i830_float_to_csc(color_conversion->ry) << 16) |
+ (i830_float_to_csc(color_conversion->gy)));
+ OUTREG(TV_CSC_Y2,
+ (i830_float_to_csc(color_conversion->by) << 16) |
+ (i830_float_to_luma(color_conversion->ay)));
+
+ OUTREG(TV_CSC_U,
+ (i830_float_to_csc(color_conversion->ru) << 16) |
+ (i830_float_to_csc(color_conversion->gu)));
+
+ OUTREG(TV_CSC_U2,
+ (i830_float_to_csc(color_conversion->bu) << 16) |
+ (i830_float_to_luma(color_conversion->au)));
+
+ OUTREG(TV_CSC_V,
+ (i830_float_to_csc(color_conversion->rv) << 16) |
+ (i830_float_to_csc(color_conversion->gv)));
+
+ OUTREG(TV_CSC_V2,
+ (i830_float_to_csc(color_conversion->bv) << 16) |
+ (i830_float_to_luma(color_conversion->av)));
+
+ OUTREG(TV_CLR_KNOBS, 0x00606000);
+ OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
+ (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
+ {
+ int pipeconf_reg = (intel_crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int dspcntr_reg = (intel_crtc->plane == 0) ? DSPACNTR : DSPBCNTR;
+ int pipeconf = INREG(pipeconf_reg);
+ int dspcntr = INREG(dspcntr_reg);
+ int dspbase_reg = (intel_crtc->plane == 0) ? DSPABASE : DSPBBASE;
+ int xpos = 0x0, ypos = 0x0;
+ unsigned int xsize, ysize;
+ /* Pipe must be off here */
+ OUTREG(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+
+ if (!IS_I9XX(pI830)) {
+ /* Wait for vblank for the disable to take effect */
+ i830WaitForVblank(pScrn);
+ }
+
+ OUTREG(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
+ /* Wait for vblank for the disable to take effect. */
+ i830WaitForVblank(pScrn);
+
+ /* Filter ctl must be set before TV_WIN_SIZE */
+ OUTREG(TV_FILTER_CTL_1, TV_AUTO_SCALE);
+ xsize = tv_mode->hblank_start - tv_mode->hblank_end;
+ if (tv_mode->progressive)
+ ysize = tv_mode->nbr_end + 1;
+ else
+ ysize = 2*tv_mode->nbr_end + 1;
+
+ xpos += dev_priv->margin[TV_MARGIN_LEFT];
+ ypos += dev_priv->margin[TV_MARGIN_TOP];
+ xsize -= (dev_priv->margin[TV_MARGIN_LEFT] +
+ dev_priv->margin[TV_MARGIN_RIGHT]);
+ ysize -= (dev_priv->margin[TV_MARGIN_TOP] +
+ dev_priv->margin[TV_MARGIN_BOTTOM]);
+ OUTREG(TV_WIN_POS, (xpos<<16)|ypos);
+ OUTREG(TV_WIN_SIZE, (xsize<<16)|ysize);
+
+ OUTREG(pipeconf_reg, pipeconf);
+ OUTREG(dspcntr_reg, dspcntr);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ }
+
+ j = 0;
+ for (i = 0; i < 60; i++)
+ OUTREG(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ for (i = 0; i < 60; i++)
+ OUTREG(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ for (i = 0; i < 43; i++)
+ OUTREG(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ for (i = 0; i < 43; i++)
+ OUTREG(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
+ OUTREG(TV_DAC, 0);
+ OUTREG(TV_CTL, tv_ctl);
+}
+
+static const DisplayModeRec reported_modes[] = {
+ {
+ .name = "NTSC 480i",
+ .Clock = 107520,
+ .HDisplay = 1280,
+ .HSyncStart = 1368,
+ .HSyncEnd = 1496,
+ .HTotal = 1712,
+
+ .VDisplay = 1024,
+ .VSyncStart = 1027,
+ .VSyncEnd = 1034,
+ .VTotal = 1104,
+ .type = M_T_DRIVER
+ },
+};
+
+/**
+ * Detects TV presence by checking for load.
+ *
+ * Requires that the current pipe's DPLL is active.
+
+ * \return TRUE if TV is connected.
+ * \return FALSE if TV is disconnected.
+ */
+static int
+i830_tv_detect_type (xf86CrtcPtr crtc,
+ xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ CARD32 tv_ctl, save_tv_ctl;
+ CARD32 tv_dac, save_tv_dac;
+ int type = TV_TYPE_UNKNOWN;
+
+ tv_dac = INREG(TV_DAC);
+ /*
+ * Detect TV by polling)
+ */
+ if (intel_output->load_detect_temp)
+ {
+ /* TV not currently running, prod it with destructive detect */
+ save_tv_dac = tv_dac;
+ tv_ctl = INREG(TV_CTL);
+ save_tv_ctl = tv_ctl;
+ tv_ctl &= ~TV_ENC_ENABLE;
+ tv_ctl &= ~TV_TEST_MODE_MASK;
+ tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+ tv_dac &= ~TVDAC_SENSE_MASK;
+ tv_dac |= (TVDAC_STATE_CHG_EN |
+ TVDAC_A_SENSE_CTL |
+ TVDAC_B_SENSE_CTL |
+ TVDAC_C_SENSE_CTL |
+ DAC_CTL_OVERRIDE |
+ DAC_A_0_7_V |
+ DAC_B_0_7_V |
+ DAC_C_0_7_V);
+ OUTREG(TV_CTL, tv_ctl);
+ OUTREG(TV_DAC, tv_dac);
+ i830WaitForVblank(pScrn);
+ tv_dac = INREG(TV_DAC);
+ OUTREG(TV_DAC, save_tv_dac);
+ OUTREG(TV_CTL, save_tv_ctl);
+ }
+ /*
+ * A B C
+ * 0 1 1 Composite
+ * 1 0 X svideo
+ * 0 0 0 Component
+ */
+ if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected Composite TV connection\n");
+ }
+ type = TV_TYPE_COMPOSITE;
+ } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected S-Video TV connection\n");
+ }
+ type = TV_TYPE_SVIDEO;
+ } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Detected Component TV connection\n");
+ }
+ type = TV_TYPE_COMPONENT;
+ } else {
+ if (pI830->debug_modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No TV connection detected\n");
+ }
+ type = TV_TYPE_NONE;
+ }
+
+ return type;
+}
+
+#ifdef RANDR_12_INTERFACE
+static int
+i830_tv_format_configure_property (xf86OutputPtr output);
+#endif
+
+/**
+ * Detect the TV connection.
+ *
+ * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure
+ * we have a pipe programmed in order to probe the TV.
+ */
+static xf86OutputStatus
+i830_tv_detect(xf86OutputPtr output)
+{
+ xf86CrtcPtr crtc;
+ DisplayModeRec mode;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ int dpms_mode;
+ int type = dev_priv->type;
+
+ mode = reported_modes[0];
+ xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ crtc = i830GetLoadDetectPipe (output, &mode, &dpms_mode);
+ if (crtc)
+ {
+ type = i830_tv_detect_type (crtc, output);
+ i830ReleaseLoadDetectPipe (output, dpms_mode);
+ }
+
+ if (type != dev_priv->type)
+ {
+ dev_priv->type = type;
+#ifdef RANDR_12_INTERFACE
+ i830_tv_format_configure_property (output);
+#endif
+ }
+
+ switch (type) {
+ case TV_TYPE_NONE:
+ return XF86OutputStatusDisconnected;
+ case TV_TYPE_UNKNOWN:
+ return XF86OutputStatusUnknown;
+ default:
+ return XF86OutputStatusConnected;
+ }
+}
+
+static struct input_res {
+ char *name;
+ int w, h;
+} input_res_table[] =
+{
+ {"640x480", 640, 480},
+ {"800x600", 800, 600},
+ {"1024x768", 1024, 768},
+ {"1280x1024", 1280, 1024},
+ {"848x480", 848, 480},
+ {"1280x720", 1280, 720},
+ {"1920x108", 1920, 1080},
+};
+
+/**
+ * Stub get_modes function.
+ *
+ * This should probably return a set of fixed modes, unless we can figure out
+ * how to probe modes off of TV connections.
+ */
+
+static DisplayModePtr
+i830_tv_get_modes(xf86OutputPtr output)
+{
+ DisplayModePtr ret = NULL, mode_ptr;
+ int j;
+ const tv_mode_t *tv_mode = i830_tv_mode_find (output);
+
+ for (j = 0; j < sizeof(input_res_table)/sizeof(input_res_table[0]); j++)
+ {
+ struct input_res *input = &input_res_table[j];
+ unsigned int hactive_s = input->w;
+ unsigned int vactive_s = input->h;
+
+ if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
+ continue;
+
+ if (input->w > 1024 && (!tv_mode->progressive
+ && !tv_mode->component_only))
+ continue;
+
+ mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));
+ mode_ptr->name = xnfalloc(strlen(input->name) + 1);
+ strcpy (mode_ptr->name, input->name);
+
+ mode_ptr->HDisplay = hactive_s;
+ mode_ptr->HSyncStart = hactive_s + 1;
+ mode_ptr->HSyncEnd = hactive_s + 64;
+ if ( mode_ptr->HSyncEnd <= mode_ptr->HSyncStart)
+ mode_ptr->HSyncEnd = mode_ptr->HSyncStart + 1;
+ mode_ptr->HTotal = hactive_s + 96;
+
+ mode_ptr->VDisplay = vactive_s;
+ mode_ptr->VSyncStart = vactive_s + 1;
+ mode_ptr->VSyncEnd = vactive_s + 32;
+ if ( mode_ptr->VSyncEnd <= mode_ptr->VSyncStart)
+ mode_ptr->VSyncEnd = mode_ptr->VSyncStart + 1;
+ mode_ptr->VTotal = vactive_s + 33;
+
+ mode_ptr->Clock = (int) (tv_mode->refresh *
+ mode_ptr->VTotal *
+ mode_ptr->HTotal / 1000.0);
+
+ mode_ptr->type = M_T_DRIVER;
+ mode_ptr->next = ret;
+ mode_ptr->prev = NULL;
+ if (ret != NULL)
+ ret->prev = mode_ptr;
+ ret = mode_ptr;
+ }
+
+ return ret;
+}
+
+static void
+i830_tv_destroy (xf86OutputPtr output)
+{
+ if (output->driver_private)
+ xfree (output->driver_private);
+}
+
+#ifdef RANDR_12_INTERFACE
+#define TV_FORMAT_NAME "TV_FORMAT"
+static Atom tv_format_atom;
+static Atom tv_format_name_atoms[NUM_TV_MODES];
+static Atom margin_atoms[4];
+static char *margin_names[4] = {
+ "LEFT", "TOP", "RIGHT", "BOTTOM"
+};
+
+static Bool
+i830_tv_format_set_property (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ const tv_mode_t *tv_mode = i830_tv_mode_lookup (dev_priv->tv_format);
+ int err;
+
+ if (!tv_mode)
+ tv_mode = &tv_modes[0];
+ err = RRChangeOutputProperty (output->randr_output, tv_format_atom,
+ XA_ATOM, 32, PropModeReplace, 1,
+ &tv_format_name_atoms[tv_mode - tv_modes],
+ FALSE, TRUE);
+ return err == Success;
+}
+
+
+/**
+ * Configure the TV_FORMAT property to list only supported formats
+ *
+ * Unless the connector is component, list only the formats supported by
+ * svideo and composite
+ */
+
+static int
+i830_tv_format_configure_property (xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ Atom current_atoms[NUM_TV_MODES];
+ int num_atoms = 0;
+ int i;
+
+ if (!output->randr_output)
+ return Success;
+
+ for (i = 0; i < NUM_TV_MODES; i++)
+ if (!tv_modes[i].component_only || dev_priv->type == TV_TYPE_COMPONENT)
+ current_atoms[num_atoms++] = tv_format_name_atoms[i];
+
+ return RRConfigureOutputProperty(output->randr_output, tv_format_atom,
+ TRUE, FALSE, FALSE,
+ num_atoms, (INT32 *) current_atoms);
+}
+
+#endif /* RANDR_12_INTERFACE */
+
+static void
+i830_tv_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ int err;
+ int i;
+
+ /* Set up the tv_format property, which takes effect on mode set
+ * and accepts strings that match exactly
+ */
+ tv_format_atom = MakeAtom(TV_FORMAT_NAME, sizeof(TV_FORMAT_NAME) - 1,
+ TRUE);
+
+ for (i = 0; i < NUM_TV_MODES; i++)
+ tv_format_name_atoms[i] = MakeAtom (tv_modes[i].name,
+ strlen (tv_modes[i].name),
+ TRUE);
+
+ err = i830_tv_format_configure_property (output);
+
+ if (err != 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+
+ /* Set the current value of the tv_format property */
+ if (!i830_tv_format_set_property (output))
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+
+ for (i = 0; i < 4; i++)
+ {
+ INT32 range[2];
+ margin_atoms[i] = MakeAtom(margin_names[i], strlen (margin_names[i]),
+ TRUE);
+
+ range[0] = 0;
+ range[1] = 100;
+ err = RRConfigureOutputProperty(output->randr_output, margin_atoms[i],
+ TRUE, TRUE, FALSE, 2, range);
+
+ if (err != 0)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+
+ err = RRChangeOutputProperty(output->randr_output, margin_atoms[i],
+ XA_INTEGER, 32, PropModeReplace,
+ 1, &dev_priv->margin[i],
+ FALSE, TRUE);
+ if (err != 0)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+#endif /* RANDR_12_INTERFACE */
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+i830_tv_set_property(xf86OutputPtr output, Atom property,
+ RRPropertyValuePtr value)
+{
+ int i;
+
+ if (property == tv_format_atom)
+ {
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ Atom atom;
+ char *name;
+ char *val;
+
+ if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+ return FALSE;
+
+ memcpy (&atom, value->data, 4);
+ name = NameForAtom (atom);
+
+ val = xalloc (strlen (name) + 1);
+ if (!val)
+ return FALSE;
+ strcpy (val, name);
+ if (!i830_tv_mode_lookup (val))
+ {
+ xfree (val);
+ return FALSE;
+ }
+ xfree (dev_priv->tv_format);
+ dev_priv->tv_format = val;
+ return TRUE;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (property == margin_atoms[i])
+ {
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_tv_priv *dev_priv = intel_output->dev_priv;
+ INT32 val;
+
+ if (value->type != XA_INTEGER || value->format != 32 ||
+ value->size != 1)
+ return FALSE;
+
+ memcpy (&val, value->data, 4);
+ dev_priv->margin[i] = val;
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+#endif /* RANDR_12_INTERFACE */
+
+static const xf86OutputFuncsRec i830_tv_output_funcs = {
+ .create_resources = i830_tv_create_resources,
+ .dpms = i830_tv_dpms,
+ .save = i830_tv_save,
+ .restore = i830_tv_restore,
+ .mode_valid = i830_tv_mode_valid,
+ .mode_fixup = i830_tv_mode_fixup,
+ .prepare = i830_output_prepare,
+ .mode_set = i830_tv_mode_set,
+ .commit = i830_output_commit,
+ .detect = i830_tv_detect,
+ .get_modes = i830_tv_get_modes,
+ .destroy = i830_tv_destroy,
+#ifdef RANDR_12_INTERFACE
+ .set_property = i830_tv_set_property,
+#endif
+};
+
+void
+i830_tv_init(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86OutputPtr output;
+ I830OutputPrivatePtr intel_output;
+ struct i830_tv_priv *dev_priv;
+ CARD32 tv_dac_on, tv_dac_off, save_tv_dac;
+
+ if (pI830->quirk_flag & QUIRK_IGNORE_TV)
+ return;
+
+ if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
+ return;
+
+ /*
+ * Sanity check the TV output by checking to see if the
+ * DAC register holds a value
+ */
+ save_tv_dac = INREG(TV_DAC);
+
+ OUTREG(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
+ tv_dac_on = INREG(TV_DAC);
+
+ OUTREG(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
+ tv_dac_off = INREG(TV_DAC);
+
+ OUTREG(TV_DAC, save_tv_dac);
+
+ /*
+ * If the register does not hold the state change enable
+ * bit, (either as a 0 or a 1), assume it doesn't really
+ * exist
+ */
+ if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
+ (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
+ return;
+
+ output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
+
+ if (!output)
+ return;
+
+ intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+ sizeof (struct i830_tv_priv), 1);
+ if (!intel_output)
+ {
+ xf86OutputDestroy (output);
+ return;
+ }
+ dev_priv = (struct i830_tv_priv *) (intel_output + 1);
+ intel_output->type = I830_OUTPUT_TVOUT;
+ intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+ intel_output->clone_mask = (1 << I830_OUTPUT_TVOUT);
+ intel_output->dev_priv = dev_priv;
+ dev_priv->type = TV_TYPE_UNKNOWN;
+
+ dev_priv->tv_format = NULL;
+
+ /* BIOS margin values */
+ dev_priv->margin[TV_MARGIN_LEFT] = 54;
+ dev_priv->margin[TV_MARGIN_TOP] = 36;
+ dev_priv->margin[TV_MARGIN_RIGHT] = 46;
+ dev_priv->margin[TV_MARGIN_BOTTOM] = 37;
+
+ if (output->conf_monitor)
+ {
+ char *tv_format;
+
+ tv_format = xf86findOptionValue (output->conf_monitor->mon_option_lst, "TV Format");
+ if (tv_format)
+ dev_priv->tv_format = xstrdup (tv_format);
+ }
+ if (!dev_priv->tv_format)
+ dev_priv->tv_format = xstrdup (tv_modes[0].name);
+
+ output->driver_private = intel_output;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+}
diff --git a/driver/xf86-video-intel/src/i830_xaa.c b/driver/xf86-video-intel/src/i830_xaa.c
new file mode 100644
index 000000000..fabac20e2
--- /dev/null
+++ b/driver/xf86-video-intel/src/i830_xaa.c
@@ -0,0 +1,888 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ * -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ * -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+#include "mipict.h"
+
+#ifndef DO_SCANLINE_IMAGE_WRITE
+#define DO_SCANLINE_IMAGE_WRITE 0
+#endif
+
+/* 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);
+
+void
+i830_xaa_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+Bool
+I830XAAInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ int width = 0;
+ int nr_buffers = 0;
+ unsigned char *ptr = NULL;
+
+ if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
+ ErrorF("I830XAAInit\n");
+
+ pI830->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr)
+ return FALSE;
+
+ 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->xaa_scratch->size != 0) {
+ width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ nr_buffers = pI830->xaa_scratch->size / width;
+ ptr = pI830->FbBase + pI830->xaa_scratch->offset;
+ }
+ } else {
+ /* On the secondary screen */
+ I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+ if (pI8301->xaa_scratch_2->size != 0) {
+ width = ((pScrn->displayWidth + 31) & ~31) / 8;
+ nr_buffers = pI8301->xaa_scratch_2->size / width;
+ /* We have to use the primary screen's FbBase, as that's where
+ * we allocated xaa_scratch_2, so we get the correct pointer */
+ ptr = pI8301->FbBase + pI8301->xaa_scratch_2->offset;
+ }
+ }
+
+ 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;
+
+ for(i = 0; i < pScrn->numEntities; i++) {
+ if(xf86IsEntityShared(pScrn->entityList[i]))
+ shared_accel = TRUE;
+ }
+ if(shared_accel == TRUE)
+ infoPtr->RestoreAccelState = I830RestoreAccelState;
+ }
+
+ /* Set up pI830->bufferOffset */
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+ if (!XAAInit(pScreen, infoPtr))
+ return FALSE;
+
+ if (ps != NULL) {
+ if (IS_I865G(pI830) || IS_I855(pI830) ||
+ IS_845G(pI830) || IS_I830(pI830))
+ {
+ pI830->xaa_check_composite = i830_check_composite;
+ pI830->xaa_prepare_composite = i830_prepare_composite;
+ pI830->xaa_composite = i830_composite;
+ pI830->xaa_done_composite = i830_done_composite;
+ } else if (IS_I915G(pI830) || IS_I915GM(pI830) ||
+ IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ {
+ pI830->xaa_check_composite = i915_check_composite;
+ pI830->xaa_prepare_composite = i915_prepare_composite;
+ pI830->xaa_composite = i830_composite;
+ pI830->xaa_done_composite = i830_done_composite;
+ } else {
+ pI830->xaa_check_composite = i965_check_composite;
+ pI830->xaa_prepare_composite = i965_prepare_composite;
+ pI830->xaa_composite = i965_composite;
+ pI830->xaa_done_composite = i830_done_composite;
+ }
+
+ pI830->saved_composite = ps->Composite;
+ ps->Composite = i830_xaa_composite;
+ }
+
+ return TRUE;
+}
+
+static unsigned int
+I830CheckTiling(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (pI830->bufferOffset == pI830->front_buffer->offset &&
+ pI830->front_buffer->tiling != TILE_NONE)
+ {
+ return TRUE;
+ }
+#ifdef XF86DRI
+ if (pI830->back_buffer != NULL &&
+ pI830->bufferOffset == pI830->back_buffer->offset &&
+ pI830->back_buffer->tiling != TILE_NONE)
+ {
+ return TRUE;
+ }
+ if (pI830->depth_buffer != NULL &&
+ pI830->bufferOffset == pI830->depth_buffer->offset &&
+ pI830->depth_buffer->tiling != TILE_NONE)
+ {
+ return TRUE;
+ }
+ if (pI830->third_buffer != NULL &&
+ pI830->bufferOffset == pI830->third_buffer->offset &&
+ pI830->third_buffer->tiling != TILE_NONE)
+ {
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+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);
+
+ if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+ } else {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ }
+
+#ifdef I830_USE_EXA
+ /* This function gets used by I830DRIInitBuffers(), and we might not have
+ * XAAGetPatternROP() available. So just use the ROPs from our EXA code
+ * if available.
+ */
+ pI830->BR[13] |= (I830PatternROP[rop] << 16);
+#else
+ pI830->BR[13] |= ((XAAGetPatternROP(rop) << 16);
+#endif
+
+ 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();
+ }
+
+ if (IS_I965G(pI830))
+ I830EmitFlush(pScrn);
+}
+
+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);
+
+ if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+ } else {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ }
+
+#ifdef I830_USE_EXA
+ /* This function gets used by I830DRIInitBuffers(), and we might not have
+ * XAAGetCopyROP() available. So just use the ROPs from our EXA code
+ * if available.
+ */
+ pI830->BR[13] |= I830CopyROP[rop] << 16;
+#else
+ pI830->BR[13] |= XAAGetCopyROP(rop) << 16;
+#endif
+
+ 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;
+ unsigned int tiled = I830CheckTiling(pScrn);
+
+ 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 | tiled << 15 | tiled << 11);
+ } else {
+ OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 15 | tiled << 11);
+ }
+ 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();
+ }
+
+ if (IS_I965G(pI830))
+ I830EmitFlush(pScrn);
+}
+
+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;
+
+ if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+ } else {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp);
+ }
+ 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;
+ unsigned int tiled = I830CheckTiling(pScrn);
+
+ 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 | tiled << 11 |
+ ((patty << 8) & XY_MONO_PAT_VERT_SEED) |
+ ((pattx << 12) & XY_MONO_PAT_HORT_SEED));
+ } else {
+ OUT_RING(XY_MONO_PAT_BLT_CMD | tiled << 11 |
+ ((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();
+ }
+
+ if (IS_I965G(pI830))
+ I830EmitFlush(pScrn);
+}
+
+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 */
+ if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+ } else {
+ 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);
+ unsigned int tiled = I830CheckTiling(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 xaa_scratch_2, 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 |
+ tiled << 11 | XY_MONO_SRC_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(XY_MONO_SRC_BLT_CMD | tiled << 11);
+ }
+ 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 (IS_I965G(pI830))
+ I830EmitFlush(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 */
+ if (IS_I965G(pI830) && I830CheckTiling(pScrn)) {
+ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp) >> 4;
+ } else {
+ 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);
+ unsigned int tiled = I830CheckTiling(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 xaa_scratch_2, 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 |
+ tiled << 11 | XY_SRC_COPY_BLT_WRITE_RGB);
+ } else {
+ OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 11);
+ }
+ 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 /* DO_SCANLINE_IMAGE_WRITE */
+/* Support for multiscreen */
+
+/**
+ * Special case acceleration for Render acceleration of rotation operations
+ * by xf86Rotate.c
+ */
+void
+i830_xaa_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ PictureScreenPtr ps;
+ PixmapPtr pSrcPixmap, pDstPixmap;
+ RegionRec region;
+ BoxPtr pbox;
+ int nbox;
+ int i;
+
+ /* Throw out cases that aren't going to be our rotation first */
+ if (pMask != NULL || op != PictOpSrc || pSrc->pDrawable == NULL)
+ goto fallback;
+
+ if (pSrc->pDrawable->type != DRAWABLE_WINDOW ||
+ pDst->pDrawable->type != DRAWABLE_PIXMAP)
+ {
+ goto fallback;
+ }
+ pSrcPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pSrc->pDrawable);
+ pDstPixmap = (PixmapPtr)pDst->pDrawable;
+
+ /* Check if the dest is one of our shadow pixmaps */
+ for (i = 0; i < xf86_config->num_crtc; i++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+ if (crtc->rotatedPixmap == pDstPixmap)
+ break;
+ }
+ if (i == xf86_config->num_crtc)
+ goto fallback;
+
+ if (pSrcPixmap != pScreen->GetScreenPixmap(pScreen))
+ goto fallback;
+
+ /* OK, so we've got a Render operation on one of our shadow pixmaps, with
+ * the source being the real framebuffer. We know that both of these are
+ * in framebuffer, with no x/y offsets, i.e. normal pixmaps like our EXA-
+ * based Render acceleration code expects.
+ */
+ assert(pSrcPixmap->drawable.x == 0);
+ assert(pSrcPixmap->drawable.y == 0);
+ assert(pDstPixmap->drawable.x == 0);
+ assert(pDstPixmap->drawable.y == 0);
+
+ if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
+ xSrc, ySrc, 0, 0, xDst, yDst,
+ width, height))
+ return;
+
+ if (!pI830->xaa_check_composite(op, pSrc, NULL, pDst)) {
+ REGION_UNINIT(pScreen, &region);
+ goto fallback;
+ }
+
+ if (!pI830->xaa_prepare_composite(op, pSrc, NULL, pDst,
+ pSrcPixmap, NULL, pDstPixmap))
+ {
+ REGION_UNINIT(pScreen, &region);
+ goto fallback;
+ }
+
+ nbox = REGION_NUM_RECTS(&region);
+ pbox = REGION_RECTS(&region);
+
+ xSrc -= xDst;
+ ySrc -= yDst;
+
+ while (nbox--)
+ {
+ pI830->xaa_composite(pDstPixmap,
+ pbox->x1 + xSrc,
+ pbox->y1 + ySrc,
+ 0, 0,
+ pbox->x1,
+ pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+ pI830->xaa_done_composite(pDstPixmap);
+ i830MarkSync(pScrn);
+
+ return;
+
+fallback:
+ /* Fallback path: Call down to the next level (XAA) */
+ ps = GetPictureScreenIfSet(pScreen);
+
+ ps->Composite = pI830->saved_composite;
+
+ ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+
+ pI830->saved_composite = ps->Composite;
+ ps->Composite = i830_xaa_composite;
+}
+
+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-intel/src/i915_render.c b/driver/xf86-video-intel/src/i915_render.c
new file mode 100644
index 000000000..ca85bf73c
--- /dev/null
+++ b/driver/xf86-video-intel/src/i915_render.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...) \
+do { \
+ DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \
+ return FALSE; \
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) \
+do { \
+ return FALSE; \
+} while(0)
+#endif
+
+struct formatinfo {
+ int fmt;
+ CARD32 card_fmt;
+};
+
+struct blendinfo {
+ Bool dst_alpha;
+ Bool src_alpha;
+ CARD32 src_blend;
+ CARD32 dst_blend;
+};
+
+static struct blendinfo i915_blend_op[] = {
+ /* Clear */
+ {0, 0, BLENDFACT_ZERO, BLENDFACT_ZERO},
+ /* Src */
+ {0, 0, BLENDFACT_ONE, BLENDFACT_ZERO},
+ /* Dst */
+ {0, 0, BLENDFACT_ZERO, BLENDFACT_ONE},
+ /* Over */
+ {0, 1, BLENDFACT_ONE, BLENDFACT_INV_SRC_ALPHA},
+ /* OverReverse */
+ {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
+ /* In */
+ {1, 0, BLENDFACT_DST_ALPHA, BLENDFACT_ZERO},
+ /* InReverse */
+ {0, 1, BLENDFACT_ZERO, BLENDFACT_SRC_ALPHA},
+ /* Out */
+ {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
+ /* OutReverse */
+ {0, 1, BLENDFACT_ZERO, BLENDFACT_INV_SRC_ALPHA},
+ /* Atop */
+ {1, 1, BLENDFACT_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
+ /* AtopReverse */
+ {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
+ /* Xor */
+ {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
+ /* Add */
+ {0, 0, BLENDFACT_ONE, BLENDFACT_ONE},
+};
+
+static struct formatinfo i915_tex_formats[] = {
+ {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
+ {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
+ {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
+ {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
+ {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565 },
+ {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+ {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
+ {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+ {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
+ {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8 },
+};
+
+static CARD32 i915_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+ CARD32 sblend, dblend;
+
+ sblend = i915_blend_op[op].src_blend;
+ dblend = i915_blend_op[op].dst_blend;
+
+ /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+ * it as always 1.
+ */
+ if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) {
+ if (sblend == BLENDFACT_DST_ALPHA)
+ sblend = BLENDFACT_ONE;
+ else if (sblend == BLENDFACT_INV_DST_ALPHA)
+ sblend = BLENDFACT_ZERO;
+ }
+
+ /* i915 engine reads 8bit color buffer into green channel in cases
+ like color buffer blending .etc, and also writes back green channel.
+ So with dst_alpha blend we should use color factor. See spec on
+ "8-bit rendering" */
+ if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) {
+ if (sblend == BLENDFACT_DST_ALPHA)
+ sblend = BLENDFACT_DST_COLR;
+ else if (sblend == BLENDFACT_INV_DST_ALPHA)
+ sblend = BLENDFACT_INV_DST_COLR;
+ }
+
+ /* If the source alpha is being used, then we should only be in a case
+ * where the source blend factor is 0, and the source blend value is the
+ * mask channels multiplied by the source picture's alpha.
+ */
+ if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
+ i915_blend_op[op].src_alpha)
+ {
+ if (dblend == BLENDFACT_SRC_ALPHA) {
+ dblend = BLENDFACT_SRC_COLR;
+ } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
+ dblend = BLENDFACT_INV_SRC_COLR;
+ }
+ }
+
+ return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+ (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
+}
+
+static Bool i915_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+ switch (pDstPicture->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ *dst_format = COLR_BUF_ARGB8888;
+ break;
+ case PICT_r5g6b5:
+ *dst_format = COLR_BUF_RGB565;
+ break;
+ case PICT_a1r5g5b5:
+ case PICT_x1r5g5b5:
+ *dst_format = COLR_BUF_ARGB1555;
+ break;
+ case PICT_a8:
+ *dst_format = COLR_BUF_8BIT;
+ break;
+ case PICT_a4r4g4b4:
+ case PICT_x4r4g4b4:
+ *dst_format = COLR_BUF_ARGB4444;
+ break;
+ default:
+ I830FALLBACK("Unsupported dest format 0x%x\n",
+ (int)pDstPicture->format);
+ }
+
+ return TRUE;
+}
+
+static Bool i915_check_composite_texture(PicturePtr pPict, int unit)
+{
+ int w = pPict->pDrawable->width;
+ int h = pPict->pDrawable->height;
+ int i;
+
+ if ((w > 0x7ff) || (h > 0x7ff))
+ I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+ for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
+ i++)
+ {
+ if (i915_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]))
+ I830FALLBACK("Unsupported picture format 0x%x\n",
+ (int)pPict->format);
+
+ if (pPict->repeat && pPict->repeatType != RepeatNormal)
+ I830FALLBACK("extended repeat (%d) not supported\n",
+ pPict->repeatType);
+
+ if (pPict->filter != PictFilterNearest &&
+ pPict->filter != PictFilterBilinear)
+ I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+ return TRUE;
+}
+
+Bool
+i915_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ CARD32 tmp1;
+
+ /* Check for unsupported compositing operations. */
+ if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0]))
+ I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+ if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format))
+ {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i915_blend_op[op].src_alpha &&
+ (i915_blend_op[op].src_blend != BLENDFACT_ZERO))
+ I830FALLBACK("Component alpha not supported with source "
+ "alpha and source value blending.\n");
+ }
+
+ if (!i915_check_composite_texture(pSrcPicture, 0))
+ I830FALLBACK("Check Src picture texture\n");
+ if (pMaskPicture != NULL && !i915_check_composite_texture(pMaskPicture, 1))
+ I830FALLBACK("Check Mask picture texture\n");
+
+ if (!i915_get_dest_format(pDstPicture, &tmp1))
+ I830FALLBACK("Get Color buffer format\n");
+
+ return TRUE;
+}
+
+static Bool
+i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 format, offset, pitch, filter;
+ int w, h, i;
+ CARD32 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
+
+ offset = intel_get_pixmap_offset(pPix);
+ pitch = intel_get_pixmap_pitch(pPix);
+ w = pPict->pDrawable->width;
+ h = pPict->pDrawable->height;
+ pI830->scale_units[unit][0] = pPix->drawable.width;
+ pI830->scale_units[unit][1] = pPix->drawable.height;
+
+ for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
+ i++)
+ {
+ if (i915_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ if (i == sizeof(i915_tex_formats)/ sizeof(i915_tex_formats[0]))
+ I830FALLBACK("unknown texture format\n");
+ format = i915_tex_formats[i].card_fmt;
+
+ if (pPict->repeat)
+ wrap_mode = TEXCOORDMODE_WRAP;
+
+ switch (pPict->filter) {
+ case PictFilterNearest:
+ filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
+ (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ break;
+ case PictFilterBilinear:
+ filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
+ (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
+ break;
+ default:
+ filter = 0;
+ I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+ }
+
+ pI830->mapstate[unit * 3 + 0] = offset;
+ pI830->mapstate[unit * 3 + 1] = format |
+ MS3_USE_FENCE_REGS |
+ ((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
+ ((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
+ pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
+
+ pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE <<
+ SS2_MIP_FILTER_SHIFT);
+ pI830->samplerstate[unit * 3 + 0] |= filter;
+ pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
+ pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
+ pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
+ pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
+ pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
+
+ pI830->transform[unit] = pPict->transform;
+
+ return TRUE;
+}
+
+Bool
+i915_prepare_composite(int op, PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 dst_format, dst_offset, dst_pitch;
+ CARD32 blendctl;
+ int out_reg = FS_OC;
+
+ IntelEmitInvarientState(pScrn);
+ *pI830->last_3d = LAST_3D_RENDER;
+
+ i915_get_dest_format(pDstPicture, &dst_format);
+ dst_offset = intel_get_pixmap_offset(pDst);
+ dst_pitch = intel_get_pixmap_pitch(pDst);
+ FS_LOCALS(20);
+
+ if (!i915_texture_setup(pSrcPicture, pSrc, 0))
+ I830FALLBACK("fail to setup src texture\n");
+ if (pMask != NULL) {
+ if (!i915_texture_setup(pMaskPicture, pMask, 1))
+ I830FALLBACK("fail to setup mask texture\n");
+ } else {
+ pI830->transform[1] = NULL;
+ pI830->scale_units[1][0] = -1;
+ pI830->scale_units[1][1] = -1;
+ }
+
+ if (pMask == NULL) {
+ BEGIN_LP_RING(10);
+ OUT_RING(_3DSTATE_MAP_STATE | 3);
+ OUT_RING(0x00000001); /* map 0 */
+ OUT_RING(pI830->mapstate[0]);
+ OUT_RING(pI830->mapstate[1]);
+ OUT_RING(pI830->mapstate[2]);
+
+ OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
+ OUT_RING(0x00000001); /* sampler 0 */
+ OUT_RING(pI830->samplerstate[0]);
+ OUT_RING(pI830->samplerstate[1]);
+ OUT_RING(pI830->samplerstate[2]);
+ ADVANCE_LP_RING();
+ } else {
+ BEGIN_LP_RING(16);
+ OUT_RING(_3DSTATE_MAP_STATE | 6);
+ OUT_RING(0x00000003); /* map 0,1 */
+ OUT_RING(pI830->mapstate[0]);
+ OUT_RING(pI830->mapstate[1]);
+ OUT_RING(pI830->mapstate[2]);
+ OUT_RING(pI830->mapstate[3]);
+ OUT_RING(pI830->mapstate[4]);
+ OUT_RING(pI830->mapstate[5]);
+
+ OUT_RING(_3DSTATE_SAMPLER_STATE | 6);
+ OUT_RING(0x00000003); /* sampler 0,1 */
+ OUT_RING(pI830->samplerstate[0]);
+ OUT_RING(pI830->samplerstate[1]);
+ OUT_RING(pI830->samplerstate[2]);
+ OUT_RING(pI830->samplerstate[3]);
+ OUT_RING(pI830->samplerstate[4]);
+ OUT_RING(pI830->samplerstate[5]);
+ ADVANCE_LP_RING();
+ }
+ {
+ CARD32 ss2;
+
+ BEGIN_LP_RING(16);
+ OUT_RING(_3DSTATE_BUF_INFO_CMD);
+ OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
+ BUF_3D_PITCH(dst_pitch));
+ OUT_RING(BUF_3D_ADDR(dst_offset));
+
+ OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_RING(dst_format);
+
+ OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
+ I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
+ ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
+ if (pMask)
+ ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
+ else
+ ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
+ OUT_RING(ss2);
+ OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE| S4_VFMT_XY);
+ blendctl = i915_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
+ OUT_RING(0x00000000); /* Disable stencil buffer */
+ OUT_RING(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
+
+ /* draw rect is unconditional */
+ OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+ OUT_RING(0x00000000);
+ OUT_RING(0x00000000); /* ymin, xmin*/
+ OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+ DRAW_XMAX(pDst->drawable.width - 1));
+ OUT_RING(0x00000000); /* yorig, xorig (relate to color buffer?)*/
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+
+ if (dst_format == COLR_BUF_8BIT)
+ out_reg = FS_U0;
+
+ FS_BEGIN();
+
+ /* Declare the registers necessary for our program. I don't think the
+ * S then T ordering is necessary.
+ */
+ i915_fs_dcl(FS_S0);
+ if (pMask)
+ i915_fs_dcl(FS_S1);
+ i915_fs_dcl(FS_T0);
+ if (pMask)
+ i915_fs_dcl(FS_T1);
+
+ /* Load the pSrcPicture texel */
+ i915_fs_texld(FS_R0, FS_S0, FS_T0);
+ /* If the texture lacks an alpha channel, force the alpha to 1. */
+ if (PICT_FORMAT_A(pSrcPicture->format) == 0)
+ i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one());
+
+ if (!pMask) {
+ /* No mask, so move to output color */
+ i915_fs_mov(out_reg, i915_fs_operand_reg(FS_R0));
+ } else {
+ /* Load the pMaskPicture texel */
+ i915_fs_texld(FS_R1, FS_S1, FS_T1);
+ /* If the texture lacks an alpha channel, force the alpha to 1. */
+ if (PICT_FORMAT_A(pMaskPicture->format) == 0)
+ i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
+
+ /* If component alpha is active in the mask and the blend operation
+ * uses the source alpha, then we know we don't need the source
+ * value (otherwise we would have hit a fallback earlier), so we
+ * provide the source alpha (src.A * mask.X) as output color.
+ * Conversely, if CA is set and we don't need the source alpha, then
+ * we produce the source value (src.X * mask.X) and the source alpha
+ * is unused.. Otherwise, we provide the non-CA source value
+ * (src.X * mask.A).
+ */
+ if (pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format))
+ {
+ if (i915_blend_op[op].src_alpha) {
+ i915_fs_mul(out_reg, i915_fs_operand(FS_R0, W, W, W, W),
+ i915_fs_operand_reg(FS_R1));
+ } else {
+ i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0),
+ i915_fs_operand_reg(FS_R1));
+ }
+ } else {
+ i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0),
+ i915_fs_operand(FS_R1, W, W, W, W));
+ }
+ }
+ if (dst_format == COLR_BUF_8BIT)
+ i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W));
+
+ FS_END();
+
+ return TRUE;
+}
diff --git a/driver/xf86-video-intel/src/i965_render.c b/driver/xf86-video-intel/src/i965_render.c
new file mode 100644
index 000000000..ad3b53ef5
--- /dev/null
+++ b/driver/xf86-video-intel/src/i965_render.c
@@ -0,0 +1,1190 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Wang Zhenyu <zhenyu.z.wang@intel.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+
+/* bring in brw structs */
+#include "brw_defines.h"
+#include "brw_structs.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...) \
+do { \
+ DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); \
+ return FALSE; \
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) \
+do { \
+ return FALSE; \
+} while(0)
+#endif
+
+struct blendinfo {
+ Bool dst_alpha;
+ Bool src_alpha;
+ CARD32 src_blend;
+ CARD32 dst_blend;
+};
+
+struct formatinfo {
+ int fmt;
+ CARD32 card_fmt;
+};
+
+// refer vol2, 3d rasterization 3.8.1
+
+/* defined in brw_defines.h */
+static struct blendinfo i965_blend_op[] = {
+ /* Clear */
+ {0, 0, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_ZERO},
+ /* Src */
+ {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ZERO},
+ /* Dst */
+ {0, 0, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_ONE},
+ /* Over */
+ {0, 1, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_INV_SRC_ALPHA},
+ /* OverReverse */
+ {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE},
+ /* In */
+ {1, 0, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
+ /* InReverse */
+ {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_SRC_ALPHA},
+ /* Out */
+ {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO},
+ /* OutReverse */
+ {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_INV_SRC_ALPHA},
+ /* Atop */
+ {1, 1, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
+ /* AtopReverse */
+ {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA},
+ /* Xor */
+ {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA},
+ /* Add */
+ {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ONE},
+};
+
+/* FIXME: surface format defined in brw_defines.h, shared Sampling engine
+ * 1.7.2
+ */
+static struct formatinfo i965_tex_formats[] = {
+ {PICT_a8r8g8b8, BRW_SURFACEFORMAT_B8G8R8A8_UNORM },
+ {PICT_x8r8g8b8, BRW_SURFACEFORMAT_B8G8R8X8_UNORM },
+ {PICT_a8b8g8r8, BRW_SURFACEFORMAT_R8G8B8A8_UNORM },
+ {PICT_x8b8g8r8, BRW_SURFACEFORMAT_R8G8B8X8_UNORM },
+ {PICT_r5g6b5, BRW_SURFACEFORMAT_B5G6R5_UNORM },
+ {PICT_a1r5g5b5, BRW_SURFACEFORMAT_B5G5R5A1_UNORM },
+ {PICT_a8, BRW_SURFACEFORMAT_A8_UNORM },
+};
+
+static void i965_get_blend_cntl(int op, PicturePtr pMask, CARD32 dst_format,
+ CARD32 *sblend, CARD32 *dblend)
+{
+
+ *sblend = i965_blend_op[op].src_blend;
+ *dblend = i965_blend_op[op].dst_blend;
+
+ /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+ * it as always 1.
+ */
+ if (PICT_FORMAT_A(dst_format) == 0 && i965_blend_op[op].dst_alpha) {
+ if (*sblend == BRW_BLENDFACTOR_DST_ALPHA)
+ *sblend = BRW_BLENDFACTOR_ONE;
+ else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA)
+ *sblend = BRW_BLENDFACTOR_ZERO;
+ }
+
+ /* If the source alpha is being used, then we should only be in a case where
+ * the source blend factor is 0, and the source blend value is the mask
+ * channels multiplied by the source picture's alpha.
+ */
+ if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format)
+ && i965_blend_op[op].src_alpha) {
+ if (*dblend == BRW_BLENDFACTOR_SRC_ALPHA) {
+ *dblend = BRW_BLENDFACTOR_SRC_COLOR;
+ } else if (*dblend == BRW_BLENDFACTOR_INV_SRC_ALPHA) {
+ *dblend = BRW_BLENDFACTOR_INV_SRC_COLOR;
+ }
+ }
+
+}
+
+static Bool i965_get_dest_format(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+ switch (pDstPicture->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ *dst_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ break;
+ case PICT_r5g6b5:
+ *dst_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+ break;
+ case PICT_a1r5g5b5:
+ *dst_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
+ break;
+ case PICT_x1r5g5b5:
+ *dst_format = BRW_SURFACEFORMAT_B5G5R5X1_UNORM;
+ break;
+ case PICT_a8:
+ *dst_format = BRW_SURFACEFORMAT_A8_UNORM;
+ break;
+ case PICT_a4r4g4b4:
+ case PICT_x4r4g4b4:
+ *dst_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
+ break;
+ default:
+ I830FALLBACK("Unsupported dest format 0x%x\n",
+ (int)pDstPicture->format);
+ }
+
+ return TRUE;
+}
+
+static Bool i965_check_composite_texture(PicturePtr pPict, int unit)
+{
+ int w = pPict->pDrawable->width;
+ int h = pPict->pDrawable->height;
+ int i;
+
+ if ((w > 0x7ff) || (h > 0x7ff))
+ I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+ for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
+ i++)
+ {
+ if (i965_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]))
+ I830FALLBACK("Unsupported picture format 0x%x\n",
+ (int)pPict->format);
+
+ if (pPict->repeat && pPict->repeatType != RepeatNormal)
+ I830FALLBACK("extended repeat (%d) not supported\n",
+ pPict->repeatType);
+
+ if (pPict->filter != PictFilterNearest &&
+ pPict->filter != PictFilterBilinear)
+ {
+ I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+ }
+
+ return TRUE;
+}
+
+Bool
+i965_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ CARD32 tmp1;
+
+ /* Check for unsupported compositing operations. */
+ if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0]))
+ I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+
+ if (pMaskPicture && pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i965_blend_op[op].src_alpha &&
+ (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO))
+ {
+ I830FALLBACK("Component alpha not supported with source "
+ "alpha and source value blending.\n");
+ }
+ }
+
+ if (!i965_check_composite_texture(pSrcPicture, 0))
+ I830FALLBACK("Check Src picture texture\n");
+ if (pMaskPicture != NULL && !i965_check_composite_texture(pMaskPicture, 1))
+ I830FALLBACK("Check Mask picture texture\n");
+
+ if (!i965_get_dest_format(pDstPicture, &tmp1))
+ I830FALLBACK("Get Color buffer format\n");
+
+ return TRUE;
+
+}
+
+#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1)
+
+static int urb_vs_start, urb_vs_size;
+static int urb_gs_start, urb_gs_size;
+static int urb_clip_start, urb_clip_size;
+static int urb_sf_start, urb_sf_size;
+static int urb_cs_start, urb_cs_size;
+
+static struct brw_surface_state *dest_surf_state, dest_surf_state_local;
+static struct brw_surface_state *src_surf_state, src_surf_state_local;
+static struct brw_surface_state *mask_surf_state, mask_surf_state_local;
+static struct brw_sampler_state *src_sampler_state, src_sampler_state_local;
+static struct brw_sampler_state *mask_sampler_state, mask_sampler_state_local;
+static struct brw_sampler_default_color *default_color_state;
+
+static struct brw_vs_unit_state *vs_state, vs_state_local;
+static struct brw_sf_unit_state *sf_state, sf_state_local;
+static struct brw_wm_unit_state *wm_state, wm_state_local;
+static struct brw_cc_unit_state *cc_state, cc_state_local;
+static struct brw_cc_viewport *cc_viewport;
+
+static struct brw_instruction *sf_kernel;
+static struct brw_instruction *ps_kernel;
+static struct brw_instruction *sip_kernel;
+
+static CARD32 *binding_table;
+static int binding_table_entries;
+
+static int dest_surf_offset, src_surf_offset, mask_surf_offset;
+static int src_sampler_offset, mask_sampler_offset,vs_offset;
+static int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+static int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+static int wm_scratch_offset;
+static int binding_table_offset;
+static int default_color_offset;
+static int next_offset, total_state_size;
+static char *state_base;
+static int state_base_offset;
+static float *vb;
+static int vb_size = (6 * 4) * 4 ; /* 6 DWORDS per vertex - and mask*/
+
+static CARD32 src_blend, dst_blend;
+
+static const CARD32 sip_kernel_static[][4] = {
+/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */
+ { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+
+/*
+ * this program computes dA/dx and dA/dy for the texture coordinates along
+ * with the base texture coordinate. It was extracted from the Mesa driver
+ */
+
+#define SF_KERNEL_NUM_GRF 16
+#define SF_MAX_THREADS 1
+
+static const CARD32 sf_kernel_static[][4] = {
+#include "exa_sf_prog.h"
+};
+
+static const CARD32 sf_kernel_static_mask[][4] = {
+#include "exa_sf_mask_prog.h"
+};
+
+static const CARD32 sf_kernel_static_rotation[][4] = {
+#include "exa_sf_rotation_prog.h"
+};
+
+/* ps kernels */
+#define PS_KERNEL_NUM_GRF 32
+#define PS_MAX_THREADS 32
+
+static const CARD32 ps_kernel_static_nomask [][4] = {
+#include "exa_wm_nomask_prog.h"
+};
+
+static const CARD32 ps_kernel_static_maskca [][4] = {
+#include "exa_wm_maskca_prog.h"
+};
+
+static const CARD32 ps_kernel_static_maskca_srcalpha [][4] = {
+#include "exa_wm_maskca_srcalpha_prog.h"
+};
+
+static const CARD32 ps_kernel_static_masknoca [][4] = {
+#include "exa_wm_masknoca_prog.h"
+};
+
+static const CARD32 ps_kernel_static_rotation [][4] = {
+#include "exa_wm_rotation_prog.h"
+};
+
+static CARD32
+i965_get_card_format(PicturePtr pPict)
+{
+ int i;
+
+ for (i = 0; i < sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]);
+ i++)
+ {
+ if (i965_tex_formats[i].fmt == pPict->format)
+ break;
+ }
+ return i965_tex_formats[i].card_fmt;
+}
+
+static Bool
+i965_check_rotation_transform(PictTransformPtr t)
+{
+ /* XXX this is arbitrary */
+ int a, b;
+ a = xFixedToInt(t->matrix[0][1]);
+ b = xFixedToInt(t->matrix[1][0]);
+ if (a == -1 && b == 1)
+ return TRUE;
+ else if (a == 1 && b == -1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+Bool
+i965_prepare_composite(int op, PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 src_offset, src_pitch, src_tile_format = 0, src_tiled = 0;
+ CARD32 mask_offset = 0, mask_pitch = 0, mask_tile_format = 0,
+ mask_tiled = 0;
+ CARD32 dst_format, dst_offset, dst_pitch, dst_tile_format = 0,
+ dst_tiled = 0;
+ Bool rotation_program = FALSE;
+
+ IntelEmitInvarientState(pScrn);
+ *pI830->last_3d = LAST_3D_RENDER;
+
+ src_offset = intel_get_pixmap_offset(pSrc);
+ src_pitch = intel_get_pixmap_pitch(pSrc);
+ if (i830_pixmap_tiled(pSrc)) {
+ src_tiled = 1;
+ src_tile_format = 0; /* Tiled X */
+ }
+ dst_offset = intel_get_pixmap_offset(pDst);
+ dst_pitch = intel_get_pixmap_pitch(pDst);
+ if (i830_pixmap_tiled(pDst)) {
+ dst_tiled = 1;
+ dst_tile_format = 0; /* Tiled X */
+ }
+ if (pMask) {
+ mask_offset = intel_get_pixmap_offset(pMask);
+ mask_pitch = intel_get_pixmap_pitch(pMask);
+ if (i830_pixmap_tiled(pMask)) {
+ mask_tiled = 1;
+ mask_tile_format = 0; /* Tiled X */
+ }
+ }
+ pI830->scale_units[0][0] = pSrc->drawable.width;
+ pI830->scale_units[0][1] = pSrc->drawable.height;
+
+ pI830->transform[0] = pSrcPicture->transform;
+
+ if (!pMask) {
+ pI830->transform[1] = NULL;
+ pI830->scale_units[1][0] = -1;
+ pI830->scale_units[1][1] = -1;
+ if (pI830->transform[0] &&
+ i965_check_rotation_transform(pI830->transform[0]))
+ rotation_program = TRUE;
+ } else {
+ pI830->transform[1] = pMaskPicture->transform;
+ if (pI830->transform[1])
+ I830FALLBACK("i965 mask transform not implemented!\n");
+ pI830->scale_units[1][0] = pMask->drawable.width;
+ pI830->scale_units[1][1] = pMask->drawable.height;
+ }
+
+ /* setup 3d pipeline state */
+
+ binding_table_entries = 2; /* default no mask */
+
+ /* Set up our layout of state in framebuffer. First the general state: */
+ next_offset = 0;
+ vs_offset = ALIGN(next_offset, 64);
+ next_offset = vs_offset + sizeof(*vs_state);
+
+ sf_offset = ALIGN(next_offset, 32);
+ next_offset = sf_offset + sizeof(*sf_state);
+
+ wm_offset = ALIGN(next_offset, 32);
+ next_offset = wm_offset + sizeof(*wm_state);
+
+ wm_scratch_offset = ALIGN(next_offset, 1024);
+ next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+
+ cc_offset = ALIGN(next_offset, 32);
+ next_offset = cc_offset + sizeof(*cc_state);
+
+ /* keep current sf_kernel, which will send one setup urb entry to
+ * PS kernel
+ */
+ sf_kernel_offset = ALIGN(next_offset, 64);
+ if (pMask)
+ next_offset = sf_kernel_offset + sizeof (sf_kernel_static_mask);
+ else if (rotation_program)
+ next_offset = sf_kernel_offset + sizeof (sf_kernel_static_rotation);
+ else
+ next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+
+ ps_kernel_offset = ALIGN(next_offset, 64);
+ if (pMask) {
+ if (pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ if (i965_blend_op[op].src_alpha) {
+ next_offset = ps_kernel_offset +
+ sizeof(ps_kernel_static_maskca_srcalpha);
+ } else {
+ next_offset = ps_kernel_offset +
+ sizeof(ps_kernel_static_maskca);
+ }
+ } else
+ next_offset = ps_kernel_offset +
+ sizeof(ps_kernel_static_masknoca);
+ } else if (rotation_program) {
+ next_offset = ps_kernel_offset + sizeof (ps_kernel_static_rotation);
+ } else {
+ next_offset = ps_kernel_offset + sizeof (ps_kernel_static_nomask);
+ }
+
+ sip_kernel_offset = ALIGN(next_offset, 64);
+ next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+
+ /* needed? */
+ cc_viewport_offset = ALIGN(next_offset, 32);
+ next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+ /* for texture sampler */
+ src_sampler_offset = ALIGN(next_offset, 32);
+ next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+ if (pMask) {
+ mask_sampler_offset = ALIGN(next_offset, 32);
+ next_offset = mask_sampler_offset + sizeof(*mask_sampler_state);
+ }
+ /* Align VB to native size of elements, for safety */
+ vb_offset = ALIGN(next_offset, 32);
+ next_offset = vb_offset + vb_size;
+
+ /* And then the general state: */
+ dest_surf_offset = ALIGN(next_offset, 32);
+ next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+
+ src_surf_offset = ALIGN(next_offset, 32);
+ next_offset = src_surf_offset + sizeof(*src_surf_state);
+
+ if (pMask) {
+ mask_surf_offset = ALIGN(next_offset, 32);
+ next_offset = mask_surf_offset + sizeof(*mask_surf_state);
+ binding_table_entries = 3;
+ }
+
+ binding_table_offset = ALIGN(next_offset, 32);
+ next_offset = binding_table_offset + (binding_table_entries * 4);
+
+ default_color_offset = ALIGN(next_offset, 32);
+ next_offset = default_color_offset + sizeof(*default_color_state);
+
+ total_state_size = next_offset;
+ assert(total_state_size < pI830->exa_965_state->size);
+
+ state_base_offset = pI830->exa_965_state->offset;
+ state_base_offset = ALIGN(state_base_offset, 64);
+ state_base = (char *)(pI830->FbBase + state_base_offset);
+
+ sf_kernel = (void *)(state_base + sf_kernel_offset);
+ ps_kernel = (void *)(state_base + ps_kernel_offset);
+ sip_kernel = (void *)(state_base + sip_kernel_offset);
+
+ cc_viewport = (void *)(state_base + cc_viewport_offset);
+
+ binding_table = (void *)(state_base + binding_table_offset);
+
+ vb = (void *)(state_base + vb_offset);
+
+ default_color_state = (void*)(state_base + default_color_offset);
+
+ /* Set up a default static partitioning of the URB, which is supposed to
+ * allow anything we would want to do, at potentially lower performance.
+ */
+#define URB_CS_ENTRY_SIZE 0
+#define URB_CS_ENTRIES 0
+
+#define URB_VS_ENTRY_SIZE 1 // each 512-bit row
+#define URB_VS_ENTRIES 8 // we needs at least 8 entries
+
+#define URB_GS_ENTRY_SIZE 0
+#define URB_GS_ENTRIES 0
+
+#define URB_CLIP_ENTRY_SIZE 0
+#define URB_CLIP_ENTRIES 0
+
+#define URB_SF_ENTRY_SIZE 2
+#define URB_SF_ENTRIES 1
+
+ urb_vs_start = 0;
+ urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+ urb_gs_start = urb_vs_start + urb_vs_size;
+ urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+ urb_clip_start = urb_gs_start + urb_gs_size;
+ urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+ urb_sf_start = urb_clip_start + urb_clip_size;
+ urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+ urb_cs_start = urb_sf_start + urb_sf_size;
+ urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+ /* Because we only have a single static buffer for our state currently,
+ * we have to sync before updating it every time.
+ */
+ i830WaitSync(pScrn);
+
+ memset (cc_viewport, 0, sizeof (*cc_viewport));
+ cc_viewport->min_depth = -1.e35;
+ cc_viewport->max_depth = 1.e35;
+
+ /* Color calculator state */
+ cc_state = &cc_state_local;
+ memset(cc_state, 0, sizeof(*cc_state));
+ cc_state->cc0.stencil_enable = 0; /* disable stencil */
+ cc_state->cc2.depth_test = 0; /* disable depth test */
+ cc_state->cc2.logicop_enable = 0; /* disable logic op */
+ cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */
+ cc_state->cc3.blend_enable = 1; /* enable color blend */
+ cc_state->cc3.alpha_test = 0; /* disable alpha test */
+ cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
+ cc_viewport_offset) >> 5;
+ cc_state->cc5.dither_enable = 0; /* disable dither */
+ cc_state->cc5.logicop_func = 0xc; /* COPY */
+ cc_state->cc5.statistics_enable = 1;
+ cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+ i965_get_blend_cntl(op, pMaskPicture, pDstPicture->format,
+ &src_blend, &dst_blend);
+ /* XXX: alpha blend factor should be same as color, but check
+ * for CA case in future
+ */
+ cc_state->cc5.ia_src_blend_factor = src_blend;
+ cc_state->cc5.ia_dest_blend_factor = dst_blend;
+ cc_state->cc6.blend_function = BRW_BLENDFUNCTION_ADD;
+ cc_state->cc6.src_blend_factor = src_blend;
+ cc_state->cc6.dest_blend_factor = dst_blend;
+ cc_state->cc6.clamp_post_alpha_blend = 1;
+ cc_state->cc6.clamp_pre_alpha_blend = 1;
+ cc_state->cc6.clamp_range = 0; /* clamp range [0,1] */
+
+ cc_state = (void *)(state_base + cc_offset);
+ memcpy (cc_state, &cc_state_local, sizeof (cc_state_local));
+
+ /* Upload system kernel */
+ memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+
+ /* Set up the state buffer for the destination surface */
+ dest_surf_state = &dest_surf_state_local;
+ memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+ dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+ dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+ i965_get_dest_format(pDstPicture, &dst_format);
+ dest_surf_state->ss0.surface_format = dst_format;
+
+ dest_surf_state->ss0.writedisable_alpha = 0;
+ dest_surf_state->ss0.writedisable_red = 0;
+ dest_surf_state->ss0.writedisable_green = 0;
+ dest_surf_state->ss0.writedisable_blue = 0;
+ dest_surf_state->ss0.color_blend = 1;
+ dest_surf_state->ss0.vert_line_stride = 0;
+ dest_surf_state->ss0.vert_line_stride_ofs = 0;
+ dest_surf_state->ss0.mipmap_layout_mode = 0;
+ dest_surf_state->ss0.render_cache_read_mode = 0;
+
+ dest_surf_state->ss1.base_addr = dst_offset;
+ dest_surf_state->ss2.height = pDst->drawable.height - 1;
+ dest_surf_state->ss2.width = pDst->drawable.width - 1;
+ dest_surf_state->ss2.mip_count = 0;
+ dest_surf_state->ss2.render_target_rotation = 0;
+ dest_surf_state->ss3.pitch = dst_pitch - 1;
+ dest_surf_state->ss3.tile_walk = dst_tile_format;
+ dest_surf_state->ss3.tiled_surface = dst_tiled;
+
+ dest_surf_state = (void *)(state_base + dest_surf_offset);
+ memcpy (dest_surf_state, &dest_surf_state_local, sizeof (dest_surf_state_local));
+
+ /* Set up the source surface state buffer */
+ src_surf_state = &src_surf_state_local;
+ memset(src_surf_state, 0, sizeof(*src_surf_state));
+ src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+ src_surf_state->ss0.surface_format = i965_get_card_format(pSrcPicture);
+
+ src_surf_state->ss0.writedisable_alpha = 0;
+ src_surf_state->ss0.writedisable_red = 0;
+ src_surf_state->ss0.writedisable_green = 0;
+ src_surf_state->ss0.writedisable_blue = 0;
+ src_surf_state->ss0.color_blend = 1;
+ src_surf_state->ss0.vert_line_stride = 0;
+ src_surf_state->ss0.vert_line_stride_ofs = 0;
+ src_surf_state->ss0.mipmap_layout_mode = 0;
+ src_surf_state->ss0.render_cache_read_mode = 0;
+
+ src_surf_state->ss1.base_addr = src_offset;
+ src_surf_state->ss2.width = pSrc->drawable.width - 1;
+ src_surf_state->ss2.height = pSrc->drawable.height - 1;
+ src_surf_state->ss2.mip_count = 0;
+ src_surf_state->ss2.render_target_rotation = 0;
+ src_surf_state->ss3.pitch = src_pitch - 1;
+ src_surf_state->ss3.tile_walk = src_tile_format;
+ src_surf_state->ss3.tiled_surface = src_tiled;
+
+ src_surf_state = (void *)(state_base + src_surf_offset);
+ memcpy (src_surf_state, &src_surf_state_local, sizeof (src_surf_state_local));
+
+ /* setup mask surface */
+ if (pMask) {
+ mask_surf_state = &mask_surf_state_local;
+ memset(mask_surf_state, 0, sizeof(*mask_surf_state));
+ mask_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+ mask_surf_state->ss0.surface_format =
+ i965_get_card_format(pMaskPicture);
+
+ mask_surf_state->ss0.writedisable_alpha = 0;
+ mask_surf_state->ss0.writedisable_red = 0;
+ mask_surf_state->ss0.writedisable_green = 0;
+ mask_surf_state->ss0.writedisable_blue = 0;
+ mask_surf_state->ss0.color_blend = 1;
+ mask_surf_state->ss0.vert_line_stride = 0;
+ mask_surf_state->ss0.vert_line_stride_ofs = 0;
+ mask_surf_state->ss0.mipmap_layout_mode = 0;
+ mask_surf_state->ss0.render_cache_read_mode = 0;
+
+ mask_surf_state->ss1.base_addr = mask_offset;
+ mask_surf_state->ss2.width = pMask->drawable.width - 1;
+ mask_surf_state->ss2.height = pMask->drawable.height - 1;
+ mask_surf_state->ss2.mip_count = 0;
+ mask_surf_state->ss2.render_target_rotation = 0;
+ mask_surf_state->ss3.pitch = mask_pitch - 1;
+ mask_surf_state->ss3.tile_walk = mask_tile_format;
+ mask_surf_state->ss3.tiled_surface = mask_tiled;
+
+ mask_surf_state = (void *)(state_base + mask_surf_offset);
+ memcpy (mask_surf_state, &mask_surf_state_local, sizeof (mask_surf_state_local));
+ }
+
+ /* Set up a binding table for our surfaces. Only the PS will use it */
+ binding_table[0] = state_base_offset + dest_surf_offset;
+ binding_table[1] = state_base_offset + src_surf_offset;
+ if (pMask)
+ binding_table[2] = state_base_offset + mask_surf_offset;
+
+ /* PS kernel use this sampler */
+ src_sampler_state = &src_sampler_state_local;
+ memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+ src_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+ switch(pSrcPicture->filter) {
+ case PictFilterNearest:
+ src_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+ src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+ break;
+ case PictFilterBilinear:
+ src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+ src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+ break;
+ default:
+ I830FALLBACK("Bad filter 0x%x\n", pSrcPicture->filter);
+ }
+
+ memset(default_color_state, 0, sizeof(*default_color_state));
+ default_color_state->color[0] = 0.0; /* R */
+ default_color_state->color[1] = 0.0; /* G */
+ default_color_state->color[2] = 0.0; /* B */
+ default_color_state->color[3] = 0.0; /* A */
+
+ src_sampler_state->ss0.default_color_mode = 0; /* GL mode */
+
+ if (!pSrcPicture->repeat) {
+ src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+ src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+ src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP_BORDER;
+ src_sampler_state->ss2.default_color_pointer =
+ (state_base_offset + default_color_offset) >> 5;
+ } else {
+ src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ }
+ src_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+
+ src_sampler_state = (void *)(state_base + src_sampler_offset);
+ memcpy (src_sampler_state, &src_sampler_state_local, sizeof (src_sampler_state_local));
+
+ if (pMask) {
+ mask_sampler_state = &mask_sampler_state_local;
+ memset(mask_sampler_state, 0, sizeof(*mask_sampler_state));
+ mask_sampler_state->ss0.lod_preclamp = 1; /* GL mode */
+ switch(pMaskPicture->filter) {
+ case PictFilterNearest:
+ mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+ mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+ break;
+ case PictFilterBilinear:
+ mask_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+ mask_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+ break;
+ default:
+ I830FALLBACK("Bad filter 0x%x\n", pMaskPicture->filter);
+ }
+
+ if (!pMaskPicture->repeat) {
+ mask_sampler_state->ss1.r_wrap_mode =
+ BRW_TEXCOORDMODE_CLAMP_BORDER;
+ mask_sampler_state->ss1.s_wrap_mode =
+ BRW_TEXCOORDMODE_CLAMP_BORDER;
+ mask_sampler_state->ss1.t_wrap_mode =
+ BRW_TEXCOORDMODE_CLAMP_BORDER;
+ mask_sampler_state->ss2.default_color_pointer =
+ (state_base_offset + default_color_offset)>>5;
+ } else {
+ mask_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ mask_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ mask_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
+ }
+ mask_sampler_state->ss3.chroma_key_enable = 0; /* disable chromakey */
+
+ mask_sampler_state = (void *)(state_base + mask_sampler_offset);
+ memcpy (mask_sampler_state, &mask_sampler_state_local, sizeof (mask_sampler_state_local));
+ }
+
+ /* Set up the vertex shader to be disabled (passthrough) */
+ vs_state = &vs_state_local;
+ memset(vs_state, 0, sizeof(*vs_state));
+ vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+ vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+ vs_state->vs6.vs_enable = 0;
+ vs_state->vs6.vert_cache_disable = 1;
+
+ vs_state = (void *)(state_base + vs_offset);
+ memcpy (vs_state, &vs_state_local, sizeof (vs_state_local));
+
+ /* Set up the SF kernel to do coord interp: for each attribute,
+ * calculate dA/dx and dA/dy. Hand these interpolation coefficients
+ * back to SF which then hands pixels off to WM.
+ */
+ if (pMask)
+ memcpy(sf_kernel, sf_kernel_static_mask,
+ sizeof (sf_kernel_static_mask));
+ else if (rotation_program)
+ memcpy(sf_kernel, sf_kernel_static_rotation,
+ sizeof (sf_kernel_static_rotation));
+ else
+ memcpy(sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+
+ sf_state = &sf_state_local;
+ memset(sf_state, 0, sizeof(*sf_state));
+ sf_state->thread0.kernel_start_pointer =
+ (state_base_offset + sf_kernel_offset) >> 6;
+ sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+ sf_state->sf1.single_program_flow = 1;
+ sf_state->sf1.binding_table_entry_count = 0;
+ sf_state->sf1.thread_priority = 0;
+ sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+ sf_state->sf1.illegal_op_exception_enable = 1;
+ sf_state->sf1.mask_stack_exception_enable = 1;
+ sf_state->sf1.sw_exception_enable = 1;
+ sf_state->thread2.per_thread_scratch_space = 0;
+ /* scratch space is not used in our kernel */
+ sf_state->thread2.scratch_space_base_pointer = 0;
+ sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+ sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+ sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+ /* don't smash vertex header, read start from dw8 */
+ sf_state->thread3.urb_entry_read_offset = 1;
+ sf_state->thread3.dispatch_grf_start_reg = 3;
+ sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+ sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+ sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+ sf_state->thread4.stats_enable = 1;
+ sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+ sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+ sf_state->sf6.scissor = 0;
+ sf_state->sf7.trifan_pv = 2;
+ sf_state->sf6.dest_org_vbias = 0x8;
+ sf_state->sf6.dest_org_hbias = 0x8;
+
+ sf_state = (void *)(state_base + sf_offset);
+ memcpy (sf_state, &sf_state_local, sizeof (sf_state_local));
+
+ /* Set up the PS kernel (dispatched by WM) */
+ if (pMask) {
+ if (pMaskPicture->componentAlpha &&
+ PICT_FORMAT_RGB(pMaskPicture->format)) {
+ if (i965_blend_op[op].src_alpha)
+ memcpy(ps_kernel, ps_kernel_static_maskca_srcalpha,
+ sizeof (ps_kernel_static_maskca_srcalpha));
+ else
+ memcpy(ps_kernel, ps_kernel_static_maskca,
+ sizeof (ps_kernel_static_maskca));
+ } else
+ memcpy(ps_kernel, ps_kernel_static_masknoca,
+ sizeof (ps_kernel_static_masknoca));
+ } else if (rotation_program) {
+ memcpy(ps_kernel, ps_kernel_static_rotation,
+ sizeof (ps_kernel_static_rotation));
+ } else {
+ memcpy(ps_kernel, ps_kernel_static_nomask,
+ sizeof (ps_kernel_static_nomask));
+ }
+
+ wm_state = &wm_state_local;
+ memset(wm_state, 0, sizeof (*wm_state));
+ wm_state->thread0.kernel_start_pointer =
+ (state_base_offset + ps_kernel_offset) >> 6;
+ wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+ wm_state->thread1.single_program_flow = 1;
+ if (!pMask)
+ wm_state->thread1.binding_table_entry_count = 2; /* 1 tex and fb */
+ else
+ wm_state->thread1.binding_table_entry_count = 3; /* 2 tex and fb */
+
+ wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+ wm_scratch_offset)>>10;
+ wm_state->thread2.per_thread_scratch_space = 0;
+ wm_state->thread3.const_urb_entry_read_length = 0;
+ wm_state->thread3.const_urb_entry_read_offset = 0;
+ /* Each pair of attributes (src/mask coords) is one URB entry */
+ if (pMask)
+ wm_state->thread3.urb_entry_read_length = 2;
+ else
+ wm_state->thread3.urb_entry_read_length = 1;
+ wm_state->thread3.urb_entry_read_offset = 0;
+ /* wm kernel use urb from 3, see wm_program in compiler module */
+ wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
+
+ wm_state->wm4.stats_enable = 1; /* statistic */
+ wm_state->wm4.sampler_state_pointer = (state_base_offset +
+ src_sampler_offset) >> 5;
+ wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+ wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+ wm_state->wm5.thread_dispatch_enable = 1;
+ /* just use 16-pixel dispatch (4 subspans), don't need to change kernel
+ * start point
+ */
+ wm_state->wm5.enable_16_pix = 1;
+ wm_state->wm5.enable_8_pix = 0;
+ wm_state->wm5.early_depth_test = 1;
+
+ wm_state = (void *)(state_base + wm_offset);
+ memcpy (wm_state, &wm_state_local, sizeof (wm_state_local));
+
+ /* Begin the long sequence of commands needed to set up the 3D
+ * rendering pipe
+ */
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_FLUSH |
+ MI_STATE_INSTRUCTION_CACHE_FLUSH |
+ BRW_MI_GLOBAL_SNAPSHOT_RESET);
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+ {
+ BEGIN_LP_RING(12);
+
+ /* Match Mesa driver setup */
+ OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+ OUT_RING(BRW_CS_URB_STATE | 0);
+ OUT_RING((0 << 4) | /* URB Entry Allocation Size */
+ (0 << 0)); /* Number of URB Entries */
+
+ /* Zero out the two base address registers so all offsets are
+ * absolute.
+ */
+ OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */
+ /* general state max addr, disabled */
+ OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+ /* media object state max addr, disabled */
+ OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+
+ /* Set system instruction pointer */
+ OUT_RING(BRW_STATE_SIP | 0);
+ OUT_RING(state_base_offset + sip_kernel_offset);
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+ {
+ BEGIN_LP_RING(26);
+ /* Pipe control */
+ OUT_RING(BRW_PIPE_CONTROL |
+ BRW_PIPE_CONTROL_NOWRITE |
+ BRW_PIPE_CONTROL_IS_FLUSH |
+ 2);
+ OUT_RING(0); /* Destination address */
+ OUT_RING(0); /* Immediate data low DW */
+ OUT_RING(0); /* Immediate data high DW */
+
+ /* Binding table pointers */
+ OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+ OUT_RING(0); /* vs */
+ OUT_RING(0); /* gs */
+ OUT_RING(0); /* clip */
+ OUT_RING(0); /* sf */
+ /* Only the PS uses the binding table */
+ OUT_RING(state_base_offset + binding_table_offset); /* ps */
+
+ /* The drawing rectangle clipping is always on. Set it to values that
+ * shouldn't do any clipping.
+ */
+ OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */
+ OUT_RING(0x00000000); /* ymin, xmin */
+ OUT_RING(DRAW_YMAX(pDst->drawable.height - 1) |
+ DRAW_XMAX(pDst->drawable.width - 1)); /* ymax, xmax */
+ OUT_RING(0x00000000); /* yorigin, xorigin */
+
+ /* skip the depth buffer */
+ /* skip the polygon stipple */
+ /* skip the polygon stipple offset */
+ /* skip the line stipple */
+
+ /* Set the pointers to the 3d pipeline state */
+ OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+ OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */
+ OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */
+ OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */
+ OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */
+ OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */
+ OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */
+
+ /* URB fence */
+ OUT_RING(BRW_URB_FENCE |
+ UF0_CS_REALLOC |
+ UF0_SF_REALLOC |
+ UF0_CLIP_REALLOC |
+ UF0_GS_REALLOC |
+ UF0_VS_REALLOC |
+ 1);
+ OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+ ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+ ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+ OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+ ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+ /* Constant buffer state */
+ OUT_RING(BRW_CS_URB_STATE | 0);
+ OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
+ (URB_CS_ENTRIES << 0));
+ ADVANCE_LP_RING();
+ }
+ {
+ int nelem = pMask ? 3: 2;
+ BEGIN_LP_RING(pMask?12:10);
+ /* Set up the pointer to our vertex buffer */
+ OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 3);
+ OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+ VB0_VERTEXDATA |
+ ((4 * 2 * nelem) << VB0_BUFFER_PITCH_SHIFT));
+ OUT_RING(state_base_offset + vb_offset);
+ OUT_RING(3);
+ OUT_RING(0); // ignore for VERTEXDATA, but still there
+
+ /* Set up our vertex elements, sourced from the single vertex buffer.
+ */
+ OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1));
+ /* vertex coordinates */
+ OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (0 << VE0_OFFSET_SHIFT));
+ OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+ (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+ /* u0, v0 */
+ OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (8 << VE0_OFFSET_SHIFT)); /* offset vb in bytes */
+ OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
+ (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
+ (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
+ /* u1, v1 */
+ if (pMask) {
+ OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (16 << VE0_OFFSET_SHIFT));
+ OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) |
+ (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) |
+ (10 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+ }
+
+ ADVANCE_LP_RING();
+ }
+
+#ifdef I830DEBUG
+ ErrorF("try to sync to show any errors...");
+ I830Sync(pScrn);
+#endif
+ return TRUE;
+}
+
+void
+i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int w, int h)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ Bool has_mask;
+ float src_x[3], src_y[3], mask_x[3], mask_y[3];
+ int i;
+
+ i830_get_transformed_coordinates(srcX, srcY,
+ pI830->transform[0],
+ &src_x[0], &src_y[0]);
+ i830_get_transformed_coordinates(srcX, srcY + h,
+ pI830->transform[0],
+ &src_x[1], &src_y[1]);
+ i830_get_transformed_coordinates(srcX + w, srcY + h,
+ pI830->transform[0],
+ &src_x[2], &src_y[2]);
+
+ if (pI830->scale_units[1][0] == -1 || pI830->scale_units[1][1] == -1) {
+ has_mask = FALSE;
+ } else {
+ has_mask = TRUE;
+ i830_get_transformed_coordinates(maskX, maskY,
+ pI830->transform[1],
+ &mask_x[0], &mask_y[0]);
+ i830_get_transformed_coordinates(maskX, maskY + h,
+ pI830->transform[1],
+ &mask_x[1], &mask_y[1]);
+ i830_get_transformed_coordinates(maskX + w, maskY + h,
+ pI830->transform[1],
+ &mask_x[2], &mask_y[2]);
+ }
+
+ /* Wait for any existing composite rectangles to land before we overwrite
+ * the VB with the next one.
+ */
+ i830WaitSync(pScrn);
+
+ i = 0;
+ /* rect (x2,y2) */
+ vb[i++] = (float)(dstX + w);
+ vb[i++] = (float)(dstY + h);
+ vb[i++] = src_x[2] / pI830->scale_units[0][0];
+ vb[i++] = src_y[2] / pI830->scale_units[0][1];
+ if (has_mask) {
+ vb[i++] = mask_x[2] / pI830->scale_units[1][0];
+ vb[i++] = mask_y[2] / pI830->scale_units[1][1];
+ }
+
+ /* rect (x1,y2) */
+ vb[i++] = (float)dstX;
+ vb[i++] = (float)(dstY + h);
+ vb[i++] = src_x[1] / pI830->scale_units[0][0];
+ vb[i++] = src_y[1] / pI830->scale_units[0][1];
+ if (has_mask) {
+ vb[i++] = mask_x[1] / pI830->scale_units[1][0];
+ vb[i++] = mask_y[1] / pI830->scale_units[1][1];
+ }
+
+ /* rect (x1,y1) */
+ vb[i++] = (float)dstX;
+ vb[i++] = (float)dstY;
+ vb[i++] = src_x[0] / pI830->scale_units[0][0];
+ vb[i++] = src_y[0] / pI830->scale_units[0][1];
+ if (has_mask) {
+ vb[i++] = mask_x[0] / pI830->scale_units[1][0];
+ vb[i++] = mask_y[0] / pI830->scale_units[1][1];
+ }
+
+ {
+ BEGIN_LP_RING(6);
+ OUT_RING(BRW_3DPRIMITIVE |
+ BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+ (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) |
+ (0 << 9) | /* CTG - indirect vertex count */
+ 4);
+ OUT_RING(3); /* vertex count per instance */
+ OUT_RING(0); /* start vertex offset */
+ OUT_RING(1); /* single instance */
+ OUT_RING(0); /* start instance location */
+ OUT_RING(0); /* index buffer offset, ignored */
+ ADVANCE_LP_RING();
+ }
+#ifdef I830DEBUG
+ ErrorF("sync after 3dprimitive");
+ I830Sync(pScrn);
+#endif
+ /* we must be sure that the pipeline is flushed before next exa draw,
+ because that will be new state, binding state and instructions*/
+ {
+ BEGIN_LP_RING(4);
+ OUT_RING(BRW_PIPE_CONTROL |
+ BRW_PIPE_CONTROL_NOWRITE |
+ BRW_PIPE_CONTROL_WC_FLUSH |
+ BRW_PIPE_CONTROL_IS_FLUSH |
+ (1 << 10) | /* XXX texture cache flush for BLC/CTG */
+ 2);
+ OUT_RING(0); /* Destination address */
+ OUT_RING(0); /* Immediate data low DW */
+ OUT_RING(0); /* Immediate data high DW */
+ ADVANCE_LP_RING();
+ }
+
+ /* Mark sync so we can wait for it before setting up the VB on the next
+ * rectangle.
+ */
+ i830MarkSync(pScrn);
+}
diff --git a/driver/xf86-video-intel/src/i965_video.c b/driver/xf86-video-intel/src/i965_video.c
new file mode 100644
index 000000000..035727034
--- /dev/null
+++ b/driver/xf86-video-intel/src/i965_video.c
@@ -0,0 +1,855 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ * Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86xv.h"
+#include "fourcc.h"
+
+#include "i830.h"
+#include "i830_video.h"
+#include "brw_defines.h"
+#include "brw_structs.h"
+#include <string.h>
+
+/* Make assert() work. */
+#undef NDEBUG
+#include <assert.h>
+
+static const CARD32 sip_kernel_static[][4] = {
+/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */
+ { 0x00000030, 0x20000108, 0x00001220, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+/* nop (4) g0<1>UD { align1 + } */
+ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 },
+};
+
+/*
+ * this program computes dA/dx and dA/dy for the texture coordinates along
+ * with the base texture coordinate. It was extracted from the Mesa driver.
+ * It uses about 10 GRF registers.
+ */
+
+#define SF_KERNEL_NUM_GRF 16
+#define SF_MAX_THREADS 1
+
+static const CARD32 sf_kernel_static[][4] = {
+#include "sf_prog.h"
+};
+
+/*
+ * Ok, this kernel picks up the required data flow values in g0 and g1
+ * and passes those along in m0 and m1. In m2-m9, it sticks constant
+ * values (bright pink).
+ */
+
+/* Our PS kernel uses less than 32 GRF registers (about 20) */
+#define PS_KERNEL_NUM_GRF 32
+#define PS_MAX_THREADS 32
+
+#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1)
+
+static const CARD32 ps_kernel_static[][4] = {
+#include "wm_prog.h"
+};
+
+#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define WM_BINDING_TABLE_ENTRIES 2
+
+static CARD32 float_to_uint (float f) {
+ union {CARD32 i; float f;} x;
+ x.f = f;
+ return x.i;
+}
+
+#if 0
+static struct {
+ CARD32 svg_ctl;
+ char *name;
+} svg_ctl_bits[] = {
+ { BRW_SVG_CTL_GS_BA, "General State Base Address" },
+ { BRW_SVG_CTL_SS_BA, "Surface State Base Address" },
+ { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" },
+ { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" },
+ { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" },
+ { BRW_SVG_CTL_SIP, "System Instruction Pointer" },
+ { 0, 0 },
+};
+
+static void
+brw_debug (ScrnInfoPtr pScrn, char *when)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int i;
+ CARD32 v;
+
+ I830Sync (pScrn);
+ ErrorF("brw_debug: %s\n", when);
+ for (i = 0; svg_ctl_bits[i].name; i++) {
+ OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl);
+ v = INREG(BRW_SVG_RDATA);
+ ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v);
+ }
+}
+#endif
+
+#define WATCH_SF 0
+#define WATCH_WIZ 0
+#define WATCH_STATS 0
+
+void
+I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
+ RegionPtr dstRegion,
+ short width, short height, int video_pitch,
+ int x1, int y1, int x2, int y2,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ PixmapPtr pPixmap)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ BoxPtr pbox;
+ int nbox, dxo, dyo, pix_xoff, pix_yoff;
+ int urb_vs_start, urb_vs_size;
+ int urb_gs_start, urb_gs_size;
+ int urb_clip_start, urb_clip_size;
+ int urb_sf_start, urb_sf_size;
+ int urb_cs_start, urb_cs_size;
+ struct brw_surface_state *dest_surf_state;
+ struct brw_surface_state *src_surf_state;
+ struct brw_sampler_state *src_sampler_state;
+ struct brw_vs_unit_state *vs_state;
+ struct brw_sf_unit_state *sf_state;
+ struct brw_wm_unit_state *wm_state;
+ struct brw_cc_unit_state *cc_state;
+ struct brw_cc_viewport *cc_viewport;
+ struct brw_instruction *sf_kernel;
+ struct brw_instruction *ps_kernel;
+ struct brw_instruction *sip_kernel;
+ float *vb;
+ float src_scale_x, src_scale_y;
+ CARD32 *binding_table;
+ Bool first_output = TRUE;
+ int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset;
+ int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset;
+ int wm_scratch_offset;
+ int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset;
+ int binding_table_offset;
+ int next_offset, total_state_size;
+ int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */
+ char *state_base;
+ int state_base_offset;
+
+#if 0
+ ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height,
+ video_pitch);
+#endif
+
+ /* enable debug */
+ OUTREG (INST_PM,
+ (1 << (16 + 4)) |
+ (1 << 4));
+#if 0
+ ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM));
+#endif
+
+ assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2));
+
+ IntelEmitInvarientState(pScrn);
+ *pI830->last_3d = LAST_3D_VIDEO;
+
+ next_offset = 0;
+
+ /* Set up our layout of state in framebuffer. First the general state: */
+ vs_offset = ALIGN(next_offset, 64);
+ next_offset = vs_offset + sizeof(*vs_state);
+ sf_offset = ALIGN(next_offset, 32);
+ next_offset = sf_offset + sizeof(*sf_state);
+ wm_offset = ALIGN(next_offset, 32);
+ next_offset = wm_offset + sizeof(*wm_state);
+ wm_scratch_offset = ALIGN(next_offset, 1024);
+ next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS;
+ cc_offset = ALIGN(next_offset, 32);
+ next_offset = cc_offset + sizeof(*cc_state);
+
+ sf_kernel_offset = ALIGN(next_offset, 64);
+ next_offset = sf_kernel_offset + sizeof (sf_kernel_static);
+ ps_kernel_offset = ALIGN(next_offset, 64);
+ next_offset = ps_kernel_offset + sizeof (ps_kernel_static);
+ sip_kernel_offset = ALIGN(next_offset, 64);
+ next_offset = sip_kernel_offset + sizeof (sip_kernel_static);
+ cc_viewport_offset = ALIGN(next_offset, 32);
+ next_offset = cc_viewport_offset + sizeof(*cc_viewport);
+
+ src_sampler_offset = ALIGN(next_offset, 32);
+ next_offset = src_sampler_offset + sizeof(*src_sampler_state);
+
+ /* Align VB to native size of elements, for safety */
+ vb_offset = ALIGN(next_offset, 8);
+ next_offset = vb_offset + vb_size;
+
+ /* And then the general state: */
+ dest_surf_offset = ALIGN(next_offset, 32);
+ next_offset = dest_surf_offset + sizeof(*dest_surf_state);
+ src_surf_offset = ALIGN(next_offset, 32);
+ next_offset = src_surf_offset + sizeof(*src_surf_state);
+ binding_table_offset = ALIGN(next_offset, 32);
+ next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4);
+
+ /* Allocate an area in framebuffer for our state layout we just set up */
+ total_state_size = next_offset;
+ assert (total_state_size < BRW_LINEAR_EXTRA);
+
+ /*
+ * Use the extra space allocated at the end of the Xv buffer
+ */
+ state_base_offset = pPriv->extra_offset;
+ state_base_offset = ALIGN(state_base_offset, 64);
+
+ state_base = (char *)(pI830->FbBase + state_base_offset);
+ /* Set up our pointers to state structures in framebuffer. It would
+ * probably be a good idea to fill these structures out in system memory
+ * and then dump them there, instead.
+ */
+ vs_state = (void *)(state_base + vs_offset);
+ sf_state = (void *)(state_base + sf_offset);
+ wm_state = (void *)(state_base + wm_offset);
+ cc_state = (void *)(state_base + cc_offset);
+ sf_kernel = (void *)(state_base + sf_kernel_offset);
+ ps_kernel = (void *)(state_base + ps_kernel_offset);
+ sip_kernel = (void *)(state_base + sip_kernel_offset);
+
+ cc_viewport = (void *)(state_base + cc_viewport_offset);
+ dest_surf_state = (void *)(state_base + dest_surf_offset);
+ src_surf_state = (void *)(state_base + src_surf_offset);
+ src_sampler_state = (void *)(state_base + src_sampler_offset);
+ binding_table = (void *)(state_base + binding_table_offset);
+ vb = (void *)(state_base + vb_offset);
+
+#if 0
+ ErrorF("vs: 0x%08x\n", state_base_offset + vs_offset);
+ ErrorF("wm: 0x%08x\n", state_base_offset + wm_offset);
+ ErrorF("sf: 0x%08x\n", state_base_offset + sf_offset);
+ ErrorF("cc: 0x%08x\n", state_base_offset + cc_offset);
+ ErrorF("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset);
+ ErrorF("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset);
+ ErrorF("sip kernel: 0x%08x\n", state_base_offset + sip_kernel_offset);
+ ErrorF("cc_vp: 0x%08x\n", state_base_offset + cc_viewport_offset);
+ ErrorF("src sampler: 0x%08x\n", state_base_offset + src_sampler_offset);
+ ErrorF("vb: 0x%08x\n", state_base_offset + vb_offset);
+ ErrorF("dst surf: 0x%08x\n", state_base_offset + dest_surf_offset);
+ ErrorF("src surf: 0x%08x\n", state_base_offset + src_surf_offset);
+ ErrorF("binding table: 0x%08x\n", state_base_offset + binding_table_offset);
+#endif
+
+ /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it.
+ * A VUE consists of a 256-bit vertex header followed by the vertex data,
+ * which in our case is 4 floats (128 bits), thus a single 512-bit URB
+ * entry.
+ */
+#define URB_VS_ENTRIES 8
+#define URB_VS_ENTRY_SIZE 1
+
+#define URB_GS_ENTRIES 0
+#define URB_GS_ENTRY_SIZE 0
+
+#define URB_CLIP_ENTRIES 0
+#define URB_CLIP_ENTRY_SIZE 0
+
+ /* The SF kernel we use outputs only 4 256-bit registers, leading to an
+ * entry size of 2 512-bit URBs. We don't need to have many entries to
+ * output as we're generally working on large rectangles and don't care
+ * about having WM threads running on different rectangles simultaneously.
+ */
+#define URB_SF_ENTRIES 1
+#define URB_SF_ENTRY_SIZE 2
+
+#define URB_CS_ENTRIES 0
+#define URB_CS_ENTRY_SIZE 0
+
+ urb_vs_start = 0;
+ urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
+ urb_gs_start = urb_vs_start + urb_vs_size;
+ urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
+ urb_clip_start = urb_gs_start + urb_gs_size;
+ urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
+ urb_sf_start = urb_clip_start + urb_clip_size;
+ urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
+ urb_cs_start = urb_sf_start + urb_sf_size;
+ urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
+
+ /* We'll be poking the state buffers that could be in use by the 3d
+ * hardware here, but we should have synced the 3D engine already in
+ * I830PutImage.
+ */
+
+ memset (cc_viewport, 0, sizeof (*cc_viewport));
+ cc_viewport->min_depth = -1.e35;
+ cc_viewport->max_depth = 1.e35;
+
+ /* Color calculator state */
+ memset(cc_state, 0, sizeof(*cc_state));
+ cc_state->cc0.stencil_enable = 0; /* disable stencil */
+ cc_state->cc2.depth_test = 0; /* disable depth test */
+ cc_state->cc2.logicop_enable = 1; /* enable logic op */
+ cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */
+ cc_state->cc3.blend_enable = 0; /* disable color blend */
+ cc_state->cc3.alpha_test = 0; /* disable alpha test */
+ cc_state->cc4.cc_viewport_state_offset = (state_base_offset +
+ cc_viewport_offset) >> 5;
+ cc_state->cc5.dither_enable = 0; /* disable dither */
+ cc_state->cc5.logicop_func = 0xc; /* WHITE */
+ cc_state->cc5.statistics_enable = 1;
+ cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD;
+ cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE;
+ cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE;
+
+ /* Upload system kernel */
+ memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static));
+
+ /* Set up the state buffer for the destination surface */
+ memset(dest_surf_state, 0, sizeof(*dest_surf_state));
+ dest_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+ dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32;
+ if (pI830->cpp == 2) {
+ dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+ } else {
+ dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ }
+ dest_surf_state->ss0.writedisable_alpha = 0;
+ dest_surf_state->ss0.writedisable_red = 0;
+ dest_surf_state->ss0.writedisable_green = 0;
+ dest_surf_state->ss0.writedisable_blue = 0;
+ dest_surf_state->ss0.color_blend = 1;
+ dest_surf_state->ss0.vert_line_stride = 0;
+ dest_surf_state->ss0.vert_line_stride_ofs = 0;
+ dest_surf_state->ss0.mipmap_layout_mode = 0;
+ dest_surf_state->ss0.render_cache_read_mode = 0;
+
+ dest_surf_state->ss1.base_addr = intel_get_pixmap_offset(pPixmap);
+ dest_surf_state->ss2.height = pScrn->virtualY - 1;
+ dest_surf_state->ss2.width = pScrn->virtualX - 1;
+ dest_surf_state->ss2.mip_count = 0;
+ dest_surf_state->ss2.render_target_rotation = 0;
+ dest_surf_state->ss3.pitch = intel_get_pixmap_pitch(pPixmap) - 1;
+ dest_surf_state->ss3.tiled_surface = i830_pixmap_tiled(pPixmap);
+ dest_surf_state->ss3.tile_walk = 0; /* TileX */
+
+ /* Set up the source surface state buffer */
+ memset(src_surf_state, 0, sizeof(*src_surf_state));
+ src_surf_state->ss0.surface_type = BRW_SURFACE_2D;
+ /* src_surf_state->ss0.data_return_format =
+ BRW_SURFACERETURNFORMAT_FLOAT32; */
+ switch (id) {
+ case FOURCC_YUY2:
+ src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL;
+ break;
+ case FOURCC_UYVY:
+ src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY;
+ break;
+ }
+ src_surf_state->ss0.writedisable_alpha = 0;
+ src_surf_state->ss0.writedisable_red = 0;
+ src_surf_state->ss0.writedisable_green = 0;
+ src_surf_state->ss0.writedisable_blue = 0;
+ src_surf_state->ss0.color_blend = 1;
+ src_surf_state->ss0.vert_line_stride = 0;
+ src_surf_state->ss0.vert_line_stride_ofs = 0;
+ src_surf_state->ss0.mipmap_layout_mode = 0;
+ src_surf_state->ss0.render_cache_read_mode = 0;
+
+ src_surf_state->ss1.base_addr = pPriv->YBuf0offset;
+ src_surf_state->ss2.width = width - 1;
+ src_surf_state->ss2.height = height - 1;
+ src_surf_state->ss2.mip_count = 0;
+ src_surf_state->ss2.render_target_rotation = 0;
+ src_surf_state->ss3.pitch = video_pitch - 1;
+ /* FIXME: account for tiling if we ever do it */
+
+ /* Set up a binding table for our two surfaces. Only the PS will use it */
+ /* XXX: are these offset from the right place? */
+ binding_table[0] = state_base_offset + dest_surf_offset;
+ binding_table[1] = state_base_offset + src_surf_offset;
+
+ /* Set up the packed YUV source sampler. Doesn't do colorspace conversion.
+ */
+ memset(src_sampler_state, 0, sizeof(*src_sampler_state));
+ src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+ src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+ src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+
+ /* Set up the vertex shader to be disabled (passthrough) */
+ memset(vs_state, 0, sizeof(*vs_state));
+ vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+ vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+ vs_state->vs6.vs_enable = 0;
+ vs_state->vs6.vert_cache_disable = 1;
+
+ /* Set up the SF kernel to do coord interp: for each attribute,
+ * calculate dA/dx and dA/dy. Hand these interpolation coefficients
+ * back to SF which then hands pixels off to WM.
+ */
+
+ memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static));
+ memset(sf_state, 0, sizeof(*sf_state));
+ sf_state->thread0.kernel_start_pointer =
+ (state_base_offset + sf_kernel_offset) >> 6;
+ sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
+ sf_state->sf1.single_program_flow = 1; /* XXX */
+ sf_state->sf1.binding_table_entry_count = 0;
+ sf_state->sf1.thread_priority = 0;
+ sf_state->sf1.floating_point_mode = 0; /* Mesa does this */
+ sf_state->sf1.illegal_op_exception_enable = 1;
+ sf_state->sf1.mask_stack_exception_enable = 1;
+ sf_state->sf1.sw_exception_enable = 1;
+ sf_state->thread2.per_thread_scratch_space = 0;
+ /* scratch space is not used in our kernel */
+ sf_state->thread2.scratch_space_base_pointer = 0;
+ sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */
+ sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */
+ sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */
+ sf_state->thread3.urb_entry_read_offset = 0;
+ sf_state->thread3.dispatch_grf_start_reg = 3;
+ sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
+ sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
+ sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
+ sf_state->thread4.stats_enable = 1;
+ sf_state->sf5.viewport_transform = FALSE; /* skip viewport */
+ sf_state->sf6.cull_mode = BRW_CULLMODE_NONE;
+ sf_state->sf6.scissor = 0;
+ sf_state->sf7.trifan_pv = 2;
+ sf_state->sf6.dest_org_vbias = 0x8;
+ sf_state->sf6.dest_org_hbias = 0x8;
+
+ memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static));
+ memset (wm_state, 0, sizeof (*wm_state));
+ wm_state->thread0.kernel_start_pointer =
+ (state_base_offset + ps_kernel_offset) >> 6;
+ wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
+ wm_state->thread1.single_program_flow = 1; /* XXX */
+ wm_state->thread1.binding_table_entry_count = 2;
+ /* Though we never use the scratch space in our WM kernel, it has to be
+ * set, and the minimum allocation is 1024 bytes.
+ */
+ wm_state->thread2.scratch_space_base_pointer = (state_base_offset +
+ wm_scratch_offset) >> 10;
+ wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */
+ wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */
+ wm_state->thread3.const_urb_entry_read_length = 0;
+ wm_state->thread3.const_urb_entry_read_offset = 0;
+ wm_state->thread3.urb_entry_read_length = 1; /* XXX */
+ wm_state->thread3.urb_entry_read_offset = 0; /* XXX */
+ wm_state->wm4.stats_enable = 1;
+ wm_state->wm4.sampler_state_pointer = (state_base_offset +
+ src_sampler_offset) >> 5;
+ wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+ wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+ wm_state->wm5.thread_dispatch_enable = 1;
+ wm_state->wm5.enable_16_pix = 1;
+ wm_state->wm5.enable_8_pix = 0;
+ wm_state->wm5.early_depth_test = 1;
+
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_FLUSH |
+ MI_STATE_INSTRUCTION_CACHE_FLUSH |
+ BRW_MI_GLOBAL_SNAPSHOT_RESET);
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+
+ /* brw_debug (pScrn, "before base address modify"); */
+ {
+ BEGIN_LP_RING(12);
+ /* Match Mesa driver setup */
+ OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+ /* Mesa does this. Who knows... */
+ OUT_RING(BRW_CS_URB_STATE | 0);
+ OUT_RING((0 << 4) | /* URB Entry Allocation Size */
+ (0 << 0)); /* Number of URB Entries */
+
+ /* Zero out the two base address registers so all offsets are
+ * absolute
+ */
+ OUT_RING(BRW_STATE_BASE_ADDRESS | 4);
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */
+ OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */
+ /* general state max addr, disabled */
+ OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+ /* media object state max addr, disabled */
+ OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY);
+
+ /* Set system instruction pointer */
+ OUT_RING(BRW_STATE_SIP | 0);
+ /* system instruction pointer */
+ OUT_RING(state_base_offset + sip_kernel_offset);
+
+ OUT_RING(MI_NOOP);
+ ADVANCE_LP_RING();
+ }
+
+ /* brw_debug (pScrn, "after base address modify"); */
+
+ {
+ BEGIN_LP_RING(42);
+ /* Enable VF statistics */
+ OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1);
+
+ /* Pipe control */
+ OUT_RING(BRW_PIPE_CONTROL |
+ BRW_PIPE_CONTROL_NOWRITE |
+ BRW_PIPE_CONTROL_IS_FLUSH |
+ 2);
+ OUT_RING(0); /* Destination address */
+ OUT_RING(0); /* Immediate data low DW */
+ OUT_RING(0); /* Immediate data high DW */
+
+ /* Binding table pointers */
+ OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4);
+ OUT_RING(0); /* vs */
+ OUT_RING(0); /* gs */
+ OUT_RING(0); /* clip */
+ OUT_RING(0); /* sf */
+ /* Only the PS uses the binding table */
+ OUT_RING(state_base_offset + binding_table_offset); /* ps */
+
+ /* Blend constant color (magenta is fun) */
+ OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3);
+ OUT_RING(float_to_uint (1.0));
+ OUT_RING(float_to_uint (0.0));
+ OUT_RING(float_to_uint (1.0));
+ OUT_RING(float_to_uint (1.0));
+
+ /* The drawing rectangle clipping is always on. Set it to values that
+ * shouldn't do any clipping.
+ */
+ OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */
+ OUT_RING(0x00000000); /* ymin, xmin */
+ OUT_RING((pScrn->virtualX - 1) |
+ (pScrn->virtualY - 1) << 16); /* ymax, xmax */
+ OUT_RING(0x00000000); /* yorigin, xorigin */
+
+ /* skip the depth buffer */
+ /* skip the polygon stipple */
+ /* skip the polygon stipple offset */
+ /* skip the line stipple */
+
+ /* Set the pointers to the 3d pipeline state */
+ OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5);
+ OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */
+ /* disable GS, resulting in passthrough */
+ OUT_RING(BRW_GS_DISABLE);
+ /* disable CLIP, resulting in passthrough */
+ OUT_RING(BRW_CLIP_DISABLE);
+ OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */
+ OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */
+ OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */
+
+ /* URB fence */
+ OUT_RING(BRW_URB_FENCE |
+ UF0_CS_REALLOC |
+ UF0_SF_REALLOC |
+ UF0_CLIP_REALLOC |
+ UF0_GS_REALLOC |
+ UF0_VS_REALLOC |
+ 1);
+ OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
+ ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
+ ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
+ OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
+ ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
+
+ /* Constant buffer state */
+ OUT_RING(BRW_CS_URB_STATE | 0);
+ OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) |
+ (URB_CS_ENTRIES << 0));
+
+ /* Set up the pointer to our vertex buffer */
+ OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2);
+ /* four 32-bit floats per vertex */
+ OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) |
+ VB0_VERTEXDATA |
+ ((4 * 4) << VB0_BUFFER_PITCH_SHIFT));
+ OUT_RING(state_base_offset + vb_offset);
+ OUT_RING(3); /* four corners to our rectangle */
+
+ /* Set up our vertex elements, sourced from the single vertex buffer. */
+ OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
+ /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+ OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (0 << VE0_OFFSET_SHIFT));
+ OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+ (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+ /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+ OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (8 << VE0_OFFSET_SHIFT));
+ OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+ (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+ (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+
+ OUT_RING(MI_NOOP); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ /* Set up the offset for translating from the given region (in screen
+ * coordinates) to the backing pixmap.
+ */
+#ifdef COMPOSITE
+ pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x;
+ pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+ pix_xoff = 0;
+ pix_yoff = 0;
+#endif
+
+ dxo = dstRegion->extents.x1;
+ dyo = dstRegion->extents.y1;
+
+ /* Use normalized texture coordinates */
+ src_scale_x = ((float)src_w / width) / (float)drw_w;
+ src_scale_y = ((float)src_h / height) / (float)drw_h;
+
+ pbox = REGION_RECTS(dstRegion);
+ nbox = REGION_NUM_RECTS(dstRegion);
+ while (nbox--) {
+ int box_x1 = pbox->x1;
+ int box_y1 = pbox->y1;
+ int box_x2 = pbox->x2;
+ int box_y2 = pbox->y2;
+ int i;
+
+ if (!first_output) {
+ /* Since we use the same little vertex buffer over and over, sync
+ * for subsequent rectangles.
+ */
+ i830WaitSync(pScrn);
+ }
+
+ pbox++;
+
+ i = 0;
+ vb[i++] = (box_x2 - dxo) * src_scale_x;
+ vb[i++] = (box_y2 - dyo) * src_scale_y;
+ vb[i++] = (float) box_x2 + pix_xoff;
+ vb[i++] = (float) box_y2 + pix_yoff;
+
+ vb[i++] = (box_x1 - dxo) * src_scale_x;
+ vb[i++] = (box_y2 - dyo) * src_scale_y;
+ vb[i++] = (float) box_x1 + pix_xoff;
+ vb[i++] = (float) box_y2 + pix_yoff;
+
+ vb[i++] = (box_x1 - dxo) * src_scale_x;
+ vb[i++] = (box_y1 - dyo) * src_scale_y;
+ vb[i++] = (float) box_x1 + pix_xoff;
+ vb[i++] = (float) box_y1 + pix_yoff;
+
+#if 0
+ ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+ INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+ INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+
+ OUTREG(BRW_VF_CTL,
+ BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID |
+ BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX |
+ BRW_VF_CTL_SNAPSHOT_ENABLE);
+ OUTREG(BRW_VF_STRG_VAL, 0);
+#endif
+
+#if 0
+ OUTREG(BRW_VS_CTL,
+ BRW_VS_CTL_SNAPSHOT_ALL_THREADS |
+ BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT |
+ BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE);
+
+ OUTREG(BRW_VS_STRG_VAL, 0);
+#endif
+
+#if WATCH_SF
+ OUTREG(BRW_SF_CTL,
+ BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT |
+ BRW_SF_CTL_SNAPSHOT_ALL_THREADS |
+ BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE);
+ OUTREG(BRW_SF_STRG_VAL, 0);
+#endif
+
+#if WATCH_WIZ
+ OUTREG(BRW_WIZ_CTL,
+ BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE |
+ BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS |
+ BRW_WIZ_CTL_SNAPSHOT_ENABLE);
+ OUTREG(BRW_WIZ_STRG_VAL,
+ (box_x1) | (box_y1 << 16));
+#endif
+
+#if 0
+ OUTREG(BRW_TS_CTL,
+ BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR |
+ BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS |
+ BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS |
+ BRW_TS_CTL_SNAPSHOT_ENABLE);
+#endif
+
+ BEGIN_LP_RING(6);
+ OUT_RING(BRW_3DPRIMITIVE |
+ BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+ (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) |
+ (0 << 9) | /* CTG - indirect vertex count */
+ 4);
+ OUT_RING(3); /* vertex count per instance */
+ OUT_RING(0); /* start vertex offset */
+ OUT_RING(1); /* single instance */
+ OUT_RING(0); /* start instance location */
+ OUT_RING(0); /* index buffer offset, ignored */
+ ADVANCE_LP_RING();
+
+#if 0
+ for (j = 0; j < 100000; j++) {
+ ctl = INREG(BRW_VF_CTL);
+ if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE)
+ break;
+ }
+
+ rdata = INREG(BRW_VF_RDATA);
+ OUTREG(BRW_VF_CTL, 0);
+ ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata);
+#endif
+
+#if 0
+ for (j = 0; j < 1000000; j++) {
+ ctl = INREG(BRW_VS_CTL);
+ if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE)
+ break;
+ }
+
+ rdata = INREG(BRW_VS_RDATA);
+ for (k = 0; k <= 3; k++) {
+ OUTREG(BRW_VS_CTL,
+ BRW_VS_CTL_SNAPSHOT_COMPLETE |
+ (k << 8));
+ rdata = INREG(BRW_VS_RDATA);
+ ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+ }
+
+ OUTREG(BRW_VS_CTL, 0);
+#endif
+
+#if WATCH_SF
+ for (j = 0; j < 1000000; j++) {
+ ctl = INREG(BRW_SF_CTL);
+ if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE)
+ break;
+ }
+
+ for (k = 0; k <= 7; k++) {
+ OUTREG(BRW_SF_CTL,
+ BRW_SF_CTL_SNAPSHOT_COMPLETE |
+ (k << 8));
+ rdata = INREG(BRW_SF_RDATA);
+ ErrorF("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata);
+ }
+
+ OUTREG(BRW_SF_CTL, 0);
+#endif
+
+#if WATCH_WIZ
+ for (j = 0; j < 100000; j++) {
+ ctl = INREG(BRW_WIZ_CTL);
+ if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE)
+ break;
+ }
+
+ rdata = INREG(BRW_WIZ_RDATA);
+ OUTREG(BRW_WIZ_CTL, 0);
+ ErrorF("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata);
+#endif
+
+#if 0
+ for (j = 0; j < 100000; j++) {
+ ctl = INREG(BRW_TS_CTL);
+ if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE)
+ break;
+ }
+
+ rdata = INREG(BRW_TS_RDATA);
+ OUTREG(BRW_TS_CTL, 0);
+ ErrorF("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata);
+
+ ErrorF("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n",
+ INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0),
+ INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0));
+#endif
+
+#if 0
+ for (j = 0; j < 256; j++) {
+ OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT);
+ rdata = INREG(BRW_TD_RDATA);
+ ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata);
+ }
+#endif
+ first_output = FALSE;
+ i830MarkSync(pScrn);
+ }
+
+ i830WaitSync(pScrn);
+#if WATCH_STATS
+ i830_dump_error_state(pScrn);
+#endif
+}
diff --git a/driver/xf86-video-intel/src/ivch/Makefile.am b/driver/xf86-video-intel/src/ivch/Makefile.am
new file mode 100644
index 000000000..1dc9cb352
--- /dev/null
+++ b/driver/xf86-video-intel/src/ivch/Makefile.am
@@ -0,0 +1,15 @@
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+ivch_la_LTLIBRARIES = ivch.la
+ivch_la_LDFLAGS = -module -avoid-version
+ivch_ladir = @moduledir@/drivers
+
+ivch_la_SOURCES = \
+ ivch.c \
+ ivch_module.c \
+ ivch_reg.h
diff --git a/driver/xf86-video-intel/src/ivch/Makefile.in b/driver/xf86-video-intel/src/ivch/Makefile.in
new file mode 100644
index 000000000..231d3d2c3
--- /dev/null
+++ b/driver/xf86-video-intel/src/ivch/Makefile.in
@@ -0,0 +1,511 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/ivch
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(ivch_ladir)"
+ivch_laLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(ivch_la_LTLIBRARIES)
+ivch_la_LIBADD =
+am_ivch_la_OBJECTS = ivch.lo ivch_module.lo
+ivch_la_OBJECTS = $(am_ivch_la_OBJECTS)
+ivch_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(ivch_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(ivch_la_SOURCES)
+DIST_SOURCES = $(ivch_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+ivch_la_LTLIBRARIES = ivch.la
+ivch_la_LDFLAGS = -module -avoid-version
+ivch_ladir = @moduledir@/drivers
+ivch_la_SOURCES = \
+ ivch.c \
+ ivch_module.c \
+ ivch_reg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ivch/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/ivch/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-ivch_laLTLIBRARIES: $(ivch_la_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(ivch_ladir)" || $(MKDIR_P) "$(DESTDIR)$(ivch_ladir)"
+ @list='$(ivch_la_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(ivch_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(ivch_ladir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(ivch_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(ivch_ladir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-ivch_laLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ivch_la_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(ivch_ladir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(ivch_ladir)/$$p"; \
+ done
+
+clean-ivch_laLTLIBRARIES:
+ -test -z "$(ivch_la_LTLIBRARIES)" || rm -f $(ivch_la_LTLIBRARIES)
+ @list='$(ivch_la_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+ivch.la: $(ivch_la_OBJECTS) $(ivch_la_DEPENDENCIES)
+ $(ivch_la_LINK) -rpath $(ivch_ladir) $(ivch_la_OBJECTS) $(ivch_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ivch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ivch_module.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(ivch_ladir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-ivch_laLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ivch_laLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ivch_laLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-ivch_laLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-ivch_laLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-ivch_laLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/ivch/ivch.c b/driver/xf86-video-intel/src/ivch/ivch.c
new file mode 100644
index 000000000..ac57ff3af
--- /dev/null
+++ b/driver/xf86-video-intel/src/ivch/ivch.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+#include <unistd.h>
+
+#include "../i2c_vid.h"
+#include "../i830_bios.h"
+#include "ivch_reg.h"
+
+struct ivch_priv {
+ I2CDevRec d;
+
+ xf86OutputPtr output;
+ Bool quiet;
+
+ CARD16 width;
+ CARD16 height;
+
+ CARD16 save_VR01;
+ CARD16 save_VR40;
+};
+
+struct vch_capabilities {
+ struct aimdb_block aimdb_block;
+ CARD8 panel_type;
+ CARD8 set_panel_type;
+ CARD8 slave_address;
+ CARD8 capabilities;
+#define VCH_PANEL_FITTING_SUPPORT (0x3 << 0)
+#define VCH_PANEL_FITTING_TEXT (1 << 2)
+#define VCH_PANEL_FITTING_GRAPHICS (1 << 3)
+#define VCH_PANEL_FITTING_RATIO (1 << 4)
+#define VCH_DITHERING (1 << 5)
+ CARD8 backlight_gpio;
+ CARD8 set_panel_type_us_gpios;
+} __attribute__ ((packed));
+
+static void
+ivch_dump_regs(I2CDevPtr d);
+
+/**
+ * Reads a register on the ivch.
+ *
+ * Each of the 256 registers are 16 bits long.
+ */
+static Bool
+ivch_read(struct ivch_priv *priv, int addr, CARD16 *data)
+{
+ I2CBusPtr b = priv->d.pI2CBus;
+ I2CByte *p = (I2CByte *) data;
+
+ if (!b->I2CStart(b, priv->d.StartTimeout))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr | 1))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, addr))
+ goto fail;
+
+ if (!b->I2CGetByte(&priv->d, p++, FALSE))
+ goto fail;
+
+ if (!b->I2CGetByte(&priv->d, p++, TRUE))
+ goto fail;
+
+ b->I2CStop(&priv->d);
+
+ return TRUE;
+
+ fail:
+ if (!priv->quiet) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "ivch: Unable to read register 0x%02x from %s:%02x.\n",
+ addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+ }
+ b->I2CStop(&priv->d);
+
+ return FALSE;
+}
+
+/** Writes a 16-bit register on the ivch */
+static Bool
+ivch_write(struct ivch_priv *priv, int addr, CARD16 data)
+{
+ I2CBusPtr b = priv->d.pI2CBus;
+
+ if (!b->I2CStart(b, priv->d.StartTimeout))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, addr))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, data & 0xff))
+ goto fail;
+
+ if (!b->I2CPutByte(&priv->d, data >> 8))
+ goto fail;
+
+ b->I2CStop(&priv->d);
+
+ return TRUE;
+
+ fail:
+ b->I2CStop(&priv->d);
+
+ if (!priv->quiet) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write register 0x%02x to %s:%d.\n",
+ addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
+ }
+
+ return FALSE;
+}
+
+/** Probes the given bus and slave address for an ivch */
+static void *
+ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+ struct ivch_priv *priv;
+ CARD16 temp;
+
+ priv = xcalloc(1, sizeof(struct ivch_priv));
+ if (priv == NULL)
+ return NULL;
+
+ priv->output = NULL;
+ priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller";
+ priv->d.SlaveAddr = addr;
+ priv->d.pI2CBus = b;
+ priv->d.StartTimeout = b->StartTimeout;
+ priv->d.BitTimeout = b->BitTimeout;
+ priv->d.AcknTimeout = b->AcknTimeout;
+ priv->d.ByteTimeout = b->ByteTimeout;
+ priv->d.DriverPrivate.ptr = priv;
+ priv->quiet = TRUE;
+
+ if (!ivch_read(priv, VR00, &temp))
+ goto out;
+ priv->quiet = FALSE;
+
+ /* Since the identification bits are probably zeroes, which doesn't seem
+ * very unique, check that the value in the base address field matches
+ * the address it's responding on.
+ */
+ if ((temp & VR00_BASE_ADDRESS_MASK) != (priv->d.SlaveAddr >> 1)) {
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
+ "ivch detect failed due to address mismatch "
+ "(%d vs %d)\n",
+ (temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr >> 1);
+ }
+
+ if (!xf86I2CDevInit(&priv->d)) {
+ goto out;
+ }
+
+ ivch_read(priv, VR20, &priv->width);
+ ivch_read(priv, VR21, &priv->height);
+
+ return priv;
+
+out:
+ xfree(priv);
+ return NULL;
+}
+
+static xf86OutputStatus
+ivch_detect(I2CDevPtr d)
+{
+ return XF86OutputStatusConnected;
+}
+
+static ModeStatus
+ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+ if (mode->Clock > 112000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+/** Sets the power state of the panel connected to the ivch */
+static void
+ivch_dpms(I2CDevPtr d, int mode)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ int i;
+ CARD16 vr01, vr30, backlight;
+
+ /* Set the new power state of the panel. */
+ if (!ivch_read(priv, VR01, &vr01))
+ return;
+
+ if (mode == DPMSModeOn)
+ backlight = 1;
+ else
+ backlight = 0;
+ ivch_write(priv, VR80, backlight);
+
+ if (mode == DPMSModeOn)
+ vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
+ else
+ vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
+
+ ivch_write(priv, VR01, vr01);
+
+ /* Wait for the panel to make its state transition */
+ for (i = 0; i < 100; i++) {
+ if (!ivch_read(priv, VR30, &vr30))
+ break;
+
+ if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn))
+ break;
+ usleep (1000);
+ }
+ /* And wait some more; without this, the vch fails to resync sometimes */
+ usleep (16 * 1000);
+}
+
+static void
+ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ CARD16 vr40 = 0;
+ CARD16 vr01;
+
+ vr01 = 0;
+ vr40 = (VR40_STALL_ENABLE |
+ VR40_VERTICAL_INTERP_ENABLE |
+ VR40_HORIZONTAL_INTERP_ENABLE);
+
+ if (mode->HDisplay != adjusted_mode->HDisplay ||
+ mode->VDisplay != adjusted_mode->VDisplay)
+ {
+ CARD16 x_ratio, y_ratio;
+
+ vr01 |= VR01_PANEL_FIT_ENABLE;
+ vr40 |= VR40_CLOCK_GATING_ENABLE;
+ x_ratio = (((mode->HDisplay - 1) << 16) / (adjusted_mode->HDisplay - 1)) >> 2;
+ y_ratio = (((mode->VDisplay - 1) << 16) / (adjusted_mode->VDisplay - 1)) >> 2;
+ ivch_write (priv, VR42, x_ratio);
+ ivch_write (priv, VR41, y_ratio);
+ }
+ else
+ {
+ vr01 &= ~VR01_PANEL_FIT_ENABLE;
+ vr40 &= ~VR40_CLOCK_GATING_ENABLE;
+ }
+ vr40 &= ~VR40_AUTO_RATIO_ENABLE;
+
+ ivch_write(priv, VR01, vr01);
+ ivch_write(priv, VR40, vr40);
+
+ ivch_dump_regs(d);
+}
+
+static void
+ivch_dump_regs(I2CDevPtr d)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+ CARD16 val;
+
+ ivch_read(priv, VR00, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR00: 0x%04x\n", val);
+ ivch_read(priv, VR01, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR01: 0x%04x\n", val);
+ ivch_read(priv, VR30, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR30: 0x%04x\n", val);
+ ivch_read(priv, VR40, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val);
+
+ /* GPIO registers */
+ ivch_read(priv, VR80, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR80: 0x%04x\n", val);
+ ivch_read(priv, VR81, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR81: 0x%04x\n", val);
+ ivch_read(priv, VR82, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR82: 0x%04x\n", val);
+ ivch_read(priv, VR83, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR83: 0x%04x\n", val);
+ ivch_read(priv, VR84, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR84: 0x%04x\n", val);
+ ivch_read(priv, VR85, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR85: 0x%04x\n", val);
+ ivch_read(priv, VR86, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR86: 0x%04x\n", val);
+ ivch_read(priv, VR87, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR87: 0x%04x\n", val);
+ ivch_read(priv, VR88, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR88: 0x%04x\n", val);
+
+ /* Scratch register 0 - AIM Panel type */
+ ivch_read(priv, VR8E, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8E: 0x%04x\n", val);
+
+ /* Scratch register 1 - Status register */
+ ivch_read(priv, VR8F, &val);
+ xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR8F: 0x%04x\n", val);
+}
+
+static void
+ivch_save(I2CDevPtr d)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+ ivch_read(priv, VR01, &priv->save_VR01);
+ ivch_read(priv, VR40, &priv->save_VR40);
+}
+
+static void
+ivch_restore(I2CDevPtr d)
+{
+ struct ivch_priv *priv = d->DriverPrivate.ptr;
+
+ ivch_write(priv, VR01, priv->save_VR01);
+ ivch_write(priv, VR40, priv->save_VR40);
+}
+
+
+I830I2CVidOutputRec ivch_methods = {
+ .init = ivch_init,
+ .dpms = ivch_dpms,
+ .save = ivch_save,
+ .restore = ivch_restore,
+ .mode_valid = ivch_mode_valid,
+ .mode_set = ivch_mode_set,
+ .detect = ivch_detect,
+ .dump_regs = ivch_dump_regs,
+};
diff --git a/driver/xf86-video-intel/src/ivch/ivch_module.c b/driver/xf86-video-intel/src/ivch/ivch_module.c
new file mode 100644
index 000000000..1ed483b12
--- /dev/null
+++ b/driver/xf86-video-intel/src/ivch/ivch_module.c
@@ -0,0 +1,64 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(ivch_setup);
+
+static XF86ModuleVersionInfo ivch_version = {
+ "ivch",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ { 0,0,0,0 }
+};
+
+_X_EXPORT XF86ModuleData ivchModuleData = {
+ &ivch_version,
+ ivch_setup,
+ NULL
+};
+
+static pointer
+ivch_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ return (pointer)1;
+}
diff --git a/driver/xf86-video-intel/src/ivch/ivch_reg.h b/driver/xf86-video-intel/src/ivch/ivch_reg.h
new file mode 100644
index 000000000..bcd8c56a3
--- /dev/null
+++ b/driver/xf86-video-intel/src/ivch/ivch_reg.h
@@ -0,0 +1,291 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file
+ * This file contains the register definitions for the i82807aa.
+ *
+ * Documentation on this chipset can be found in datasheet #29069001 at
+ * intel.com.
+ */
+#ifndef I82807AA_REG_H
+#define I82807AA_REG_H
+
+/** @defgroup VR00 VCH Revision & GMBus Base Addr
+ * @{
+ */
+#define VR00 0x00
+# define VR00_BASE_ADDRESS_MASK 0x007f
+/** @} */
+
+/** @defgroup VR01 VCH Functionality Enable
+ * @{
+ */
+#define VR01 0x01
+/**
+ * Enable the panel fitter
+ */
+# define VR01_PANEL_FIT_ENABLE (1 << 3)
+/**
+ * Enables the LCD display.
+ *
+ * This must not be set while VR01_DVO_BYPASS_ENABLE is set.
+ */
+# define VR01_LCD_ENABLE (1 << 2)
+/** Enables the DVO repeater. */
+# define VR01_DVO_BYPASS_ENABLE (1 << 1)
+/** Enables the DVO clock */
+# define VR01_DVO_ENABLE (1 << 0)
+/** @} */
+
+/** @defgroup VR10 LCD Interface Format
+ * @{
+ */
+#define VR10 0x10
+/** Enables LVDS output instead of CMOS */
+# define VR10_LVDS_ENABLE (1 << 4)
+/** Enables 18-bit LVDS output. */
+# define VR10_INTERFACE_1X18 (0 << 2)
+/** Enables 24-bit LVDS or CMOS output */
+# define VR10_INTERFACE_1X24 (1 << 2)
+/** Enables 2x18-bit LVDS or CMOS output. */
+# define VR10_INTERFACE_2X18 (2 << 2)
+/** Enables 2x24-bit LVDS output */
+# define VR10_INTERFACE_2X24 (3 << 2)
+/** @} */
+
+/** @defgroup VR11 CMOS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR12 LVDS Output Control
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR18 PLL clock select
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR19 PLL clock divisor M
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1A PLL clock divisor N
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR1F FIFO Pre-load
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR20 LCD Horizontal Display Size
+ * @{
+ */
+#define VR20 0x20
+/** @} */
+
+/** @defgroup VR21 LCD Vertical Display Size
+ * @{
+ */
+#define VR21 0x20
+/** @} */
+
+/** @defgroup VR22 Horizontal TRP to DE Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR23 Horizontal TRP to DE End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR24 Horizontal TRP To LP Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR25 Horizontal TRP To LP End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR26 Vertical TRP To FLM Start Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR27 Vertical TRP To FLM End Delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR30 Panel power down status
+ * @{
+ */
+#define VR30 0x30
+/** Read only bit indicating that the panel is not in a safe poweroff state. */
+# define VR30_PANEL_ON (1 << 15)
+/** @} */
+
+/** @defgroup VR31 Tpon Panel power on sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR32 Tpon Panel power off sequencing delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR33 Tstay Panel power off stay down delay
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR34 Maximal FLM Pulse Interval
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR35 Maximal LP Pulse Interval
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR40
+ * @{
+ */
+#define VR40 0x40
+# define VR40_STALL_ENABLE (1 << 13)
+# define VR40_VERTICAL_INTERP_ENABLE (1 << 12)
+# define VR40_ENHANCED_PANEL_FITTING (1 << 11)
+# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10)
+# define VR40_AUTO_RATIO_ENABLE (1 << 9)
+# define VR40_CLOCK_GATING_ENABLE (1 << 8)
+/** @} */
+
+/** @defgroup VR41 Panel Fitting Vertical Ratio
+ * @{
+ *
+ * (((image_height - 1) << 16) / ((panel_height - 1))) >> 2
+ */
+/** @} */
+#define VR41 0x41
+
+/** @defgroup VR42 Panel Fitting Horizontal Ratio
+ * @{
+ * (((image_width - 1) << 16) / ((panel_width - 1))) >> 2
+ */
+/** @} */
+#define VR42 0x42
+
+/** @defgroup VR43 Horizontal Image Size
+ * @{
+ */
+/** @} */
+#define VR43 0x43
+
+/** @defgroup VR44 Panel Fitting Coefficient 0
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR45 Panel Fitting Coefficient 1
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR46 Panel Fitting Coefficient 2
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR47 Panel Fitting Coefficient 3
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR48 Panel Fitting Coefficient 4
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR49 Panel Fitting Coefficient 5
+ * @{
+ */
+/** @} */
+
+/** @defgroup VR80 GPIO 0
+ * @{
+ */
+/** @} */
+
+#define VR80 0x80
+#define VR81 0x81
+#define VR82 0x82
+#define VR83 0x83
+#define VR84 0x84
+#define VR85 0x85
+#define VR86 0x86
+#define VR87 0x87
+
+/** @defgroup VR88 GPIO 8
+ * @{
+ */
+/** @} */
+
+#define VR88 0x88
+
+/** @defgroup VR8E Graphics BIOS scratch 0
+ * @{
+ */
+#define VR8E 0x8E
+# define VR8E_PANEL_TYPE_MASK (0xf << 0)
+# define VR8E_PANEL_INTERFACE_CMOS (0 << 4)
+# define VR8E_PANEL_INTERFACE_LVDS (1 << 4)
+# define VR8E_FORCE_DEFAULT_PANEL (1 << 5)
+/** @} */
+
+/** @defgroup VR8F Graphics BIOS scratch 1
+ * @{
+ */
+#define VR8F 0x8F
+# define VR8F_VCH_PRESENT (1 << 0)
+# define VR8F_DISPLAY_CONN (1 << 1)
+# define VR8F_POWER_MASK (0x3c)
+# define VR8F_POWER_POS (2)
+/** @} */
+
+
+#endif /* I82807AA_REG_H */
diff --git a/driver/xf86-video-intel/src/local_xf86Rename.h b/driver/xf86-video-intel/src/local_xf86Rename.h
new file mode 100644
index 000000000..e1e788f30
--- /dev/null
+++ b/driver/xf86-video-intel/src/local_xf86Rename.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#define XF86NAME(x) intel_##x
diff --git a/driver/xf86-video-intel/src/modes/xf86Crtc.c b/driver/xf86-video-intel/src/modes/xf86Crtc.c
new file mode 100644
index 000000000..d375da897
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Crtc.c
@@ -0,0 +1,2264 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#include "xf86xv.h"
+
+/*
+ * Initialize xf86CrtcConfig structure
+ */
+
+int xf86CrtcConfigPrivateIndex = -1;
+
+_X_EXPORT void
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr config;
+
+ if (xf86CrtcConfigPrivateIndex == -1)
+ xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
+ config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+
+ config->funcs = funcs;
+
+ scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
+}
+
+_X_EXPORT void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+ int minWidth, int minHeight,
+ int maxWidth, int maxHeight)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ config->minWidth = minWidth;
+ config->minHeight = minHeight;
+ config->maxWidth = maxWidth;
+ config->maxHeight = maxHeight;
+}
+
+/*
+ * Crtc functions
+ */
+_X_EXPORT xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr scrn,
+ const xf86CrtcFuncsRec *funcs)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc, *crtcs;
+
+ crtc = xcalloc (sizeof (xf86CrtcRec), 1);
+ if (!crtc)
+ return NULL;
+ crtc->scrn = scrn;
+ crtc->funcs = funcs;
+#ifdef RANDR_12_INTERFACE
+ crtc->randr_crtc = NULL;
+#endif
+ crtc->rotation = RR_Rotate_0;
+ crtc->desiredRotation = RR_Rotate_0;
+ if (xf86_config->crtc)
+ crtcs = xrealloc (xf86_config->crtc,
+ (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ else
+ crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ {
+ xfree (crtc);
+ return NULL;
+ }
+ xf86_config->crtc = crtcs;
+ xf86_config->crtc[xf86_config->num_crtc++] = crtc;
+ return crtc;
+}
+
+_X_EXPORT void
+xf86CrtcDestroy (xf86CrtcPtr crtc)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ int c;
+
+ (*crtc->funcs->destroy) (crtc);
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ if (xf86_config->crtc[c] == crtc)
+ {
+ memmove (&xf86_config->crtc[c],
+ &xf86_config->crtc[c+1],
+ ((xf86_config->num_crtc - (c + 1)) * sizeof(void*)));
+ xf86_config->num_crtc--;
+ break;
+ }
+ xfree (crtc);
+}
+
+
+/**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+_X_EXPORT Bool
+xf86CrtcInUse (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o]->crtc == crtc)
+ return TRUE;
+ return FALSE;
+}
+
+_X_EXPORT void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
+{
+#ifdef RENDER
+ int subpixel_order = SubPixelUnknown;
+ Bool has_none = FALSE;
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+
+ if (output->crtc == crtc)
+ {
+ switch (output->subpixel_order) {
+ case SubPixelNone:
+ has_none = TRUE;
+ break;
+ case SubPixelUnknown:
+ break;
+ default:
+ subpixel_order = output->subpixel_order;
+ break;
+ }
+ }
+ if (subpixel_order != SubPixelUnknown)
+ break;
+ }
+ if (subpixel_order != SubPixelUnknown)
+ {
+ static const int circle[4] = {
+ SubPixelHorizontalRGB,
+ SubPixelVerticalRGB,
+ SubPixelHorizontalBGR,
+ SubPixelVerticalBGR,
+ };
+ int rotate;
+ int c;
+ for (rotate = 0; rotate < 4; rotate++)
+ if (crtc->rotation & (1 << rotate))
+ break;
+ for (c = 0; c < 4; c++)
+ if (circle[c] == subpixel_order)
+ break;
+ c = (c + rotate) & 0x3;
+ if ((crtc->rotation & RR_Reflect_X) && !(c & 1))
+ c ^= 2;
+ if ((crtc->rotation & RR_Reflect_Y) && (c & 1))
+ c ^= 2;
+ subpixel_order = circle[c];
+ break;
+ }
+ }
+ if (subpixel_order == SubPixelUnknown && has_none)
+ subpixel_order = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subpixel_order);
+#endif
+}
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+_X_EXPORT Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+ int x, int y)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+ Bool ret = FALSE;
+ Bool didLock = FALSE;
+ DisplayModePtr adjusted_mode;
+ DisplayModeRec saved_mode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+
+ crtc->enabled = xf86CrtcInUse (crtc);
+
+ if (!crtc->enabled)
+ {
+ /* XXX disable crtc? */
+ return TRUE;
+ }
+
+ adjusted_mode = xf86DuplicateMode(mode);
+
+ didLock = crtc->funcs->lock (crtc);
+
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+ /* Update crtc values up front so the driver can rely on them for mode
+ * setting.
+ */
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
+
+ /* XXX short-circuit changes to base location only */
+
+ /* Pass our mode to the outputs and the CRTC to give them a chance to
+ * adjust it according to limitations or output properties, and also
+ * a chance to reject the mode entirely.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+ goto done;
+ }
+ }
+
+ if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+ goto done;
+ }
+
+ if (!xf86CrtcRotate (crtc, mode, rotation)) {
+ goto done;
+ }
+
+ /* Prepare the outputs and CRTCs before setting the mode. */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ /* Disable the output as the first thing we do. */
+ output->funcs->prepare(output);
+ }
+
+ crtc->funcs->prepare(crtc);
+
+ /* Set up the DPLL and any output state that needs to adjust or depend
+ * on the DPLL.
+ */
+ crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ output->funcs->mode_set(output, mode, adjusted_mode);
+ }
+
+ /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+ crtc->funcs->commit(crtc);
+ for (i = 0; i < xf86_config->num_output; i++)
+ {
+ xf86OutputPtr output = xf86_config->output[i];
+ if (output->crtc == crtc)
+ {
+ output->funcs->commit(output);
+#ifdef RANDR_12_INTERFACE
+ if (output->randr_output)
+ RRPostPendingProperties (output->randr_output);
+#endif
+ }
+ }
+
+ /* XXX free adjustedmode */
+ ret = TRUE;
+ if (scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+
+done:
+ if (!ret) {
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ crtc->rotation = saved_rotation;
+ crtc->mode = saved_mode;
+ }
+
+ if (didLock)
+ crtc->funcs->unlock (crtc);
+
+ return ret;
+}
+
+/*
+ * Output functions
+ */
+
+extern XF86ConfigPtr xf86configptr;
+
+typedef enum {
+ OPTION_PREFERRED_MODE,
+ OPTION_POSITION,
+ OPTION_BELOW,
+ OPTION_RIGHT_OF,
+ OPTION_ABOVE,
+ OPTION_LEFT_OF,
+ OPTION_ENABLE,
+ OPTION_DISABLE,
+ OPTION_MIN_CLOCK,
+ OPTION_MAX_CLOCK,
+ OPTION_IGNORE,
+ OPTION_ROTATE,
+} OutputOpts;
+
+static OptionInfoRec xf86OutputOptions[] = {
+ {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE },
+ {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE },
+ {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE },
+ {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE },
+ {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE },
+ {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
+ {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+enum {
+ OPTION_MODEDEBUG,
+};
+
+static OptionInfoRec xf86DeviceOptions[] = {
+ {OPTION_MODEDEBUG, "ModeDebug", OPTV_STRING, {0}, FALSE },
+ {-1, NULL, OPTV_NONE, {0}, FALSE },
+};
+
+static void
+xf86OutputSetMonitor (xf86OutputPtr output)
+{
+ char *option_name;
+ static const char monitor_prefix[] = "monitor-";
+ char *monitor;
+
+ if (!output->name)
+ return;
+
+ if (output->options)
+ xfree (output->options);
+
+ output->options = xnfalloc (sizeof (xf86OutputOptions));
+ memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions));
+
+ option_name = xnfalloc (strlen (monitor_prefix) +
+ strlen (output->name) + 1);
+ strcpy (option_name, monitor_prefix);
+ strcat (option_name, output->name);
+ monitor = xf86findOptionValue (output->scrn->options, option_name);
+ if (!monitor)
+ monitor = output->name;
+ else
+ xf86MarkOptionUsedByName (output->scrn->options, option_name);
+ xfree (option_name);
+ output->conf_monitor = xf86findMonitor (monitor,
+ xf86configptr->conf_monitor_lst);
+ /*
+ * Find the monitor section of the screen and use that
+ */
+ if (!output->conf_monitor && output->use_screen_monitor)
+ output->conf_monitor = xf86findMonitor (output->scrn->monitor->id,
+ xf86configptr->conf_monitor_lst);
+ if (output->conf_monitor)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s using monitor section %s\n",
+ output->name, output->conf_monitor->mon_identifier);
+ xf86ProcessOptions (output->scrn->scrnIndex,
+ output->conf_monitor->mon_option_lst,
+ output->options);
+ }
+ else
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s has no monitor section\n",
+ output->name);
+}
+
+static Bool
+xf86OutputEnabled (xf86OutputPtr output)
+{
+ Bool enable, disable;
+
+ /* check to see if this output was enabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s enabled by config file\n", output->name);
+ return TRUE;
+ }
+ /* or if this output was disabled in the config file */
+ if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable)
+ {
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s disabled by config file\n", output->name);
+ return FALSE;
+ }
+ /* otherwise, enable if it is not disconnected */
+ enable = output->status != XF86OutputStatusDisconnected;
+ xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
+ "Output %s %sconnected\n", output->name, enable ? "" : "dis");
+ return enable;
+}
+
+static Bool
+xf86OutputIgnored (xf86OutputPtr output)
+{
+ return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
+}
+
+static char *direction[4] = {
+ "normal",
+ "left",
+ "inverted",
+ "right"
+};
+
+static Rotation
+xf86OutputInitialRotation (xf86OutputPtr output)
+{
+ char *rotate_name = xf86GetOptValString (output->options,
+ OPTION_ROTATE);
+ int i;
+
+ if (!rotate_name)
+ return RR_Rotate_0;
+
+ for (i = 0; i < 4; i++)
+ if (xf86nameCompare (direction[i], rotate_name) == 0)
+ return (1 << i);
+ return RR_Rotate_0;
+}
+
+_X_EXPORT xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr scrn,
+ const xf86OutputFuncsRec *funcs,
+ const char *name)
+{
+ xf86OutputPtr output, *outputs;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int len;
+
+ if (name)
+ len = strlen (name) + 1;
+ else
+ len = 0;
+
+ output = xcalloc (sizeof (xf86OutputRec) + len, 1);
+ if (!output)
+ return NULL;
+ output->scrn = scrn;
+ output->funcs = funcs;
+ if (name)
+ {
+ output->name = (char *) (output + 1);
+ strcpy (output->name, name);
+ }
+ output->subpixel_order = SubPixelUnknown;
+ /*
+ * Use the old per-screen monitor section for the first output
+ */
+ output->use_screen_monitor = (xf86_config->num_output == 0);
+#ifdef RANDR_12_INTERFACE
+ output->randr_output = NULL;
+#endif
+ if (name)
+ {
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ {
+ xfree (output);
+ return FALSE;
+ }
+ }
+
+
+ if (xf86_config->output)
+ outputs = xrealloc (xf86_config->output,
+ (xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ else
+ outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr));
+ if (!outputs)
+ {
+ xfree (output);
+ return NULL;
+ }
+
+ xf86_config->output = outputs;
+ xf86_config->output[xf86_config->num_output++] = output;
+
+ return output;
+}
+
+_X_EXPORT Bool
+xf86OutputRename (xf86OutputPtr output, const char *name)
+{
+ int len = strlen(name) + 1;
+ char *newname = xalloc (len);
+
+ if (!newname)
+ return FALSE; /* so sorry... */
+
+ strcpy (newname, name);
+ if (output->name && output->name != (char *) (output + 1))
+ xfree (output->name);
+ output->name = newname;
+ xf86OutputSetMonitor (output);
+ if (xf86OutputIgnored (output))
+ return FALSE;
+ return TRUE;
+}
+
+_X_EXPORT void
+xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor)
+{
+ if (use_screen_monitor != output->use_screen_monitor)
+ {
+ output->use_screen_monitor = use_screen_monitor;
+ xf86OutputSetMonitor (output);
+ }
+}
+
+_X_EXPORT void
+xf86OutputDestroy (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ (*output->funcs->destroy) (output);
+ while (output->probed_modes)
+ xf86DeleteMode (&output->probed_modes, output->probed_modes);
+ for (o = 0; o < xf86_config->num_output; o++)
+ if (xf86_config->output[o] == output)
+ {
+ memmove (&xf86_config->output[o],
+ &xf86_config->output[o+1],
+ ((xf86_config->num_output - (o + 1)) * sizeof(void*)));
+ xf86_config->num_output--;
+ break;
+ }
+ if (output->name && output->name != (char *) (output + 1))
+ xfree (output->name);
+ xfree (output);
+}
+
+/*
+ * Called during CreateScreenResources to hook up RandR
+ */
+static Bool
+xf86CrtcCreateScreenResources (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ screen->CreateScreenResources = config->CreateScreenResources;
+
+ if (!(*screen->CreateScreenResources)(screen))
+ return FALSE;
+
+ if (!xf86RandR12CreateScreenResources (screen))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Clean up config on server reset
+ */
+static Bool
+xf86CrtcCloseScreen (int index, ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+
+ screen->CloseScreen = config->CloseScreen;
+
+ xf86RotateCloseScreen (screen);
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->randr_output = NULL;
+ }
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->randr_crtc = NULL;
+ }
+ return screen->CloseScreen (index, screen);
+}
+
+/*
+ * Called at ScreenInit time to set up
+ */
+_X_EXPORT Bool
+xf86CrtcScreenInit (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ /* Rotation */
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
+ xf86DisableRandR(); /* Disable old RandR extension support */
+ xf86RandR12Init (screen);
+
+ /* support all rotations if every crtc has the shadow alloc funcs */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create)
+ break;
+ }
+ if (c == config->num_crtc)
+ xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
+ RR_Rotate_180 | RR_Rotate_270 |
+ RR_Reflect_X | RR_Reflect_Y);
+ else
+ xf86RandR12SetRotations (screen, RR_Rotate_0);
+
+ /* Wrap CreateScreenResources so we can initialize the RandR code */
+ config->CreateScreenResources = screen->CreateScreenResources;
+ screen->CreateScreenResources = xf86CrtcCreateScreenResources;
+
+ config->CloseScreen = screen->CloseScreen;
+ screen->CloseScreen = xf86CrtcCloseScreen;
+
+ return TRUE;
+}
+
+static DisplayModePtr
+xf86DefaultMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+ int target_preferred = 0;
+ int mm_height;
+
+ mm_height = output->mm_height;
+ if (!mm_height)
+ mm_height = 203; /* 768 pixels at 96dpi */
+ /*
+ * Pick a mode closest to 96dpi
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dpi;
+ int preferred = (mode->type & M_T_PREFERRED) != 0;
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* yes, use VDisplay here, not xf86ModeHeight */
+ dpi = (mode->VDisplay * 254) / (mm_height * 10);
+ diff = dpi - 96;
+ diff = diff < 0 ? -diff : diff;
+ if (target_mode == NULL || (preferred > target_preferred) ||
+ (preferred == target_preferred && diff < target_diff))
+ {
+ target_mode = mode;
+ target_diff = diff;
+ target_preferred = preferred;
+ }
+ }
+ return target_mode;
+}
+
+static DisplayModePtr
+xf86ClosestMode (xf86OutputPtr output,
+ DisplayModePtr match, Rotation match_rotation,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ DisplayModePtr mode;
+ int target_diff = 0;
+
+ /*
+ * Pick a mode closest to the specified mode
+ */
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ int dx, dy;
+ int diff;
+
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* exact matches are preferred */
+ if (output->initial_rotation == match_rotation &&
+ xf86ModesEqual (mode, match))
+ return mode;
+
+ dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation);
+ dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation);
+ diff = dx * dx + dy * dy;
+ if (target_mode == NULL || diff < target_diff)
+ {
+ target_mode = mode;
+ target_diff = diff;
+ }
+ }
+ return target_mode;
+}
+
+static Bool
+xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
+{
+ DisplayModePtr mode;
+
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ if (mode->type & M_T_PREFERRED)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int
+xf86PickCrtcs (ScrnInfoPtr scrn,
+ xf86CrtcPtr *best_crtcs,
+ DisplayModePtr *modes,
+ int n,
+ int width,
+ int height)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ xf86CrtcPtr *crtcs;
+ xf86CrtcPtr best_crtc;
+ int best_score;
+ int score;
+ int my_score;
+
+ if (n == config->num_output)
+ return 0;
+ output = config->output[n];
+
+ /*
+ * Compute score with this output disabled
+ */
+ best_crtcs[n] = NULL;
+ best_crtc = NULL;
+ best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
+ if (modes[n] == NULL)
+ return best_score;
+
+ crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr));
+ if (!crtcs)
+ return best_score;
+
+ my_score = 1;
+ /* Score outputs that are known to be connected higher */
+ if (output->status == XF86OutputStatusConnected)
+ my_score++;
+ /* Score outputs with preferred modes higher */
+ if (xf86OutputHasPreferredMode (output, width, height))
+ my_score++;
+ /*
+ * Select a crtc for this output and
+ * then attempt to configure the remaining
+ * outputs
+ */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ if ((output->possible_crtcs & (1 << c)) == 0)
+ continue;
+
+ crtc = config->crtc[c];
+ /*
+ * Check to see if some other output is
+ * using this crtc
+ */
+ for (o = 0; o < n; o++)
+ if (best_crtcs[o] == crtc)
+ break;
+ if (o < n)
+ {
+ /*
+ * If the two outputs desire the same mode,
+ * see if they can be cloned
+ */
+ if (xf86ModesEqual (modes[o], modes[n]) &&
+ config->output[0]->initial_rotation == config->output[n]->initial_rotation &&
+ config->output[o]->initial_x == config->output[n]->initial_x &&
+ config->output[o]->initial_y == config->output[n]->initial_y)
+ {
+ if ((output->possible_clones & (1 << o)) == 0)
+ continue; /* nope, try next CRTC */
+ }
+ else
+ continue; /* different modes, can't clone */
+ }
+ crtcs[n] = crtc;
+ memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
+ score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
+ if (score > best_score)
+ {
+ best_crtc = crtc;
+ best_score = score;
+ memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
+ }
+ }
+ xfree (crtcs);
+ return best_score;
+}
+
+
+/*
+ * Compute the virtual size necessary to place all of the available
+ * crtcs in the specified configuration.
+ *
+ * canGrow indicates that the driver can make the screen larger than its initial
+ * configuration. If FALSE, this function will enlarge the screen to include
+ * the largest available mode.
+ */
+
+static void
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
+ Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int width = 0, height = 0;
+ int o;
+ int c;
+ int s;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ int crtc_width = 0, crtc_height = 0;
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ if (crtc->enabled)
+ {
+ crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
+ crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
+ }
+ if (!canGrow) {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ for (s = 0; s < config->num_crtc; s++)
+ if (output->possible_crtcs & (1 << s))
+ {
+ DisplayModePtr mode;
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (mode->HDisplay > crtc_width)
+ crtc_width = mode->HDisplay;
+ if (mode->VDisplay > crtc_width)
+ crtc_width = mode->VDisplay;
+ if (mode->VDisplay > crtc_height)
+ crtc_height = mode->VDisplay;
+ if (mode->HDisplay > crtc_height)
+ crtc_height = mode->HDisplay;
+ }
+ }
+ }
+ }
+ if (crtc_width > width)
+ width = crtc_width;
+ if (crtc_height > height)
+ height = crtc_height;
+ }
+ if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
+ if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
+ if (config->minWidth && width < config->minWidth) width = config->minWidth;
+ if (config->minHeight && height < config->minHeight) height = config->minHeight;
+ *widthp = width;
+ *heightp = height;
+}
+
+#define POSITION_UNSET -100000
+
+static Bool
+xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+ int min_x, min_y;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x = output->initial_y = POSITION_UNSET;
+ }
+
+ /*
+ * Loop until all outputs are set
+ */
+ for (;;)
+ {
+ Bool any_set = FALSE;
+ Bool keep_going = FALSE;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ static const OutputOpts relations[] = {
+ OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF
+ };
+ xf86OutputPtr output = config->output[o];
+ xf86OutputPtr relative;
+ char *relative_name;
+ char *position;
+ OutputOpts relation;
+ int r;
+
+ if (output->initial_x != POSITION_UNSET)
+ continue;
+ position = xf86GetOptValString (output->options,
+ OPTION_POSITION);
+ /*
+ * Absolute position wins
+ */
+ if (position)
+ {
+ int x, y;
+ if (sscanf (position, "%d %d", &x, &y) == 2)
+ {
+ output->initial_x = x;
+ output->initial_y = y;
+ }
+ else
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s position not of form \"x y\"\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ }
+ any_set = TRUE;
+ continue;
+ }
+ /*
+ * Next comes relative positions
+ */
+ relation = 0;
+ relative_name = NULL;
+ for (r = 0; r < 4; r++)
+ {
+ relation = relations[r];
+ relative_name = xf86GetOptValString (output->options,
+ relation);
+ if (relative_name)
+ break;
+ }
+ if (relative_name)
+ {
+ int or;
+ relative = NULL;
+ for (or = 0; or < config->num_output; or++)
+ {
+ xf86OutputPtr out_rel = config->output[or];
+ XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
+
+ if (rel_mon)
+ {
+ if (xf86nameCompare (rel_mon->mon_identifier,
+ relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (strcmp (out_rel->name, relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (!relative)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to unknown output %s\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
+ if (relative->initial_x == POSITION_UNSET)
+ {
+ keep_going = TRUE;
+ continue;
+ }
+ output->initial_x = relative->initial_x;
+ output->initial_y = relative->initial_y;
+ switch (relation) {
+ case OPTION_BELOW:
+ output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_RIGHT_OF:
+ output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_ABOVE:
+ output->initial_y -= xf86ModeHeight (modes[or], relative->initial_rotation);
+ break;
+ case OPTION_LEFT_OF:
+ output->initial_x -= xf86ModeWidth (modes[or], relative->initial_rotation);
+ break;
+ default:
+ break;
+ }
+ any_set = TRUE;
+ continue;
+ }
+
+ /* Nothing set, just stick them at 0,0 */
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ }
+ if (!keep_going)
+ break;
+ if (!any_set)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ if (output->initial_x == POSITION_UNSET)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output position loop. Moving %s to 0,0\n",
+ output->name);
+ output->initial_x = output->initial_y = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * normalize positions
+ */
+ min_x = 1000000;
+ min_y = 1000000;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (output->initial_x < min_x)
+ min_x = output->initial_x;
+ if (output->initial_y < min_y)
+ min_y = output->initial_y;
+ }
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->initial_x -= min_x;
+ output->initial_y -= min_y;
+ }
+ return TRUE;
+}
+
+/*
+ * XXX walk the monitor mode list and prune out duplicates that
+ * are inserted by xf86DDCMonitorSet. In an ideal world, that
+ * function would do this work by itself.
+ */
+
+static void
+xf86PruneDuplicateMonitorModes (MonPtr Monitor)
+{
+ DisplayModePtr master, clone, next;
+
+ for (master = Monitor->Modes;
+ master && master != Monitor->Last;
+ master = master->next)
+ {
+ for (clone = master->next; clone && clone != Monitor->Modes; clone = next)
+ {
+ next = clone->next;
+ if (xf86ModesEqual (master, clone))
+ {
+ if (Monitor->Last == clone)
+ Monitor->Last = clone->prev;
+ xf86DeleteMode (&Monitor->Modes, clone);
+ }
+ }
+ }
+}
+
+/** Return - 0 + if a should be earlier, same or later than b in list
+ */
+static int
+xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+{
+ int diff;
+
+ diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0);
+ if (diff)
+ return diff;
+ diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay;
+ if (diff)
+ return diff;
+ diff = b->Clock - a->Clock;
+ return diff;
+}
+
+/**
+ * Insertion sort input in-place and return the resulting head
+ */
+static DisplayModePtr
+xf86SortModes (DisplayModePtr input)
+{
+ DisplayModePtr output = NULL, i, o, n, *op, prev;
+
+ /* sort by preferred status and pixel area */
+ while (input)
+ {
+ i = input;
+ input = input->next;
+ for (op = &output; (o = *op); op = &o->next)
+ if (xf86ModeCompare (o, i) > 0)
+ break;
+ i->next = *op;
+ *op = i;
+ }
+ /* prune identical modes */
+ for (o = output; o && (n = o->next); o = n)
+ {
+ if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n))
+ {
+ o->next = n->next;
+ xfree (n->name);
+ xfree (n);
+ n = o;
+ }
+ }
+ /* hook up backward links */
+ prev = NULL;
+ for (o = output; o; o = o->next)
+ {
+ o->prev = prev;
+ prev = o;
+ }
+ return output;
+}
+
+_X_EXPORT void
+xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o;
+
+ /* When canGrow was TRUE in the initial configuration we have to
+ * compare against the maximum values so that we don't drop modes.
+ * When canGrow was FALSE, the maximum values would have been clamped
+ * anyway.
+ */
+ if (maxX == 0 || maxY == 0) {
+ maxX = config->maxWidth;
+ maxY = config->maxHeight;
+ }
+
+ /* Elide duplicate modes before defaulting code uses them */
+ xf86PruneDuplicateMonitorModes (scrn->monitor);
+
+ /* Probe the list of modes for each output. */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode;
+ DisplayModePtr config_modes = NULL, output_modes, default_modes;
+ char *preferred_mode;
+ xf86MonPtr edid_monitor;
+ XF86ConfMonitorPtr conf_monitor;
+ MonRec mon_rec;
+ int min_clock = 0;
+ int max_clock = 0;
+ double clock;
+ enum { sync_config, sync_edid, sync_default } sync_source = sync_default;
+
+ while (output->probed_modes != NULL)
+ xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+ /*
+ * Check connection status
+ */
+ output->status = (*output->funcs->detect)(output);
+
+ if (output->status == XF86OutputStatusDisconnected)
+ {
+ xf86OutputSetEDID (output, NULL);
+ continue;
+ }
+
+ memset (&mon_rec, '\0', sizeof (mon_rec));
+
+ conf_monitor = output->conf_monitor;
+
+ if (conf_monitor)
+ {
+ int i;
+
+ for (i = 0; i < conf_monitor->mon_n_hsync; i++)
+ {
+ mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo;
+ mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi;
+ mon_rec.nHsync++;
+ sync_source = sync_config;
+ }
+ for (i = 0; i < conf_monitor->mon_n_vrefresh; i++)
+ {
+ mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo;
+ mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi;
+ mon_rec.nVrefresh++;
+ sync_source = sync_config;
+ }
+ config_modes = xf86GetMonitorModes (scrn, conf_monitor);
+ }
+
+ output_modes = (*output->funcs->get_modes) (output);
+
+ edid_monitor = output->MonInfo;
+
+ if (edid_monitor)
+ {
+ int i;
+ Bool set_hsync = mon_rec.nHsync == 0;
+ Bool set_vrefresh = mon_rec.nVrefresh == 0;
+
+ for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++)
+ {
+ if (edid_monitor->det_mon[i].type == DS_RANGES)
+ {
+ struct monitor_ranges *ranges = &edid_monitor->det_mon[i].section.ranges;
+ if (set_hsync && ranges->max_h)
+ {
+ mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h;
+ mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h;
+ mon_rec.nHsync++;
+ if (sync_source == sync_default)
+ sync_source = sync_edid;
+ }
+ if (set_vrefresh && ranges->max_v)
+ {
+ mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v;
+ mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v;
+ mon_rec.nVrefresh++;
+ if (sync_source == sync_default)
+ sync_source = sync_edid;
+ }
+ if (ranges->max_clock > max_clock)
+ max_clock = ranges->max_clock;
+ }
+ }
+ }
+
+ if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ min_clock = (int) clock;
+ if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK,
+ OPTUNITS_KHZ, &clock))
+ max_clock = (int) clock;
+
+ /*
+ * These limits will end up setting a 1024x768@60Hz mode by default,
+ * which seems like a fairly good mode to use when nothing else is
+ * specified
+ */
+ if (mon_rec.nHsync == 0)
+ {
+ mon_rec.hsync[0].lo = 31.0;
+ mon_rec.hsync[0].hi = 55.0;
+ mon_rec.nHsync = 1;
+ }
+ if (mon_rec.nVrefresh == 0)
+ {
+ mon_rec.vrefresh[0].lo = 58.0;
+ mon_rec.vrefresh[0].hi = 62.0;
+ mon_rec.nVrefresh = 1;
+ }
+ default_modes = xf86GetDefaultModes (output->interlaceAllowed,
+ output->doubleScanAllowed);
+
+ if (sync_source == sync_config)
+ {
+ /*
+ * Check output and config modes against sync range from config file
+ */
+ xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+ xf86ValidateModesSync (scrn, config_modes, &mon_rec);
+ }
+ /*
+ * Check default modes against sync range
+ */
+ xf86ValidateModesSync (scrn, default_modes, &mon_rec);
+ /*
+ * Check default modes against monitor max clock
+ */
+ if (max_clock)
+ xf86ValidateModesClocks(scrn, default_modes,
+ &min_clock, &max_clock, 1);
+
+ output->probed_modes = NULL;
+ output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes);
+ output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes);
+
+ /*
+ * Check all modes against max size
+ */
+ if (maxX && maxY)
+ xf86ValidateModesSize (scrn, output->probed_modes,
+ maxX, maxY, 0);
+
+ /*
+ * Check all modes against output
+ */
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ if (mode->status == MODE_OK)
+ mode->status = (*output->funcs->mode_valid)(output, mode);
+
+ xf86PruneInvalidModes(scrn, &output->probed_modes,
+ config->debug_modes);
+
+ output->probed_modes = xf86SortModes (output->probed_modes);
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = xf86GetOptValString (output->options,
+ OPTION_PREFERRED_MODE);
+
+ if (preferred_mode)
+ {
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (!strcmp (preferred_mode, mode->name))
+ {
+ if (mode != output->probed_modes)
+ {
+ if (mode->prev)
+ mode->prev->next = mode->next;
+ if (mode->next)
+ mode->next->prev = mode->prev;
+ mode->next = output->probed_modes;
+ output->probed_modes->prev = mode;
+ mode->prev = NULL;
+ output->probed_modes = mode;
+ }
+ mode->type |= M_T_PREFERRED;
+ }
+ else
+ mode->type &= ~M_T_PREFERRED;
+ }
+ }
+
+ output->initial_rotation = xf86OutputInitialRotation (output);
+
+ if (config->debug_modes) {
+ if (output->probed_modes != NULL) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Printing probed modes for output %s\n",
+ output->name);
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "No remaining probed modes for output %s\n",
+ output->name);
+ }
+ }
+ for (mode = output->probed_modes; mode != NULL; mode = mode->next)
+ {
+ /* The code to choose the best mode per pipe later on will require
+ * VRefresh to be set.
+ */
+ mode->VRefresh = xf86ModeVRefresh(mode);
+ xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+
+ if (config->debug_modes)
+ xf86PrintModeline(scrn->scrnIndex, mode);
+ }
+ }
+}
+
+
+/**
+ * Copy one of the output mode lists to the ScrnInfo record
+ */
+
+/* XXX where does this function belong? Here? */
+_X_EXPORT void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
+
+_X_EXPORT void
+xf86SetScrnInfoModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86OutputPtr output;
+ xf86CrtcPtr crtc;
+ DisplayModePtr last, mode;
+
+ output = config->output[config->compat_output];
+ if (!output->crtc)
+ {
+ int o;
+
+ output = NULL;
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc)
+ {
+ config->compat_output = o;
+ output = config->output[o];
+ break;
+ }
+ /* no outputs are active, punt and leave things as they are */
+ if (!output)
+ return;
+ }
+ crtc = output->crtc;
+
+ /* Clear any existing modes from scrn->modes */
+ while (scrn->modes != NULL)
+ xf86DeleteMode(&scrn->modes, scrn->modes);
+
+ /* Set scrn->modes to the mode list for the 'compat' output */
+ scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
+
+ for (mode = scrn->modes; mode; mode = mode->next)
+ if (xf86ModesEqual (mode, &crtc->desiredMode))
+ break;
+
+ if (scrn->modes != NULL) {
+ /* For some reason, scrn->modes is circular, unlike the other mode
+ * lists. How great is that?
+ */
+ for (last = scrn->modes; last && last->next; last = last->next)
+ ;
+ last->next = scrn->modes;
+ scrn->modes->prev = last;
+ if (mode) {
+ while (scrn->modes != mode)
+ scrn->modes = scrn->modes->next;
+ }
+ }
+ scrn->currentMode = scrn->modes;
+}
+
+/**
+ * Construct default screen configuration
+ *
+ * Given auto-detected (and, eventually, configured) values,
+ * construct a usable configuration for the system
+ *
+ * canGrow indicates that the driver can resize the screen to larger than its
+ * initially configured size via the config->funcs->resize hook. If TRUE, this
+ * function will set virtualX and virtualY to match the initial configuration
+ * and leave config->max{Width,Height} alone. If FALSE, it will bloat
+ * virtual[XY] to include the largest modes and set config->max{Width,Height}
+ * accordingly.
+ */
+
+_X_EXPORT Bool
+xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int o, c;
+ DisplayModePtr target_mode = NULL;
+ Rotation target_rotation = RR_Rotate_0;
+ xf86CrtcPtr *crtcs;
+ DisplayModePtr *modes;
+ Bool *enabled;
+ int width;
+ int height;
+
+ /* Set up the device options */
+ config->options = xnfalloc (sizeof (xf86DeviceOptions));
+ memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions));
+ xf86ProcessOptions (scrn->scrnIndex,
+ scrn->options,
+ config->options);
+ config->debug_modes = xf86ReturnOptValBool (config->options,
+ OPTION_MODEDEBUG, FALSE);
+
+ if (scrn->display->virtualX)
+ width = scrn->display->virtualX;
+ else
+ width = config->maxWidth;
+ if (scrn->display->virtualY)
+ height = scrn->display->virtualY;
+ else
+ height = config->maxHeight;
+
+ xf86ProbeOutputModes (scrn, width, height);
+
+ crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
+ modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+ enabled = xnfcalloc (config->num_output, sizeof (Bool));
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ modes[o] = NULL;
+ enabled[o] = xf86OutputEnabled (output);
+ }
+
+ /*
+ * Let outputs with preferred modes drive screen size
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (enabled[o] &&
+ xf86OutputHasPreferredMode (output, width, height))
+ {
+ target_mode = xf86DefaultMode (output, width, height);
+ target_rotation = output->initial_rotation;
+ if (target_mode)
+ {
+ modes[o] = target_mode;
+ config->compat_output = o;
+ break;
+ }
+ }
+ }
+ if (!target_mode)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ if (enabled[o])
+ {
+ target_mode = xf86DefaultMode (output, width, height);
+ target_rotation = output->initial_rotation;
+ if (target_mode)
+ {
+ modes[o] = target_mode;
+ config->compat_output = o;
+ break;
+ }
+ }
+ }
+ }
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ if (enabled[o])
+ {
+ if (!modes[o])
+ modes[o] = xf86ClosestMode (output, target_mode,
+ target_rotation, width, height);
+ if (!modes[o])
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s enabled but has no modes\n",
+ output->name);
+ else
+ xf86DrvMsg (scrn->scrnIndex, X_INFO,
+ "Output %s using initial mode %s\n",
+ output->name, modes[o]->name);
+ }
+ }
+
+ /*
+ * Set the position of each output
+ */
+ if (!xf86InitialOutputPositions (scrn, modes))
+ {
+ xfree (crtcs);
+ xfree (modes);
+ return FALSE;
+ }
+
+ /*
+ * Assign CRTCs to fit output configuration
+ */
+ if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
+ {
+ xfree (crtcs);
+ xfree (modes);
+ return FALSE;
+ }
+
+ /* XXX override xf86 common frame computation code */
+
+ scrn->display->frameX0 = 0;
+ scrn->display->frameY0 = 0;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->enabled = FALSE;
+ memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
+ }
+
+ /*
+ * Set initial configuration
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr mode = modes[o];
+ xf86CrtcPtr crtc = crtcs[o];
+
+ if (mode && crtc)
+ {
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = output->initial_rotation;
+ crtc->desiredX = output->initial_x;
+ crtc->desiredY = output->initial_y;
+ crtc->enabled = TRUE;
+ crtc->x = output->initial_x;
+ crtc->y = output->initial_y;
+ output->crtc = crtc;
+ }
+ }
+
+ if (scrn->display->virtualX == 0)
+ {
+ /*
+ * Expand virtual size to cover the current config and potential mode
+ * switches, if the driver can't enlarge the screen later.
+ */
+ xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
+
+ scrn->display->virtualX = width;
+ scrn->display->virtualY = height;
+ }
+
+ if (width > scrn->virtualX)
+ scrn->virtualX = width;
+ if (height > scrn->virtualY)
+ scrn->virtualY = height;
+
+ /*
+ * Make sure the configuration isn't too small.
+ */
+ if (width < config->minWidth || height < config->minHeight)
+ return FALSE;
+
+ /*
+ * Limit the crtc config to virtual[XY] if the driver can't grow the
+ * desktop.
+ */
+ if (!canGrow)
+ {
+ xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
+ width, height);
+ }
+
+ /* Mirror output modes to scrn mode list */
+ xf86SetScrnInfoModes (scrn);
+
+ xfree (crtcs);
+ xfree (modes);
+ return TRUE;
+}
+
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+_X_EXPORT Bool
+xf86SetDesiredModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+
+ /*
+ * Turn off everything so mode setting is done
+ * with hardware in a consistent state
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->funcs->dpms(crtc, DPMSModeOff);
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ }
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ xf86OutputPtr output = NULL;
+ int o;
+
+ if (config->output[config->compat_output]->crtc == crtc)
+ output = config->output[config->compat_output];
+ else
+ {
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc == crtc)
+ {
+ output = config->output[o];
+ break;
+ }
+ }
+ /*
+ * Skip disabled crtcs
+ */
+ if (!output)
+ continue;
+
+ /* Mark that we'll need to re-set the mode for sure */
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ if (!crtc->desiredMode.CrtcHDisplay)
+ {
+ DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode);
+
+ if (!mode)
+ return FALSE;
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = RR_Rotate_0;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+
+ if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
+ crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ }
+
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+}
+
+/**
+ * In the current world order, there are lists of modes per output, which may
+ * or may not include the mode that was asked to be set by XFree86's mode
+ * selection. Find the closest one, in the following preference order:
+ *
+ * - Equality
+ * - Closer in size to the requested mode, but no larger
+ * - Closer in refresh rate to the requested mode.
+ */
+
+_X_EXPORT DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
+{
+ DisplayModePtr best = NULL, scan = NULL;
+
+ for (scan = output->probed_modes; scan != NULL; scan = scan->next)
+ {
+ /* If there's an exact match, we're done. */
+ if (xf86ModesEqual(scan, desired)) {
+ best = desired;
+ break;
+ }
+
+ /* Reject if it's larger than the desired mode. */
+ if (scan->HDisplay > desired->HDisplay ||
+ scan->VDisplay > desired->VDisplay)
+ {
+ continue;
+ }
+
+ /*
+ * If we haven't picked a best mode yet, use the first
+ * one in the size range
+ */
+ if (best == NULL)
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's closer to the right size than the current best
+ * option.
+ */
+ if ((scan->HDisplay > best->HDisplay &&
+ scan->VDisplay >= best->VDisplay) ||
+ (scan->HDisplay >= best->HDisplay &&
+ scan->VDisplay > best->VDisplay))
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's still closer to the right refresh than the current
+ * best resolution.
+ */
+ if (scan->HDisplay == best->HDisplay &&
+ scan->VDisplay == best->VDisplay &&
+ (fabs(scan->VRefresh - desired->VRefresh) <
+ fabs(best->VRefresh - desired->VRefresh))) {
+ best = scan;
+ }
+ }
+ return best;
+}
+
+/**
+ * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
+ * take the specified mode and apply it to the crtc connected to the compat
+ * output. Then, find similar modes for the other outputs, as with the
+ * InitialConfiguration code above. The goal is to clone the desired
+ * mode across all outputs that are currently active.
+ */
+
+_X_EXPORT Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ Bool ok = TRUE;
+ xf86OutputPtr compat_output = config->output[config->compat_output];
+ DisplayModePtr compat_mode;
+ int c;
+
+ /*
+ * Let the compat output drive the final mode selection
+ */
+ compat_mode = xf86OutputFindClosestMode (compat_output, desired);
+ if (compat_mode)
+ desired = compat_mode;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ DisplayModePtr crtc_mode = NULL;
+ int o;
+
+ if (!crtc->enabled)
+ continue;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr output_mode;
+
+ /* skip outputs not on this crtc */
+ if (output->crtc != crtc)
+ continue;
+
+ if (crtc_mode)
+ {
+ output_mode = xf86OutputFindClosestMode (output, crtc_mode);
+ if (output_mode != crtc_mode)
+ output->crtc = NULL;
+ }
+ else
+ crtc_mode = xf86OutputFindClosestMode (output, desired);
+ }
+ if (!crtc_mode)
+ {
+ crtc->enabled = FALSE;
+ continue;
+ }
+ if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
+ ok = FALSE;
+ else
+ {
+ crtc->desiredMode = *crtc_mode;
+ crtc->desiredRotation = rotation;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+ }
+ xf86DisableUnusedFunctions(pScrn);
+#if RANDR_12_INTERFACE
+ xf86RandR12TellChanged (pScrn->pScreen);
+#endif
+ return ok;
+}
+
+
+/**
+ * Set the DPMS power mode of all outputs and CRTCs.
+ *
+ * If the new mode is off, it will turn off outputs and then CRTCs.
+ * Otherwise, it will affect CRTCs before outputs.
+ */
+_X_EXPORT void
+xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+
+ if (!scrn->vtSema)
+ return;
+
+ if (mode == DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ if (crtc->enabled)
+ (*crtc->funcs->dpms) (crtc, mode);
+ }
+
+ if (mode != DPMSModeOff) {
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ if (output->crtc != NULL)
+ (*output->funcs->dpms) (output, mode);
+ }
+ }
+}
+
+/**
+ * Implement the screensaver by just calling down into the driver DPMS hooks.
+ *
+ * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
+ * the outputs will still get disabled (blanked).
+ */
+_X_EXPORT Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (xf86IsUnblank(mode))
+ xf86DPMSSet(pScrn, DPMSModeOn, 0);
+ else
+ xf86DPMSSet(pScrn, DPMSModeOff, 0);
+
+ return TRUE;
+}
+
+/**
+ * Disable all inactive crtcs and outputs
+ */
+_X_EXPORT void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o, c;
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+ if (!output->crtc)
+ (*output->funcs->dpms)(output, DPMSModeOff);
+ }
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!crtc->enabled)
+ {
+ crtc->funcs->dpms(crtc, DPMSModeOff);
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ }
+ }
+}
+
+#ifdef RANDR_12_INTERFACE
+
+#define EDID_ATOM_NAME "EDID_DATA"
+
+/**
+ * Set the RandR EDID property
+ */
+static void
+xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
+{
+ Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE);
+
+ /* This may get called before the RandR resources have been created */
+ if (output->randr_output == NULL)
+ return;
+
+ if (data_len != 0) {
+ RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
+ PropModeReplace, data_len, data, FALSE, TRUE);
+ } else {
+ RRDeleteOutputProperty(output->randr_output, edid_atom);
+ }
+}
+
+#endif
+
+/**
+ * Set the EDID information for the specified output
+ */
+_X_EXPORT void
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int i;
+#ifdef RANDR_12_INTERFACE
+ int size;
+#endif
+
+ if (output->MonInfo != NULL)
+ xfree(output->MonInfo);
+
+ output->MonInfo = edid_mon;
+
+ if (config->debug_modes) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n",
+ output->name);
+ xf86PrintEDID(edid_mon);
+ }
+
+ /* Set the DDC properties for the 'compat' output */
+ if (output == config->output[config->compat_output])
+ xf86SetDDCproperties(scrn, edid_mon);
+
+#ifdef RANDR_12_INTERFACE
+ /* Set the RandR output properties */
+ size = 0;
+ if (edid_mon)
+ {
+ if (edid_mon->ver.version == 1)
+ size = 128;
+ else if (edid_mon->ver.version == 2)
+ size = 256;
+ }
+ xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
+#endif
+
+ if (edid_mon)
+ {
+ /* Pull out a phyiscal size from a detailed timing if available. */
+ for (i = 0; i < 4; i++) {
+ if (edid_mon->det_mon[i].type == DT &&
+ edid_mon->det_mon[i].section.d_timings.h_size != 0 &&
+ edid_mon->det_mon[i].section.d_timings.v_size != 0)
+ {
+ output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size;
+ output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size;
+ break;
+ }
+ }
+
+ /* if no mm size is available from a detailed timing, check the max size field */
+ if ((!output->mm_width || !output->mm_height) &&
+ (edid_mon->features.hsize && edid_mon->features.vsize))
+ {
+ output->mm_width = edid_mon->features.hsize * 10;
+ output->mm_height = edid_mon->features.vsize * 10;
+ }
+ }
+}
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+_X_EXPORT DisplayModePtr
+xf86OutputGetEDIDModes (xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr edid_mon = output->MonInfo;
+
+ if (!edid_mon)
+ return NULL;
+ return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
+}
+
+_X_EXPORT xf86MonPtr
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+{
+ ScrnInfoPtr scrn = output->scrn;
+
+ return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
+}
+
+static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D",
+ "DVI-A", "Composite", "S-Video",
+ "Component", "LFP", "Proprietary" };
+_X_EXPORT char *
+xf86ConnectorGetName(xf86ConnectorType connector)
+{
+ return _xf86ConnectorNames[connector];
+}
+
+static void
+x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
+{
+ dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
+ dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
+ dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
+ dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
+
+ if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2)
+ dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
+}
+
+static void
+x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
+{
+ if (crtc->enabled) {
+ crtc_box->x1 = crtc->x;
+ crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
+ crtc_box->y1 = crtc->y;
+ crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
+ } else
+ crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
+static int
+xf86_crtc_box_area(BoxPtr box)
+{
+ return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
+}
+
+/*
+ * Return the crtc covering 'box'. If two crtcs cover a portion of
+ * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+ * with greater coverage
+ */
+
+static xf86CrtcPtr
+xf86_covering_crtc(ScrnInfoPtr pScrn,
+ BoxPtr box,
+ xf86CrtcPtr desired,
+ BoxPtr crtc_box_ret)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc, best_crtc;
+ int coverage, best_coverage;
+ int c;
+ BoxRec crtc_box, cover_box;
+
+ best_crtc = NULL;
+ best_coverage = 0;
+ crtc_box_ret->x1 = 0;
+ crtc_box_ret->x2 = 0;
+ crtc_box_ret->y1 = 0;
+ crtc_box_ret->y2 = 0;
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ crtc = xf86_config->crtc[c];
+ x86_crtc_box(crtc, &crtc_box);
+ x86_crtc_box_intersect(&cover_box, &crtc_box, box);
+ coverage = xf86_crtc_box_area(&cover_box);
+ if (coverage && crtc == desired) {
+ *crtc_box_ret = crtc_box;
+ return crtc;
+ } else if (coverage > best_coverage) {
+ *crtc_box_ret = crtc_box;
+ best_crtc = crtc;
+ best_coverage = coverage;
+ }
+ }
+ return best_crtc;
+}
+
+/*
+ * For overlay video, compute the relevant CRTC and
+ * clip video to that
+ */
+
+_X_EXPORT Bool
+xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
+ xf86CrtcPtr *crtc_ret,
+ xf86CrtcPtr desired_crtc,
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height)
+{
+ Bool ret;
+ RegionRec crtc_region_local;
+ RegionPtr crtc_region = reg;
+
+ if (crtc_ret) {
+ BoxRec crtc_box;
+ xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst,
+ desired_crtc,
+ &crtc_box);
+
+ if (crtc) {
+ REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1);
+ crtc_region = &crtc_region_local;
+ REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg);
+ }
+ *crtc_ret = crtc;
+ }
+
+ ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb,
+ crtc_region, width, height);
+
+ if (crtc_region != reg)
+ REGION_UNINIT (pScreen, &crtc_region_local);
+
+ return ret;
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86Crtc.h b/driver/xf86-video-intel/src/modes/xf86Crtc.h
new file mode 100644
index 000000000..9693e12bb
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Crtc.h
@@ -0,0 +1,788 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+#ifndef _XF86CRTC_H_
+#define _XF86CRTC_H_
+
+#include <edid.h>
+#include "randrstr.h"
+#if XF86_MODES_RENAME
+#include "xf86Rename.h"
+#endif
+#include "xf86Modes.h"
+#include "xf86Cursor.h"
+#include "damage.h"
+#include "picturestr.h"
+
+/* Compat definitions for older X Servers. */
+#ifndef M_T_PREFERRED
+#define M_T_PREFERRED 0x08
+#endif
+#ifndef M_T_DRIVER
+#define M_T_DRIVER 0x40
+#endif
+#ifndef HARDWARE_CURSOR_ARGB
+#define HARDWARE_CURSOR_ARGB 0x00004000
+#endif
+
+typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
+typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
+
+/* define a standard for connector types */
+typedef enum _xf86ConnectorType {
+ XF86ConnectorNone,
+ XF86ConnectorVGA,
+ XF86ConnectorDVI_I,
+ XF86ConnectorDVI_D,
+ XF86ConnectorDVI_A,
+ XF86ConnectorComposite,
+ XF86ConnectorSvideo,
+ XF86ConnectorComponent,
+ XF86ConnectorLFP,
+ XF86ConnectorProprietary,
+} xf86ConnectorType;
+
+typedef enum _xf86OutputStatus {
+ XF86OutputStatusConnected,
+ XF86OutputStatusDisconnected,
+ XF86OutputStatusUnknown,
+} xf86OutputStatus;
+
+typedef struct _xf86CrtcFuncs {
+ /**
+ * Turns the crtc on/off, or sets intermediate power levels if available.
+ *
+ * Unsupported intermediate modes drop to the lower power setting. If the
+ * mode is DPMSModeOff, the crtc must be disabled sufficiently for it to
+ * be safe to call mode_set.
+ */
+ void
+ (*dpms)(xf86CrtcPtr crtc,
+ int mode);
+
+ /**
+ * Saves the crtc's state for restoration on VT switch.
+ */
+ void
+ (*save)(xf86CrtcPtr crtc);
+
+ /**
+ * Restore's the crtc's state at VT switch.
+ */
+ void
+ (*restore)(xf86CrtcPtr crtc);
+
+ /**
+ * Lock CRTC prior to mode setting, mostly for DRI.
+ * Returns whether unlock is needed
+ */
+ Bool
+ (*lock) (xf86CrtcPtr crtc);
+
+ /**
+ * Unlock CRTC after mode setting, mostly for DRI
+ */
+ void
+ (*unlock) (xf86CrtcPtr crtc);
+
+ /**
+ * Callback to adjust the mode to be set in the CRTC.
+ *
+ * This allows a CRTC to adjust the clock or even the entire set of
+ * timings, which is used for panels with fixed timings or for
+ * buses with clock limitations.
+ */
+ Bool
+ (*mode_fixup)(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+
+ /**
+ * Prepare CRTC for an upcoming mode set.
+ */
+ void
+ (*prepare)(xf86CrtcPtr crtc);
+
+ /**
+ * Callback for setting up a video mode after fixups have been made.
+ */
+ void
+ (*mode_set)(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y);
+
+ /**
+ * Commit mode changes to a CRTC
+ */
+ void
+ (*commit)(xf86CrtcPtr crtc);
+
+ /* Set the color ramps for the CRTC to the given values. */
+ void
+ (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size);
+
+ /**
+ * Allocate the shadow area, delay the pixmap creation until needed
+ */
+ void *
+ (*shadow_allocate) (xf86CrtcPtr crtc, int width, int height);
+
+ /**
+ * Create shadow pixmap for rotation support
+ */
+ PixmapPtr
+ (*shadow_create) (xf86CrtcPtr crtc, void *data, int width, int height);
+
+ /**
+ * Destroy shadow pixmap
+ */
+ void
+ (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data);
+
+ /**
+ * Set cursor colors
+ */
+ void
+ (*set_cursor_colors) (xf86CrtcPtr crtc, int bg, int fg);
+
+ /**
+ * Set cursor position
+ */
+ void
+ (*set_cursor_position) (xf86CrtcPtr crtc, int x, int y);
+
+ /**
+ * Show cursor
+ */
+ void
+ (*show_cursor) (xf86CrtcPtr crtc);
+
+ /**
+ * Hide cursor
+ */
+ void
+ (*hide_cursor) (xf86CrtcPtr crtc);
+
+ /**
+ * Load monochrome image
+ */
+ void
+ (*load_cursor_image) (xf86CrtcPtr crtc, CARD8 *image);
+
+ /**
+ * Load ARGB image
+ */
+ void
+ (*load_cursor_argb) (xf86CrtcPtr crtc, CARD32 *image);
+
+ /**
+ * Clean up driver-specific bits of the crtc
+ */
+ void
+ (*destroy) (xf86CrtcPtr crtc);
+} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
+
+struct _xf86Crtc {
+ /**
+ * Associated ScrnInfo
+ */
+ ScrnInfoPtr scrn;
+
+ /**
+ * Active state of this CRTC
+ *
+ * Set when this CRTC is driving one or more outputs
+ */
+ Bool enabled;
+
+ /**
+ * Active mode
+ *
+ * This reflects the mode as set in the CRTC currently
+ * It will be cleared when the VT is not active or
+ * during server startup
+ */
+ DisplayModeRec mode;
+ Rotation rotation;
+ PixmapPtr rotatedPixmap;
+ void *rotatedData;
+
+ /**
+ * Position on screen
+ *
+ * Locates this CRTC within the frame buffer
+ */
+ int x, y;
+
+ /**
+ * Desired mode
+ *
+ * This is set to the requested mode, independent of
+ * whether the VT is active. In particular, it receives
+ * the startup configured mode and saves the active mode
+ * on VT switch.
+ */
+ DisplayModeRec desiredMode;
+ Rotation desiredRotation;
+ int desiredX, desiredY;
+
+ /** crtc-specific functions */
+ const xf86CrtcFuncsRec *funcs;
+
+ /**
+ * Driver private
+ *
+ * Holds driver-private information
+ */
+ void *driver_private;
+
+#ifdef RANDR_12_INTERFACE
+ /**
+ * RandR crtc
+ *
+ * When RandR 1.2 is available, this
+ * points at the associated crtc object
+ */
+ RRCrtcPtr randr_crtc;
+#else
+ void *randr_crtc;
+#endif
+
+ /**
+ * Current cursor is ARGB
+ */
+ Bool cursor_argb;
+ /**
+ * Track whether cursor is within CRTC range
+ */
+ Bool cursor_in_range;
+ /**
+ * Track state of cursor associated with this CRTC
+ */
+ Bool cursor_shown;
+
+ /**
+ * Current transformation matrix
+ */
+ PictTransform crtc_to_framebuffer;
+ PictTransform framebuffer_to_crtc;
+ Bool transform_in_use;
+ /**
+ * Bounding box in screen space
+ */
+ BoxRec bounds;
+};
+
+typedef struct _xf86OutputFuncs {
+ /**
+ * Called to allow the output a chance to create properties after the
+ * RandR objects have been created.
+ */
+ void
+ (*create_resources)(xf86OutputPtr output);
+
+ /**
+ * Turns the output on/off, or sets intermediate power levels if available.
+ *
+ * Unsupported intermediate modes drop to the lower power setting. If the
+ * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
+ * disabled afterwards.
+ */
+ void
+ (*dpms)(xf86OutputPtr output,
+ int mode);
+
+ /**
+ * Saves the output's state for restoration on VT switch.
+ */
+ void
+ (*save)(xf86OutputPtr output);
+
+ /**
+ * Restore's the output's state at VT switch.
+ */
+ void
+ (*restore)(xf86OutputPtr output);
+
+ /**
+ * Callback for testing a video mode for a given output.
+ *
+ * This function should only check for cases where a mode can't be supported
+ * on the output specifically, and not represent generic CRTC limitations.
+ *
+ * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+ */
+ int
+ (*mode_valid)(xf86OutputPtr output,
+ DisplayModePtr pMode);
+
+ /**
+ * Callback to adjust the mode to be set in the CRTC.
+ *
+ * This allows an output to adjust the clock or even the entire set of
+ * timings, which is used for panels with fixed timings or for
+ * buses with clock limitations.
+ */
+ Bool
+ (*mode_fixup)(xf86OutputPtr output,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+
+ /**
+ * Callback for preparing mode changes on an output
+ */
+ void
+ (*prepare)(xf86OutputPtr output);
+
+ /**
+ * Callback for committing mode changes on an output
+ */
+ void
+ (*commit)(xf86OutputPtr output);
+
+ /**
+ * Callback for setting up a video mode after fixups have been made.
+ *
+ * This is only called while the output is disabled. The dpms callback
+ * must be all that's necessary for the output, to turn the output on
+ * after this function is called.
+ */
+ void
+ (*mode_set)(xf86OutputPtr output,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+
+ /**
+ * Probe for a connected output, and return detect_status.
+ */
+ xf86OutputStatus
+ (*detect)(xf86OutputPtr output);
+
+ /**
+ * Query the device for the modes it provides.
+ *
+ * This function may also update MonInfo, mm_width, and mm_height.
+ *
+ * \return singly-linked list of modes or NULL if no modes found.
+ */
+ DisplayModePtr
+ (*get_modes)(xf86OutputPtr output);
+
+#ifdef RANDR_12_INTERFACE
+ /**
+ * Callback when an output's property has changed.
+ */
+ Bool
+ (*set_property)(xf86OutputPtr output,
+ Atom property,
+ RRPropertyValuePtr value);
+#endif
+ /**
+ * Clean up driver-specific bits of the output
+ */
+ void
+ (*destroy) (xf86OutputPtr output);
+} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
+
+struct _xf86Output {
+ /**
+ * Associated ScrnInfo
+ */
+ ScrnInfoPtr scrn;
+
+ /**
+ * Currently connected crtc (if any)
+ *
+ * If this output is not in use, this field will be NULL.
+ */
+ xf86CrtcPtr crtc;
+
+ /**
+ * Possible CRTCs for this output as a mask of crtc indices
+ */
+ CARD32 possible_crtcs;
+
+ /**
+ * Possible outputs to share the same CRTC as a mask of output indices
+ */
+ CARD32 possible_clones;
+
+ /**
+ * Whether this output can support interlaced modes
+ */
+ Bool interlaceAllowed;
+
+ /**
+ * Whether this output can support double scan modes
+ */
+ Bool doubleScanAllowed;
+
+ /**
+ * List of available modes on this output.
+ *
+ * This should be the list from get_modes(), plus perhaps additional
+ * compatible modes added later.
+ */
+ DisplayModePtr probed_modes;
+
+ /**
+ * Options parsed from the related monitor section
+ */
+ OptionInfoPtr options;
+
+ /**
+ * Configured monitor section
+ */
+ XF86ConfMonitorPtr conf_monitor;
+
+ /**
+ * Desired initial position
+ */
+ int initial_x, initial_y;
+
+ /**
+ * Desired initial rotation
+ */
+ Rotation initial_rotation;
+
+ /**
+ * Current connection status
+ *
+ * This indicates whether a monitor is known to be connected
+ * to this output or not, or whether there is no way to tell
+ */
+ xf86OutputStatus status;
+
+ /** EDID monitor information */
+ xf86MonPtr MonInfo;
+
+ /** subpixel order */
+ int subpixel_order;
+
+ /** Physical size of the currently attached output device. */
+ int mm_width, mm_height;
+
+ /** Output name */
+ char *name;
+
+ /** output-specific functions */
+ const xf86OutputFuncsRec *funcs;
+
+ /** driver private information */
+ void *driver_private;
+
+ /** Whether to use the old per-screen Monitor config section */
+ Bool use_screen_monitor;
+
+#ifdef RANDR_12_INTERFACE
+ /**
+ * RandR 1.2 output structure.
+ *
+ * When RandR 1.2 is available, this points at the associated
+ * RandR output structure and is created when this output is created
+ */
+ RROutputPtr randr_output;
+#else
+ void *randr_output;
+#endif
+};
+
+typedef struct _xf86CrtcConfigFuncs {
+ /**
+ * Requests that the driver resize the screen.
+ *
+ * The driver is responsible for updating scrn->virtualX and scrn->virtualY.
+ * If the requested size cannot be set, the driver should leave those values
+ * alone and return FALSE.
+ *
+ * A naive driver that cannot reallocate the screen may simply change
+ * virtual[XY]. A more advanced driver will want to also change the
+ * devPrivate.ptr and devKind of the screen pixmap, update any offscreen
+ * pixmaps it may have moved, and change pScrn->displayWidth.
+ */
+ Bool
+ (*resize)(ScrnInfoPtr scrn,
+ int width,
+ int height);
+} xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
+
+typedef struct _xf86CrtcConfig {
+ int num_output;
+ xf86OutputPtr *output;
+ /**
+ * compat_output is used whenever we deal
+ * with legacy code that only understands a single
+ * output. pScrn->modes will be loaded from this output,
+ * adjust frame will whack this output, etc.
+ */
+ int compat_output;
+
+ int num_crtc;
+ xf86CrtcPtr *crtc;
+
+ int minWidth, minHeight;
+ int maxWidth, maxHeight;
+
+ /* For crtc-based rotation */
+ DamagePtr rotation_damage;
+ Bool rotation_damage_registered;
+
+ /* DGA */
+ unsigned int dga_flags;
+ unsigned long dga_address;
+ DGAModePtr dga_modes;
+ int dga_nmode;
+ int dga_width, dga_height, dga_stride;
+ DisplayModePtr dga_save_mode;
+
+ const xf86CrtcConfigFuncsRec *funcs;
+
+ CreateScreenResourcesProcPtr CreateScreenResources;
+
+ CloseScreenProcPtr CloseScreen;
+
+ /* Cursor information */
+ xf86CursorInfoPtr cursor_info;
+ CursorPtr cursor;
+ CARD8 *cursor_image;
+ Bool cursor_on;
+ CARD32 cursor_fg, cursor_bg;
+
+ /**
+ * Options parsed from the related device section
+ */
+ OptionInfoPtr options;
+
+ Bool debug_modes;
+
+ /* wrap screen BlockHandler for rotation */
+ ScreenBlockHandlerProcPtr BlockHandler;
+
+} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
+
+extern int xf86CrtcConfigPrivateIndex;
+
+#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr))
+
+/*
+ * Initialize xf86CrtcConfig structure
+ */
+
+void
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs);
+
+void
+xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
+ int minWidth, int minHeight,
+ int maxWidth, int maxHeight);
+
+/*
+ * Crtc functions
+ */
+xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr scrn,
+ const xf86CrtcFuncsRec *funcs);
+
+void
+xf86CrtcDestroy (xf86CrtcPtr crtc);
+
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+ int x, int y);
+
+/*
+ * Assign crtc rotation during mode set
+ */
+Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+
+/*
+ * Clean up rotation during CloseScreen
+ */
+void
+xf86RotateCloseScreen (ScreenPtr pScreen);
+
+/**
+ * Return whether any output is assigned to the crtc
+ */
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc);
+
+/*
+ * Output functions
+ */
+xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr scrn,
+ const xf86OutputFuncsRec *funcs,
+ const char *name);
+
+void
+xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor);
+
+Bool
+xf86OutputRename (xf86OutputPtr output, const char *name);
+
+void
+xf86OutputDestroy (xf86OutputPtr output);
+
+void
+xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY);
+
+void
+xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
+
+Bool
+xf86CrtcScreenInit (ScreenPtr pScreen);
+
+Bool
+xf86InitialConfiguration (ScrnInfoPtr pScrn, Bool canGrow);
+
+void
+xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
+
+Bool
+xf86SaveScreen(ScreenPtr pScreen, int mode);
+
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+
+DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired);
+
+Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation);
+
+/**
+ * Set the EDID information for the specified output
+ */
+void
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
+
+/**
+ * Return the list of modes supported by the EDID information
+ * stored in 'output'
+ */
+DisplayModePtr
+xf86OutputGetEDIDModes (xf86OutputPtr output);
+
+xf86MonPtr
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
+
+/**
+ * Initialize dga for this screen
+ */
+
+Bool
+xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address);
+
+/**
+ * Re-initialize dga for this screen (as when the set of modes changes)
+ */
+
+Bool
+xf86DiDGAReInit (ScreenPtr pScreen);
+
+/*
+ * Set the subpixel order reported for the screen using
+ * the information from the outputs
+ */
+
+void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen);
+
+/*
+ * Get a standard string name for a connector type
+ */
+char *
+xf86ConnectorGetName(xf86ConnectorType connector);
+
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+Bool
+xf86SetDesiredModes (ScrnInfoPtr pScrn);
+
+/**
+ * Initialize the CRTC-based cursor code. CRTC function vectors must
+ * contain relevant cursor setting functions.
+ *
+ * Driver should call this from ScreenInit function
+ */
+Bool
+xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags);
+
+/**
+ * Called when anything on the screen is reconfigured.
+ *
+ * Reloads cursor images as needed, then adjusts cursor positions.
+ *
+ * Driver should call this from crtc commit function.
+ */
+void
+xf86_reload_cursors (ScreenPtr screen);
+
+/**
+ * Called from EnterVT to turn the cursors back on
+ */
+void
+xf86_show_cursors (ScrnInfoPtr scrn);
+
+/**
+ * Called by the driver to turn cursors off
+ */
+void
+xf86_hide_cursors (ScrnInfoPtr scrn);
+
+/**
+ * Clean up CRTC-based cursor code. Driver must call this at CloseScreen time.
+ */
+void
+xf86_cursors_fini (ScreenPtr screen);
+
+/*
+ * For overlay video, compute the relevant CRTC and
+ * clip video to that.
+ * wraps xf86XVClipVideoHelper()
+ */
+
+Bool
+xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
+ xf86CrtcPtr *crtc_ret,
+ xf86CrtcPtr desired_crtc,
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height);
+
+#endif /* _XF86CRTC_H_ */
diff --git a/driver/xf86-video-intel/src/modes/xf86Cursors.c b/driver/xf86-video-intel/src/modes/xf86Cursors.c
new file mode 100644
index 000000000..b5101642b
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Cursors.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+#include "cursorstr.h"
+
+/*
+ * Given a screen coordinate, rotate back to a cursor source coordinate
+ */
+static void
+xf86_crtc_rotate_coord (Rotation rotation,
+ int width,
+ int height,
+ int x_dst,
+ int y_dst,
+ int *x_src,
+ int *y_src)
+{
+ int t;
+
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ break;
+ case RR_Rotate_90:
+ t = x_dst;
+ x_dst = height - y_dst - 1;
+ y_dst = t;
+ break;
+ case RR_Rotate_180:
+ x_dst = width - x_dst - 1;
+ y_dst = height - y_dst - 1;
+ break;
+ case RR_Rotate_270:
+ t = x_dst;
+ x_dst = y_dst;
+ y_dst = width - t - 1;
+ break;
+ }
+ if (rotation & RR_Reflect_X)
+ x_dst = width - x_dst - 1;
+ if (rotation & RR_Reflect_Y)
+ y_dst = height - y_dst - 1;
+ *x_src = x_dst;
+ *y_src = y_dst;
+}
+
+/*
+ * Given a cursor source coordinate, rotate to a screen coordinate
+ */
+static void
+xf86_crtc_rotate_coord_back (Rotation rotation,
+ int width,
+ int height,
+ int x_dst,
+ int y_dst,
+ int *x_src,
+ int *y_src)
+{
+ int t;
+
+ if (rotation & RR_Reflect_X)
+ x_dst = width - x_dst - 1;
+ if (rotation & RR_Reflect_Y)
+ y_dst = height - y_dst - 1;
+
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ break;
+ case RR_Rotate_90:
+ t = x_dst;
+ x_dst = y_dst;
+ y_dst = width - t - 1;
+ break;
+ case RR_Rotate_180:
+ x_dst = width - x_dst - 1;
+ y_dst = height - y_dst - 1;
+ break;
+ case RR_Rotate_270:
+ t = x_dst;
+ x_dst = height - y_dst - 1;
+ y_dst = t;
+ break;
+ }
+ *x_src = x_dst;
+ *y_src = y_dst;
+}
+
+/*
+ * Convert an x coordinate to a position within the cursor bitmap
+ */
+static int
+cursor_bitpos (int flags, int x, Bool mask)
+{
+ if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
+ mask = !mask;
+ if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED)
+ x = (x & ~3) | (3 - (x & 3));
+ if (flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST)
+ x = (x & ~7) | (7 - (x & 7));
+ if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
+ x = (x << 1) + mask;
+ else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8)
+ x = ((x & ~7) << 1) | (mask << 3) | (x & 7);
+ else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16)
+ x = ((x & ~15) << 1) | (mask << 4) | (x & 15);
+ else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32)
+ x = ((x & ~31) << 1) | (mask << 5) | (x & 31);
+ else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)
+ x = ((x & ~63) << 1) | (mask << 6) | (x & 63);
+ return x;
+}
+
+/*
+ * Fetch one bit from a cursor bitmap
+ */
+static CARD8
+get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+{
+ x = cursor_bitpos (flags, x, mask);
+ image += y * stride;
+ return (image[(x >> 3)] >> (x & 7)) & 1;
+}
+
+/*
+ * Set one bit in a cursor bitmap
+ */
+static void
+set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+{
+ x = cursor_bitpos (flags, x, mask);
+ image += y * stride;
+ image[(x >> 3)] |= 1 << (x & 7);
+}
+
+/*
+ * Load a two color cursor into a driver that supports only ARGB cursors
+ */
+static void
+xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
+ int x, y;
+ int xin, yin;
+ int stride = cursor_info->MaxWidth >> 2;
+ int flags = cursor_info->Flags;
+ CARD32 bits;
+
+#ifdef ARGB_CURSOR
+ crtc->cursor_argb = FALSE;
+#endif
+
+ for (y = 0; y < cursor_info->MaxHeight; y++)
+ for (x = 0; x < cursor_info->MaxWidth; x++)
+ {
+ xf86_crtc_rotate_coord (crtc->rotation,
+ cursor_info->MaxWidth,
+ cursor_info->MaxHeight,
+ x, y, &xin, &yin);
+ if (get_bit (src, stride, flags, xin, yin, TRUE) ==
+ ((flags & HARDWARE_CURSOR_INVERT_MASK) == 0))
+ {
+ if (get_bit (src, stride, flags, xin, yin, FALSE))
+ bits = xf86_config->cursor_fg;
+ else
+ bits = xf86_config->cursor_bg;
+ }
+ else
+ bits = 0;
+ cursor_image[y * cursor_info->MaxWidth + x] = bits;
+ }
+ crtc->funcs->load_cursor_argb (crtc, cursor_image);
+}
+
+/*
+ * Set the colors for a two-color cursor (ignore for ARGB cursors)
+ */
+static void
+xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg)
+{
+ ScreenPtr screen = scrn->pScreen;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ CursorPtr cursor = xf86_config->cursor;
+ int c;
+ CARD8 *bits = cursor ? cursor->devPriv[screen->myNum] : NULL;
+
+ /* Save ARGB versions of these colors */
+ xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
+ xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled && !crtc->cursor_argb)
+ {
+ if (crtc->funcs->load_cursor_image)
+ crtc->funcs->set_cursor_colors (crtc, bg, fg);
+ else if (bits)
+ xf86_crtc_convert_cursor_to_argb (crtc, bits);
+ }
+ }
+}
+
+static void
+xf86_crtc_hide_cursor (xf86CrtcPtr crtc)
+{
+ if (crtc->cursor_shown)
+ {
+ crtc->funcs->hide_cursor (crtc);
+ crtc->cursor_shown = FALSE;
+ }
+}
+
+_X_EXPORT void
+xf86_hide_cursors (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ xf86_config->cursor_on = FALSE;
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled)
+ xf86_crtc_hide_cursor (crtc);
+ }
+}
+
+static void
+xf86_crtc_show_cursor (xf86CrtcPtr crtc)
+{
+ if (!crtc->cursor_shown && crtc->cursor_in_range)
+ {
+ crtc->funcs->show_cursor (crtc);
+ crtc->cursor_shown = TRUE;
+ }
+}
+
+_X_EXPORT void
+xf86_show_cursors (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ xf86_config->cursor_on = TRUE;
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled)
+ xf86_crtc_show_cursor (crtc);
+ }
+}
+
+static void
+xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ DisplayModePtr mode = &crtc->mode;
+ Bool in_range;
+ int dx, dy;
+
+ /*
+ * Transform position of cursor on screen
+ */
+ if (crtc->transform_in_use)
+ {
+ PictVector v;
+ v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1);
+ PictureTransformPoint (&crtc->framebuffer_to_crtc, &v);
+ x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]);
+ }
+ else
+ {
+ x -= crtc->x;
+ y -= crtc->y;
+ }
+ /*
+ * Transform position of cursor upper left corner
+ */
+ xf86_crtc_rotate_coord_back (crtc->rotation,
+ cursor_info->MaxWidth,
+ cursor_info->MaxHeight,
+ 0, 0, &dx, &dy);
+ x -= dx;
+ y -= dy;
+
+ /*
+ * Disable the cursor when it is outside the viewport
+ */
+ in_range = TRUE;
+ if (x >= mode->HDisplay || y >= mode->VDisplay ||
+ x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight)
+ {
+ in_range = FALSE;
+ x = 0;
+ y = 0;
+ }
+
+ crtc->cursor_in_range = in_range;
+
+ if (in_range)
+ {
+ crtc->funcs->set_cursor_position (crtc, x, y);
+ xf86_crtc_show_cursor (crtc);
+ }
+ else
+ xf86_crtc_hide_cursor (crtc);
+}
+
+static void
+xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ /* undo what xf86HWCurs did to the coordinates */
+ x += scrn->frameX0;
+ y += scrn->frameY0;
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled)
+ xf86_crtc_set_cursor_position (crtc, x, y);
+ }
+}
+
+/*
+ * Load a two-color cursor into a crtc, performing rotation as needed
+ */
+static void
+xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ CARD8 *cursor_image;
+
+#ifdef ARGB_CURSOR
+ crtc->cursor_argb = FALSE;
+#endif
+
+ if (crtc->rotation == RR_Rotate_0)
+ cursor_image = src;
+ else
+ {
+ int x, y;
+ int xin, yin;
+ int stride = cursor_info->MaxWidth >> 2;
+ int flags = cursor_info->Flags;
+
+ cursor_image = xf86_config->cursor_image;
+ memset(cursor_image, 0, cursor_info->MaxWidth * stride);
+
+ for (y = 0; y < cursor_info->MaxHeight; y++)
+ for (x = 0; x < cursor_info->MaxWidth; x++)
+ {
+ xf86_crtc_rotate_coord (crtc->rotation,
+ cursor_info->MaxWidth,
+ cursor_info->MaxHeight,
+ x, y, &xin, &yin);
+ if (get_bit(src, stride, flags, xin, yin, FALSE))
+ set_bit(cursor_image, stride, flags, x, y, FALSE);
+ if (get_bit(src, stride, flags, xin, yin, TRUE))
+ set_bit(cursor_image, stride, flags, x, y, TRUE);
+ }
+ }
+ crtc->funcs->load_cursor_image (crtc, cursor_image);
+}
+
+/*
+ * Load a cursor image into all active CRTCs
+ */
+static void
+xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled)
+ {
+ if (crtc->funcs->load_cursor_image)
+ xf86_crtc_load_cursor_image (crtc, src);
+ else if (crtc->funcs->load_cursor_argb)
+ xf86_crtc_convert_cursor_to_argb (crtc, src);
+ }
+ }
+}
+
+static Bool
+xf86_use_hw_cursor (ScreenPtr screen, CursorPtr cursor)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+
+ if (xf86_config->cursor)
+ FreeCursor (xf86_config->cursor, None);
+ xf86_config->cursor = cursor;
+ ++cursor->refcnt;
+
+ if (cursor->bits->width > cursor_info->MaxWidth ||
+ cursor->bits->height> cursor_info->MaxHeight)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+xf86_use_hw_cursor_argb (ScreenPtr screen, CursorPtr cursor)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+
+ if (xf86_config->cursor)
+ FreeCursor (xf86_config->cursor, None);
+ xf86_config->cursor = cursor;
+ ++cursor->refcnt;
+
+ /* Make sure ARGB support is available */
+ if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
+ return FALSE;
+
+ if (cursor->bits->width > cursor_info->MaxWidth ||
+ cursor->bits->height> cursor_info->MaxHeight)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+ CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
+ CARD32 *cursor_source = (CARD32 *) cursor->bits->argb;
+ int x, y;
+ int xin, yin;
+ CARD32 bits;
+ int source_width = cursor->bits->width;
+ int source_height = cursor->bits->height;
+ int image_width = cursor_info->MaxWidth;
+ int image_height = cursor_info->MaxHeight;
+
+ for (y = 0; y < image_height; y++)
+ for (x = 0; x < image_width; x++)
+ {
+ xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
+ x, y, &xin, &yin);
+ if (xin < source_width && yin < source_height)
+ bits = cursor_source[yin * source_width + xin];
+ else
+ bits = 0;
+ cursor_image[y * image_width + x] = bits;
+ }
+
+ crtc->funcs->load_cursor_argb (crtc, cursor_image);
+}
+
+static void
+xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->enabled)
+ xf86_crtc_load_cursor_argb (crtc, cursor);
+ }
+}
+
+_X_EXPORT Bool
+xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CursorInfoPtr cursor_info;
+
+ cursor_info = xf86CreateCursorInfoRec();
+ if (!cursor_info)
+ return FALSE;
+
+ xf86_config->cursor_image = xalloc (max_width * max_height * 4);
+
+ if (!xf86_config->cursor_image)
+ {
+ xf86DestroyCursorInfoRec (cursor_info);
+ return FALSE;
+ }
+
+ xf86_config->cursor_info = cursor_info;
+
+ cursor_info->MaxWidth = max_width;
+ cursor_info->MaxHeight = max_height;
+ cursor_info->Flags = flags;
+
+ cursor_info->SetCursorColors = xf86_set_cursor_colors;
+ cursor_info->SetCursorPosition = xf86_set_cursor_position;
+ cursor_info->LoadCursorImage = xf86_load_cursor_image;
+ cursor_info->HideCursor = xf86_hide_cursors;
+ cursor_info->ShowCursor = xf86_show_cursors;
+ cursor_info->UseHWCursor = xf86_use_hw_cursor;
+#ifdef ARGB_CURSOR
+ if (flags & HARDWARE_CURSOR_ARGB)
+ {
+ cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
+ cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
+ }
+#endif
+
+ xf86_config->cursor = NULL;
+ xf86_hide_cursors (scrn);
+
+ return xf86InitCursor (screen, cursor_info);
+}
+
+/**
+ * Called when anything on the screen is reconfigured.
+ *
+ * Reloads cursor images as needed, then adjusts cursor positions
+ */
+
+_X_EXPORT void
+xf86_reload_cursors (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn;
+ xf86CrtcConfigPtr xf86_config;
+ xf86CursorInfoPtr cursor_info;
+ CursorPtr cursor;
+ int x, y;
+
+ /* initial mode setting will not have set a screen yet */
+ if (!screen)
+ return;
+ scrn = xf86Screens[screen->myNum];
+ xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ /* make sure the cursor code has been initialized */
+ cursor_info = xf86_config->cursor_info;
+ if (!cursor_info)
+ return;
+
+ cursor = xf86_config->cursor;
+ GetSpritePosition (&x, &y);
+ if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
+ (*cursor_info->HideCursor)(scrn);
+
+ if (cursor)
+ {
+#ifdef ARGB_CURSOR
+ if (cursor->bits->argb && cursor_info->LoadCursorARGB)
+ (*cursor_info->LoadCursorARGB) (scrn, cursor);
+ else
+#endif
+ (*cursor_info->LoadCursorImage)(cursor_info->pScrn,
+ cursor->devPriv[screen->myNum]);
+
+ (*cursor_info->SetCursorPosition)(cursor_info->pScrn, x, y);
+ (*cursor_info->ShowCursor)(cursor_info->pScrn);
+ }
+}
+
+/**
+ * Clean up CRTC-based cursor code
+ */
+_X_EXPORT void
+xf86_cursors_fini (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (xf86_config->cursor_info)
+ {
+ xf86DestroyCursorInfoRec (xf86_config->cursor_info);
+ xf86_config->cursor_info = NULL;
+ }
+ if (xf86_config->cursor_image)
+ {
+ xfree (xf86_config->cursor_image);
+ xf86_config->cursor_image = NULL;
+ }
+ if (xf86_config->cursor)
+ {
+ FreeCursor (xf86_config->cursor, None);
+ xf86_config->cursor = NULL;
+ }
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86DiDGA.c b/driver/xf86-video-intel/src/modes/xf86DiDGA.c
new file mode 100644
index 000000000..f40d0abef
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86DiDGA.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86_OSproc.h"
+#include "dgaproc.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+
+static Bool
+xf86_dga_get_modes (ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ DGAModePtr modes, mode;
+ DisplayModePtr display_mode;
+ int bpp = scrn->bitsPerPixel >> 3;
+ int num;
+
+ num = 0;
+ display_mode = scrn->modes;
+ while (display_mode)
+ {
+ num++;
+ display_mode = display_mode->next;
+ if (display_mode == scrn->modes)
+ break;
+ }
+
+ if (!num)
+ return FALSE;
+
+ modes = xalloc(num * sizeof(DGAModeRec));
+ if (!modes)
+ return FALSE;
+
+ num = 0;
+ display_mode = scrn->modes;
+ while (display_mode)
+ {
+ mode = modes + num++;
+
+ mode->mode = display_mode;
+ mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ if (display_mode->Flags & V_DBLSCAN)
+ mode->flags |= DGA_DOUBLESCAN;
+ if (display_mode->Flags & V_INTERLACE)
+ mode->flags |= DGA_INTERLACED;
+ mode->byteOrder = scrn->imageByteOrder;
+ mode->depth = scrn->depth;
+ mode->bitsPerPixel = scrn->bitsPerPixel;
+ mode->red_mask = scrn->mask.red;
+ mode->green_mask = scrn->mask.green;
+ mode->blue_mask = scrn->mask.blue;
+ mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
+ mode->viewportWidth = display_mode->HDisplay;
+ mode->viewportHeight = display_mode->VDisplay;
+ mode->xViewportStep = (bpp == 3) ? 2 : 1;
+ mode->yViewportStep = 1;
+ mode->viewportFlags = DGA_FLIP_RETRACE;
+ mode->offset = 0;
+ mode->address = (unsigned char *) xf86_config->dga_address;
+ mode->bytesPerScanline = xf86_config->dga_stride;
+ mode->imageWidth = xf86_config->dga_width;
+ mode->imageHeight = xf86_config->dga_height;
+ mode->pixmapWidth = mode->imageWidth;
+ mode->pixmapHeight = mode->imageHeight;
+ mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
+ mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
+
+ display_mode = display_mode->next;
+ if (display_mode == scrn->modes)
+ break;
+ }
+ if (xf86_config->dga_modes)
+ xfree (xf86_config->dga_modes);
+ xf86_config->dga_nmode = num;
+ xf86_config->dga_modes = modes;
+ return TRUE;
+}
+
+static Bool
+xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode)
+{
+ ScreenPtr pScreen = scrn->pScreen;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (!display_mode)
+ {
+ if (xf86_config->dga_save_mode)
+ {
+ xf86SwitchMode(pScreen, xf86_config->dga_save_mode);
+ xf86_config->dga_save_mode = NULL;
+ }
+ }
+ else
+ {
+ if (!xf86_config->dga_save_mode)
+ {
+ xf86_config->dga_save_mode = scrn->currentMode;
+ xf86SwitchMode(pScreen, display_mode->mode);
+ }
+ }
+ return TRUE;
+}
+
+static int
+xf86_dga_get_viewport(ScrnInfoPtr scrn)
+{
+ return 0;
+}
+
+static void
+xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags)
+{
+ scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags);
+}
+
+static Bool
+xf86_dga_get_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr *ppDrawable, GCPtr *ppGC)
+{
+ ScreenPtr pScreen = scrn->pScreen;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ PixmapPtr pPixmap;
+ GCPtr pGC;
+
+ pPixmap = GetScratchPixmapHeader (pScreen, xf86_config->dga_width, xf86_config->dga_height,
+ scrn->depth, scrn->bitsPerPixel, xf86_config->dga_stride,
+ (char *) scrn->memPhysBase + scrn->fbOffset);
+ if (!pPixmap)
+ return FALSE;
+ pGC = GetScratchGC (scrn->depth, pScreen);
+ if (!pGC)
+ {
+ FreeScratchPixmapHeader (pPixmap);
+ return FALSE;
+ }
+ *ppDrawable = &pPixmap->drawable;
+ *ppGC = pGC;
+ return TRUE;
+}
+
+static void
+xf86_dga_release_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr pDrawable, GCPtr pGC)
+{
+ FreeScratchGC (pGC);
+ FreeScratchPixmapHeader ((PixmapPtr) pDrawable);
+}
+
+static void
+xf86_dga_fill_rect(ScrnInfoPtr scrn, int x, int y, int w, int h, unsigned long color)
+{
+ GCPtr pGC;
+ DrawablePtr pDrawable;
+ XID vals[1];
+ xRectangle r;
+
+ if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
+ return;
+ vals[0] = color;
+ ChangeGC (pGC, GCForeground, vals);
+ ValidateGC (pDrawable, pGC);
+ r.x = x;
+ r.y = y;
+ r.width = w;
+ r.height = h;
+ pGC->ops->PolyFillRect (pDrawable, pGC, 1, &r);
+ xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
+}
+
+static void
+xf86_dga_sync(ScrnInfoPtr scrn)
+{
+ ScreenPtr pScreen = scrn->pScreen;
+ WindowPtr pRoot = WindowTable [pScreen->myNum];
+ char buffer[4];
+
+ pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
+}
+
+static void
+xf86_dga_blit_rect(ScrnInfoPtr scrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+
+ if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
+ return;
+ ValidateGC (pDrawable, pGC);
+ pGC->ops->CopyArea (pDrawable, pDrawable, pGC, srcx, srcy, w, h, dstx, dsty);
+ xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
+}
+
+static Bool
+xf86_dga_open_framebuffer(ScrnInfoPtr scrn,
+ char **name,
+ unsigned char **mem, int *size, int *offset, int *flags)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ *size = xf86_config->dga_stride * xf86_config->dga_height;
+ *mem = (unsigned char *) (xf86_config->dga_address);
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
+
+static void
+xf86_dga_close_framebuffer(ScrnInfoPtr scrn)
+{
+}
+
+static DGAFunctionRec xf86_dga_funcs = {
+ xf86_dga_open_framebuffer,
+ xf86_dga_close_framebuffer,
+ xf86_dga_set_mode,
+ xf86_dga_set_viewport,
+ xf86_dga_get_viewport,
+ xf86_dga_sync,
+ xf86_dga_fill_rect,
+ xf86_dga_blit_rect,
+ NULL
+};
+
+_X_EXPORT Bool
+xf86DiDGAReInit (ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ if (!xf86_dga_get_modes (pScreen))
+ return FALSE;
+
+ return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode);
+}
+
+_X_EXPORT Bool
+xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address)
+{
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ xf86_config->dga_flags = 0;
+ xf86_config->dga_address = dga_address;
+ xf86_config->dga_width = scrn->virtualX;
+ xf86_config->dga_height = scrn->virtualY;
+ xf86_config->dga_stride = scrn->displayWidth * scrn->bitsPerPixel >> 3;
+
+ if (!xf86_dga_get_modes (pScreen))
+ return FALSE;
+
+ return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode);
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86EdidModes.c b/driver/xf86-video-intel/src/modes/xf86EdidModes.c
new file mode 100644
index 000000000..8b5e69d9a
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86EdidModes.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright 2006 Luc Verhaegen.
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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 This file covers code to convert a xf86MonPtr containing EDID-probed
+ * information into a list of modes, including applying monitor-specific
+ * quirks to fix broken EDID data.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include <X11/Xatom.h>
+#include "property.h"
+#include "propertyst.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include <string.h>
+#include <math.h>
+
+/*
+ * Quirks to work around broken EDID data from various monitors.
+ */
+
+typedef enum {
+ DDC_QUIRK_NONE = 0,
+ /* First detailed mode is bogus, prefer largest mode at 60hz */
+ DDC_QUIRK_PREFER_LARGE_60 = 1 << 0,
+ /* 135MHz clock is too high, drop a bit */
+ DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1,
+} ddc_quirk_t;
+
+static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Belinea 10 15 55 */
+ if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+ DDC->vendor.prod_id == 1516)
+ return TRUE;
+
+ /* Acer AL1706 */
+ if (memcmp (DDC->vendor.name, "ACR", 4) == 0 &&
+ DDC->vendor.prod_id == 44358)
+ return TRUE;
+
+ /* Bug #10814: Samsung SyncMaster 225BW */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 596)
+ return TRUE;
+
+ /* Bug #10545: Samsung SyncMaster 226BW */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 638)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */
+ if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
+ DDC->vendor.prod_id == 59264)
+ return TRUE;
+
+ return FALSE;
+}
+
+typedef struct {
+ Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
+ ddc_quirk_t quirk;
+ char *description;
+} ddc_quirk_map_t;
+
+static const ddc_quirk_map_t ddc_quirks[] = {
+ {
+ quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60,
+ "Detailed timing is not preferred, use largest mode at 60Hz"
+ },
+ {
+ quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH,
+ "Recommended 135MHz pixel clock is too high"
+ },
+ {
+ NULL, DDC_QUIRK_NONE,
+ "No known quirks"
+ },
+};
+
+/*
+ * TODO:
+ * - for those with access to the VESA DMT standard; review please.
+ */
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
+#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+static DisplayModeRec DDCEstablishedModes[17] = {
+ { MODEPREFIX("800x600"), 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
+ { MODEPREFIX("800x600"), 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
+ { MODEPREFIX("640x480"), 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
+ { MODEPREFIX("640x480"), 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
+ { MODEPREFIX("640x480"), 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
+ { MODEPREFIX("640x480"), 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
+ { MODEPREFIX("720x400"), 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
+ { MODEPREFIX("720x400"), 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
+ { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
+ { MODEPREFIX("1024x768"), 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
+ { MODEPREFIX("1024x768"), 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
+ { MODEPREFIX("1024x768"), 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
+ { MODEPREFIX("1024x768"), 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
+ { MODEPREFIX("832x624"), 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
+ { MODEPREFIX("800x600"), 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
+ { MODEPREFIX("800x600"), 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
+ { MODEPREFIX("1152x864"), 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
+};
+
+static DisplayModePtr
+DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
+ ddc_quirk_t quirks)
+{
+ DisplayModePtr Modes = NULL, Mode = NULL;
+ CARD32 bits = (timing->t1) | (timing->t2 << 8) |
+ ((timing->t_manu & 0x80) << 9);
+ int i;
+
+ for (i = 0; i < 17; i++) {
+ if (bits & (0x01 << i)) {
+ Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+ }
+
+ return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
+ ddc_quirk_t quirks)
+{
+ DisplayModePtr Modes = NULL, Mode = NULL;
+ int i;
+
+ for (i = 0; i < STD_TIMINGS; i++) {
+ if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
+ Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
+ timing[i].refresh, FALSE, FALSE);
+ Mode->type = M_T_DRIVER;
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+ }
+
+ return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
+ int preferred, ddc_quirk_t quirks)
+{
+ DisplayModePtr Mode;
+
+ /*
+ * Refuse to create modes that are insufficiently large. 64 is a random
+ * number, maybe the spec says something about what the minimum is. In
+ * particular I see this frequently with _old_ EDID, 1.0 or so, so maybe
+ * our parser is just being too aggresive there.
+ */
+ if (timing->h_active < 64 || timing->v_active < 64) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: Ignoring tiny %dx%d mode\n", __func__,
+ timing->h_active, timing->v_active);
+ return NULL;
+ }
+
+ /* We don't do stereo */
+ if (timing->stereo) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: Ignoring: We don't handle stereo.\n", __func__);
+ return NULL;
+ }
+
+ /* We only do seperate sync currently */
+ if (timing->sync != 0x03) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: %dx%d Warning: We only handle seperate"
+ " sync.\n", __func__, timing->h_active, timing->v_active);
+ }
+
+ Mode = xnfalloc(sizeof(DisplayModeRec));
+ memset(Mode, 0, sizeof(DisplayModeRec));
+
+ Mode->type = M_T_DRIVER;
+ if (preferred)
+ Mode->type |= M_T_PREFERRED;
+
+ if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
+ timing->clock == 135000000 )
+ Mode->Clock = 108880;
+ else
+ Mode->Clock = timing->clock / 1000.0;
+
+ Mode->HDisplay = timing->h_active;
+ Mode->HSyncStart = timing->h_active + timing->h_sync_off;
+ Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
+ Mode->HTotal = timing->h_active + timing->h_blanking;
+
+ Mode->VDisplay = timing->v_active;
+ Mode->VSyncStart = timing->v_active + timing->v_sync_off;
+ Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
+ Mode->VTotal = timing->v_active + timing->v_blanking;
+
+ xf86SetModeDefaultName(Mode);
+
+ /* We ignore h/v_size and h/v_border for now. */
+
+ if (timing->interlaced)
+ Mode->Flags |= V_INTERLACE;
+
+ if (timing->misc & 0x02)
+ Mode->Flags |= V_PVSYNC;
+ else
+ Mode->Flags |= V_NVSYNC;
+
+ if (timing->misc & 0x01)
+ Mode->Flags |= V_PHSYNC;
+ else
+ Mode->Flags |= V_NHSYNC;
+
+ return Mode;
+}
+
+/*
+ *
+ */
+static void
+DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
+{
+ DisplayModePtr Mode = Modes;
+
+ if (!Monitor || !Modes)
+ return;
+
+ /* set up the ranges for scanning through the modes */
+ Monitor->nHsync = 1;
+ Monitor->hsync[0].lo = 1024.0;
+ Monitor->hsync[0].hi = 0.0;
+
+ Monitor->nVrefresh = 1;
+ Monitor->vrefresh[0].lo = 1024.0;
+ Monitor->vrefresh[0].hi = 0.0;
+
+ while (Mode) {
+ if (!Mode->HSync)
+ Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
+
+ if (!Mode->VRefresh)
+ Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
+ ((float) (Mode->HTotal * Mode->VTotal));
+
+ if (Mode->HSync < Monitor->hsync[0].lo)
+ Monitor->hsync[0].lo = Mode->HSync;
+
+ if (Mode->HSync > Monitor->hsync[0].hi)
+ Monitor->hsync[0].hi = Mode->HSync;
+
+ if (Mode->VRefresh < Monitor->vrefresh[0].lo)
+ Monitor->vrefresh[0].lo = Mode->VRefresh;
+
+ if (Mode->VRefresh > Monitor->vrefresh[0].hi)
+ Monitor->vrefresh[0].hi = Mode->VRefresh;
+
+ Mode = Mode->next;
+ }
+}
+
+_X_EXPORT DisplayModePtr
+xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
+{
+ int preferred, i;
+ DisplayModePtr Modes = NULL, Mode;
+ ddc_quirk_t quirks;
+
+ xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
+ DDC->vendor.name, DDC->vendor.prod_id);
+ quirks = DDC_QUIRK_NONE;
+ for (i = 0; ddc_quirks[i].detect; i++)
+ if (ddc_quirks[i].detect (scrnIndex, DDC))
+ {
+ xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
+ ddc_quirks[i].description);
+ quirks |= ddc_quirks[i].quirk;
+ }
+
+ preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+ if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+ preferred = 0;
+
+ for (i = 0; i < DET_TIMINGS; i++) {
+ struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
+
+ switch (det_mon->type) {
+ case DT:
+ Mode = DDCModeFromDetailedTiming(scrnIndex,
+ &det_mon->section.d_timings,
+ preferred,
+ quirks);
+ preferred = 0;
+ Modes = xf86ModesAdd(Modes, Mode);
+ break;
+ case DS_STD_TIMINGS:
+ Mode = DDCModesFromStandardTiming(scrnIndex,
+ det_mon->section.std_t,
+ quirks);
+ Modes = xf86ModesAdd(Modes, Mode);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Add established timings */
+ Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ /* Add standard timings */
+ Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+ {
+ DisplayModePtr best = Modes;
+ for (Mode = Modes; Mode; Mode = Mode->next)
+ {
+ if (Mode == best) continue;
+ if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
+ {
+ best = Mode;
+ continue;
+ }
+ if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
+ {
+ double mode_refresh = xf86ModeVRefresh (Mode);
+ double best_refresh = xf86ModeVRefresh (best);
+ double mode_dist = fabs(mode_refresh - 60.0);
+ double best_dist = fabs(best_refresh - 60.0);
+ if (mode_dist < best_dist)
+ {
+ best = Mode;
+ continue;
+ }
+ }
+ }
+ if (best)
+ best->type |= M_T_PREFERRED;
+ }
+ return Modes;
+}
+
+/*
+ * Fill out MonPtr with xf86MonPtr information.
+ */
+_X_EXPORT void
+xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
+{
+ DisplayModePtr Modes = NULL, Mode;
+ int i, clock;
+ Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE;
+
+ if (!Monitor || !DDC)
+ return;
+
+ Monitor->DDC = DDC;
+
+ Monitor->widthmm = 10 * DDC->features.hsize;
+ Monitor->heightmm = 10 * DDC->features.vsize;
+
+ /* If this is a digital display, then we can use reduced blanking */
+ if (DDC->features.input_type)
+ Monitor->reducedblanking = TRUE;
+ /* Allow the user to also enable this through config */
+
+ Modes = xf86DDCGetModes(scrnIndex, DDC);
+
+ /* Skip EDID ranges if they were specified in the config file */
+ have_hsync = (Monitor->nHsync != 0);
+ have_vrefresh = (Monitor->nVrefresh != 0);
+ have_maxpixclock = (Monitor->maxPixClock != 0);
+
+ /* Go through the detailed monitor sections */
+ for (i = 0; i < DET_TIMINGS; i++) {
+ switch (DDC->det_mon[i].type) {
+ case DS_RANGES:
+ if (!have_hsync) {
+ if (!Monitor->nHsync)
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using EDID range info for horizontal sync\n");
+ Monitor->hsync[Monitor->nHsync].lo =
+ DDC->det_mon[i].section.ranges.min_h;
+ Monitor->hsync[Monitor->nHsync].hi =
+ DDC->det_mon[i].section.ranges.max_h;
+ Monitor->nHsync++;
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using hsync ranges from config file\n");
+ }
+
+ if (!have_vrefresh) {
+ if (!Monitor->nVrefresh)
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using EDID range info for vertical refresh\n");
+ Monitor->vrefresh[Monitor->nVrefresh].lo =
+ DDC->det_mon[i].section.ranges.min_v;
+ Monitor->vrefresh[Monitor->nVrefresh].hi =
+ DDC->det_mon[i].section.ranges.max_v;
+ Monitor->nVrefresh++;
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using vrefresh ranges from config file\n");
+ }
+
+ clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
+ if (!have_maxpixclock && clock > Monitor->maxPixClock)
+ Monitor->maxPixClock = clock;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (Modes) {
+ /* Print Modes */
+ xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n");
+
+ Mode = Modes;
+ while (Mode) {
+ xf86PrintModeline(scrnIndex, Mode);
+ Mode = Mode->next;
+ }
+
+ /* Do we still need ranges to be filled in? */
+ if (!Monitor->nHsync || !Monitor->nVrefresh)
+ DDCGuessRangesFromModes(scrnIndex, Monitor, Modes);
+
+ /* look for last Mode */
+ Mode = Modes;
+
+ while (Mode->next)
+ Mode = Mode->next;
+
+ /* add to MonPtr */
+ if (Monitor->Modes) {
+ Monitor->Last->next = Modes;
+ Modes->prev = Monitor->Last;
+ Monitor->Last = Mode;
+ } else {
+ Monitor->Modes = Modes;
+ Monitor->Last = Mode;
+ }
+ }
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86Modes.c b/driver/xf86-video-intel/src/modes/xf86Modes.c
new file mode 100644
index 000000000..f49c2921c
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Modes.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR 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 copyright holder(s)
+ * and 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 copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86Modes.h"
+#include "xf86Priv.h"
+
+extern XF86ConfigPtr xf86configptr;
+
+/**
+ * @file this file contains symbols from xf86Mode.c and friends that are static
+ * there but we still want to use. We need to come up with better API here.
+ */
+
+#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
+/**
+ * Calculates the horizontal sync rate of a mode.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+_X_EXPORT double
+xf86ModeHSync(DisplayModePtr mode)
+{
+ double hsync = 0.0;
+
+ if (mode->HSync > 0.0)
+ hsync = mode->HSync;
+ else if (mode->HTotal > 0)
+ hsync = (float)mode->Clock / (float)mode->HTotal;
+
+ return hsync;
+}
+
+/**
+ * Calculates the vertical refresh rate of a mode.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+_X_EXPORT double
+xf86ModeVRefresh(DisplayModePtr mode)
+{
+ double refresh = 0.0;
+
+ if (mode->VRefresh > 0.0)
+ refresh = mode->VRefresh;
+ else if (mode->HTotal > 0 && mode->VTotal > 0) {
+ refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
+ if (mode->Flags & V_INTERLACE)
+ refresh *= 2.0;
+ if (mode->Flags & V_DBLSCAN)
+ refresh /= 2.0;
+ if (mode->VScan > 1)
+ refresh /= (float)(mode->VScan);
+ }
+ return refresh;
+}
+
+_X_EXPORT int
+xf86ModeWidth (DisplayModePtr mode, Rotation rotation)
+{
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode->HDisplay;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode->VDisplay;
+ default:
+ return 0;
+ }
+}
+
+_X_EXPORT int
+xf86ModeHeight (DisplayModePtr mode, Rotation rotation)
+{
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode->VDisplay;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode->HDisplay;
+ default:
+ return 0;
+ }
+}
+
+/** Sets a default mode name of <width>x<height> on a mode. */
+_X_EXPORT void
+xf86SetModeDefaultName(DisplayModePtr mode)
+{
+ if (mode->name != NULL)
+ xfree(mode->name);
+
+ mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
+}
+
+/*
+ * xf86SetModeCrtc
+ *
+ * Initialises the Crtc parameters for a mode. The initialisation includes
+ * adjustments for interlaced and double scan modes.
+ *
+ * Exact copy of xf86Mode.c's.
+ */
+_X_EXPORT void
+xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
+{
+ if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
+ return;
+
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+ p->CrtcHSyncEnd = p->HSyncEnd;
+ p->CrtcHTotal = p->HTotal;
+ p->CrtcHSkew = p->HSkew;
+ p->CrtcVDisplay = p->VDisplay;
+ p->CrtcVSyncStart = p->VSyncStart;
+ p->CrtcVSyncEnd = p->VSyncEnd;
+ p->CrtcVTotal = p->VTotal;
+ if (p->Flags & V_INTERLACE) {
+ if (adjustFlags & INTERLACE_HALVE_V) {
+ p->CrtcVDisplay /= 2;
+ p->CrtcVSyncStart /= 2;
+ p->CrtcVSyncEnd /= 2;
+ p->CrtcVTotal /= 2;
+ }
+ /* Force interlaced modes to have an odd VTotal */
+ /* maybe we should only do this when INTERLACE_HALVE_V is set? */
+ p->CrtcVTotal |= 1;
+ }
+
+ if (p->Flags & V_DBLSCAN) {
+ p->CrtcVDisplay *= 2;
+ p->CrtcVSyncStart *= 2;
+ p->CrtcVSyncEnd *= 2;
+ p->CrtcVTotal *= 2;
+ }
+ if (p->VScan > 1) {
+ p->CrtcVDisplay *= p->VScan;
+ p->CrtcVSyncStart *= p->VScan;
+ p->CrtcVSyncEnd *= p->VScan;
+ p->CrtcVTotal *= p->VScan;
+ }
+ p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+ p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+ p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+ p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+ p->CrtcHAdjusted = FALSE;
+ p->CrtcVAdjusted = FALSE;
+}
+
+/**
+ * Allocates and returns a copy of pMode, including pointers within pMode.
+ */
+_X_EXPORT DisplayModePtr
+xf86DuplicateMode(DisplayModePtr pMode)
+{
+ DisplayModePtr pNew;
+
+ pNew = xnfalloc(sizeof(DisplayModeRec));
+ *pNew = *pMode;
+ pNew->next = NULL;
+ pNew->prev = NULL;
+ if (pNew->name == NULL) {
+ xf86SetModeDefaultName(pMode);
+ } else {
+ pNew->name = xnfstrdup(pMode->name);
+ }
+
+ return pNew;
+}
+
+/**
+ * Duplicates every mode in the given list and returns a pointer to the first
+ * mode.
+ *
+ * \param modeList doubly-linked mode list
+ */
+_X_EXPORT DisplayModePtr
+xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+{
+ DisplayModePtr first = NULL, last = NULL;
+ DisplayModePtr mode;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ DisplayModePtr new;
+
+ new = xf86DuplicateMode(mode);
+
+ /* Insert pNew into modeList */
+ if (last) {
+ last->next = new;
+ new->prev = last;
+ } else {
+ first = new;
+ new->prev = NULL;
+ }
+ new->next = NULL;
+ last = new;
+ }
+
+ return first;
+}
+
+/**
+ * Returns true if the given modes should program to the same timings.
+ *
+ * This doesn't use Crtc values, as it might be used on ModeRecs without the
+ * Crtc values set. So, it's assumed that the other numbers are enough.
+ *
+ * This isn't in xf86Modes.c, but it might deserve to be there.
+ */
+_X_EXPORT Bool
+xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
+{
+ if (pMode1->Clock == pMode2->Clock &&
+ pMode1->HDisplay == pMode2->HDisplay &&
+ pMode1->HSyncStart == pMode2->HSyncStart &&
+ pMode1->HSyncEnd == pMode2->HSyncEnd &&
+ pMode1->HTotal == pMode2->HTotal &&
+ pMode1->HSkew == pMode2->HSkew &&
+ pMode1->VDisplay == pMode2->VDisplay &&
+ pMode1->VSyncStart == pMode2->VSyncStart &&
+ pMode1->VSyncEnd == pMode2->VSyncEnd &&
+ pMode1->VTotal == pMode2->VTotal &&
+ pMode1->VScan == pMode2->VScan &&
+ pMode1->Flags == pMode2->Flags)
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* exact copy of xf86Mode.c */
+static void
+add(char **p, char *new)
+{
+ *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
+ strcat(*p, " ");
+ strcat(*p, new);
+}
+
+/**
+ * Print out a modeline.
+ *
+ * Convenient VRefresh printing was added, though, compared to xf86Mode.c
+ */
+_X_EXPORT void
+xf86PrintModeline(int scrnIndex,DisplayModePtr mode)
+{
+ char tmp[256];
+ char *flags = xnfcalloc(1, 1);
+
+ if (mode->HSkew) {
+ snprintf(tmp, 256, "hskew %i", mode->HSkew);
+ add(&flags, tmp);
+ }
+ if (mode->VScan) {
+ snprintf(tmp, 256, "vscan %i", mode->VScan);
+ add(&flags, tmp);
+ }
+ if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
+ if (mode->Flags & V_CSYNC) add(&flags, "composite");
+ if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
+ if (mode->Flags & V_BCAST) add(&flags, "bcast");
+ if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
+ if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
+ if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
+ if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
+ if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
+ if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
+#if 0
+ if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
+#endif
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s "
+ "(%.01f kHz)\n",
+ mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
+ mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
+ mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
+ mode->VTotal, flags, xf86ModeHSync(mode));
+ xfree(flags);
+}
+#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
+
+/**
+ * Marks as bad any modes with unsupported flags.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ * \param flags flags supported by the driver.
+ *
+ * \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough?
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int flags)
+{
+ DisplayModePtr mode;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
+ mode->status = MODE_NO_INTERLACE;
+ if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
+ mode->status = MODE_NO_DBLESCAN;
+ }
+}
+
+/**
+ * Marks as bad any modes extending beyond the given max X, Y, or pitch.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int maxX, int maxY, int maxPitch)
+{
+ DisplayModePtr mode;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ if (maxPitch > 0 && mode->HDisplay > maxPitch)
+ mode->status = MODE_BAD_WIDTH;
+
+ if (maxX > 0 && mode->HDisplay > maxX)
+ mode->status = MODE_VIRTUAL_X;
+
+ if (maxY > 0 && mode->VDisplay > maxY)
+ mode->status = MODE_VIRTUAL_Y;
+
+ if (mode->next == modeList)
+ break;
+ }
+}
+
+/**
+ * Marks as bad any modes that aren't supported by the given monitor's
+ * hsync and vrefresh ranges.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ MonPtr mon)
+{
+ DisplayModePtr mode;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ Bool bad;
+ int i;
+
+ bad = TRUE;
+ for (i = 0; i < mon->nHsync; i++) {
+ if (xf86ModeHSync(mode) >= mon->hsync[i].lo &&
+ xf86ModeHSync(mode) <= mon->hsync[i].hi)
+ {
+ bad = FALSE;
+ }
+ }
+ if (bad)
+ mode->status = MODE_HSYNC;
+
+ bad = TRUE;
+ for (i = 0; i < mon->nVrefresh; i++) {
+ if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
+ xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
+ {
+ bad = FALSE;
+ }
+ }
+ if (bad)
+ mode->status = MODE_VSYNC;
+
+ if (mode->next == modeList)
+ break;
+ }
+}
+
+/**
+ * Marks as bad any modes extending beyond outside of the given clock ranges.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ * \param min pointer to minimums of clock ranges
+ * \param max pointer to maximums of clock ranges
+ * \param n_ranges number of ranges.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int *min, int *max, int n_ranges)
+{
+ DisplayModePtr mode;
+ int i;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ Bool good = FALSE;
+ for (i = 0; i < n_ranges; i++) {
+ if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
+ good = TRUE;
+ break;
+ }
+ }
+ if (!good)
+ mode->status = MODE_CLOCK_RANGE;
+ }
+}
+
+/**
+ * If the user has specified a set of mode names to use, mark as bad any modes
+ * not listed.
+ *
+ * The user mode names specified are prefixes to names of modes, so "1024x768"
+ * will match modes named "1024x768", "1024x768x75", "1024x768-good", but
+ * "1024x768x75" would only match "1024x768x75" from that list.
+ *
+ * MODE_BAD is used as the rejection flag, for lack of a better flag.
+ *
+ * \param modeList doubly-linked or circular list of modes.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+{
+ DisplayModePtr mode;
+
+ if (pScrn->display->modes[0] == NULL)
+ return;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ int i;
+ Bool good = FALSE;
+
+ for (i = 0; pScrn->display->modes[i] != NULL; i++) {
+ if (strncmp(pScrn->display->modes[i], mode->name,
+ strlen(pScrn->display->modes[i])) == 0) {
+ good = TRUE;
+ break;
+ }
+ }
+ if (!good)
+ mode->status = MODE_BAD;
+ }
+}
+
+
+/**
+ * Frees any modes from the list with a status other than MODE_OK.
+ *
+ * \param modeList pointer to a doubly-linked or circular list of modes.
+ * \param verbose determines whether the reason for mode invalidation is
+ * printed.
+ *
+ * This is not in xf86Modes.c, but would be part of the proposed new API.
+ */
+_X_EXPORT void
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+ Bool verbose)
+{
+ DisplayModePtr mode;
+
+ for (mode = *modeList; mode != NULL;) {
+ DisplayModePtr next = mode->next, first = *modeList;
+
+ if (mode->status != MODE_OK) {
+ if (verbose) {
+ char *type = "";
+ if (mode->type & M_T_BUILTIN)
+ type = "built-in ";
+ else if (mode->type & M_T_DEFAULT)
+ type = "default ";
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Not using %smode \"%s\" (%s)\n", type, mode->name,
+ xf86ModeStatusToString(mode->status));
+ }
+ xf86DeleteMode(modeList, mode);
+ }
+
+ if (next == first)
+ break;
+ mode = next;
+ }
+}
+
+/**
+ * Adds the new mode into the mode list, and returns the new list
+ *
+ * \param modes doubly-linked mode list.
+ */
+_X_EXPORT DisplayModePtr
+xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new)
+{
+ if (modes == NULL)
+ return new;
+
+ if (new) {
+ DisplayModePtr mode = modes;
+
+ while (mode->next)
+ mode = mode->next;
+
+ mode->next = new;
+ new->prev = mode;
+ }
+
+ return modes;
+}
+
+/**
+ * Build a mode list from a list of config file modes
+ */
+static DisplayModePtr
+xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
+{
+ DisplayModePtr head = NULL, prev = NULL, mode;
+
+ for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
+ {
+ mode = xcalloc(1, sizeof(DisplayModeRec));
+ if (!mode)
+ continue;
+ mode->name = xstrdup(conf_mode->ml_identifier);
+ if (!mode->name)
+ {
+ xfree (mode);
+ continue;
+ }
+ mode->type = 0;
+ mode->Clock = conf_mode->ml_clock;
+ mode->HDisplay = conf_mode->ml_hdisplay;
+ mode->HSyncStart = conf_mode->ml_hsyncstart;
+ mode->HSyncEnd = conf_mode->ml_hsyncend;
+ mode->HTotal = conf_mode->ml_htotal;
+ mode->VDisplay = conf_mode->ml_vdisplay;
+ mode->VSyncStart = conf_mode->ml_vsyncstart;
+ mode->VSyncEnd = conf_mode->ml_vsyncend;
+ mode->VTotal = conf_mode->ml_vtotal;
+ mode->Flags = conf_mode->ml_flags;
+ mode->HSkew = conf_mode->ml_hskew;
+ mode->VScan = conf_mode->ml_vscan;
+
+ mode->prev = prev;
+ mode->next = NULL;
+ if (prev)
+ prev->next = mode;
+ else
+ head = mode;
+ prev = mode;
+ }
+ return head;
+}
+
+/**
+ * Build a mode list from a monitor configuration
+ */
+_X_EXPORT DisplayModePtr
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
+{
+ DisplayModePtr modes = NULL;
+ XF86ConfModesLinkPtr modes_link;
+
+ if (!conf_monitor)
+ return NULL;
+
+ /*
+ * first we collect the mode lines from the UseModes directive
+ */
+ for (modes_link = conf_monitor->mon_modes_sect_lst;
+ modes_link;
+ modes_link = modes_link->list.next)
+ {
+ /* If this modes link hasn't been resolved, go look it up now */
+ if (!modes_link->ml_modes)
+ modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str,
+ xf86configptr->conf_modes_lst);
+ if (modes_link->ml_modes)
+ modes = xf86ModesAdd (modes,
+ xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
+ }
+
+ return xf86ModesAdd (modes,
+ xf86GetConfigModes (conf_monitor->mon_modeline_lst));
+}
+
+/**
+ * Build a mode list containing all of the default modes
+ */
+_X_EXPORT DisplayModePtr
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
+{
+ DisplayModePtr head = NULL, prev = NULL, mode;
+ int i;
+
+ for (i = 0; xf86DefaultModes[i].name != NULL; i++)
+ {
+ DisplayModePtr defMode = &xf86DefaultModes[i];
+
+ if (!interlaceAllowed && (defMode->Flags & V_INTERLACE))
+ continue;
+ if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN))
+ continue;
+
+ mode = xalloc(sizeof(DisplayModeRec));
+ if (!mode)
+ continue;
+ memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec));
+ mode->name = xstrdup(xf86DefaultModes[i].name);
+ if (!mode->name)
+ {
+ xfree (mode);
+ continue;
+ }
+ mode->prev = prev;
+ mode->next = NULL;
+ if (prev)
+ prev->next = mode;
+ else
+ head = mode;
+ prev = mode;
+ }
+ return head;
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86Modes.h b/driver/xf86-video-intel/src/modes/xf86Modes.h
new file mode 100644
index 000000000..2bd4edeba
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Modes.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _XF86MODES_H_
+#define _XF86MODES_H_
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xorgVersion.h"
+#include "edid.h"
+#include "xf86Parser.h"
+#if XF86_MODES_RENAME
+#include "xf86Rename.h"
+#endif
+
+double xf86ModeHSync(DisplayModePtr mode);
+double xf86ModeVRefresh(DisplayModePtr mode);
+
+int
+xf86ModeWidth (DisplayModePtr mode, Rotation rotation);
+
+int
+xf86ModeHeight (DisplayModePtr mode, Rotation rotation);
+
+DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode);
+DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn,
+ DisplayModePtr modeList);
+void xf86SetModeDefaultName(DisplayModePtr mode);
+void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
+Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
+void xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
+DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
+
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
+ Bool Reduced, Bool Interlaced);
+
+void
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int flags);
+
+void
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int *min, int *max, int n_ranges);
+
+void
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int maxX, int maxY, int maxPitch);
+
+void
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ MonPtr mon);
+
+void
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+ Bool verbose);
+
+void
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+ int flags);
+
+void
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+
+DisplayModePtr
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
+
+DisplayModePtr
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
+
+#endif /* _XF86MODES_H_ */
diff --git a/driver/xf86-video-intel/src/modes/xf86RandR12.c b/driver/xf86-video-intel/src/modes/xf86RandR12.c
new file mode 100644
index 000000000..7169f74c8
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86RandR12.c
@@ -0,0 +1,1139 @@
+/*
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86.h"
+#include "os.h"
+#include "mibank.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+#include "mipointer.h"
+#include "windowstr.h"
+#include <randrstr.h>
+#include <X11/extensions/render.h>
+
+#include "xf86Crtc.h"
+#include "xf86RandR12.h"
+
+typedef struct _xf86RandR12Info {
+ int virtualX;
+ int virtualY;
+ int mmWidth;
+ int mmHeight;
+ int maxX;
+ int maxY;
+ Rotation rotation; /* current mode */
+ Rotation supported_rotations; /* driver supported */
+} XF86RandRInfoRec, *XF86RandRInfoPtr;
+
+#ifdef RANDR_12_INTERFACE
+static Bool xf86RandR12Init12 (ScreenPtr pScreen);
+static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
+#endif
+
+static int xf86RandR12Index;
+static int xf86RandR12Generation;
+
+#define XF86RANDRINFO(p) \
+ ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
+
+static int
+xf86RandR12ModeRefresh (DisplayModePtr mode)
+{
+ if (mode->VRefresh)
+ return (int) (mode->VRefresh + 0.5);
+ else
+ return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
+}
+
+static Bool
+xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ RRScreenSizePtr pSize;
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ int refresh0 = 60;
+ int maxX = 0, maxY = 0;
+
+ *rotations = randrp->supported_rotations;
+
+ if (randrp->virtualX == -1 || randrp->virtualY == -1)
+ {
+ randrp->virtualX = scrp->virtualX;
+ randrp->virtualY = scrp->virtualY;
+ }
+
+ /* Re-probe the outputs for new monitors or modes */
+ if (scrp->vtSema)
+ {
+ xf86ProbeOutputModes (scrp, 0, 0);
+ xf86SetScrnInfoModes (scrp);
+ xf86DiDGAReInit (pScreen);
+ }
+
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ int refresh = xf86RandR12ModeRefresh (mode);
+ if (randrp->maxX == 0 || randrp->maxY == 0)
+ {
+ if (maxX < mode->HDisplay)
+ maxX = mode->HDisplay;
+ if (maxY < mode->VDisplay)
+ maxY = mode->VDisplay;
+ }
+ if (mode == scrp->modes)
+ refresh0 = refresh;
+ pSize = RRRegisterSize (pScreen,
+ mode->HDisplay, mode->VDisplay,
+ randrp->mmWidth, randrp->mmHeight);
+ if (!pSize)
+ return FALSE;
+ RRRegisterRate (pScreen, pSize, refresh);
+
+ if (xf86ModesEqual(mode, scrp->currentMode) &&
+ mode->HDisplay == scrp->virtualX &&
+ mode->VDisplay == scrp->virtualY)
+ {
+ RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
+ }
+ if (mode->next == scrp->modes)
+ break;
+ }
+
+ if (randrp->maxX == 0 || randrp->maxY == 0)
+ {
+ randrp->maxX = maxX;
+ randrp->maxY = maxY;
+ }
+
+ if (scrp->currentMode->HDisplay != randrp->virtualX ||
+ scrp->currentMode->VDisplay != randrp->virtualY)
+ {
+ pSize = RRRegisterSize (pScreen,
+ randrp->virtualX, randrp->virtualY,
+ randrp->mmWidth,
+ randrp->mmHeight);
+ if (!pSize)
+ return FALSE;
+ RRRegisterRate (pScreen, pSize, refresh0);
+ if (scrp->virtualX == randrp->virtualX &&
+ scrp->virtualY == randrp->virtualY)
+ {
+ RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+xf86RandR12SetMode (ScreenPtr pScreen,
+ DisplayModePtr mode,
+ Bool useVirtual,
+ int mmWidth,
+ int mmHeight)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ int oldWidth = pScreen->width;
+ int oldHeight = pScreen->height;
+ int oldmmWidth = pScreen->mmWidth;
+ int oldmmHeight = pScreen->mmHeight;
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+ DisplayModePtr currentMode = NULL;
+ Bool ret = TRUE;
+ PixmapPtr pspix = NULL;
+
+ if (pRoot)
+ (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+ if (useVirtual)
+ {
+ scrp->virtualX = randrp->virtualX;
+ scrp->virtualY = randrp->virtualY;
+ }
+ else
+ {
+ scrp->virtualX = mode->HDisplay;
+ scrp->virtualY = mode->VDisplay;
+ }
+
+ if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
+ {
+ /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
+ pScreen->width = scrp->virtualY;
+ pScreen->height = scrp->virtualX;
+ pScreen->mmWidth = mmHeight;
+ pScreen->mmHeight = mmWidth;
+ }
+ else
+ {
+ pScreen->width = scrp->virtualX;
+ pScreen->height = scrp->virtualY;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
+ }
+ if (scrp->currentMode == mode) {
+ /* Save current mode */
+ currentMode = scrp->currentMode;
+ /* Reset, just so we ensure the drivers SwitchMode is called */
+ scrp->currentMode = NULL;
+ }
+ /*
+ * We know that if the driver failed to SwitchMode to the rotated
+ * version, then it should revert back to it's prior mode.
+ */
+ if (!xf86SwitchMode (pScreen, mode))
+ {
+ ret = FALSE;
+ scrp->virtualX = pScreen->width = oldWidth;
+ scrp->virtualY = pScreen->height = oldHeight;
+ pScreen->mmWidth = oldmmWidth;
+ pScreen->mmHeight = oldmmHeight;
+ scrp->currentMode = currentMode;
+ }
+ /*
+ * Get the new Screen pixmap ptr as SwitchMode might have called
+ * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
+ * Unfortunately.
+ */
+ pspix = (*pScreen->GetScreenPixmap) (pScreen);
+ if (pspix->devPrivate.ptr)
+ scrp->pixmapPrivate = pspix->devPrivate;
+
+ /*
+ * Make sure the layout is correct
+ */
+ xf86ReconfigureLayout();
+
+ /*
+ * Make sure the whole screen is visible
+ */
+ xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+ xf86SetViewport (pScreen, 0, 0);
+ if (pRoot)
+ (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+ return ret;
+}
+
+_X_EXPORT Bool
+xf86RandR12SetConfig (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ int px, py;
+ Bool useVirtual = FALSE;
+ int maxX = 0, maxY = 0;
+ Rotation oldRotation = randrp->rotation;
+
+ randrp->rotation = rotation;
+
+ if (randrp->virtualX == -1 || randrp->virtualY == -1)
+ {
+ randrp->virtualX = scrp->virtualX;
+ randrp->virtualY = scrp->virtualY;
+ }
+
+ miPointerPosition (&px, &py);
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ if (randrp->maxX == 0 || randrp->maxY == 0)
+ {
+ if (maxX < mode->HDisplay)
+ maxX = mode->HDisplay;
+ if (maxY < mode->VDisplay)
+ maxY = mode->VDisplay;
+ }
+ if (mode->HDisplay == pSize->width &&
+ mode->VDisplay == pSize->height &&
+ (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
+ break;
+ if (mode->next == scrp->modes)
+ {
+ if (pSize->width == randrp->virtualX &&
+ pSize->height == randrp->virtualY)
+ {
+ mode = scrp->modes;
+ useVirtual = TRUE;
+ break;
+ }
+ if (randrp->maxX == 0 || randrp->maxY == 0)
+ {
+ randrp->maxX = maxX;
+ randrp->maxY = maxY;
+ }
+ return FALSE;
+ }
+ }
+
+ if (randrp->maxX == 0 || randrp->maxY == 0)
+ {
+ randrp->maxX = maxX;
+ randrp->maxY = maxY;
+ }
+
+ if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+ pSize->mmHeight)) {
+ randrp->rotation = oldRotation;
+ return FALSE;
+ }
+
+ /*
+ * Move the cursor back where it belongs; SwitchMode repositions it
+ */
+ if (pScreen == miPointerCurrentScreen ())
+ {
+ px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+ py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+
+ xf86SetViewport(pScreen, px, py);
+
+ (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+ }
+
+ return TRUE;
+}
+
+static Bool
+xf86RandR12ScreenSetSize (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight)
+{
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+ PixmapPtr pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
+ Bool ret = FALSE;
+
+ if (randrp->virtualX == -1 || randrp->virtualY == -1)
+ {
+ randrp->virtualX = pScrn->virtualX;
+ randrp->virtualY = pScrn->virtualY;
+ }
+ if (pRoot && pScrn->vtSema)
+ (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+
+ /* Let the driver update virtualX and virtualY */
+ if (!(*config->funcs->resize)(pScrn, width, height))
+ goto finish;
+
+ ret = TRUE;
+
+ pScreen->width = pScrnPix->drawable.width = width;
+ pScreen->height = pScrnPix->drawable.height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
+
+ xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
+ xf86SetViewport (pScreen, 0, 0);
+
+finish:
+ if (pRoot && pScrn->vtSema)
+ (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+#if RANDR_12_INTERFACE
+ if (WindowTable[pScreen->myNum] && ret)
+ RRScreenSizeNotify (pScreen);
+#endif
+ return ret;
+}
+
+_X_EXPORT Rotation
+xf86RandR12GetRotation(ScreenPtr pScreen)
+{
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+ return randrp->rotation;
+}
+
+_X_EXPORT Bool
+xf86RandR12CreateScreenResources (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ int c;
+ int width, height;
+ int mmWidth, mmHeight;
+#ifdef PANORAMIX
+ /* XXX disable RandR when using Xinerama */
+ if (!noPanoramiXExtension)
+ return TRUE;
+#endif
+
+ /*
+ * Compute size of screen
+ */
+ width = 0; height = 0;
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+
+ if (crtc->enabled && crtc_width > width)
+ width = crtc_width;
+ if (crtc->enabled && crtc_height > height)
+ height = crtc_height;
+ }
+
+ if (width && height)
+ {
+ /*
+ * Compute physical size of screen
+ */
+ if (monitorResolution)
+ {
+ mmWidth = width * 25.4 / monitorResolution;
+ mmHeight = height * 25.4 / monitorResolution;
+ }
+ else
+ {
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (output->conf_monitor &&
+ (output->conf_monitor->mon_width > 0 &&
+ output->conf_monitor->mon_height > 0))
+ {
+ /*
+ * Prefer user configured DisplaySize
+ */
+ mmWidth = output->conf_monitor->mon_width;
+ mmHeight = output->conf_monitor->mon_height;
+ }
+ else if (crtc && crtc->mode.HDisplay &&
+ output->mm_width && output->mm_height)
+ {
+ /*
+ * If the output has a mode and a declared size, use that
+ * to scale the screen size
+ */
+ DisplayModePtr mode = &crtc->mode;
+ mmWidth = output->mm_width * width / mode->HDisplay;
+ mmHeight = output->mm_height * height / mode->VDisplay;
+ }
+ else
+ {
+ /*
+ * Otherwise, just set the screen to 96dpi
+ */
+ mmWidth = width * 25.4 / 96;
+ mmHeight = height * 25.4 / 96;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Setting screen physical size to %d x %d\n",
+ mmWidth, mmHeight);
+ xf86RandR12ScreenSetSize (pScreen,
+ width,
+ height,
+ mmWidth,
+ mmHeight);
+ }
+
+ if (randrp->virtualX == -1 || randrp->virtualY == -1)
+ {
+ randrp->virtualX = pScrn->virtualX;
+ randrp->virtualY = pScrn->virtualY;
+ }
+ xf86CrtcSetScreenSubpixelOrder (pScreen);
+#if RANDR_12_INTERFACE
+ if (xf86RandR12CreateScreenResources12 (pScreen))
+ return TRUE;
+#endif
+ return TRUE;
+}
+
+
+_X_EXPORT Bool
+xf86RandR12Init (ScreenPtr pScreen)
+{
+ rrScrPrivPtr rp;
+ XF86RandRInfoPtr randrp;
+
+#ifdef PANORAMIX
+ /* XXX disable RandR when using Xinerama */
+ if (!noPanoramiXExtension)
+ return TRUE;
+#endif
+ if (xf86RandR12Generation != serverGeneration)
+ {
+ xf86RandR12Index = AllocateScreenPrivateIndex();
+ xf86RandR12Generation = serverGeneration;
+ }
+
+ randrp = xalloc (sizeof (XF86RandRInfoRec));
+ if (!randrp)
+ return FALSE;
+
+ if (!RRScreenInit(pScreen))
+ {
+ xfree (randrp);
+ return FALSE;
+ }
+ rp = rrGetScrPriv(pScreen);
+ rp->rrGetInfo = xf86RandR12GetInfo;
+ rp->rrSetConfig = xf86RandR12SetConfig;
+
+ randrp->virtualX = -1;
+ randrp->virtualY = -1;
+ randrp->mmWidth = pScreen->mmWidth;
+ randrp->mmHeight = pScreen->mmHeight;
+
+ randrp->rotation = RR_Rotate_0; /* initial rotated mode */
+
+ randrp->supported_rotations = RR_Rotate_0;
+
+ randrp->maxX = randrp->maxY = 0;
+
+ pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
+
+#if RANDR_12_INTERFACE
+ if (!xf86RandR12Init12 (pScreen))
+ return FALSE;
+#endif
+ return TRUE;
+}
+
+_X_EXPORT void
+xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
+{
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+#if RANDR_12_INTERFACE
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ int c;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ for (c = 0; c < config->num_crtc; c++) {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ RRCrtcSetRotations (crtc->randr_crtc, rotations);
+ }
+#endif
+ randrp->supported_rotations = rotations;
+}
+
+_X_EXPORT void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+{
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ if (xf86RandR12Generation != serverGeneration ||
+ XF86RANDRINFO(pScreen)->virtualX == -1)
+ {
+ *x = pScrn->virtualX;
+ *y = pScrn->virtualY;
+ } else {
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+ *x = randrp->virtualX;
+ *y = randrp->virtualY;
+ }
+}
+
+#if RANDR_12_INTERFACE
+
+#define FLAG_BITS (RR_HSyncPositive | \
+ RR_HSyncNegative | \
+ RR_VSyncPositive | \
+ RR_VSyncNegative | \
+ RR_Interlace | \
+ RR_DoubleScan | \
+ RR_CSync | \
+ RR_CSyncPositive | \
+ RR_CSyncNegative | \
+ RR_HSkewPresent | \
+ RR_BCast | \
+ RR_PixelMultiplex | \
+ RR_DoubleClock | \
+ RR_ClockDivideBy2)
+
+static Bool
+xf86RandRModeMatches (RRModePtr randr_mode,
+ DisplayModePtr mode)
+{
+#if 0
+ if (match_name)
+ {
+ /* check for same name */
+ int len = strlen (mode->name);
+ if (randr_mode->mode.nameLength != len) return FALSE;
+ if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE;
+ }
+#endif
+
+ /* check for same timings */
+ if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE;
+ if (randr_mode->mode.width != mode->HDisplay) return FALSE;
+ if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE;
+ if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE;
+ if (randr_mode->mode.hTotal != mode->HTotal) return FALSE;
+ if (randr_mode->mode.hSkew != mode->HSkew) return FALSE;
+ if (randr_mode->mode.height != mode->VDisplay) return FALSE;
+ if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE;
+ if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE;
+ if (randr_mode->mode.vTotal != mode->VTotal) return FALSE;
+
+ /* check for same flags (using only the XF86 valid flag bits) */
+ if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
+ return FALSE;
+
+ /* everything matches */
+ return TRUE;
+}
+
+static Bool
+xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
+{
+ ScreenPtr pScreen = randr_crtc->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RRModePtr randr_mode = NULL;
+ int x;
+ int y;
+ Rotation rotation;
+ int numOutputs;
+ RROutputPtr *randr_outputs;
+ RROutputPtr randr_output;
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+ xf86OutputPtr output;
+ int i, j;
+ DisplayModePtr mode = &crtc->mode;
+ Bool ret;
+
+ randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+ if (!randr_outputs)
+ return FALSE;
+ x = crtc->x;
+ y = crtc->y;
+ rotation = crtc->rotation;
+ numOutputs = 0;
+ randr_mode = NULL;
+ for (i = 0; i < config->num_output; i++)
+ {
+ output = config->output[i];
+ if (output->crtc == crtc)
+ {
+ randr_output = output->randr_output;
+ randr_outputs[numOutputs++] = randr_output;
+ /*
+ * We make copies of modes, so pointer equality
+ * isn't sufficient
+ */
+ for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++)
+ {
+ RRModePtr m = (j < randr_output->numModes ?
+ randr_output->modes[j] :
+ randr_output->userModes[j-randr_output->numModes]);
+
+ if (xf86RandRModeMatches (m, mode))
+ {
+ randr_mode = m;
+ break;
+ }
+ }
+ }
+ }
+ ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
+ rotation, numOutputs, randr_outputs);
+ DEALLOCATE_LOCAL(randr_outputs);
+ return ret;
+}
+
+/*
+ * Convert a RandR mode to a DisplayMode
+ */
+static void
+xf86RandRModeConvert (ScrnInfoPtr scrn,
+ RRModePtr randr_mode,
+ DisplayModePtr mode)
+{
+ mode->prev = NULL;
+ mode->next = NULL;
+ mode->name = NULL;
+ mode->status = MODE_OK;
+ mode->type = 0;
+
+ mode->Clock = randr_mode->mode.dotClock / 1000;
+
+ mode->HDisplay = randr_mode->mode.width;
+ mode->HSyncStart = randr_mode->mode.hSyncStart;
+ mode->HSyncEnd = randr_mode->mode.hSyncEnd;
+ mode->HTotal = randr_mode->mode.hTotal;
+ mode->HSkew = randr_mode->mode.hSkew;
+
+ mode->VDisplay = randr_mode->mode.height;
+ mode->VSyncStart = randr_mode->mode.vSyncStart;
+ mode->VSyncEnd = randr_mode->mode.vSyncEnd;
+ mode->VTotal = randr_mode->mode.vTotal;
+ mode->VScan = 0;
+
+ mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
+
+ xf86SetModeCrtc (mode, scrn->adjustFlags);
+}
+
+static Bool
+xf86RandR12CrtcSet (ScreenPtr pScreen,
+ RRCrtcPtr randr_crtc,
+ RRModePtr randr_mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int num_randr_outputs,
+ RROutputPtr *randr_outputs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+ Bool changed = FALSE;
+ int o, ro;
+ xf86CrtcPtr *save_crtcs;
+ Bool save_enabled = crtc->enabled;
+
+ save_crtcs = ALLOCATE_LOCAL(config->num_output * sizeof (xf86CrtcPtr));
+ if ((randr_mode != NULL) != crtc->enabled)
+ changed = TRUE;
+ else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
+ changed = TRUE;
+
+ if (rotation != crtc->rotation)
+ changed = TRUE;
+
+ if (x != crtc->x || y != crtc->y)
+ changed = TRUE;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ xf86CrtcPtr new_crtc;
+
+ save_crtcs[o] = output->crtc;
+
+ if (output->crtc == crtc)
+ new_crtc = NULL;
+ else
+ new_crtc = output->crtc;
+ for (ro = 0; ro < num_randr_outputs; ro++)
+ if (output->randr_output == randr_outputs[ro])
+ {
+ new_crtc = crtc;
+ break;
+ }
+ if (new_crtc != output->crtc)
+ {
+ changed = TRUE;
+ output->crtc = new_crtc;
+ }
+ }
+ for (ro = 0; ro < num_randr_outputs; ro++)
+ if (randr_outputs[ro]->pendingProperties)
+ changed = TRUE;
+
+ /* XXX need device-independent mode setting code through an API */
+ if (changed)
+ {
+ crtc->enabled = randr_mode != NULL;
+
+ if (randr_mode)
+ {
+ DisplayModeRec mode;
+
+ xf86RandRModeConvert (pScrn, randr_mode, &mode);
+ if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y))
+ {
+ crtc->enabled = save_enabled;
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ output->crtc = save_crtcs[o];
+ }
+ DEALLOCATE_LOCAL(save_crtcs);
+ return FALSE;
+ }
+ /*
+ * Save the last successful setting for EnterVT
+ */
+ crtc->desiredMode = mode;
+ crtc->desiredRotation = rotation;
+ crtc->desiredX = x;
+ crtc->desiredY = y;
+ }
+ xf86DisableUnusedFunctions (pScrn);
+ }
+ DEALLOCATE_LOCAL(save_crtcs);
+ return xf86RandR12CrtcNotify (randr_crtc);
+}
+
+static Bool
+xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
+ RRCrtcPtr randr_crtc)
+{
+ xf86CrtcPtr crtc = randr_crtc->devPrivate;
+
+ if (crtc->funcs->gamma_set == NULL)
+ return FALSE;
+
+ if (!crtc->scrn->vtSema)
+ return TRUE;
+
+ crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
+ randr_crtc->gammaBlue, randr_crtc->gammaSize);
+
+ return TRUE;
+}
+
+static Bool
+xf86RandR12OutputSetProperty (ScreenPtr pScreen,
+ RROutputPtr randr_output,
+ Atom property,
+ RRPropertyValuePtr value)
+{
+ xf86OutputPtr output = randr_output->devPrivate;
+
+ /* If we don't have any property handler, then we don't care what the
+ * user is setting properties to.
+ */
+ if (output->funcs->set_property == NULL)
+ return TRUE;
+
+ /*
+ * This function gets called even when vtSema is FALSE, as
+ * drivers will need to remember the correct value to apply
+ * when the VT switch occurs
+ */
+ return output->funcs->set_property(output, property, value);
+}
+
+static Bool
+xf86RandR12OutputValidateMode (ScreenPtr pScreen,
+ RROutputPtr randr_output,
+ RRModePtr randr_mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86OutputPtr output = randr_output->devPrivate;
+ DisplayModeRec mode;
+
+ xf86RandRModeConvert (pScrn, randr_mode, &mode);
+ /*
+ * This function may be called when vtSema is FALSE, so
+ * the underlying function must either avoid touching the hardware
+ * or return FALSE when vtSema is FALSE
+ */
+ if (output->funcs->mode_valid (output, &mode) != MODE_OK)
+ return FALSE;
+ return TRUE;
+}
+
+static void
+xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
+{
+}
+
+/**
+ * Given a list of xf86 modes and a RandR Output object, construct
+ * RandR modes and assign them to the output
+ */
+static Bool
+xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
+{
+ DisplayModePtr mode;
+ RRModePtr *rrmodes = NULL;
+ int nmode = 0;
+ int npreferred = 0;
+ Bool ret = TRUE;
+ int pref;
+
+ for (mode = modes; mode; mode = mode->next)
+ nmode++;
+
+ if (nmode) {
+ rrmodes = xalloc (nmode * sizeof (RRModePtr));
+
+ if (!rrmodes)
+ return FALSE;
+ nmode = 0;
+
+ for (pref = 1; pref >= 0; pref--) {
+ for (mode = modes; mode; mode = mode->next) {
+ if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
+ xRRModeInfo modeInfo;
+ RRModePtr rrmode;
+
+ modeInfo.nameLength = strlen (mode->name);
+ modeInfo.width = mode->HDisplay;
+ modeInfo.dotClock = mode->Clock * 1000;
+ modeInfo.hSyncStart = mode->HSyncStart;
+ modeInfo.hSyncEnd = mode->HSyncEnd;
+ modeInfo.hTotal = mode->HTotal;
+ modeInfo.hSkew = mode->HSkew;
+
+ modeInfo.height = mode->VDisplay;
+ modeInfo.vSyncStart = mode->VSyncStart;
+ modeInfo.vSyncEnd = mode->VSyncEnd;
+ modeInfo.vTotal = mode->VTotal;
+ modeInfo.modeFlags = mode->Flags;
+
+ rrmode = RRModeGet (&modeInfo, mode->name);
+ if (rrmode) {
+ rrmodes[nmode++] = rrmode;
+ npreferred += pref;
+ }
+ }
+ }
+ }
+ }
+
+ ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
+ xfree (rrmodes);
+ return ret;
+}
+
+/*
+ * Mirror the current mode configuration to RandR
+ */
+static Bool
+xf86RandR12SetInfo12 (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RROutputPtr *clones;
+ RRCrtcPtr *crtcs;
+ int ncrtc;
+ int o, c, l;
+ RRCrtcPtr randr_crtc;
+ int nclone;
+
+ clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+ crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ ncrtc = 0;
+ for (c = 0; c < config->num_crtc; c++)
+ if (output->possible_crtcs & (1 << c))
+ crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
+
+ if (output->crtc)
+ randr_crtc = output->crtc->randr_crtc;
+ else
+ randr_crtc = NULL;
+
+ if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
+ {
+ DEALLOCATE_LOCAL (crtcs);
+ DEALLOCATE_LOCAL (clones);
+ return FALSE;
+ }
+
+ RROutputSetPhysicalSize(output->randr_output,
+ output->mm_width,
+ output->mm_height);
+ xf86RROutputSetModes (output->randr_output, output->probed_modes);
+
+ switch (output->status) {
+ case XF86OutputStatusConnected:
+ RROutputSetConnection (output->randr_output, RR_Connected);
+ break;
+ case XF86OutputStatusDisconnected:
+ RROutputSetConnection (output->randr_output, RR_Disconnected);
+ break;
+ case XF86OutputStatusUnknown:
+ RROutputSetConnection (output->randr_output, RR_UnknownConnection);
+ break;
+ }
+
+ RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
+
+ /*
+ * Valid clones
+ */
+ nclone = 0;
+ for (l = 0; l < config->num_output; l++)
+ {
+ xf86OutputPtr clone = config->output[l];
+
+ if (l != o && (output->possible_clones & (1 << l)))
+ clones[nclone++] = clone->randr_output;
+ }
+ if (!RROutputSetClones (output->randr_output, clones, nclone))
+ {
+ DEALLOCATE_LOCAL (crtcs);
+ DEALLOCATE_LOCAL (clones);
+ return FALSE;
+ }
+ }
+ DEALLOCATE_LOCAL (crtcs);
+ DEALLOCATE_LOCAL (clones);
+ return TRUE;
+}
+
+
+
+/*
+ * Query the hardware for the current state, then mirror
+ * that to RandR
+ */
+static Bool
+xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ if (!pScrn->vtSema)
+ return TRUE;
+ xf86ProbeOutputModes (pScrn, 0, 0);
+ xf86SetScrnInfoModes (pScrn);
+ xf86DiDGAReInit (pScreen);
+ return xf86RandR12SetInfo12 (pScreen);
+}
+
+static Bool
+xf86RandR12CreateObjects12 (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+ int o;
+
+ if (!RRInit ())
+ return FALSE;
+
+ /*
+ * Configure crtcs
+ */
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+
+ crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
+ RRCrtcGammaSetSize (crtc->randr_crtc, 256);
+ }
+ /*
+ * Configure outputs
+ */
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+
+ output->randr_output = RROutputCreate (pScreen, output->name,
+ strlen (output->name),
+ output);
+
+ if (output->funcs->create_resources != NULL)
+ output->funcs->create_resources(output);
+ RRPostPendingProperties (output->randr_output);
+ }
+ return TRUE;
+}
+
+static Bool
+xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
+{
+ int c;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ for (c = 0; c < config->num_crtc; c++)
+ xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
+
+
+ RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
+ config->maxWidth, config->maxHeight);
+ return TRUE;
+}
+
+/*
+ * Something happened within the screen configuration due
+ * to DGA, VidMode or hot key. Tell RandR
+ */
+
+_X_EXPORT void
+xf86RandR12TellChanged (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ int c;
+
+ if (!randrp)
+ return;
+ xf86RandR12SetInfo12 (pScreen);
+ for (c = 0; c < config->num_crtc; c++)
+ xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
+
+ RRTellChanged (pScreen);
+}
+
+static void
+xf86RandR12PointerMoved (int scrnIndex, int x, int y)
+{
+}
+
+static Bool
+xf86RandR12Init12 (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ rrScrPrivPtr rp = rrGetScrPriv(pScreen);
+
+ rp->rrGetInfo = xf86RandR12GetInfo12;
+ rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
+ rp->rrCrtcSet = xf86RandR12CrtcSet;
+ rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
+ rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
+ rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
+ rp->rrModeDestroy = xf86RandR12ModeDestroy;
+ rp->rrSetConfig = NULL;
+ pScrn->PointerMoved = xf86RandR12PointerMoved;
+ if (!xf86RandR12CreateObjects12 (pScreen))
+ return FALSE;
+
+ /*
+ * Configure output modes
+ */
+ if (!xf86RandR12SetInfo12 (pScreen))
+ return FALSE;
+ return TRUE;
+}
+
+#endif
+
+_X_EXPORT Bool
+xf86RandR12PreInit (ScrnInfoPtr pScrn)
+{
+ return TRUE;
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86RandR12.h b/driver/xf86-video-intel/src/modes/xf86RandR12.h
new file mode 100644
index 000000000..4fd855cf5
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86RandR12.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef _XF86_RANDR_H_
+#define _XF86_RANDR_H_
+#include <randrstr.h>
+#include <X11/extensions/render.h>
+#if XF86_MODES_RENAME
+#include "xf86Rename.h"
+#endif
+
+Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
+Bool xf86RandR12Init(ScreenPtr pScreen);
+void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
+Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+ RRScreenSizePtr pSize);
+Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
+void xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+Bool xf86RandR12PreInit (ScrnInfoPtr pScrn);
+void xf86RandR12TellChanged (ScreenPtr pScreen);
+
+#endif /* _XF86_RANDR_H_ */
diff --git a/driver/xf86-video-intel/src/modes/xf86Rename.h b/driver/xf86-video-intel/src/modes/xf86Rename.h
new file mode 100644
index 000000000..b8c1d70ef
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Rename.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef _XF86RENAME_H_
+#define _XF86RENAME_H_
+
+#include "local_xf86Rename.h"
+
+#define xf86_cursors_fini XF86NAME(xf86_cursors_fini)
+#define xf86_cursors_init XF86NAME(xf86_cursors_init)
+#define xf86_hide_cursors XF86NAME(xf86_hide_cursors)
+#define xf86_reload_cursors XF86NAME(xf86_reload_cursors)
+#define xf86_show_cursors XF86NAME(xf86_show_cursors)
+#define xf86ConnectorGetName XF86NAME(xf86ConnectorGetName)
+#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit)
+#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex)
+#define xf86CrtcCreate XF86NAME(xf86CrtcCreate)
+#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy)
+#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
+#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
+#define xf86CrtcScreenInit XF86NAME(xf86CrtcScreenInit)
+#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
+#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
+#define xf86CVTMode XF86NAME(xf86CVTMode)
+#define xf86DDCMonitorSet XF86NAME(xf86DDCMonitorSet)
+#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions)
+#define xf86DPMSSet XF86NAME(xf86DPMSSet)
+#define xf86DuplicateMode XF86NAME(xf86DuplicateMode)
+#define xf86DuplicateModes XF86NAME(xf86DuplicateModes)
+#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes)
+#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes)
+#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration)
+#define xf86ModeHSync XF86NAME(xf86ModeHSync)
+#define xf86ModesAdd XF86NAME(xf86ModesAdd)
+#define xf86ModesEqual XF86NAME(xf86ModesEqual)
+#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh)
+#define xf86OutputCreate XF86NAME(xf86OutputCreate)
+#define xf86OutputDestroy XF86NAME(xf86OutputDestroy)
+#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID)
+#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes)
+#define xf86OutputRename XF86NAME(xf86OutputRename)
+#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID)
+#define xf86OutputUseScreenMonitor XF86NAME(xf86OutputUseScreenMonitor)
+#define xf86PrintModeline XF86NAME(xf86PrintModeline)
+#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes)
+#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes)
+#define xf86RotateCloseScreen XF86NAME(xf86RotateCloseScreen)
+#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc)
+#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName)
+#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes)
+#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks)
+#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags)
+#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
+#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
+#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
+#define xf86DiDGAInit XF86NAME(xf86DiDGAInit)
+#define xf86DiDGAReInit XF86NAME(xf86DiDGAReInit)
+#define xf86DDCGetModes XF86NAME(xf86DDCGetModes)
+#define xf86RandR12CreateScreenResources XF86NAME(xf86RandR12CreateScreenResources)
+#define xf86RandR12GetOriginalVirtualSize XF86NAME(xf86RandR12GetOriginalVirtualSize)
+#define xf86RandR12GetRotation XF86NAME(xf86RandR12GetRotation)
+#define xf86RandR12Init XF86NAME(xf86RandR12Init)
+#define xf86RandR12PreInit XF86NAME(xf86RandR12PreInit)
+#define xf86RandR12SetConfig XF86NAME(xf86RandR12SetConfig)
+#define xf86RandR12SetRotations XF86NAME(xf86RandR12SetRotations)
+#define xf86SaveScreen XF86NAME(xf86SaveScreen)
+#define xf86CrtcSetScreenSubpixelOrder XF86NAME(xf86CrtcSetScreenSubpixelOrder)
+#define xf86ModeWidth XF86NAME(xf86ModeWidth)
+#define xf86ModeHeight XF86NAME(xf86ModeHeight)
+#define xf86OutputFindClosestMode XF86NAME(xf86OutputFindClosestMode)
+#define xf86SetSingleMode XF86NAME(xf86SetSingleMode)
+#define xf86SetDesiredModes XF86NAME(xf86SetDesiredModes)
+
+#endif /* _XF86RENAME_H_ */
diff --git a/driver/xf86-video-intel/src/modes/xf86Rotate.c b/driver/xf86-video-intel/src/modes/xf86Rotate.c
new file mode 100644
index 000000000..380478f7f
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86Rotate.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "fb.h"
+#include "windowstr.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+
+/* borrowed from composite extension, move to Render and publish? */
+
+static VisualPtr
+compGetWindowVisual (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ VisualID vid = wVisual (pWin);
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ if (pScreen->visuals[i].vid == vid)
+ return &pScreen->visuals[i];
+ return 0;
+}
+
+static PictFormatPtr
+compWindowFormat (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ return PictureMatchVisual (pScreen, pWin->drawable.depth,
+ compGetWindowVisual (pWin));
+}
+
+#define F(x) IntToxFixed(x)
+
+static void
+PictureTransformIdentity (PictTransformPtr matrix)
+{
+ int i;
+ memset (matrix, '\0', sizeof (PictTransform));
+ for (i = 0; i < 3; i++)
+ matrix->matrix[i][i] = F(1);
+}
+
+static Bool
+PictureTransformMultiply (PictTransformPtr dst, PictTransformPtr l, PictTransformPtr r)
+{
+ PictTransform d;
+ int dx, dy;
+ int o;
+
+ for (dy = 0; dy < 3; dy++)
+ for (dx = 0; dx < 3; dx++)
+ {
+ xFixed_48_16 v;
+ xFixed_32_32 partial;
+ v = 0;
+ for (o = 0; o < 3; o++)
+ {
+ partial = (xFixed_32_32) l->matrix[dy][o] * (xFixed_32_32) r->matrix[o][dx];
+ v += partial >> 16;
+ }
+ if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+ return FALSE;
+ d.matrix[dy][dx] = (xFixed) v;
+ }
+ *dst = d;
+ return TRUE;
+}
+
+static void
+PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy)
+{
+ memset (t, '\0', sizeof (PictTransform));
+ t->matrix[0][0] = sx;
+ t->matrix[1][1] = sy;
+ t->matrix[2][2] = F (1);
+}
+
+static xFixed
+fixed_inverse (xFixed x)
+{
+ return (xFixed) ((((xFixed_48_16) F(1)) * F(1)) / x);
+}
+
+static Bool
+PictureTransformScale (PictTransformPtr forward,
+ PictTransformPtr reverse,
+ xFixed sx, xFixed sy)
+{
+ PictTransform t;
+
+ PictureTransformInitScale (&t, sx, sy);
+ if (!PictureTransformMultiply (forward, &t, forward))
+ return FALSE;
+ PictureTransformInitScale (&t, fixed_inverse (sx), fixed_inverse (sy));
+ if (!PictureTransformMultiply (reverse, reverse, &t))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s)
+{
+ memset (t, '\0', sizeof (PictTransform));
+ t->matrix[0][0] = c;
+ t->matrix[0][1] = -s;
+ t->matrix[1][0] = s;
+ t->matrix[1][1] = c;
+ t->matrix[2][2] = F (1);
+}
+
+static Bool
+PictureTransformRotate (PictTransformPtr forward,
+ PictTransformPtr reverse,
+ xFixed c, xFixed s)
+{
+ PictTransform t;
+ PictureTransformInitRotate (&t, c, s);
+ if (!PictureTransformMultiply (forward, &t, forward))
+ return FALSE;
+
+ PictureTransformInitRotate (&t, c, -s);
+ if (!PictureTransformMultiply (reverse, reverse, &t))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty)
+{
+ memset (t, '\0', sizeof (PictTransform));
+ t->matrix[0][0] = F (1);
+ t->matrix[0][2] = tx;
+ t->matrix[1][1] = F (1);
+ t->matrix[1][2] = ty;
+ t->matrix[2][2] = F (1);
+}
+
+static Bool
+PictureTransformTranslate (PictTransformPtr forward,
+ PictTransformPtr reverse,
+ xFixed tx, xFixed ty)
+{
+ PictTransform t;
+ PictureTransformInitTranslate (&t, tx, ty);
+ if (!PictureTransformMultiply (forward, &t, forward))
+ return FALSE;
+
+ PictureTransformInitTranslate (&t, -tx, -ty);
+ if (!PictureTransformMultiply (reverse, reverse, &t))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
+{
+ PictVector v[4];
+ int i;
+ int x1, y1, x2, y2;
+
+ v[0].vector[0] = F (b->x1); v[0].vector[1] = F (b->y1); v[0].vector[2] = F(1);
+ v[1].vector[0] = F (b->x2); v[1].vector[1] = F (b->y1); v[1].vector[2] = F(1);
+ v[2].vector[0] = F (b->x2); v[2].vector[1] = F (b->y2); v[2].vector[2] = F(1);
+ v[3].vector[0] = F (b->x1); v[3].vector[1] = F (b->y2); v[3].vector[2] = F(1);
+ for (i = 0; i < 4; i++)
+ {
+ PictureTransformPoint (matrix, &v[i]);
+ x1 = xFixedToInt (v[i].vector[0]);
+ y1 = xFixedToInt (v[i].vector[1]);
+ x2 = xFixedToInt (xFixedCeil (v[i].vector[0]));
+ y2 = xFixedToInt (xFixedCeil (v[i].vector[1]));
+ if (i == 0)
+ {
+ b->x1 = x1; b->y1 = y1;
+ b->x2 = x2; b->y2 = y2;
+ }
+ else
+ {
+ if (x1 < b->x1) b->x1 = x1;
+ if (y1 < b->y1) b->y1 = y1;
+ if (x2 > b->x2) b->x2 = x2;
+ if (y2 > b->y2) b->y2 = y2;
+ }
+ }
+}
+
+static Bool
+PictureTransformIsIdentity(PictTransform *t)
+{
+ return ((t->matrix[0][0] == t->matrix[1][1]) &&
+ (t->matrix[0][0] == t->matrix[2][2]) &&
+ (t->matrix[0][0] != 0) &&
+ (t->matrix[0][1] == 0) &&
+ (t->matrix[0][2] == 0) &&
+ (t->matrix[1][0] == 0) &&
+ (t->matrix[1][2] == 0) &&
+ (t->matrix[2][0] == 0) &&
+ (t->matrix[2][1] == 0));
+}
+
+#define toF(x) ((float) (x) / 65536.0f)
+
+static void
+PictureTransformErrorF (PictTransform *t)
+{
+ ErrorF ("{ { %f %f %f } { %f %f %f } { %f %f %f } }",
+ toF(t->matrix[0][0]), toF(t->matrix[0][1]), toF(t->matrix[0][2]),
+ toF(t->matrix[1][0]), toF(t->matrix[1][1]), toF(t->matrix[1][2]),
+ toF(t->matrix[2][0]), toF(t->matrix[2][1]), toF(t->matrix[2][2]));
+}
+
+static Bool
+PictureTransformIsInverse (char *where, PictTransform *a, PictTransform *b)
+{
+ PictTransform t;
+
+ PictureTransformMultiply (&t, a, b);
+ if (!PictureTransformIsIdentity (&t))
+ {
+ ErrorF ("%s: ", where);
+ PictureTransformErrorF (a);
+ ErrorF (" * ");
+ PictureTransformErrorF (b);
+ ErrorF (" = ");
+ PictureTransformErrorF (a);
+ ErrorF ("\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ ScreenPtr screen = scrn->pScreen;
+ WindowPtr root = WindowTable[screen->myNum];
+ PixmapPtr dst_pixmap = crtc->rotatedPixmap;
+ PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]);
+ int error;
+ PicturePtr src, dst;
+ int n = REGION_NUM_RECTS(region);
+ BoxPtr b = REGION_RECTS(region);
+ XID include_inferiors = IncludeInferiors;
+
+ src = CreatePicture (None,
+ &root->drawable,
+ format,
+ CPSubwindowMode,
+ &include_inferiors,
+ serverClient,
+ &error);
+ if (!src)
+ return;
+
+ dst = CreatePicture (None,
+ &dst_pixmap->drawable,
+ format,
+ 0L,
+ NULL,
+ serverClient,
+ &error);
+ if (!dst)
+ return;
+
+ error = SetPictureTransform (src, &crtc->crtc_to_framebuffer);
+ if (error)
+ return;
+
+ while (n--)
+ {
+ BoxRec dst_box;
+
+ dst_box = *b;
+ PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc);
+ CompositePicture (PictOpSrc,
+ src, NULL, dst,
+ dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
+ dst_box.x2 - dst_box.x1,
+ dst_box.y2 - dst_box.y1);
+ b++;
+ }
+ FreePicture (src, None);
+ FreePicture (dst, None);
+}
+
+static void
+xf86CrtcDamageShadow (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ BoxRec damage_box;
+ RegionRec damage_region;
+ ScreenPtr pScreen = pScrn->pScreen;
+
+ damage_box.x1 = crtc->x;
+ damage_box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ damage_box.y1 = crtc->y;
+ damage_box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+ REGION_INIT (pScreen, &damage_region, &damage_box, 1);
+ DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+ &damage_region);
+ REGION_UNINIT (pScreen, &damage_region);
+}
+
+static void
+xf86RotatePrepare (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->rotatedData && !crtc->rotatedPixmap)
+ {
+ crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+ crtc->rotatedData,
+ crtc->mode.HDisplay,
+ crtc->mode.VDisplay);
+ if (!xf86_config->rotation_damage_registered)
+ {
+ /* Hook damage to screen pixmap */
+ DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+ xf86_config->rotation_damage);
+ xf86_config->rotation_damage_registered = TRUE;
+ }
+
+ xf86CrtcDamageShadow (crtc);
+ }
+ }
+}
+
+static Bool
+xf86RotateRedisplay(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ DamagePtr damage = xf86_config->rotation_damage;
+ RegionPtr region;
+
+ if (!damage)
+ return FALSE;
+ xf86RotatePrepare (pScreen);
+ region = DamageRegion(damage);
+ if (REGION_NOTEMPTY(pScreen, region))
+ {
+ int c;
+ SourceValidateProcPtr SourceValidate;
+
+ /*
+ * SourceValidate is used by the software cursor code
+ * to pull the cursor off of the screen when reading
+ * bits from the frame buffer. Bypassing this function
+ * leaves the software cursor in place
+ */
+ SourceValidate = pScreen->SourceValidate;
+ pScreen->SourceValidate = NULL;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->rotation != RR_Rotate_0 && crtc->enabled)
+ {
+ RegionRec crtc_damage;
+
+ /* compute portion of damage that overlaps crtc */
+ REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1);
+ REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
+
+ /* update damaged region */
+ if (REGION_NOTEMPTY(pScreen, &crtc_damage))
+ xf86RotateCrtcRedisplay (crtc, &crtc_damage);
+
+ REGION_UNINIT (pScreen, &crtc_damage);
+ }
+ }
+ pScreen->SourceValidate = SourceValidate;
+ DamageEmpty(damage);
+ }
+ return TRUE;
+}
+
+static void
+xf86RotateBlockHandler(int screenNum, pointer blockData,
+ pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ScrnInfoPtr pScrn = xf86Screens[screenNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ pScreen->BlockHandler = xf86_config->BlockHandler;
+ (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
+ if (xf86RotateRedisplay(pScreen))
+ {
+ /* Re-wrap if rotation is still happening */
+ xf86_config->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = xf86RotateBlockHandler;
+ }
+}
+
+static void
+xf86RotateDestroy (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ ScreenPtr pScreen = pScrn->pScreen;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ /* Free memory from rotation */
+ if (crtc->rotatedPixmap || crtc->rotatedData)
+ {
+ crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
+ crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
+ }
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ if (xf86_config->crtc[c]->rotatedPixmap ||
+ xf86_config->crtc[c]->rotatedData)
+ return;
+
+ /*
+ * Clean up damage structures when no crtcs are rotated
+ */
+ if (xf86_config->rotation_damage)
+ {
+ /* Free damage structure */
+ if (xf86_config->rotation_damage_registered)
+ {
+ DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+ xf86_config->rotation_damage);
+ xf86_config->rotation_damage_registered = FALSE;
+ }
+ DamageDestroy (xf86_config->rotation_damage);
+ xf86_config->rotation_damage = NULL;
+ }
+}
+
+_X_EXPORT void
+xf86RotateCloseScreen (ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ xf86RotateDestroy (xf86_config->crtc[c]);
+}
+
+_X_EXPORT Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ ScreenPtr pScreen = pScrn->pScreen;
+ PictTransform crtc_to_fb, fb_to_crtc;
+
+ PictureTransformIdentity (&crtc_to_fb);
+ PictureTransformIdentity (&fb_to_crtc);
+ PictureTransformIsInverse ("identity", &crtc_to_fb, &fb_to_crtc);
+ if (rotation != RR_Rotate_0)
+ {
+ xFixed rot_cos, rot_sin, rot_dx, rot_dy;
+ xFixed scale_x, scale_y, scale_dx, scale_dy;
+ int mode_w = crtc->mode.HDisplay;
+ int mode_h = crtc->mode.VDisplay;
+
+ /* rotation */
+ switch (rotation & 0xf) {
+ default:
+ case RR_Rotate_0:
+ rot_cos = F ( 1); rot_sin = F ( 0);
+ rot_dx = F ( 0); rot_dy = F ( 0);
+ break;
+ case RR_Rotate_90:
+ rot_cos = F ( 0); rot_sin = F ( 1);
+ rot_dx = F ( mode_h); rot_dy = F (0);
+ break;
+ case RR_Rotate_180:
+ rot_cos = F (-1); rot_sin = F ( 0);
+ rot_dx = F (mode_w); rot_dy = F ( mode_h);
+ break;
+ case RR_Rotate_270:
+ rot_cos = F ( 0); rot_sin = F (-1);
+ rot_dx = F ( 0); rot_dy = F ( mode_w);
+ break;
+ }
+
+ PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin);
+ PictureTransformIsInverse ("rotate", &crtc_to_fb, &fb_to_crtc);
+
+ PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy);
+ PictureTransformIsInverse ("rotate translate", &crtc_to_fb, &fb_to_crtc);
+
+ /* reflection */
+ scale_x = F (1);
+ scale_dx = 0;
+ scale_y = F (1);
+ scale_dy = 0;
+ if (rotation & RR_Reflect_X)
+ {
+ scale_x = F(-1);
+ if (rotation & (RR_Rotate_0|RR_Rotate_180))
+ scale_dx = F(mode_w);
+ else
+ scale_dx = F(mode_h);
+ }
+ if (rotation & RR_Reflect_Y)
+ {
+ scale_y = F(-1);
+ if (rotation & (RR_Rotate_0|RR_Rotate_180))
+ scale_dy = F(mode_h);
+ else
+ scale_dy = F(mode_w);
+ }
+
+ PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y);
+ PictureTransformIsInverse ("scale", &crtc_to_fb, &fb_to_crtc);
+
+ PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy);
+ PictureTransformIsInverse ("scale translate", &crtc_to_fb, &fb_to_crtc);
+
+ }
+
+ /*
+ * If the untranslated transformation is the identity,
+ * disable the shadow buffer
+ */
+ if (PictureTransformIsIdentity (&crtc_to_fb))
+ {
+ crtc->transform_in_use = FALSE;
+ PictureTransformInitTranslate (&crtc->crtc_to_framebuffer,
+ F (-crtc->x), F (-crtc->y));
+ PictureTransformInitTranslate (&crtc->framebuffer_to_crtc,
+ F ( crtc->x), F ( crtc->y));
+ xf86RotateDestroy (crtc);
+ }
+ else
+ {
+ PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, crtc->x, crtc->y);
+ PictureTransformIsInverse ("offset", &crtc_to_fb, &fb_to_crtc);
+
+ /*
+ * these are the size of the shadow pixmap, which
+ * matches the mode, not the pre-rotated copy in the
+ * frame buffer
+ */
+ int width = mode->HDisplay;
+ int height = mode->VDisplay;
+ void *shadowData = crtc->rotatedData;
+ PixmapPtr shadow = crtc->rotatedPixmap;
+ int old_width = shadow ? shadow->drawable.width : 0;
+ int old_height = shadow ? shadow->drawable.height : 0;
+
+ /* Allocate memory for rotation */
+ if (old_width != width || old_height != height)
+ {
+ if (shadow || shadowData)
+ {
+ crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+ crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
+ }
+ shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
+ if (!shadowData)
+ goto bail1;
+ crtc->rotatedData = shadowData;
+ /* shadow will be damaged in xf86RotatePrepare */
+ }
+ else
+ {
+ /* mark shadowed area as damaged so it will be repainted */
+ xf86CrtcDamageShadow (crtc);
+ }
+
+ if (!xf86_config->rotation_damage)
+ {
+ /* Create damage structure */
+ xf86_config->rotation_damage = DamageCreate (NULL, NULL,
+ DamageReportNone,
+ TRUE, pScreen, pScreen);
+ if (!xf86_config->rotation_damage)
+ goto bail2;
+
+ /* Wrap block handler */
+ xf86_config->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = xf86RotateBlockHandler;
+ }
+ if (0)
+ {
+ bail2:
+ if (shadow || shadowData)
+ {
+ crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+ crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
+ }
+ bail1:
+ if (old_width && old_height)
+ crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+ NULL,
+ old_width,
+ old_height);
+ return FALSE;
+ }
+ crtc->transform_in_use = TRUE;
+ crtc->crtc_to_framebuffer = crtc_to_fb;
+ crtc->framebuffer_to_crtc = fb_to_crtc;
+ crtc->bounds.x1 = 0;
+ crtc->bounds.x2 = crtc->mode.HDisplay;
+ crtc->bounds.y1 = 0;
+ crtc->bounds.y2 = crtc->mode.VDisplay;
+ PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
+ }
+
+ /* All done */
+ return TRUE;
+}
diff --git a/driver/xf86-video-intel/src/modes/xf86cvt.c b/driver/xf86-video-intel/src/modes/xf86cvt.c
new file mode 100644
index 000000000..69ccc4259
--- /dev/null
+++ b/driver/xf86-video-intel/src/modes/xf86cvt.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2005-2006 Luc Verhaegen.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR 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.
+ */
+
+/**
+ * @file This is a copy of xf86cvt.c from the X Server, for compatibility with
+ * old servers (pre-1.2).
+ */
+
+/*
+ * The reason for having this function in a file of its own is
+ * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
+ * code is shared directly.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86.h"
+#include "xf86Modes.h"
+
+#include <string.h>
+
+/*
+ * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
+ *
+ * These calculations are stolen from the CVT calculation spreadsheet written
+ * by Graham Loveridge. He seems to be claiming no copyright and there seems to
+ * be no license attached to this. He apparently just wants to see his name
+ * mentioned.
+ *
+ * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ * Comments and structure corresponds to the comments and structure of the xls.
+ * This should ease importing of future changes to the standard (not very
+ * likely though).
+ *
+ * About margins; i'm sure that they are to be the bit between HDisplay and
+ * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
+ * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
+ * outside sync "margin" for some reason. Since we prefer seeing proper
+ * blanking instead of the overscan colour, and since the Crtc* values will
+ * probably get altered after us, we will disable margins altogether. With
+ * these calculations, Margins will plainly expand H/VDisplay, and we don't
+ * want that. -- libv
+ *
+ */
+_X_EXPORT DisplayModePtr
+xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+ Bool Interlaced)
+{
+ DisplayModeRec *Mode = xnfalloc(sizeof(DisplayModeRec));
+
+ /* 1) top/bottom margin size (% of height) - default: 1.8 */
+#define CVT_MARGIN_PERCENTAGE 1.8
+
+ /* 2) character cell horizontal granularity (pixels) - default 8 */
+#define CVT_H_GRANULARITY 8
+
+ /* 4) Minimum vertical porch (lines) - default 3 */
+#define CVT_MIN_V_PORCH 3
+
+ /* 4) Minimum number of vertical back porch lines - default 6 */
+#define CVT_MIN_V_BPORCH 6
+
+ /* Pixel Clock step (kHz) */
+#define CVT_CLOCK_STEP 250
+
+ Bool Margins = FALSE;
+ float VFieldRate, HPeriod;
+ int HDisplayRnd, HMargin;
+ int VDisplayRnd, VMargin, VSync;
+ float Interlace; /* Please rename this */
+
+ memset(Mode, 0, sizeof(DisplayModeRec));
+
+ /* CVT default is 60.0Hz */
+ if (!VRefresh)
+ VRefresh = 60.0;
+
+ /* 1. Required field rate */
+ if (Interlaced)
+ VFieldRate = VRefresh * 2;
+ else
+ VFieldRate = VRefresh;
+
+ /* 2. Horizontal pixels */
+ HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
+
+ /* 3. Determine left and right borders */
+ if (Margins) {
+ /* right margin is actually exactly the same as left */
+ HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+ HMargin -= HMargin % CVT_H_GRANULARITY;
+ } else
+ HMargin = 0;
+
+ /* 4. Find total active pixels */
+ Mode->HDisplay = HDisplayRnd + 2*HMargin;
+
+ /* 5. Find number of lines per field */
+ if (Interlaced)
+ VDisplayRnd = VDisplay / 2;
+ else
+ VDisplayRnd = VDisplay;
+
+ /* 6. Find top and bottom margins */
+ /* nope. */
+ if (Margins)
+ /* top and bottom margins are equal again. */
+ VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+ else
+ VMargin = 0;
+
+ Mode->VDisplay = VDisplay + 2*VMargin;
+
+ /* 7. Interlace */
+ if (Interlaced)
+ Interlace = 0.5;
+ else
+ Interlace = 0.0;
+
+ /* Determine VSync Width from aspect ratio */
+ if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
+ VSync = 4;
+ else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
+ VSync = 5;
+ else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
+ VSync = 6;
+ else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
+ VSync = 7;
+ else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
+ VSync = 7;
+ else /* Custom */
+ VSync = 10;
+
+ if (!Reduced) { /* simplified GTF calculation */
+
+ /* 4) Minimum time of vertical sync + back porch interval (µs)
+ * default 550.0 */
+#define CVT_MIN_VSYNC_BP 550.0
+
+ /* 3) Nominal HSync width (% of line period) - default 8 */
+#define CVT_HSYNC_PERCENTAGE 8
+
+ float HBlankPercentage;
+ int VSyncAndBackPorch, VBackPorch;
+ int HBlank;
+
+ /* 8. Estimated Horizontal period */
+ HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
+ (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
+
+ /* 9. Find number of lines in sync + backporch */
+ if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
+ VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
+ else
+ VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
+
+ /* 10. Find number of lines in back porch */
+ VBackPorch = VSyncAndBackPorch - VSync;
+
+ /* 11. Find total number of lines in vertical field */
+ Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
+ + CVT_MIN_V_PORCH;
+
+ /* 5) Definition of Horizontal blanking time limitation */
+ /* Gradient (%/kHz) - default 600 */
+#define CVT_M_FACTOR 600
+
+ /* Offset (%) - default 40 */
+#define CVT_C_FACTOR 40
+
+ /* Blanking time scaling factor - default 128 */
+#define CVT_K_FACTOR 128
+
+ /* Scaling factor weighting - default 20 */
+#define CVT_J_FACTOR 20
+
+#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
+#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
+ CVT_J_FACTOR
+
+ /* 12. Find ideal blanking duty cycle from formula */
+ HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
+
+ /* 13. Blanking time */
+ if (HBlankPercentage < 20)
+ HBlankPercentage = 20;
+
+ HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
+ HBlank -= HBlank % (2*CVT_H_GRANULARITY);
+
+ /* 14. Find total number of pixels in a line. */
+ Mode->HTotal = Mode->HDisplay + HBlank;
+
+ /* Fill in HSync values */
+ Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
+
+ Mode->HSyncStart = Mode->HSyncEnd -
+ (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
+ Mode->HSyncStart += CVT_H_GRANULARITY -
+ Mode->HSyncStart % CVT_H_GRANULARITY;
+
+ /* Fill in VSync values */
+ Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
+ Mode->VSyncEnd = Mode->VSyncStart + VSync;
+
+ } else { /* Reduced blanking */
+ /* Minimum vertical blanking interval time (µs) - default 460 */
+#define CVT_RB_MIN_VBLANK 460.0
+
+ /* Fixed number of clocks for horizontal sync */
+#define CVT_RB_H_SYNC 32.0
+
+ /* Fixed number of clocks for horizontal blanking */
+#define CVT_RB_H_BLANK 160.0
+
+ /* Fixed number of lines for vertical front porch - default 3 */
+#define CVT_RB_VFPORCH 3
+
+ int VBILines;
+
+ /* 8. Estimate Horizontal period. */
+ HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
+ (VDisplayRnd + 2*VMargin);
+
+ /* 9. Find number of lines in vertical blanking */
+ VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
+
+ /* 10. Check if vertical blanking is sufficient */
+ if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
+ VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+
+ /* 11. Find total number of lines in vertical field */
+ Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
+
+ /* 12. Find total number of pixels in a line */
+ Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
+
+ /* Fill in HSync values */
+ Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
+ Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
+
+ /* Fill in VSync values */
+ Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
+ Mode->VSyncEnd = Mode->VSyncStart + VSync;
+ }
+
+ /* 15/13. Find pixel clock frequency (kHz for xf86) */
+ Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
+ Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
+
+ /* 16/14. Find actual Horizontal Frequency (kHz) */
+ Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
+
+ /* 17/15. Find actual Field rate */
+ Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
+ ((float) (Mode->HTotal * Mode->VTotal));
+
+ /* 18/16. Find actual vertical frame frequency */
+ /* ignore - just set the mode flag for interlaced */
+ if (Interlaced)
+ Mode->VTotal *= 2;
+
+ {
+ char Name[256];
+ Name[0] = 0;
+
+ snprintf(Name, 256, "%dx%d", HDisplay, VDisplay);
+
+ Mode->name = xnfalloc(strlen(Name) + 1);
+ memcpy(Mode->name, Name, strlen(Name) + 1);
+ }
+
+ if (Reduced)
+ Mode->Flags |= V_PHSYNC | V_NVSYNC;
+ else
+ Mode->Flags |= V_NHSYNC | V_PVSYNC;
+
+ if (Interlaced)
+ Mode->Flags |= V_INTERLACE;
+
+ return Mode;
+}
diff --git a/driver/xf86-video-intel/src/parser/xf86Optrec.h b/driver/xf86-video-intel/src/parser/xf86Optrec.h
new file mode 100644
index 000000000..183b85720
--- /dev/null
+++ b/driver/xf86-video-intel/src/parser/xf86Optrec.h
@@ -0,0 +1,112 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * 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 X CONSORTIUM 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 Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2001 by The XFree86 Project, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR 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 copyright holder(s)
+ * and 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 copyright holder(s) and author(s).
+ */
+
+
+/*
+ * This file contains the Option Record that is passed between the Parser,
+ * and Module setup procs.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifndef _xf86Optrec_h_
+#define _xf86Optrec_h_
+#include <stdio.h>
+
+/*
+ * all records that need to be linked lists should contain a GenericList as
+ * their first field.
+ */
+typedef struct generic_list_rec
+{
+ void *next;
+}
+GenericListRec, *GenericListPtr, *glp;
+
+/*
+ * All options are stored using this data type.
+ */
+typedef struct
+{
+ GenericListRec list;
+ char *opt_name;
+ char *opt_val;
+ int opt_used;
+ char *opt_comment;
+}
+XF86OptionRec, *XF86OptionPtr;
+
+
+XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val);
+XF86OptionPtr xf86optionListDup(XF86OptionPtr opt);
+void xf86optionListFree(XF86OptionPtr opt);
+char *xf86optionName(XF86OptionPtr opt);
+char *xf86optionValue(XF86OptionPtr opt);
+XF86OptionPtr xf86newOption(char *name, char *value);
+XF86OptionPtr xf86nextOption(XF86OptionPtr list);
+XF86OptionPtr xf86findOption(XF86OptionPtr list, const char *name);
+char *xf86findOptionValue(XF86OptionPtr list, const char *name);
+int xf86findOptionBoolean (XF86OptionPtr, const char *, int);
+XF86OptionPtr xf86optionListCreate(const char **options, int count, int used);
+XF86OptionPtr xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail);
+char *xf86configStrdup (const char *s);
+int xf86nameCompare (const char *s1, const char *s2);
+char *xf86uLongToString(unsigned long i);
+void xf86debugListOptions(XF86OptionPtr);
+XF86OptionPtr xf86parseOption(XF86OptionPtr head);
+void xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs);
+
+
+#endif /* _xf86Optrec_h_ */
diff --git a/driver/xf86-video-intel/src/parser/xf86Parser.h b/driver/xf86-video-intel/src/parser/xf86Parser.h
new file mode 100644
index 000000000..dc30823cc
--- /dev/null
+++ b/driver/xf86-video-intel/src/parser/xf86Parser.h
@@ -0,0 +1,484 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * 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 X CONSORTIUM 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 Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR 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 copyright holder(s)
+ * and 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 copyright holder(s) and author(s).
+ */
+
+
+/*
+ * This file contains the external interfaces for the XFree86 configuration
+ * file parser.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifndef _xf86Parser_h_
+#define _xf86Parser_h_
+
+#include "xf86Optrec.h"
+
+#define HAVE_PARSER_DECLS
+
+typedef struct
+{
+ char *file_logfile;
+ char *file_rgbpath;
+ char *file_modulepath;
+ char *file_inputdevs;
+ char *file_fontpath;
+ char *file_comment;
+}
+XF86ConfFilesRec, *XF86ConfFilesPtr;
+
+/* Values for load_type */
+#define XF86_LOAD_MODULE 0
+#define XF86_LOAD_DRIVER 1
+#define XF86_DISABLE_MODULE 2
+
+typedef struct
+{
+ GenericListRec list;
+ int load_type;
+ char *load_name;
+ XF86OptionPtr load_opt;
+ char *load_comment;
+ int ignore;
+}
+XF86LoadRec, *XF86LoadPtr;
+
+typedef struct
+{
+ XF86LoadPtr mod_load_lst;
+ XF86LoadPtr mod_disable_lst;
+ char *mod_comment;
+}
+XF86ConfModuleRec, *XF86ConfModulePtr;
+
+#define CONF_IMPLICIT_KEYBOARD "Implicit Core Keyboard"
+
+#define CONF_IMPLICIT_POINTER "Implicit Core Pointer"
+
+#define XF86CONF_PHSYNC 0x0001
+#define XF86CONF_NHSYNC 0x0002
+#define XF86CONF_PVSYNC 0x0004
+#define XF86CONF_NVSYNC 0x0008
+#define XF86CONF_INTERLACE 0x0010
+#define XF86CONF_DBLSCAN 0x0020
+#define XF86CONF_CSYNC 0x0040
+#define XF86CONF_PCSYNC 0x0080
+#define XF86CONF_NCSYNC 0x0100
+#define XF86CONF_HSKEW 0x0200 /* hskew provided */
+#define XF86CONF_BCAST 0x0400
+#define XF86CONF_CUSTOM 0x0800 /* timing numbers customized by editor */
+#define XF86CONF_VSCAN 0x1000
+
+typedef struct
+{
+ GenericListRec list;
+ char *ml_identifier;
+ int ml_clock;
+ int ml_hdisplay;
+ int ml_hsyncstart;
+ int ml_hsyncend;
+ int ml_htotal;
+ int ml_vdisplay;
+ int ml_vsyncstart;
+ int ml_vsyncend;
+ int ml_vtotal;
+ int ml_vscan;
+ int ml_flags;
+ int ml_hskew;
+ char *ml_comment;
+}
+XF86ConfModeLineRec, *XF86ConfModeLinePtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *vp_identifier;
+ XF86OptionPtr vp_option_lst;
+ char *vp_comment;
+}
+XF86ConfVideoPortRec, *XF86ConfVideoPortPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *va_identifier;
+ char *va_vendor;
+ char *va_board;
+ char *va_busid;
+ char *va_driver;
+ XF86OptionPtr va_option_lst;
+ XF86ConfVideoPortPtr va_port_lst;
+ char *va_fwdref;
+ char *va_comment;
+}
+XF86ConfVideoAdaptorRec, *XF86ConfVideoAdaptorPtr;
+
+#define CONF_MAX_HSYNC 8
+#define CONF_MAX_VREFRESH 8
+
+typedef struct
+{
+ float hi, lo;
+}
+parser_range;
+
+typedef struct
+{
+ int red, green, blue;
+}
+parser_rgb;
+
+typedef struct
+{
+ GenericListRec list;
+ char *modes_identifier;
+ XF86ConfModeLinePtr mon_modeline_lst;
+ char *modes_comment;
+}
+XF86ConfModesRec, *XF86ConfModesPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *ml_modes_str;
+ XF86ConfModesPtr ml_modes;
+}
+XF86ConfModesLinkRec, *XF86ConfModesLinkPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *mon_identifier;
+ char *mon_vendor;
+ char *mon_modelname;
+ int mon_width; /* in mm */
+ int mon_height; /* in mm */
+ XF86ConfModeLinePtr mon_modeline_lst;
+ int mon_n_hsync;
+ parser_range mon_hsync[CONF_MAX_HSYNC];
+ int mon_n_vrefresh;
+ parser_range mon_vrefresh[CONF_MAX_VREFRESH];
+ float mon_gamma_red;
+ float mon_gamma_green;
+ float mon_gamma_blue;
+ XF86OptionPtr mon_option_lst;
+ XF86ConfModesLinkPtr mon_modes_sect_lst;
+ char *mon_comment;
+}
+XF86ConfMonitorRec, *XF86ConfMonitorPtr;
+
+#define CONF_MAXDACSPEEDS 4
+#define CONF_MAXCLOCKS 128
+
+typedef struct
+{
+ GenericListRec list;
+ char *dev_identifier;
+ char *dev_vendor;
+ char *dev_board;
+ char *dev_chipset;
+ char *dev_busid;
+ char *dev_card;
+ char *dev_driver;
+ char *dev_ramdac;
+ int dev_dacSpeeds[CONF_MAXDACSPEEDS];
+ int dev_videoram;
+ int dev_textclockfreq;
+ unsigned long dev_bios_base;
+ unsigned long dev_mem_base;
+ unsigned long dev_io_base;
+ char *dev_clockchip;
+ int dev_clocks;
+ int dev_clock[CONF_MAXCLOCKS];
+ int dev_chipid;
+ int dev_chiprev;
+ int dev_irq;
+ int dev_screen;
+ XF86OptionPtr dev_option_lst;
+ char *dev_comment;
+}
+XF86ConfDeviceRec, *XF86ConfDevicePtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *mode_name;
+}
+XF86ModeRec, *XF86ModePtr;
+
+typedef struct
+{
+ GenericListRec list;
+ int disp_frameX0;
+ int disp_frameY0;
+ int disp_virtualX;
+ int disp_virtualY;
+ int disp_depth;
+ int disp_bpp;
+ char *disp_visual;
+ parser_rgb disp_weight;
+ parser_rgb disp_black;
+ parser_rgb disp_white;
+ XF86ModePtr disp_mode_lst;
+ XF86OptionPtr disp_option_lst;
+ char *disp_comment;
+}
+XF86ConfDisplayRec, *XF86ConfDisplayPtr;
+
+typedef struct
+{
+ XF86OptionPtr flg_option_lst;
+ char *flg_comment;
+}
+XF86ConfFlagsRec, *XF86ConfFlagsPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *al_adaptor_str;
+ XF86ConfVideoAdaptorPtr al_adaptor;
+}
+XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *scrn_identifier;
+ char *scrn_obso_driver;
+ int scrn_defaultdepth;
+ int scrn_defaultbpp;
+ int scrn_defaultfbbpp;
+ char *scrn_monitor_str;
+ XF86ConfMonitorPtr scrn_monitor;
+ char *scrn_device_str;
+ XF86ConfDevicePtr scrn_device;
+ XF86ConfAdaptorLinkPtr scrn_adaptor_lst;
+ XF86ConfDisplayPtr scrn_display_lst;
+ XF86OptionPtr scrn_option_lst;
+ char *scrn_comment;
+}
+XF86ConfScreenRec, *XF86ConfScreenPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *inp_identifier;
+ char *inp_driver;
+ XF86OptionPtr inp_option_lst;
+ char *inp_comment;
+}
+XF86ConfInputRec, *XF86ConfInputPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ XF86ConfInputPtr iref_inputdev;
+ char *iref_inputdev_str;
+ XF86OptionPtr iref_option_lst;
+}
+XF86ConfInputrefRec, *XF86ConfInputrefPtr;
+
+/* Values for adj_where */
+#define CONF_ADJ_OBSOLETE -1
+#define CONF_ADJ_ABSOLUTE 0
+#define CONF_ADJ_RIGHTOF 1
+#define CONF_ADJ_LEFTOF 2
+#define CONF_ADJ_ABOVE 3
+#define CONF_ADJ_BELOW 4
+#define CONF_ADJ_RELATIVE 5
+
+typedef struct
+{
+ GenericListRec list;
+ int adj_scrnum;
+ XF86ConfScreenPtr adj_screen;
+ char *adj_screen_str;
+ XF86ConfScreenPtr adj_top;
+ char *adj_top_str;
+ XF86ConfScreenPtr adj_bottom;
+ char *adj_bottom_str;
+ XF86ConfScreenPtr adj_left;
+ char *adj_left_str;
+ XF86ConfScreenPtr adj_right;
+ char *adj_right_str;
+ int adj_where;
+ int adj_x;
+ int adj_y;
+ char *adj_refscreen;
+}
+XF86ConfAdjacencyRec, *XF86ConfAdjacencyPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *inactive_device_str;
+ XF86ConfDevicePtr inactive_device;
+}
+XF86ConfInactiveRec, *XF86ConfInactivePtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *lay_identifier;
+ XF86ConfAdjacencyPtr lay_adjacency_lst;
+ XF86ConfInactivePtr lay_inactive_lst;
+ XF86ConfInputrefPtr lay_input_lst;
+ XF86OptionPtr lay_option_lst;
+ char *lay_comment;
+}
+XF86ConfLayoutRec, *XF86ConfLayoutPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *vs_name;
+ char *vs_identifier;
+ XF86OptionPtr vs_option_lst;
+ char *vs_comment;
+}
+XF86ConfVendSubRec, *XF86ConfVendSubPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ char *vnd_identifier;
+ XF86OptionPtr vnd_option_lst;
+ XF86ConfVendSubPtr vnd_sub_lst;
+ char *vnd_comment;
+}
+XF86ConfVendorRec, *XF86ConfVendorPtr;
+
+typedef struct
+{
+ GenericListRec list;
+ int buf_count;
+ int buf_size;
+ char *buf_flags;
+ char *buf_comment;
+}
+XF86ConfBuffersRec, *XF86ConfBuffersPtr;
+
+typedef struct
+{
+ char *dri_group_name;
+ int dri_group;
+ int dri_mode;
+ XF86ConfBuffersPtr dri_buffers_lst;
+ char *dri_comment;
+}
+XF86ConfDRIRec, *XF86ConfDRIPtr;
+
+typedef struct
+{
+ XF86OptionPtr ext_option_lst;
+ char *extensions_comment;
+}
+XF86ConfExtensionsRec, *XF86ConfExtensionsPtr;
+
+typedef struct
+{
+ XF86ConfFilesPtr conf_files;
+ XF86ConfModulePtr conf_modules;
+ XF86ConfFlagsPtr conf_flags;
+ XF86ConfVideoAdaptorPtr conf_videoadaptor_lst;
+ XF86ConfModesPtr conf_modes_lst;
+ XF86ConfMonitorPtr conf_monitor_lst;
+ XF86ConfDevicePtr conf_device_lst;
+ XF86ConfScreenPtr conf_screen_lst;
+ XF86ConfInputPtr conf_input_lst;
+ XF86ConfLayoutPtr conf_layout_lst;
+ XF86ConfVendorPtr conf_vendor_lst;
+ XF86ConfDRIPtr conf_dri;
+ XF86ConfExtensionsPtr conf_extensions;
+ char *conf_comment;
+}
+XF86ConfigRec, *XF86ConfigPtr;
+
+typedef struct
+{
+ int token; /* id of the token */
+ char *name; /* pointer to the LOWERCASED name */
+}
+xf86ConfigSymTabRec, *xf86ConfigSymTabPtr;
+
+/*
+ * prototypes for public functions
+ */
+extern const char *xf86openConfigFile (const char *, const char *,
+ const char *);
+extern void xf86setBuiltinConfig(const char *config[]);
+extern XF86ConfigPtr xf86readConfigFile (void);
+extern void xf86closeConfigFile (void);
+extern void xf86freeConfig (XF86ConfigPtr p);
+extern int xf86writeConfigFile (const char *, XF86ConfigPtr);
+XF86ConfDevicePtr xf86findDevice(const char *ident, XF86ConfDevicePtr p);
+XF86ConfLayoutPtr xf86findLayout(const char *name, XF86ConfLayoutPtr list);
+XF86ConfMonitorPtr xf86findMonitor(const char *ident, XF86ConfMonitorPtr p);
+XF86ConfModesPtr xf86findModes(const char *ident, XF86ConfModesPtr p);
+XF86ConfModeLinePtr xf86findModeLine(const char *ident, XF86ConfModeLinePtr p);
+XF86ConfScreenPtr xf86findScreen(const char *ident, XF86ConfScreenPtr p);
+XF86ConfInputPtr xf86findInput(const char *ident, XF86ConfInputPtr p);
+XF86ConfInputPtr xf86findInputByDriver(const char *driver, XF86ConfInputPtr p);
+XF86ConfVideoAdaptorPtr xf86findVideoAdaptor(const char *ident,
+ XF86ConfVideoAdaptorPtr p);
+
+GenericListPtr xf86addListItem(GenericListPtr head, GenericListPtr c_new);
+int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2);
+
+int xf86pathIsAbsolute(const char *path);
+int xf86pathIsSafe(const char *path);
+char *xf86addComment(char *cur, char *add);
+
+#endif /* _xf86Parser_h_ */
diff --git a/driver/xf86-video-intel/src/reg_dumper/Makefile.am b/driver/xf86-video-intel/src/reg_dumper/Makefile.am
new file mode 100644
index 000000000..aee26d0ed
--- /dev/null
+++ b/driver/xf86-video-intel/src/reg_dumper/Makefile.am
@@ -0,0 +1,12 @@
+noinst_PROGRAMS = intel_reg_dumper
+
+intel_reg_dumper_SOURCES = \
+ main.c \
+ reg_dumper.h \
+ xprintf.c \
+ ../i830_debug.c
+
+intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
+
+intel_reg_dumper_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
+ -I$(srcdir)/.. -DREG_DUMPER
diff --git a/driver/xf86-video-intel/src/reg_dumper/Makefile.in b/driver/xf86-video-intel/src/reg_dumper/Makefile.in
new file mode 100644
index 000000000..28cb5a31e
--- /dev/null
+++ b/driver/xf86-video-intel/src/reg_dumper/Makefile.in
@@ -0,0 +1,522 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = intel_reg_dumper$(EXEEXT)
+subdir = src/reg_dumper
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_intel_reg_dumper_OBJECTS = intel_reg_dumper-main.$(OBJEXT) \
+ intel_reg_dumper-xprintf.$(OBJEXT) \
+ intel_reg_dumper-i830_debug.$(OBJEXT)
+intel_reg_dumper_OBJECTS = $(am_intel_reg_dumper_OBJECTS)
+am__DEPENDENCIES_1 =
+intel_reg_dumper_DEPENDENCIES = $(am__DEPENDENCIES_1)
+intel_reg_dumper_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(intel_reg_dumper_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(intel_reg_dumper_SOURCES)
+DIST_SOURCES = $(intel_reg_dumper_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+intel_reg_dumper_SOURCES = \
+ main.c \
+ reg_dumper.h \
+ xprintf.c \
+ ../i830_debug.c
+
+intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
+intel_reg_dumper_CFLAGS = $(PCIACCESS_CFLAGS) $(WARN_CFLAGS) \
+ -I$(srcdir)/.. -DREG_DUMPER
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/reg_dumper/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/reg_dumper/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+intel_reg_dumper$(EXEEXT): $(intel_reg_dumper_OBJECTS) $(intel_reg_dumper_DEPENDENCIES)
+ @rm -f intel_reg_dumper$(EXEEXT)
+ $(intel_reg_dumper_LINK) $(intel_reg_dumper_OBJECTS) $(intel_reg_dumper_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_reg_dumper-i830_debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_reg_dumper-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_reg_dumper-xprintf.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+intel_reg_dumper-main.o: main.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-main.o -MD -MP -MF $(DEPDIR)/intel_reg_dumper-main.Tpo -c -o intel_reg_dumper-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-main.Tpo $(DEPDIR)/intel_reg_dumper-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='intel_reg_dumper-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+
+intel_reg_dumper-main.obj: main.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-main.obj -MD -MP -MF $(DEPDIR)/intel_reg_dumper-main.Tpo -c -o intel_reg_dumper-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-main.Tpo $(DEPDIR)/intel_reg_dumper-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='intel_reg_dumper-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+
+intel_reg_dumper-xprintf.o: xprintf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-xprintf.o -MD -MP -MF $(DEPDIR)/intel_reg_dumper-xprintf.Tpo -c -o intel_reg_dumper-xprintf.o `test -f 'xprintf.c' || echo '$(srcdir)/'`xprintf.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-xprintf.Tpo $(DEPDIR)/intel_reg_dumper-xprintf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xprintf.c' object='intel_reg_dumper-xprintf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-xprintf.o `test -f 'xprintf.c' || echo '$(srcdir)/'`xprintf.c
+
+intel_reg_dumper-xprintf.obj: xprintf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-xprintf.obj -MD -MP -MF $(DEPDIR)/intel_reg_dumper-xprintf.Tpo -c -o intel_reg_dumper-xprintf.obj `if test -f 'xprintf.c'; then $(CYGPATH_W) 'xprintf.c'; else $(CYGPATH_W) '$(srcdir)/xprintf.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-xprintf.Tpo $(DEPDIR)/intel_reg_dumper-xprintf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xprintf.c' object='intel_reg_dumper-xprintf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-xprintf.obj `if test -f 'xprintf.c'; then $(CYGPATH_W) 'xprintf.c'; else $(CYGPATH_W) '$(srcdir)/xprintf.c'; fi`
+
+intel_reg_dumper-i830_debug.o: ../i830_debug.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-i830_debug.o -MD -MP -MF $(DEPDIR)/intel_reg_dumper-i830_debug.Tpo -c -o intel_reg_dumper-i830_debug.o `test -f '../i830_debug.c' || echo '$(srcdir)/'`../i830_debug.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-i830_debug.Tpo $(DEPDIR)/intel_reg_dumper-i830_debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../i830_debug.c' object='intel_reg_dumper-i830_debug.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-i830_debug.o `test -f '../i830_debug.c' || echo '$(srcdir)/'`../i830_debug.c
+
+intel_reg_dumper-i830_debug.obj: ../i830_debug.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -MT intel_reg_dumper-i830_debug.obj -MD -MP -MF $(DEPDIR)/intel_reg_dumper-i830_debug.Tpo -c -o intel_reg_dumper-i830_debug.obj `if test -f '../i830_debug.c'; then $(CYGPATH_W) '../i830_debug.c'; else $(CYGPATH_W) '$(srcdir)/../i830_debug.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/intel_reg_dumper-i830_debug.Tpo $(DEPDIR)/intel_reg_dumper-i830_debug.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../i830_debug.c' object='intel_reg_dumper-i830_debug.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(intel_reg_dumper_CFLAGS) $(CFLAGS) -c -o intel_reg_dumper-i830_debug.obj `if test -f '../i830_debug.c'; then $(CYGPATH_W) '../i830_debug.c'; else $(CYGPATH_W) '$(srcdir)/../i830_debug.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/reg_dumper/main.c b/driver/xf86-video-intel/src/reg_dumper/main.c
new file mode 100644
index 000000000..5c8ef9ede
--- /dev/null
+++ b/driver/xf86-video-intel/src/reg_dumper/main.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+
+#include "reg_dumper.h"
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev;
+ I830Rec i830;
+ ScrnInfoRec scrn;
+ int err, mmio_bar;
+ void *mmio;
+
+ err = pci_system_init();
+ if (err != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ err = pci_device_probe(dev);
+ if (err != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ i830.PciInfo = &i830.pci_info_rec;
+ i830.PciInfo->chipType = dev->device_id;
+
+ i830.pci_dev = dev;
+
+ mmio_bar = IS_I9XX((&i830)) ? 0 : 1;
+
+ err = pci_device_map_range (dev,
+ dev->regions[mmio_bar].base_addr,
+ dev->regions[mmio_bar].size,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ &mmio);
+
+ if (err != 0) {
+ fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err));
+ exit(1);
+ }
+ i830.mmio = mmio;
+
+ scrn.scrnIndex = 0;
+ scrn.pI830 = &i830;
+
+ i830DumpRegs(&scrn);
+
+ return 0;
+}
+
+void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...)
+{
+ va_list va;
+
+ switch (severity) {
+ case X_INFO:
+ printf("(II): ");
+ break;
+ case X_WARNING:
+ printf("(WW): ");
+ break;
+ case X_ERROR:
+ printf("(EE): ");
+ break;
+ }
+
+ va_start(va, format);
+ vprintf(format, va);
+ va_end(va);
+}
diff --git a/driver/xf86-video-intel/src/reg_dumper/reg_dumper.h b/driver/xf86-video-intel/src/reg_dumper/reg_dumper.h
new file mode 100644
index 000000000..07ddf6fd1
--- /dev/null
+++ b/driver/xf86-video-intel/src/reg_dumper/reg_dumper.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+
+/** @file
+ * This file defines the typedefs and stub structures necessary for us to
+ * use i830_debug.c mostly unmodified.
+ */
+
+typedef uint32_t CARD32;
+typedef char Bool;
+
+#define FALSE 0
+#define TRUE 1
+
+#define X_INFO 0
+#define X_WARNING 1
+#define X_ERROR 2
+
+struct pci_info_rec {
+ uint16_t chipType;
+};
+
+typedef struct _i830 {
+ /* Fields in common with the real pI830 */
+ struct pci_info_rec *PciInfo;
+
+ /* Fields used for setting up reg_dumper */
+ struct pci_device *pci_dev;
+ struct pci_info_rec pci_info_rec;
+ volatile unsigned char *mmio;
+} I830Rec, *I830Ptr;
+
+typedef struct _scrn {
+ /* Fields in common with the real pScrn */
+ int scrnIndex;
+
+ /* Fields used for setting up reg_dumper */
+ I830Ptr pI830;
+} ScrnInfoRec, *ScrnInfoPtr;
+
+#define I830PTR(pScrn) (pScrn->pI830)
+
+#define INREG8(reg) (*(volatile uint8_t *)((pI830)->mmio + (reg)))
+#define INREG16(reg) (*(volatile uint16_t *)((pI830)->mmio + (reg)))
+#define INREG(reg) (*(volatile uint32_t *)((pI830)->mmio + (reg)))
+#define OUTREG8(reg, val) \
+ *(volatile uint8_t *)((pI830)->mmio + (reg)) = (val)
+#define OUTREG16(reg, val) \
+ *(volatile uint16_t *)((pI830)->mmio + (reg)) = (val)
+#define OUTREG(reg, val) \
+ *(volatile uint32_t *)((pI830)->mmio + (reg)) = (val)
+
+#define xalloc malloc
+#define xfree free
+#define ErrorF printf
+
+char *XNFprintf(const char *format, ...);
+void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...);
+void i830DumpRegs(ScrnInfoPtr pScrn);
diff --git a/driver/xf86-video-intel/src/reg_dumper/xprintf.c b/driver/xf86-video-intel/src/reg_dumper/xprintf.c
new file mode 100644
index 000000000..125ae8704
--- /dev/null
+++ b/driver/xf86-video-intel/src/reg_dumper/xprintf.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004 Alexander Gottwald
+ *
+ * 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above 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.
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include "reg_dumper.h"
+
+static char *
+XNFvprintf(const char *format, va_list va)
+{
+ char *ret;
+ int size;
+ va_list va2;
+
+ va_copy(va2, va);
+ size = vsnprintf(NULL, 0, format, va2);
+ va_end(va2);
+
+ ret = (char *)malloc(size + 1);
+ if (ret == NULL)
+ return NULL;
+
+ vsnprintf(ret, size + 1, format, va);
+ ret[size] = 0;
+ return ret;
+}
+
+char *
+XNFprintf(const char *format, ...)
+{
+ char *ret;
+ va_list va;
+ va_start(va, format);
+ ret = XNFvprintf(format, va);
+ va_end(va);
+ return ret;
+}
diff --git a/driver/xf86-video-intel/src/sil164/Makefile.am b/driver/xf86-video-intel/src/sil164/Makefile.am
new file mode 100644
index 000000000..497ee9f7b
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/Makefile.am
@@ -0,0 +1,16 @@
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+sil164_la_LTLIBRARIES = sil164.la
+sil164_la_LDFLAGS = -module -avoid-version
+sil164_ladir = @moduledir@/drivers
+
+sil164_la_SOURCES = \
+ sil164.c \
+ sil164_module.c \
+ sil164.h \
+ sil164_reg.h
diff --git a/driver/xf86-video-intel/src/sil164/Makefile.in b/driver/xf86-video-intel/src/sil164/Makefile.in
new file mode 100644
index 000000000..2ebdc98ce
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/Makefile.in
@@ -0,0 +1,512 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/sil164
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(sil164_ladir)"
+sil164_laLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(sil164_la_LTLIBRARIES)
+sil164_la_LIBADD =
+am_sil164_la_OBJECTS = sil164.lo sil164_module.lo
+sil164_la_OBJECTS = $(am_sil164_la_OBJECTS)
+sil164_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(sil164_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(sil164_la_SOURCES)
+DIST_SOURCES = $(sil164_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+sil164_la_LTLIBRARIES = sil164.la
+sil164_la_LDFLAGS = -module -avoid-version
+sil164_ladir = @moduledir@/drivers
+sil164_la_SOURCES = \
+ sil164.c \
+ sil164_module.c \
+ sil164.h \
+ sil164_reg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/sil164/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/sil164/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-sil164_laLTLIBRARIES: $(sil164_la_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(sil164_ladir)" || $(MKDIR_P) "$(DESTDIR)$(sil164_ladir)"
+ @list='$(sil164_la_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(sil164_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(sil164_ladir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(sil164_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(sil164_ladir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-sil164_laLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sil164_la_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(sil164_ladir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(sil164_ladir)/$$p"; \
+ done
+
+clean-sil164_laLTLIBRARIES:
+ -test -z "$(sil164_la_LTLIBRARIES)" || rm -f $(sil164_la_LTLIBRARIES)
+ @list='$(sil164_la_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+sil164.la: $(sil164_la_OBJECTS) $(sil164_la_DEPENDENCIES)
+ $(sil164_la_LINK) -rpath $(sil164_ladir) $(sil164_la_OBJECTS) $(sil164_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sil164.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sil164_module.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(sil164_ladir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sil164_laLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-sil164_laLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-sil164_laLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-sil164_laLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-sil164_laLTLIBRARIES install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-sil164_laLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/sil164/sil164.c b/driver/xf86-video-intel/src/sil164/sil164.c
new file mode 100644
index 000000000..12fe8e2e5
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/sil164.c
@@ -0,0 +1,249 @@
+/* -*- c-basic-offset: 4 -*- */
+/**************************************************************************
+
+Copyright © 2006 Dave Airlie
+
+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 AUTHOR 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
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "sil164.h"
+#include "sil164_reg.h"
+
+static Bool
+sil164ReadByte(SIL164Ptr sil, int addr, CARD8 *ch)
+{
+ if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
+ if (!sil->quiet) {
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to read from %s Slave %d.\n",
+ sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+sil164WriteByte(SIL164Ptr sil, int addr, CARD8 ch)
+{
+ if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
+ if (!sil->quiet) {
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave %d.\n",
+ sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Silicon Image 164 driver for chip on i2c bus */
+static void *
+sil164_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+ /* this will detect the SIL164 chip on the specified i2c bus */
+ SIL164Ptr sil;
+ unsigned char ch;
+
+ sil = xcalloc(1, sizeof(SIL164Rec));
+ if (sil == NULL)
+ return NULL;
+
+ sil->d.DevName = "SIL164 TMDS Controller";
+ sil->d.SlaveAddr = addr;
+ sil->d.pI2CBus = b;
+ sil->d.StartTimeout = b->StartTimeout;
+ sil->d.BitTimeout = b->BitTimeout;
+ sil->d.AcknTimeout = b->AcknTimeout;
+ sil->d.ByteTimeout = b->ByteTimeout;
+ sil->d.DriverPrivate.ptr = sil;
+ sil->quiet = TRUE;
+
+ if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
+ goto out;
+
+ if (ch!=(SIL164_VID & 0xFF)) {
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+ "sil164 not detected got %d: from %s Slave %d.\n",
+ ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+ goto out;
+ }
+
+ if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
+ goto out;
+
+ if (ch!=(SIL164_DID & 0xFF)) {
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR,
+ "sil164 not detected got %d: from %s Slave %d.\n",
+ ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
+ goto out;
+ }
+ sil->quiet = FALSE;
+
+ if (!xf86I2CDevInit(&(sil->d))) {
+ goto out;
+ }
+
+ return sil;
+
+out:
+ xfree(sil);
+ return NULL;
+}
+
+static xf86OutputStatus
+sil164_detect(I2CDevPtr d)
+{
+ SIL164Ptr sil = SILPTR(d);
+ CARD8 reg9;
+
+ sil164ReadByte(sil, SIL164_REG9, &reg9);
+
+ if (reg9 & SIL164_9_HTPLG)
+ return XF86OutputStatusConnected;
+ else
+ return XF86OutputStatusDisconnected;
+}
+
+static ModeStatus
+sil164_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+ return MODE_OK;
+}
+
+static void
+sil164_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ /* As long as the basics are set up, since we don't have clock dependencies
+ * in the mode setup, we can just leave the registers alone and everything
+ * will work fine.
+ */
+ /* recommended programming sequence from doc */
+ /*sil164WriteByte(sil, 0x08, 0x30);
+ sil164WriteByte(sil, 0x09, 0x00);
+ sil164WriteByte(sil, 0x0a, 0x90);
+ sil164WriteByte(sil, 0x0c, 0x89);
+ sil164WriteByte(sil, 0x08, 0x31);*/
+ /* don't do much */
+ return;
+}
+
+/* set the SIL164 power state */
+static void
+sil164_dpms(I2CDevPtr d, int mode)
+{
+ SIL164Ptr sil = SILPTR(d);
+ int ret;
+ unsigned char ch;
+
+ ret = sil164ReadByte(sil, SIL164_REG8, &ch);
+ if (ret == FALSE)
+ return;
+
+ if (mode == DPMSModeOn)
+ ch |= SIL164_8_PD;
+ else
+ ch &= ~SIL164_8_PD;
+
+ sil164WriteByte(sil, SIL164_REG8, ch);
+
+ return;
+}
+
+static void
+sil164_dump_regs(I2CDevPtr d)
+{
+ SIL164Ptr sil = SILPTR(d);
+ CARD8 val;
+
+ sil164ReadByte(sil, SIL164_FREQ_LO, &val);
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n",
+ val);
+ sil164ReadByte(sil, SIL164_FREQ_HI, &val);
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n",
+ val);
+ sil164ReadByte(sil, SIL164_REG8, &val);
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val);
+ sil164ReadByte(sil, SIL164_REG9, &val);
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val);
+ sil164ReadByte(sil, SIL164_REGC, &val);
+ xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val);
+}
+
+static void
+sil164_save(I2CDevPtr d)
+{
+ SIL164Ptr sil = SILPTR(d);
+
+ if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
+ return;
+
+ if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
+ return;
+
+ if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
+ return;
+
+ return;
+}
+
+static void
+sil164_restore(I2CDevPtr d)
+{
+ SIL164Ptr sil = SILPTR(d);
+
+ /* Restore it powered down initially */
+ sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1);
+
+ sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9);
+ sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc);
+ sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8);
+}
+
+
+I830I2CVidOutputRec SIL164VidOutput = {
+ .init = sil164_init,
+ .detect = sil164_detect,
+ .mode_valid = sil164_mode_valid,
+ .mode_set = sil164_mode_set,
+ .dpms = sil164_dpms,
+ .dump_regs = sil164_dump_regs,
+ .save = sil164_save,
+ .restore = sil164_restore,
+};
diff --git a/driver/xf86-video-intel/src/sil164/sil164.h b/driver/xf86-video-intel/src/sil164/sil164.h
new file mode 100644
index 000000000..9f823d6b1
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/sil164.h
@@ -0,0 +1,31 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+#ifndef SIL164_H
+#define SIL164_H
+
+#define SIL164_ADDR_1 0x38
+
+#endif
diff --git a/driver/xf86-video-intel/src/sil164/sil164_module.c b/driver/xf86-video-intel/src/sil164/sil164_module.c
new file mode 100644
index 000000000..d3bda8196
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/sil164_module.c
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 4 -*- */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(sil164Setup);
+
+static XF86ModuleVersionInfo sil164VersRec = {
+ "sil164",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ { 0,0,0,0 }
+};
+
+_X_EXPORT XF86ModuleData sil164ModuleData = {
+ &sil164VersRec,
+ sil164Setup,
+ NULL
+};
+
+static pointer
+sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ return (pointer)1;
+}
diff --git a/driver/xf86-video-intel/src/sil164/sil164_reg.h b/driver/xf86-video-intel/src/sil164/sil164_reg.h
new file mode 100644
index 000000000..734e55dd1
--- /dev/null
+++ b/driver/xf86-video-intel/src/sil164/sil164_reg.h
@@ -0,0 +1,75 @@
+/* -*- c-basic-offset: 4 -*- */
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+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.
+
+**************************************************************************/
+
+#ifndef SIL164_REG_H
+#define SIL164_REG_H
+
+#define SIL164_VID 0x0001
+#define SIL164_DID 0x0006
+
+#define SIL164_VID_LO 0x00
+#define SIL164_VID_HI 0x01
+#define SIL164_DID_LO 0x02
+#define SIL164_DID_HI 0x03
+#define SIL164_REV 0x04
+#define SIL164_RSVD 0x05
+#define SIL164_FREQ_LO 0x06
+#define SIL164_FREQ_HI 0x07
+
+#define SIL164_REG8 0x08
+#define SIL164_8_VEN (1<<5)
+#define SIL164_8_HEN (1<<4)
+#define SIL164_8_DSEL (1<<3)
+#define SIL164_8_BSEL (1<<2)
+#define SIL164_8_EDGE (1<<1)
+#define SIL164_8_PD (1<<0)
+
+#define SIL164_REG9 0x09
+#define SIL164_9_VLOW (1<<7)
+#define SIL164_9_MSEL_MASK (0x7<<4)
+#define SIL164_9_TSEL (1<<3)
+#define SIL164_9_RSEN (1<<2)
+#define SIL164_9_HTPLG (1<<1)
+#define SIL164_9_MDI (1<<0)
+
+#define SIL164_REGC 0x0c
+
+typedef struct _Sil164SaveRec {
+ CARD8 reg8;
+ CARD8 reg9;
+ CARD8 regc;
+} SIL164SaveRec;
+
+typedef struct {
+ I2CDevRec d;
+ Bool quiet;
+ SIL164SaveRec SavedReg;
+ SIL164SaveRec ModeReg;
+} SIL164Rec, *SIL164Ptr;
+
+#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
+
+#endif
diff --git a/driver/xf86-video-intel/src/tfp410/Makefile.am b/driver/xf86-video-intel/src/tfp410/Makefile.am
new file mode 100644
index 000000000..89a27d034
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/Makefile.am
@@ -0,0 +1,16 @@
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+
+tfp410_la_LTLIBRARIES = tfp410.la
+tfp410_la_LDFLAGS = -module -avoid-version
+tfp410_ladir = @moduledir@/drivers
+
+tfp410_la_SOURCES = \
+ tfp410.c \
+ tfp410_module.c \
+ tfp410.h \
+ tfp410_reg.h
diff --git a/driver/xf86-video-intel/src/tfp410/Makefile.in b/driver/xf86-video-intel/src/tfp410/Makefile.in
new file mode 100644
index 000000000..92b935a4c
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/Makefile.in
@@ -0,0 +1,512 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/tfp410
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(tfp410_ladir)"
+tfp410_laLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(tfp410_la_LTLIBRARIES)
+tfp410_la_LIBADD =
+am_tfp410_la_OBJECTS = tfp410.lo tfp410_module.lo
+tfp410_la_OBJECTS = $(am_tfp410_la_OBJECTS)
+tfp410_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(tfp410_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(tfp410_la_SOURCES)
+DIST_SOURCES = $(tfp410_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRIVER_NAME = @DRIVER_NAME@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_LIBS = @DRI_LIBS@
+DRI_MM_CFLAGS = @DRI_MM_CFLAGS@
+DRI_MM_LIBS = @DRI_MM_LIBS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XMODES_CFLAGS = @XMODES_CFLAGS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_LIBS = @XORG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gen4asm = @gen4asm@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# 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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@
+tfp410_la_LTLIBRARIES = tfp410.la
+tfp410_la_LDFLAGS = -module -avoid-version
+tfp410_ladir = @moduledir@/drivers
+tfp410_la_SOURCES = \
+ tfp410.c \
+ tfp410_module.c \
+ tfp410.h \
+ tfp410_reg.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/tfp410/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/tfp410/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-tfp410_laLTLIBRARIES: $(tfp410_la_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(tfp410_ladir)" || $(MKDIR_P) "$(DESTDIR)$(tfp410_ladir)"
+ @list='$(tfp410_la_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(tfp410_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(tfp410_ladir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(tfp410_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(tfp410_ladir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-tfp410_laLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(tfp410_la_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(tfp410_ladir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(tfp410_ladir)/$$p"; \
+ done
+
+clean-tfp410_laLTLIBRARIES:
+ -test -z "$(tfp410_la_LTLIBRARIES)" || rm -f $(tfp410_la_LTLIBRARIES)
+ @list='$(tfp410_la_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+tfp410.la: $(tfp410_la_OBJECTS) $(tfp410_la_DEPENDENCIES)
+ $(tfp410_la_LINK) -rpath $(tfp410_ladir) $(tfp410_la_OBJECTS) $(tfp410_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfp410.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfp410_module.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(tfp410_ladir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-tfp410_laLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-tfp410_laLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-tfp410_laLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-tfp410_laLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip install-tfp410_laLTLIBRARIES installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-tfp410_laLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/driver/xf86-video-intel/src/tfp410/tfp410.c b/driver/xf86-video-intel/src/tfp410/tfp410.c
new file mode 100644
index 000000000..b79fd2a87
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/tfp410.c
@@ -0,0 +1,271 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Dave Mueller <dave.mueller@gmx.ch>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "compiler.h"
+#include "miscstruct.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "../i2c_vid.h"
+#include "tfp410.h"
+#include "tfp410_reg.h"
+
+static Bool
+tfp410ReadByte(TFP410Ptr tfp, int addr, CARD8 *ch)
+{
+ if (!xf86I2CReadByte(&(tfp->d), addr, ch)) {
+ if (!tfp->quiet) {
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to read from %s Slave %d.\n",
+ tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+tfp410WriteByte(TFP410Ptr tfp, int addr, CARD8 ch)
+{
+ if (!xf86I2CWriteByte(&(tfp->d), addr, ch)) {
+ if (!tfp->quiet) {
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+ "Unable to write to %s Slave %d.\n",
+ tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int
+tfp410GetID(TFP410Ptr tfp, int addr)
+{
+ unsigned char ch1, ch2;
+
+ if (tfp410ReadByte(tfp, addr+0, &ch1) &&
+ tfp410ReadByte(tfp, addr+1, &ch2)) {
+
+ return ((ch2<<8) & 0xFF00) | (ch1 & 0x00FF);
+ }
+ return -1;
+}
+
+/* Ti TFP410 driver for chip on i2c bus */
+static void *
+tfp410_init(I2CBusPtr b, I2CSlaveAddr addr)
+{
+ /* this will detect the tfp410 chip on the specified i2c bus */
+ TFP410Ptr tfp;
+ int id;
+
+ tfp = xcalloc(1, sizeof(TFP410Rec));
+ if (tfp == NULL)
+ return NULL;
+
+ tfp->d.DevName = "TFP410 TMDS Controller";
+ tfp->d.SlaveAddr = addr;
+ tfp->d.pI2CBus = b;
+ tfp->d.StartTimeout = b->StartTimeout;
+ tfp->d.BitTimeout = b->BitTimeout;
+ tfp->d.AcknTimeout = b->AcknTimeout;
+ tfp->d.ByteTimeout = b->ByteTimeout;
+ tfp->d.DriverPrivate.ptr = tfp;
+ tfp->quiet = TRUE;
+
+ if ((id = tfp410GetID(tfp, TFP410_VID_LO)) != TFP410_VID) {
+ if (id != 0xffffffff) {
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+ "tfp410 not detected got VID %X: from %s Slave %d.\n",
+ id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+ }
+ goto out;
+ }
+
+ if ((id = tfp410GetID(tfp, TFP410_DID_LO)) != TFP410_DID) {
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR,
+ "tfp410 not detected got DID %X: from %s Slave %d.\n",
+ id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr);
+ goto out;
+ }
+ tfp->quiet = FALSE;
+
+ if (!xf86I2CDevInit(&(tfp->d))) {
+ goto out;
+ }
+
+ return tfp;
+
+out:
+ xfree(tfp);
+ return NULL;
+}
+
+static xf86OutputStatus
+tfp410_detect(I2CDevPtr d)
+{
+ TFP410Ptr tfp = TFPPTR(d);
+ xf86OutputStatus ret = XF86OutputStatusDisconnected;
+ unsigned char ctl2;
+
+ if (tfp410ReadByte(tfp, TFP410_CTL_2, &ctl2)) {
+ if (ctl2 & TFP410_CTL_2_HTPLG)
+ ret = XF86OutputStatusConnected;
+ else
+ ret = XF86OutputStatusDisconnected;
+ }
+
+ return ret;
+}
+
+static ModeStatus
+tfp410_mode_valid(I2CDevPtr d, DisplayModePtr mode)
+{
+ return MODE_OK;
+}
+
+static void
+tfp410_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ /* As long as the basics are set up, since we don't have clock dependencies
+ * in the mode setup, we can just leave the registers alone and everything
+ * will work fine.
+ */
+ /* don't do much */
+ return;
+}
+
+/* set the tfp410 power state */
+static void
+tfp410_dpms(I2CDevPtr d, int mode)
+{
+ TFP410Ptr tfp = TFPPTR(d);
+ unsigned char ctl1;
+
+ if (!tfp410ReadByte(tfp, TFP410_CTL_1, &ctl1))
+ return;
+
+ if (mode == DPMSModeOn)
+ ctl1 |= TFP410_CTL_1_PD;
+ else
+ ctl1 &= ~TFP410_CTL_1_PD;
+
+ tfp410WriteByte(tfp, TFP410_CTL_1, ctl1);
+}
+
+static void
+tfp410_dump_regs(I2CDevPtr d)
+{
+ TFP410Ptr tfp = TFPPTR(d);
+ CARD8 val, val2;
+
+ tfp410ReadByte(tfp, TFP410_REV, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_REV: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_CTL_1, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_CTL1: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_CTL_2, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_CTL2: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_CTL_3, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_CTL3: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_USERCFG, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_USERCFG: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_DE_DLY, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_DE_DLY: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_DE_CTL, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_DE_CTL: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_DE_TOP, &val);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_DE_TOP: 0x%02X\n", val);
+ tfp410ReadByte(tfp, TFP410_DE_CNT_LO, &val);
+ tfp410ReadByte(tfp, TFP410_DE_CNT_HI, &val2);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
+ tfp410ReadByte(tfp, TFP410_DE_LIN_LO, &val);
+ tfp410ReadByte(tfp, TFP410_DE_LIN_HI, &val2);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
+ tfp410ReadByte(tfp, TFP410_H_RES_LO, &val);
+ tfp410ReadByte(tfp, TFP410_H_RES_HI, &val2);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_H_RES: 0x%02X%02X\n", val2, val);
+ tfp410ReadByte(tfp, TFP410_V_RES_LO, &val);
+ tfp410ReadByte(tfp, TFP410_V_RES_HI, &val2);
+ xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO,
+ "TFP410_V_RES: 0x%02X%02X\n", val2, val);
+}
+
+static void
+tfp410_save(I2CDevPtr d)
+{
+ TFP410Ptr tfp = TFPPTR(d);
+
+ if (!tfp410ReadByte(tfp, TFP410_CTL_1, &tfp->SavedReg.ctl1))
+ return;
+
+ if (!tfp410ReadByte(tfp, TFP410_CTL_2, &tfp->SavedReg.ctl2))
+ return;
+}
+
+static void
+tfp410_restore(I2CDevPtr d)
+{
+ TFP410Ptr tfp = TFPPTR(d);
+
+ /* Restore it powered down initially */
+ tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1 & ~0x1);
+
+ tfp410WriteByte(tfp, TFP410_CTL_2, tfp->SavedReg.ctl2);
+ tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1);
+}
+
+I830I2CVidOutputRec TFP410VidOutput = {
+ .init = tfp410_init,
+ .detect = tfp410_detect,
+ .mode_valid = tfp410_mode_valid,
+ .mode_set = tfp410_mode_set,
+ .dpms = tfp410_dpms,
+ .dump_regs = tfp410_dump_regs,
+ .save = tfp410_save,
+ .restore = tfp410_restore,
+};
diff --git a/driver/xf86-video-intel/src/tfp410/tfp410.h b/driver/xf86-video-intel/src/tfp410/tfp410.h
new file mode 100644
index 000000000..fb3f45244
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/tfp410.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Dave Mueller <dave.mueller@gmx.ch>
+ *
+ */
+
+#ifndef TFP410_H
+#define TFP410_H
+
+#define TFP410_ADDR_1 0x38
+
+#endif
diff --git a/driver/xf86-video-intel/src/tfp410/tfp410_module.c b/driver/xf86-video-intel/src/tfp410/tfp410_module.c
new file mode 100644
index 000000000..c05b21a68
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/tfp410_module.c
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 4 -*- */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(tfp410Setup);
+
+static XF86ModuleVersionInfo tfp410VersRec = {
+ "tfp410",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ { 0,0,0,0 }
+};
+
+_X_EXPORT XF86ModuleData tfp410ModuleData = {
+ &tfp410VersRec,
+ tfp410Setup,
+ NULL
+};
+
+static pointer
+tfp410Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ return (pointer)1;
+}
diff --git a/driver/xf86-video-intel/src/tfp410/tfp410_reg.h b/driver/xf86-video-intel/src/tfp410/tfp410_reg.h
new file mode 100644
index 000000000..c555b9779
--- /dev/null
+++ b/driver/xf86-video-intel/src/tfp410/tfp410_reg.h
@@ -0,0 +1,106 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Dave Mueller
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Dave Mueller <dave.mueller@gmx.ch>
+ *
+ */
+
+#ifndef TFP410_REG_H
+#define TFP410_REG_H
+
+/* register definitions according to the TFP410 data sheet */
+#define TFP410_VID 0x014C
+#define TFP410_DID 0x0410
+
+#define TFP410_VID_LO 0x00
+#define TFP410_VID_HI 0x01
+#define TFP410_DID_LO 0x02
+#define TFP410_DID_HI 0x03
+#define TFP410_REV 0x04
+
+#define TFP410_CTL_1 0x08
+#define TFP410_CTL_1_TDIS (1<<6)
+#define TFP410_CTL_1_VEN (1<<5)
+#define TFP410_CTL_1_HEN (1<<4)
+#define TFP410_CTL_1_DSEL (1<<3)
+#define TFP410_CTL_1_BSEL (1<<2)
+#define TFP410_CTL_1_EDGE (1<<1)
+#define TFP410_CTL_1_PD (1<<0)
+
+#define TFP410_CTL_2 0x09
+#define TFP410_CTL_2_VLOW (1<<7)
+#define TFP410_CTL_2_MSEL_MASK (0x7<<4)
+#define TFP410_CTL_2_MSEL (1<<4)
+#define TFP410_CTL_2_TSEL (1<<3)
+#define TFP410_CTL_2_RSEN (1<<2)
+#define TFP410_CTL_2_HTPLG (1<<1)
+#define TFP410_CTL_2_MDI (1<<0)
+
+#define TFP410_CTL_3 0x0A
+#define TFP410_CTL_3_DK_MASK (0x7<<5)
+#define TFP410_CTL_3_DK (1<<5)
+#define TFP410_CTL_3_DKEN (1<<4)
+#define TFP410_CTL_3_CTL_MASK (0x7<<1)
+#define TFP410_CTL_3_CTL (1<<1)
+
+#define TFP410_USERCFG 0x0B
+
+#define TFP410_DE_DLY 0x32
+
+#define TFP410_DE_CTL 0x33
+#define TFP410_DE_CTL_DEGEN (1<<6)
+#define TFP410_DE_CTL_VSPOL (1<<5)
+#define TFP410_DE_CTL_HSPOL (1<<4)
+#define TFP410_DE_CTL_DEDLY8 (1<<0)
+
+#define TFP410_DE_TOP 0x34
+
+#define TFP410_DE_CNT_LO 0x36
+#define TFP410_DE_CNT_HI 0x37
+
+#define TFP410_DE_LIN_LO 0x38
+#define TFP410_DE_LIN_HI 0x39
+
+#define TFP410_H_RES_LO 0x3A
+#define TFP410_H_RES_HI 0x3B
+
+#define TFP410_V_RES_LO 0x3C
+#define TFP410_V_RES_HI 0x3D
+
+typedef struct _TFP410SaveRec {
+ CARD8 ctl1;
+ CARD8 ctl2;
+} TFP410SaveRec;
+
+typedef struct {
+ I2CDevRec d;
+ Bool quiet;
+
+ TFP410SaveRec SavedReg;
+ TFP410SaveRec ModeReg;
+} TFP410Rec, *TFP410Ptr;
+
+#define TFPPTR(d) ((TFP410Ptr)(d->DriverPrivate.ptr))
+
+#endif