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 +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" "" +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] [ []] + +tvo_set is not case sensitive for , & +fields. +When no is given, tvo_set just dumps the current state of +TV attributes. + +Recognized commands: +set Set to +inc Increment by 1 +dec Decrement by 1 +zero Set to 0 + +Recognized values for 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 +#include +#include +#include +#include +#include +#include + +/********************************************************************** + * + * 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] [ []]\n\n" , program_name); + fprintf(stderr , "When is absent, a dump of all attributes is done\n"); + fprintf(stderr , "Allowed s:\n" + "set Set to \n" + "inc Increment by 1\n" + "dec Decrement by 1\n" + "zero Set to 0\n" + "\nAllowed 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; +}