diff -Naur src/tvo_set/Imakefile.orig src/tvo_set/Imakefile
--- src/tvo_set/Imakefile.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/tvo_set/Imakefile	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,37 @@
+XCOMM $Id: Imakefile,v 1.1.2.1 2004/01/27 22:55:40 fulivi Exp $
+XCOMM
+XCOMM Imakefile for tvo_set utility
+XCOMM
+XCOMM Copyright (C) 2004 Federico Ulivi
+XCOMM
+XCOMM This program is free software; you can redistribute it and/or modify
+XCOMM it under the terms of the GNU General Public License as published by
+XCOMM the Free Software Foundation; either version 2 of the License, or
+XCOMM (at your option) any later version.
+XCOMM
+XCOMM This program is distributed in the hope that it will be useful,
+XCOMM but WITHOUT ANY WARRANTY; without even the implied warranty of
+XCOMM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+XCOMM GNU General Public License for more details.
+XCOMM
+XCOMM You should have received a copy of the GNU General Public License
+XCOMM along with this program; if not, write to the Free Software
+XCOMM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+XCOMM
+XCOMM AUTHORS: F.Ulivi
+XCOMM NOTES:
+XCOMM $Log: Imakefile,v $
+XCOMM Revision 1.1.2.1  2004/01/27 22:55:40  fulivi
+XCOMM Initial release
+XCOMM
+XCOMM Revision 1.1.2.1  2004/01/25 23:07:31  fede
+XCOMM *** empty log message ***
+XCOMM
+XCOMM
+
+        DEPLIBS = $(DEPXVLIB) $(DEPXLIB)
+LOCAL_LIBRARIES = $(XVLIB) $(XLIB)
+           SRCS = tvo_set.c
+           OBJS = tvo_set.o
+
+ComplexProgramTargetNoMan(tvo_set)
diff -Naur src/Makefile.in.orig src/Makefile.in
--- src/Makefile.in.orig	2006-08-24 17:08:45.000000000 -0700
+++ src/Makefile.in	2006-09-08 03:29:40.000000000 -0700
@@ -81,6 +81,7 @@
 am__installdirs = "$(DESTDIR)$(ati_drv_ladir)" \
 	"$(DESTDIR)$(atimisc_drv_ladir)" "$(DESTDIR)$(r128_drv_ladir)" \
 	"$(DESTDIR)$(radeon_drv_ladir)" \
+	"$(DESTDIR)$(theater_out_drv_ladir)" \
 	"$(DESTDIR)$(theatre200_drv_ladir)" \
 	"$(DESTDIR)$(theatre_detect_drv_ladir)" \
 	"$(DESTDIR)$(theatre_drv_ladir)"
@@ -88,11 +89,13 @@
 atimisc_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 r128_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 radeon_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
+theater_out_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 theatre200_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 theatre_detect_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 theatre_drv_laLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(ati_drv_la_LTLIBRARIES) $(atimisc_drv_la_LTLIBRARIES) \
 	$(r128_drv_la_LTLIBRARIES) $(radeon_drv_la_LTLIBRARIES) \
+	$(theater_out_drv_la_LTLIBRARIES) \
 	$(theatre200_drv_la_LTLIBRARIES) \
 	$(theatre_detect_drv_la_LTLIBRARIES) \
 	$(theatre_drv_la_LTLIBRARIES)
@@ -148,6 +151,10 @@
 	radeon_video.lo radeon_bios.lo radeon_mm_i2c.lo radeon_vip.lo \
 	radeon_misc.lo $(am__objects_7) $(am__objects_8)
 radeon_drv_la_OBJECTS = $(am_radeon_drv_la_OBJECTS)
+theatre_out_drv_la_LIBADD =
+am_theater_out_drv_la_OBJECTS = theater_out_drv_la-theater_out.lo \
+	theater_out_drv_la-theater_out_module.lo
+theater_out_drv_la_OBJECTS = $(am_theater_out_drv_la_OBJECTS)
 theatre200_drv_la_LIBADD =
 am_theatre200_drv_la_OBJECTS = theatre200_drv_la-theatre200.lo \
 	theatre200_drv_la-theatre200_module.lo
@@ -172,13 +179,14 @@
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
 SOURCES = $(ati_drv_la_SOURCES) $(atimisc_drv_la_SOURCES) \
 	$(r128_drv_la_SOURCES) $(radeon_drv_la_SOURCES) \
-	$(theatre200_drv_la_SOURCES) $(theatre_detect_drv_la_SOURCES) \
-	$(theatre_drv_la_SOURCES)
+	$(theater_out_drv_la_SOURCES) $(theatre200_drv_la_SOURES) \
+	$(theatre_detect_drv_la_SOURCES) $(theatre_drv_la_SOURCES)
 DIST_SOURCES = $(am__ati_drv_la_SOURCES_DIST) \
 	$(am__atimisc_drv_la_SOURCES_DIST) \
 	$(am__r128_drv_la_SOURCES_DIST) \
-	$(am__radeon_drv_la_SOURCES_DIST) $(theatre200_drv_la_SOURCES) \
-	$(theatre_detect_drv_la_SOURCES) $(theatre_drv_la_SOURCES)
+	$(am__radeon_drv_la_SOURCES_DIST) $(theater_out_drv_la_SOURCES) \
+	$(theatre200_drv_la_SOURCES) $(theatre_detect_drv_la_SOURCES) \
+	$(theatre_drv_la_SOURCES)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -379,6 +387,15 @@
 theatre_drv_la_SOURCES = \
 	theatre.c theatre_module.c
 
+theater_out_drv_la_LTLIBRARIES = theater_out_drv.la
+theater_out_drv_la_LDFLAGS = -module -avoid-version
+theater_out_drv_ladir = @moduledir@/multimedia
+theater_out_drv_la_CFLAGS = \
+	$(AM_CFLAGS) -DMICROC_DIR=\"$(theater_out_drv_ladir)\"
+
+theater_out_drv_la_SOURCES = \
+	theater_out.c theater_out_module.c
+
 theatre200_drv_la_LTLIBRARIES = theatre200_drv.la
 theatre200_drv_la_LDFLAGS = -module -avoid-version
 theatre200_drv_ladir = @moduledir@/multimedia
@@ -474,6 +491,7 @@
 	radeon_sarea.h \
 	radeon_version.h \
 	radeon_video.h \
+	theater_out.h \
 	theatre200.h \
 	theatre_detect.h \
 	theatre.h \
@@ -621,6 +639,33 @@
 	  echo "rm -f \"$${dir}/so_locations\""; \
 	  rm -f "$${dir}/so_locations"; \
 	done
+install-theater_out_drv_laLTLIBRARIES: $(theater_out_drv_la_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(theater_out_drv_ladir)" || $(mkdir_p) "$(DESTDIR)$(theater_out_drv_ladir)"
+	@list='$(theater_out_drv_la_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) --mode=install $(theater_out_drv_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(theater_out_drv_ladir)/$$f'"; \
+	    $(LIBTOOL) --mode=install $(theater_out_drv_laLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(theater_out_drv_ladir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-theater_out_drv_laLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@set -x; list='$(theater_out_drv_la_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(theater_out_drv_ladir)/$$p'"; \
+	  $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(theater_out_drv_ladir)/$$p"; \
+	done
+
+clean-theater_out_drv_laLTLIBRARIES:
+	-test -z "$(theater_out_drv_la_LTLIBRARIES)" || rm -f $(theater_out_drv_la_LTLIBRARIES)
+	@list='$(theater_out_drv_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
 install-theatre200_drv_laLTLIBRARIES: $(theatre200_drv_la_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	test -z "$(theatre200_drv_ladir)" || $(mkdir_p) "$(DESTDIR)$(theatre200_drv_ladir)"
@@ -710,6 +755,8 @@
 	$(LINK) -rpath $(r128_drv_ladir) $(r128_drv_la_LDFLAGS) $(r128_drv_la_OBJECTS) $(r128_drv_la_LIBADD) $(LIBS)
 radeon_drv.la: $(radeon_drv_la_OBJECTS) $(radeon_drv_la_DEPENDENCIES) 
 	$(LINK) -rpath $(radeon_drv_ladir) $(radeon_drv_la_LDFLAGS) $(radeon_drv_la_OBJECTS) $(radeon_drv_la_LIBADD) $(LIBS)
+theater_out_drv.la: $(theater_out_drv_la_OBJECTS) $(theater_out_drv_la_DEPENDENCIES) 
+	$(LINK) -rpath $(theater_out_drv_ladir) $(theater_out_drv_la_LDFLAGS) $(theater_out_drv_la_OBJECTS) $(theater_out_drv_la_LIBADD) $(LIBS)
 theatre200_drv.la: $(theatre200_drv_la_OBJECTS) $(theatre200_drv_la_DEPENDENCIES) 
 	$(LINK) -rpath $(theatre200_drv_ladir) $(theatre200_drv_la_LDFLAGS) $(theatre200_drv_la_OBJECTS) $(theatre200_drv_la_LIBADD) $(LIBS)
 theatre_detect_drv.la: $(theatre_detect_drv_la_OBJECTS) $(theatre_detect_drv_la_DEPENDENCIES) 
@@ -791,6 +838,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_probe.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_video.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_vip.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theater_out_drv_la-theater_out.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theater_out_drv_la-theater_out_module.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theatre.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theatre200_drv_la-theatre200.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theatre200_drv_la-theatre200_module.Plo@am__quote@
@@ -819,6 +868,20 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
 
+theater_out_drv_la-theater_out.lo: theater_out.c
+@am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(theater_out_drv_la_CFLAGS) $(CFLAGS) -MT theater_out_drv_la-theater_out.lo -MD -MP -MF "$(DEPDIR)/theater_out_drv_la-theater_out.Tpo" -c -o theater_out_drv_la-theater_out.lo `test -f 'theater_out.c' || echo '$(srcdir)/'`theater_out.c; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/theater_out_drv_la-theater_out.Tpo" "$(DEPDIR)/theater_out_drv_la-theater_out.Plo"; else rm -f "$(DEPDIR)/theater_out_drv_la-theater_out.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='theater_out.c' object='theater_out_drv_la-theater_out.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(theater_out_drv_la_CFLAGS) $(CFLAGS) -c -o theater_out_drv_la-theater_out.lo `test -f 'theater_out.c' || echo '$(srcdir)/'`theater_out.c
+
+theater_out_drv_la-theater_out_module.lo: theater_out_module.c
+@am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(theater_out_drv_la_CFLAGS) $(CFLAGS) -MT theater_out_drv_la-theater_out_module.lo -MD -MP -MF "$(DEPDIR)/theater_out_drv_la-theater_out_module.Tpo" -c -o theater_out_drv_la-theater_out_module.lo `test -f 'theater_out_module.c' || echo '$(srcdir)/'`theater_out_module.c; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/theater_out_drv_la-theater_out_module.Tpo" "$(DEPDIR)/theater_out_drv_la-theater_out_module.Plo"; else rm -f "$(DEPDIR)/theater_out_drv_la-theater_out_module.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='theater_out_module.c' object='theater_out_drv_la-theater_out_module.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(theater_out_drv_la_CFLAGS) $(CFLAGS) -c -o theater_out_drv_la-theater_out_module.lo `test -f 'theater_out_module.c' || echo '$(srcdir)/'`theater_out_module.c
+
 theatre200_drv_la-theatre200.lo: theatre200.c
 @am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(theatre200_drv_la_CFLAGS) $(CFLAGS) -MT theatre200_drv_la-theatre200.lo -MD -MP -MF "$(DEPDIR)/theatre200_drv_la-theatre200.Tpo" -c -o theatre200_drv_la-theatre200.lo `test -f 'theatre200.c' || echo '$(srcdir)/'`theatre200.c; \
 @am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/theatre200_drv_la-theatre200.Tpo" "$(DEPDIR)/theatre200_drv_la-theatre200.Plo"; else rm -f "$(DEPDIR)/theatre200_drv_la-theatre200.Tpo"; exit 1; fi
@@ -922,7 +985,7 @@
 check: check-am
 all-am: Makefile $(LTLIBRARIES)
 installdirs:
-	for dir in "$(DESTDIR)$(ati_drv_ladir)" "$(DESTDIR)$(atimisc_drv_ladir)" "$(DESTDIR)$(r128_drv_ladir)" "$(DESTDIR)$(radeon_drv_ladir)" "$(DESTDIR)$(theatre200_drv_ladir)" "$(DESTDIR)$(theatre_detect_drv_ladir)" "$(DESTDIR)$(theatre_drv_ladir)"; do \
+	for dir in "$(DESTDIR)$(ati_drv_ladir)" "$(DESTDIR)$(atimisc_drv_ladir)" "$(DESTDIR)$(r128_drv_ladir)" "$(DESTDIR)$(radeon_drv_ladir)" "$(DESTDIR)$(theater_out_drv_ladir)" "$(DESTDIR)$(theatre200_drv_ladir)" "$(DESTDIR)$(theatre_detect_drv_ladir)" "$(DESTDIR)$(theatre_drv_ladir)"; do \
 	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
 	done
 install: install-am
@@ -954,6 +1017,7 @@
 clean-am: clean-ati_drv_laLTLIBRARIES clean-atimisc_drv_laLTLIBRARIES \
 	clean-generic clean-libtool clean-r128_drv_laLTLIBRARIES \
 	clean-radeon_drv_laLTLIBRARIES \
+	clean-theater_out_drv_laLTLIBRARIES \
 	clean-theatre200_drv_laLTLIBRARIES \
 	clean-theatre_detect_drv_laLTLIBRARIES \
 	clean-theatre_drv_laLTLIBRARIES mostlyclean-am
@@ -978,6 +1042,7 @@
 	install-atimisc_drv_laLTLIBRARIES \
 	install-r128_drv_laLTLIBRARIES \
 	install-radeon_drv_laLTLIBRARIES \
+	install-theater_out_drv_laLTLIBRARIES \
 	install-theatre200_drv_laLTLIBRARIES \
 	install-theatre_detect_drv_laLTLIBRARIES \
 	install-theatre_drv_laLTLIBRARIES
@@ -1012,6 +1077,7 @@
 	uninstall-atimisc_drv_laLTLIBRARIES uninstall-info-am \
 	uninstall-r128_drv_laLTLIBRARIES \
 	uninstall-radeon_drv_laLTLIBRARIES \
+	uninstall-theater_out_drv_laLTLIBRARIES \
 	uninstall-theatre200_drv_laLTLIBRARIES \
 	uninstall-theatre_detect_drv_laLTLIBRARIES \
 	uninstall-theatre_drv_laLTLIBRARIES
@@ -1020,6 +1086,7 @@
 	clean-ati_drv_laLTLIBRARIES clean-atimisc_drv_laLTLIBRARIES \
 	clean-generic clean-libtool clean-r128_drv_laLTLIBRARIES \
 	clean-radeon_drv_laLTLIBRARIES \
+	clean-theater_out_drv_laLTLIBRARIES \
 	clean-theatre200_drv_laLTLIBRARIES \
 	clean-theatre_detect_drv_laLTLIBRARIES \
 	clean-theatre_drv_laLTLIBRARIES ctags distclean \
@@ -1030,6 +1097,7 @@
 	install-exec install-exec-am install-info install-info-am \
 	install-man install-r128_drv_laLTLIBRARIES \
 	install-radeon_drv_laLTLIBRARIES install-strip \
+	install-theater_out_drv_laLTLIBRARIES \
 	install-theatre200_drv_laLTLIBRARIES \
 	install-theatre_detect_drv_laLTLIBRARIES \
 	install-theatre_drv_laLTLIBRARIES installcheck installcheck-am \
@@ -1040,6 +1108,7 @@
 	uninstall-atimisc_drv_laLTLIBRARIES uninstall-info-am \
 	uninstall-r128_drv_laLTLIBRARIES \
 	uninstall-radeon_drv_laLTLIBRARIES \
+	uninstall-theater_out_drv_laLTLIBRARIES \
 	uninstall-theatre200_drv_laLTLIBRARIES \
 	uninstall-theatre_detect_drv_laLTLIBRARIES \
 	uninstall-theatre_drv_laLTLIBRARIES
diff -Naur src/Makefile.am.orig src/Makefile.am
--- src/Makefile.am.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/Makefile.am	2006-09-06 00:32:03.000000000 +0200
@@ -96,6 +96,15 @@
 theatre_drv_la_SOURCES = \
 	theatre.c theatre_module.c
 
+theater_out_drv_la_LTLIBRARIES = theater_out_drv.la
+theater_out_drv_la_LDFLAGS = -module -avoid-version
+theater_out_drv_ladir = @moduledir@/multimedia
+theater_out_drv_la_CFLAGS = \
+        $(AM_CFLAGS) -DMICROC_DIR=\"$(theater_out_drv_ladir)\"
+theater_out_drv_la_SOURCES = \
+        theater_out.c theater_out_module.c
+
+
 theatre200_drv_la_LTLIBRARIES = theatre200_drv.la
 theatre200_drv_la_LDFLAGS = -module -avoid-version
 theatre200_drv_ladir = @moduledir@/multimedia
@@ -190,6 +199,7 @@
 	radeon_sarea.h \
 	radeon_version.h \
 	radeon_video.h \
+	theater_out.h \
 	theatre200.h \
 	theatre_detect.h \
 	theatre.h \
diff -Naur src/README.tvout.orig src/README.tvout
--- src/README.tvout.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/README.tvout	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,236 @@
+
+      *******************************************************
+      **  XFree86 driver for TV output on ATI Radeon cards **
+      *******************************************************
+
+Copyright (c) 2003-2004, by Federico Ulivi <fulivi@lycos.com>
+Released under the GNU General Public License, version 2.
+
+1. About this driver
+--------------------
+
+This driver was developped as a part of ati.2 project. Its purpose
+is to enable the TV output of ATI Radeon cards when running the
+XFree86 graphical environment.
+
+2. Status of the driver
+-----------------------
+
+The driver is in early development stage. It currently works with
+those cards having a Rage Theater chip for TV output or with cards
+having the tv module inside the Radeon chip (ERT, Embedded Rage
+Theater, is my name for the latter).
+The driver was successfully tested on these cards:
+- Radeon 7200 / European model (TV out hw: RT 100)
+- Radeon 9000 (TV out hw: ERT)
+- Radeon 9200SE (TV out hw: ERT)
+- Radeon 7000 (TV out hw: ERT)
+
+3. Making it work
+-----------------
+
+The driver is always loaded by the Radeon driver. If you need to
+disable this auto-loading mechanism, just set the "TVOutput" option
+(see below) to "NOLOAD".
+In principle the driver should coexist with video grabbing functions,
+especially on those AIW cards where TV output is done by ERT
+inside Radeon.
+
+Principle of operation of the driver is very simple. Driver enables 
+tv output whenever the current screen resolution and tv standard match
+one of a set of pre-computed combinations. In all other cases tv output
+is simply kept disabled.
+The driver currently works in the so-called "clone" mode only. This means
+that the image on the TV screen is exactly the same as the one on the
+monitor.
+
+The driver is enabled by adding a "TVOutput" line in the "device"
+section of XF86Config-4 file (this file is usually located in /etc/X11
+directory). Syntax of this option is very simple:
+
+Section "Device"
+ ..
+ ..
+ Option "TVOuput" "<name of tv standard>"
+EndSection
+
+Names of recognized TV standards are:
+"NTSC"
+"NTSC-J"
+"PAL"
+"PAL-CN"
+"PAL-M"
+"PAL-N"
+"PAL-60"
+
+If "TVOutput" is not present or its value is invalid, TV output is kept disabled.
+
+In the current version of the driver these are the recognized TV standard &
+resolution combinations:
+
+PAL	800x600
+NTSC	800x600
+
+More combinations will be added in future releases.
+
+4. XV Interface
+---------------
+
+The driver has an external interface through some Xv attributes. 
+You can change the value of these attributes by using the tvo_set utility
+(see below).
+
+XV_TVO_STANDARD		Settable/Gettable
+	This is the tv standard in use by the driver. Its value is encoded
+	according to this table:
+
+	0	NTSC
+	1	PAL
+	2	PAL-M
+	3	PAL-60
+	4	NTSC-J
+	5	PAL-CN
+	6	PAL-N
+	7	Keep TV off
+
+XV_TVO_MODE_COMPAT	Gettable
+	This attribute is set to 1 whenever TV output is enabled, i.e.
+	whenever the current resolution & tv standard combination is 
+	recognized by the driver. 
+
+XV_TVO_HPOS	Settable/Gettable
+	Horizontal position, valid range is [-5..+5]. 
+	This attribute defines the horizontal position of the TV image.
+	Higher values shift the image to the right, lower values to the left.
+
+XV_TVO_VPOS	Settable/Gettable
+	Vertical position, valid range is [-5..+5]. 
+	This attribute defines the vertical position of the TV image.
+	Higher values shift the image upward, lower values downward.
+
+XV_TVO_HSIZE	Settable/Gettable
+	Horizontal size, valid range is [-5..+5]. 
+	This attribute is used to set the horizontal size of TV image.
+	Higher values enlarge TV lines, lower values reduce them.
+
+Default value for XV_TVO_HPOS, XV_TVO_VPOS & XV_TVO_HSIZE just after
+X Window start is 0.
+
+You might ask where a vertical size attribute has gone. It was not included
+because it's quite hard to implement (it requires changing many timings in
+the CRTC). For the moment I'm not planning to work on it.
+
+5. tvo_set utility
+------------------
+
+tvo_set is a command line utility that is used to change TV output
+attributes while X Window is running. It offers a somewhat more
+friendly interface to XV_TVO_* attributes.
+
+This is how to compile tvo_set:
+- cd to tvo_set directory
+- xmkmf
+- make
+- make install
+Last step should place the executable (tvo_set) in /usr/X11R6/bin.
+
+This is the invocation syntax:
+tvo_set [-display host:dpy] [<cmd> <attribute> [<value>]]
+
+tvo_set is not case sensitive for <cmd>, <attribute> & <value>
+fields.
+When no <cmd> is given, tvo_set just dumps the current state of
+TV attributes.
+
+Recognized commands:
+set <attribute> <value>   Set <attribute> to <value>
+inc <attribute>           Increment <attribute> by 1
+dec <attribute>           Decrement <attribute> by 1
+zero <attribute>          Set <attribute> to 0
+
+Recognized values for <attribute> field:
+hpos	Horizontal position
+vpos	Vertical position
+hsize	Horizontal size
+std	TV Standard
+
+When setting "std" attribute, both the numeric value and the name of the 
+standard are valid, see following table.
+
+Table of TV standards:
+0	NTSC
+1	PAL
+2	PAL-M
+3	PAL-60
+4	NTSC-J
+5	PAL-CN
+6	PAL-N
+7	OFF
+
+Examples:
+"tvo_set set std ntsc"
+	Set standard to NTSC
+
+"tvo_set set std off"
+	Turn off TV output
+
+"tvo_set set hsize 5"
+	Set hsize to 5
+
+"tvo_set inc hpos"
+	Shift image a bit to the right (increment hpos by 1)
+
+"tvo_set zero vpos"
+	Restore default value for vpos
+
+
+6. WARNING
+----------
+
+It's important that you are aware of the fact that, when TV output is active,
+the monitor is driven at the same vertical refresh frequency as that of the
+TV output. This means 50 or 60 Hz according to the standard you're using.
+NO CHECK IS DONE IN THE DRIVER ABOUT THE CAPABILITY OF THE MONITOR TO
+SUSTAIN THESE FREQUENCIES. You should look up in the monitor manual
+and check that 50/60 Hz is within the limits. IT IS POTENTIALLY HARMFUL
+TO THE MONITOR TO BE DRIVEN AT A FREQUENCY OUTSIDE ITS OPERATING RANGE.
+
+Note, however, that most monitors should accept a 60 Hz vertical frequency,
+since this is used in standard VGA modes. You should really check for 50 Hz 
+compatibility if you are going to use any related standard (PAL mostly).
+ATI manuals recommend checking for 50 Hz compatibility (they take
+60 Hz for granted).
+
+One last thing: I did no testing on cards having DVI/LCD outputs
+so I'm not sure about the driver behaviour with this kind of displays. 
+Be warned.
+
+6. Credits
+----------
+
+Vladimir Dergachev	For leading the GATOS project, for all the good
+			advices he gave me about dealing with ATI and for
+			all his precious technical hints.
+
+ATI external developer office
+			For providing me the Rage Theater documentation.
+
+7.  Revision history
+--------------------
+
+
+2003-09-23
+==========
+
+Initial release
+
+2003-11-26
+==========
+
+Support for ERT added
+
+2004-01-27
+==========
+
+Support for sizing/positioning of TV image added
+
diff -Naur src/radeon.h.orig src/radeon.h
--- src/radeon.h.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon.h	2006-09-06 00:35:12.000000000 +0200
@@ -66,6 +66,11 @@
 #include "xf86xv.h"
 
 #include "radeon_probe.h"
+
+//20060402
+#include "radeon_version.h"
+#include "generic_bus.h"
+
 				/* DRI support */
 #ifdef XF86DRI
 #define _XF86DRI_SERVER_
@@ -130,6 +135,7 @@
     OPTION_RAGE_THEATRE_COMPOSITE_PORT,
     OPTION_RAGE_THEATRE_SVIDEO_PORT,
     OPTION_TUNER_TYPE,
+    OPTION_TV_OUTPUT,
     OPTION_RAGE_THEATRE_MICROC_PATH,
     OPTION_RAGE_THEATRE_MICROC_TYPE,
 #endif
@@ -292,6 +298,9 @@
     unsigned          ppll_div_3;
     CARD32            htotal_cntl;
 
+//2006021904
+    CARD32            vclk_ecp_cntl;
+
 				/* Computed values for PLL2 */
     CARD32            dot_clock_freq_2;
     CARD32            pll_output_freq_2;
@@ -710,6 +719,10 @@
 	char*			RageTheatreMicrocPath;
 	char*			RageTheatreMicrocType;
     Bool               MM_TABLE_valid;
+//2006021905
+    GENERIC_BUS_Ptr   VIP;
+//2006021908
+    struct TheaterOut *theaterOut;
     struct {
     	CARD8 table_revision;
 	CARD8 table_size;
@@ -806,6 +819,9 @@
     info->fifo_slots -= entries;					\
 } while (0)
 
+//2006021908
+#include "theater_out.h"
+
 extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn);
 extern void        RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
 extern void        RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
@@ -816,6 +832,14 @@
 extern void        RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y,
 				       int clone);
 
+//2006021919
+extern void        RADEONTheaterOutSetStandard(ScrnInfoPtr, TVStd);
+extern TVStd       RADEONTheaterOutGetStandard(ScrnInfoPtr);
+extern Bool        RADEONTheaterOutGetCompatMode(ScrnInfoPtr);
+extern void        RADEONTheaterOutSetAttr(ScrnInfoPtr, TheaterOutAttr, int);
+extern int         RADEONTheaterOutGetAttr(ScrnInfoPtr, TheaterOutAttr);
+extern void        RADEONTheaterOutGetAttrLimits(ScrnInfoPtr, TheaterOutAttr, int *, int *);
+
 extern void        RADEONEngineReset(ScrnInfoPtr pScrn);
 extern void        RADEONEngineFlush(ScrnInfoPtr pScrn);
 extern void        RADEONEngineRestore(ScrnInfoPtr pScrn);
@@ -847,7 +871,12 @@
 
 extern int         RADEONMinBits(int val);
 
-extern void        RADEONInitVideo(ScreenPtr pScreen);
+//2006021919
+extern GENERIC_BUS_Ptr RADEONAllocateVIP(ScrnInfoPtr pScrn);
+
+//2006021911
+//extern void        RADEONInitVideo(ScreenPtr pScreen);
+extern void        RADEONInitVideo(ScreenPtr pScreen , GENERIC_BUS_Ptr VIP , Bool loadTheatre);
 extern void        RADEONResetVideo(ScrnInfoPtr pScrn);
 extern void        R300CGWorkaround(ScrnInfoPtr pScrn);
 
diff -Naur src/radeon_driver.c.orig src/radeon_driver.c
--- src/radeon_driver.c.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon_driver.c	2006-09-06 00:32:03.000000000 +0200
@@ -76,6 +76,8 @@
 #include "radeon_macros.h"
 #include "radeon_probe.h"
 #include "radeon_version.h"
+//2006021906
+#include "theater_out.h"
 #include "radeon_mergedfb.h"
 
 #ifdef XF86DRI
@@ -196,6 +198,8 @@
     { OPTION_RAGE_THEATRE_COMPOSITE_PORT, "RageTheatreCompositePort", OPTV_INTEGER, {0}, FALSE },
     { OPTION_RAGE_THEATRE_SVIDEO_PORT,    "RageTheatreSVideoPort",    OPTV_INTEGER, {0}, FALSE },
     { OPTION_TUNER_TYPE,                  "TunerType",                OPTV_INTEGER, {0}, FALSE },
+//2006021906
+    { OPTION_TV_OUTPUT,                   "TVOutput",                 OPTV_ANYSTR,  {0}, FALSE },
 	{ OPTION_RAGE_THEATRE_MICROC_PATH,	"RageTheatreMicrocPath",	 OPTV_STRING, {0}, FALSE },
 	{ OPTION_RAGE_THEATRE_MICROC_TYPE, 	"RageTheatreMicrocType",	 OPTV_STRING, {0}, FALSE },
 #endif
@@ -5700,6 +5704,63 @@
 
     info->PaletteSavedOnVT = FALSE;
 
+//2006021909
+    RADEONTRACE(("Allocating VIP interface"));
+    info->VIP = RADEONAllocateVIP(pScrn);
+
+/*
+if (info->VIP != NULL)
+{
+	RADEONTRACE(("\n061:NOT NULL\n"));
+}
+else
+{
+	RADEONTRACE(("\n062:NULL\n"));
+}
+*/
+
+//2006021907
+if ((s = xf86GetOptValString(info->Options , OPTION_TV_OUTPUT)) != NULL && xf86NameCmp(s , "NOLOAD") != 0)
+{
+	//RADEONTRACE(("TVOUT OPTION ON\n"));
+	RADEONTRACE(("TVOutput opt = %s\n" , s));
+	if(!xf86LoadSubModule(pScrn , "theater_out"))
+	{
+		RADEONTRACE(("Failed to find theater_out module\n"));
+	        xf86DrvMsg(pScrn->scrnIndex , X_ERROR , "Unable to load TV output module\n");
+        	info->theaterOut = NULL;
+	}
+	else
+	{
+		RADEONTRACE(("Found theater_out module\n"));
+		xf86LoaderReqSymbols(THEATER_OUT_SYMBOLS , NULL);
+//		RADEONTRACE(("071:OK\n"));
+
+		info->theaterOut = xf86_detectTheaterOut(pScrn , FALSE,info->VIP);
+//		RADEONTRACE(("072:OK\n"));
+		if (info->theaterOut != NULL)
+		{
+//			RADEONTRACE(("072:NOT NULL\n"));
+			xf86_initTheaterOut(info->theaterOut , s);
+//			RADEONTRACE(("073:start init\n"));
+		}
+		else
+		{
+			RADEONTRACE(("TheaterOut is NULL!!\n"));
+		}
+
+	}
+
+}
+else
+{
+//	RADEONTRACE(("NO TVOUT OPTION\n"));
+}
+
+
+
+
+
     RADEONSave(pScrn);
 
     if ((!info->IsSecondary) && info->IsMobility) {
@@ -6147,7 +6208,9 @@
 
     /* Init Xv */
     RADEONTRACE(("Initializing Xv\n"));
-    RADEONInitVideo(pScreen);
+//2006021911
+//    RADEONInitVideo(pScreen);
+RADEONInitVideo(pScreen , info->VIP , TRUE);
 
     if(info->MergedFB)
 	/* need this here to fix up sarea values */
@@ -6387,7 +6450,12 @@
     OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom);
     OUTREG(RADEON_OV0_SCALE_CNTL,     restore->ov0_scale_cntl);
     OUTREG(RADEON_SUBPIC_CNTL,        restore->subpic_cntl);
-    OUTREG(RADEON_VIPH_CONTROL,       restore->viph_control);
+//2006021914
+//    OUTREG(RADEON_VIPH_CONTROL,       restore->viph_control);
+  /*
+   * fulivi: removed. It messes the VIP access up
+   */
+
     OUTREG(RADEON_I2C_CNTL_1,         restore->i2c_cntl_1);
     OUTREG(RADEON_GEN_INT_CNTL,       restore->gen_int_cntl);
     OUTREG(RADEON_CAP0_TRIG_CNTL,     restore->cap0_trig_cntl);
@@ -6473,6 +6541,8 @@
     OUTREG(RADEON_CRTC_OFFSET,          restore->crtc_offset);
     OUTREG(RADEON_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
     OUTREG(RADEON_CRTC_PITCH,           restore->crtc_pitch);
+//2006021914
+OUTREG(RADEON_DISP_OUTPUT_CNTL,     restore->disp_output_cntl);
     OUTREG(RADEON_DISP_MERGE_CNTL,      restore->disp_merge_cntl);
     OUTREG(RADEON_CRTC_MORE_CNTL,       restore->crtc_more_cntl);
 
@@ -6655,12 +6725,49 @@
 	    ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
 }
 
+//2006021914
+static
+CARD8
+RADEONComputePLLGain(
+                    CARD16 reference_freq,
+                    CARD16 ref_div,
+                    CARD16 fb_div
+                    )
+{
+  unsigned vcoFreq;
+
+  vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div;
+
+  /*
+   * This is orribly crude: the VCO frequency range is divided into
+   * 3 parts, each part having a fixed PLL gain value.
+   */
+  if (vcoFreq >= 30000)
+    /*
+     * [300..max] MHz : 7
+     */
+    return 7;
+  else if (vcoFreq >= 18000)
+    /*
+     * [180..300) MHz : 4
+     */
+    return 4;
+  else
+    /*
+     * [0..180) MHz : 1
+     */
+    return 1;
+}
+
+
 /* Write PLL registers */
 static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
 				      RADEONSavePtr restore)
 {
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
+//2006021914
+CARD8 pllGain;
 
     if (info->IsMobility) {
         /* A temporal workaround for the occational blanking on certain laptop panels.
@@ -6683,15 +6790,28 @@
     OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
 	    RADEON_VCLK_SRC_SEL_CPUCLK,
 	    ~(RADEON_VCLK_SRC_SEL_MASK));
+//2006021914
+    pllGain = RADEONComputePLLGain(info->pll.reference_freq,
+                                  restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+                                  restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK);
+
+
 
     OUTPLLP(pScrn,
 	    RADEON_PPLL_CNTL,
 	    RADEON_PPLL_RESET
 	    | RADEON_PPLL_ATOMIC_UPDATE_EN
-	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN,
+//2006021914
+//	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN,
+	    | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+	    | ((CARD32)pllGain << RADEON_PPLL_PVG_SHIFT),
 	    ~(RADEON_PPLL_RESET
 	      | RADEON_PPLL_ATOMIC_UPDATE_EN
-	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+//2006021914
+//	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+	      | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+	      | RADEON_PPLL_PVG_MASK));
+
 
     OUTREGP(RADEON_CLOCK_CNTL_INDEX,
 	    RADEON_PLL_DIV_SEL,
@@ -6751,9 +6871,14 @@
 
     usleep(50000); /* Let the clock to lock */
 
-    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
-	    RADEON_VCLK_SRC_SEL_PPLLCLK,
-	    ~(RADEON_VCLK_SRC_SEL_MASK));
+//2006021914
+//    OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
+//	    RADEON_VCLK_SRC_SEL_PPLLCLK,
+//	    ~(RADEON_VCLK_SRC_SEL_MASK));
+    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL , restore->vclk_ecp_cntl);
+
+    RADEONTRACE(("VCLK_ECP_CNTL = %08X\n" , restore->vclk_ecp_cntl));
+
 }
 
 
@@ -7176,6 +7301,8 @@
     save->crtc_offset          = INREG(RADEON_CRTC_OFFSET);
     save->crtc_offset_cntl     = INREG(RADEON_CRTC_OFFSET_CNTL);
     save->crtc_pitch           = INREG(RADEON_CRTC_PITCH);
+//2006021915
+save->disp_output_cntl     = INREG(RADEON_DISP_OUTPUT_CNTL);
     save->disp_merge_cntl      = INREG(RADEON_DISP_MERGE_CNTL);
     save->crtc_more_cntl       = INREG(RADEON_CRTC_MORE_CNTL);
 
@@ -7245,6 +7372,8 @@
     save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV);
     save->ppll_div_3   = INPLL(pScrn, RADEON_PPLL_DIV_3);
     save->htotal_cntl  = INPLL(pScrn, RADEON_HTOTAL_CNTL);
+    //2006021915
+    save->vclk_ecp_cntl= INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
 
     RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08lx\n",
 		 save->ppll_ref_div,
@@ -7254,6 +7383,8 @@
 		 save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK,
 		 save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
 		 (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16));
+//2006021915
+RADEONTRACE(("Read VCLK_ECP_CNTL = %08x\n" , save->vclk_ecp_cntl));
 }
 
 /* Read PLL registers */
@@ -7362,6 +7493,16 @@
     RADEONSaveMode(pScrn, save);
     if (!info->IsSecondary)
 	RADEONSaveSurfaces(pScrn, save);
+
+//2006021915
+    /*
+     * Save initial RT state
+     */
+    if (info->theaterOut != NULL)
+	{
+//	RADEONTRACE(("2006021915\n"));
+      xf86_theaterOutSave(info->theaterOut , pScrn);
+	}
 }
 
 /* Restore the original (text) mode */
@@ -7404,6 +7545,14 @@
     if (!info->IsSecondary)
 	RADEONRestoreSurfaces(pScrn, restore);
 
+    /*
+     * Restore RT state
+     */
+    if (info->theaterOut != NULL)
+	{
+//	RADEONTRACE(("2006021915-2\n"));
+      xf86_theaterOutRestore(info->theaterOut , pScrn);
+	}
 #if 0
     /* Temp fix to "solve" VT switch problems.  When switching VTs on
      * some systems, the console can either hang or the fonts can be
@@ -8154,7 +8303,12 @@
 	save->crtc2_gen_cntl      = (RADEON_CRTC2_EN | (format << 8));
 	save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid;
 	save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid;
-	save->fp2_gen_cntl        = info->SavedReg.fp2_gen_cntl | RADEON_FP2_ON;
+//2006021915	
+//	save->fp2_gen_cntl        = info->SavedReg.fp2_gen_cntl | RADEON_FP2_ON;
+	save->fp2_gen_cntl        = info->SavedReg.fp2_gen_cntl
+				    | RADEON_FP2_SRC_SEL_CRTC2
+				    | RADEON_FP2_ON;
+
 	save->fp2_gen_cntl	  &= ~(RADEON_FP2_BLANK_EN);
 
 	if ((info->ChipFamily == CHIP_FAMILY_R200) ||
@@ -8500,15 +8654,20 @@
 				     pll->reference_freq);
     save->post_div       = post_div->divider;
 
+    //2006021915
+    /*
     RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n",
 	       save->dot_clock_freq,
 	       save->pll_output_freq,
 	       save->feedback_div,
 	       save->post_div));
+    */
 
     save->ppll_ref_div   = pll->reference_div;
     save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
     save->htotal_cntl    = 0;
+    //2006021915
+    save->vclk_ecp_cntl  = (save->vclk_ecp_cntl & ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
 }
 
 /* Define PLL2 registers for requested video mode */
@@ -8561,12 +8720,14 @@
 				       * save->pll_output_freq_2,
 				       pll->reference_freq);
     save->post_div_2       = post_div->divider;
-
+    //2006021915
+    /*
     RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n",
 	       save->dot_clock_freq_2,
 	       save->pll_output_freq_2,
 	       save->feedback_div_2,
 	       save->post_div_2));
+    */
 
     save->p2pll_ref_div    = pll->reference_div;
     save->p2pll_div_0      = (save->feedback_div_2 |
@@ -8641,6 +8802,13 @@
 #endif
 
     info->Flags = mode->Flags;
+//2006021916
+    /*
+     * Some registers are initialized from text mode state
+     */
+    save->disp_output_cntl = RADEONPTR(pScrn)->SavedReg.disp_output_cntl;
+    save->vclk_ecp_cntl    = RADEONPTR(pScrn)->SavedReg.vclk_ecp_cntl;
+
 
     RADEONInitMemMapRegisters(pScrn, save, info);
     RADEONInitCommonRegisters(save, info);
@@ -8709,9 +8877,34 @@
 
     if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE;
 
+//2006021917
+    /*
+     * Define RT state
+     */
+    if (info->theaterOut != NULL)
+      {
+//	RADEONTRACE(("2006021917\n"));
+        Bool res = xf86_theaterOutInit(info->theaterOut , mode , &info->ModeReg);
+         RADEONTRACE(("theaterOutInit returns %d\n" , res));
+      }
+
+
     pScrn->vtSema = TRUE;
     RADEONBlank(pScrn);
     RADEONRestoreMode(pScrn, &info->ModeReg);
+
+//2006021918
+
+    /*
+     * Set RT to new mode
+     */
+    if (info->theaterOut != NULL)
+	{
+//	RADEONTRACE(("2006021918\n"));
+      xf86_theaterOutRestoreMode(info->theaterOut , pScrn);
+	}
+
+
     RADEONUnblank(pScrn);
 
     info->CurrentLayout.mode = mode;
@@ -10103,3 +10296,103 @@
     pScrn->FreeScreen    = RADEONFreeScreen;
     pScrn->ValidMode     = RADEONValidMode;
 }
+
+
+/*
+ * fulivi: interface functions between RADEONSet/GetPortAttribute (in radeon_video.c) and
+ * theater_out module.
+ */
+static
+void
+RADEONRedoSwitchMode(
+                     ScrnInfoPtr pScrn
+                     )
+{
+  int scrnIndex = pScrn->scrnIndex;
+
+  /*
+   * It seems that last parameter (flags) is not used
+   */
+  RADEONSwitchMode(scrnIndex , pScrn->currentMode , 0);
+}
+
+void
+RADEONTheaterOutSetStandard(
+                            ScrnInfoPtr pScrn,
+                            TVStd std
+                            )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  RADEONTRACE(("RADEONTheaterOutSetStandard std = %d" , std));
+
+  if (info->theaterOut != NULL && xf86_theaterOutSetStandard(info->theaterOut , std))
+    RADEONRedoSwitchMode(pScrn);
+}
+
+TVStd
+RADEONTheaterOutGetStandard(
+                            ScrnInfoPtr pScrn
+                            )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  if (info->theaterOut != NULL)
+    return xf86_theaterOutGetStandard(info->theaterOut);
+  else
+    return TV_STD_KEEP_OFF;
+}
+
+Bool
+RADEONTheaterOutGetCompatMode(
+                              ScrnInfoPtr pScrn
+                              )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  if (info->theaterOut != NULL)
+    return xf86_theaterOutGetCompatMode(info->theaterOut);
+  else
+    return FALSE;
+}
+
+void
+RADEONTheaterOutSetAttr(
+                        ScrnInfoPtr pScrn,
+                        TheaterOutAttr attr,
+                        int value
+                        )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  if (info->theaterOut != NULL)
+    xf86_theaterOutSetAttr(info->theaterOut , attr , value);
+}
+
+int
+RADEONTheaterOutGetAttr(
+                        ScrnInfoPtr pScrn,
+                        TheaterOutAttr attr
+                        )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  if (info->theaterOut != NULL)
+    return xf86_theaterOutGetAttr(info->theaterOut , attr);
+  else
+    return 0;
+}
+
+void
+RADEONTheaterOutGetAttrLimits(
+                              ScrnInfoPtr pScrn,
+                              TheaterOutAttr attr,
+                              int *maxValue,
+                              int *minValue
+                              )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+
+  if (info->theaterOut != NULL)
+    xf86_theaterOutGetAttrLimits(info->theaterOut , attr , maxValue , minValue);
+}
diff -Naur src/radeon_reg.h.orig src/radeon_reg.h
--- src/radeon_reg.h.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon_reg.h	2006-09-06 00:32:03.000000000 +0200
@@ -1223,6 +1223,10 @@
 #       define RADEON_PPLL_SLEEP                (1 <<  1)
 #       define RADEON_PPLL_ATOMIC_UPDATE_EN     (1 << 16)
 #       define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+//2006021914
+#       define RADEON_PPLL_PVG_MASK             (7 << 11)
+#       define RADEON_PPLL_PVG_SHIFT            11
+
 #       define RADEON_PPLL_ATOMIC_UPDATE_VSYNC  (1 << 18)
 #define RADEON_PPLL_DIV_0                   0x0004 /* PLL */
 #define RADEON_PPLL_DIV_1                   0x0005 /* PLL */
diff -Naur src/radeon_video.c.orig src/radeon_video.c
--- src/radeon_video.c.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon_video.c	2006-09-06 00:32:03.000000000 +0200
@@ -75,7 +75,9 @@
 
 static void RADEONInitOffscreenImages(ScreenPtr);
 
-static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
+//2006021912
+//static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
+static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr , GENERIC_BUS_Ptr , Bool);
 static int  RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 static int  RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
 static void RADEONStopVideo(ScrnInfoPtr, pointer, Bool);
@@ -117,6 +119,24 @@
 	     
 static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode;
 
+//2006021920
+static Atom xvTvoStandard , xvTvoModeCompat;
+
+typedef struct
+{
+  char *name;
+  TheaterOutAttr attr;
+  Atom atom;
+} TVOAttr;
+
+static
+TVOAttr theaterOutAttrs[] =
+{
+  {"XV_TVO_HPOS" , THEATER_OUT_HPOS , 0 },
+  {"XV_TVO_VPOS" , THEATER_OUT_VPOS , 0 },
+  {"XV_TVO_HSIZE" , THEATER_OUT_HSIZE , 0 }
+};
+#define N_TVO_ATTRS (sizeof(theaterOutAttrs) / sizeof(theaterOutAttrs[ 0 ]))
 
 #define GET_PORT_PRIVATE(pScrn) \
    (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
@@ -135,14 +155,18 @@
 }
 #endif /* USE_EXA */
 
-void RADEONInitVideo(ScreenPtr pScreen)
+//2006021911
+//void RADEONInitVideo(ScreenPtr pScreen)
+void RADEONInitVideo(ScreenPtr pScreen , GENERIC_BUS_Ptr VIP , Bool loadTheatre)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
     XF86VideoAdaptorPtr newAdaptor = NULL;
     int num_adaptors;
 
-    newAdaptor = RADEONSetupImageVideo(pScreen);
+//2006021911
+//    newAdaptor = RADEONSetupImageVideo(pScreen);
+newAdaptor = RADEONSetupImageVideo(pScreen , VIP , loadTheatre);
     RADEONInitOffscreenImages(pScreen);
     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
 
@@ -235,7 +259,9 @@
 
 #endif
 
-#define NUM_ATTRIBUTES 22
+//2006021920
+//#define NUM_ATTRIBUTES 22
+#define NUM_ATTRIBUTES 22+5
 #define NUM_DEC_ATTRIBUTES (NUM_ATTRIBUTES+12)
 
 static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] =
@@ -251,6 +277,14 @@
    {XvSettable | XvGettable,     0,  255, "XV_OVERLAY_ALPHA"},
    {XvSettable | XvGettable,     0,  255, "XV_GRAPHICS_ALPHA"},
    {XvSettable | XvGettable,     0,    1, "XV_ALPHA_MODE"},
+
+//2006021920
+   {XvSettable | XvGettable,     0, TV_STD_N_STANDARDS-1, "XV_TVO_STANDARD"},
+   {             XvGettable,     0,   ~0,   "XV_TVO_MODE_COMPAT"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_TVO_HPOS"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_TVO_VPOS"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_TVO_HSIZE"},
+
    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
@@ -1056,6 +1090,8 @@
     RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
     char tmp[200];
 
+//2006021920
+unsigned i;
     /* this function is called from ScreenInit. pScreen is used 
        by XAA internally, but not valid until ScreenInit finishs.
     */
@@ -1069,6 +1105,19 @@
     xvLocationID = MAKE_ATOM("XV_LOCATION_ID");
     xvDumpStatus = MAKE_ATOM("XV_DUMP_STATUS");
  
+//2006021920
+    xvTvoStandard = MAKE_ATOM("XV_TVO_STANDARD");
+    xvTvoModeCompat = MAKE_ATOM("XV_TVO_MODE_COMPAT");
+
+    for (i = 0; i < N_TVO_ATTRS; i++)
+    {
+        char *name;
+        name = theaterOutAttrs[ i ].name;
+        theaterOutAttrs[ i ].atom = MakeAtom(name, strlen(name), TRUE);
+
+        RADEONTRACE(("RADEONResetVideo,name=%s,atom=%d\n",name,theaterOutAttrs[ i ].atom));
+    }
+
     xvBrightness   = MAKE_ATOM("XV_BRIGHTNESS");
     xvSaturation   = MAKE_ATOM("XV_SATURATION");
     xvColor        = MAKE_ATOM("XV_COLOR");
@@ -1270,7 +1319,9 @@
 }
 
 static XF86VideoAdaptorPtr
-RADEONAllocAdaptor(ScrnInfoPtr pScrn)
+RADEONAllocAdaptor(ScrnInfoPtr pScrn, GENERIC_BUS_Ptr VIP)
+//2006021913
+//RADEONAllocAdaptor(ScrnInfoPtr pScrn)
 {
     XF86VideoAdaptorPtr adapt;
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1396,7 +1447,10 @@
     #endif
 
     /* Initialize VIP bus */
-    RADEONVIP_init(pScrn, pPriv);
+//2006021921
+//    RADEONVIP_init(pScrn, pPriv);
+pPriv->VIP = VIP;
+
     info->adaptor = adapt;
 
 	if(!xf86LoadSubModule(pScrn,"theatre_detect")) 
@@ -1478,13 +1532,19 @@
 }
 
 static XF86VideoAdaptorPtr
-RADEONSetupImageVideo(ScreenPtr pScreen)
+RADEONSetupImageVideo(ScreenPtr pScreen , GENERIC_BUS_Ptr VIP , Bool loadTheatre)
+//2006021912
+//RADEONSetupImageVideo(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONPortPrivPtr pPriv;
     XF86VideoAdaptorPtr adapt;
+//2006021912
+unsigned i;
 
-    if(!(adapt = RADEONAllocAdaptor(pScrn)))
+//2006021912
+//    if(!(adapt = RADEONAllocAdaptor(pScrn)))
+if(!(adapt = RADEONAllocAdaptor(pScrn, VIP)))
 	return NULL;
 
     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
@@ -1510,6 +1570,27 @@
     adapt->PutImage = RADEONPutImage;
     adapt->QueryImageAttributes = RADEONQueryImageAttributes;
 
+//2006021921
+    /*
+     * fulivi: set limits of theater_out attributes
+     */
+    for (i = 0; i < N_TVO_ATTRS; i++)
+      {
+        int maxValue;
+        int minValue;
+        unsigned j;
+
+        RADEONTheaterOutGetAttrLimits(pScrn , theaterOutAttrs[ i ].attr , &maxValue , &minValue);
+
+        for (j = 0; i < NUM_DEC_ATTRIBUTES; j++)
+          if (strcmp(theaterOutAttrs[ i ].name , Attributes[ j ].name) == 0)
+            {
+              Attributes[ j ].min_value = minValue;
+              Attributes[ j ].max_value = maxValue;
+              break;
+            }
+      }
+
     pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr);
     REGION_NULL(pScreen, &(pPriv->clip));
 
@@ -1812,8 +1893,27 @@
 		RADEON_TDA9885_SetEncoding(pPriv);
 		}
    }
-   else 
-	return BadMatch;
+//2006021922
+//   else 
+//	return BadMatch;
+   else if (attribute == xvTvoStandard)
+      {
+        value = ClipValue(value , 0 , TV_STD_N_STANDARDS-1);
+        RADEONTheaterOutSetStandard(pScrn , (TVStd)value);
+      }
+    else
+      {
+        unsigned i;
+
+	for (i = 0; i < N_TVO_ATTRS; i++)
+        if (theaterOutAttrs[ i ].atom == attribute)
+          {
+            RADEONTheaterOutSetAttr(pScrn , theaterOutAttrs[ i ].attr , value);
+            break;
+          }
+      if (i == N_TVO_ATTRS)
+ 	return BadMatch;
+    }
 
     if (setTransform)
     {
@@ -1917,8 +2017,26 @@
         *value = pPriv->instance_id;
     else if(attribute == xvAdjustment)
   	*value = pPriv->adjustment;
-    else
-	return BadMatch;
+    else if(attribute == xvTvoStandard) // 2006021923
+        *value = (INT32)RADEONTheaterOutGetStandard(pScrn);
+    else if(attribute == xvTvoModeCompat)
+        *value = (INT32)RADEONTheaterOutGetCompatMode(pScrn);
+    else {
+        unsigned i;
+
+        for (i = 0; i < N_TVO_ATTRS; i++) {
+            if (theaterOutAttrs[ i ].atom == attribute) {
+                *value = (INT32)RADEONTheaterOutGetAttr(pScrn , theaterOutAttrs[ i].attr);
+                break;
+            }
+        }
+        if (i == N_TVO_ATTRS)
+	    return BadMatch;
+    }
+
+//2006021923
+//    else
+//	return BadMatch;
 
     return Success;
 }
diff -Naur src/radeon_video.h.orig src/radeon_video.h
--- src/radeon_video.h.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon_video.h	2006-09-06 00:32:03.000000000 +0200
@@ -47,6 +47,8 @@
    GENERIC_BUS_Ptr  VIP;
    TheatrePtr       theatre;   
 
+/*    TheaterOutPtr theaterOut; */
+
    Bool          video_stream_active;
    int           encoding;
    CARD32        frequency;
diff -Naur src/radeon_vip.c.orig src/radeon_vip.c
--- src/radeon_vip.c.orig	2006-09-06 00:36:13.000000000 +0200
+++ src/radeon_vip.c	2006-09-06 00:32:03.000000000 +0200
@@ -342,6 +342,7 @@
 
 void RADEONVIP_init(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
+/*
     pPriv->VIP=xcalloc(1,sizeof(GENERIC_BUS_Rec));
     pPriv->VIP->scrnIndex=pScrn->scrnIndex;
     pPriv->VIP->DriverPrivate.ptr=pPriv;
@@ -350,6 +351,32 @@
     pPriv->VIP->write=RADEONVIP_write;
     pPriv->VIP->fifo_read=RADEONVIP_fifo_read;
     pPriv->VIP->fifo_write=RADEONVIP_fifo_write;
-   
     RADEONVIP_reset(pScrn, pPriv);
+*/
+pPriv->VIP = RADEONAllocateVIP(pScrn);
 }
+
+/*
+ * fulivi: This new function was created because I needed VIP access from radeon_driver module
+ * (where port private data doesn't exist)
+ */
+GENERIC_BUS_Ptr
+RADEONAllocateVIP(
+               ScrnInfoPtr pScrn
+               )
+{
+  GENERIC_BUS_Ptr VIP=NULL;
+
+  VIP = xcalloc(1 , sizeof(GENERIC_BUS_Rec));
+  VIP->DriverPrivate.ptr = NULL;        /* Nobody seems to use this */
+  VIP->scrnIndex = pScrn->scrnIndex;
+  VIP->ioctl = RADEONVIP_ioctl;
+  VIP->read = RADEONVIP_read;
+  VIP->write = RADEONVIP_write;
+  VIP->fifo_read=RADEONVIP_fifo_read;
+  VIP->fifo_write=RADEONVIP_fifo_write;
+
+  RADEONVIP_reset(pScrn,NULL);
+
+  return VIP;
+ }
diff -Naur src/theater_out.c.orig src/theater_out.c
--- src/theater_out.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/theater_out.c	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,2830 @@
+/*********************************************************************
+ *
+ * $Id: theater_out.c,v 1.1.2.3 2004/01/27 22:50:35 fulivi Exp $
+ *
+ * Main file for tv output handling of ATI Rage Theater chip 
+ *
+ * Copyright (C) 2003 Federico Ulivi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * AUTHORS: F.Ulivi
+ * NOTES:
+ * $Log: theater_out.c,v $
+ * Revision 1.1.2.3  2004/01/27 22:50:35  fulivi
+ * Support for positioning/sizing of image added
+ *
+ * Revision 1.1.1.1.2.12  2004/01/18 22:59:29  fede
+ * hSize handling added
+ * Functions for get/setting h/v pos/size replaced by
+ * theaterOutSetAttr/theaterOutGetAttr/theaterOutGetAttrLimits
+ *
+ * Revision 1.1.1.1.2.11  2004/01/11 21:29:04  fede
+ * Fixes in H/V position handling
+ *
+ * Revision 1.1.1.1.2.10  2004/01/05 00:08:16  fede
+ * Functions for setting H/V position added
+ * Functions for setting/getting on/off attribute removed
+ *
+ * Revision 1.1.2.2  2003/11/26 19:50:10  fulivi
+ * Support for ERT added
+ *
+ * Revision 1.1.1.1.2.9  2003/11/25 20:46:44  fede
+ * "enabled" state removed
+ * Handling of disabled tv output fixed
+ *
+ * Revision 1.1.1.1.2.8  2003/11/23 00:47:28  fede
+ * Major cleanup of #define names
+ *
+ * Revision 1.1.1.1.2.7  2003/11/17 22:26:12  fede
+ * Support for tv standards added
+ * Support for NTSC added
+ *
+ * Revision 1.1.1.1.2.6  2003/10/14 18:40:34  fede
+ * Autodetection of ERT moved to front
+ * Some minor cleanups
+ *
+ * Revision 1.1.1.1.2.5  2003/10/11 12:29:50  fede
+ * Support for ERT added
+ *
+ * Revision 1.1  2003/09/28 21:42:37  fulivi
+ * Theater_out module added
+ *
+ * Revision 1.1.1.1.2.4  2003/09/28 15:11:57  fede
+ * Some minor aesthetic changes
+ *
+ * Revision 1.1.1.1.2.2  2003/08/31 13:35:58  fede
+ * Adapted for XFree86
+ *
+ * Revision 1.1.1.1.2.1  2003/08/09 23:20:46  fede
+ * Switched to memory mapped IO
+ * Some magic numbers turned into named constants
+ *
+ * Revision 1.1.1.1  2003/07/24 15:37:27  fede
+ * Initial version
+ *
+ *
+ *********************************************************************/
+
+#include "xf86.h"
+#include "generic_bus.h"
+#include "theatre_reg.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
+#include "theater_out.h"
+#define RADEON_NAME "RADEON"
+
+#undef read
+#undef write
+#undef ioctl
+
+#if RADEON_DEBUG
+#define RTTRACE(x)							\
+do {									\
+    ErrorF("(**) %s(%d): ", RADEON_NAME, 0);		\
+    ErrorF x;								\
+} while (0);
+#else
+#define RTTRACE(x)
+#endif
+
+/**********************************************************************
+ *
+ * MASK_N_BIT
+ *
+ **********************************************************************/
+
+#define MASK_N_BIT(n)	(1UL << (n))
+
+/**********************************************************************
+ *
+ * Constants
+ *
+ **********************************************************************/
+
+/*
+ * Reference frequency
+ * FIXME: This should be extracted from BIOS data
+ */
+#define REF_FREQUENCY		27000
+
+#define TV_PLL_FINE_INI			0X10000000
+
+/*
+ * VIP_TV_PLL_CNTL
+ */
+#define VIP_TV_PLL_CNTL_M_SHIFT		0
+#define VIP_TV_PLL_CNTL_NLO		0x1ff
+#define VIP_TV_PLL_CNTL_NLO_SHIFT	8
+#define VIP_TV_PLL_CNTL_NHI		0x600
+#define VIP_TV_PLL_CNTL_NHI_SHIFT	(21-9)
+#define VIP_TV_PLL_CNTL_P_SHIFT		24
+
+/*
+ * VIP_CRT_PLL_CNTL
+ */
+#define VIP_CRT_PLL_CNTL_M		0xff
+#define VIP_CRT_PLL_CNTL_M_SHIFT	0
+#define VIP_CRT_PLL_CNTL_NLO		0x1ff
+#define VIP_CRT_PLL_CNTL_NLO_SHIFT	8
+#define VIP_CRT_PLL_CNTL_NHI		0x600
+#define VIP_CRT_PLL_CNTL_NHI_SHIFT	(21-9)
+#define VIP_CRT_PLL_CNTL_CLKBY2		MASK_N_BIT(25)
+
+/*
+ * Value for VIP_PLL_CNTL0
+ */
+#define VIP_PLL_CNTL0_INI		0x00acac18
+#define VIP_PLL_CNTL0_TVSLEEPB		MASK_N_BIT(3)
+#define VIP_PLL_CNTL0_CRTSLEEPB		MASK_N_BIT(4)
+
+/*
+ * Value for VIP_PLL_TEST_CNTL
+ */
+#define VIP_PLL_TEST_CNTL_INI		0
+
+/*
+ * VIP_CLOCK_SEL_CNTL
+ */
+#define VIP_CLOCK_SEL_CNTL_INI		0x33
+#define VIP_CLOCK_SEL_CNTL_BYTCLK_SHIFT	2
+#define VIP_CLOCK_SEL_CNTL_BYTCLK	0xc
+#define VIP_CLOCK_SEL_CNTL_REGCLK	MASK_N_BIT(5)
+#define VIP_CLOCK_SEL_CNTL_BYTCLKD_SHIFT 8
+
+/*
+ * Value for VIP_CLKOUT_CNTL
+ */
+#define VIP_CLKOUT_CNTL_INI		0x29
+
+/*
+ * Value for VIP_SYNC_LOCK_CNTL
+ */
+#define VIP_SYNC_LOCK_CNTL_INI		0x01000000
+
+/*
+ * Value for VIP_TVO_SYNC_PAT_EXPECT
+ */
+#define VIP_TVO_SYNC_PAT_EXPECT_INI	0x00000001
+
+/*
+ * VIP_RGB_CNTL
+ */
+#define VIP_RGB_CNTL_RGB_IS_888_PACK	MASK_N_BIT(0)
+
+/*
+ * Value for VIP_VSCALER_CNTL2
+ */
+#define VIP_VSCALER_CNTL2_INI		0x10000000
+
+/*
+ * Value for VIP_Y_FALL_CNTL
+ */
+/* #define VIP_Y_FALL_CNTL_INI		0x00010200 */
+#define VIP_Y_FALL_CNTL_INI		0x80030400
+
+/*
+ * VIP_UV_ADR
+ */
+#define VIP_UV_ADR_INI			0xc8
+#define VIP_UV_ADR_HCODE_TABLE_SEL	0x06000000
+#define VIP_UV_ADR_HCODE_TABLE_SEL_SHIFT 25
+#define VIP_UV_ADR_VCODE_TABLE_SEL	0x18000000
+#define VIP_UV_ADR_VCODE_TABLE_SEL_SHIFT 27
+#define VIP_UV_ADR_MAX_UV_ADR		0x000000ff
+#define VIP_UV_ADR_MAX_UV_ADR_SHIFT	0
+#define VIP_UV_ADR_TABLE1_BOT_ADR	0x0000ff00
+#define VIP_UV_ADR_TABLE1_BOT_ADR_SHIFT	8
+#define VIP_UV_ADR_TABLE3_TOP_ADR	0x00ff0000
+#define VIP_UV_ADR_TABLE3_TOP_ADR_SHIFT	16
+#define MAX_FIFO_ADDR_RT		0x1a7
+#define MAX_FIFO_ADDR_ERT		0x1ff
+
+/*
+ * VIP_HOST_RD_WT_CNTL
+ */
+#define VIP_HOST_RD_WT_CNTL_RD		MASK_N_BIT(12)
+#define VIP_HOST_RD_WT_CNTL_RD_ACK	MASK_N_BIT(13)
+#define VIP_HOST_RD_WT_CNTL_WT		MASK_N_BIT(14)
+#define VIP_HOST_RD_WT_CNTL_WT_ACK	MASK_N_BIT(15)
+
+/*
+ * Value for VIP_SYNC_CNTL
+ */
+#define VIP_SYNC_CNTL_INI		0x28
+
+/*
+ * VIP_VSCALER_CNTL1
+ */
+#define VIP_VSCALER_CNTL1_UV_INC	0xffff
+#define VIP_VSCALER_CNTL1_UV_INC_SHIFT	0
+
+/*
+ * VIP_TIMING_CNTL
+ */
+#define VIP_TIMING_CNTL_UV_OUT_POST_SCALE_SHIFT	24
+#define VIP_TIMING_CNTL_INI		0x000b0000
+#define VIP_TIMING_CNTL_H_INC_SHIFT	0
+#define VIP_TIMING_CNTL_H_INC		0xfff
+
+/*
+ * Value for VIP_PRE_DAC_MUX_CNTL
+ */
+#define VIP_PRE_DAC_MUX_CNTL_INI	0x0000000f
+
+/*
+ * VIP_TV_DAC_CNTL
+ */
+#define VIP_TV_DAC_CNTL_NBLANK		MASK_N_BIT(0)
+#define VIP_TV_DAC_CNTL_DASLEEP		MASK_N_BIT(3)
+#define VIP_TV_DAC_CNTL_BGSLEEP		MASK_N_BIT(6)
+
+/*
+ * Value for VIP_FRAME_LOCK_CNTL
+ */
+#define VIP_FRAME_LOCK_CNTL_INI		0x0000000f
+
+/*
+ * Value for VIP_HW_DEBUG
+ */
+#define VIP_HW_DEBUG_INI 		0x00000200
+
+/*
+ * VIP_MASTER_CNTL
+ */
+#define VIP_MASTER_CNTL_TV_ASYNC_RST	MASK_N_BIT(0)
+#define VIP_MASTER_CNTL_CRT_ASYNC_RST	MASK_N_BIT(1)
+#define VIP_MASTER_CNTL_RESTART_PHASE_FIX	MASK_N_BIT(3)
+#define VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST	MASK_N_BIT(4)
+#define VIP_MASTER_CNTL_VIN_ASYNC_RST	MASK_N_BIT(5)
+#define VIP_MASTER_CNTL_AUD_ASYNC_RST	MASK_N_BIT(6)
+#define VIP_MASTER_CNTL_DVS_ASYNC_RST	MASK_N_BIT(7)
+#define VIP_MASTER_CNTL_CRT_FIFO_CE_EN	MASK_N_BIT(9)
+#define VIP_MASTER_CNTL_TV_FIFO_CE_EN	MASK_N_BIT(10)
+#define VIP_MASTER_CNTL_ON_INI		(VIP_MASTER_CNTL_RESTART_PHASE_FIX | \
+					 VIP_MASTER_CNTL_VIN_ASYNC_RST | \
+					 VIP_MASTER_CNTL_AUD_ASYNC_RST | \
+					 VIP_MASTER_CNTL_DVS_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_FIFO_CE_EN | \
+					 VIP_MASTER_CNTL_TV_FIFO_CE_EN)
+#define VIP_MASTER_CNTL_OFF_INI		(VIP_MASTER_CNTL_TV_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_ASYNC_RST | \
+					 VIP_MASTER_CNTL_RESTART_PHASE_FIX | \
+					 VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST | \
+					 VIP_MASTER_CNTL_VIN_ASYNC_RST | \
+					 VIP_MASTER_CNTL_AUD_ASYNC_RST | \
+					 VIP_MASTER_CNTL_DVS_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_FIFO_CE_EN | \
+					 VIP_MASTER_CNTL_TV_FIFO_CE_EN)
+
+/*
+ * Value for VIP_LINEAR_GAIN_SETTINGS
+ */
+#define VIP_LINEAR_GAIN_SETTINGS_INI	0x01000100
+
+/*
+ * Value for VIP_GAIN_LIMIT_SETTINGS_INI
+ */
+#define VIP_GAIN_LIMIT_SETTINGS_INI	0x017f05ff
+
+/*
+ * Value for VIP_UPSAMP_AND_GAIN_CNTL 
+ */
+#define VIP_UPSAMP_AND_GAIN_CNTL_INI	0x00000005
+
+/*
+ * RADEON_VCLK_ECP_CNTL
+ */
+#define RADEON_VCLK_ECP_CNTL_BYTECLK_POSTDIV	0x00030000
+#define RADEON_VCLK_ECP_CNTL_BYTECLK_NODIV	0x00000000
+
+/*
+ * RADEON_PLL_TEST_CNTL
+ */
+#define RADEON_PLL_TEST_CNTL_PLL_MASK_READ_B	MASK_N_BIT(9)
+
+/*
+ * RADEON_DAC_CNTL
+ */
+#define RADEON_DAC_CNTL_DAC_TVO_EN	MASK_N_BIT(10)
+
+#define RADEON_PPLL_POST3_DIV_BY_2	0x10000
+#define RADEON_PPLL_POST3_DIV_BY_3	0x40000
+#define RADEON_PPLL_FB3_DIV_SHIFT	0
+#define RADEON_PPLL_POST3_DIV_SHIFT	16
+
+/*
+ * RADEON_DISP_MERGE_CNTL
+ */
+//#define RADEON_DISP_MERGE_CNTL		0xd60
+#define	RADEON_DISP_MERGE_CNTL_INI	0xffff0000
+
+/*
+ * RADEON_HTOTAL_CNTL
+ */
+#define RADEON_HTOTAL_CNTL_HTOT_PIX_SLIP_SHIFT	0
+#define RADEON_HTOTAL_CNTL_HTOT_CNTL_VGA_EN	MASK_N_BIT(28)
+
+/*
+ * RADEON_DISP_OUTPUT_CNTL
+ */
+#define RADEON_DISP_TV_SOURCE		MASK_N_BIT(16)
+#define RADEON_DISP_TV_MODE_MASK	(3 << 17)
+#define RADEON_DISP_TV_MODE_888		(0 << 17)
+#define RADEON_DISP_TV_MODE_565		(1 << 17)
+#define RADEON_DISP_TV_YG_DITH_EN	MASK_N_BIT(19)
+#define RADEON_DISP_TV_CBB_CRR_DITH_EN	MASK_N_BIT(20)
+#define RADEON_DISP_TV_BIT_WIDTH	MASK_N_BIT(21)
+#define RADEON_DISP_TV_SYNC_MODE_MASK	(3 << 22)
+#define RADEON_DISP_TV_SYNC_COLOR_MASK	(3 << 25)
+
+/*
+ * ERT registers
+ */
+#define TV_MASTER_CNTL		0x0800
+#define		TV_MASTER_CNTL_TVCLK_ALWAYS_ON	MASK_N_BIT(30)
+#define		TV_MASTER_CNTL_TV_ON	MASK_N_BIT(31)
+#define		TV_MASTER_CNTL_ON_INI	(VIP_MASTER_CNTL_VIN_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_FIFO_CE_EN | \
+					 VIP_MASTER_CNTL_TV_FIFO_CE_EN | \
+					 TV_MASTER_CNTL_TVCLK_ALWAYS_ON | \
+					 TV_MASTER_CNTL_TV_ON)
+#define		TV_MASTER_CNTL_OFF_INI	(VIP_MASTER_CNTL_TV_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_ASYNC_RST | \
+					 VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST | \
+					 VIP_MASTER_CNTL_CRT_FIFO_CE_EN | \
+					 VIP_MASTER_CNTL_TV_FIFO_CE_EN | \
+					 TV_MASTER_CNTL_TVCLK_ALWAYS_ON)
+#define TV_RGB_CNTL		0x0804
+#define		TV_RGB_CNTL_INI	0x007b0004
+#define TV_SYNC_CNTL		0x0808
+#define TV_HTOTAL		0x080c
+#define TV_HDISP		0x0810
+#define TV_HSTART		0x0818
+#define TV_HCOUNT		0x081c
+#define TV_VTOTAL		0x0820
+#define TV_VDISP		0x0824
+#define TV_VCOUNT		0x0828
+#define TV_FTOTAL		0x082c
+#define TV_FCOUNT		0x0830
+#define TV_FRESTART		0x0834
+#define TV_HRESTART		0x0838
+#define TV_VRESTART		0x083c
+#define TV_HOST_READ_DATA	0x0840
+#define TV_HOST_WRITE_DATA	0x0844
+#define TV_HOST_RD_WT_CNTL	0x0848
+#define TV_VSCALER_CNTL1	0x084c
+#define		TV_VSCALER_CNTL1_RESTART_FIELD	MASK_N_BIT(29)
+#define TV_TIMING_CNTL		0x0850
+#define TV_VSCALER_CNTL2	0x0854
+#define TV_Y_FALL_CNTL		0x0858
+#define TV_Y_RISE_CNTL		0x085c
+#define TV_Y_SAWTOOTH_CNTL	0x0860
+#define TV_UPSAMP_AND_GAIN_CNTL 0x0864
+#define TV_GAIN_LIMIT_SETTINGS	0x0868
+#define TV_LINEAR_GAIN_SETTINGS 0x086c
+#define TV_MODULATOR_CNTL1	0x0870
+#define TV_MODULATOR_CNTL2	0x0874
+#define TV_PRE_DAC_MUX_CNTL	0x0888
+#define TV_DAC_CNTL		0x088c
+#define		TV_DAC_CNTL_NBLANK	MASK_N_BIT(0)
+#define		TV_DAC_CNTL_NHOLD	MASK_N_BIT(1)
+#define		TV_DAC_CNTL_BGSLEEP	MASK_N_BIT(6)
+#define		TV_DAC_CNTL_RDACPD	MASK_N_BIT(24)
+#define		TV_DAC_CNTL_GDACPD	MASK_N_BIT(25)
+#define		TV_DAC_CNTL_BDACPD	MASK_N_BIT(26)
+#define TV_CRC_CNTL		0x0890
+#define TV_UV_ADR		0x08ac
+
+/*
+ * ERT PLL registers
+ */
+#define TV_PLL_CNTL		0x21
+#define TV_PLL_CNTL1		0x22
+#define		TV_PLL_CNTL1_TVPLL_RESET	MASK_N_BIT(1)
+#define		TV_PLL_CNTL1_TVPLL_SLEEP	MASK_N_BIT(3)
+#define		TV_PLL_CNTL1_TVPDC_SHIFT	14
+#define		TV_PLL_CNTL1_TVPDC_MASK		(3 << 14)
+#define		TV_PLL_CNTL1_TVCLK_SRC_SEL	MASK_N_BIT(30)
+
+/*
+ * Constant upsampler coefficients
+ */
+static
+const
+CARD32 upsamplerCoeffs[] =
+{
+  0x3f010000,
+  0x7b008002,
+  0x00003f01,
+  0x341b7405,
+  0x7f3a7617,
+  0x00003d04,
+  0x2d296c0a,
+  0x0e316c2c,
+  0x00003e7d,
+  0x2d1f7503,
+  0x2927643b,
+  0x0000056f,
+  0x29257205,
+  0x25295050,
+  0x00000572
+};
+#define N_UPSAMPLER_COEFFS	(sizeof(upsamplerCoeffs) / sizeof(upsamplerCoeffs[ 0 ]))
+
+/*
+ * Maximum length of horizontal/vertical code timing tables for state storage
+ */
+#define MAX_H_CODE_TIMING_LEN	32
+#define MAX_V_CODE_TIMING_LEN	32
+
+/*
+ * Type of VIP bus
+ */
+#define VIP_TYPE	"ATI VIP BUS"
+
+/*
+ * Limits of h/v positions (hPos & vPos in TheaterOutRec)
+ */
+#define MAX_H_POSITION		5	/* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
+#define MAX_V_POSITION		5	/* Range: [-5..5], negative is up, 0 is default, positive is down */
+
+/*
+ * Unit for hPos (in TV clock periods)
+ */
+#define H_POS_UNIT		10
+
+/*
+ * Indexes in h. code timing table for horizontal line position adjustment
+ */
+#define H_TABLE_POS1		6
+#define H_TABLE_POS2		8
+
+/*
+ * Limits of hor. size (hSize in TheaterOutRec)
+ */
+#define MAX_H_SIZE		5	/* Range: [-5..5], negative is smaller, positive is larger */
+
+/**********************************************************************
+ *
+ * TimingTableEl
+ *
+ * Elements of H/V code timing tables
+ *
+ **********************************************************************/
+
+typedef CARD16 TimingTableEl;	/* Bits 0 to 13 only are actually used */
+
+/**********************************************************************
+ *
+ * ModeConstants
+ *
+ * Storage of constants related to a single video mode
+ *
+ **********************************************************************/
+
+typedef struct
+{
+  CARD16 horResolution;	
+  CARD16 verResolution;
+  TVStd  standard;
+  CARD16 horTotal;
+  CARD16 verTotal;
+  CARD16 horStart;
+  CARD16 horSyncStart;
+  CARD16 verSyncStart;
+  unsigned defRestart;
+  CARD32 vScalerCntl1;
+  CARD32 yRiseCntl;
+  CARD32 ySawtoothCntl;
+  CARD16 crtcPLL_N;
+  CARD8  crtcPLL_M;
+  Bool   crtcPLL_divBy2;
+  CARD8  crtcPLL_byteClkDiv;
+  CARD8	 crtcPLL_postDiv;
+  Bool   use888RGB;		/* False: RGB data is 565 packed (2 bytes/pixel) */
+				/* True : RGB data is 888 packed (3 bytes/pixel) */
+  unsigned pixToTV;
+  CARD8	 byteClkDelay;
+  CARD32 tvoDataDelayA;
+  CARD32 tvoDataDelayB;
+  const TimingTableEl *horTimingTable;
+  const TimingTableEl *verTimingTable;
+} ModeConstants;
+
+/**********************************************************************
+ *
+ * TheaterState
+ *
+ * Storage of RT state
+ *
+ **********************************************************************/
+
+typedef struct
+{
+  CARD32 clkout_cntl;
+  CARD32 clock_sel_cntl;
+  CARD32 crc_cntl;
+  CARD32 crt_pll_cntl;
+  CARD32 dfrestart;
+  CARD32 dhrestart;
+  CARD32 dvrestart;
+  CARD32 frame_lock_cntl;
+  CARD32 gain_limit_settings;
+  CARD32 hdisp;
+  CARD32 hstart;
+  CARD32 htotal;
+  CARD32 hw_debug;
+  CARD32 linear_gain_settings;
+  CARD32 master_cntl;
+  CARD32 modulator_cntl1;
+  CARD32 modulator_cntl2;
+  CARD32 pll_cntl0;
+  CARD32 pll_test_cntl;
+  CARD32 pre_dac_mux_cntl;
+  CARD32 rgb_cntl;
+  CARD32 sync_cntl;
+  CARD32 sync_lock_cntl;
+  CARD32 sync_size;
+  CARD32 timing_cntl;
+  CARD32 tvo_data_delay_a;
+  CARD32 tvo_data_delay_b;
+  CARD32 tvo_sync_pat_expect;
+  CARD32 tvo_sync_threshold;
+  CARD32 tv_dac_cntl;
+  CARD32 tv_pll_cntl;
+  CARD32 tv_pll_fine_cntl;
+  CARD32 upsamp_and_gain_cntl;
+  CARD32 upsamp_coeffs[ N_UPSAMPLER_COEFFS ];
+  CARD32 uv_adr;
+  CARD32 vdisp;
+  CARD32 vftotal;
+  CARD32 vscaler_cntl1;
+  CARD32 vscaler_cntl2;
+  CARD32 vtotal;
+  CARD32 y_fall_cntl;
+  CARD32 y_rise_cntl;
+  CARD32 y_saw_tooth_cntl;
+  CARD32 disp_merge_cntl;
+
+  TimingTableEl h_code_timing[ MAX_H_CODE_TIMING_LEN ];
+  TimingTableEl v_code_timing[ MAX_V_CODE_TIMING_LEN ];
+} TheaterState , *TheaterStatePtr;
+
+/**********************************************************************
+ *
+ * TheaterOutRec , TheaterOutPtr
+ *
+ * Global state of module
+ *
+ **********************************************************************/
+
+typedef struct TheaterOut
+{
+  GENERIC_BUS_Ptr VIP;
+  unsigned char   *MMIO;
+
+  int theatre_num;	/* Negative when driving an ERT */
+			/* Positive or null: index of RT on VIP bus */
+  
+  TVStd standard;
+  Bool compatibleMode;
+
+  const ModeConstants *currentMode;
+    
+  int hPos;
+  int vPos;
+  int hSize;
+
+  TheaterState savedState;
+  TheaterState modeState;
+} TheaterOutRec;
+
+/**********************************************************************
+ *
+ * TVConstants
+ *
+ * Constants that depend on tv standard only
+ *
+ **********************************************************************/
+
+typedef struct
+{
+  CARD8  tvPLL_M;
+  CARD16 tvPLL_N;
+  CARD8  tvPLL_postDiv;
+  CARD32 tvClockT;	/* Period of TV clock (unit = 100 psec) */
+  CARD32 modulatorCntl1;
+  CARD32 modulatorCntl2;
+  CARD32 vip_tvDAC_Cntl;
+  CARD32 ert_tvDAC_Cntl;
+  CARD32 vftotal;
+  unsigned linesFrame;
+  unsigned zeroHSize;	/* Length of the picture part of a hor. line for hSize = 0 (unit = 100 psec) */
+  unsigned hSizeUnit;	/* Value of hSize = 1 (unit = 100 psec) */
+} TVConstants;
+
+/**********************************************************************
+ *
+ * tvStdConsts
+ *
+ * Table of constants for tv standards (index is a TVStd)
+ *
+ **********************************************************************/
+
+static
+const
+TVConstants tvStdConsts[] =
+  {
+    /*
+     * NTSC
+     */
+    {
+      22,	/* tvPLL_M */
+      175,	/* tvPLL_N */
+      5,	/* tvPLL_postDiv */
+      233,	/* tvClockT */
+      0x60bb468c, /* modulatorCntl1 */
+      0x00000191, /* modulatorCntl2 */
+      0x00000113, /* vip_tvDAC_Cntl */
+      0x00680113, /* ert_tvDAC_Cntl */
+      1,	/* vftotal */
+      525,	/* linesFrame */
+      479166,	/* zeroHSize */
+      9478	/* hSizeUnit */
+    },
+    /*
+     * PAL
+     */
+    {
+      113,	/* tvPLL_M */
+      668,	/* tvPLL_N */
+      3,	/* tvPLL_postDiv */
+      188,	/* tvClockT */
+      0x60bb3bcc, /* modulatorCntl1 */
+      0x003e01b2, /* modulatorCntl2 */
+      0x00000013, /* vip_tvDAC_Cntl */
+      0x00680013, /* ert_tvDAC_Cntl */
+      3,	/* vftotal */
+      625,	/* linesFrame */
+      473200,	/* zeroHSize */
+      9360	/* hSizeUnit */
+    }
+  };
+
+/**********************************************************************
+ *
+ * availableModes
+ *
+ * Table of all allowed modes for tv output
+ *
+ **********************************************************************/
+
+static
+const
+TimingTableEl horTimingNTSC_BIOS[] =
+  {
+    0x0007,
+    0x003f,
+    0x0263,
+    0x0a24,
+    0x2a6b,
+    0x0a36,
+    0x126d,	/* H_TABLE_POS1 */
+    0x1bfe,
+    0x1a8f,	/* H_TABLE_POS2 */
+    0x1ec7,
+    0x3863,
+    0x1bfe,
+    0x1bfe,
+    0x1a2a,
+    0x1e95,
+    0x0e31,
+    0x201b,
+    0
+  };
+
+static
+const
+TimingTableEl verTimingNTSC_BIOS[] =
+  {
+    0x2001,
+    0x200d,
+    0x1006,
+    0x0c06,
+    0x1006,
+    0x1818,
+    0x21e3,
+    0x1006,
+    0x0c06,
+    0x1006,
+    0x1817,
+    0x21d4,
+    0x0002,
+    0
+  };
+
+static
+const
+TimingTableEl horTimingPAL_BIOS[] =
+  {
+    0x0007,
+    0x0058,
+    0x027c,
+    0x0a31,
+    0x2a77,
+    0x0a95,
+    0x124f,	/* H_TABLE_POS1 */
+    0x1bfe,
+    0x1b22,	/* H_TABLE_POS2 */
+    0x1ef9,
+    0x387c,
+    0x1bfe,
+    0x1bfe,
+    0x1b31,
+    0x1eb5,
+    0x0e43,
+    0x201b,
+    0
+  };
+
+static
+const
+TimingTableEl verTimingPAL_BIOS[] =
+  {
+    0x2001,
+    0x200c,
+    0x1005,
+    0x0c05,
+    0x1005,
+    0x1401,
+    0x1821,
+    0x2240,
+    0x1005,
+    0x0c05,
+    0x1005,
+    0x1401,
+    0x1822,
+    0x2230,
+    0x0002,
+    0
+  };
+
+static
+const
+ModeConstants availableModes[] =
+  {
+    { 
+      800,		/* horResolution */
+      600,		/* verResolution */
+      TV_STD_NTSC,	/* standard */
+      990,		/* horTotal */
+      740,		/* verTotal */
+      813,		/* horStart */
+      824,		/* horSyncStart */
+      632,		/* verSyncStart */
+      625592,		/* defRestart */
+      0x0900b46b,	/* vScalerCntl1 */
+      0x00012c00,	/* yRiseCntl */
+      0x10002d1a,	/* ySawtoothCntl */
+      592,		/* crtcPLL_N */
+      91,		/* crtcPLL_M */
+      TRUE,		/* crtcPLL_divBy2 */
+      0,		/* crtcPLL_byteClkDiv */
+      4,		/* crtcPLL_postDiv */
+      FALSE,		/* use888RGB */
+      1022,		/* pixToTV */
+      1,		/* byteClkDelay */
+      0x0a0b0907,	/* tvoDataDelayA */
+      0x060a090a,	/* tvoDataDelayB */
+      horTimingNTSC_BIOS,/* horTimingTable */
+      verTimingNTSC_BIOS/* verTimingTable */
+    },
+    { 
+      800,		/* horResolution */
+      600,		/* verResolution */
+      TV_STD_PAL,	/* standard */
+      1144,		/* horTotal */
+      706,		/* verTotal */
+      812,		/* horStart */
+      824,		/* horSyncStart */
+      669,		/* verSyncStart */
+      696700,		/* defRestart */
+      0x09009097,	/* vScalerCntl1 */
+      0x000007da,	/* yRiseCntl */
+      0x10002426,	/* ySawtoothCntl */
+      1382,		/* crtcPLL_N */
+      231,		/* crtcPLL_M */
+      TRUE,		/* crtcPLL_divBy2 */
+      0,		/* crtcPLL_byteClkDiv */
+      4,		/* crtcPLL_postDiv */
+      FALSE,		/* use888RGB */
+      759,		/* pixToTV */
+      1,		/* byteClkDelay */
+      0x0a0b0907,	/* tvoDataDelayA */
+      0x060a090a,	/* tvoDataDelayB */
+      horTimingPAL_BIOS,/* horTimingTable */
+      verTimingPAL_BIOS	/* verTimingTable */
+    }
+  };
+
+#define N_AVAILABLE_MODES	(sizeof(availableModes) / sizeof(availableModes[ 0 ]))
+
+/**********************************************************************
+ *
+ * theatre_read
+ *
+ * Read from a RT register
+ *
+ **********************************************************************/
+
+static 
+Bool 
+theatre_read(
+	     TheaterOutPtr t,
+	     CARD32 reg,
+	     CARD32 *data
+	     )
+{
+  if (t->theatre_num < 0)
+    return FALSE;
+  
+  return t->VIP->read(t->VIP, ((t->theatre_num & 0x3) << 14) | reg , 4 , (CARD8*)data);
+}
+
+/**********************************************************************
+ *
+ * theatre_write
+ *
+ * Write to a RT register
+ *
+ **********************************************************************/
+
+static
+Bool 
+theatre_write(
+	      TheaterOutPtr t,
+	      CARD32 reg,
+	      CARD32 data
+	      )
+{
+  if (t->theatre_num < 0)
+    return FALSE;
+
+  return t->VIP->write(t->VIP , ((t->theatre_num & 0x03) << 14) | reg , 4 , (CARD8*)&data);
+}
+
+/**********************************************************************
+ *
+ * ert_read
+ *
+ * Read from an ERT register
+ *
+ **********************************************************************/
+
+static 
+void 
+ert_read(
+	 TheaterOutPtr t,
+	 CARD32 reg,
+	 CARD32 *data
+	 )
+{
+  unsigned char *RADEONMMIO = t->MMIO;
+
+  if (t->theatre_num < 0)
+    *data = INREG(reg);
+}
+
+/**********************************************************************
+ *
+ * ert_write
+ *
+ * Write to an ERT register
+ *
+ **********************************************************************/
+static
+void 
+ert_write(
+	  TheaterOutPtr t,
+	  CARD32 reg,
+	  CARD32 data
+	  )
+{
+  unsigned char *RADEONMMIO = t->MMIO;
+
+  if (t->theatre_num < 0)
+    OUTREG(reg , data);
+}
+
+/**********************************************************************
+ *
+ * waitPLL_lock
+ *
+ * Wait for PLLs to lock
+ *
+ **********************************************************************/
+
+static
+void
+waitPLL_lock(
+	     TheaterOutPtr t,
+	     ScrnInfoPtr pScrn,
+	     unsigned nTests,
+	     unsigned nWaitLoops,
+	     unsigned cntThreshold
+	     )
+{
+  unsigned char *RADEONMMIO = t->MMIO;
+  CARD32 savePLLTest;
+  unsigned i;
+  unsigned j;
+
+  OUTREG(RADEON_TEST_DEBUG_MUX , (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
+
+  savePLLTest = INPLL(pScrn , RADEON_PLL_TEST_CNTL);
+
+  OUTPLL(pScrn , RADEON_PLL_TEST_CNTL , savePLLTest & ~RADEON_PLL_TEST_CNTL_PLL_MASK_READ_B);
+
+  OUTREG8(RADEON_CLOCK_CNTL_INDEX , RADEON_PLL_TEST_CNTL);
+
+  for (i = 0; i < nTests; i++)
+    {
+      OUTREG8(RADEON_CLOCK_CNTL_DATA + 3 , 0);
+      
+      for (j = 0; j < nWaitLoops; j++)
+	if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold)
+	  break;
+    }
+
+  OUTPLL(pScrn , RADEON_PLL_TEST_CNTL , savePLLTest);
+
+  OUTREG(RADEON_TEST_DEBUG_MUX , INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
+}
+
+/**********************************************************************
+ *
+ * restorePLL
+ *
+ * Set PLLs for CRTC pixel clock & TV color burst generation
+ *
+ **********************************************************************/
+
+static
+void
+restorePLL(
+	   TheaterOutPtr t,
+	   ScrnInfoPtr pScrn,
+	   TheaterStatePtr restore
+	   )
+{
+  unsigned i;
+
+  /*
+   * Set TV PLL
+   */
+  RTTRACE(("restorePLL: TV_PLL_CNTL = %08x\n" , restore->tv_pll_cntl));
+  theatre_write(t , VIP_TV_PLL_CNTL , restore->tv_pll_cntl);
+  theatre_write(t , VIP_TV_PLL_FINE_CNTL , restore->tv_pll_fine_cntl);
+
+  /*
+   * Set CRT PLL (for byte and pixel clock generation)
+   */
+  RTTRACE(("restorePLL: CRT_PLL_CNTL = %08x\n" , restore->crt_pll_cntl));
+  theatre_write(t , VIP_CRT_PLL_CNTL , restore->crt_pll_cntl);
+  
+  theatre_write(t , VIP_PLL_CNTL0 , restore->pll_cntl0);
+
+  theatre_write(t , VIP_PLL_TEST_CNTL , restore->pll_test_cntl);
+
+  /*
+   * Set coefficients for upsampler
+   */
+  for (i = 0; i < N_UPSAMPLER_COEFFS; i++)
+    theatre_write(t , VIP_UPSAMP_COEFF0_0 + i * 4 , restore->upsamp_coeffs[ i ]);
+
+  /*
+   * Waiting for PLLs to settle is skipped when restoring a state with stopped PLLs
+   */
+  if ((~restore->pll_cntl0 & (VIP_PLL_CNTL0_TVSLEEPB | VIP_PLL_CNTL0_CRTSLEEPB)) == 0)
+    {
+      waitPLL_lock(t , pScrn , 3000 , 160 , 27);
+
+      theatre_write(t , VIP_CLOCK_SEL_CNTL , restore->clock_sel_cntl & ~VIP_CLOCK_SEL_CNTL_REGCLK);
+
+      waitPLL_lock(t , pScrn , 3000 , 160 , 27);
+    }
+
+  RTTRACE(("restorePLL: CLOCK_SEL_CNTL = %08x\n" , restore->clock_sel_cntl));
+  theatre_write(t , VIP_CLOCK_SEL_CNTL , restore->clock_sel_cntl);
+
+  theatre_write(t , VIP_CLKOUT_CNTL , restore->clkout_cntl);
+}
+
+/**********************************************************************
+ *
+ * restoreTVO_SYNC
+ *
+ * Set TVO_SYNC_* registers
+ *
+ **********************************************************************/
+
+static
+void
+restoreTVO_SYNC(
+		TheaterOutPtr t,
+		TheaterStatePtr restore
+		)
+{
+  theatre_write(t , VIP_SYNC_LOCK_CNTL , restore->sync_lock_cntl);
+  theatre_write(t , VIP_TVO_SYNC_THRESHOLD , restore->tvo_sync_threshold);
+  theatre_write(t , VIP_TVO_SYNC_PAT_EXPECT , restore->tvo_sync_pat_expect);
+}
+
+/**********************************************************************
+ *
+ * restoreTVO_DataDelay
+ *
+ * Set TVO_DATA_DELAY_* registers
+ *
+ **********************************************************************/
+
+static
+void
+restoreTVO_DataDelay(
+		     TheaterOutPtr t,
+		     TheaterStatePtr restore
+		     )
+{
+  theatre_write(t , VIP_TVO_DATA_DELAY_A , restore->tvo_data_delay_a);
+  theatre_write(t , VIP_TVO_DATA_DELAY_B , restore->tvo_data_delay_b);
+}
+
+/**********************************************************************
+ *
+ * restoreRT_HV
+ *
+ * Set RT horizontal/vertical settings
+ *
+ **********************************************************************/
+
+static
+void
+restoreRT_HV(
+	     TheaterOutPtr t,
+	     TheaterStatePtr restore
+	     )
+{
+  theatre_write(t , VIP_RGB_CNTL , restore->rgb_cntl);
+
+  theatre_write(t , VIP_HTOTAL , restore->htotal);
+  theatre_write(t , VIP_HDISP  , restore->hdisp);
+  theatre_write(t , VIP_HSTART , restore->hstart);
+  
+  theatre_write(t , VIP_VTOTAL , restore->vtotal);
+  theatre_write(t , VIP_VDISP  , restore->vdisp);
+  
+  theatre_write(t , VIP_VFTOTAL , restore->vftotal);
+
+  theatre_write(t , VIP_SYNC_SIZE , restore->sync_size);
+
+  theatre_write(t , VIP_VSCALER_CNTL1 , restore->vscaler_cntl1);
+  theatre_write(t , VIP_VSCALER_CNTL2 , restore->vscaler_cntl2);
+  
+  theatre_write(t , VIP_Y_FALL_CNTL , restore->y_fall_cntl);
+  theatre_write(t , VIP_Y_RISE_CNTL , restore->y_rise_cntl);
+  theatre_write(t , VIP_Y_SAW_TOOTH_CNTL , restore->y_saw_tooth_cntl);
+}
+
+/**********************************************************************
+ *
+ * restoreRestarts
+ *
+ * Set RT D*RESTART registers
+ *
+ **********************************************************************/
+
+static
+void
+restoreRestarts(	 
+		TheaterOutPtr t,
+		TheaterStatePtr restore
+		)
+{
+  theatre_write(t , VIP_DFRESTART , restore->dfrestart);
+  theatre_write(t , VIP_DHRESTART , restore->dhrestart);
+  theatre_write(t , VIP_DVRESTART , restore->dvrestart);
+}
+
+/**********************************************************************
+ *
+ * writeFIFO
+ *
+ * Write to RT FIFO RAM
+ *
+ **********************************************************************/
+
+static
+void
+writeFIFO(
+	  TheaterOutPtr t,
+	  CARD16 addr,
+	  CARD32 value
+	  )
+{
+  CARD32 tmp;
+
+  if (t->theatre_num >= 0)
+    {
+      theatre_write(t , VIP_HOST_WRITE_DATA , value);
+
+      theatre_write(t , VIP_HOST_RD_WT_CNTL , addr | VIP_HOST_RD_WT_CNTL_WT);
+
+      do
+	{
+	  if (!theatre_read(t , VIP_HOST_RD_WT_CNTL , &tmp))
+	    break;
+	} 
+      while ((tmp & VIP_HOST_RD_WT_CNTL_WT_ACK) == 0);
+
+      theatre_write(t , VIP_HOST_RD_WT_CNTL , 0);
+    }
+  else
+    {
+      ert_write(t , TV_HOST_WRITE_DATA , value);
+
+      ert_write(t , TV_HOST_RD_WT_CNTL , addr | VIP_HOST_RD_WT_CNTL_WT);
+
+      do
+	{
+	  ert_read(t , TV_HOST_RD_WT_CNTL , &tmp);
+	} 
+      while ((tmp & VIP_HOST_RD_WT_CNTL_WT_ACK) == 0);
+
+      ert_write(t , TV_HOST_RD_WT_CNTL , 0);
+    }
+}
+
+/**********************************************************************
+ *
+ * readFIFO
+ *
+ * Read from RT FIFO RAM
+ *
+ **********************************************************************/
+
+static
+void
+readFIFO(
+	 TheaterOutPtr t,
+	 CARD16 addr,
+	 CARD32 *value
+	 )
+{
+  CARD32 tmp;
+  
+  if (t->theatre_num >= 0)
+    {
+      theatre_write(t , VIP_HOST_RD_WT_CNTL , addr | VIP_HOST_RD_WT_CNTL_RD);
+
+      do
+	{
+	  if (!theatre_read(t , VIP_HOST_RD_WT_CNTL , &tmp))
+	    break;
+	} 
+      while ((tmp & VIP_HOST_RD_WT_CNTL_RD_ACK) == 0);
+
+      theatre_write(t , VIP_HOST_RD_WT_CNTL , 0);
+
+      theatre_read(t , VIP_HOST_READ_DATA , value);
+    }
+  else
+    {
+      ert_write(t , TV_HOST_RD_WT_CNTL , addr | VIP_HOST_RD_WT_CNTL_RD);
+
+      do
+	{
+	  ert_read(t , TV_HOST_RD_WT_CNTL , &tmp);
+	} 
+      while ((tmp & VIP_HOST_RD_WT_CNTL_RD_ACK) == 0);
+
+      ert_write(t , TV_HOST_RD_WT_CNTL , 0);
+
+      ert_read(t , TV_HOST_READ_DATA , value);
+    }
+}
+
+/**********************************************************************
+ *
+ * getTimingTablesAddr
+ *
+ * Get FIFO addresses of horizontal & vertical code timing tables from
+ * settings of uv_adr register.
+ *
+ **********************************************************************/
+
+static
+void
+getTimingTablesAddr(
+		    CARD32 uv_adr,
+		    Bool isERT,
+		    CARD16 *hTable,
+		    CARD16 *vTable
+		    )
+{
+  switch ((uv_adr & VIP_UV_ADR_HCODE_TABLE_SEL) >> VIP_UV_ADR_HCODE_TABLE_SEL_SHIFT)
+    {
+    case 0:
+      *hTable = isERT ? MAX_FIFO_ADDR_ERT : MAX_FIFO_ADDR_RT;
+      break;
+
+    case 1:
+      *hTable = ((uv_adr & VIP_UV_ADR_TABLE1_BOT_ADR) >> VIP_UV_ADR_TABLE1_BOT_ADR_SHIFT) * 2;
+      break;
+
+    case 2:
+      *hTable = ((uv_adr & VIP_UV_ADR_TABLE3_TOP_ADR) >> VIP_UV_ADR_TABLE3_TOP_ADR_SHIFT) * 2;
+      break;
+
+    default:
+      /*
+       * Of course, this should never happen
+       */
+      *hTable = 0;
+      break;
+    }
+
+  switch ((uv_adr & VIP_UV_ADR_VCODE_TABLE_SEL) >> VIP_UV_ADR_VCODE_TABLE_SEL_SHIFT)
+    {
+    case 0:
+      *vTable = ((uv_adr & VIP_UV_ADR_MAX_UV_ADR) >> VIP_UV_ADR_MAX_UV_ADR_SHIFT) * 2 + 1;
+      break;
+
+    case 1:
+      *vTable = ((uv_adr & VIP_UV_ADR_TABLE1_BOT_ADR) >> VIP_UV_ADR_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
+      break;
+
+    case 2:
+      *vTable = ((uv_adr & VIP_UV_ADR_TABLE3_TOP_ADR) >> VIP_UV_ADR_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
+      break;
+
+    default:
+      /*
+       * Of course, this should never happen
+       */
+      *vTable = 0;
+      break;
+    }
+}
+
+/**********************************************************************
+ *
+ * saveTimingTables
+ *
+ * Save horizontal/vertical timing code tables
+ *
+ **********************************************************************/
+static
+void
+saveTimingTables(
+		 TheaterOutPtr t,
+		 TheaterStatePtr save
+		 )
+{
+  CARD16 hTable;
+  CARD16 vTable;
+  CARD32 tmp;
+  unsigned i;
+
+  if (t->theatre_num >= 0)
+    {
+      theatre_read(t , VIP_UV_ADR , &save->uv_adr);
+      getTimingTablesAddr(save->uv_adr , FALSE , &hTable , &vTable);
+    }
+  else
+    {
+      ert_read(t , TV_UV_ADR , &save->uv_adr);
+      getTimingTablesAddr(save->uv_adr , TRUE , &hTable , &vTable);
+    }
+
+  /*
+   * Reset FIFO arbiter in order to be able to access FIFO RAM
+   */
+  if (t->theatre_num >= 0)
+    {
+      theatre_write(t , 
+		    VIP_MASTER_CNTL , 
+		    save->master_cntl | 
+		    VIP_MASTER_CNTL_CRT_ASYNC_RST |
+		    VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST |
+		    VIP_MASTER_CNTL_TV_ASYNC_RST);
+      theatre_write(t , 
+		    VIP_MASTER_CNTL , 
+		    save->master_cntl |
+		    VIP_MASTER_CNTL_TV_ASYNC_RST |
+		    VIP_MASTER_CNTL_CRT_ASYNC_RST);
+    }
+  else
+    {
+      ert_write(t , 
+		TV_MASTER_CNTL , 
+		save->master_cntl | TV_MASTER_CNTL_TV_ON);
+    }
+
+  RTTRACE(("saveTimingTables: reading timing tables\n"));
+
+  for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2)
+    {
+      readFIFO(t , hTable-- , &tmp);
+      save->h_code_timing[ i     ] = (CARD16)((tmp >> 14) & 0x3fff);
+      save->h_code_timing[ i + 1 ] = (CARD16)(tmp & 0x3fff);
+
+      if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0)
+	break;
+    }
+
+  for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2)
+    {
+      readFIFO(t , vTable++ , &tmp);
+      save->v_code_timing[ i     ] = (CARD16)(tmp & 0x3fff);
+      save->v_code_timing[ i + 1 ] = (CARD16)((tmp >> 14) & 0x3fff);
+
+      if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0)
+	break;
+    }
+}
+		 
+/**********************************************************************
+ *
+ * restoreTimingTables
+ *
+ * Load horizontal/vertical timing code tables
+ *
+ **********************************************************************/
+
+static
+void
+restoreTimingTables(
+		    TheaterOutPtr t,
+		    TheaterStatePtr restore
+		    )
+{
+  CARD16 hTable;
+  CARD16 vTable;
+  CARD32 tmp;
+  unsigned i;
+
+  if (t->theatre_num >= 0)
+    {
+      theatre_write(t , VIP_UV_ADR , restore->uv_adr);
+      getTimingTablesAddr(restore->uv_adr , FALSE , &hTable , &vTable);
+    }
+  else
+    {
+      ert_write(t , TV_UV_ADR , restore->uv_adr);
+      getTimingTablesAddr(restore->uv_adr , TRUE , &hTable , &vTable);
+    }
+
+  for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2 , hTable--)
+    {
+      tmp = ((CARD32)restore->h_code_timing[ i ] << 14) | ((CARD32)restore->h_code_timing[ i + 1 ]);
+      writeFIFO(t , hTable , tmp);
+      if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0)
+	break;
+    }
+
+  for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2 , vTable++)
+    {
+      tmp = ((CARD32)restore->v_code_timing[ i + 1 ] << 14) | ((CARD32)restore->v_code_timing[ i ]);
+      writeFIFO(t , vTable , tmp);
+      if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0)
+	break;
+    }
+}
+
+/**********************************************************************
+ *
+ * restoreOutputStd
+ *
+ * Set tv standard & output muxes
+ *
+ **********************************************************************/
+
+static
+void
+restoreOutputStd(
+		 TheaterOutPtr t,
+		 TheaterStatePtr restore
+		 )
+{
+  theatre_write(t , VIP_SYNC_CNTL , restore->sync_cntl);
+  
+  theatre_write(t , VIP_TIMING_CNTL , restore->timing_cntl);
+
+  theatre_write(t , VIP_MODULATOR_CNTL1 , restore->modulator_cntl1);
+  theatre_write(t , VIP_MODULATOR_CNTL2 , restore->modulator_cntl2);
+ 
+  theatre_write(t , VIP_PRE_DAC_MUX_CNTL , restore->pre_dac_mux_cntl);
+
+  theatre_write(t , VIP_CRC_CNTL , restore->crc_cntl);
+
+  theatre_write(t , VIP_FRAME_LOCK_CNTL , restore->frame_lock_cntl);
+
+  theatre_write(t , VIP_HW_DEBUG , restore->hw_debug);
+}
+
+/**********************************************************************
+ *
+ * enableTV_DAC
+ *
+ * Enable/disable tv output DAC
+ *
+ **********************************************************************/
+
+static
+void
+enableTV_DAC(
+	     TheaterOutPtr t,
+	     Bool enable
+	     )
+{
+  CARD32 tmp;
+
+  theatre_read(t , VIP_TV_DAC_CNTL , &tmp);
+
+  if (enable)
+    {
+      tmp |= VIP_TV_DAC_CNTL_NBLANK;
+      tmp &= ~VIP_TV_DAC_CNTL_DASLEEP;
+      tmp &= ~VIP_TV_DAC_CNTL_BGSLEEP;
+    }
+  else
+    {
+      tmp &= ~VIP_TV_DAC_CNTL_NBLANK;
+      tmp |= VIP_TV_DAC_CNTL_DASLEEP;
+      tmp |= VIP_TV_DAC_CNTL_BGSLEEP;
+    }
+
+  theatre_write(t , VIP_TV_DAC_CNTL , tmp);
+}
+
+/**********************************************************************
+ *
+ * ERT_RestorePLL
+ *
+ * Set ERT PLLs
+ *
+ **********************************************************************/
+static
+void
+ERT_RestorePLL(
+	       TheaterOutPtr t,
+	       ScrnInfoPtr pScrn,
+	       TheaterStatePtr restore
+	       )
+{
+  unsigned char *RADEONMMIO = t->MMIO;
+
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , 0 , ~TV_PLL_CNTL1_TVCLK_SRC_SEL);
+  OUTPLL(pScrn , TV_PLL_CNTL , restore->tv_pll_cntl);
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , TV_PLL_CNTL1_TVPLL_RESET , ~TV_PLL_CNTL1_TVPLL_RESET);
+
+  waitPLL_lock(t , pScrn , 200 , 800 , 135);
+  
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , 0 , ~TV_PLL_CNTL1_TVPLL_RESET);
+
+  waitPLL_lock(t , pScrn , 300 , 160 , 27);
+  waitPLL_lock(t , pScrn , 200 , 800 , 135);
+  
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , 0 , ~0xf);
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , TV_PLL_CNTL1_TVCLK_SRC_SEL , ~TV_PLL_CNTL1_TVCLK_SRC_SEL);
+  
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , (1 << TV_PLL_CNTL1_TVPDC_SHIFT) , ~TV_PLL_CNTL1_TVPDC_MASK);
+  OUTPLLP(pScrn , TV_PLL_CNTL1 , 0 , ~TV_PLL_CNTL1_TVPLL_SLEEP);
+}
+
+/**********************************************************************
+ *
+ * ERT_RestoreHV
+ *
+ * Set ERT horizontal/vertical settings
+ *
+ **********************************************************************/
+
+static
+void
+ERT_RestoreHV(
+	      TheaterOutPtr t,
+	      TheaterStatePtr restore
+	      )
+{
+  ert_write(t , TV_RGB_CNTL , restore->rgb_cntl);
+
+  ert_write(t , TV_HTOTAL , restore->htotal);
+  ert_write(t , TV_HDISP  , restore->hdisp);
+  ert_write(t , TV_HSTART , restore->hstart);
+
+  ert_write(t , TV_VTOTAL , restore->vtotal);
+  ert_write(t , TV_VDISP  , restore->vdisp);
+
+  ert_write(t , TV_FTOTAL , restore->vftotal);
+
+  ert_write(t , TV_VSCALER_CNTL1 , restore->vscaler_cntl1);
+  ert_write(t , TV_VSCALER_CNTL2 , restore->vscaler_cntl2);
+
+  ert_write(t , TV_Y_FALL_CNTL , restore->y_fall_cntl);
+  ert_write(t , TV_Y_RISE_CNTL , restore->y_rise_cntl);
+  ert_write(t , TV_Y_SAWTOOTH_CNTL , restore->y_saw_tooth_cntl);
+}
+
+/**********************************************************************
+ *
+ * ERT_RestoreRestarts
+ *
+ * Set ERT TV_*RESTART registers
+ *
+ **********************************************************************/
+
+static
+void
+ERT_RestoreRestarts(	 
+		    TheaterOutPtr t,
+		    TheaterStatePtr restore
+		    )
+{
+  ert_write(t , TV_FRESTART , restore->dfrestart);
+  ert_write(t , TV_HRESTART , restore->dhrestart);
+  ert_write(t , TV_VRESTART , restore->dvrestart);
+}
+
+/**********************************************************************
+ *
+ * ERT_RestoreOutputStd
+ *
+ * Set tv standard & output muxes
+ *
+ **********************************************************************/
+static
+void
+ERT_RestoreOutputStd(
+		     TheaterOutPtr t,
+		     TheaterStatePtr restore
+		     )
+{
+  ert_write(t , TV_SYNC_CNTL , restore->sync_cntl);
+  
+  ert_write(t , TV_TIMING_CNTL , restore->timing_cntl);
+
+  ert_write(t , TV_MODULATOR_CNTL1 , restore->modulator_cntl1);
+  ert_write(t , TV_MODULATOR_CNTL2 , restore->modulator_cntl2);
+ 
+  ert_write(t , TV_PRE_DAC_MUX_CNTL , restore->pre_dac_mux_cntl);
+
+  ert_write(t , TV_CRC_CNTL , restore->crc_cntl);
+}
+
+/**********************************************************************
+ *
+ * ERT_IsOn
+ *
+ * Test if tv output would be enabled with a given value in TV_DAC_CNTL
+ *
+ **********************************************************************/
+static
+Bool
+ERT_IsOn(
+	 CARD32 tv_dac_cntl
+	 )
+{
+  if (tv_dac_cntl & TV_DAC_CNTL_BGSLEEP)
+    return FALSE;
+  else if ((tv_dac_cntl & (TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | TV_DAC_CNTL_BDACPD)) ==
+	   (TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | TV_DAC_CNTL_BDACPD))
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/**********************************************************************
+ *
+ * ERT_Restore
+ *
+ * Restore state of ERT
+ *
+ **********************************************************************/
+static
+void
+ERT_Restore(
+	    TheaterOutPtr t,
+	    ScrnInfoPtr pScrn,
+	    TheaterStatePtr restore
+	    )
+{
+  RTTRACE(("Entering ERT_Restore\n"));
+
+  ert_write(t , 
+	    TV_MASTER_CNTL , 
+	    restore->master_cntl | TV_MASTER_CNTL_TV_ON);
+
+  ert_write(t,
+	    TV_MASTER_CNTL ,
+	    restore->master_cntl | 
+	    VIP_MASTER_CNTL_TV_ASYNC_RST |
+	    VIP_MASTER_CNTL_CRT_ASYNC_RST |
+	    VIP_MASTER_CNTL_RESTART_PHASE_FIX |
+	    VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST);
+
+  /*
+   * Temporarily turn the TV DAC off
+   */
+  ert_write(t ,
+	    TV_DAC_CNTL ,
+	    (restore->tv_dac_cntl & ~TV_DAC_CNTL_NBLANK) |
+	    TV_DAC_CNTL_BGSLEEP |
+	    TV_DAC_CNTL_RDACPD |
+	    TV_DAC_CNTL_GDACPD |
+	    TV_DAC_CNTL_BDACPD);
+
+  RTTRACE(("ERT_Restore: checkpoint 1\n"));
+  ERT_RestorePLL(t , pScrn , restore);
+
+  RTTRACE(("ERT_Restore: checkpoint 2\n"));
+  ERT_RestoreHV(t , restore);
+
+  ert_write(t,
+	    TV_MASTER_CNTL ,
+	    restore->master_cntl | 
+	    VIP_MASTER_CNTL_TV_ASYNC_RST |
+	    VIP_MASTER_CNTL_CRT_ASYNC_RST |
+	    VIP_MASTER_CNTL_RESTART_PHASE_FIX);
+
+  RTTRACE(("ERT_Restore: checkpoint 3\n"));
+  ERT_RestoreRestarts(t , restore);
+  
+  RTTRACE(("ERT_Restore: checkpoint 4\n"));
+
+  /*
+   * Timing tables are only restored when tv output is active
+   */
+  if (ERT_IsOn(restore->tv_dac_cntl))
+    restoreTimingTables(t , restore);
+  
+  ert_write(t,
+	    TV_MASTER_CNTL ,
+	    restore->master_cntl | 
+	    VIP_MASTER_CNTL_TV_ASYNC_RST |
+	    VIP_MASTER_CNTL_RESTART_PHASE_FIX);
+
+  RTTRACE(("ERT_Restore: checkpoint 5\n"));
+  ERT_RestoreOutputStd(t , restore);
+
+  ert_write(t , 
+	    TV_MASTER_CNTL , 
+	    restore->master_cntl);
+
+  ert_write(t , RADEON_DISP_MERGE_CNTL , restore->disp_merge_cntl);
+
+  ert_write(t , TV_GAIN_LIMIT_SETTINGS , restore->gain_limit_settings);
+  ert_write(t , TV_LINEAR_GAIN_SETTINGS , restore->linear_gain_settings);
+
+  ert_write(t , TV_DAC_CNTL , restore->tv_dac_cntl);
+
+  RTTRACE(("Leaving ERT_Restore\n"));
+}
+
+/**********************************************************************
+ *
+ * RT_Restore
+ *
+ * Restore state of RT
+ *
+ **********************************************************************/
+
+static
+void
+RT_Restore(
+	   TheaterOutPtr t,
+	   ScrnInfoPtr pScrn,
+	   TheaterStatePtr restore
+	   )
+{
+  if (t->theatre_num < 0)
+    {
+      ERT_Restore(t , pScrn , restore);
+      return;
+    }
+
+  RTTRACE(("Entering RT_Restore\n"));
+
+  theatre_write(t , 
+		VIP_MASTER_CNTL , 
+		restore->master_cntl | 
+		VIP_MASTER_CNTL_TV_ASYNC_RST |
+		VIP_MASTER_CNTL_CRT_ASYNC_RST |
+		VIP_MASTER_CNTL_TV_FIFO_ASYNC_RST);
+
+  /*
+   * Temporarily turn the TV DAC off
+   */
+  theatre_write(t ,
+		VIP_TV_DAC_CNTL ,
+		(restore->tv_dac_cntl & ~VIP_TV_DAC_CNTL_NBLANK) |
+		VIP_TV_DAC_CNTL_DASLEEP | 
+		VIP_TV_DAC_CNTL_BGSLEEP);
+
+  RTTRACE(("RT_Restore: checkpoint 1\n"));
+  restoreTVO_SYNC(t , restore);
+
+  RTTRACE(("RT_Restore: checkpoint 2\n"));
+  restorePLL(t , pScrn , restore);
+
+  RTTRACE(("RT_Restore: checkpoint 3\n"));
+  restoreTVO_DataDelay(t , restore);
+
+  RTTRACE(("RT_Restore: checkpoint 4\n"));
+  restoreRT_HV(t , restore);
+  
+  theatre_write(t , 
+		VIP_MASTER_CNTL , 
+		restore->master_cntl |
+		VIP_MASTER_CNTL_TV_ASYNC_RST |
+		VIP_MASTER_CNTL_CRT_ASYNC_RST);
+
+  RTTRACE(("RT_Restore: checkpoint 5\n"));
+  restoreRestarts(t , restore);
+
+  RTTRACE(("RT_Restore: checkpoint 6\n"));
+
+  /*
+   * Timing tables are restored when tv output is active
+   */
+  if ((restore->tv_dac_cntl & (VIP_TV_DAC_CNTL_DASLEEP | VIP_TV_DAC_CNTL_BGSLEEP)) == 0)
+    restoreTimingTables(t , restore);
+  
+  theatre_write(t , 
+		VIP_MASTER_CNTL , 
+		restore->master_cntl |
+		VIP_MASTER_CNTL_TV_ASYNC_RST);
+
+  RTTRACE(("RT_Restore: checkpoint 7\n"));
+  restoreOutputStd(t , restore);
+
+  theatre_write(t , 
+		VIP_MASTER_CNTL , 
+		restore->master_cntl);
+
+  theatre_write(t , VIP_GAIN_LIMIT_SETTINGS , restore->gain_limit_settings);
+  theatre_write(t , VIP_LINEAR_GAIN_SETTINGS , restore->linear_gain_settings);
+
+  theatre_write(t , VIP_TV_DAC_CNTL , restore->tv_dac_cntl);
+
+  RTTRACE(("Leaving RT_Restore\n"));
+}
+
+/**********************************************************************
+ *
+ * RT_Save
+ *
+ * Save state of RT
+ *
+ **********************************************************************/
+
+static
+void
+RT_Save(
+	TheaterOutPtr t,
+	ScrnInfoPtr pScrn,
+	TheaterStatePtr save
+	)
+{
+  unsigned i;
+
+  RTTRACE(("Entering RT_Save\n"));
+
+  if (t->theatre_num >= 0)
+    {
+      theatre_read(t , VIP_CLKOUT_CNTL         , &save->clkout_cntl);
+      theatre_read(t , VIP_CLOCK_SEL_CNTL      , &save->clock_sel_cntl);
+      theatre_read(t , VIP_CRC_CNTL            , &save->crc_cntl);
+      theatre_read(t , VIP_CRT_PLL_CNTL        , &save->crt_pll_cntl);
+      theatre_read(t , VIP_DFRESTART           , &save->dfrestart);
+      theatre_read(t , VIP_DHRESTART           , &save->dhrestart);
+      theatre_read(t , VIP_DVRESTART           , &save->dvrestart);
+      theatre_read(t , VIP_FRAME_LOCK_CNTL     , &save->frame_lock_cntl);
+      theatre_read(t , VIP_GAIN_LIMIT_SETTINGS , &save->gain_limit_settings);
+      theatre_read(t , VIP_HDISP               , &save->hdisp);
+      theatre_read(t , VIP_HSTART              , &save->hstart);
+      theatre_read(t , VIP_HTOTAL              , &save->htotal);
+      theatre_read(t , VIP_HW_DEBUG            , &save->hw_debug);
+      theatre_read(t , VIP_LINEAR_GAIN_SETTINGS, &save->linear_gain_settings);
+      theatre_read(t , VIP_MASTER_CNTL         , &save->master_cntl);
+      theatre_read(t , VIP_MODULATOR_CNTL1     , &save->modulator_cntl1);
+      theatre_read(t , VIP_MODULATOR_CNTL2     , &save->modulator_cntl2);
+      theatre_read(t , VIP_PLL_CNTL0           , &save->pll_cntl0);
+      theatre_read(t , VIP_PLL_TEST_CNTL       , &save->pll_test_cntl);
+      theatre_read(t , VIP_PRE_DAC_MUX_CNTL    , &save->pre_dac_mux_cntl);
+      theatre_read(t , VIP_RGB_CNTL            , &save->rgb_cntl);
+      theatre_read(t , VIP_SYNC_CNTL           , &save->sync_cntl);
+      theatre_read(t , VIP_SYNC_LOCK_CNTL      , &save->sync_lock_cntl);
+      theatre_read(t , VIP_SYNC_SIZE           , &save->sync_size);
+      theatre_read(t , VIP_TIMING_CNTL         , &save->timing_cntl);
+      theatre_read(t , VIP_TVO_DATA_DELAY_A    , &save->tvo_data_delay_a);
+      theatre_read(t , VIP_TVO_DATA_DELAY_B    , &save->tvo_data_delay_b);
+      theatre_read(t , VIP_TVO_SYNC_PAT_EXPECT , &save->tvo_sync_pat_expect);
+      theatre_read(t , VIP_TVO_SYNC_THRESHOLD  , &save->tvo_sync_threshold);
+      theatre_read(t , VIP_TV_DAC_CNTL         , &save->tv_dac_cntl);
+      theatre_read(t , VIP_TV_PLL_CNTL         , &save->tv_pll_cntl);
+      theatre_read(t , VIP_TV_PLL_FINE_CNTL    , &save->tv_pll_fine_cntl);
+      theatre_read(t , VIP_UPSAMP_AND_GAIN_CNTL, &save->upsamp_and_gain_cntl);
+      theatre_read(t , VIP_VDISP               , &save->vdisp);
+      theatre_read(t , VIP_VFTOTAL             , &save->vftotal);
+      theatre_read(t , VIP_VSCALER_CNTL1       , &save->vscaler_cntl1);
+      theatre_read(t , VIP_VSCALER_CNTL2       , &save->vscaler_cntl2);
+      theatre_read(t , VIP_VTOTAL              , &save->vtotal);
+      theatre_read(t , VIP_Y_FALL_CNTL         , &save->y_fall_cntl);
+      theatre_read(t , VIP_Y_RISE_CNTL         , &save->y_rise_cntl);
+      theatre_read(t , VIP_Y_SAW_TOOTH_CNTL    , &save->y_saw_tooth_cntl);
+
+      for (i = 0; i < N_UPSAMPLER_COEFFS; i++)
+	theatre_read(t , VIP_UPSAMP_COEFF0_0 + i * 4 , &save->upsamp_coeffs[ i ]);
+
+      /*
+       * Read H/V code timing tables (current tables only are saved)
+       * This step is skipped when tv output is disabled in current RT state
+       * (see RT_Restore)
+       */
+      if ((save->tv_dac_cntl & (VIP_TV_DAC_CNTL_DASLEEP | VIP_TV_DAC_CNTL_BGSLEEP)) == 0)
+	saveTimingTables(t , save);
+    }
+  else
+    {
+      /*
+       * ERT
+       */
+      ert_read(t , TV_CRC_CNTL             , &save->crc_cntl);
+      ert_read(t , TV_FRESTART             , &save->dfrestart);
+      ert_read(t , TV_HRESTART             , &save->dhrestart);
+      ert_read(t , TV_VRESTART             , &save->dvrestart);
+      ert_read(t , TV_GAIN_LIMIT_SETTINGS  , &save->gain_limit_settings);
+      ert_read(t , TV_HDISP                , &save->hdisp);
+      ert_read(t , TV_HSTART               , &save->hstart);
+      ert_read(t , TV_HTOTAL               , &save->htotal);
+      ert_read(t , TV_LINEAR_GAIN_SETTINGS , &save->linear_gain_settings);
+      ert_read(t , TV_MASTER_CNTL          , &save->master_cntl);
+      ert_read(t , TV_RGB_CNTL             , &save->rgb_cntl);
+      ert_read(t , TV_MODULATOR_CNTL1      , &save->modulator_cntl1);
+      ert_read(t , TV_MODULATOR_CNTL2      , &save->modulator_cntl2);
+      ert_read(t , TV_PRE_DAC_MUX_CNTL     , &save->pre_dac_mux_cntl);
+      ert_read(t , TV_SYNC_CNTL            , &save->sync_cntl);
+      ert_read(t , TV_TIMING_CNTL          , &save->timing_cntl);
+      ert_read(t , TV_DAC_CNTL             , &save->tv_dac_cntl);
+      ert_read(t , TV_UPSAMP_AND_GAIN_CNTL , &save->upsamp_and_gain_cntl);
+      ert_read(t , TV_VDISP                , &save->vdisp);
+      ert_read(t , TV_FTOTAL               , &save->vftotal);
+      ert_read(t , TV_VSCALER_CNTL1        , &save->vscaler_cntl1);
+      ert_read(t , TV_VSCALER_CNTL2        , &save->vscaler_cntl2);
+      ert_read(t , TV_VTOTAL               , &save->vtotal);
+      ert_read(t , TV_Y_FALL_CNTL          , &save->y_fall_cntl);
+      ert_read(t , TV_Y_RISE_CNTL          , &save->y_rise_cntl);
+      ert_read(t , TV_Y_SAWTOOTH_CNTL      , &save->y_saw_tooth_cntl);
+
+      ert_read(t , RADEON_DISP_MERGE_CNTL  , &save->disp_merge_cntl);
+
+      save->tv_pll_cntl = INPLL(pScrn , TV_PLL_CNTL);
+      
+      /*
+       * Read H/V code timing tables (current tables only are saved)
+       * This step is skipped when tv output is disabled in current RT state
+       * (see RT_Restore)
+       */
+      if (ERT_IsOn(save->tv_dac_cntl))
+	saveTimingTables(t , save);
+    }
+
+
+  RTTRACE(("RT_Save returning\n"));
+}
+
+/**********************************************************************
+ *
+ * computeRestarts
+ *
+ * Compute F,V,H restarts from default restart position and 
+ * hPos & vPos
+ * Return TRUE when code timing table was changed
+ *
+ **********************************************************************/
+
+static
+Bool
+computeRestarts(
+		const ModeConstants *constPtr,
+		TVStd tvStd,
+		int hPos,
+		int vPos,
+		int hSize,
+		TheaterStatePtr save
+		)
+{
+  int restart;
+  const TVConstants *pTvStd = &tvStdConsts[ tvStd ];
+  unsigned hTotal;
+  unsigned vTotal;
+  unsigned fTotal;
+  int vOffset;
+  int hOffset;
+  TimingTableEl p1;
+  TimingTableEl p2;
+  Bool hChanged;
+  CARD16 hInc;
+
+  hTotal = constPtr->horTotal;
+  vTotal = constPtr->verTotal;
+  fTotal = pTvStd->vftotal + 1;
+
+  /*
+   * Adjust positions 1&2 in hor. code timing table
+   */
+  hOffset = hPos * H_POS_UNIT;
+
+  p1 = constPtr->horTimingTable[ H_TABLE_POS1 ];
+  p2 = constPtr->horTimingTable[ H_TABLE_POS2 ];
+
+  p1 = (TimingTableEl)((int)p1 + hOffset);
+  p2 = (TimingTableEl)((int)p2 - hOffset);
+
+  hChanged = (p1 != save->h_code_timing[ H_TABLE_POS1 ] || 
+	      p2 != save->h_code_timing[ H_TABLE_POS2 ]);
+
+  save->h_code_timing[ H_TABLE_POS1 ] = p1;
+  save->h_code_timing[ H_TABLE_POS2 ] = p2;
+
+  /*
+   * Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels)
+   */
+  hOffset = (hOffset * (int)(constPtr->pixToTV)) / 1000;
+
+  /*
+   * Adjust restart
+   */
+  restart = constPtr->defRestart;
+ 
+  /*
+   * Convert vPos TV lines to n. of CRTC pixels
+   * Be verrrrry careful when mixing signed & unsigned values in C..
+   */
+  vOffset = ((int)(vTotal * hTotal) * 2 * vPos) / (int)(pTvStd->linesFrame);
+
+  restart -= vOffset + hOffset;
+
+  RTTRACE(("computeRestarts: def = %u, h = %d , v = %d , p1=%04x , p2=%04x , restart = %d\n" , constPtr->defRestart , hPos , vPos , p1 , p2 , restart));
+
+  save->dhrestart = restart % hTotal;
+  restart /= hTotal;
+  save->dvrestart = restart % vTotal;
+  restart /= vTotal;
+  save->dfrestart = restart % fTotal;
+
+  RTTRACE(("computeRestarts: F/H/V=%u,%u,%u\n" , save->dfrestart , save->dvrestart , save->dhrestart));
+
+  /*
+   * Compute H_INC from hSize
+   */
+  hInc = (CARD16)((int)(constPtr->horResolution * 4096 * pTvStd->tvClockT) / 
+		  (hSize * (int)(pTvStd->hSizeUnit) + (int)(pTvStd->zeroHSize)));
+  save->timing_cntl = (save->timing_cntl & ~VIP_TIMING_CNTL_H_INC) |
+    ((CARD32)hInc << VIP_TIMING_CNTL_H_INC_SHIFT);
+
+  RTTRACE(("computeRestarts: hSize=%d,hInc=%u\n" , hSize , hInc));
+
+  return hChanged;
+}
+
+/**********************************************************************
+ *
+ * RT_Init
+ *
+ * Define RT state for a given standard/resolution combination
+ *
+ **********************************************************************/
+
+static
+void
+RT_Init(
+	const ModeConstants *constPtr,
+	TVStd tvStd,
+	Bool isErt,
+	Bool enable,
+	int hPos,
+	int vPos,
+	int hSize,
+	TheaterStatePtr save
+	)
+{
+  unsigned i;
+  CARD32 tmp;
+  const TVConstants *pTvStd = &tvStdConsts[ tvStd ];
+
+  save->clkout_cntl = VIP_CLKOUT_CNTL_INI;
+
+  save->clock_sel_cntl = VIP_CLOCK_SEL_CNTL_INI |  
+    (constPtr->crtcPLL_byteClkDiv << VIP_CLOCK_SEL_CNTL_BYTCLK_SHIFT) |
+    (constPtr->byteClkDelay << VIP_CLOCK_SEL_CNTL_BYTCLKD_SHIFT);
+
+  save->crc_cntl = 0;
+
+  tmp = ((CARD32)constPtr->crtcPLL_M << VIP_CRT_PLL_CNTL_M_SHIFT) |
+    (((CARD32)constPtr->crtcPLL_N & VIP_CRT_PLL_CNTL_NLO) << VIP_CRT_PLL_CNTL_NLO_SHIFT) |
+    (((CARD32)constPtr->crtcPLL_N & VIP_CRT_PLL_CNTL_NHI) << VIP_CRT_PLL_CNTL_NHI_SHIFT);
+  if (constPtr->crtcPLL_divBy2)
+    tmp |= VIP_CRT_PLL_CNTL_CLKBY2;
+  save->crt_pll_cntl = tmp;
+
+  save->frame_lock_cntl = VIP_FRAME_LOCK_CNTL_INI;
+
+  save->gain_limit_settings = VIP_GAIN_LIMIT_SETTINGS_INI;
+
+  save->hdisp = constPtr->horResolution - 1;
+  save->hstart = constPtr->horStart;
+  save->htotal = constPtr->horTotal - 1;
+
+  save->hw_debug = VIP_HW_DEBUG_INI;
+
+  save->linear_gain_settings = VIP_LINEAR_GAIN_SETTINGS_INI;
+
+  /*
+   * TEST   TEST   TEST   TEST   TEST   TEST   TEST   TEST   TEST   
+   */
+  if (isErt)
+    save->master_cntl = enable ? TV_MASTER_CNTL_ON_INI : TV_MASTER_CNTL_OFF_INI;
+  else
+    save->master_cntl = enable ? VIP_MASTER_CNTL_ON_INI : VIP_MASTER_CNTL_OFF_INI;
+
+  save->modulator_cntl1 = pTvStd->modulatorCntl1;
+  save->modulator_cntl2 = pTvStd->modulatorCntl2;
+
+  save->pll_cntl0 = VIP_PLL_CNTL0_INI;
+  save->pll_test_cntl = VIP_PLL_TEST_CNTL_INI;
+
+  save->pre_dac_mux_cntl = VIP_PRE_DAC_MUX_CNTL_INI;
+
+  if (isErt)
+    save->rgb_cntl = TV_RGB_CNTL_INI;
+  else
+    /*
+     * Instruct RT to accept either 565 or 888 packed pixels
+     */
+    save->rgb_cntl = constPtr->use888RGB ? VIP_RGB_CNTL_RGB_IS_888_PACK : 0;
+
+  save->sync_cntl = VIP_SYNC_CNTL_INI;
+
+  save->sync_lock_cntl = VIP_SYNC_LOCK_CNTL_INI;
+
+  save->sync_size = constPtr->horResolution + 8;
+  
+  tmp = (constPtr->vScalerCntl1 >> VIP_VSCALER_CNTL1_UV_INC_SHIFT) & VIP_VSCALER_CNTL1_UV_INC;
+  tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
+  tmp = (tmp << VIP_TIMING_CNTL_UV_OUT_POST_SCALE_SHIFT) | 
+    VIP_TIMING_CNTL_INI;
+  save->timing_cntl = tmp;
+
+  save->tvo_data_delay_a = constPtr->tvoDataDelayA;
+  save->tvo_data_delay_b = constPtr->tvoDataDelayB;
+
+  save->tvo_sync_pat_expect = VIP_TVO_SYNC_PAT_EXPECT_INI;
+
+  if (constPtr->use888RGB)
+    save->tvo_sync_threshold = constPtr->horResolution + constPtr->horResolution / 2;
+  else
+    save->tvo_sync_threshold = constPtr->horResolution;
+
+  if (isErt)
+    {
+      if (enable)
+	save->tv_dac_cntl = pTvStd->ert_tvDAC_Cntl;
+      else
+	save->tv_dac_cntl = (pTvStd->ert_tvDAC_Cntl & ~(TV_DAC_CNTL_NBLANK | TV_DAC_CNTL_NHOLD)) |
+	  (TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | TV_DAC_CNTL_BDACPD);
+    }
+  else
+    {
+      if (enable)
+	save->tv_dac_cntl = pTvStd->vip_tvDAC_Cntl;
+      else
+	save->tv_dac_cntl = (pTvStd->vip_tvDAC_Cntl & ~VIP_TV_DAC_CNTL_NBLANK) | 
+	  (VIP_TV_DAC_CNTL_DASLEEP | VIP_TV_DAC_CNTL_BGSLEEP);
+    }
+
+  tmp = ((CARD32)(pTvStd->tvPLL_M) << VIP_TV_PLL_CNTL_M_SHIFT) |
+    (((CARD32)(pTvStd->tvPLL_N) & VIP_TV_PLL_CNTL_NLO) << VIP_TV_PLL_CNTL_NLO_SHIFT) |
+    (((CARD32)(pTvStd->tvPLL_N) & VIP_TV_PLL_CNTL_NHI) << VIP_TV_PLL_CNTL_NHI_SHIFT) |
+    ((CARD32)(pTvStd->tvPLL_postDiv) << VIP_TV_PLL_CNTL_P_SHIFT);
+  save->tv_pll_cntl = tmp;
+  save->tv_pll_fine_cntl = TV_PLL_FINE_INI;
+
+  save->upsamp_and_gain_cntl = VIP_UPSAMP_AND_GAIN_CNTL_INI;
+
+  memcpy(&save->upsamp_coeffs[ 0 ] , upsamplerCoeffs , sizeof(save->upsamp_coeffs));
+
+  save->uv_adr = VIP_UV_ADR_INI;
+
+  save->vdisp = constPtr->verResolution - 1;
+  save->vftotal = pTvStd->vftotal;
+
+  save->vscaler_cntl1 = constPtr->vScalerCntl1;
+  if (isErt)
+    save->vscaler_cntl1 |= TV_VSCALER_CNTL1_RESTART_FIELD;
+  save->vscaler_cntl2 = VIP_VSCALER_CNTL2_INI;
+
+  save->vtotal = constPtr->verTotal - 1;
+
+  save->y_fall_cntl = VIP_Y_FALL_CNTL_INI;
+  save->y_rise_cntl = constPtr->yRiseCntl;
+  save->y_saw_tooth_cntl = constPtr->ySawtoothCntl;
+
+  save->disp_merge_cntl = RADEON_DISP_MERGE_CNTL_INI;
+
+  for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++)
+    {
+      if ((save->h_code_timing[ i ] = constPtr->horTimingTable[ i ]) == 0)
+	break;
+    }
+
+  for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++)
+    {
+      if ((save->v_code_timing[ i ] = constPtr->verTimingTable[ i ]) == 0)
+	break;
+    }
+
+  /*
+   * This must be called AFTER loading timing tables as they are modified by this function
+   */
+  computeRestarts(constPtr , tvStd , hPos , vPos , hSize , save);
+}
+
+/**********************************************************************
+ *
+ * RT_InitCRTC
+ *
+ **********************************************************************/
+static
+void
+RT_InitCRTC(
+	    const ModeConstants *constPtr,
+	    Bool isErt,
+	    RADEONSavePtr save
+	    )
+{
+  save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
+    (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
+
+  save->crtc_h_sync_strt_wid = (save->crtc_h_sync_strt_wid & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) |
+    (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
+    (constPtr->horSyncStart & 7);
+
+  save->crtc_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
+    ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
+
+  save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) |
+    ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
+
+  save->htotal_cntl = ((constPtr->horTotal & 7) << RADEON_HTOTAL_CNTL_HTOT_PIX_SLIP_SHIFT) | RADEON_HTOTAL_CNTL_HTOT_CNTL_VGA_EN;
+
+  if (isErt)
+    {
+      unsigned postDiv;
+
+      save->ppll_ref_div = constPtr->crtcPLL_M;
+
+      switch (constPtr->crtcPLL_postDiv)
+	{
+	case 1:
+	  postDiv = 0;
+	  break;
+
+	case 2:
+	  postDiv = 1;
+	  break;
+
+	case 3:
+	  postDiv = 4;
+	  break;
+
+	case 4:
+	  postDiv = 2;
+	  break;
+
+	case 6:
+	  postDiv = 6;
+	  break;
+
+	case 8:
+	  postDiv = 3;
+	  break;
+
+	case 12:
+	  postDiv = 7;
+	  break;
+
+	case 16:
+	default:
+	  postDiv = 5;
+	  break;
+	}
+
+      save->ppll_div_3 = (constPtr->crtcPLL_N << RADEON_PPLL_FB3_DIV_SHIFT) | 
+	(postDiv << RADEON_PPLL_POST3_DIV_SHIFT);
+
+      save->vclk_ecp_cntl &= ~RADEON_VCLK_SRC_SEL_MASK;
+      save->vclk_ecp_cntl |= RADEON_VCLK_SRC_SEL_PPLLCLK;
+    }
+  else
+    {
+      save->ppll_div_3 &= ~RADEON_PPLL_POST3_DIV_MASK;
+      save->ppll_div_3 |= (constPtr->use888RGB ? RADEON_PPLL_POST3_DIV_BY_3 : RADEON_PPLL_POST3_DIV_BY_2);
+
+      /*
+       * Set Radeon to be clocked from RT
+       */
+      save->vclk_ecp_cntl &= ~RADEON_VCLK_SRC_SEL_MASK;
+      save->vclk_ecp_cntl |= RADEON_VCLK_SRC_SEL_BYTECLK;
+
+      save->vclk_ecp_cntl &= ~RADEON_VCLK_ECP_CNTL_BYTECLK_POSTDIV;
+      save->vclk_ecp_cntl |= RADEON_VCLK_ECP_CNTL_BYTECLK_NODIV;
+
+      /*
+       * Instruct Radeon to output either 565 or 888 packed pixels
+       */
+      save->disp_output_cntl &= 
+	~(RADEON_DISP_TV_SOURCE |
+	  RADEON_DISP_TV_MODE_MASK |
+	  RADEON_DISP_TV_CBB_CRR_DITH_EN |
+	  RADEON_DISP_TV_BIT_WIDTH |
+	  RADEON_DISP_TV_SYNC_MODE_MASK |
+	  RADEON_DISP_TV_SYNC_COLOR_MASK);
+      save->disp_output_cntl |= (constPtr->use888RGB ? 
+				 RADEON_DISP_TV_YG_DITH_EN | RADEON_DISP_TV_MODE_888 : 
+				 RADEON_DISP_TV_YG_DITH_EN | RADEON_DISP_TV_MODE_565);
+
+      save->crtc_ext_cntl |= RADEON_CRTC_VGA_XOVERSCAN;
+      save->dac_cntl |= RADEON_DAC_CNTL_DAC_TVO_EN;
+    }
+}
+
+/**********************************************************************
+ *
+ * ERTAutoDetect
+ *
+ **********************************************************************/
+static
+Bool
+ERTAutoDetect(
+	      ScrnInfoPtr pScrn
+	      )
+{
+  RADEONInfoPtr  info       = RADEONPTR(pScrn);
+  unsigned char *RADEONMMIO = info->MMIO;
+  CARD32 saveReg = INREG(TV_LINEAR_GAIN_SETTINGS);
+  Bool detected = FALSE;
+
+  /*
+   * Ultra-dumb way of detecting an ERT: check that a register is present 
+   * @ TV_LINEAR_GAIN_SETTINGS (this is probably one of the most harmless
+   * register to touch)
+   */
+  OUTREG(TV_LINEAR_GAIN_SETTINGS , 0x15500aa);
+
+  if (INREG(TV_LINEAR_GAIN_SETTINGS) == 0x15500aa)
+    {
+      OUTREG(TV_LINEAR_GAIN_SETTINGS , 0x0aa0155);
+      if (INREG(TV_LINEAR_GAIN_SETTINGS) == 0x0aa0155)
+	detected = TRUE;
+    }
+
+  OUTREG(TV_LINEAR_GAIN_SETTINGS , saveReg);
+  
+  return detected;
+}
+
+/**********************************************************************
+ *
+ * detectTheaterOut
+ *
+ * Detect presence of a RT chip
+ *
+ **********************************************************************/
+
+TheaterOutPtr 
+detectTheaterOut(
+		 ScrnInfoPtr pScrn,
+		 Bool forceVIP,
+		GENERIC_BUS_Ptr b
+		 )
+{
+  RADEONInfoPtr info = RADEONPTR(pScrn);
+  //GENERIC_BUS_Ptr b = info->VIP;
+  TheaterOutPtr t;  
+  int i;
+  CARD32 val;
+  char s[20];
+   
+if (b != NULL)
+{
+//	RTTRACE(("0711:OK\n"));
+}
+else
+{
+//	RTTRACE(("0712:FAILED\n"));
+}
+
+
+  b->ioctl(b , GB_IOCTL_GET_TYPE , 20 , s);
+
+//RTTRACE(("0713: %s vs %s\n",VIP_TYPE,s));
+
+  if (strcmp(VIP_TYPE , s))
+    {
+      xf86DrvMsg(b->scrnIndex , X_ERROR , "detectTheaterOut must be called with bus of type \"%s\", not \"%s\"\n",
+		 VIP_TYPE , s);
+      return NULL;
+    }
+   
+  t = xcalloc(1 , sizeof(TheaterOutRec));
+  t->theatre_num = -1;
+  t->MMIO = info->MMIO;
+  t->VIP = b;
+
+  if (!forceVIP && ERTAutoDetect(pScrn))
+    xf86DrvMsg(b->scrnIndex , X_INFO , "Embedded Rage Theater detected\n");
+  else
+    {
+      //
+      // Is this really needed?
+      // 
+      b->read(b , VIP_VIP_VENDOR_DEVICE_ID , 4 , (CARD8*)&val);
+
+      for (i = 0; i < 4; i++)
+	{
+//	RTTRACE(("0713X\n"));
+	  if(b->read(b , ((i & 0x03) << 14) | VIP_VIP_VENDOR_DEVICE_ID , 4 , (CARD8*)&val))
+	    {
+	      if (val)
+		{
+		xf86DrvMsg(b->scrnIndex , X_INFO , "Device %d on VIP bus ids as 0x%08x\n" , i , val);
+//		RTTRACE(("07130\n"));
+		}
+	      if (t->theatre_num >= 0)
+		{
+//		RTTRACE(("07131\n"));
+		continue;	// already found one instance
+		}
+	      if (val == RT100_ATI_ID)
+		{
+//		RTTRACE(("07132\n"));
+		t->theatre_num = i;
+		}
+	    } 
+	  else 
+	    {
+//		RTTRACE(("0713Y\n"));
+	      xf86DrvMsg(b->scrnIndex , X_INFO , "No response from device %d on VIP bus\n" , i);	
+	    }
+	}
+//		RTTRACE(("0713Z\n"));
+      if (t->theatre_num >= 0)
+	{
+//      RTTRACE(("0714:OK\n"));
+	  xf86DrvMsg(b->scrnIndex , X_INFO , 
+		     "Detected Rage Theatre as device %d on VIP bus\n" , t->theatre_num);
+	  theatre_read(t , VIP_VIP_REVISION_ID , &val);
+	  xf86DrvMsg(b->scrnIndex , X_INFO , "Detected Rage Theatre revision %8.8X\n" , val);
+	}
+      else
+	{
+//	  RTTRACE(("0714:FAILED\n"));
+	  xfree(t);
+	  return NULL;
+	}
+    }
+    
+  return t;
+}
+
+/**********************************************************************
+ *
+ * initTheaterOut
+ *
+ * Initialization of module
+ *
+ * 's' should be the value of TV_Output option (i.e. the initial TV
+ * standard)
+ *
+ **********************************************************************/
+
+void
+initTheaterOut(
+	       TheaterOutPtr t,
+	       const char *s
+	       )
+{
+  RTTRACE(("Entering initTheaterOut, s = %s\n" , s));
+  /*
+   * TEST   TEST   TEST   TEST   TEST   TEST   TEST   TEST   TEST   
+   */
+  if (xf86NameCmp(s , "NTSC") == 0)
+    t->standard = TV_STD_NTSC;
+  else if (xf86NameCmp(s , "PAL") == 0)
+    t->standard = TV_STD_PAL;
+  else if (xf86NameCmp(s , "PAL-M") == 0)
+    t->standard = TV_STD_PAL_M;
+  else if (xf86NameCmp(s , "PAL-60") == 0)
+    t->standard = TV_STD_PAL_60;
+  else if (xf86NameCmp(s , "NTSC-J") == 0)
+    t->standard = TV_STD_NTSC_J;
+  else if (xf86NameCmp(s , "PAL-CN") == 0)
+    t->standard = TV_STD_PAL_CN;
+  else if (xf86NameCmp(s , "PAL-N") == 0)
+    t->standard = TV_STD_PAL_N;
+  else
+    {
+      xf86DrvMsg(0 , X_WARNING , "Unrecognized TV standard in TVOutput option (%s), TV output is disabled\n" , s);
+      t->standard = TV_STD_KEEP_OFF;
+    }
+  t->compatibleMode = FALSE;
+
+  t->hPos = 0;
+  t->vPos = 0;
+  t->hSize = 0;
+}
+
+/**********************************************************************
+ *
+ * theaterOutSave
+ *
+ * Save current state of RT as initial state (the one that is restored
+ * when switching back to text mode)
+ *
+ **********************************************************************/
+
+void
+theaterOutSave(
+	       TheaterOutPtr t,
+	       ScrnInfoPtr pScrn
+	       )
+{
+  RTTRACE(("Entering theaterOutSave\n"));
+  RT_Save(t , pScrn , &t->savedState);
+}
+
+/**********************************************************************
+ *
+ * theaterOutRestore
+ *
+ * Restore state of RT from initial state (the one saved through 
+ * theaterOutSave)
+ *
+ **********************************************************************/
+
+void
+theaterOutRestore(
+		  TheaterOutPtr t,
+		  ScrnInfoPtr pScrn
+		  )
+{
+  RTTRACE(("Entering theaterOutRestore\n"));
+  RT_Restore(t , pScrn , &t->savedState);
+}
+		  
+/**********************************************************************
+ *
+ * theaterOutInit
+ *
+ * Define state for cloning current CRTC mode on TV output
+ * It works in this way:
+ * 1. It checks if resolution in "mode" parameter is one of those 
+ *    allowing tv output
+ * 2. If resolution is OK, define RT state according to resolution and
+ *    and current settings (tv standard etc.)
+ *    If resolution is not ok, define RT state to turn tv output off
+ * 3. If resolution is OK, modify Radeon state to make it correct for 
+ *    tv output (this is needed,e.g., to set vertical frequency to 50/60 Hz)
+ *
+ * Return value is TRUE when mode is OK for cloning on tv and tv output
+ * is enabled, FALSE otherwise
+ *
+ **********************************************************************/
+
+Bool
+theaterOutInit(
+	       TheaterOutPtr t,
+	       DisplayModePtr mode,
+	       RADEONSavePtr save
+	       )
+{
+  const ModeConstants *p;
+  Bool isErt = t->theatre_num < 0;
+
+  RTTRACE(("Entering theaterOutInit: std=%u h=%u v=%u\n" , t->standard , mode->HDisplay , mode->VDisplay));
+
+  t->compatibleMode = FALSE;
+
+  if (t->standard != TV_STD_KEEP_OFF)
+    {
+      /*
+       * Search mode among available ones
+       */
+      for (p = availableModes; p < (availableModes + N_AVAILABLE_MODES); p++)
+	{
+	  if (p->horResolution == mode->HDisplay &&
+	      p->verResolution == mode->VDisplay &&
+	      p->standard == t->standard)
+	    {
+	      /*
+	       * Match found
+	       */
+	      t->compatibleMode = TRUE;
+	      t->currentMode = p;
+
+	      RT_Init(p , t->standard , isErt , TRUE , t->hPos , t->vPos , t->hSize , &t->modeState);
+	      RT_InitCRTC(p , isErt , save);
+
+	      return TRUE;
+	    }
+	}
+    }
+
+  /*
+   * Match not found or tv output disabled
+   * First parameter is dummy when setting for no tv output, so any mode
+   * will do (here first mode in table is passed).
+   */
+  RT_Init(availableModes , TV_STD_NTSC , isErt , FALSE , t->hPos , t->vPos , t->hSize , &t->modeState);
+  return FALSE;
+}
+	       
+/**********************************************************************
+ *
+ * theaterOutRestoreMode
+ *
+ * Set state of RT to the one defined by last call to theaterOutInit
+ *
+ **********************************************************************/
+
+void
+theaterOutRestoreMode(
+		      TheaterOutPtr t,
+		      ScrnInfoPtr pScrn
+		      )
+{
+  RTTRACE(("Entering theaterOutRestoreMode\n"));
+  RT_Restore(t , pScrn , &t->modeState);
+}
+
+/**********************************************************************
+ *
+ * theaterOutSetStandard
+ *
+ * Set TV output standard
+ *
+ * Return value is TRUE when video mode should be set again
+ *
+ **********************************************************************/
+Bool
+theaterOutSetStandard(
+		      TheaterOutPtr t,
+		      TVStd std
+		      )
+{
+  TVStd oldStd = t->standard;
+
+  RTTRACE(("Entering theaterOutSetStandard\n"));
+
+  if (std >= TV_STD_N_STANDARDS)
+    std = TV_STD_KEEP_OFF;
+
+  t->standard = std;
+
+  if (t->compatibleMode)
+    return oldStd != std;
+  else 
+    return std != TV_STD_KEEP_OFF && oldStd == TV_STD_KEEP_OFF;
+}
+		      
+/**********************************************************************
+ *
+ * theaterOutGetStandard
+ *
+ * Get current TV output standard
+ *
+ **********************************************************************/
+TVStd
+theaterOutGetStandard(
+		      TheaterOutPtr t
+		      )
+{
+  return t->standard;
+}
+
+/**********************************************************************
+ *
+ * theaterOutGetCompatMode
+ *
+ * Return whether the current mode is compatible with tv output or not
+ *
+ **********************************************************************/
+Bool
+theaterOutGetCompatMode(
+			TheaterOutPtr t
+			)
+{
+  return t->compatibleMode;
+}
+
+/**********************************************************************
+ *
+ * updateHVPosition
+ *
+ * Set hw registers for a new h/v position & h size
+ *
+ **********************************************************************/
+static
+void
+updateHVPosition(
+		 TheaterOutPtr t
+		 )
+{
+  Bool reloadTable;
+
+  reloadTable = computeRestarts(t->currentMode , t->standard , t->hPos , t->vPos , t->hSize , &t->modeState);
+
+  if (t->theatre_num < 0)
+    {
+      ERT_RestoreRestarts(t , &t->modeState);
+      ert_write(t , TV_TIMING_CNTL , t->modeState.timing_cntl);
+
+      if (reloadTable)
+	{
+	  ert_write(t,
+		    TV_MASTER_CNTL ,
+		    t->modeState.master_cntl | 
+		    VIP_MASTER_CNTL_TV_ASYNC_RST |
+		    VIP_MASTER_CNTL_CRT_ASYNC_RST |
+		    VIP_MASTER_CNTL_RESTART_PHASE_FIX);
+
+	  restoreTimingTables(t , &t->modeState);
+	
+	  ert_write(t , 
+		    TV_MASTER_CNTL , 
+		    t->modeState.master_cntl);
+	}
+    }
+  else
+    {
+      restoreRestarts(t , &t->modeState);
+      theatre_write(t , VIP_TIMING_CNTL , t->modeState.timing_cntl);
+
+      if (reloadTable)
+	{
+	  theatre_write(t , 
+			VIP_MASTER_CNTL , 
+			t->modeState.master_cntl |
+			VIP_MASTER_CNTL_TV_ASYNC_RST |
+			VIP_MASTER_CNTL_CRT_ASYNC_RST);
+
+	  restoreTimingTables(t , &t->modeState);
+	
+	  theatre_write(t , 
+			VIP_MASTER_CNTL , 
+			t->modeState.master_cntl);
+	}
+    }
+}
+
+/**********************************************************************
+ *
+ * theaterOutSetAttr
+ *
+ * Set an attribute
+ *
+ **********************************************************************/
+void
+theaterOutSetAttr(
+		  TheaterOutPtr t,
+		  TheaterOutAttr attr,
+		  int value
+		  )
+{
+  switch (attr)
+    {
+    case THEATER_OUT_HPOS:
+      if (value < -MAX_H_POSITION)
+	t->hPos = -MAX_H_POSITION;
+      else if (value > MAX_H_POSITION)
+	t->hPos = MAX_H_POSITION;
+      else
+	t->hPos = value;
+      break;
+	
+    case THEATER_OUT_VPOS:
+      if (value < -MAX_V_POSITION)
+	t->vPos = -MAX_V_POSITION;
+      else if (value > MAX_V_POSITION)
+	t->vPos = MAX_V_POSITION;
+      else
+	t->vPos = value;
+      break;
+	
+    case THEATER_OUT_HSIZE:
+      if (value < -MAX_H_SIZE)
+	t->hSize = -MAX_H_SIZE;
+      else if (value > MAX_H_SIZE)
+	t->hSize = MAX_H_SIZE;
+      else
+	t->hSize = value;
+      break;
+
+    default:
+      return;
+    }
+
+  if (t->compatibleMode)
+    updateHVPosition(t);
+}
+		      
+/**********************************************************************
+ *
+ * theaterOutGetAttr
+ *
+ * Get an attribute
+ *
+ **********************************************************************/
+int
+theaterOutGetAttr(
+		  TheaterOutPtr t,
+		  TheaterOutAttr attr
+		  )
+{
+  switch (attr)
+    {
+    case THEATER_OUT_HPOS:
+      return t->hPos;
+	
+    case THEATER_OUT_VPOS:
+      return t->vPos;
+	
+    case THEATER_OUT_HSIZE:
+      return t->hSize;
+
+    default:
+      return 0;
+    }
+}
+		      
+/**********************************************************************
+ *
+ * theaterOutGetAttrLimits
+ *
+ * Get limits for an attribute value
+ *
+ **********************************************************************/
+void
+theaterOutGetAttrLimits(
+			TheaterOutPtr t,
+			TheaterOutAttr attr,
+			int *maxValue,
+			int *minValue
+			)
+{
+  switch (attr)
+    {
+    case THEATER_OUT_HPOS:
+      *maxValue = MAX_H_POSITION;
+      *minValue = -MAX_H_POSITION;
+      break;
+	
+    case THEATER_OUT_VPOS:
+      *maxValue = MAX_V_POSITION;
+      *minValue = -MAX_V_POSITION;
+      break;
+	
+    case THEATER_OUT_HSIZE:
+      *maxValue = MAX_H_SIZE;
+      *minValue = -MAX_H_SIZE;
+      break;
+
+    default:
+      break;
+    }
+}
diff -Naur src/theater_out.h.orig src/theater_out.h
--- src/theater_out.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/theater_out.h	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,370 @@
+/*********************************************************************
+ *
+ * $Id: theater_out.h,v 1.1.2.2 2004/01/27 22:50:35 fulivi Exp $
+ *
+ * Interface file for theater_out module
+ *
+ * Copyright (C) 2003 Federico Ulivi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * AUTHORS: F.Ulivi
+ * NOTES:
+ * $Log: theater_out.h,v $
+ * Revision 1.1.2.2  2004/01/27 22:50:35  fulivi
+ * Support for positioning/sizing of image added
+ *
+ * Revision 1.1.2.9  2004/01/18 23:01:12  fede
+ * Functions for get/setting h/v pos/size replaced by
+ * theaterOutSetAttr/theaterOutGetAttr/theaterOutGetAttrLimits
+ * Circular inclusion with radeon.h fixed
+ *
+ * Revision 1.1.2.8  2004/01/11 21:43:32  fede
+ * Fixed problem with definition of TVStd
+ *
+ * Revision 1.1.2.7  2004/01/05 00:09:59  fede
+ * Functions for setting/getting H/V position added
+ * Functions for setting/getting on/off attribute removed
+ *
+ * Revision 1.1.2.1  2003/11/26 19:50:10  fulivi
+ * Support for ERT added
+ *
+ * Revision 1.1.2.6  2003/11/25 20:44:00  fede
+ * TV_STD_KEEP_OFF added
+ *
+ * Revision 1.1.2.5  2003/10/14 18:41:32  fede
+ * forceERT changed to forceVIP
+ *
+ * Revision 1.1.2.4  2003/10/11 12:30:30  fede
+ * Support for ERT added
+ *
+ * Revision 1.1  2003/09/28 21:42:37  fulivi
+ * Theater_out module added
+ *
+ * Revision 1.1.2.3  2003/09/28 15:26:09  fede
+ * Minor aesthetic changes
+ *
+ * Revision 1.1.2.1  2003/08/31 13:36:35  fede
+ * *** empty log message ***
+ *
+ *
+ *********************************************************************/
+
+#ifndef _THEATER_OUT_H
+#define _THEATER_OUT_H
+
+/**********************************************************************
+ *
+ * TheaterOutPtr
+ *
+ * Pointer to TheaterOut struct. Actual definition is in theater_out.c
+ *
+ **********************************************************************/
+typedef struct TheaterOut *TheaterOutPtr;
+
+/**********************************************************************
+ *
+ * TVStd
+ *
+ * Tv standard
+ *
+ **********************************************************************/
+typedef enum
+  {
+    TV_STD_NTSC,
+    TV_STD_PAL,
+    TV_STD_PAL_M,
+    TV_STD_PAL_60,
+    TV_STD_NTSC_J,
+    TV_STD_PAL_CN,
+    TV_STD_PAL_N,
+    TV_STD_KEEP_OFF,
+    TV_STD_N_STANDARDS	/* Must be last */
+  } TVStd;
+
+/**********************************************************************
+ *
+ * TheaterOutAttr
+ *
+ * Integer-valued attributes of this module
+ *
+ **********************************************************************/
+typedef enum
+  {
+    THEATER_OUT_HPOS,	/* Horizontal position */
+    THEATER_OUT_VPOS,	/* Vertical position */
+    THEATER_OUT_HSIZE	/* Horizontal size */
+  } TheaterOutAttr;
+
+#ifndef _RADEON_H_
+#include "radeon.h"
+#endif
+
+/**********************************************************************
+ *
+ * detectTheaterOut
+ *
+ * Detect presence of a RT chip
+ *
+ **********************************************************************/
+
+extern
+TheaterOutPtr 
+detectTheaterOut(
+		 ScrnInfoPtr pScrn,
+		 Bool forceVIP,
+GENERIC_BUS_Ptr b
+		 );
+
+/**********************************************************************
+ *
+ * initTheaterOut
+ *
+ * Initialization of module
+ *
+ * 's' should be the value of TV_Output option (i.e. the initial TV
+ * standard)
+ *
+ **********************************************************************/
+
+extern
+void
+initTheaterOut(
+	       TheaterOutPtr t,
+	       const char *s
+	       );
+
+/**********************************************************************
+ *
+ * theaterOutSave
+ *
+ * Save current state of RT as initial state (the one that is restored
+ * when switching back to text mode)
+ *
+ **********************************************************************/
+
+extern
+void
+theaterOutSave(
+	       TheaterOutPtr t,
+	       ScrnInfoPtr pScrn
+	       );
+
+/**********************************************************************
+ *
+ * theaterOutRestore
+ *
+ * Restore state of RT from initial state (the one saved through 
+ * theaterOutSave)
+ *
+ **********************************************************************/
+
+extern
+void
+theaterOutRestore(
+		  TheaterOutPtr t,
+		  ScrnInfoPtr pScrn
+		  );
+		  
+/**********************************************************************
+ *
+ * theaterOutInit
+ *
+ * Define state for cloning current CRTC mode on TV output
+ * It works in this way:
+ * 1. It checks if resolution in "mode" parameter is one of those 
+ *    allowing tv output
+ * 2. If resolution is OK, define RT state according to resolution and
+ *    and current settings (tv standard etc.)
+ *    If resolution is not ok, define RT state to turn tv output off
+ * 3. If resolution is OK, modify Radeon state to make it correct for 
+ *    tv output (this is needed,e.g., to set vertical frequency to 50/60 Hz)
+ *
+ * Return value is TRUE when mode is OK for cloning on tv and tv output
+ * is enabled, FALSE otherwise
+ *
+ **********************************************************************/
+
+extern
+Bool
+theaterOutInit(
+	       TheaterOutPtr t,
+	       DisplayModePtr mode,
+	       RADEONSavePtr save
+	       );
+	       
+/**********************************************************************
+ *
+ * theaterOutRestoreMode
+ *
+ * Set state of RT to the one defined by last call to theaterOutInit
+ *
+ **********************************************************************/
+
+extern
+void
+theaterOutRestoreMode(
+		      TheaterOutPtr t,
+		      ScrnInfoPtr pScrn
+		      );
+
+/**********************************************************************
+ *
+ * theaterOutSetStandard
+ *
+ * Set TV output standard
+ *
+ * Return value is TRUE when video mode should be set again
+ *
+ **********************************************************************/
+
+extern
+Bool
+theaterOutSetStandard(
+		      TheaterOutPtr t,
+		      TVStd std
+		      );
+		      
+/**********************************************************************
+ *
+ * theaterOutGetStandard
+ *
+ * Get current TV output standard
+ *
+ **********************************************************************/
+extern
+TVStd
+theaterOutGetStandard(
+		      TheaterOutPtr t
+		      );
+
+/**********************************************************************
+ *
+ * theaterOutGetCompatMode
+ *
+ * Return whether the current mode is compatible with tv output or not
+ *
+ **********************************************************************/
+extern
+Bool
+theaterOutGetCompatMode(
+			TheaterOutPtr t
+			);
+
+/**********************************************************************
+ *
+ * theaterOutSetAttr
+ *
+ * Set an attribute
+ *
+ **********************************************************************/
+extern
+void
+theaterOutSetAttr(
+		  TheaterOutPtr t,
+		  TheaterOutAttr attr,
+		  int value
+		  );
+
+/**********************************************************************
+ *
+ * theaterOutGetAttr
+ *
+ * Get an attribute
+ *
+ **********************************************************************/
+extern
+int
+theaterOutGetAttr(
+		  TheaterOutPtr t,
+		  TheaterOutAttr attr
+		  );
+
+/**********************************************************************
+ *
+ * theaterOutGetAttrLimits
+ *
+ * Get limits for an attribute value
+ *
+ **********************************************************************/
+extern
+void
+theaterOutGetAttrLimits(
+			TheaterOutPtr t,
+			TheaterOutAttr attr,
+			int *maxValue,
+			int *minValue
+			);
+
+/**********************************************************************
+ *
+ * THEATER_OUT_SYMBOLS
+ *
+ * Symbol list for module loading
+ *
+ **********************************************************************/
+
+#define THEATER_OUT_SYMBOLS	"detectTheaterOut", \
+				"initTheaterOut", \
+				"theaterOutSave", \
+				"theaterOutRestore", \
+				"theaterOutInit", \
+				"theaterOutRestoreMode", \
+				"theaterOutSetStandard", \
+				"theaterOutGetStandard", \
+				"theaterOutGetCompatMode", \
+				"theaterOutSetAttr", \
+				"theaterOutGetAttr", \
+				"theaterOutGetAttrLimits"
+
+/**********************************************************************
+ *
+ * External access to module functions
+ *
+ **********************************************************************/
+
+#ifdef XFree86LOADER
+
+#define xf86_detectTheaterOut	((TheaterOutPtr (*)(ScrnInfoPtr , Bool,GENERIC_BUS_Ptr))LoaderSymbol("detectTheaterOut"))
+#define xf86_initTheaterOut	((void (*)(TheaterOutPtr , const char*))LoaderSymbol("initTheaterOut"))
+#define xf86_theaterOutSave	((void (*)(TheaterOutPtr , ScrnInfoPtr))LoaderSymbol("theaterOutSave"))
+#define xf86_theaterOutRestore	((void (*)(TheaterOutPtr , ScrnInfoPtr))LoaderSymbol("theaterOutRestore"))
+#define xf86_theaterOutInit	((Bool (*)(TheaterOutPtr , DisplayModePtr , RADEONSavePtr))LoaderSymbol("theaterOutInit"))
+#define xf86_theaterOutRestoreMode	((void (*)(TheaterOutPtr , ScrnInfoPtr))LoaderSymbol("theaterOutRestoreMode"))
+#define xf86_theaterOutSetStandard	((Bool (*)(TheaterOutPtr , TVStd))LoaderSymbol("theaterOutSetStandard"))
+#define xf86_theaterOutGetStandard	((TVStd (*)(TheaterOutPtr))LoaderSymbol("theaterOutGetStandard"))
+#define xf86_theaterOutGetCompatMode	((Bool (*)(TheaterOutPtr))LoaderSymbol("theaterOutGetCompatMode"))
+#define xf86_theaterOutSetAttr	((void (*)(TheaterOutPtr , TheaterOutAttr , int))LoaderSymbol("theaterOutSetAttr"))
+#define xf86_theaterOutGetAttr	((int (*)(TheaterOutPtr , TheaterOutAttr))LoaderSymbol("theaterOutGetAttr"))
+#define xf86_theaterOutGetAttrLimits	((void (*)(TheaterOutPtr , TheaterOutAttr , int * , int *))LoaderSymbol("theaterOutGetAttrLimits"))
+
+#else
+
+#define xf86_detectTheaterOut	detectTheaterOut
+#define xf86_initTheaterOut	initTheaterOut
+#define xf86_theaterOutSave	theaterOutSave
+#define xf86_theaterOutRestore	theaterOutRestore
+#define xf86_theaterOutInit	theaterOutInit
+#define xf86_theaterOutRestoreMode	theaterOutRestoreMode
+#define xf86_theaterOutSetStandard	theaterOutSetStandard
+#define xf86_theaterOutGetStandard	theaterOutGetStandard
+#define xf86_theaterOutGetCompatMode	theaterOutGetCompatMode
+#define xf86_theaterOutSetAttr	theaterOutSetAttr	
+#define xf86_theaterOutGetAttr	theaterOutGetAttr	
+#define xf86_theaterOutGetAttrLimits	theaterOutGetAttrLimits
+
+#endif	/* XFree86LOADER */
+
+#endif  /* _THEATER_OUT_H */
diff -Naur src/theater_out_module.c.orig src/theater_out_module.c
--- src/theater_out_module.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/theater_out_module.c	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,45 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Module.h"
+
+static MODULESETUPPROTO(theaterOutSetup);
+
+static 
+XF86ModuleVersionInfo 
+theaterVersRec =
+{
+  "theater_out",	/* modname */
+  MODULEVENDORSTRING,	/* vendor */
+  MODINFOSTRING1,	/* _modinfo1_ */
+  MODINFOSTRING2,	/* _modinfo2_ */
+  XORG_VERSION_CURRENT,	/* xf86version */
+  1,			/* majorversion */
+  0,			/* minorversion */
+  0,			/* patchlevel */
+  ABI_CLASS_VIDEODRV,	/* abiclass */
+  ABI_VIDEODRV_VERSION,	/* abiversion */
+  MOD_CLASS_NONE,	/* moduleclass */
+  { 0 , 0 , 0 , 0 }	/* checksum */
+};
+ 
+_X_EXPORT XF86ModuleData 
+theater_outModuleData = 
+  { 
+    &theaterVersRec, 
+    theaterOutSetup, 
+    NULL 
+  }; 
+
+static
+pointer
+theaterOutSetup(
+		pointer module, 
+		pointer opts, 
+		int *errmaj, 
+		int *errmin
+		)
+{
+  return (pointer)1;
+}
diff -Naur src/tvo_set/tvo_set.c.orig src/tvo_set/tvo_set.c
--- src/tvo_set/tvo_set.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ src/tvo_set/tvo_set.c	2006-09-06 00:32:03.000000000 +0200
@@ -0,0 +1,472 @@
+/*********************************************************************
+ *
+ * $Id: tvo_set.c,v 1.1.2.1 2004/01/27 22:55:40 fulivi Exp $
+ *
+ * Main (and only) module of tvo_set utility. 
+ * The purpose of this utility is to set various parameters of
+ * tv output module.
+ *
+ * Copyright (C) 2004 Federico Ulivi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * AUTHORS: F.Ulivi
+ * NOTES:
+ * $Log: tvo_set.c,v $
+ * Revision 1.1.2.1  2004/01/27 22:55:40  fulivi
+ * Initial release
+ *
+ * Revision 1.1.2.2  2004/01/25 23:07:47  fede
+ * GPL notice added
+ *
+ * Revision 1.1.2.1  2004/01/25 15:09:42  fede
+ * First version
+ *
+ *
+ *********************************************************************/
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+/**********************************************************************
+ *
+ * program_name
+ *
+ **********************************************************************/
+static
+const char *program_name;
+
+/**********************************************************************
+ *
+ * Action
+ *
+ **********************************************************************/
+typedef enum
+  {
+    ACT_FULL_DUMP,
+    ACT_SET,
+    ACT_INC,
+    ACT_DEC,
+    ACT_ZERO
+  } Action;
+
+/**********************************************************************
+ *
+ * attrNames / attrData
+ *
+ **********************************************************************/
+typedef struct
+{
+  Atom atom;
+  int minValue;
+  int maxValue;
+} AttrData;
+
+typedef struct
+{
+  char* extName;
+  char* attrName;
+  char* description;
+} AttrName;
+
+static
+const AttrName attrNames[] =
+  {
+    { "hpos" , "XV_TVO_HPOS" , "Horizontal position" },
+    { "vpos" , "XV_TVO_VPOS" , "Vertical position" },
+    { "hsize" , "XV_TVO_HSIZE" , "Horizontal size" },
+    { "std" , "XV_TVO_STANDARD" , "TV Standard" }
+  };
+
+#define N_ATTRS (sizeof(attrNames) / sizeof(attrNames[ 0 ]))
+/*
+ * Index of TV standard attribute
+ */
+#define STD_ATTR        3
+
+static
+AttrData attrData[ N_ATTRS ];
+
+/**********************************************************************
+ *
+ * stdNames
+ *
+ **********************************************************************/
+static
+const char *stdNames[] = 
+  {
+    "NTSC",
+    "PAL",
+    "PAL-M",
+    "PAL-60",
+    "NTSC-J",
+    "PAL-CN",
+    "PAL-N",
+    "OFF"
+  };
+#define N_STDS  (sizeof(stdNames) / sizeof(stdNames[ 0 ]))
+
+/**********************************************************************
+ *
+ * scanAttributes
+ *
+ **********************************************************************/
+static
+Bool
+subScanAttributes(
+                  Display *dpy,
+                  XvAttribute *pAttributes,
+                  int nAttributes
+                  )
+{
+  unsigned i;
+  unsigned j;
+  Atom theAtom;
+
+  for (i = 0; i < N_ATTRS; i++)
+    {
+      const char* name = attrNames[ i ].attrName;
+
+      for (j = 0; j < nAttributes; j++)
+        {
+          if (strcmp(name , pAttributes[ j ].name) == 0)
+            {
+              attrData[ i ].minValue = pAttributes[ j ].min_value;
+              attrData[ i ].maxValue = pAttributes[ j ].max_value;
+              if ((pAttributes[ j ].flags & (XvGettable | XvSettable)) != (XvGettable | XvSettable))
+                return False;
+              
+              theAtom = XInternAtom(dpy , name , True);
+              if (theAtom == None)
+                return False;
+
+              attrData[ i ].atom = theAtom;
+
+              break;
+            }
+        }
+      if (j == nAttributes)
+        return False;
+    }
+
+  return True;
+}
+
+static
+Bool
+scanAttributes(
+               Display *dpy,
+               XvPortID portID
+               )
+{
+  XvAttribute *pAttributes;
+  int nAttributes;
+  Bool res = False;
+
+  if ((pAttributes = XvQueryPortAttributes(dpy , portID , &nAttributes)) == 0)
+    return False;
+
+  if (nAttributes > 0)
+    res = subScanAttributes(dpy , pAttributes , nAttributes);
+
+  XFree(pAttributes);
+  return res;
+}
+               
+/**********************************************************************
+ *
+ * getAttribute
+ *
+ **********************************************************************/
+static
+void
+getAttribute(
+             Display *dpy,
+             XvPortID portID,
+             int attribute,
+             int *value
+             )
+{
+  if (XvGetPortAttribute(dpy , 
+                         portID , 
+                         attrData[ attribute ].atom ,
+                         value) == Success)
+    return;
+
+  fprintf(stderr , "%s: Unable to get value of attribute %s\n" , program_name , attrNames[ attribute ].attrName);
+  exit(2);
+}
+
+/**********************************************************************
+ *
+ * setAttribute
+ *
+ **********************************************************************/
+static
+void
+setAttribute(
+             Display *dpy,
+             XvPortID portID,
+             int attribute,
+             int value
+             )
+{
+  int dummy;
+
+  if (XvSetPortAttribute(dpy , portID , attrData[ attribute ].atom , value) != Success)
+    {
+      fprintf(stderr , "%s: Unable to set value of attribute %s\n" , program_name , attrNames[ attribute ].attrName);
+      exit(2);
+    }
+
+  getAttribute(dpy , portID , attribute , &dummy);
+}
+
+/**********************************************************************
+ *
+ * parseAttribute
+ *
+ **********************************************************************/
+static
+int
+parseAttribute(
+               const char *name
+               )
+{
+  int i;
+
+  for (i = 0; i < N_ATTRS; i++)
+    if (strcasecmp(name , attrNames[ i ].extName) == 0)
+      return i;
+
+  return -1;
+}
+
+/**********************************************************************
+ *
+ * parseStd
+ *
+ **********************************************************************/
+static
+int
+parseStd(
+         const char *name
+         )
+{
+  int i;
+
+  for (i = 0; i < N_STDS; i++)
+    if (strcasecmp(name , stdNames[ i ]) == 0)
+      return i;
+
+  return -1;
+}
+
+/**********************************************************************
+ *
+ * printUsage
+ *
+ **********************************************************************/
+static
+void
+printUsage(void)
+{
+  unsigned i;
+
+  fprintf(stderr , "Usage:\n"
+          "%s [-display host:dpy] [<cmd> <attribute> [<value>]]\n\n" , program_name);
+  fprintf(stderr , "When <cmd> is absent, a dump of all attributes is done\n");
+  fprintf(stderr , "Allowed <cmd>s:\n"
+                   "set <attribute> <value>   Set <attribute> to <value>\n"
+                   "inc <attribute>           Increment <attribute> by 1\n"
+                   "dec <attribute>           Decrement <attribute> by 1\n"
+                   "zero <attribute>          Set <attribute> to 0\n"
+                   "\nAllowed <attribute>s:\n");
+
+  for (i = 0; i < N_ATTRS; i++)
+    fprintf(stderr , "%-6s  %s\n" , attrNames[ i ].extName , attrNames[ i ].description);
+
+  fprintf(stderr , "\nFor %s attribute, both the numeric value and the name of the standard are valid.\n" ,
+          attrNames[ STD_ATTR ].extName);
+
+  fprintf(stderr , "\nAllowed standards:\n");
+  
+  for (i = 0; i < N_STDS; i++)
+    fprintf(stderr , "%d %s\n" , i , stdNames[ i ]);
+
+  exit(1);
+}
+
+/**********************************************************************
+ *
+ * main
+ *
+ **********************************************************************/
+int 
+main(
+     int argc, 
+     char *argv[]
+     )
+{
+  Action action;
+  Display *dpy;
+  char *disname = NULL;
+  unsigned argIdx = 1;
+  int attribute;
+  int value;
+  unsigned ver, rev, eventB, reqB, errorB; 
+  XvAdaptorInfo *ainfo;
+  unsigned nadaptors;
+  unsigned i;
+  XvPortID portID;
+
+  program_name = argv[ 0 ];
+
+  if (argc >= 3 && 
+      strcmp(argv[ argIdx ] , "-display") == 0)
+    {
+      argIdx++;
+      disname = argv[ argIdx++ ];
+    }
+
+  if (argIdx < argc)
+    {
+      if (strcasecmp(argv[ argIdx ] , "set") == 0)
+        action = ACT_SET;
+      else if (strcasecmp(argv[ argIdx ] , "inc") == 0)
+        action = ACT_INC;
+      else if (strcasecmp(argv[ argIdx ] , "dec") == 0)
+        action = ACT_DEC;
+      else if (strcasecmp(argv[ argIdx ] , "zero") == 0)
+        action = ACT_ZERO;
+      else
+        printUsage();
+
+      argIdx++;
+      if (argIdx >= argc)
+        printUsage();
+
+      if ((attribute = parseAttribute(argv[ argIdx ])) < 0)
+        {
+          fprintf(stderr , "%s: Unrecognized attribute name (%s)\n" , program_name , argv[ argIdx ]);
+          printUsage();
+        }
+      argIdx++;
+
+      if (action == ACT_SET)
+        {
+          if (argIdx >= argc)
+            printUsage();
+          if (sscanf(argv[ argIdx ] , "%d" , &value) != 1 &&
+              (attribute != STD_ATTR || (value = parseStd(argv[ argIdx ])) < 0))
+            printUsage();
+        }
+    }
+  else 
+    action = ACT_FULL_DUMP;
+
+  /*
+   * Open display
+   */
+  if (!(dpy = XOpenDisplay(disname))) 
+    {
+      fprintf(stderr , "%s: Unable to open display %s\n" , program_name , 
+              (disname != NULL) ? disname : XDisplayName(NULL));
+      return -1;
+    }
+
+  if (XvQueryExtension(dpy, &ver, &rev, &reqB, &eventB, &errorB) != Success) 
+    {
+      fprintf(stderr , "%s: No XV Extension on %s\n" , program_name ,
+              (disname != NULL) ? disname : XDisplayName(NULL));
+      return 0;
+    } 
+  
+  /*
+   * Use screen #0
+   */
+  XvQueryAdaptors(dpy , RootWindow(dpy , 0) , &nadaptors , &ainfo);
+  
+  if (!nadaptors)
+    {
+      fprintf(stderr , "%s: No adaptors present\n" , program_name);
+      return 0;
+    } 
+
+  /*
+   * Use adaptor #0
+   */
+  portID = ainfo[ 0 ].base_id;
+  if (!scanAttributes(dpy , portID))
+    {
+      fprintf(stderr , "%s: Invalid attributes in XV adaptor\n" , program_name);
+      return 0;
+    }
+
+  switch (action)
+    {
+    case ACT_FULL_DUMP:
+      for(i = 0; i < nadaptors; i++)
+        {
+          printf("Adaptor #%d: \"%s\"\n" , i , ainfo[ i ].name);
+          printf("  number of ports   : %d\n" , ainfo[ i ].num_ports);
+          printf("  port base         : %d\n" , ainfo[ i ].base_id);
+          printf("  number of adaptors: %u\n" , ainfo[ i ].num_adaptors);
+        }
+      for (i = 0; i < N_ATTRS; i++)
+        {
+          getAttribute(dpy , portID , i , &value);
+          if (i == STD_ATTR)
+            if (value < 0 || value >= N_STDS)
+              printf ("%s = ??? (%d)\n" , attrNames[ i ].extName , value);
+            else
+              printf ("%s = %s (%d)\n" , attrNames[ i ].extName , stdNames[ value ] , value);
+          else
+            printf("%s = %d\n" , attrNames[ i ].extName , value);
+        }
+      break;
+
+    case ACT_SET:
+      setAttribute(dpy , portID , attribute , value);
+      break;
+
+    case ACT_INC:
+      getAttribute(dpy , portID , attribute , &value);
+      value++;
+      if (value > attrData[ attribute ].maxValue)
+        value = attrData[ attribute ].minValue;
+      setAttribute(dpy , portID , attribute , value);
+      break;
+
+    case ACT_DEC:
+      getAttribute(dpy , portID , attribute , &value);
+      value--;
+      if (value < attrData[ attribute ].minValue)
+        value = attrData[ attribute ].maxValue;
+      setAttribute(dpy , portID , attribute , value);
+      break;
+
+    case ACT_ZERO:
+      setAttribute(dpy , portID , attribute , 0);
+      break;
+    }
+
+  return 0;
+}