[media] bt8xx: move analog TV part to be together with DTV one
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 14 Aug 2012 14:49:09 +0000 (11:49 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 19:35:54 +0000 (16:35 -0300)
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
32 files changed:
drivers/media/pci/bt8xx/Kconfig
drivers/media/pci/bt8xx/Makefile
drivers/media/pci/bt8xx/bt848.h [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-audio-hook.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-audio-hook.h [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-cards.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-driver.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-gpio.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-i2c.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-if.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-input.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-risc.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv-vbi.c [new file with mode: 0644]
drivers/media/pci/bt8xx/bttv.h [new file with mode: 0644]
drivers/media/pci/bt8xx/bttvp.h [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt8xx/Kconfig [deleted file]
drivers/media/video/bt8xx/Makefile [deleted file]
drivers/media/video/bt8xx/bt848.h [deleted file]
drivers/media/video/bt8xx/bttv-audio-hook.c [deleted file]
drivers/media/video/bt8xx/bttv-audio-hook.h [deleted file]
drivers/media/video/bt8xx/bttv-cards.c [deleted file]
drivers/media/video/bt8xx/bttv-driver.c [deleted file]
drivers/media/video/bt8xx/bttv-gpio.c [deleted file]
drivers/media/video/bt8xx/bttv-i2c.c [deleted file]
drivers/media/video/bt8xx/bttv-if.c [deleted file]
drivers/media/video/bt8xx/bttv-input.c [deleted file]
drivers/media/video/bt8xx/bttv-risc.c [deleted file]
drivers/media/video/bt8xx/bttv-vbi.c [deleted file]
drivers/media/video/bt8xx/bttv.h [deleted file]
drivers/media/video/bt8xx/bttvp.h [deleted file]

index 8668e634c7ec96da068ed22ba013352e32626ba0..f2667a5cc144269c5b3697a6232bc9e35ae302f7 100644 (file)
@@ -1,5 +1,26 @@
+config VIDEO_BT848
+       tristate "BT848 Video For Linux"
+       depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEOBUF_DMA_SG
+       depends on RC_CORE
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
+       ---help---
+         Support for BT848 based frame grabber/overlay boards. This includes
+         the Miro, Hauppauge and STB boards. Please read the material in
+         <file:Documentation/video4linux/bttv/> for more information.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bttv.
+
 config DVB_BT8XX
-       tristate "BT8xx based PCI cards"
+       tristate "DVB/ATSC Support for bt878 based TV cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_SP887X if !DVB_FE_CUSTOMISE
index c008d0c135d6a174975520175e07e83716bd8832..ae347b78fccfcb1ae999359ea8a4d56a58c986f0 100644 (file)
@@ -1,6 +1,11 @@
+bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
+                      bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+                      bttv-input.o bttv-audio-hook.o
+
+obj-$(CONFIG_VIDEO_BT848) += bttv.o
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/video/bt8xx
+ccflags-y += -Idrivers/media/video
 ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/bt8xx/bt848.h b/drivers/media/pci/bt8xx/bt848.h
new file mode 100644 (file)
index 0000000..c37e6ac
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+    bt848.h - Bt848 register offsets
+
+    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _BT848_H_
+#define _BT848_H_
+
+#ifndef PCI_VENDOR_ID_BROOKTREE
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#endif
+#ifndef PCI_DEVICE_ID_BT848
+#define PCI_DEVICE_ID_BT848     0x350
+#endif
+#ifndef PCI_DEVICE_ID_BT849
+#define PCI_DEVICE_ID_BT849     0x351
+#endif
+#ifndef PCI_DEVICE_ID_FUSION879
+#define PCI_DEVICE_ID_FUSION879        0x36c
+#endif
+
+#ifndef PCI_DEVICE_ID_BT878
+#define PCI_DEVICE_ID_BT878     0x36e
+#endif
+#ifndef PCI_DEVICE_ID_BT879
+#define PCI_DEVICE_ID_BT879     0x36f
+#endif
+
+/* Brooktree 848 registers */
+
+#define BT848_DSTATUS          0x000
+#define BT848_DSTATUS_PRES     (1<<7)
+#define BT848_DSTATUS_HLOC     (1<<6)
+#define BT848_DSTATUS_FIELD    (1<<5)
+#define BT848_DSTATUS_NUML     (1<<4)
+#define BT848_DSTATUS_CSEL     (1<<3)
+#define BT848_DSTATUS_PLOCK    (1<<2)
+#define BT848_DSTATUS_LOF      (1<<1)
+#define BT848_DSTATUS_COF      (1<<0)
+
+#define BT848_IFORM            0x004
+#define BT848_IFORM_HACTIVE    (1<<7)
+#define BT848_IFORM_MUXSEL     (3<<5)
+#define BT848_IFORM_MUX0       (2<<5)
+#define BT848_IFORM_MUX1       (3<<5)
+#define BT848_IFORM_MUX2       (1<<5)
+#define BT848_IFORM_XTSEL      (3<<3)
+#define BT848_IFORM_XT0        (1<<3)
+#define BT848_IFORM_XT1        (2<<3)
+#define BT848_IFORM_XTAUTO     (3<<3)
+#define BT848_IFORM_XTBOTH     (3<<3)
+#define BT848_IFORM_NTSC       1
+#define BT848_IFORM_NTSC_J     2
+#define BT848_IFORM_PAL_BDGHI  3
+#define BT848_IFORM_PAL_M      4
+#define BT848_IFORM_PAL_N      5
+#define BT848_IFORM_SECAM      6
+#define BT848_IFORM_PAL_NC     7
+#define BT848_IFORM_AUTO       0
+#define BT848_IFORM_NORM       7
+
+#define BT848_TDEC             0x008
+#define BT848_TDEC_DEC_FIELD   (1<<7)
+#define BT848_TDEC_FLDALIGN    (1<<6)
+#define BT848_TDEC_DEC_RAT     (0x1f)
+
+#define BT848_E_CROP           0x00C
+#define BT848_O_CROP           0x08C
+
+#define BT848_E_VDELAY_LO      0x010
+#define BT848_O_VDELAY_LO      0x090
+
+#define BT848_E_VACTIVE_LO     0x014
+#define BT848_O_VACTIVE_LO     0x094
+
+#define BT848_E_HDELAY_LO      0x018
+#define BT848_O_HDELAY_LO      0x098
+
+#define BT848_E_HACTIVE_LO     0x01C
+#define BT848_O_HACTIVE_LO     0x09C
+
+#define BT848_E_HSCALE_HI      0x020
+#define BT848_O_HSCALE_HI      0x0A0
+
+#define BT848_E_HSCALE_LO      0x024
+#define BT848_O_HSCALE_LO      0x0A4
+
+#define BT848_BRIGHT           0x028
+
+#define BT848_E_CONTROL        0x02C
+#define BT848_O_CONTROL        0x0AC
+#define BT848_CONTROL_LNOTCH    (1<<7)
+#define BT848_CONTROL_COMP      (1<<6)
+#define BT848_CONTROL_LDEC      (1<<5)
+#define BT848_CONTROL_CBSENSE   (1<<4)
+#define BT848_CONTROL_CON_MSB   (1<<2)
+#define BT848_CONTROL_SAT_U_MSB (1<<1)
+#define BT848_CONTROL_SAT_V_MSB (1<<0)
+
+#define BT848_CONTRAST_LO      0x030
+#define BT848_SAT_U_LO         0x034
+#define BT848_SAT_V_LO         0x038
+#define BT848_HUE              0x03C
+
+#define BT848_E_SCLOOP         0x040
+#define BT848_O_SCLOOP         0x0C0
+#define BT848_SCLOOP_CAGC       (1<<6)
+#define BT848_SCLOOP_CKILL      (1<<5)
+#define BT848_SCLOOP_HFILT_AUTO (0<<3)
+#define BT848_SCLOOP_HFILT_CIF  (1<<3)
+#define BT848_SCLOOP_HFILT_QCIF (2<<3)
+#define BT848_SCLOOP_HFILT_ICON (3<<3)
+
+#define BT848_SCLOOP_PEAK       (1<<7)
+#define BT848_SCLOOP_HFILT_MINP (1<<3)
+#define BT848_SCLOOP_HFILT_MEDP (2<<3)
+#define BT848_SCLOOP_HFILT_MAXP (3<<3)
+
+
+#define BT848_OFORM            0x048
+#define BT848_OFORM_RANGE      (1<<7)
+#define BT848_OFORM_CORE0      (0<<5)
+#define BT848_OFORM_CORE8      (1<<5)
+#define BT848_OFORM_CORE16     (2<<5)
+#define BT848_OFORM_CORE32     (3<<5)
+
+#define BT848_E_VSCALE_HI      0x04C
+#define BT848_O_VSCALE_HI      0x0CC
+#define BT848_VSCALE_YCOMB     (1<<7)
+#define BT848_VSCALE_COMB      (1<<6)
+#define BT848_VSCALE_INT       (1<<5)
+#define BT848_VSCALE_HI        15
+
+#define BT848_E_VSCALE_LO      0x050
+#define BT848_O_VSCALE_LO      0x0D0
+#define BT848_TEST             0x054
+#define BT848_ADELAY           0x060
+#define BT848_BDELAY           0x064
+
+#define BT848_ADC              0x068
+#define BT848_ADC_RESERVED     (2<<6)
+#define BT848_ADC_SYNC_T       (1<<5)
+#define BT848_ADC_AGC_EN       (1<<4)
+#define BT848_ADC_CLK_SLEEP    (1<<3)
+#define BT848_ADC_Y_SLEEP      (1<<2)
+#define BT848_ADC_C_SLEEP      (1<<1)
+#define BT848_ADC_CRUSH        (1<<0)
+
+#define BT848_WC_UP            0x044
+#define BT848_WC_DOWN          0x078
+
+#define BT848_E_VTC            0x06C
+#define BT848_O_VTC            0x0EC
+#define BT848_VTC_HSFMT        (1<<7)
+#define BT848_VTC_VFILT_2TAP   0
+#define BT848_VTC_VFILT_3TAP   1
+#define BT848_VTC_VFILT_4TAP   2
+#define BT848_VTC_VFILT_5TAP   3
+
+#define BT848_SRESET           0x07C
+
+#define BT848_COLOR_FMT             0x0D4
+#define BT848_COLOR_FMT_O_RGB32     (0<<4)
+#define BT848_COLOR_FMT_O_RGB24     (1<<4)
+#define BT848_COLOR_FMT_O_RGB16     (2<<4)
+#define BT848_COLOR_FMT_O_RGB15     (3<<4)
+#define BT848_COLOR_FMT_O_YUY2      (4<<4)
+#define BT848_COLOR_FMT_O_BtYUV     (5<<4)
+#define BT848_COLOR_FMT_O_Y8        (6<<4)
+#define BT848_COLOR_FMT_O_RGB8      (7<<4)
+#define BT848_COLOR_FMT_O_YCrCb422  (8<<4)
+#define BT848_COLOR_FMT_O_YCrCb411  (9<<4)
+#define BT848_COLOR_FMT_O_RAW       (14<<4)
+#define BT848_COLOR_FMT_E_RGB32     0
+#define BT848_COLOR_FMT_E_RGB24     1
+#define BT848_COLOR_FMT_E_RGB16     2
+#define BT848_COLOR_FMT_E_RGB15     3
+#define BT848_COLOR_FMT_E_YUY2      4
+#define BT848_COLOR_FMT_E_BtYUV     5
+#define BT848_COLOR_FMT_E_Y8        6
+#define BT848_COLOR_FMT_E_RGB8      7
+#define BT848_COLOR_FMT_E_YCrCb422  8
+#define BT848_COLOR_FMT_E_YCrCb411  9
+#define BT848_COLOR_FMT_E_RAW       14
+
+#define BT848_COLOR_FMT_RGB32       0x00
+#define BT848_COLOR_FMT_RGB24       0x11
+#define BT848_COLOR_FMT_RGB16       0x22
+#define BT848_COLOR_FMT_RGB15       0x33
+#define BT848_COLOR_FMT_YUY2        0x44
+#define BT848_COLOR_FMT_BtYUV       0x55
+#define BT848_COLOR_FMT_Y8          0x66
+#define BT848_COLOR_FMT_RGB8        0x77
+#define BT848_COLOR_FMT_YCrCb422    0x88
+#define BT848_COLOR_FMT_YCrCb411    0x99
+#define BT848_COLOR_FMT_RAW         0xee
+
+#define BT848_VTOTAL_LO             0xB0
+#define BT848_VTOTAL_HI             0xB4
+
+#define BT848_COLOR_CTL                0x0D8
+#define BT848_COLOR_CTL_EXT_FRMRATE    (1<<7)
+#define BT848_COLOR_CTL_COLOR_BARS     (1<<6)
+#define BT848_COLOR_CTL_RGB_DED        (1<<5)
+#define BT848_COLOR_CTL_GAMMA          (1<<4)
+#define BT848_COLOR_CTL_WSWAP_ODD      (1<<3)
+#define BT848_COLOR_CTL_WSWAP_EVEN     (1<<2)
+#define BT848_COLOR_CTL_BSWAP_ODD      (1<<1)
+#define BT848_COLOR_CTL_BSWAP_EVEN     (1<<0)
+
+#define BT848_CAP_CTL                  0x0DC
+#define BT848_CAP_CTL_DITH_FRAME       (1<<4)
+#define BT848_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
+#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
+#define BT848_CAP_CTL_CAPTURE_ODD      (1<<1)
+#define BT848_CAP_CTL_CAPTURE_EVEN     (1<<0)
+
+#define BT848_VBI_PACK_SIZE    0x0E0
+
+#define BT848_VBI_PACK_DEL     0x0E4
+#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc
+#define BT848_VBI_PACK_DEL_EXT_FRAME  2
+#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1
+
+
+#define BT848_INT_STAT         0x100
+#define BT848_INT_MASK         0x104
+
+#define BT848_INT_ETBF         (1<<23)
+
+#define BT848_INT_RISCS   (0xf<<28)
+#define BT848_INT_RISC_EN (1<<27)
+#define BT848_INT_RACK    (1<<25)
+#define BT848_INT_FIELD   (1<<24)
+#define BT848_INT_SCERR   (1<<19)
+#define BT848_INT_OCERR   (1<<18)
+#define BT848_INT_PABORT  (1<<17)
+#define BT848_INT_RIPERR  (1<<16)
+#define BT848_INT_PPERR   (1<<15)
+#define BT848_INT_FDSR    (1<<14)
+#define BT848_INT_FTRGT   (1<<13)
+#define BT848_INT_FBUS    (1<<12)
+#define BT848_INT_RISCI   (1<<11)
+#define BT848_INT_GPINT   (1<<9)
+#define BT848_INT_I2CDONE (1<<8)
+#define BT848_INT_VPRES   (1<<5)
+#define BT848_INT_HLOCK   (1<<4)
+#define BT848_INT_OFLOW   (1<<3)
+#define BT848_INT_HSYNC   (1<<2)
+#define BT848_INT_VSYNC   (1<<1)
+#define BT848_INT_FMTCHG  (1<<0)
+
+
+#define BT848_GPIO_DMA_CTL             0x10C
+#define BT848_GPIO_DMA_CTL_GPINTC      (1<<15)
+#define BT848_GPIO_DMA_CTL_GPINTI      (1<<14)
+#define BT848_GPIO_DMA_CTL_GPWEC       (1<<13)
+#define BT848_GPIO_DMA_CTL_GPIOMODE    (3<<11)
+#define BT848_GPIO_DMA_CTL_GPCLKMODE   (1<<10)
+#define BT848_GPIO_DMA_CTL_PLTP23_4    (0<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_8    (1<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_16   (2<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_32   (3<<6)
+#define BT848_GPIO_DMA_CTL_PLTP1_4     (0<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_8     (1<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_16    (2<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_32    (3<<4)
+#define BT848_GPIO_DMA_CTL_PKTP_4      (0<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_8      (1<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_16     (2<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_32     (3<<2)
+#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1)
+#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
+
+#define BT848_I2C              0x110
+#define BT878_I2C_MODE         (1<<7)
+#define BT878_I2C_RATE         (1<<6)
+#define BT878_I2C_NOSTOP       (1<<5)
+#define BT878_I2C_NOSTART      (1<<4)
+#define BT848_I2C_DIV          (0xf<<4)
+#define BT848_I2C_SYNC         (1<<3)
+#define BT848_I2C_W3B         (1<<2)
+#define BT848_I2C_SCL          (1<<1)
+#define BT848_I2C_SDA          (1<<0)
+
+#define BT848_RISC_STRT_ADD    0x114
+#define BT848_GPIO_OUT_EN      0x118
+#define BT848_GPIO_REG_INP     0x11C
+#define BT848_RISC_COUNT       0x120
+#define BT848_GPIO_DATA        0x200
+
+
+/* Bt848 RISC commands */
+
+/* only for the SYNC RISC command */
+#define BT848_FIFO_STATUS_FM1  0x06
+#define BT848_FIFO_STATUS_FM3  0x0e
+#define BT848_FIFO_STATUS_SOL  0x02
+#define BT848_FIFO_STATUS_EOL4 0x01
+#define BT848_FIFO_STATUS_EOL3 0x0d
+#define BT848_FIFO_STATUS_EOL2 0x09
+#define BT848_FIFO_STATUS_EOL1 0x05
+#define BT848_FIFO_STATUS_VRE  0x04
+#define BT848_FIFO_STATUS_VRO  0x0c
+#define BT848_FIFO_STATUS_PXV  0x00
+
+#define BT848_RISC_RESYNC      (1<<15)
+
+/* WRITE and SKIP */
+/* disable which bytes of each DWORD */
+#define BT848_RISC_BYTE0       (1U<<12)
+#define BT848_RISC_BYTE1       (1U<<13)
+#define BT848_RISC_BYTE2       (1U<<14)
+#define BT848_RISC_BYTE3       (1U<<15)
+#define BT848_RISC_BYTE_ALL    (0x0fU<<12)
+#define BT848_RISC_BYTE_NONE   0
+/* cause RISCI */
+#define BT848_RISC_IRQ         (1U<<24)
+/* RISC command is last one in this line */
+#define BT848_RISC_EOL         (1U<<26)
+/* RISC command is first one in this line */
+#define BT848_RISC_SOL         (1U<<27)
+
+#define BT848_RISC_WRITE       (0x01U<<28)
+#define BT848_RISC_SKIP        (0x02U<<28)
+#define BT848_RISC_WRITEC      (0x05U<<28)
+#define BT848_RISC_JUMP        (0x07U<<28)
+#define BT848_RISC_SYNC        (0x08U<<28)
+
+#define BT848_RISC_WRITE123    (0x09U<<28)
+#define BT848_RISC_SKIP123     (0x0aU<<28)
+#define BT848_RISC_WRITE1S23   (0x0bU<<28)
+
+
+/* Bt848A and higher only !! */
+#define BT848_TGLB             0x080
+#define BT848_TGCTRL           0x084
+#define BT848_FCAP             0x0E8
+#define BT848_PLL_F_LO         0x0F0
+#define BT848_PLL_F_HI         0x0F4
+
+#define BT848_PLL_XCI          0x0F8
+#define BT848_PLL_X            (1<<7)
+#define BT848_PLL_C            (1<<6)
+
+#define BT848_DVSIF            0x0FC
+
+/* Bt878 register */
+
+#define BT878_DEVCTRL 0x40
+#define BT878_EN_TBFX 0x02
+#define BT878_EN_VSFX 0x04
+
+#endif
diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.c b/drivers/media/pci/bt8xx/bttv-audio-hook.c
new file mode 100644 (file)
index 0000000..2364d16
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Handlers for board audio hooks, splitted from bttv-cards
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License
+ */
+
+#include "bttv-audio-hook.h"
+
+#include <linux/delay.h>
+
+/* ----------------------------------------------------------------------- */
+/* winview                                                                 */
+
+void winview_volume(struct bttv *btv, __u16 volume)
+{
+       /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
+       int bits_out, loops, vol, data;
+
+       /* 32 levels logarithmic */
+       vol = 32 - ((volume>>11));
+       /* units */
+       bits_out = (PT2254_DBS_IN_2>>(vol%5));
+       /* tens */
+       bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+       bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
+       data = gpio_read();
+       data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+                 WINVIEW_PT2254_STROBE);
+       for (loops = 17; loops >= 0 ; loops--) {
+               if (bits_out & (1<<loops))
+                       data |=  WINVIEW_PT2254_DATA;
+               else
+                       data &= ~WINVIEW_PT2254_DATA;
+               gpio_write(data);
+               udelay(5);
+               data |= WINVIEW_PT2254_CLK;
+               gpio_write(data);
+               udelay(5);
+               data &= ~WINVIEW_PT2254_CLK;
+               gpio_write(data);
+       }
+       data |=  WINVIEW_PT2254_STROBE;
+       data &= ~WINVIEW_PT2254_DATA;
+       gpio_write(data);
+       udelay(10);
+       data &= ~WINVIEW_PT2254_STROBE;
+       gpio_write(data);
+}
+
+/* ----------------------------------------------------------------------- */
+/* mono/stereo control for various cards (which don't use i2c chips but    */
+/* connect something to the GPIO pins                                      */
+
+void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned int con = 0;
+
+       if (set) {
+               gpio_inout(0x300, 0x300);
+               if (t->audmode & V4L2_TUNER_MODE_LANG1)
+                       con = 0x000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)
+                       con = 0x300;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)
+                       con = 0x200;
+/*             if (t->audmode & V4L2_TUNER_MODE_MONO)
+ *                     con = 0x100; */
+               gpio_bits(0x300, con);
+       } else {
+               t->audmode = V4L2_TUNER_MODE_STEREO |
+                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned int val, con;
+
+       if (btv->radio_user)
+               return;
+
+       val = gpio_read();
+       if (set) {
+               con = 0x000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG2) {
+                       if (t->audmode & V4L2_TUNER_MODE_LANG1) {
+                               /* LANG1 + LANG2 */
+                               con = 0x100;
+                       }
+                       else {
+                               /* LANG2 */
+                               con = 0x300;
+                       }
+               }
+               if (con != (val & 0x300)) {
+                       gpio_bits(0x300, con);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"gvbctv5pci");
+               }
+       } else {
+               switch (val & 0x70) {
+                 case 0x10:
+                       t->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
+                       break;
+                 case 0x30:
+                       t->rxsubchans = V4L2_TUNER_SUB_LANG2;
+                       break;
+                 case 0x50:
+                       t->rxsubchans = V4L2_TUNER_SUB_LANG1;
+                       break;
+                 case 0x60:
+                       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+                       break;
+                 case 0x70:
+                       t->rxsubchans = V4L2_TUNER_SUB_MONO;
+                       break;
+                 default:
+                       t->rxsubchans = V4L2_TUNER_SUB_MONO |
+                                        V4L2_TUNER_SUB_STEREO |
+                                        V4L2_TUNER_SUB_LANG1 |
+                                        V4L2_TUNER_SUB_LANG2;
+               }
+               t->audmode = V4L2_TUNER_MODE_STEREO |
+                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+/*
+ * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
+ *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
+ *  0xdde enables mono and 0xccd enables sap
+ *
+ * Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
+ *  input/output sound connection, so both must be set for output mode.
+ *
+ * Looks like it's needed only for the "tvphone", the "tvphone 98"
+ * handles this with a tda9840
+ *
+ */
+
+void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       int val = 0;
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
+                       val = 0x02;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)
+                       val = 0x01;
+               if (val) {
+                       gpio_bits(0x03,val);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"avermedia");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1;
+               return;
+       }
+}
+
+
+void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       int val = 0;
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
+                       val = 0x01;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
+                       val = 0x02;
+               btaor(val, ~0x03, BT848_GPIO_DATA);
+               if (bttv_gpio)
+                       bttv_gpio_tracking(btv,"avermedia");
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+               return;
+       }
+}
+
+/* Lifetec 9415 handling */
+
+void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       int val = 0;
+
+       if (gpio_read() & 0x4000) {
+               t->audmode = V4L2_TUNER_MODE_MONO;
+               return;
+       }
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
+                       val = 0x0080;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
+                       val = 0x0880;
+               if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
+                   (t->audmode & V4L2_TUNER_MODE_MONO))
+                       val = 0;
+               gpio_bits(0x0880, val);
+               if (bttv_gpio)
+                       bttv_gpio_tracking(btv,"lt9415");
+       } else {
+               /* autodetect doesn't work with this card :-( */
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+               return;
+       }
+}
+
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
+void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
+{
+       unsigned int con = 0;
+
+       if (set) {
+               gpio_inout(0x180000,0x180000);
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)
+                       con = 0x080000;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)
+                       con = 0x180000;
+               gpio_bits(0x180000, con);
+               if (bttv_gpio)
+                       bttv_gpio_tracking(btv,"terratv");
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+
+void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned long val = 0;
+
+       if (set) {
+               /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
+               if (t->audmode & V4L2_TUNER_MODE_MONO)          /* Mono */
+                       val = 0x420000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
+                       val = 0x420000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
+                       val = 0x410000;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)        /* Stereo */
+                       val = 0x020000;
+               if (val) {
+                       gpio_bits(0x430000, val);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"winfast2000");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
+ * revision 9B has on-board TDA9874A sound decoder).
+ *
+ * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
+ *       will mute this cards.
+ */
+void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned int val = 0;
+
+       if (btv->radio_user)
+               return;
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_MONO)  {
+                       val = 0x01;
+               }
+               if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
+                   || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
+                       val = 0x02;
+               }
+               if (val) {
+                       gpio_bits(0x03,val);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"pvbt878p9b");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for FlyVideo 2000S (with tda9874 decoder)
+ * based on pvbt878p9b_audio() - this is not tested, please fix!!!
+ */
+void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned int val = 0xffff;
+
+       if (btv->radio_user)
+               return;
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_MONO)  {
+                       val = 0x0000;
+               }
+               if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
+                   || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
+                       val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
+               }
+               if (val != 0xffff) {
+                       gpio_bits(0x1800, val);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"fv2000s");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+/*
+ * sound control for Canopus WinDVR PCI
+ * Masaki Suzuki <masaki@btree.org>
+ */
+void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned long val = 0;
+
+       if (set) {
+               if (t->audmode & V4L2_TUNER_MODE_MONO)
+                       val = 0x040000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG1)
+                       val = 0;
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)
+                       val = 0x100000;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)
+                       val = 0;
+               if (val) {
+                       gpio_bits(0x140000, val);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv,"windvr");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+       }
+}
+
+/*
+ * sound control for AD-TVK503
+ * Hiroshi Takekawa <sian@big.or.jp>
+ */
+void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+       unsigned int con = 0xffffff;
+
+       /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
+
+       if (set) {
+               /* btor(***, BT848_GPIO_OUT_EN); */
+               if (t->audmode & V4L2_TUNER_MODE_LANG1)
+                       con = 0x00000000;
+               if (t->audmode & V4L2_TUNER_MODE_LANG2)
+                       con = 0x00180000;
+               if (t->audmode & V4L2_TUNER_MODE_STEREO)
+                       con = 0x00000000;
+               if (t->audmode & V4L2_TUNER_MODE_MONO)
+                       con = 0x00060000;
+               if (con != 0xffffff) {
+                       gpio_bits(0x1e0000,con);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv, "adtvk503");
+               }
+       } else {
+               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+       }
+}
diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.h b/drivers/media/pci/bt8xx/bttv-audio-hook.h
new file mode 100644 (file)
index 0000000..159d07a
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Handlers for board audio hooks, splitted from bttv-cards
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License
+ */
+
+#include "bttvp.h"
+
+void winview_volume (struct bttv *btv, __u16 volume);
+
+void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void terratv_audio(struct bttv *btv,  struct v4l2_tuner *tuner, int set);
+void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
new file mode 100644 (file)
index 0000000..38952fa
--- /dev/null
@@ -0,0 +1,4895 @@
+/*
+
+    bttv-cards.c
+
+    this file has configuration informations - card-specific stuff
+    like the big tvcards array for the most part
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                          & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <net/checksum.h>
+
+#include <asm/unaligned.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <media/tvaudio.h>
+#include "bttv-audio-hook.h"
+
+/* fwd decl */
+static void boot_msp34xx(struct bttv *btv, int pin);
+static void hauppauge_eeprom(struct bttv *btv);
+static void avermedia_eeprom(struct bttv *btv);
+static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
+static void modtec_eeprom(struct bttv *btv);
+static void init_PXC200(struct bttv *btv);
+static void init_RTV24(struct bttv *btv);
+
+static void rv605_muxsel(struct bttv *btv, unsigned int input);
+static void eagle_muxsel(struct bttv *btv, unsigned int input);
+static void xguard_muxsel(struct bttv *btv, unsigned int input);
+static void ivc120_muxsel(struct bttv *btv, unsigned int input);
+static void gvc1100_muxsel(struct bttv *btv, unsigned int input);
+
+static void PXC200_muxsel(struct bttv *btv, unsigned int input);
+
+static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
+static void picolo_tetra_init(struct bttv *btv);
+
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input);
+static void tibetCS16_init(struct bttv *btv);
+
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input);
+static void kodicom4400r_init(struct bttv *btv);
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+
+static void geovision_muxsel(struct bttv *btv, unsigned int input);
+
+static void phytec_muxsel(struct bttv *btv, unsigned int input);
+
+static void gv800s_muxsel(struct bttv *btv, unsigned int input);
+static void gv800s_init(struct bttv *btv);
+
+static void td3116_muxsel(struct bttv *btv, unsigned int input);
+
+static int terratec_active_radio_upgrade(struct bttv *btv);
+static int tea5757_read(struct bttv *btv);
+static int tea5757_write(struct bttv *btv, int value);
+static void identify_by_eeprom(struct bttv *btv,
+                              unsigned char eeprom_data[256]);
+static int __devinit pvr_boot(struct bttv *btv);
+
+/* config variables */
+static unsigned int triton1;
+static unsigned int vsfx;
+static unsigned int latency = UNSET;
+int no_overlay=-1;
+
+static unsigned int card[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int pll[BTTV_MAX]    = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int tuner[BTTV_MAX]  = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int svhs[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int audiodev[BTTV_MAX];
+static unsigned int saa6588[BTTV_MAX];
+static struct bttv  *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
+static unsigned int autoload = UNSET;
+static unsigned int gpiomask = UNSET;
+static unsigned int audioall = UNSET;
+static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
+
+/* insmod options */
+module_param(triton1,    int, 0444);
+module_param(vsfx,       int, 0444);
+module_param(no_overlay, int, 0444);
+module_param(latency,    int, 0444);
+module_param(gpiomask,   int, 0444);
+module_param(audioall,   int, 0444);
+module_param(autoload,   int, 0444);
+
+module_param_array(card,     int, NULL, 0444);
+module_param_array(pll,      int, NULL, 0444);
+module_param_array(tuner,    int, NULL, 0444);
+module_param_array(svhs,     int, NULL, 0444);
+module_param_array(remote,   int, NULL, 0444);
+module_param_array(audiodev, int, NULL, 0444);
+module_param_array(audiomux, int, NULL, 0444);
+
+MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
+                "[enable bug compatibility for triton1 + others]");
+MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
+                "[yet another chipset flaw workaround]");
+MODULE_PARM_DESC(latency,"pci latency timer");
+MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
+MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)");
+MODULE_PARM_DESC(tuner,"specify installed tuner type");
+MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore");
+MODULE_PARM_DESC(audiodev, "specify audio device:\n"
+               "\t\t-1 = no audio\n"
+               "\t\t 0 = autodetect (default)\n"
+               "\t\t 1 = msp3400\n"
+               "\t\t 2 = tda7432\n"
+               "\t\t 3 = tvaudio");
+MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition.");
+MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
+               " [some VIA/SIS chipsets are known to have problem with overlay]");
+
+/* ----------------------------------------------------------------------- */
+/* list of card IDs for bt878+ cards                                       */
+
+static struct CARD {
+       unsigned id;
+       int cardnr;
+       char *name;
+} cards[] __devinitdata = {
+       { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV" },
+       { 0x39000070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV-D" },
+       { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR,  "Hauppauge WinTV/PVR" },
+       { 0xff000070, BTTV_BOARD_OSPREY1x0,     "Osprey-100" },
+       { 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" },
+       { 0xff020070, BTTV_BOARD_OSPREY500,     "Osprey-500" },
+       { 0xff030070, BTTV_BOARD_OSPREY2000,    "Osprey-2000" },
+       { 0xff040070, BTTV_BOARD_OSPREY540,     "Osprey-540" },
+       { 0xff070070, BTTV_BOARD_OSPREY440,     "Osprey-440" },
+
+       { 0x00011002, BTTV_BOARD_ATI_TVWONDER,  "ATI TV Wonder" },
+       { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" },
+
+       { 0x6606107d, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+       { 0x6607107d, BTTV_BOARD_WINFASTVC100,  "Leadtek WinFast VC 100" },
+       { 0x6609107d, BTTV_BOARD_WINFAST2000,   "Leadtek TV 2000 XP" },
+       { 0x263610b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
+       { 0x264510b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
+       { 0x402010fc, BTTV_BOARD_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
+       { 0x405010fc, BTTV_BOARD_GVBCTV4PCI,    "I-O Data Co. GV-BCTV4/PCI" },
+       { 0x407010fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
+       { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
+
+       { 0x001211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
+       /* some cards ship with byteswapped IDs ... */
+       { 0x1200bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
+       { 0xff00bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
+       /* this seems to happen as well ... */
+       { 0xff1211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
+
+       { 0x3000121a, BTTV_BOARD_VOODOOTV_200,  "3Dfx VoodooTV 200" },
+       { 0x263710b4, BTTV_BOARD_VOODOOTV_FM,   "3Dfx VoodooTV FM" },
+       { 0x3060121a, BTTV_BOARD_STB2,    "3Dfx VoodooTV 100/ STB OEM" },
+
+       { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
+       { 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" },
+       { 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
+       { 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+       { 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" },
+       { 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" },
+       { 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS,  "Phoebe TV Master (CPH060)" },
+
+       { 0x00011461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
+       { 0x00021461, BTTV_BOARD_AVERMEDIA98,   "AVermedia TVCapture 98" },
+       { 0x00031461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
+       { 0x00041461, BTTV_BOARD_AVERMEDIA98,   "AVerMedia TVCapture 98" },
+       { 0x03001461, BTTV_BOARD_AVERMEDIA98,   "VDOMATE TV TUNER CARD" },
+
+       { 0x1117153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL B/G)" },
+       { 0x1118153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL B/G)" },
+       { 0x1119153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL I)" },
+       { 0x111a153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL I)" },
+
+       { 0x1123153b, BTTV_BOARD_TERRATVRADIO,  "Terratec TV Radio+" },
+       { 0x1127153b, BTTV_BOARD_TERRATV,       "Terratec TV+ (V1.05)"    },
+       /* clashes with FlyVideo
+        *{ 0x18521852, BTTV_BOARD_TERRATV,     "Terratec TV+ (V1.10)"    }, */
+       { 0x1134153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (LR102)" },
+       { 0x1135153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* LR102 */
+       { 0x5018153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue" },       /* ?? */
+       { 0xff3b153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* ?? */
+
+       { 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
+       { 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
+       { 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+       { 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+       { 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+
+       { 0x1430aa00, BTTV_BOARD_PV143,         "Provideo PV143A" },
+       { 0x1431aa00, BTTV_BOARD_PV143,         "Provideo PV143B" },
+       { 0x1432aa00, BTTV_BOARD_PV143,         "Provideo PV143C" },
+       { 0x1433aa00, BTTV_BOARD_PV143,         "Provideo PV143D" },
+       { 0x1433aa03, BTTV_BOARD_PV143,         "Security Eyes" },
+
+       { 0x1460aa00, BTTV_BOARD_PV150,         "Provideo PV150A-1" },
+       { 0x1461aa01, BTTV_BOARD_PV150,         "Provideo PV150A-2" },
+       { 0x1462aa02, BTTV_BOARD_PV150,         "Provideo PV150A-3" },
+       { 0x1463aa03, BTTV_BOARD_PV150,         "Provideo PV150A-4" },
+
+       { 0x1464aa04, BTTV_BOARD_PV150,         "Provideo PV150B-1" },
+       { 0x1465aa05, BTTV_BOARD_PV150,         "Provideo PV150B-2" },
+       { 0x1466aa06, BTTV_BOARD_PV150,         "Provideo PV150B-3" },
+       { 0x1467aa07, BTTV_BOARD_PV150,         "Provideo PV150B-4" },
+
+       { 0xa132ff00, BTTV_BOARD_IVC100,        "IVC-100"  },
+       { 0xa1550000, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550001, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550002, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550003, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550100, BTTV_BOARD_IVC200,        "IVC-200G" },
+       { 0xa1550101, BTTV_BOARD_IVC200,        "IVC-200G" },
+       { 0xa1550102, BTTV_BOARD_IVC200,        "IVC-200G" },
+       { 0xa1550103, BTTV_BOARD_IVC200,        "IVC-200G" },
+       { 0xa1550800, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550801, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550802, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa1550803, BTTV_BOARD_IVC200,        "IVC-200"  },
+       { 0xa182ff00, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff01, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff02, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff03, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff04, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff05, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff06, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff07, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff08, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff09, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0a, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0b, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0c, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0d, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0e, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xa182ff0f, BTTV_BOARD_IVC120,        "IVC-120G" },
+       { 0xf0500000, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+       { 0xf0500001, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+       { 0xf0500002, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+       { 0xf0500003, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+
+       { 0x41424344, BTTV_BOARD_GRANDTEC,      "GrandTec Multi Capture" },
+       { 0x01020304, BTTV_BOARD_XGUARD,        "Grandtec Grand X-Guard" },
+
+       { 0x18501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+       { 0xa0501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+       { 0x18511851, BTTV_BOARD_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
+       { 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
+       { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
+       { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
+
+       { 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
+       { 0x010114c7, BTTV_BOARD_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
+
+       { 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
+       { 0x217d6606, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+       { 0xfff6f6ff, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+       { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" },
+       { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" },
+       { 0x00790e11, BTTV_BOARD_WINDVR,        "Canopus WinDVR PCI" },
+       { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX,       "Face to Face Tvmax" },
+       { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" },
+       { 0x146caa0c, BTTV_BOARD_PV951,         "ituner spectra8" },
+       { 0x200a1295, BTTV_BOARD_PXC200,        "ImageNation PXC200A" },
+
+       { 0x40111554, BTTV_BOARD_PV_BT878P_9B,  "Prolink Pixelview PV-BT" },
+       { 0x17de0a01, BTTV_BOARD_KWORLD,        "Mecer TV/FM/Video Tuner" },
+
+       { 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" },
+       { 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" },
+       { 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
+       { 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
+
+       { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" },
+
+       { 0x53534149, BTTV_BOARD_SSAI_SECURITY, "SSAI Security Video Interface" },
+       { 0x5353414a, BTTV_BOARD_SSAI_ULTRASOUND, "SSAI Ultrasound Video Interface" },
+
+       /* likely broken, vendor id doesn't match the other magic views ...
+        * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+
+       /* Duplicate PCI ID, reconfigure for this board during the eeprom read.
+       * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB,  "Hauppauge ImpactVCB" }, */
+
+       { 0x109e036e, BTTV_BOARD_CONCEPTRONIC_CTVFMI2,  "Conceptronic CTVFMi v2"},
+
+       /* DVB cards (using pci function .1 for mpeg data xfer) */
+       { 0x001c11bd, BTTV_BOARD_PINNACLESAT,   "Pinnacle PCTV Sat" },
+       { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+       { 0x20007063, BTTV_BOARD_PC_HDTV,       "pcHDTV HD-2000 TV"},
+       { 0x002611bd, BTTV_BOARD_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
+       { 0x00011822, BTTV_BOARD_TWINHAN_DST,   "Twinhan VisionPlus DVB" },
+       { 0xfc00270f, BTTV_BOARD_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
+       { 0x07711461, BTTV_BOARD_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
+       { 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
+       { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
+       { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,    "Ultraview DVB-T Lite" },
+       { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
+       { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
+       { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,    "DViCO FusionHDTV 2" },
+       { 0x763c008a, BTTV_BOARD_GEOVISION_GV600,       "GeoVision GV-600" },
+       { 0x18011000, BTTV_BOARD_ENLTV_FM_2,    "Encore ENL TV-FM-2" },
+       { 0x763d800a, BTTV_BOARD_GEOVISION_GV800S, "GeoVision GV-800(S) (master)" },
+       { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
+       { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
+       { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
+
+       { 0x15401830, BTTV_BOARD_PV183,         "Provideo PV183-1" },
+       { 0x15401831, BTTV_BOARD_PV183,         "Provideo PV183-2" },
+       { 0x15401832, BTTV_BOARD_PV183,         "Provideo PV183-3" },
+       { 0x15401833, BTTV_BOARD_PV183,         "Provideo PV183-4" },
+       { 0x15401834, BTTV_BOARD_PV183,         "Provideo PV183-5" },
+       { 0x15401835, BTTV_BOARD_PV183,         "Provideo PV183-6" },
+       { 0x15401836, BTTV_BOARD_PV183,         "Provideo PV183-7" },
+       { 0x15401837, BTTV_BOARD_PV183,         "Provideo PV183-8" },
+       { 0x3116f200, BTTV_BOARD_TVT_TD3116,    "Tongwei Video Technology TD-3116" },
+       { 0x02280279, BTTV_BOARD_APOSONIC_WDVR, "Aposonic W-DVR" },
+       { 0, -1, NULL }
+};
+
+/* ----------------------------------------------------------------------- */
+/* array with description for bt848 / bt878 tv/grabber cards               */
+
+struct tvcard bttv_tvcards[] = {
+       /* ---- card 0x00 ---------------------------------- */
+       [BTTV_BOARD_UNKNOWN] = {
+               .name           = " *** UNKNOWN/GENERIC *** ",
+               .video_inputs   = 4,
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MIRO] = {
+               .name           = "MIRO PCTV",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 0, 0, 0 },
+               .gpiomute       = 10,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_HAUPPAUGE] = {
+               .name           = "Hauppauge (bt848)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_STB] = {
+               .name           = "STB, Gateway P/N 6000699 (bt848)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 4, 0, 2, 3 },
+               .gpiomute       = 1,
+               .no_msp34xx     = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+       },
+
+       /* ---- card 0x04 ---------------------------------- */
+       [BTTV_BOARD_INTEL] = {
+               .name           = "Intel Create and Share PCI/ Smart Video Recorder III",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 2,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0 },
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_DIAMOND] = {
+               .name           = "Diamond DTV2000",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 3,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0, 1, 0, 1 },
+               .gpiomute       = 3,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_AVERMEDIA] = {
+               .name           = "AVerMedia TVPhone",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomask       = 0x0f,
+               .gpiomux        = { 0x0c, 0x04, 0x08, 0x04 },
+               /*                0x04 for some cards ?? */
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= avermedia_tvphone_audio,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_MATRIX_VISION] = {
+               .name           = "MATRIX-Vision MV-Delta",
+               .video_inputs   = 5,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
+               .gpiomux        = { 0 },
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x08 ---------------------------------- */
+       [BTTV_BOARD_FLYVIDEO] = {
+               .name           = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xc00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0xc00, 0x800, 0x400 },
+               .gpiomute       = 0xc00,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TURBOTV] = {
+               .name           = "IMS/IXmicro TurboTV",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 3,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 1, 2, 3 },
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_HAUPPAUGE878] = {
+               .name           = "Hauppauge (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x0f, /* old: 7 */
+               .muxsel         = MUXSEL(2, 0, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MIROPRO] = {
+               .name           = "MIRO PCTV pro",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x3014f,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x20001,0x10001, 0, 0 },
+               .gpiomute       = 10,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x0c ---------------------------------- */
+       [BTTV_BOARD_ADSTECH_TV] = {
+               .name           = "ADS Technologies Channel Surfer TV (bt848)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 13, 14, 11, 7 },
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_AVERMEDIA98] = {
+               .name           = "AVerMedia TVCapture 98",
+               .video_inputs   = 3,
+               /* .audio_inputs= 4, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 13, 14, 11, 7 },
+               .msp34xx_alt    = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= avermedia_tv_stereo_audio,
+               .no_gpioirq     = 1,
+       },
+       [BTTV_BOARD_VHX] = {
+               .name           = "Aimslab Video Highway Xtreme (VHX)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */
+               .gpiomute       = 4,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ZOLTRIX] = {
+               .name           = "Zoltrix TV-Max",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 1, 0 },
+               .gpiomute       = 10,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x10 ---------------------------------- */
+       [BTTV_BOARD_PIXVIEWPLAYTV] = {
+               .name           = "Prolink Pixelview PlayTV (bt878)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x01fe00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
+               .gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
+               .gpiomute       = 0x002000,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_WINVIEW_601] = {
+               .name           = "Leadtek WinView 601",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x8300f8,
+               .muxsel         = MUXSEL(2, 3, 1, 1, 0),
+               .gpiomux        = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
+               .gpiomute       = 0xcfa007,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .volume_gpio    = winview_volume,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_AVEC_INTERCAP] = {
+               .name           = "AVEC Intercapture",
+               .video_inputs   = 3,
+               /* .audio_inputs= 2, */
+               .svhs           = 2,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 0, 0, 0 },
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_LIFE_FLYKIT] = {
+               .name           = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x8dff00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x14 ---------------------------------- */
+       [BTTV_BOARD_CEI_RAFFLES] = {
+               .name           = "CEI Raffles Card",
+               .video_inputs   = 3,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_CONFERENCETV] = {
+               .name           = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
+               .video_inputs   = 4,
+               /* .audio_inputs= 2,  tuner, line in */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_PHOEBE_TVMAS] = {
+               .name           = "Askey CPH050/ Phoebe Tv Master + FM",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xc00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 0x800, 0x400 },
+               .gpiomute       = 0xc00,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MODTEC_205] = {
+               .name           = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .has_dig_in     = 1,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 0), /* input 2 is digital */
+               /* .digital_mode= DIGITAL_MODE_CAMERA, */
+               .gpiomux        = { 0, 0, 0, 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ALPS_TSBB5_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x18 ---------------------------------- */
+       [BTTV_BOARD_MAGICTVIEW061] = {
+               .name           = "Askey CPH05X/06X (bt878) [many vendors]",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xe00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = {0x400, 0x400, 0x400, 0x400 },
+               .gpiomute       = 0xc00,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+               .has_radio      = 1,  /* not every card has radio */
+       },
+       [BTTV_BOARD_VOBIS_BOOSTAR] = {
+               .name           = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x1f0fff,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
+               .gpiomute       = 0x40000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= terratv_audio,
+       },
+       [BTTV_BOARD_HAUPPAUG_WCAM] = {
+               .name           = "Hauppauge WinCam newer (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 0, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MAXI] = {
+               .name           = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
+               .video_inputs   = 4,
+               /* .audio_inputs= 2, */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x1c ---------------------------------- */
+       [BTTV_BOARD_TERRATV] = {
+               .name           = "Terratec TerraTV+ Version 1.1 (bt878)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x1f0fff,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0x00000 },
+               .gpiomute       = 0x40000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= terratv_audio,
+               /* GPIO wiring:
+               External 20 pin connector (for Active Radio Upgrade board)
+               gpio00: i2c-sda
+               gpio01: i2c-scl
+               gpio02: om5610-data
+               gpio03: om5610-clk
+               gpio04: om5610-wre
+               gpio05: om5610-stereo
+               gpio06: rds6588-davn
+               gpio07: Pin 7 n.c.
+               gpio08: nIOW
+               gpio09+10: nIOR, nSEL ?? (bt878)
+                       gpio09: nIOR (bt848)
+                       gpio10: nSEL (bt848)
+               Sound Routing:
+               gpio16: u2-A0 (1st 4052bt)
+               gpio17: u2-A1
+               gpio18: u2-nEN
+               gpio19: u4-A0 (2nd 4052)
+               gpio20: u4-A1
+                       u4-nEN - GND
+               Btspy:
+                       00000 : Cdrom (internal audio input)
+                       10000 : ext. Video audio input
+                       20000 : TV Mono
+                       a0000 : TV Mono/2
+               1a0000 : TV Stereo
+                       30000 : Radio
+                       40000 : Mute
+       */
+
+       },
+       [BTTV_BOARD_PXC200] = {
+               /* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
+               .name           = "Imagenation PXC200",
+               .video_inputs   = 5,
+               /* .audio_inputs= 1, */
+               .svhs           = 1, /* was: 4 */
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
+               .gpiomux        = { 0 },
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .muxsel_hook    = PXC200_muxsel,
+
+       },
+       [BTTV_BOARD_FLYVIDEO_98] = {
+               .name           = "Lifeview FlyVideo 98 LR50",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,  /* 0x8dfe00 */
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x0800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_IPROTV] = {
+               .name           = "Formac iProTV, Formac ProTV I (bt848)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 1,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 0, 0, 0 },
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x20 ---------------------------------- */
+       [BTTV_BOARD_INTEL_C_S_PCI] = {
+               .name           = "Intel Create and Share PCI/ Smart Video Recorder III",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 2,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0 },
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TERRATVALUE] = {
+               .name           = "Terratec TerraTValue Version Bt878",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xffff00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x500, 0, 0x300, 0x900 },
+               .gpiomute       = 0x900,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_WINFAST2000] = {
+               .name           = "Leadtek WinFast 2000/ WinFast 2000 XP",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               /* TV, CVid, SVid, CVid over SVid connector */
+               .muxsel         = MUXSEL(2, 3, 1, 1, 0),
+               /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
+               .gpiomask       = 0xb33000,
+               .gpiomux        = { 0x122000,0x1000,0x0000,0x620000 },
+               .gpiomute       = 0x800000,
+               /* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
+                       gpio23 -- hef4052:nEnable (0x800000)
+                       gpio12 -- hef4052:A1
+                       gpio13 -- hef4052:A0
+               0x0000: external audio
+               0x1000: FM
+               0x2000: TV
+               0x3000: n.c.
+               Note: There exists another variant "Winfast 2000" with tv stereo !?
+               Note: eeprom only contains FF and pci subsystem id 107d:6606
+               */
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= winfast2000_audio,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_CHRONOS_VS2] = {
+               .name           = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II",
+               .video_inputs   = 4,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x24 ---------------------------------- */
+       [BTTV_BOARD_TYPHOON_TVIEW] = {
+               .name           = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner",
+               .video_inputs   = 4,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_PXELVWPLTVPRO] = {
+               .name           = "Prolink PixelView PlayTV pro",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xff,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x21, 0x20, 0x24, 0x2c },
+               .gpiomute       = 0x29,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MAGICTVIEW063] = {
+               .name           = "Askey CPH06X TView99",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x551e00,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0x551400, 0x551200, 0, 0 },
+               .gpiomute       = 0x551c00,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_PINNACLE] = {
+               .name           = "Pinnacle PCTV Studio/Rave",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x03000F,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 0xd0001, 0, 0 },
+               .gpiomute       = 1,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x28 ---------------------------------- */
+       [BTTV_BOARD_STB2] = {
+               .name           = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 4, 0, 2, 3 },
+               .gpiomute       = 1,
+               .no_msp34xx     = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_AVPHONE98] = {
+               .name           = "AVerMedia TVPhone 98",
+               .video_inputs   = 3,
+               /* .audio_inputs= 4, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 13, 4, 11, 7 },
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+               .audio_mode_gpio= avermedia_tvphone_audio,
+       },
+       [BTTV_BOARD_PV951] = {
+               .name           = "ProVideo PV951", /* pic16c54 */
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 0, 0},
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ONAIR_TV] = {
+               .name           = "Little OnAir TV",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xe00b,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
+               .gpiomute       = 0xff3ffc,
+               .no_msp34xx     = 1,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x2c ---------------------------------- */
+       [BTTV_BOARD_SIGMA_TVII_FM] = {
+               .name           = "Sigma TVII-FM",
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 3,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 1, 0, 2 },
+               .gpiomute       = 3,
+               .no_msp34xx     = 1,
+               .pll            = PLL_NONE,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MATRIX_VISION2] = {
+               .name           = "MATRIX-Vision MV-Delta 2",
+               .video_inputs   = 5,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ZOLTRIX_GENIE] = {
+               .name           = "Zoltrix Genie TV/FM",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xbcf03f,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0xbc803f, 0xbc903f, 0xbcb03f, 0 },
+               .gpiomute       = 0xbcb03f,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_4039FR5_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TERRATVRADIO] = {
+               .name           = "Terratec TV/Radio+",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x70000,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
+               .gpiomute       = 0x40000,
+               .no_msp34xx     = 1,
+               .pll            = PLL_35,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+       },
+
+       /* ---- card 0x30 ---------------------------------- */
+       [BTTV_BOARD_DYNALINK] = {
+               .name           = "Askey CPH03x/ Dynalink Magic TView",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = {2,0,0,0 },
+               .gpiomute       = 1,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_GVBCTV3PCI] = {
+               .name           = "IODATA GV-BCTV3/PCI",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x010f00,
+               .muxsel         = MUXSEL(2, 3, 0, 0),
+               .gpiomux        = {0x10000, 0, 0x10000, 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ALPS_TSHC6_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= gvbctv3pci_audio,
+       },
+       [BTTV_BOARD_PXELVWPLTVPAK] = {
+               .name           = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
+               .video_inputs   = 5,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .has_dig_in     = 1,
+               .gpiomask       = 0xAA0000,
+               .muxsel         = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
+               /* .digital_mode= DIGITAL_MODE_CAMERA, */
+               .gpiomux        = { 0x20000, 0, 0x80000, 0x80000 },
+               .gpiomute       = 0xa8000,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+               /* GPIO wiring: (different from Rev.4C !)
+                       GPIO17: U4.A0 (first hef4052bt)
+                       GPIO19: U4.A1
+                       GPIO20: U5.A1 (second hef4052bt)
+                       GPIO21: U4.nEN
+                       GPIO22: BT832 Reset Line
+                       GPIO23: A5,A0, U5,nEN
+               Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
+               */
+       },
+       [BTTV_BOARD_EAGLE] = {
+               .name           = "Eagle Wireless Capricorn2 (bt878A)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 0, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .pll            = PLL_28,
+               .tuner_type     = UNSET /* TUNER_ALPS_TMDH2_NTSC */,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x34 ---------------------------------- */
+       [BTTV_BOARD_PINNACLEPRO] = {
+               /* David Härdeman <david@2gen.com> */
+               .name           = "Pinnacle PCTV Studio Pro",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 0x03000F,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 0xd0001, 0, 0 },
+               .gpiomute       = 10,
+                               /* sound path (5 sources):
+                               MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
+                                       0= ext. Audio IN
+                                       1= from MUX2
+                                       2= Mono TV sound from Tuner
+                                       3= not connected
+                               MUX2 (mask 0x30000):
+                                       0,2,3= from MSP34xx
+                                       1= FM stereo Radio from Tuner */
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TVIEW_RDS_FM] = {
+               /* Claas Langbehn <claas@bigfoot.com>,
+               Sven Grothklags <sven@upb.de> */
+               .name           = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
+               .video_inputs   = 4,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 0x1c,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 0x10, 8 },
+               .gpiomute       = 4,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_LIFETEC_9415] = {
+               /* Tim Röstermundt <rosterm@uni-muenster.de>
+               in de.comp.os.unix.linux.hardware:
+                       options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
+                       gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
+                       options tuner type=5 */
+               .name           = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x18e0,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x0000,0x0800,0x1000,0x1000 },
+               .gpiomute       = 0x18e0,
+                       /* For cards with tda9820/tda9821:
+                               0x0000: Tuner normal stereo
+                               0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
+                               0x0880: Tuner A2 stereo */
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_BESTBUY_EASYTV] = {
+               /* Miguel Angel Alvarez <maacruz@navegalia.com>
+               old Easy TV BT848 version (model CPH031) */
+               .name           = "Askey CPH031/ BESTBUY Easy TV",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xF,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 2, 0, 0, 0 },
+               .gpiomute       = 10,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x38 ---------------------------------- */
+       [BTTV_BOARD_FLYVIDEO_98FM] = {
+               /* Gordon Heydon <gjheydon@bigfoot.com ('98) */
+               .name           = "Lifeview FlyVideo 98FM LR50",
+               .video_inputs   = 4,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 0x1800,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
+               .gpiomute       = 0x1800,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               /* This is the ultimate cheapo capture card
+               * just a BT848A on a small PCB!
+               * Steve Hosgood <steve@equiinet.com> */
+       [BTTV_BOARD_GRANDTEC] = {
+               .name           = "GrandTec 'Grand Video Capture' (Bt848)",
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(3, 1),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_35,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ASKEY_CPH060] = {
+               /* Daniel Herrington <daniel.herrington@home.com> */
+               .name           = "Askey CPH060/ Phoebe TV Master Only (No FM)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xe00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x400, 0x400, 0x400, 0x400 },
+               .gpiomute       = 0x800,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ASKEY_CPH03X] = {
+               /* Matti Mottus <mottus@physic.ut.ee> */
+               .name           = "Askey CPH03x TV Capturer",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x03000F,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 2, 0, 0, 0 },
+               .gpiomute       = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+       },
+
+       /* ---- card 0x3c ---------------------------------- */
+       [BTTV_BOARD_MM100PCTV] = {
+               /* Philip Blundell <philb@gnu.org> */
+               .name           = "Modular Technology MM100PCTV",
+               .video_inputs   = 2,
+               /* .audio_inputs= 2, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 11,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 0, 0, 1 },
+               .gpiomute       = 8,
+               .pll            = PLL_35,
+               .tuner_type     = TUNER_TEMIC_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_GMV1] = {
+               /* Adrian Cox <adrian@humboldt.co.uk */
+               .name           = "AG Electronics GMV1",
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .gpiomask       = 0xF,
+               .muxsel         = MUXSEL(2, 2),
+               .gpiomux        = { },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_BESTBUY_EASYTV2] = {
+               /* Miguel Angel Alvarez <maacruz@navegalia.com>
+               new Easy TV BT878 version (model CPH061)
+               special thanks to Informatica Mieres for providing the card */
+               .name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 2, */
+               .svhs           = 2,
+               .gpiomask       = 0xFF,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 1, 0, 4, 4 },
+               .gpiomute       = 9,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_ATI_TVWONDER] = {
+               /* Lukas Gebauer <geby@volny.cz> */
+               .name           = "ATI TV-Wonder",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xf03f,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0xbffe, 0, 0xbfff, 0 },
+               .gpiomute       = 0xbffe,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x40 ---------------------------------- */
+       [BTTV_BOARD_ATI_TVWONDERVE] = {
+               /* Lukas Gebauer <geby@volny.cz> */
+               .name           = "ATI TV-Wonder VE",
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 1,
+               .muxsel         = MUXSEL(2, 3, 0, 1),
+               .gpiomux        = { 0, 0, 1, 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_FLYVIDEO2000] = {
+               /* DeeJay <deejay@westel900.net (2000S) */
+               .name           = "Lifeview FlyVideo 2000S LR90",
+               .video_inputs   = 3,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 0x18e0,
+               .muxsel         = MUXSEL(2, 3, 0, 1),
+                               /* Radio changed from 1e80 to 0x800 to make
+                               FlyVideo2000S in .hu happy (gm)*/
+                               /* -dk-???: set mute=0x1800 for tda9874h daughterboard */
+               .gpiomux        = { 0x0000,0x0800,0x1000,0x1000 },
+               .gpiomute       = 0x1800,
+               .audio_mode_gpio= fv2000s_audio,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TERRATVALUER] = {
+               .name           = "Terratec TValueRadio",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0xffff00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x500, 0x500, 0x300, 0x900 },
+               .gpiomute       = 0x900,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_GVBCTV4PCI] = {
+               /* TANAKA Kei <peg00625@nifty.com> */
+               .name           = "IODATA GV-BCTV4/PCI",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x010f00,
+               .muxsel         = MUXSEL(2, 3, 0, 0),
+               .gpiomux        = {0x10000, 0, 0x10000, 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_SHARP_2U5JF5540_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= gvbctv3pci_audio,
+       },
+
+       /* ---- card 0x44 ---------------------------------- */
+       [BTTV_BOARD_VOODOOTV_FM] = {
+               .name           = "3Dfx VoodooTV FM (Euro)",
+               /* try "insmod msp3400 simple=0" if you have
+               * sound problems with this card. */
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x4f8a00,
+               /* 0x100000: 1=MSP enabled (0=disable again)
+               * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+               .gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
+               .gpiomute       = 0x947fff,
+               /* tvtuner, radio,   external,internal, mute,  stereo
+               * tuner, Composit, SVid, Composit-on-Svid-adapter */
+               .muxsel         = MUXSEL(2, 3, 0, 1),
+               .tuner_type     = TUNER_MT2032,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_VOODOOTV_200] = {
+               .name           = "VoodooTV 200 (USA)",
+               /* try "insmod msp3400 simple=0" if you have
+               * sound problems with this card. */
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x4f8a00,
+               /* 0x100000: 1=MSP enabled (0=disable again)
+               * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+               .gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
+               .gpiomute       = 0x947fff,
+               /* tvtuner, radio,   external,internal, mute,  stereo
+               * tuner, Composit, SVid, Composit-on-Svid-adapter */
+               .muxsel         = MUXSEL(2, 3, 0, 1),
+               .tuner_type     = TUNER_MT2032,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_AIMMS] = {
+               /* Philip Blundell <pb@nexus.co.uk> */
+               .name           = "Active Imaging AIMMS",
+               .video_inputs   = 1,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .muxsel         = MUXSEL(2),
+               .gpiomask       = 0
+       },
+       [BTTV_BOARD_PV_BT878P_PLUS] = {
+               /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+               .name           = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 4, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */
+               .gpiomute       = 13,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_LG_PAL_I_FM,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+               /* GPIO wiring:
+                       GPIO0: U4.A0 (hef4052bt)
+                       GPIO1: U4.A1
+                       GPIO2: U4.A1 (second hef4052bt)
+                       GPIO3: U4.nEN, U5.A0, A5.nEN
+                       GPIO8-15: vrd866b ?
+               */
+       },
+       [BTTV_BOARD_FLYVIDEO98EZ] = {
+               .name           = "Lifeview FlyVideo 98EZ (capture only) LR51",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 2,
+               /* AV1, AV2, SVHS, CVid adapter on SVHS */
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+       /* ---- card 0x48 ---------------------------------- */
+       [BTTV_BOARD_PV_BT878P_9B] = {
+               /* Dariusz Kowalewski <darekk@automex.pl> */
+               .name           = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x3f,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x01, 0x00, 0x03, 0x03 },
+               .gpiomute       = 0x09,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */
+               .has_radio      = 1,  /* Note: not all cards have radio */
+               .has_remote     = 1,
+               /* GPIO wiring:
+                       GPIO0: A0 hef4052
+                       GPIO1: A1 hef4052
+                       GPIO3: nEN hef4052
+                       GPIO8-15: vrd866b
+                       GPIO20,22,23: R30,R29,R28
+               */
+       },
+       [BTTV_BOARD_SENSORAY311_611] = {
+               /* Clay Kunz <ckunz@mail.arc.nasa.gov> */
+               /* you must jumper JP5 for the 311 card (PC/104+) to work */
+               .name           = "Sensoray 311/611",
+               .video_inputs   = 5,
+               /* .audio_inputs= 0, */
+               .svhs           = 4,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
+               .gpiomux        = { 0 },
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_RV605] = {
+               /* Miguel Freitas <miguel@cetuc.puc-rio.br> */
+               .name           = "RemoteVision MX (RV605)",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x00,
+               .gpiomask2      = 0x07ff,
+               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
+               .no_msp34xx     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .muxsel_hook    = rv605_muxsel,
+       },
+       [BTTV_BOARD_POWERCLR_MTV878] = {
+               .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
+               .video_inputs   = 3,
+               /* .audio_inputs= 2, */
+               .svhs           = 2,
+               .gpiomask       = 0x1C800F,  /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
+               .muxsel         = MUXSEL(2, 1, 1),
+               .gpiomux        = { 0, 1, 2, 2 },
+               .gpiomute       = 4,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+       },
+
+       /* ---- card 0x4c ---------------------------------- */
+       [BTTV_BOARD_WINDVR] = {
+               /* Masaki Suzuki <masaki@btree.org> */
+               .name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x140007,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= windvr_audio,
+       },
+       [BTTV_BOARD_GRANDTEC_MULTI] = {
+               .name           = "GrandTec Multi Capture Card (Bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_KWORLD] = {
+               .name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
+               .video_inputs   = 4,
+               /* .audio_inputs= 3, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               /* Tuner, SVid, SVHS, SVid to SVHS connector */
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio!
+                                               * This card lacks external Audio In, so we mute it on Ext. & Int.
+                                               * The PCB can take a sbx1637/sbx1673, wiring unknown.
+                                               * This card lacks PCI subsystem ID, sigh.
+                                               * gpiomux =1: lower volume, 2+3: mute
+                                               * btwincap uses 0x80000/0x80003
+                                               */
+               .gpiomute       = 4,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
+               radio signal strength indicators work fine. */
+               .has_radio      = 1,
+               /* GPIO Info:
+                       GPIO0,1:   HEF4052 A0,A1
+                       GPIO2:     HEF4052 nENABLE
+                       GPIO3-7:   n.c.
+                       GPIO8-13:  IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card]
+                       GPIO14,15: ??
+                       GPIO16-21: n.c.
+                       GPIO22,23: ??
+                       ??       : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
+       },
+       [BTTV_BOARD_DSP_TCVIDEO] = {
+               /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
+               .name           = "DSP Design TCVIDEO",
+               .video_inputs   = 4,
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+               /* ---- card 0x50 ---------------------------------- */
+       [BTTV_BOARD_HAUPPAUGEPVR] = {
+               .name           = "Hauppauge WinTV PVR",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 0, 1, 1),
+               .pll            = PLL_28,
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+
+               .gpiomask       = 7,
+               .gpiomux        = {7},
+       },
+       [BTTV_BOARD_GVBCTV5PCI] = {
+               .name           = "IODATA GV-BCTV5/PCI",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x0f0f80,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = {0x030000, 0x010000, 0, 0 },
+               .gpiomute       = 0x020000,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= gvbctv5pci_audio,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_OSPREY1x0] = {
+               .name           = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */
+               .video_inputs   = 4,                  /* id-inputs-clock */
+               /* .audio_inputs= 0, */
+               .svhs           = 3,
+               .muxsel         = MUXSEL(3, 2, 0, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY1x0_848] = {
+               .name           = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
+               .video_inputs   = 3,
+               /* .audio_inputs= 0, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+
+               /* ---- card 0x54 ---------------------------------- */
+       [BTTV_BOARD_OSPREY101_848] = {
+               .name           = "Osprey 101 (848)", /* 0x05-40C0-C1 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(3, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY1x1] = {
+               .name           = "Osprey 101/151",       /* 0x1(4|5)-0004-C4 */
+               .video_inputs   = 1,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(0),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY1x1_SVID] = {
+               .name           = "Osprey 101/151 w/ svid",  /* 0x(16|17|20)-00C4-C1 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(0, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY2xx] = {
+               .name           = "Osprey 200/201/250/251",  /* 0x1(8|9|E|F)-0004-C4 */
+               .video_inputs   = 1,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(0),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+
+               /* ---- card 0x58 ---------------------------------- */
+       [BTTV_BOARD_OSPREY2x0_SVID] = {
+               .name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(0, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY2x0] = {
+               .name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(2, 3),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY500] = {
+               .name           = "Osprey 500",   /* 500 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(2, 3),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       [BTTV_BOARD_OSPREY540] = {
+               .name           = "Osprey 540",   /* 540 */
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+
+               /* ---- card 0x5C ---------------------------------- */
+       [BTTV_BOARD_OSPREY2000] = {
+               .name           = "Osprey 2000",  /* 2000 */
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(2, 3),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
+       },
+       [BTTV_BOARD_IDS_EAGLE] = {
+               /* M G Berberich <berberic@forwiss.uni-passau.de> */
+               .name           = "IDS Eagle",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .muxsel_hook    = eagle_muxsel,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_PINNACLESAT] = {
+               .name           = "Pinnacle PCTV Sat",
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel         = MUXSEL(3, 1),
+               .pll            = PLL_28,
+               .no_gpioirq     = 1,
+               .has_dvb        = 1,
+       },
+       [BTTV_BOARD_FORMAC_PROTV] = {
+               .name           = "Formac ProTV II (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .gpiomask       = 2,
+               /* TV, Comp1, Composite over SVID con, SVID */
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 2, 0, 0 },
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+       /* sound routing:
+               GPIO=0x00,0x01,0x03: mute (?)
+               0x02: both TV and radio (tuner: FM1216/I)
+               The card has onboard audio connectors labeled "cdrom" and "board",
+               not soldered here, though unknown wiring.
+               Card lacks: external audio in, pci subsystem id.
+       */
+       },
+
+               /* ---- card 0x60 ---------------------------------- */
+       [BTTV_BOARD_MACHTV] = {
+               .name           = "MachTV",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3},
+               .gpiomute       = 4,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_EURESYS_PICOLO] = {
+               .name           = "Euresys Picolo",
+               .video_inputs   = 3,
+               /* .audio_inputs= 0, */
+               .svhs           = 2,
+               .gpiomask       = 0,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel         = MUXSEL(2, 0, 1),
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_PV150] = {
+               /* Luc Van Hoeylandt <luc@e-magic.be> */
+               .name           = "ProVideo PV150", /* 0x4f */
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_AD_TVK503] = {
+               /* Hiroshi Takekawa <sian@big.or.jp> */
+               /* This card lacks subsystem ID */
+               .name           = "AD-TVK503", /* 0x63 */
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x001e8007,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               /*                  Tuner, Radio, external, internal, off,  on */
+               .gpiomux        = { 0x08,  0x0f,  0x0a,     0x08 },
+               .gpiomute       = 0x0f,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .audio_mode_gpio= adtvk503_audio,
+       },
+
+               /* ---- card 0x64 ---------------------------------- */
+       [BTTV_BOARD_HERCULES_SM_TV] = {
+               .name           = "Hercules Smart TV Stereo",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               /* Notes:
+               - card lacks subsystem ID
+               - stereo variant w/ daughter board with tda9874a @0xb0
+               - Audio Routing:
+                       always from tda9874 independent of GPIO (?)
+                       external line in: unknown
+               - Other chips: em78p156elp @ 0x96 (probably IR remote control)
+                       hef4053 (instead 4052) for unknown function
+               */
+       },
+       [BTTV_BOARD_PACETV] = {
+               .name           = "Pace TV & Radio Card",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               /* Tuner, CVid, SVid, CVid over SVid connector */
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomask       = 0,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+               .pll            = PLL_28,
+               /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+               only internal line out: (4pin header) RGGL
+               Radio must be decoded by msp3410d (not routed through)*/
+               /*
+               .digital_mode   = DIGITAL_MODE_CAMERA,  todo!
+               */
+       },
+       [BTTV_BOARD_IVC200] = {
+               /* Chris Willing <chris@vislab.usyd.edu.au> */
+               .name           = "IVC-200",
+               .video_inputs   = 1,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0xdf,
+               .muxsel         = MUXSEL(2),
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_IVCE8784] = {
+               .name           = "IVCE-8784",
+               .video_inputs   = 1,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0xdf,
+               .muxsel         = MUXSEL(2),
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_XGUARD] = {
+               .name           = "Grand X-Guard / Trust 814PCI",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .gpiomask2      = 0xff,
+               .muxsel         = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0),
+               .muxsel_hook    = xguard_muxsel,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+       },
+
+               /* ---- card 0x68 ---------------------------------- */
+       [BTTV_BOARD_NEBULA_DIGITV] = {
+               .name           = "Nebula Electronics DigiTV",
+               .video_inputs   = 1,
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .has_dvb        = 1,
+               .has_remote     = 1,
+               .gpiomask       = 0x1b,
+               .no_gpioirq     = 1,
+       },
+       [BTTV_BOARD_PV143] = {
+               /* Jorge Boncompte - DTI2 <jorge@dti2.net> */
+               .name           = "ProVideo PV143",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_VD009X1_VD011_MINIDIN] = {
+               /* M.Klahr@phytec.de */
+               .name           = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 3,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_VD009X1_VD011_COMBI] = {
+               .name           = "PHYTEC VD-009-X1 VD-011 Combi (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 3,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+
+               /* ---- card 0x6c ---------------------------------- */
+       [BTTV_BOARD_VD009_MINIDIN] = {
+               .name           = "PHYTEC VD-009 MiniDIN (bt878)",
+               .video_inputs   = 10,
+               /* .audio_inputs= 0, */
+               .svhs           = 9,
+               .gpiomask       = 0x00,
+               .gpiomask2      = 0x03, /* used for external vodeo mux */
+               .muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 0),
+               .muxsel_hook    = phytec_muxsel,
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_VD009_COMBI] = {
+               .name           = "PHYTEC VD-009 Combi (bt878)",
+               .video_inputs   = 10,
+               /* .audio_inputs= 0, */
+               .svhs           = 9,
+               .gpiomask       = 0x00,
+               .gpiomask2      = 0x03, /* used for external vodeo mux */
+               .muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 1),
+               .muxsel_hook    = phytec_muxsel,
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_IVC100] = {
+               .name           = "IVC-100",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0xdf,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_IVC120] = {
+               /* IVC-120G - Alan Garfield <alan@fromorbit.com> */
+               .name           = "IVC-120G",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,   /* card has no svhs */
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+               .muxsel_hook    = ivc120_muxsel,
+               .pll            = PLL_28,
+       },
+
+               /* ---- card 0x70 ---------------------------------- */
+       [BTTV_BOARD_PC_HDTV] = {
+               .name           = "pcHDTV HD-2000 TV",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
+               .tuner_addr     = ADDR_UNSET,
+               .has_dvb        = 1,
+       },
+       [BTTV_BOARD_TWINHAN_DST] = {
+               .name           = "Twinhan DST + clones",
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_video       = 1,
+               .has_dvb        = 1,
+       },
+       [BTTV_BOARD_WINFASTVC100] = {
+               .name           = "Winfast VC100",
+               .video_inputs   = 3,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               /* Vid In, SVid In, Vid over SVid in connector */
+               .muxsel         = MUXSEL(3, 1, 1, 3),
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+       },
+       [BTTV_BOARD_TEV560] = {
+               .name           = "Teppro TEV-560/InterVision IV-560",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 3,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 1, 1, 1, 1 },
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_35,
+       },
+
+               /* ---- card 0x74 ---------------------------------- */
+       [BTTV_BOARD_SIMUS_GVC1100] = {
+               .name           = "SIMUS GVC1100",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .gpiomask       = 0x3F,
+               .muxsel_hook    = gvc1100_muxsel,
+       },
+       [BTTV_BOARD_NGSTV_PLUS] = {
+               /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
+               .name           = "NGS NGSTV+",
+               .video_inputs   = 3,
+               .svhs           = 2,
+               .gpiomask       = 0x008007,
+               .muxsel         = MUXSEL(2, 3, 0, 0),
+               .gpiomux        = { 0, 0, 0, 0 },
+               .gpiomute       = 0x000003,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_LMLBT4] = {
+               /* http://linuxmedialabs.com */
+               .name           = "LMLBT4",
+               .video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TEKRAM_M205] = {
+               /* Helmroos Harri <harri.helmroos@pp.inet.fi> */
+               .name           = "Tekram M205 PRO",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = 2,
+               .gpiomask       = 0x68,
+               .muxsel         = MUXSEL(2, 3, 1),
+               .gpiomux        = { 0x68, 0x68, 0x61, 0x61 },
+               .pll            = PLL_28,
+       },
+
+               /* ---- card 0x78 ---------------------------------- */
+       [BTTV_BOARD_CONTVFMI] = {
+               /* Javier Cendan Ares <jcendan@lycos.es> */
+               /* bt878 TV + FM without subsystem ID */
+               .name           = "Conceptronic CONTVFMi",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x008007,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 2 },
+               .gpiomute       = 3,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_PICOLO_TETRA_CHIP] = {
+               /*Eric DEBIEF <debief@telemsa.com>*/
+               /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controlled*/
+               /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the following declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/
+               /*0x79 in bttv.h*/
+               .name           = "Euresys Picolo Tetra",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .gpiomask2      = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               /*878A input is always MUX0, see above.*/
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_SPIRIT_TV] = {
+               /* Spirit TV Tuner from http://spiritmodems.com.au */
+               /* Stafford Goodsell <surge@goliath.homeunix.org> */
+               .name           = "Spirit TV Tuner",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x0000000f,
+               .muxsel         = MUXSEL(2, 1, 1),
+               .gpiomux        = { 0x02, 0x00, 0x00, 0x00 },
+               .tuner_type     = TUNER_TEMIC_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+       },
+       [BTTV_BOARD_AVDVBT_771] = {
+               /* Wolfram Joost <wojo@frokaschwei.de> */
+               .name           = "AVerMedia AVerTV DVB-T 771",
+               .video_inputs   = 2,
+               .svhs           = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .muxsel         = MUXSEL(3, 3),
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+               .has_dvb        = 1,
+               .no_gpioirq     = 1,
+               .has_remote     = 1,
+       },
+               /* ---- card 0x7c ---------------------------------- */
+       [BTTV_BOARD_AVDVBT_761] = {
+               /* Matt Jesson <dvb@jesson.eclipse.co.uk> */
+               /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */
+               .name           = "AverMedia AverTV DVB-T 761",
+               .video_inputs   = 2,
+               .svhs           = 1,
+               .muxsel         = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .has_dvb        = 1,
+               .no_gpioirq     = 1,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_MATRIX_VISIONSQ] = {
+               /* andre.schwarz@matrix-vision.de */
+               .name           = "MATRIX Vision Sigma-SQ",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x0,
+               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3),
+               .muxsel_hook    = sigmaSQ_muxsel,
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MATRIX_VISIONSLC] = {
+               /* andre.schwarz@matrix-vision.de */
+               .name           = "MATRIX Vision Sigma-SLC",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x0,
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .muxsel_hook    = sigmaSLC_muxsel,
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               /* BTTV_BOARD_APAC_VIEWCOMP */
+       [BTTV_BOARD_APAC_VIEWCOMP] = {
+               /* Attila Kondoros <attila.kondoros@chello.hu> */
+               /* bt878 TV + FM 0x00000000 subsystem ID */
+               .name           = "APAC Viewcomp 878(AMAX)",
+               .video_inputs   = 2,
+               /* .audio_inputs= 1, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0xFF,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 0, 0, 0 },
+               .gpiomute       = 10,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
+               .has_radio      = 1,   /* not every card has radio */
+       },
+
+               /* ---- card 0x80 ---------------------------------- */
+       [BTTV_BOARD_DVICO_DVBT_LITE] = {
+               /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
+               .name           = "DViCO FusionHDTV DVB-T Lite",
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+               .no_video       = 1,
+               .has_dvb        = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_VGEAR_MYVCD] = {
+               /* Steven <photon38@pchome.com.tw> */
+               .name           = "V-Gear MyVCD",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x3f,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .gpiomux        = {0x31, 0x31, 0x31, 0x31 },
+               .gpiomute       = 0x31,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 0,
+       },
+       [BTTV_BOARD_SUPER_TV] = {
+               /* Rick C <cryptdragoon@gmail.com> */
+               .name           = "Super TV Tuner",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+               .gpiomask       = 0x008007,
+               .gpiomux        = { 0, 0x000001,0,0 },
+               .has_radio      = 1,
+       },
+       [BTTV_BOARD_TIBET_CS16] = {
+               /* Chris Fanning <video4linux@haydon.net> */
+               .name           = "Tibet Systems 'Progress DVR' CS16",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .muxsel_hook    = tibetCS16_muxsel,
+       },
+       [BTTV_BOARD_KODICOM_4400R] = {
+               /* Bill Brack <wbrack@mmm.com.hk> */
+               /*
+               * Note that, because of the card's wiring, the "master"
+               * BT878A chip (i.e. the one which controls the analog switch
+               * and must use this card type) is the 2nd one detected.  The
+               * other 3 chips should use card type 0x85, whose description
+               * follows this one.  There is a EEPROM on the card (which is
+               * connected to the I2C of one of those other chips), but is
+               * not currently handled.  There is also a facility for a
+               * "monitor", which is also not currently implemented.
+               */
+               .name           = "Kodicom 4400R (master)",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               /* GPIO bits 0-9 used for analog switch:
+               *   00 - 03:    camera selector
+               *   04 - 06:    channel (controller) selector
+               *   07: data (1->on, 0->off)
+               *   08: strobe
+               *   09: reset
+               * bit 16 is input from sync separator for the channel
+               */
+               .gpiomask       = 0x0003ff,
+               .no_gpioirq     = 1,
+               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel_hook    = kodicom4400r_muxsel,
+       },
+       [BTTV_BOARD_KODICOM_4400R_SL] = {
+               /* Bill Brack <wbrack@mmm.com.hk> */
+               /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
+               * one which controls the analog switch, and must use the card type)
+               * is the 2nd one detected.  The other 3 chips should use this card
+               * type
+               */
+               .name           = "Kodicom 4400R (slave)",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x010000,
+               .no_gpioirq     = 1,
+               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel_hook    = kodicom4400r_muxsel,
+       },
+               /* ---- card 0x86---------------------------------- */
+       [BTTV_BOARD_ADLINK_RTV24] = {
+               /* Michael Henson <mhenson@clarityvi.com> */
+               /* Adlink RTV24 with special unlock codes */
+               .name           = "Adlink RTV24",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .tuner_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+       },
+               /* ---- card 0x87---------------------------------- */
+       [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
+               /* Michael Krufky <mkrufky@m1k.net> */
+               .name           = "DViCO FusionHDTV 5 Lite",
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+               .tuner_addr     = ADDR_UNSET,
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1),
+               .gpiomask       = 0x00e00007,
+               .gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
+               .gpiomute       = 0x00c00007,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .has_dvb        = 1,
+       },
+               /* ---- card 0x88---------------------------------- */
+       [BTTV_BOARD_ACORP_Y878F] = {
+               /* Mauro Carvalho Chehab <mchehab@infradead.org> */
+               .name           = "Acorp Y878F",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x01fe00,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
+               .gpiomute       = 0x002000,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_YMEC_TVF66T5_B_DFF,
+               .tuner_addr     = 0xc1 >>1,
+               .has_radio      = 1,
+       },
+               /* ---- card 0x89 ---------------------------------- */
+       [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = {
+               .name           = "Conceptronic CTVFMi v2",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x001c0007,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 2 },
+               .gpiomute       = 3,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TENA_9533_DI,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+               .has_radio      = 1,
+       },
+               /* ---- card 0x8a ---------------------------------- */
+       [BTTV_BOARD_PV_BT878P_2E] = {
+               .name           = "Prolink Pixelview PV-BT878P+ (Rev.2E)",
+               .video_inputs   = 5,
+               /* .audio_inputs= 1, */
+               .svhs           = 3,
+               .has_dig_in     = 1,
+               .gpiomask       = 0x01fe00,
+               .muxsel         = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
+               /* .digital_mode= DIGITAL_MODE_CAMERA, */
+               .gpiomux        = { 0x00400, 0x10400, 0x04400, 0x80000 },
+               .gpiomute       = 0x12400,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_LG_PAL_FM,
+               .tuner_addr     = ADDR_UNSET,
+               .has_remote     = 1,
+       },
+               /* ---- card 0x8b ---------------------------------- */
+       [BTTV_BOARD_PV_M4900] = {
+               /* Sérgio Fortier <sergiofortier@yahoo.com.br> */
+               .name           = "Prolink PixelView PlayTV MPEG2 PV-M4900",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x3f,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x21, 0x20, 0x24, 0x2c },
+               .gpiomute       = 0x29,
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_YMEC_TVF_5533MF,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
+               /* ---- card 0x8c ---------------------------------- */
+       /* Has four Bt878 chips behind a PCI bridge, each chip has:
+            one external BNC composite input (mux 2)
+            three internal composite inputs (unknown muxes)
+            an 18-bit stereo A/D (CS5331A), which has:
+              one external stereo unblanced (RCA) audio connection
+              one (or 3?) internal stereo balanced (XLR) audio connection
+              input is selected via gpio to a 14052B mux
+                (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300)
+              gain is controlled via an X9221A chip on the I2C bus @0x28
+              sample rate is controlled via gpio to an MK1413S
+                (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3)
+            There is neither a tuner nor an svideo input. */
+       [BTTV_BOARD_OSPREY440]  = {
+               .name           = "Osprey 440",
+               .video_inputs   = 4,
+               /* .audio_inputs= 2, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 3, 0, 1), /* 3,0,1 are guesses */
+               .gpiomask       = 0x303,
+               .gpiomute       = 0x000, /* int + 32kHz */
+               .gpiomux        = { 0, 0, 0x000, 0x100},
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+               /* ---- card 0x8d ---------------------------------- */
+       [BTTV_BOARD_ASOUND_SKYEYE] = {
+               .name           = "Asound Skyeye PCTV",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 15,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 2, 0, 0, 0 },
+               .gpiomute       = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               /* ---- card 0x8e ---------------------------------- */
+       [BTTV_BOARD_SABRENT_TVFM] = {
+               .name           = "Sabrent TV-FM (bttv version)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x108007,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 100000, 100002, 100002, 100000 },
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .tuner_addr     = ADDR_UNSET,
+               .has_radio      = 1,
+       },
+       /* ---- card 0x8f ---------------------------------- */
+       [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
+               .name           = "Hauppauge ImpactVCB (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x0f, /* old: 7 */
+               .muxsel         = MUXSEL(0, 1, 3, 2), /* Composite 0-3 */
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_MACHTV_MAGICTV] = {
+               /* Julian Calaby <julian.calaby@gmail.com>
+                * Slightly different from original MachTV definition (0x60)
+
+                * FIXME: RegSpy says gpiomask should be "0x001c800f", but it
+                * stuffs up remote chip. Bug is a pin on the jaecs is not set
+                * properly (methinks) causing no keyup bits being set */
+
+               .name           = "MagicTV", /* rebranded MachTV */
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 7,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 3 },
+               .gpiomute       = 4,
+               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_SSAI_SECURITY] = {
+               .name           = "SSAI Security Video Interface",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(0, 1, 2, 3),
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_SSAI_ULTRASOUND] = {
+               .name           = "SSAI Ultrasound Video Interface",
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = 1,
+               .muxsel         = MUXSEL(2, 0, 1, 3),
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       /* ---- card 0x94---------------------------------- */
+       [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+               .name           = "DViCO FusionHDTV 2",
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
+               .tuner_addr     = ADDR_UNSET,
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .muxsel         = MUXSEL(2, 3, 1),
+               .gpiomask       = 0x00e00007,
+               .gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
+               .gpiomute       = 0x00c00007,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+       },
+       /* ---- card 0x95---------------------------------- */
+       [BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
+               .name           = "Typhoon TV-Tuner PCI (50684)",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x3014f,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0x20001,0x10001, 0, 0 },
+               .gpiomute       = 10,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_GEOVISION_GV600] = {
+               /* emhn@usb.ve */
+               .name           = "Geovision GV-600",
+               .video_inputs   = 16,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x0,
+               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+               .muxsel_hook    = geovision_muxsel,
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_KOZUMI_KTV_01C] = {
+               /* Mauro Lacy <mauro@lacy.com.ar>
+                * Based on MagicTV and Conceptronic CONTVFMi */
+
+               .name           = "Kozumi KTV-01C",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               .gpiomask       = 0x008007,
+               .muxsel         = MUXSEL(2, 3, 1, 1),
+               .gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
+               .gpiomute       = 3, /* CONTVFMi */
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
+       [BTTV_BOARD_ENLTV_FM_2] = {
+               /* Encore TV Tuner Pro ENL TV-FM-2
+                  Mauro Carvalho Chehab <mchehab@infradead.org */
+               .name           = "Encore ENL TV-FM-2",
+               .video_inputs   = 3,
+               /* .audio_inputs= 1, */
+               .svhs           = 2,
+               /* bit 6          -> IR disabled
+                  bit 18/17 = 00 -> mute
+                              01 -> enable external audio input
+                              10 -> internal audio input (mono?)
+                              11 -> internal audio input
+                */
+               .gpiomask       = 0x060040,
+               .muxsel         = MUXSEL(2, 3, 3),
+               .gpiomux        = { 0x60000, 0x60000, 0x20000, 0x20000 },
+               .gpiomute       = 0,
+               .tuner_type     = TUNER_TCL_MF02GIP_5N,
+               .tuner_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       },
+               [BTTV_BOARD_VD012] = {
+               /* D.Heer@Phytec.de */
+               .name           = "PHYTEC VD-012 (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(0, 2, 3, 1),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               [BTTV_BOARD_VD012_X1] = {
+               /* D.Heer@Phytec.de */
+               .name           = "PHYTEC VD-012-X1 (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 3,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(2, 3, 1),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               [BTTV_BOARD_VD012_X2] = {
+               /* D.Heer@Phytec.de */
+               .name           = "PHYTEC VD-012-X2 (bt878)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 0, */
+               .svhs           = 3,
+               .gpiomask       = 0x00,
+               .muxsel         = MUXSEL(3, 2, 1),
+               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+               [BTTV_BOARD_GEOVISION_GV800S] = {
+               /* Bruno Christo <bchristo@inf.ufsm.br>
+                *
+                * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
+                *      1 audio input  per BT878A = 4 audio inputs
+                *      4 video inputs per BT878A = 16 video inputs
+                * This is the first BT878A chip of the GV-800(S). It's the
+                * "master" chip and it controls the video inputs through an
+                * analog multiplexer (a CD22M3494) via some GPIO pins. The
+                * slaves should use card type 0x9e (following this one).
+                * There is a EEPROM on the card which is currently not handled.
+                * The audio input is not working yet.
+                */
+               .name           = "Geovision GV-800(S) (master)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0xf107f,
+               .no_gpioirq     = 1,
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel_hook    = gv800s_muxsel,
+       },
+               [BTTV_BOARD_GEOVISION_GV800S_SL] = {
+               /* Bruno Christo <bchristo@inf.ufsm.br>
+                *
+                * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
+                *      1 audio input  per BT878A = 4 audio inputs
+                *      4 video inputs per BT878A = 16 video inputs
+                * The 3 other BT878A chips are "slave" chips of the GV-800(S)
+                * and should use this card type.
+                * The audio input is not working yet.
+                */
+               .name           = "Geovision GV-800(S) (slave)",
+               .video_inputs   = 4,
+               /* .audio_inputs= 1, */
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0x00,
+               .no_gpioirq     = 1,
+               .muxsel         = MUXSEL(2, 2, 2, 2),
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda7432     = 1,
+               .muxsel_hook    = gv800s_muxsel,
+       },
+       [BTTV_BOARD_PV183] = {
+               .name           = "ProVideo PV183", /* 0x9f */
+               .video_inputs   = 2,
+               /* .audio_inputs= 0, */
+               .svhs           = NO_SVHS,
+               .gpiomask       = 0,
+               .muxsel         = MUXSEL(2, 3),
+               .gpiomux        = { 0 },
+               .no_msp34xx     = 1,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = ADDR_UNSET,
+       },
+       [BTTV_BOARD_TVT_TD3116] = {
+               .name           = "Tongwei Video Technology TD-3116",
+               .video_inputs   = 16,
+               .gpiomask       = 0xc00ff,
+               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+               .muxsel_hook    = td3116_muxsel,
+               .svhs           = NO_SVHS,
+               .pll            = PLL_28,
+               .tuner_type     = TUNER_ABSENT,
+       },
+       [BTTV_BOARD_APOSONIC_WDVR] = {
+               .name           = "Aposonic W-DVR",
+               .video_inputs   = 4,
+               .svhs           = NO_SVHS,
+               .muxsel         = MUXSEL(2, 3, 1, 0),
+               .tuner_type     = TUNER_ABSENT,
+       },
+
+};
+
+static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
+
+/* ----------------------------------------------------------------------- */
+
+static unsigned char eeprom_data[256];
+
+/*
+ * identify card
+ */
+void __devinit bttv_idcard(struct bttv *btv)
+{
+       unsigned int gpiobits;
+       int i,type;
+
+       /* read PCI subsystem ID */
+       btv->cardid  = btv->c.pci->subsystem_device << 16;
+       btv->cardid |= btv->c.pci->subsystem_vendor;
+
+       if (0 != btv->cardid && 0xffffffff != btv->cardid) {
+               /* look for the card */
+               for (type = -1, i = 0; cards[i].id != 0; i++)
+                       if (cards[i].id  == btv->cardid)
+                               type = i;
+
+               if (type != -1) {
+                       /* found it */
+                       pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+                               btv->c.nr, cards[type].name, cards[type].cardnr,
+                               btv->cardid & 0xffff,
+                               (btv->cardid >> 16) & 0xffff);
+                       btv->c.type = cards[type].cardnr;
+               } else {
+                       /* 404 */
+                       pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+                               btv->c.nr, btv->cardid & 0xffff,
+                               (btv->cardid >> 16) & 0xffff);
+                       pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
+               }
+       }
+
+       /* let the user override the autodetected type */
+       if (card[btv->c.nr] < bttv_num_tvcards)
+               btv->c.type=card[btv->c.nr];
+
+       /* print which card config we are using */
+       pr_info("%d: using: %s [card=%d,%s]\n",
+               btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+               card[btv->c.nr] < bttv_num_tvcards
+               ? "insmod option" : "autodetected");
+
+       /* overwrite gpio stuff ?? */
+       if (UNSET == audioall && UNSET == audiomux[0])
+               return;
+
+       if (UNSET != audiomux[0]) {
+               gpiobits = 0;
+               for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+                       bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
+                       gpiobits |= audiomux[i];
+               }
+       } else {
+               gpiobits = audioall;
+               for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+                       bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
+               }
+       }
+       bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
+       pr_info("%d: gpio config override: mask=0x%x, mux=",
+               btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
+       for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+               pr_cont("%s0x%x",
+                       i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+       }
+       pr_cont("\n");
+}
+
+/*
+ * (most) board specific initialisations goes here
+ */
+
+/* Some Modular Technology cards have an eeprom, but no subsystem ID */
+static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
+{
+       int type = -1;
+
+       if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13))
+               type = BTTV_BOARD_MODTEC_205;
+       else if (0 == strncmp(eeprom_data+20,"Picolo",7))
+               type = BTTV_BOARD_EURESYS_PICOLO;
+       else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0)
+               type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */
+
+       if (-1 != type) {
+               btv->c.type = type;
+               pr_info("%d: detected by eeprom: %s [card=%d]\n",
+                       btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+       }
+}
+
+static void flyvideo_gpio(struct bttv *btv)
+{
+       int gpio, has_remote, has_radio, is_capture_only;
+       int is_lr90, has_tda9820_tda9821;
+       int tuner_type = UNSET, ttype;
+
+       gpio_inout(0xffffff, 0);
+       udelay(8);  /* without this we would see the 0x1800 mask */
+       gpio = gpio_read();
+       /* FIXME: must restore OUR_EN ??? */
+
+       /* all cards provide GPIO info, some have an additional eeprom
+        * LR50: GPIO coding can be found lower right CP1 .. CP9
+        *       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
+        *       GPIO14-12: n.c.
+        * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
+
+        * lowest 3 bytes are remote control codes (no handshake needed)
+        * xxxFFF: No remote control chip soldered
+        * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
+        * Note: Some bits are Audio_Mask !
+        */
+       ttype = (gpio & 0x0f0000) >> 16;
+       switch (ttype) {
+       case 0x0:
+               tuner_type = 2;  /* NTSC, e.g. TPI8NSR11P */
+               break;
+       case 0x2:
+               tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
+               break;
+       case 0x4:
+               tuner_type = 5;  /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
+               break;
+       case 0x6:
+               tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
+               break;
+       case 0xC:
+               tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
+               break;
+       default:
+               pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
+               break;
+       }
+
+       has_remote          =   gpio & 0x800000;
+       has_radio           =   gpio & 0x400000;
+       /*   unknown                   0x200000;
+        *   unknown2                  0x100000; */
+       is_capture_only     = !(gpio & 0x008000); /* GPIO15 */
+       has_tda9820_tda9821 = !(gpio & 0x004000);
+       is_lr90             = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
+       /*
+        * gpio & 0x001000    output bit for audio routing */
+
+       if (is_capture_only)
+               tuner_type = TUNER_ABSENT; /* No tuner present */
+
+       pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+               btv->c.nr, has_radio ? "yes" : "no",
+               has_remote ? "yes" : "no", tuner_type, gpio);
+       pr_info("%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+               btv->c.nr, is_lr90 ? "yes" : "no",
+               has_tda9820_tda9821 ? "yes" : "no",
+               is_capture_only ? "yes" : "no");
+
+       if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
+               btv->tuner_type = tuner_type;
+       btv->has_radio = has_radio;
+
+       /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
+        * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
+        * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
+       if (has_tda9820_tda9821)
+               btv->audio_mode_gpio = lt9415_audio;
+       /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
+}
+
+static int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
+                              14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
+static int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
+                              1,1,1,1,   1,1,1,0,  0,0,0,0,  0,1,0,0 };
+
+static void miro_pinnacle_gpio(struct bttv *btv)
+{
+       int id,msp,gpio;
+       char *info;
+
+       gpio_inout(0xffffff, 0);
+       gpio = gpio_read();
+       id   = ((gpio>>10) & 63) -1;
+       msp  = bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx");
+       if (id < 32) {
+               btv->tuner_type = miro_tunermap[id];
+               if (0 == (gpio & 0x20)) {
+                       btv->has_radio = 1;
+                       if (!miro_fmtuner[id]) {
+                               btv->has_matchbox = 1;
+                               btv->mbox_we    = (1<<6);
+                               btv->mbox_most  = (1<<7);
+                               btv->mbox_clk   = (1<<8);
+                               btv->mbox_data  = (1<<9);
+                               btv->mbox_mask  = (1<<6)|(1<<7)|(1<<8)|(1<<9);
+                       }
+               } else {
+                       btv->has_radio = 0;
+               }
+               if (-1 != msp) {
+                       if (btv->c.type == BTTV_BOARD_MIRO)
+                               btv->c.type = BTTV_BOARD_MIROPRO;
+                       if (btv->c.type == BTTV_BOARD_PINNACLE)
+                               btv->c.type = BTTV_BOARD_PINNACLEPRO;
+               }
+               pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+                       btv->c.nr, id+1, btv->tuner_type,
+                       !btv->has_radio ? "no" :
+                       (btv->has_matchbox ? "matchbox" : "fmtuner"),
+                       (-1 == msp) ? "no" : "yes");
+       } else {
+               /* new cards with microtune tuner */
+               id = 63 - id;
+               btv->has_radio = 0;
+               switch (id) {
+               case 1:
+                       info = "PAL / mono";
+                       btv->tda9887_conf = TDA9887_INTERCARRIER;
+                       break;
+               case 2:
+                       info = "PAL+SECAM / stereo";
+                       btv->has_radio = 1;
+                       btv->tda9887_conf = TDA9887_QSS;
+                       break;
+               case 3:
+                       info = "NTSC / stereo";
+                       btv->has_radio = 1;
+                       btv->tda9887_conf = TDA9887_QSS;
+                       break;
+               case 4:
+                       info = "PAL+SECAM / mono";
+                       btv->tda9887_conf = TDA9887_QSS;
+                       break;
+               case 5:
+                       info = "NTSC / mono";
+                       btv->tda9887_conf = TDA9887_INTERCARRIER;
+                       break;
+               case 6:
+                       info = "NTSC / stereo";
+                       btv->tda9887_conf = TDA9887_INTERCARRIER;
+                       break;
+               case 7:
+                       info = "PAL / stereo";
+                       btv->tda9887_conf = TDA9887_INTERCARRIER;
+                       break;
+               default:
+                       info = "oops: unknown card";
+                       break;
+               }
+               if (-1 != msp)
+                       btv->c.type = BTTV_BOARD_PINNACLEPRO;
+               pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+                       btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+               btv->tuner_type = TUNER_MT2032;
+       }
+}
+
+/* GPIO21   L: Buffer aktiv, H: Buffer inaktiv */
+#define LM1882_SYNC_DRIVE     0x200000L
+
+static void init_ids_eagle(struct bttv *btv)
+{
+       gpio_inout(0xffffff,0xFFFF37);
+       gpio_write(0x200020);
+
+       /* flash strobe inverter ?! */
+       gpio_write(0x200024);
+
+       /* switch sync drive off */
+       gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
+
+       /* set BT848 muxel to 2 */
+       btaor((2)<<5, ~(2<<5), BT848_IFORM);
+}
+
+/* Muxsel helper for the IDS Eagle.
+ * the eagles does not use the standard muxsel-bits but
+ * has its own multiplexer */
+static void eagle_muxsel(struct bttv *btv, unsigned int input)
+{
+       gpio_bits(3, input & 3);
+
+       /* composite */
+       /* set chroma ADC to sleep */
+       btor(BT848_ADC_C_SLEEP, BT848_ADC);
+       /* set to composite video */
+       btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+       btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+
+       /* switch sync drive off */
+       gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
+}
+
+static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
+{
+       static const int masks[] = {0x30, 0x01, 0x12, 0x23};
+       gpio_write(masks[input%4]);
+}
+
+/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and
+   alarms output
+
+   GPIObit    | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+   assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1|   |   |
+
+   IN - sensor inputs, INx - sensor inputs and TI XORed together
+   O1,O2,O3 - alarm outputs (relays)
+
+   OUT ENABLE   1    1   0  . 1  1   0   0 . 0   0   0    0   = 0x6C0
+
+*/
+
+static void init_lmlbt4x(struct bttv *btv)
+{
+       pr_debug("LMLBT4x init\n");
+       btwrite(0x000000, BT848_GPIO_REG_INP);
+       gpio_inout(0xffffff, 0x0006C0);
+       gpio_write(0x000000);
+}
+
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int inmux = input % 8;
+       gpio_inout( 0xf, 0xf );
+       gpio_bits( 0xf, inmux );
+}
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int inmux = input % 4;
+       gpio_inout( 3<<9, 3<<9 );
+       gpio_bits( 3<<9, inmux<<9 );
+}
+
+static void geovision_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int inmux = input % 16;
+       gpio_inout(0xf, 0xf);
+       gpio_bits(0xf, inmux);
+}
+
+/*
+ * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878.
+ * The first 74HC4051 has the lower 8 inputs, the second one the higher 8.
+ * The muxes are controlled via a 74HC373 latch which is connected to
+ * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch.
+ * Q0 of the latch is connected to the Enable (~E) input of the first
+ * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051.
+ * Q4 - Q7 are connected to the second 74HC4051 in the same way.
+ */
+
+static void td3116_latch_value(struct bttv *btv, u32 value)
+{
+       gpio_bits((1<<18) | 0xff, value);
+       gpio_bits((1<<18) | 0xff, (1<<18) | value);
+       udelay(1);
+       gpio_bits((1<<18) | 0xff, value);
+}
+
+static void td3116_muxsel(struct bttv *btv, unsigned int input)
+{
+       u32 value;
+       u32 highbit;
+
+       highbit = (input & 0x8) >> 3 ;
+
+       /* Disable outputs and set value in the mux */
+       value = 0x11; /* Disable outputs */
+       value |= ((input & 0x7) << 1)  << (4 * highbit);
+       td3116_latch_value(btv, value);
+
+       /* Enable the correct output */
+       value &= ~0x11;
+       value |= ((highbit ^ 0x1) << 4) | highbit;
+       td3116_latch_value(btv, value);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void bttv_reset_audio(struct bttv *btv)
+{
+       /*
+        * BT878A has a audio-reset register.
+        * 1. This register is an audio reset function but it is in
+        *    function-0 (video capture) address space.
+        * 2. It is enough to do this once per power-up of the card.
+        * 3. There is a typo in the Conexant doc -- it is not at
+        *    0x5B, but at 0x058. (B is an odd-number, obviously a typo!).
+        * --//Shrikumar 030609
+        */
+       if (btv->id != 878)
+               return;
+
+       if (bttv_debug)
+               pr_debug("%d: BT878A ARESET\n", btv->c.nr);
+       btwrite((1<<7), 0x058);
+       udelay(10);
+       btwrite(     0, 0x058);
+}
+
+/* initialization part one -- before registering i2c bus */
+void __devinit bttv_init_card1(struct bttv *btv)
+{
+       switch (btv->c.type) {
+       case BTTV_BOARD_HAUPPAUGE:
+       case BTTV_BOARD_HAUPPAUGE878:
+               boot_msp34xx(btv,5);
+               break;
+       case BTTV_BOARD_VOODOOTV_200:
+       case BTTV_BOARD_VOODOOTV_FM:
+               boot_msp34xx(btv,20);
+               break;
+       case BTTV_BOARD_AVERMEDIA98:
+               boot_msp34xx(btv,11);
+               break;
+       case BTTV_BOARD_HAUPPAUGEPVR:
+               pvr_boot(btv);
+               break;
+       case BTTV_BOARD_TWINHAN_DST:
+       case BTTV_BOARD_AVDVBT_771:
+       case BTTV_BOARD_PINNACLESAT:
+               btv->use_i2c_hw = 1;
+               break;
+       case BTTV_BOARD_ADLINK_RTV24:
+               init_RTV24( btv );
+               break;
+
+       }
+       if (!bttv_tvcards[btv->c.type].has_dvb)
+               bttv_reset_audio(btv);
+}
+
+/* initialization part two -- after registering i2c bus */
+void __devinit bttv_init_card2(struct bttv *btv)
+{
+       btv->tuner_type = UNSET;
+
+       if (BTTV_BOARD_UNKNOWN == btv->c.type) {
+               bttv_readee(btv,eeprom_data,0xa0);
+               identify_by_eeprom(btv,eeprom_data);
+       }
+
+       switch (btv->c.type) {
+       case BTTV_BOARD_MIRO:
+       case BTTV_BOARD_MIROPRO:
+       case BTTV_BOARD_PINNACLE:
+       case BTTV_BOARD_PINNACLEPRO:
+               /* miro/pinnacle */
+               miro_pinnacle_gpio(btv);
+               break;
+       case BTTV_BOARD_FLYVIDEO_98:
+       case BTTV_BOARD_MAXI:
+       case BTTV_BOARD_LIFE_FLYKIT:
+       case BTTV_BOARD_FLYVIDEO:
+       case BTTV_BOARD_TYPHOON_TVIEW:
+       case BTTV_BOARD_CHRONOS_VS2:
+       case BTTV_BOARD_FLYVIDEO_98FM:
+       case BTTV_BOARD_FLYVIDEO2000:
+       case BTTV_BOARD_FLYVIDEO98EZ:
+       case BTTV_BOARD_CONFERENCETV:
+       case BTTV_BOARD_LIFETEC_9415:
+               flyvideo_gpio(btv);
+               break;
+       case BTTV_BOARD_HAUPPAUGE:
+       case BTTV_BOARD_HAUPPAUGE878:
+       case BTTV_BOARD_HAUPPAUGEPVR:
+               /* pick up some config infos from the eeprom */
+               bttv_readee(btv,eeprom_data,0xa0);
+               hauppauge_eeprom(btv);
+               break;
+       case BTTV_BOARD_AVERMEDIA98:
+       case BTTV_BOARD_AVPHONE98:
+               bttv_readee(btv,eeprom_data,0xa0);
+               avermedia_eeprom(btv);
+               break;
+       case BTTV_BOARD_PXC200:
+               init_PXC200(btv);
+               break;
+       case BTTV_BOARD_PICOLO_TETRA_CHIP:
+               picolo_tetra_init(btv);
+               break;
+       case BTTV_BOARD_VHX:
+               btv->has_radio    = 1;
+               btv->has_matchbox = 1;
+               btv->mbox_we      = 0x20;
+               btv->mbox_most    = 0;
+               btv->mbox_clk     = 0x08;
+               btv->mbox_data    = 0x10;
+               btv->mbox_mask    = 0x38;
+               break;
+       case BTTV_BOARD_VOBIS_BOOSTAR:
+       case BTTV_BOARD_TERRATV:
+               terratec_active_radio_upgrade(btv);
+               break;
+       case BTTV_BOARD_MAGICTVIEW061:
+               if (btv->cardid == 0x3002144f) {
+                       btv->has_radio=1;
+                       pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+                               btv->c.nr);
+               }
+               break;
+       case BTTV_BOARD_STB2:
+               if (btv->cardid == 0x3060121a) {
+                       /* Fix up entry for 3DFX VoodooTV 100,
+                          which is an OEM STB card variant. */
+                       btv->has_radio=0;
+                       btv->tuner_type=TUNER_TEMIC_NTSC;
+               }
+               break;
+       case BTTV_BOARD_OSPREY1x0:
+       case BTTV_BOARD_OSPREY1x0_848:
+       case BTTV_BOARD_OSPREY101_848:
+       case BTTV_BOARD_OSPREY1x1:
+       case BTTV_BOARD_OSPREY1x1_SVID:
+       case BTTV_BOARD_OSPREY2xx:
+       case BTTV_BOARD_OSPREY2x0_SVID:
+       case BTTV_BOARD_OSPREY2x0:
+       case BTTV_BOARD_OSPREY440:
+       case BTTV_BOARD_OSPREY500:
+       case BTTV_BOARD_OSPREY540:
+       case BTTV_BOARD_OSPREY2000:
+               bttv_readee(btv,eeprom_data,0xa0);
+               osprey_eeprom(btv, eeprom_data);
+               break;
+       case BTTV_BOARD_IDS_EAGLE:
+               init_ids_eagle(btv);
+               break;
+       case BTTV_BOARD_MODTEC_205:
+               bttv_readee(btv,eeprom_data,0xa0);
+               modtec_eeprom(btv);
+               break;
+       case BTTV_BOARD_LMLBT4:
+               init_lmlbt4x(btv);
+               break;
+       case BTTV_BOARD_TIBET_CS16:
+               tibetCS16_init(btv);
+               break;
+       case BTTV_BOARD_KODICOM_4400R:
+               kodicom4400r_init(btv);
+               break;
+       case BTTV_BOARD_GEOVISION_GV800S:
+               gv800s_init(btv);
+               break;
+       }
+
+       /* pll configuration */
+       if (!(btv->id==848 && btv->revision==0x11)) {
+               /* defaults from card list */
+               if (PLL_28 == bttv_tvcards[btv->c.type].pll) {
+                       btv->pll.pll_ifreq=28636363;
+                       btv->pll.pll_crystal=BT848_IFORM_XT0;
+               }
+               if (PLL_35 == bttv_tvcards[btv->c.type].pll) {
+                       btv->pll.pll_ifreq=35468950;
+                       btv->pll.pll_crystal=BT848_IFORM_XT1;
+               }
+               /* insmod options can override */
+               switch (pll[btv->c.nr]) {
+               case 0: /* none */
+                       btv->pll.pll_crystal = 0;
+                       btv->pll.pll_ifreq   = 0;
+                       btv->pll.pll_ofreq   = 0;
+                       break;
+               case 1: /* 28 MHz */
+               case 28:
+                       btv->pll.pll_ifreq   = 28636363;
+                       btv->pll.pll_ofreq   = 0;
+                       btv->pll.pll_crystal = BT848_IFORM_XT0;
+                       break;
+               case 2: /* 35 MHz */
+               case 35:
+                       btv->pll.pll_ifreq   = 35468950;
+                       btv->pll.pll_ofreq   = 0;
+                       btv->pll.pll_crystal = BT848_IFORM_XT1;
+                       break;
+               }
+       }
+       btv->pll.pll_current = -1;
+
+       /* tuner configuration (from card list / autodetect / insmod option) */
+       if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
+               if (UNSET == btv->tuner_type)
+                       btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
+       if (UNSET != tuner[btv->c.nr])
+               btv->tuner_type = tuner[btv->c.nr];
+
+       if (btv->tuner_type == TUNER_ABSENT)
+               pr_info("%d: tuner absent\n", btv->c.nr);
+       else if (btv->tuner_type == UNSET)
+               pr_warn("%d: tuner type unset\n", btv->c.nr);
+       else
+               pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
+
+       if (autoload != UNSET) {
+               pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+               pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+                       btv->c.nr);
+       }
+
+       if (UNSET == btv->tuner_type)
+               btv->tuner_type = TUNER_ABSENT;
+
+       btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
+                  bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
+       btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
+                   UNSET : bttv_tvcards[btv->c.type].svhs;
+       if (svhs[btv->c.nr] != UNSET)
+               btv->svhs = svhs[btv->c.nr];
+       if (remote[btv->c.nr] != UNSET)
+               btv->has_remote = remote[btv->c.nr];
+
+       if (bttv_tvcards[btv->c.type].has_radio)
+               btv->has_radio = 1;
+       if (bttv_tvcards[btv->c.type].has_remote)
+               btv->has_remote = 1;
+       if (!bttv_tvcards[btv->c.type].no_gpioirq)
+               btv->gpioirq = 1;
+       if (bttv_tvcards[btv->c.type].volume_gpio)
+               btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
+       if (bttv_tvcards[btv->c.type].audio_mode_gpio)
+               btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
+
+       if (btv->tuner_type == TUNER_ABSENT)
+               return;  /* no tuner or related drivers to load */
+
+       if (btv->has_saa6588 || saa6588[btv->c.nr]) {
+               /* Probe for RDS receiver chip */
+               static const unsigned short addrs[] = {
+                       0x20 >> 1,
+                       0x22 >> 1,
+                       I2C_CLIENT_END
+               };
+               struct v4l2_subdev *sd;
+
+               sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                       &btv->c.i2c_adap, "saa6588", 0, addrs);
+               btv->has_saa6588 = (sd != NULL);
+       }
+
+       /* try to detect audio/fader chips */
+
+       /* First check if the user specified the audio chip via a module
+          option. */
+
+       switch (audiodev[btv->c.nr]) {
+       case -1:
+               return; /* do not load any audio module */
+
+       case 0: /* autodetect */
+               break;
+
+       case 1: {
+               /* The user specified that we should probe for msp3400 */
+               static const unsigned short addrs[] = {
+                       I2C_ADDR_MSP3400 >> 1,
+                       I2C_ADDR_MSP3400_ALT >> 1,
+                       I2C_CLIENT_END
+               };
+
+               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                       &btv->c.i2c_adap, "msp3400", 0, addrs);
+               if (btv->sd_msp34xx)
+                       return;
+               goto no_audio;
+       }
+
+       case 2: {
+               /* The user specified that we should probe for tda7432 */
+               static const unsigned short addrs[] = {
+                       I2C_ADDR_TDA7432 >> 1,
+                       I2C_CLIENT_END
+               };
+
+               if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tda7432", 0, addrs))
+                       return;
+               goto no_audio;
+       }
+
+       case 3: {
+               /* The user specified that we should probe for tvaudio */
+               btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                       &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+               if (btv->sd_tvaudio)
+                       return;
+               goto no_audio;
+       }
+
+       default:
+               pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
+               return;
+       }
+
+       /* There were no overrides, so now we try to discover this through the
+          card definition */
+
+       /* probe for msp3400 first: this driver can detect whether or not
+          it really is a msp3400, so it will return NULL when the device
+          found is really something else (e.g. a tea6300). */
+       if (!bttv_tvcards[btv->c.type].no_msp34xx) {
+               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                       &btv->c.i2c_adap, "msp3400",
+                       0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1));
+       } else if (bttv_tvcards[btv->c.type].msp34xx_alt) {
+               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                       &btv->c.i2c_adap, "msp3400",
+                       0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1));
+       }
+
+       /* If we found a msp34xx, then we're done. */
+       if (btv->sd_msp34xx)
+               return;
+
+       /* it might also be a tda7432. */
+       if (!bttv_tvcards[btv->c.type].no_tda7432) {
+               static const unsigned short addrs[] = {
+                       I2C_ADDR_TDA7432 >> 1,
+                       I2C_CLIENT_END
+               };
+
+               if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tda7432", 0, addrs))
+                       return;
+       }
+
+       /* Now see if we can find one of the tvaudio devices. */
+       btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+               &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+       if (btv->sd_tvaudio)
+               return;
+
+no_audio:
+       pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
+}
+
+
+/* initialize the tuner */
+void __devinit bttv_init_tuner(struct bttv *btv)
+{
+       int addr = ADDR_UNSET;
+
+       if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+               addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+       if (btv->tuner_type != TUNER_ABSENT) {
+               struct tuner_setup tun_setup;
+
+               /* Load tuner module before issuing tuner config call! */
+               if (btv->has_radio)
+                       v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+               v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
+
+               tun_setup.mode_mask = T_ANALOG_TV;
+               tun_setup.type = btv->tuner_type;
+               tun_setup.addr = addr;
+
+               if (btv->has_radio)
+                       tun_setup.mode_mask |= T_RADIO;
+
+               bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
+       }
+
+       if (btv->tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &btv->tda9887_conf;
+
+               bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void modtec_eeprom(struct bttv *btv)
+{
+       if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
+               btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
+               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+                       btv->c.nr, &eeprom_data[0x1e]);
+       } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
+               btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
+               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+                       btv->c.nr, &eeprom_data[0x1e]);
+       } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
+               btv->tuner_type=TUNER_PHILIPS_NTSC;
+               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+                       btv->c.nr, &eeprom_data[0x1e]);
+       } else {
+               pr_info("%d: Modtec: Unknown TunerString: %s\n",
+                       btv->c.nr, &eeprom_data[0x1e]);
+       }
+}
+
+static void __devinit hauppauge_eeprom(struct bttv *btv)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
+       btv->tuner_type = tv.tuner_type;
+       btv->has_radio  = tv.has_radio;
+
+       pr_info("%d: Hauppauge eeprom indicates model#%d\n",
+               btv->c.nr, tv.model);
+
+       /*
+        * Some of the 878 boards have duplicate PCI IDs. Switch the board
+        * type based on model #.
+        */
+       if(tv.model == 64900) {
+               pr_info("%d: Switching board type from %s to %s\n",
+                       btv->c.nr,
+                       bttv_tvcards[btv->c.type].name,
+                       bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
+               btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
+       }
+
+       /* The 61334 needs the msp3410 to do the radio demod to get sound */
+       if (tv.model == 61334)
+               btv->radio_uses_msp_demodulator = 1;
+}
+
+static int terratec_active_radio_upgrade(struct bttv *btv)
+{
+       int freq;
+
+       btv->has_radio    = 1;
+       btv->has_matchbox = 1;
+       btv->mbox_we      = 0x10;
+       btv->mbox_most    = 0x20;
+       btv->mbox_clk     = 0x08;
+       btv->mbox_data    = 0x04;
+       btv->mbox_mask    = 0x3c;
+
+       btv->mbox_iow     = 1 <<  8;
+       btv->mbox_ior     = 1 <<  9;
+       btv->mbox_csel    = 1 << 10;
+
+       freq=88000/62.5;
+       tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
+       if (0x1ed8 == tea5757_read(btv)) {
+               pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
+               btv->has_radio    = 1;
+               btv->has_saa6588  = 1;
+               btv->has_matchbox = 1;
+       } else {
+               btv->has_radio    = 0;
+               btv->has_matchbox = 0;
+       }
+       return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * minimal bootstrap for the WinTV/PVR -- upload altera firmware.
+ *
+ * The hcwamc.rbf firmware file is on the Hauppauge driver CD.  Have
+ * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be
+ * unpacked with unzip).
+ */
+#define PVR_GPIO_DELAY         10
+
+#define BTTV_ALT_DATA          0x000001
+#define BTTV_ALT_DCLK          0x100000
+#define BTTV_ALT_NCONFIG       0x800000
+
+static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
+                                    u32 microlen)
+{
+       u32 n;
+       u8 bits;
+       int i;
+
+       gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG);
+       gpio_write(0);
+       udelay(PVR_GPIO_DELAY);
+
+       gpio_write(BTTV_ALT_NCONFIG);
+       udelay(PVR_GPIO_DELAY);
+
+       for (n = 0; n < microlen; n++) {
+               bits = micro[n];
+               for (i = 0 ; i < 8 ; i++) {
+                       gpio_bits(BTTV_ALT_DCLK,0);
+                       if (bits & 0x01)
+                               gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
+                       else
+                               gpio_bits(BTTV_ALT_DATA,0);
+                       gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
+                       bits >>= 1;
+               }
+       }
+       gpio_bits(BTTV_ALT_DCLK,0);
+       udelay(PVR_GPIO_DELAY);
+
+       /* begin Altera init loop (Not necessary,but doesn't hurt) */
+       for (i = 0 ; i < 30 ; i++) {
+               gpio_bits(BTTV_ALT_DCLK,0);
+               gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
+       }
+       gpio_bits(BTTV_ALT_DCLK,0);
+       return 0;
+}
+
+static int __devinit pvr_boot(struct bttv *btv)
+{
+       const struct firmware *fw_entry;
+       int rc;
+
+       rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
+       if (rc != 0) {
+               pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
+               return rc;
+       }
+       rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
+       pr_info("%d: altera firmware upload %s\n",
+               btv->c.nr, (rc < 0) ? "failed" : "ok");
+       release_firmware(fw_entry);
+       return rc;
+}
+
+/* ----------------------------------------------------------------------- */
+/* some osprey specific stuff                                              */
+
+static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
+{
+       int i;
+       u32 serial = 0;
+       int cardid = -1;
+
+       /* This code will nevery actually get called in this case.... */
+       if (btv->c.type == BTTV_BOARD_UNKNOWN) {
+               /* this might be an antique... check for MMAC label in eeprom */
+               if (!strncmp(ee, "MMAC", 4)) {
+                       u8 checksum = 0;
+                       for (i = 0; i < 21; i++)
+                               checksum += ee[i];
+                       if (checksum != ee[21])
+                               return;
+                       cardid = BTTV_BOARD_OSPREY1x0_848;
+                       for (i = 12; i < 21; i++)
+                               serial *= 10, serial += ee[i] - '0';
+               }
+       } else {
+               unsigned short type;
+
+               for (i = 4*16; i < 8*16; i += 16) {
+                       u16 checksum = ip_compute_csum(ee + i, 16);
+
+                       if ((checksum&0xff) + (checksum>>8) == 0xff)
+                               break;
+               }
+               if (i >= 8*16)
+                       return;
+               ee += i;
+
+               /* found a valid descriptor */
+               type = get_unaligned_be16((__be16 *)(ee+4));
+
+               switch(type) {
+               /* 848 based */
+               case 0x0004:
+                       cardid = BTTV_BOARD_OSPREY1x0_848;
+                       break;
+               case 0x0005:
+                       cardid = BTTV_BOARD_OSPREY101_848;
+                       break;
+
+               /* 878 based */
+               case 0x0012:
+               case 0x0013:
+                       cardid = BTTV_BOARD_OSPREY1x0;
+                       break;
+               case 0x0014:
+               case 0x0015:
+                       cardid = BTTV_BOARD_OSPREY1x1;
+                       break;
+               case 0x0016:
+               case 0x0017:
+               case 0x0020:
+                       cardid = BTTV_BOARD_OSPREY1x1_SVID;
+                       break;
+               case 0x0018:
+               case 0x0019:
+               case 0x001E:
+               case 0x001F:
+                       cardid = BTTV_BOARD_OSPREY2xx;
+                       break;
+               case 0x001A:
+               case 0x001B:
+                       cardid = BTTV_BOARD_OSPREY2x0_SVID;
+                       break;
+               case 0x0040:
+                       cardid = BTTV_BOARD_OSPREY500;
+                       break;
+               case 0x0050:
+               case 0x0056:
+                       cardid = BTTV_BOARD_OSPREY540;
+                       /* bttv_osprey_540_init(btv); */
+                       break;
+               case 0x0060:
+               case 0x0070:
+               case 0x00A0:
+                       cardid = BTTV_BOARD_OSPREY2x0;
+                       /* enable output on select control lines */
+                       gpio_inout(0xffffff,0x000303);
+                       break;
+               case 0x00D8:
+                       cardid = BTTV_BOARD_OSPREY440;
+                       break;
+               default:
+                       /* unknown...leave generic, but get serial # */
+                       pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+                               btv->c.nr, type);
+                       break;
+               }
+               serial = get_unaligned_be32((__be32 *)(ee+6));
+       }
+
+       pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+               btv->c.nr, cardid,
+               cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+
+       if (cardid<0 || btv->c.type == cardid)
+               return;
+
+       /* card type isn't set correctly */
+       if (card[btv->c.nr] < bttv_num_tvcards) {
+               pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+                       btv->c.nr);
+       } else {
+               pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+                       btv->c.nr, btv->c.type, cardid);
+               btv->c.type = cardid;
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+/* AVermedia specific stuff, from  bktr_card.c                             */
+
+static int tuner_0_table[] = {
+       TUNER_PHILIPS_NTSC,  TUNER_PHILIPS_PAL /* PAL-BG*/,
+       TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL /* PAL-I*/,
+       TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
+       TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
+       TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL,
+       TUNER_PHILIPS_FM1216ME_MK3 };
+
+static int tuner_1_table[] = {
+       TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
+       TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+       TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+       TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
+       TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
+
+static void __devinit avermedia_eeprom(struct bttv *btv)
+{
+       int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
+
+       tuner_make      = (eeprom_data[0x41] & 0x7);
+       tuner_tv_fm     = (eeprom_data[0x41] & 0x18) >> 3;
+       tuner_format    = (eeprom_data[0x42] & 0xf0) >> 4;
+       btv->has_remote = (eeprom_data[0x42] & 0x01);
+
+       if (tuner_make == 0 || tuner_make == 2)
+               if (tuner_format <= 0x0a)
+                       tuner_type = tuner_0_table[tuner_format];
+       if (tuner_make == 1)
+               if (tuner_format <= 9)
+                       tuner_type = tuner_1_table[tuner_format];
+
+       if (tuner_make == 4)
+               if (tuner_format == 0x09)
+                       tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
+
+       pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+               btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
+       if (tuner_type) {
+               btv->tuner_type = tuner_type;
+               pr_cont("%d", tuner_type);
+       } else
+               pr_cont("Unknown type");
+       pr_cont(" radio:%s remote control:%s\n",
+              tuner_tv_fm     ? "yes" : "no",
+              btv->has_remote ? "yes" : "no");
+}
+
+/*
+ * For Voodoo TV/FM and Voodoo 200.  These cards' tuners use a TDA9880
+ * analog demod, which is not I2C controlled like the newer and more common
+ * TDA9887 series.  Instead is has two tri-state input pins, S0 and S1,
+ * that control the IF for the video and audio.  Apparently, bttv GPIO
+ * 0x10000 is connected to S0.  S0 low selects a 38.9 MHz VIF for B/G/D/K/I
+ * (i.e., PAL) while high selects 45.75 MHz for M/N (i.e., NTSC).
+ */
+u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
+{
+
+       if (btv->audio == TVAUDIO_INPUT_TUNER) {
+               if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
+                       gpiobits |= 0x10000;
+               else
+                       gpiobits &= ~0x10000;
+       }
+
+       gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits);
+       return gpiobits;
+}
+
+
+/*
+ * reset/enable the MSP on some Hauppauge cards
+ * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
+ *
+ * Hauppauge:  pin  5
+ * Voodoo:     pin 20
+ */
+static void __devinit boot_msp34xx(struct bttv *btv, int pin)
+{
+       int mask = (1 << pin);
+
+       gpio_inout(mask,mask);
+       gpio_bits(mask,0);
+       mdelay(2);
+       udelay(500);
+       gpio_bits(mask,mask);
+
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"msp34xx");
+       if (bttv_verbose)
+               pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+                       btv->c.nr, pin);
+}
+
+/* ----------------------------------------------------------------------- */
+/*  Imagenation L-Model PXC200 Framegrabber */
+/*  This is basically the same procedure as
+ *  used by Alessandro Rubini in his pxc200
+ *  driver, but using BTTV functions */
+
+static void __devinit init_PXC200(struct bttv *btv)
+{
+       static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
+                                           0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+                                           0x00 };
+       unsigned int i;
+       int tmp;
+       u32 val;
+
+       /* Initialise GPIO-connevted stuff */
+       gpio_inout(0xffffff, (1<<13));
+       gpio_write(0);
+       udelay(3);
+       gpio_write(1<<13);
+       /* GPIO inputs are pulled up, so no need to drive
+        * reset pin any longer */
+       gpio_bits(0xffffff, 0);
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"pxc200");
+
+       /*  we could/should try and reset/control the AD pots? but
+           right now  we simply  turned off the crushing.  Without
+           this the AGC drifts drifts
+           remember the EN is reverse logic -->
+           setting BT848_ADC_AGC_EN disable the AGC
+           tboult@eecs.lehigh.edu
+       */
+
+       btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
+
+       /*      Initialise MAX517 DAC */
+       pr_info("Setting DAC reference voltage level ...\n");
+       bttv_I2CWrite(btv,0x5E,0,0x80,1);
+
+       /*      Initialise 12C508 PIC */
+       /*      The I2CWrite and I2CRead commmands are actually to the
+        *      same chips - but the R/W bit is included in the address
+        *      argument so the numbers are different */
+
+
+       pr_info("Initialising 12C508 PIC chip ...\n");
+
+       /* First of all, enable the clock line. This is used in the PXC200-F */
+       val = btread(BT848_GPIO_DMA_CTL);
+       val |= BT848_GPIO_DMA_CTL_GPCLKMODE;
+       btwrite(val, BT848_GPIO_DMA_CTL);
+
+       /* Then, push to 0 the reset pin long enough to reset the *
+        * device same as above for the reset line, but not the same
+        * value sent to the GPIO-connected stuff
+        * which one is the good one? */
+       gpio_inout(0xffffff,(1<<2));
+       gpio_write(0);
+       udelay(10);
+       gpio_write(1<<2);
+
+       for (i = 0; i < ARRAY_SIZE(vals); i++) {
+               tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
+               if (tmp != -1) {
+                       pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+                              vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
+               }
+       }
+
+       pr_info("PXC200 Initialised\n");
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+/*
+ *  The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
+ *  it. This apparently involves the following procedure for each 878 chip:
+ *
+ *  1) write 0x00C3FEFF to the GPIO_OUT_EN register
+ *
+ *  2)  write to GPIO_DATA
+ *      - 0x0E
+ *      - sleep 1ms
+ *      - 0x10 + 0x0E
+ *      - sleep 10ms
+ *      - 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
+ *                 error. ERROR_CPLD_Check_Failed stop.
+ *
+ *  3) write to GPIO_DATA
+ *      - write 0x4400 + 0x0E
+ *      - sleep 10ms
+ *      - write 0x4410 + 0x0E
+ *      - sleep 1ms
+ *      - write 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( buf>>18 & 0x01 ) || ( buf>>19 & 0x01 != 0 )
+ *                error. ERROR_CPLD_Check_Failed.
+ */
+/* ----------------------------------------------------------------------- */
+static void
+init_RTV24 (struct bttv *btv)
+{
+       uint32_t dataRead = 0;
+       long watchdog_value = 0x0E;
+
+       pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
+               btv->c.nr);
+
+       btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
+
+       btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+       msleep (1);
+       btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
+       msleep (10);
+       btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+
+       dataRead = btread (BT848_GPIO_DATA);
+
+       if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
+               pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+                       btv->c.nr, dataRead);
+       }
+
+       btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
+       msleep (10);
+       btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
+       msleep (1);
+       btwrite (watchdog_value, BT848_GPIO_DATA);
+       msleep (1);
+       dataRead = btread (BT848_GPIO_DATA);
+
+       if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
+               pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+                       btv->c.nr, dataRead);
+
+               return;
+       }
+
+       pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
+/*
+ * Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
+ */
+
+static void bus_low(struct bttv *btv, int bit)
+{
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+               udelay(5);
+       }
+
+       gpio_bits(bit,0);
+       udelay(5);
+
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+               udelay(5);
+       }
+}
+
+static void bus_high(struct bttv *btv, int bit)
+{
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+               udelay(5);
+       }
+
+       gpio_bits(bit,bit);
+       udelay(5);
+
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+               udelay(5);
+       }
+}
+
+static int bus_in(struct bttv *btv, int bit)
+{
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+               udelay(5);
+
+               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+               udelay(5);
+       }
+       return gpio_read() & (bit);
+}
+
+/* TEA5757 register bits */
+#define TEA_FREQ               0:14
+#define TEA_BUFFER             15:15
+
+#define TEA_SIGNAL_STRENGTH    16:17
+
+#define TEA_PORT1              18:18
+#define TEA_PORT0              19:19
+
+#define TEA_BAND               20:21
+#define TEA_BAND_FM            0
+#define TEA_BAND_MW            1
+#define TEA_BAND_LW            2
+#define TEA_BAND_SW            3
+
+#define TEA_MONO               22:22
+#define TEA_ALLOW_STEREO       0
+#define TEA_FORCE_MONO         1
+
+#define TEA_SEARCH_DIRECTION   23:23
+#define TEA_SEARCH_DOWN                0
+#define TEA_SEARCH_UP          1
+
+#define TEA_STATUS             24:24
+#define TEA_STATUS_TUNED       0
+#define TEA_STATUS_SEARCHING   1
+
+/* Low-level stuff */
+static int tea5757_read(struct bttv *btv)
+{
+       unsigned long timeout;
+       int value = 0;
+       int i;
+
+       /* better safe than sorry */
+       gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
+
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+               udelay(5);
+       }
+
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"tea5757 read");
+
+       bus_low(btv,btv->mbox_we);
+       bus_low(btv,btv->mbox_clk);
+
+       udelay(10);
+       timeout= jiffies + msecs_to_jiffies(1000);
+
+       /* wait for DATA line to go low; error if it doesn't */
+       while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
+               schedule();
+       if (bus_in(btv,btv->mbox_data)) {
+               pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
+               return -1;
+       }
+
+       dprintk("%d: tea5757:", btv->c.nr);
+       for (i = 0; i < 24; i++) {
+               udelay(5);
+               bus_high(btv,btv->mbox_clk);
+               udelay(5);
+               dprintk_cont("%c",
+                            bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
+               bus_low(btv,btv->mbox_clk);
+               value <<= 1;
+               value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
+               dprintk_cont("%c",
+                            bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
+       }
+       dprintk_cont("\n");
+       dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
+       return value;
+}
+
+static int tea5757_write(struct bttv *btv, int value)
+{
+       int i;
+       int reg = value;
+
+       gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
+
+       if (btv->mbox_ior) {
+               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+               udelay(5);
+       }
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"tea5757 write");
+
+       dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
+       bus_low(btv,btv->mbox_clk);
+       bus_high(btv,btv->mbox_we);
+       for (i = 0; i < 25; i++) {
+               if (reg & 0x1000000)
+                       bus_high(btv,btv->mbox_data);
+               else
+                       bus_low(btv,btv->mbox_data);
+               reg <<= 1;
+               bus_high(btv,btv->mbox_clk);
+               udelay(10);
+               bus_low(btv,btv->mbox_clk);
+               udelay(10);
+       }
+       bus_low(btv,btv->mbox_we);  /* unmute !!! */
+       return 0;
+}
+
+void tea5757_set_freq(struct bttv *btv, unsigned short freq)
+{
+       dprintk("tea5757_set_freq %d\n",freq);
+       tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
+}
+
+/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
+ *
+ * This is needed because rv605 don't use a normal multiplex, but a crosspoint
+ * switch instead (CD22M3494E). This IC can have multiple active connections
+ * between Xn (input) and Yn (output) pins. We need to clear any existing
+ * connection prior to establish a new one, pulsing the STROBE pin.
+ *
+ * The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin.
+ * GPIO pins are wired as:
+ *  GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroller)
+ *  GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroller)
+ *  GPIO[7]   - DATA (xpoint)    - P1[7] (microcontroller)
+ *  GPIO[8]   -                  - P3[5] (microcontroller)
+ *  GPIO[9]   - RESET (xpoint)   - P3[6] (microcontroller)
+ *  GPIO[10]  - STROBE (xpoint)  - P3[7] (microcontroller)
+ *  GPINTR    -                  - P3[4] (microcontroller)
+ *
+ * The microcontroller is a 80C32 like. It should be possible to change xpoint
+ * configuration either directly (as we are doing) or using the microcontroller
+ * which is also wired to I2C interface. I have no further info on the
+ * microcontroller features, one would need to disassembly the firmware.
+ * note: the vendor refused to give any information on this product, all
+ *       that stuff was found using a multimeter! :)
+ */
+static void rv605_muxsel(struct bttv *btv, unsigned int input)
+{
+       static const u8 muxgpio[] = { 0x3, 0x1, 0x2, 0x4, 0xf, 0x7, 0xe, 0x0,
+                                     0xd, 0xb, 0xc, 0x6, 0x9, 0x5, 0x8, 0xa };
+
+       gpio_bits(0x07f, muxgpio[input]);
+
+       /* reset all conections */
+       gpio_bits(0x200,0x200);
+       mdelay(1);
+       gpio_bits(0x200,0x000);
+       mdelay(1);
+
+       /* create a new connection */
+       gpio_bits(0x480,0x480);
+       mdelay(1);
+       gpio_bits(0x480,0x080);
+       mdelay(1);
+}
+
+/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning]
+ *
+ * The CS16 (available on eBay cheap) is a PCI board with four Fusion
+ * 878A chips, a PCI bridge, an Atmel microcontroller, four sync separator
+ * chips, ten eight input analog multiplexors, a not chip and a few
+ * other components.
+ *
+ * 16 inputs on a secondary bracket are provided and can be selected
+ * from each of the four capture chips.  Two of the eight input
+ * multiplexors are used to select from any of the 16 input signals.
+ *
+ * Unsupported hardware capabilities:
+ *  . A video output monitor on the secondary bracket can be selected from
+ *    one of the 878A chips.
+ *  . Another passthrough but I haven't spent any time investigating it.
+ *  . Digital I/O (logic level connected to GPIO) is available from an
+ *    onboard header.
+ *
+ * The on chip input mux should always be set to 2.
+ * GPIO[16:19] - Video input selection
+ * GPIO[0:3]   - Video output monitor select (only available from one 878A)
+ * GPIO[?:?]   - Digital I/O.
+ *
+ * There is an ATMEL microcontroller with an 8031 core on board.  I have not
+ * determined what function (if any) it provides.  With the microcontroller
+ * and sync separator chips a guess is that it might have to do with video
+ * switching and maybe some digital I/O.
+ */
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input)
+{
+       /* video mux */
+       gpio_bits(0x0f0000, input << 16);
+}
+
+static void tibetCS16_init(struct bttv *btv)
+{
+       /* enable gpio bits, mask obtained via btSpy */
+       gpio_inout(0xffffff, 0x0f7fff);
+       gpio_write(0x0f7fff);
+}
+
+/*
+ * The following routines for the Kodicom-4400r get a little mind-twisting.
+ * There is a "master" controller and three "slave" controllers, together
+ * an analog switch which connects any of 16 cameras to any of the BT87A's.
+ * The analog switch is controlled by the "master", but the detection order
+ * of the four BT878A chips is in an order which I just don't understand.
+ * The "master" is actually the second controller to be detected.  The
+ * logic on the board uses logical numbers for the 4 controllers, but
+ * those numbers are different from the detection sequence.  When working
+ * with the analog switch, we need to "map" from the detection sequence
+ * over to the board's logical controller number.  This mapping sequence
+ * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
+ * unit 3, the second (which is the master) is logical unit 0, etc.
+ * We need to maintain the status of the analog switch (which of the 16
+ * cameras is connected to which of the 4 controllers).  Rather than
+ * add to the bttv structure for this, we use the data reserved for
+ * the mbox (unused for this card type).
+ */
+
+/*
+ * First a routine to set the analog switch, which controls which camera
+ * is routed to which controller.  The switch comprises an X-address
+ * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
+ * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
+ * A data value (gpio bit 7) of '1' enables the switch, and '0' disables
+ * the switch.  A STROBE bit (gpio bit 8) latches the data value into the
+ * specified address.  The idea is to set the address and data, then bring
+ * STROBE high, and finally bring STROBE back to low.
+ */
+static void kodicom4400r_write(struct bttv *btv,
+                              unsigned char xaddr,
+                              unsigned char yaddr,
+                              unsigned char data) {
+       unsigned int udata;
+
+       udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf);
+       gpio_bits(0x1ff, udata);                /* write ADDR and DAT */
+       gpio_bits(0x1ff, udata | (1 << 8));     /* strobe high */
+       gpio_bits(0x1ff, udata);                /* strobe low */
+}
+
+/*
+ * Next the mux select.  Both the "master" and "slave" 'cards' (controllers)
+ * use this routine.  The routine finds the "master" for the card, maps
+ * the controller number from the detected position over to the logical
+ * number, writes the appropriate data to the analog switch, and housekeeps
+ * the local copy of the switch information.  The parameter 'input' is the
+ * requested camera number (0 - 15).
+ */
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
+{
+       char *sw_status;
+       int xaddr, yaddr;
+       struct bttv *mctlr;
+       static unsigned char map[4] = {3, 0, 2, 1};
+
+       mctlr = master[btv->c.nr];
+       if (mctlr == NULL) {    /* ignore if master not yet detected */
+               return;
+       }
+       yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
+       yaddr = map[yaddr];
+       sw_status = (char *)(&mctlr->mbox_we);
+       xaddr = input & 0xf;
+       /* Check if the controller/camera pair has changed, else ignore */
+       if (sw_status[yaddr] != xaddr)
+       {
+               /* "open" the old switch, "close" the new one, save the new */
+               kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
+               sw_status[yaddr] = xaddr;
+               kodicom4400r_write(mctlr, xaddr, yaddr, 1);
+       }
+}
+
+/*
+ * During initialisation, we need to reset the analog switch.  We
+ * also preset the switch to map the 4 connectors on the card to the
+ * *user's* (see above description of kodicom4400r_muxsel) channels
+ * 0 through 3
+ */
+static void kodicom4400r_init(struct bttv *btv)
+{
+       char *sw_status = (char *)(&btv->mbox_we);
+       int ix;
+
+       gpio_inout(0x0003ff, 0x0003ff);
+       gpio_write(1 << 9);     /* reset MUX */
+       gpio_write(0);
+       /* Preset camera 0 to the 4 controllers */
+       for (ix = 0; ix < 4; ix++) {
+               sw_status[ix] = ix;
+               kodicom4400r_write(btv, ix, ix, 1);
+       }
+       /*
+        * Since this is the "master", we need to set up the
+        * other three controller chips' pointers to this structure
+        * for later use in the muxsel routine.
+        */
+       if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3))
+           return;
+       master[btv->c.nr-1] = btv;
+       master[btv->c.nr]   = btv;
+       master[btv->c.nr+1] = btv;
+       master[btv->c.nr+2] = btv;
+}
+
+/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+ * video multiplexers to provide up to 16 video inputs. These
+ * multiplexers are controlled by the lower 8 GPIO pins of the
+ * bt878. The multiplexers probably Pericom PI5V331Q or similar.
+
+ * xxx0 is pin xxx of multiplexer U5,
+ * yyy1 is pin yyy of multiplexer U2
+ */
+#define ENA0    0x01
+#define ENB0    0x02
+#define ENA1    0x04
+#define ENB1    0x08
+
+#define IN10    0x10
+#define IN00    0x20
+#define IN11    0x40
+#define IN01    0x80
+
+static void xguard_muxsel(struct bttv *btv, unsigned int input)
+{
+       static const int masks[] = {
+               ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10,
+               ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10,
+               ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11,
+               ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11,
+       };
+       gpio_write(masks[input%16]);
+}
+static void picolo_tetra_init(struct bttv *btv)
+{
+       /*This is the video input redirection fonctionality : I DID NOT USED IT. */
+       btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */
+       btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A]  set to 1*/
+}
+static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
+{
+
+       dprintk("%d : picolo_tetra_muxsel =>  input = %d\n", btv->c.nr, input);
+       /*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
+       /*GPIO[20]&GPIO[21] used to choose the right input*/
+       btwrite (input<<20,BT848_GPIO_DATA);
+
+}
+
+/*
+ * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
+ *
+ * The IVC120G security card has 4 i2c controlled TDA8540 matrix
+ * swichers to provide 16 channels to MUX0. The TDA8540's have
+ * 4 independent outputs and as such the IVC120G also has the
+ * optional "Monitor Out" bus. This allows the card to be looking
+ * at one input while the monitor is looking at another.
+ *
+ * Since I've couldn't be bothered figuring out how to add an
+ * independent muxsel for the monitor bus, I've just set it to
+ * whatever the card is looking at.
+ *
+ *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
+ *  OUT1 of the TDA8540's is connected to "Monitor Out"        (0x0C)
+ *
+ *  TDA8540_ALT3 IN0-3 = Channel 13 - 16       (0x03)
+ *  TDA8540_ALT4 IN0-3 = Channel 1 - 4         (0x03)
+ *  TDA8540_ALT5 IN0-3 = Channel 5 - 8         (0x03)
+ *  TDA8540_ALT6 IN0-3 = Channel 9 - 12                (0x03)
+ *
+ */
+
+/* All 7 possible sub-ids for the TDA8540 Matrix Switcher */
+#define I2C_TDA8540        0x90
+#define I2C_TDA8540_ALT1   0x92
+#define I2C_TDA8540_ALT2   0x94
+#define I2C_TDA8540_ALT3   0x96
+#define I2C_TDA8540_ALT4   0x98
+#define I2C_TDA8540_ALT5   0x9a
+#define I2C_TDA8540_ALT6   0x9c
+
+static void ivc120_muxsel(struct bttv *btv, unsigned int input)
+{
+       /* Simple maths */
+       int key = input % 4;
+       int matrix = input / 4;
+
+       dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+               btv->c.nr, input, matrix, key);
+
+       /* Handles the input selection on the TDA8540's */
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
+                     ((matrix == 3) ? (key | key << 2) : 0x00), 1);
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
+                     ((matrix == 0) ? (key | key << 2) : 0x00), 1);
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x00,
+                     ((matrix == 1) ? (key | key << 2) : 0x00), 1);
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
+                     ((matrix == 2) ? (key | key << 2) : 0x00), 1);
+
+       /* Handles the output enables on the TDA8540's */
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
+                     ((matrix == 3) ? 0x03 : 0x00), 1);  /* 13 - 16 */
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
+                     ((matrix == 0) ? 0x03 : 0x00), 1);  /* 1-4 */
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
+                     ((matrix == 1) ? 0x03 : 0x00), 1);  /* 5-8 */
+       bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
+                     ((matrix == 2) ? 0x03 : 0x00), 1);  /* 9-12 */
+
+       /* 878's MUX0 is already selected for input via muxsel values */
+}
+
+
+/* PXC200 muxsel helper
+ * luke@syseng.anu.edu.au
+ * another transplant
+ * from Alessandro Rubini (rubini@linux.it)
+ *
+ * There are 4 kinds of cards:
+ * PXC200L which is bt848
+ * PXC200F which is bt848 with PIC controlling mux
+ * PXC200AL which is bt878
+ * PXC200AF which is bt878 with PIC controlling mux
+ */
+#define PX_CFG_PXC200F 0x01
+#define PX_FLAG_PXC200A  0x00001000 /* a pxc200A is bt-878 based */
+#define PX_I2C_PIC       0x0f
+#define PX_PXC200A_CARDID 0x200a1295
+#define PX_I2C_CMD_CFG   0x00
+
+static void PXC200_muxsel(struct bttv *btv, unsigned int input)
+{
+       int rc;
+       long mux;
+       int bitmask;
+       unsigned char buf[2];
+
+       /* Read PIC config to determine if this is a PXC200F */
+       /* PX_I2C_CMD_CFG*/
+       buf[0]=0;
+       buf[1]=0;
+       rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
+       if (rc) {
+               pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+                        btv->c.nr, rc);
+         /* not PXC ? do nothing */
+               return;
+       }
+
+       rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
+       if (!(rc & PX_CFG_PXC200F)) {
+               pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+                        btv->c.nr, rc);
+               return;
+       }
+
+
+       /* The multiplexer in the 200F is handled by the GPIO port */
+       /* get correct mapping between inputs  */
+       /*  mux = bttv_tvcards[btv->type].muxsel[input] & 3; */
+       /* ** not needed!?   */
+       mux = input;
+
+       /* make sure output pins are enabled */
+       /* bitmask=0x30f; */
+       bitmask=0x302;
+       /* check whether we have a PXC200A */
+       if (btv->cardid == PX_PXC200A_CARDID)  {
+          bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */
+          bitmask |= 7<<4; /* the DAC */
+       }
+       btwrite(bitmask, BT848_GPIO_OUT_EN);
+
+       bitmask = btread(BT848_GPIO_DATA);
+       if (btv->cardid == PX_PXC200A_CARDID)
+         bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7);
+       else /* older device */
+         bitmask = (bitmask & ~0x300) | ((mux & 3) << 8);
+       btwrite(bitmask,BT848_GPIO_DATA);
+
+       /*
+        * Was "to be safe, set the bt848 to input 0"
+        * Actually, since it's ok at load time, better not messing
+        * with these bits (on PXC200AF you need to set mux 2 here)
+        *
+        * needed because bttv-driver sets mux before calling this function
+        */
+       if (btv->cardid == PX_PXC200A_CARDID)
+         btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM);
+       else /* older device */
+         btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
+
+       pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
+}
+
+static void phytec_muxsel(struct bttv *btv, unsigned int input)
+{
+       unsigned int mux = input % 4;
+
+       if (input == btv->svhs)
+               mux = 0;
+
+       gpio_bits(0x3, mux);
+}
+
+/*
+ * GeoVision GV-800(S) functions
+ * Bruno Christo <bchristo@inf.ufsm.br>
+*/
+
+/* This is a function to control the analog switch, which determines which
+ * camera is routed to which controller.  The switch comprises an X-address
+ * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
+ * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
+ * A data value (gpio bit 18) of '1' enables the switch, and '0' disables
+ * the switch.  A STROBE bit (gpio bit 17) latches the data value into the
+ * specified address. There is also a chip select (gpio bit 16).
+ * The idea is to set the address and chip select together, bring
+ * STROBE high, write the data, and finally bring STROBE back to low.
+ */
+static void gv800s_write(struct bttv *btv,
+                        unsigned char xaddr,
+                        unsigned char yaddr,
+                        unsigned char data) {
+       /* On the "master" 878A:
+       * GPIO bits 0-9 are used for the analog switch:
+       *   00 - 03:    camera selector
+       *   04 - 06:    878A (controller) selector
+       *   16:         cselect
+       *   17:         strobe
+       *   18:         data (1->on, 0->off)
+       *   19:         reset
+       */
+       const u32 ADDRESS = ((xaddr&0xf) | (yaddr&3)<<4);
+       const u32 CSELECT = 1<<16;
+       const u32 STROBE = 1<<17;
+       const u32 DATA = data<<18;
+
+       gpio_bits(0x1007f, ADDRESS | CSELECT);  /* write ADDRESS and CSELECT */
+       gpio_bits(0x20000, STROBE);             /* STROBE high */
+       gpio_bits(0x40000, DATA);               /* write DATA */
+       gpio_bits(0x20000, ~STROBE);            /* STROBE low */
+}
+
+/*
+ * GeoVision GV-800(S) muxsel
+ *
+ * Each of the 4 cards (controllers) use this function.
+ * The controller using this function selects the input through the GPIO pins
+ * of the "master" card. A pointer to this card is stored in master[btv->c.nr].
+ *
+ * The parameter 'input' is the requested camera number (0-4) on the controller.
+ * The map array has the address of each input. Note that the addresses in the
+ * array are in the sequence the original GeoVision driver uses, that is, set
+ * every controller to input 0, then to input 1, 2, 3, repeat. This means that
+ * the physical "camera 1" connector corresponds to controller 0 input 0,
+ * "camera 2" corresponds to controller 1 input 0, and so on.
+ *
+ * After getting the input address, the function then writes the appropriate
+ * data to the analog switch, and housekeeps the local copy of the switch
+ * information.
+ */
+static void gv800s_muxsel(struct bttv *btv, unsigned int input)
+{
+       struct bttv *mctlr;
+       char *sw_status;
+       int xaddr, yaddr;
+       static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
+                                         { 0x1, 0x5, 0xb, 0x7 },
+                                         { 0x2, 0x8, 0xc, 0xe },
+                                         { 0x3, 0x9, 0xd, 0xf } };
+       input = input%4;
+       mctlr = master[btv->c.nr];
+       if (mctlr == NULL) {
+               /* do nothing until the "master" is detected */
+               return;
+       }
+       yaddr = (btv->c.nr - mctlr->c.nr) & 3;
+       sw_status = (char *)(&mctlr->mbox_we);
+       xaddr = map[yaddr][input] & 0xf;
+
+       /* Check if the controller/camera pair has changed, ignore otherwise */
+       if (sw_status[yaddr] != xaddr) {
+               /* disable the old switch, enable the new one and save status */
+               gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
+               sw_status[yaddr] = xaddr;
+               gv800s_write(mctlr, xaddr, yaddr, 1);
+       }
+}
+
+/* GeoVision GV-800(S) "master" chip init */
+static void gv800s_init(struct bttv *btv)
+{
+       char *sw_status = (char *)(&btv->mbox_we);
+       int ix;
+
+       gpio_inout(0xf107f, 0xf107f);
+       gpio_write(1<<19); /* reset the analog MUX */
+       gpio_write(0);
+
+       /* Preset camera 0 to the 4 controllers */
+       for (ix = 0; ix < 4; ix++) {
+               sw_status[ix] = ix;
+               gv800s_write(btv, ix, ix, 1);
+       }
+
+       /* Inputs on the "master" controller need this brightness fix */
+       bttv_I2CWrite(btv, 0x18, 0x5, 0x90, 1);
+
+       if (btv->c.nr > BTTV_MAX-4)
+               return;
+       /*
+        * Store the "master" controller pointer in the master
+        * array for later use in the muxsel function.
+        */
+       master[btv->c.nr]   = btv;
+       master[btv->c.nr+1] = btv;
+       master[btv->c.nr+2] = btv;
+       master[btv->c.nr+3] = btv;
+}
+
+/* ----------------------------------------------------------------------- */
+/* motherboard chipset specific stuff                                      */
+
+void __init bttv_check_chipset(void)
+{
+       int pcipci_fail = 0;
+       struct pci_dev *dev = NULL;
+
+       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))       /* should check if target is AGP */
+               pcipci_fail = 1;
+       if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
+               triton1 = 1;
+       if (pci_pci_problems & PCIPCI_VSFX)
+               vsfx = 1;
+#ifdef PCIPCI_ALIMAGIK
+       if (pci_pci_problems & PCIPCI_ALIMAGIK)
+               latency = 0x0A;
+#endif
+
+
+       /* print warnings about any quirks found */
+       if (triton1)
+               pr_info("Host bridge needs ETBF enabled\n");
+       if (vsfx)
+               pr_info("Host bridge needs VSFX enabled\n");
+       if (pcipci_fail) {
+               pr_info("bttv and your chipset may not work together\n");
+               if (!no_overlay) {
+                       pr_info("overlay will be disabled\n");
+                       no_overlay = 1;
+               } else {
+                       pr_info("overlay forced. Use this option at your own risk.\n");
+               }
+       }
+       if (UNSET != latency)
+               pr_info("pci latency fixup [%d]\n", latency);
+       while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_82441, dev))) {
+               unsigned char b;
+               pci_read_config_byte(dev, 0x53, &b);
+               if (bttv_debug)
+                       pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+                               b);
+       }
+}
+
+int __devinit bttv_handle_chipset(struct bttv *btv)
+{
+       unsigned char command;
+
+       if (!triton1 && !vsfx && UNSET == latency)
+               return 0;
+
+       if (bttv_verbose) {
+               if (triton1)
+                       pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+                               btv->c.nr);
+               if (vsfx && btv->id >= 878)
+                       pr_info("%d: enabling VSFX\n", btv->c.nr);
+               if (UNSET != latency)
+                       pr_info("%d: setting pci timer to %d\n",
+                               btv->c.nr, latency);
+       }
+
+       if (btv->id < 878) {
+               /* bt848 (mis)uses a bit in the irq mask for etbf */
+               if (triton1)
+                       btv->triton1 = BT848_INT_ETBF;
+       } else {
+               /* bt878 has a bit in the pci config space for it */
+               pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command);
+               if (triton1)
+                       command |= BT878_EN_TBFX;
+               if (vsfx)
+                       command |= BT878_EN_VSFX;
+               pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command);
+       }
+       if (UNSET != latency)
+               pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
+       return 0;
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
new file mode 100644 (file)
index 0000000..b58ff87
--- /dev/null
@@ -0,0 +1,4630 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler <rjkm@thp.uni-koeln.de>
+                          & Marcus Metzler <mocm@thp.uni-koeln.de>
+    (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
+
+    some v4l2 code lines are taken from Justin's bttv2 driver which is
+    (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
+
+    V4L1 removal from:
+    (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+
+    Fixes to be fully V4L2 compliant by
+    (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tvaudio.h>
+#include <media/msp3400.h>
+
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <media/saa6588.h>
+
+#define BTTV_VERSION "0.9.19"
+
+unsigned int bttv_num;                 /* number of Bt848s in use */
+struct bttv *bttvs[BTTV_MAX];
+
+unsigned int bttv_debug;
+unsigned int bttv_verbose = 1;
+unsigned int bttv_gpio;
+
+/* config variables */
+#ifdef __BIG_ENDIAN
+static unsigned int bigendian=1;
+#else
+static unsigned int bigendian;
+#endif
+static unsigned int radio[BTTV_MAX];
+static unsigned int irq_debug;
+static unsigned int gbuffers = 8;
+static unsigned int gbufsize = 0x208000;
+static unsigned int reset_crop = 1;
+
+static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int debug_latency;
+static int disable_ir;
+
+static unsigned int fdsr;
+
+/* options */
+static unsigned int combfilter;
+static unsigned int lumafilter;
+static unsigned int automute    = 1;
+static unsigned int chroma_agc;
+static unsigned int adc_crush   = 1;
+static unsigned int whitecrush_upper = 0xCF;
+static unsigned int whitecrush_lower = 0x7F;
+static unsigned int vcr_hack;
+static unsigned int irq_iswitch;
+static unsigned int uv_ratio    = 50;
+static unsigned int full_luma_range;
+static unsigned int coring;
+
+/* API features (turn on/off stuff for testing) */
+static unsigned int v4l2        = 1;
+
+/* insmod args */
+module_param(bttv_verbose,      int, 0644);
+module_param(bttv_gpio,         int, 0644);
+module_param(bttv_debug,        int, 0644);
+module_param(irq_debug,         int, 0644);
+module_param(debug_latency,     int, 0644);
+module_param(disable_ir,        int, 0444);
+
+module_param(fdsr,              int, 0444);
+module_param(gbuffers,          int, 0444);
+module_param(gbufsize,          int, 0444);
+module_param(reset_crop,        int, 0444);
+
+module_param(v4l2,              int, 0644);
+module_param(bigendian,         int, 0644);
+module_param(irq_iswitch,       int, 0644);
+module_param(combfilter,        int, 0444);
+module_param(lumafilter,        int, 0444);
+module_param(automute,          int, 0444);
+module_param(chroma_agc,        int, 0444);
+module_param(adc_crush,         int, 0444);
+module_param(whitecrush_upper,  int, 0444);
+module_param(whitecrush_lower,  int, 0444);
+module_param(vcr_hack,          int, 0444);
+module_param(uv_ratio,          int, 0444);
+module_param(full_luma_range,   int, 0444);
+module_param(coring,            int, 0444);
+
+module_param_array(radio,       int, NULL, 0444);
+module_param_array(video_nr,    int, NULL, 0444);
+module_param_array(radio_nr,    int, NULL, 0444);
+module_param_array(vbi_nr,      int, NULL, 0444);
+
+MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
+MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
+MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
+MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
+MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
+MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+                "is 1 (yes) for compatibility with older applications");
+MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
+MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
+MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
+MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
+MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
+MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
+MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
+MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(BTTV_VERSION);
+
+/* ----------------------------------------------------------------------- */
+/* sysfs                                                                   */
+
+static ssize_t show_card(struct device *cd,
+                        struct device_attribute *attr, char *buf)
+{
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+       struct bttv *btv = video_get_drvdata(vfd);
+       return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
+}
+static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
+
+/* ----------------------------------------------------------------------- */
+/* dvb auto-load setup                                                     */
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       request_module("dvb-bt8xx");
+}
+
+static void request_modules(struct bttv *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct bttv *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+/* ----------------------------------------------------------------------- */
+/* static data                                                             */
+
+/* special timing tables from conexant... */
+static u8 SRAM_Table[][60] =
+{
+       /* PAL digital input over GPIO[7:0] */
+       {
+               45, // 45 bytes following
+               0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
+               0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
+               0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
+               0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
+               0x37,0x00,0xAF,0x21,0x00
+       },
+       /* NTSC digital input over GPIO[7:0] */
+       {
+               51, // 51 bytes following
+               0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
+               0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
+               0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
+               0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
+               0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
+               0x00,
+       },
+       // TGB_NTSC392 // quartzsight
+       // This table has been modified to be used for Fusion Rev D
+       {
+               0x2A, // size of table = 42
+               0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
+               0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
+               0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
+               0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
+               0x20, 0x00
+       }
+};
+
+/* minhdelayx1 first video pixel we can capture on a line and
+   hdelayx1    start of active video, both relative to rising edge of
+               /HRESET pulse (0H) in 1 / fCLKx1.
+   swidth      width of active video and
+   totalwidth  total line width, both in 1 / fCLKx1.
+   sqwidth     total line width in square pixels.
+   vdelay      start of active video in 2 * field lines relative to
+               trailing edge of /VRESET pulse (VDELAY register).
+   sheight     height of active video in 2 * field lines.
+   videostart0 ITU-R frame line number of the line corresponding
+               to vdelay in the first field. */
+#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,     \
+               vdelay, sheight, videostart0)                            \
+       .cropcap.bounds.left = minhdelayx1,                              \
+       /* * 2 because vertically we count field lines times two, */     \
+       /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */           \
+       .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
+       /* 4 is a safety margin at the end of the line. */               \
+       .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,        \
+       .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,      \
+       .cropcap.defrect.left = hdelayx1,                                \
+       .cropcap.defrect.top = (videostart0) * 2,                        \
+       .cropcap.defrect.width = swidth,                                 \
+       .cropcap.defrect.height = sheight,                               \
+       .cropcap.pixelaspect.numerator = totalwidth,                     \
+       .cropcap.pixelaspect.denominator = sqwidth,
+
+const struct bttv_tvnorm bttv_tvnorms[] = {
+       /* PAL-BDGHI */
+       /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+       /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
+       {
+               .v4l2_id        = V4L2_STD_PAL,
+               .name           = "PAL",
+               .Fsc            = 35468950,
+               .swidth         = 924,
+               .sheight        = 576,
+               .totalwidth     = 1135,
+               .adelay         = 0x7f,
+               .bdelay         = 0x72,
+               .iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+               .scaledtwidth   = 1135,
+               .hdelayx1       = 186,
+               .hactivex1      = 924,
+               .vdelay         = 0x20,
+               .vbipack        = 255, /* min (2048 / 4, 0x1ff) & 0xff */
+               .sram           = 0,
+               /* ITU-R frame line number of the first VBI line
+                  we can capture, of the first and second field.
+                  The last line is determined by cropcap.bounds. */
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* Should be (768 * 1135 + 944 / 2) / 944.
+                          cropcap.defrect is used for image width
+                          checks, so we keep the old value 924. */
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
+               /* bt878 (and bt848?) can capture another
+                  line below active video. */
+               .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
+       },{
+               .v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
+               .name           = "NTSC",
+               .Fsc            = 28636363,
+               .swidth         = 768,
+               .sheight        = 480,
+               .totalwidth     = 910,
+               .adelay         = 0x68,
+               .bdelay         = 0x5d,
+               .iform          = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+               .scaledtwidth   = 910,
+               .hdelayx1       = 128,
+               .hactivex1      = 910,
+               .vdelay         = 0x1a,
+               .vbipack        = 144, /* min (1600 / 4, 0x1ff) & 0xff */
+               .sram           = 1,
+               .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 128,
+                       /* Should be (640 * 910 + 780 / 2) / 780? */
+                       /* swidth */ 768,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
+       },{
+               .v4l2_id        = V4L2_STD_SECAM,
+               .name           = "SECAM",
+               .Fsc            = 35468950,
+               .swidth         = 924,
+               .sheight        = 576,
+               .totalwidth     = 1135,
+               .adelay         = 0x7f,
+               .bdelay         = 0xb0,
+               .iform          = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+               .scaledtwidth   = 1135,
+               .hdelayx1       = 186,
+               .hactivex1      = 922,
+               .vdelay         = 0x20,
+               .vbipack        = 255,
+               .sram           = 0, /* like PAL, correct? */
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
+       },{
+               .v4l2_id        = V4L2_STD_PAL_Nc,
+               .name           = "PAL-Nc",
+               .Fsc            = 28636363,
+               .swidth         = 640,
+               .sheight        = 576,
+               .totalwidth     = 910,
+               .adelay         = 0x68,
+               .bdelay         = 0x5d,
+               .iform          = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+               .scaledtwidth   = 780,
+               .hdelayx1       = 130,
+               .hactivex1      = 734,
+               .vdelay         = 0x1a,
+               .vbipack        = 144,
+               .sram           = -1,
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 130,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
+       },{
+               .v4l2_id        = V4L2_STD_PAL_M,
+               .name           = "PAL-M",
+               .Fsc            = 28636363,
+               .swidth         = 640,
+               .sheight        = 480,
+               .totalwidth     = 910,
+               .adelay         = 0x68,
+               .bdelay         = 0x5d,
+               .iform          = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+               .scaledtwidth   = 780,
+               .hdelayx1       = 135,
+               .hactivex1      = 754,
+               .vdelay         = 0x1a,
+               .vbipack        = 144,
+               .sram           = -1,
+               .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 135,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
+       },{
+               .v4l2_id        = V4L2_STD_PAL_N,
+               .name           = "PAL-N",
+               .Fsc            = 35468950,
+               .swidth         = 768,
+               .sheight        = 576,
+               .totalwidth     = 1135,
+               .adelay         = 0x7f,
+               .bdelay         = 0x72,
+               .iform          = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+               .scaledtwidth   = 944,
+               .hdelayx1       = 186,
+               .hactivex1      = 922,
+               .vdelay         = 0x20,
+               .vbipack        = 144,
+               .sram           = -1,
+               .vbistart       = { 7, 320 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ (768 * 1135 + 944 / 2) / 944,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x20,
+                       /* sheight */ 576,
+                       /* videostart0 */ 23)
+       },{
+               .v4l2_id        = V4L2_STD_NTSC_M_JP,
+               .name           = "NTSC-JP",
+               .Fsc            = 28636363,
+               .swidth         = 640,
+               .sheight        = 480,
+               .totalwidth     = 910,
+               .adelay         = 0x68,
+               .bdelay         = 0x5d,
+               .iform          = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+               .scaledtwidth   = 780,
+               .hdelayx1       = 135,
+               .hactivex1      = 754,
+               .vdelay         = 0x16,
+               .vbipack        = 144,
+               .sram           = -1,
+               .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 135,
+                       /* swidth */ (640 * 910 + 780 / 2) / 780,
+                       /* totalwidth */ 910,
+                       /* sqwidth */ 780,
+                       /* vdelay */ 0x16,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
+       },{
+               /* that one hopefully works with the strange timing
+                * which video recorders produce when playing a NTSC
+                * tape on a PAL TV ... */
+               .v4l2_id        = V4L2_STD_PAL_60,
+               .name           = "PAL-60",
+               .Fsc            = 35468950,
+               .swidth         = 924,
+               .sheight        = 480,
+               .totalwidth     = 1135,
+               .adelay         = 0x7f,
+               .bdelay         = 0x72,
+               .iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+               .scaledtwidth   = 1135,
+               .hdelayx1       = 186,
+               .hactivex1      = 924,
+               .vdelay         = 0x1a,
+               .vbipack        = 255,
+               .vtotal         = 524,
+               .sram           = -1,
+               .vbistart       = { 10, 273 },
+               CROPCAP(/* minhdelayx1 */ 68,
+                       /* hdelayx1 */ 186,
+                       /* swidth */ 924,
+                       /* totalwidth */ 1135,
+                       /* sqwidth */ 944,
+                       /* vdelay */ 0x1a,
+                       /* sheight */ 480,
+                       /* videostart0 */ 23)
+       }
+};
+static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
+
+/* ----------------------------------------------------------------------- */
+/* bttv format list
+   packed pixel formats must come first */
+static const struct bttv_format formats[] = {
+       {
+               .name     = "8 bpp, gray",
+               .fourcc   = V4L2_PIX_FMT_GREY,
+               .btformat = BT848_COLOR_FMT_Y8,
+               .depth    = 8,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "8 bpp, dithered color",
+               .fourcc   = V4L2_PIX_FMT_HI240,
+               .btformat = BT848_COLOR_FMT_RGB8,
+               .depth    = 8,
+               .flags    = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
+       },{
+               .name     = "15 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB555,
+               .btformat = BT848_COLOR_FMT_RGB15,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "15 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB555X,
+               .btformat = BT848_COLOR_FMT_RGB15,
+               .btswap   = 0x03, /* byteswap */
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "16 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .btformat = BT848_COLOR_FMT_RGB16,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "16 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB565X,
+               .btformat = BT848_COLOR_FMT_RGB16,
+               .btswap   = 0x03, /* byteswap */
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "24 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR24,
+               .btformat = BT848_COLOR_FMT_RGB24,
+               .depth    = 24,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "32 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR32,
+               .btformat = BT848_COLOR_FMT_RGB32,
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "32 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB32,
+               .btformat = BT848_COLOR_FMT_RGB32,
+               .btswap   = 0x0f, /* byte+word swap */
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "4:2:2, packed, YUYV",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .btformat = BT848_COLOR_FMT_YUY2,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .btformat = BT848_COLOR_FMT_YUY2,
+               .btswap   = 0x03, /* byteswap */
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "4:2:2, planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV422P,
+               .btformat = BT848_COLOR_FMT_YCrCb422,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PLANAR,
+               .hshift   = 1,
+               .vshift   = 0,
+       },{
+               .name     = "4:2:0, planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV420,
+               .btformat = BT848_COLOR_FMT_YCrCb422,
+               .depth    = 12,
+               .flags    = FORMAT_FLAGS_PLANAR,
+               .hshift   = 1,
+               .vshift   = 1,
+       },{
+               .name     = "4:2:0, planar, Y-Cr-Cb",
+               .fourcc   = V4L2_PIX_FMT_YVU420,
+               .btformat = BT848_COLOR_FMT_YCrCb422,
+               .depth    = 12,
+               .flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
+               .hshift   = 1,
+               .vshift   = 1,
+       },{
+               .name     = "4:1:1, planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV411P,
+               .btformat = BT848_COLOR_FMT_YCrCb411,
+               .depth    = 12,
+               .flags    = FORMAT_FLAGS_PLANAR,
+               .hshift   = 2,
+               .vshift   = 0,
+       },{
+               .name     = "4:1:0, planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV410,
+               .btformat = BT848_COLOR_FMT_YCrCb411,
+               .depth    = 9,
+               .flags    = FORMAT_FLAGS_PLANAR,
+               .hshift   = 2,
+               .vshift   = 2,
+       },{
+               .name     = "4:1:0, planar, Y-Cr-Cb",
+               .fourcc   = V4L2_PIX_FMT_YVU410,
+               .btformat = BT848_COLOR_FMT_YCrCb411,
+               .depth    = 9,
+               .flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
+               .hshift   = 2,
+               .vshift   = 2,
+       },{
+               .name     = "raw scanlines",
+               .fourcc   = -1,
+               .btformat = BT848_COLOR_FMT_RAW,
+               .depth    = 8,
+               .flags    = FORMAT_FLAGS_RAW,
+       }
+};
+static const unsigned int FORMATS = ARRAY_SIZE(formats);
+
+/* ----------------------------------------------------------------------- */
+
+#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
+
+static const struct v4l2_queryctrl no_ctl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+static const struct v4l2_queryctrl bttv_ctls[] = {
+       /* --- video --- */
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 256,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_CONTRAST,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 128,
+               .default_value = 27648,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_SATURATION,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 128,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_HUE,
+               .name          = "Hue",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 256,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },
+       /* --- audio --- */
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 65535,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_AUDIO_BALANCE,
+               .name          = "Balance",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_AUDIO_BASS,
+               .name          = "Bass",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_AUDIO_TREBLE,
+               .name          = "Treble",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535/100,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },
+       /* --- private --- */
+       {
+               .id            = V4L2_CID_PRIVATE_CHROMA_AGC,
+               .name          = "chroma agc",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_COMBFILTER,
+               .name          = "combfilter",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_AUTOMUTE,
+               .name          = "automute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_LUMAFILTER,
+               .name          = "luma decimation filter",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_AGC_CRUSH,
+               .name          = "agc crush",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_VCR_HACK,
+               .name          = "vcr hack",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
+               .name          = "whitecrush upper",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 0xCF,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
+               .name          = "whitecrush lower",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 0x7F,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_UV_RATIO,
+               .name          = "uv ratio",
+               .minimum       = 0,
+               .maximum       = 100,
+               .step          = 1,
+               .default_value = 50,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+               .name          = "full luma range",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_CORING,
+               .name          = "coring",
+               .minimum       = 0,
+               .maximum       = 3,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+
+
+
+};
+
+static const struct v4l2_queryctrl *ctrl_by_id(int id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
+               if (bttv_ctls[i].id == id)
+                       return bttv_ctls+i;
+
+       return NULL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* resource management                                                     */
+
+/*
+   RESOURCE_    allocated by                freed by
+
+   VIDEO_READ   bttv_read 1)                bttv_read 2)
+
+   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF
+                VIDIOC_QBUF 1)              bttv_release
+                VIDIOCMCAPTURE 1)
+
+   OVERLAY      VIDIOCCAPTURE on            VIDIOCCAPTURE off
+                VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
+                3)                          bttv_release
+
+   VBI          VIDIOC_STREAMON             VIDIOC_STREAMOFF
+                VIDIOC_QBUF 1)              bttv_release
+                bttv_read, bttv_poll 1) 4)
+
+   1) The resource must be allocated when we enter buffer prepare functions
+      and remain allocated while buffers are in the DMA queue.
+   2) This is a single frame read.
+   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
+      RESOURCE_OVERLAY is allocated.
+   4) This is a continuous read, implies VIDIOC_STREAMON.
+
+   Note this driver permits video input and standard changes regardless if
+   resources are allocated.
+*/
+
+#define VBI_RESOURCES (RESOURCE_VBI)
+#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
+                        RESOURCE_VIDEO_STREAM | \
+                        RESOURCE_OVERLAY)
+
+static
+int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
+{
+       int xbits; /* mutual exclusive resources */
+
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       xbits = bit;
+       if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
+               xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
+
+       /* is it free? */
+       if (btv->resources & xbits) {
+               /* no, someone else uses it */
+               goto fail;
+       }
+
+       if ((bit & VIDEO_RESOURCES)
+           && 0 == (btv->resources & VIDEO_RESOURCES)) {
+               /* Do crop - use current, don't - use default parameters. */
+               __s32 top = btv->crop[!!fh->do_crop].rect.top;
+
+               if (btv->vbi_end > top)
+                       goto fail;
+
+               /* We cannot capture the same line as video and VBI data.
+                  Claim scan lines crop[].rect.top to bottom. */
+               btv->crop_start = top;
+       } else if (bit & VBI_RESOURCES) {
+               __s32 end = fh->vbi_fmt.end;
+
+               if (end > btv->crop_start)
+                       goto fail;
+
+               /* Claim scan lines above fh->vbi_fmt.end. */
+               btv->vbi_end = end;
+       }
+
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       btv->resources |= bit;
+       return 1;
+
+ fail:
+       return 0;
+}
+
+static
+int check_btres(struct bttv_fh *fh, int bit)
+{
+       return (fh->resources & bit);
+}
+
+static
+int locked_btres(struct bttv *btv, int bit)
+{
+       return (btv->resources & bit);
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_vbi_lines(struct bttv *btv)
+{
+       btv->vbi_end = 0;
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_video_lines(struct bttv *btv)
+{
+       const struct bttv_tvnorm *tvnorm;
+       u8 crop;
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+       btv->crop_start = tvnorm->cropcap.bounds.top
+               + tvnorm->cropcap.bounds.height;
+
+       /* VBI capturing ends at VDELAY, start of video capturing, no
+          matter how many lines the VBI RISC program expects. When video
+          capturing is off, it shall no longer "preempt" VBI capturing,
+          so we set VDELAY to maximum. */
+       crop = btread(BT848_E_CROP) | 0xc0;
+       btwrite(crop, BT848_E_CROP);
+       btwrite(0xfe, BT848_E_VDELAY_LO);
+       btwrite(crop, BT848_O_CROP);
+       btwrite(0xfe, BT848_O_VDELAY_LO);
+}
+
+static
+void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
+{
+       if ((fh->resources & bits) != bits) {
+               /* trying to free resources not allocated by us ... */
+               pr_err("BUG! (btres)\n");
+       }
+       fh->resources  &= ~bits;
+       btv->resources &= ~bits;
+
+       bits = btv->resources;
+
+       if (0 == (bits & VIDEO_RESOURCES))
+               disclaim_video_lines(btv);
+
+       if (0 == (bits & VBI_RESOURCES))
+               disclaim_vbi_lines(btv);
+}
+
+/* ----------------------------------------------------------------------- */
+/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC          */
+
+/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
+   PLL_X = Reference pre-divider (0=1, 1=2)
+   PLL_C = Post divider (0=6, 1=4)
+   PLL_I = Integer input
+   PLL_F = Fractional input
+
+   F_input = 28.636363 MHz:
+   PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
+*/
+
+static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
+{
+       unsigned char fl, fh, fi;
+
+       /* prevent overflows */
+       fin/=4;
+       fout/=4;
+
+       fout*=12;
+       fi=fout/fin;
+
+       fout=(fout%fin)*256;
+       fh=fout/fin;
+
+       fout=(fout%fin)*256;
+       fl=fout/fin;
+
+       btwrite(fl, BT848_PLL_F_LO);
+       btwrite(fh, BT848_PLL_F_HI);
+       btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
+}
+
+static void set_pll(struct bttv *btv)
+{
+       int i;
+
+       if (!btv->pll.pll_crystal)
+               return;
+
+       if (btv->pll.pll_ofreq == btv->pll.pll_current) {
+               dprintk("%d: PLL: no change required\n", btv->c.nr);
+               return;
+       }
+
+       if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
+               /* no PLL needed */
+               if (btv->pll.pll_current == 0)
+                       return;
+               if (bttv_verbose)
+                       pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+                               btv->c.nr, btv->pll.pll_ifreq);
+               btwrite(0x00,BT848_TGCTRL);
+               btwrite(0x00,BT848_PLL_XCI);
+               btv->pll.pll_current = 0;
+               return;
+       }
+
+       if (bttv_verbose)
+               pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+                       btv->c.nr,
+                       btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+       set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+
+       for (i=0; i<10; i++) {
+               /*  Let other people run while the PLL stabilizes */
+               msleep(10);
+
+               if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
+                       btwrite(0,BT848_DSTATUS);
+               } else {
+                       btwrite(0x08,BT848_TGCTRL);
+                       btv->pll.pll_current = btv->pll.pll_ofreq;
+                       if (bttv_verbose)
+                               pr_info("PLL set ok\n");
+                       return;
+               }
+       }
+       btv->pll.pll_current = -1;
+       if (bttv_verbose)
+               pr_info("Setting PLL failed\n");
+       return;
+}
+
+/* used to switch between the bt848's analog/digital video capture modes */
+static void bt848A_set_timing(struct bttv *btv)
+{
+       int i, len;
+       int table_idx = bttv_tvnorms[btv->tvnorm].sram;
+       int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
+
+       if (btv->input == btv->dig) {
+               dprintk("%d: load digital timing table (table_idx=%d)\n",
+                       btv->c.nr,table_idx);
+
+               /* timing change...reset timing generator address */
+               btwrite(0x00, BT848_TGCTRL);
+               btwrite(0x02, BT848_TGCTRL);
+               btwrite(0x00, BT848_TGCTRL);
+
+               len=SRAM_Table[table_idx][0];
+               for(i = 1; i <= len; i++)
+                       btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
+               btv->pll.pll_ofreq = 27000000;
+
+               set_pll(btv);
+               btwrite(0x11, BT848_TGCTRL);
+               btwrite(0x41, BT848_DVSIF);
+       } else {
+               btv->pll.pll_ofreq = fsc;
+               set_pll(btv);
+               btwrite(0x0, BT848_DVSIF);
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void bt848_bright(struct bttv *btv, int bright)
+{
+       int value;
+
+       // printk("set bright: %d\n", bright); // DEBUG
+       btv->bright = bright;
+
+       /* We want -128 to 127 we get 0-65535 */
+       value = (bright >> 8) - 128;
+       btwrite(value & 0xff, BT848_BRIGHT);
+}
+
+static void bt848_hue(struct bttv *btv, int hue)
+{
+       int value;
+
+       btv->hue = hue;
+
+       /* -128 to 127 */
+       value = (hue >> 8) - 128;
+       btwrite(value & 0xff, BT848_HUE);
+}
+
+static void bt848_contrast(struct bttv *btv, int cont)
+{
+       int value,hibit;
+
+       btv->contrast = cont;
+
+       /* 0-511 */
+       value = (cont  >> 7);
+       hibit = (value >> 6) & 4;
+       btwrite(value & 0xff, BT848_CONTRAST_LO);
+       btaor(hibit, ~4, BT848_E_CONTROL);
+       btaor(hibit, ~4, BT848_O_CONTROL);
+}
+
+static void bt848_sat(struct bttv *btv, int color)
+{
+       int val_u,val_v,hibits;
+
+       btv->saturation = color;
+
+       /* 0-511 for the color */
+       val_u   = ((color * btv->opt_uv_ratio) / 50) >> 7;
+       val_v   = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
+       hibits  = (val_u >> 7) & 2;
+       hibits |= (val_v >> 8) & 1;
+       btwrite(val_u & 0xff, BT848_SAT_U_LO);
+       btwrite(val_v & 0xff, BT848_SAT_V_LO);
+       btaor(hibits, ~3, BT848_E_CONTROL);
+       btaor(hibits, ~3, BT848_O_CONTROL);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int
+video_mux(struct bttv *btv, unsigned int input)
+{
+       int mux,mask2;
+
+       if (input >= bttv_tvcards[btv->c.type].video_inputs)
+               return -EINVAL;
+
+       /* needed by RemoteVideo MX */
+       mask2 = bttv_tvcards[btv->c.type].gpiomask2;
+       if (mask2)
+               gpio_inout(mask2,mask2);
+
+       if (input == btv->svhs)  {
+               btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
+               btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
+       } else {
+               btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+               btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+       }
+       mux = bttv_muxsel(btv, input);
+       btaor(mux<<5, ~(3<<5), BT848_IFORM);
+       dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
+
+       /* card specific hook */
+       if(bttv_tvcards[btv->c.type].muxsel_hook)
+               bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
+       return 0;
+}
+
+static char *audio_modes[] = {
+       "audio: tuner", "audio: radio", "audio: extern",
+       "audio: intern", "audio: mute"
+};
+
+static int
+audio_mux(struct bttv *btv, int input, int mute)
+{
+       int gpio_val, signal;
+       struct v4l2_control ctrl;
+
+       gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
+                  bttv_tvcards[btv->c.type].gpiomask);
+       signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
+
+       btv->mute = mute;
+       btv->audio = input;
+
+       /* automute */
+       mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+
+       if (mute)
+               gpio_val = bttv_tvcards[btv->c.type].gpiomute;
+       else
+               gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
+
+       switch (btv->c.type) {
+       case BTTV_BOARD_VOODOOTV_FM:
+       case BTTV_BOARD_VOODOOTV_200:
+               gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
+               break;
+
+       default:
+               gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
+       }
+
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
+       if (in_interrupt())
+               return 0;
+
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = btv->mute;
+       bttv_call_all(btv, core, s_ctrl, &ctrl);
+       if (btv->sd_msp34xx) {
+               u32 in;
+
+               /* Note: the inputs tuner/radio/extern/intern are translated
+                  to msp routings. This assumes common behavior for all msp3400
+                  based TV cards. When this assumption fails, then the
+                  specific MSP routing must be added to the card table.
+                  For now this is sufficient. */
+               switch (input) {
+               case TVAUDIO_INPUT_RADIO:
+                       /* Some boards need the msp do to the radio demod */
+                       if (btv->radio_uses_msp_demodulator) {
+                               in = MSP_INPUT_DEFAULT;
+                               break;
+                       }
+                       in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+                       break;
+               case TVAUDIO_INPUT_EXTERN:
+                       in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+                       break;
+               case TVAUDIO_INPUT_INTERN:
+                       /* Yes, this is the same input as for RADIO. I doubt
+                          if this is ever used. The only board with an INTERN
+                          input is the BTTV_BOARD_AVERMEDIA98. I wonder how
+                          that was tested. My guess is that the whole INTERN
+                          input does not work. */
+                       in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+                       break;
+               case TVAUDIO_INPUT_TUNER:
+               default:
+                       /* This is the only card that uses TUNER2, and afaik,
+                          is the only difference between the VOODOOTV_FM
+                          and VOODOOTV_200 */
+                       if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
+                               in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
+                                       MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
+                       else
+                               in = MSP_INPUT_DEFAULT;
+                       break;
+               }
+               v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
+                              in, MSP_OUTPUT_DEFAULT, 0);
+       }
+       if (btv->sd_tvaudio) {
+               v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
+                               input, 0, 0);
+       }
+       return 0;
+}
+
+static inline int
+audio_mute(struct bttv *btv, int mute)
+{
+       return audio_mux(btv, btv->audio, mute);
+}
+
+static inline int
+audio_input(struct bttv *btv, int input)
+{
+       return audio_mux(btv, input, btv->mute);
+}
+
+static void
+bttv_crop_calc_limits(struct bttv_crop *c)
+{
+       /* Scale factor min. 1:1, max. 16:1. Min. image size
+          48 x 32. Scaled width must be a multiple of 4. */
+
+       if (1) {
+               /* For bug compatibility with VIDIOCGCAP and image
+                  size checks in earlier driver versions. */
+               c->min_scaled_width = 48;
+               c->min_scaled_height = 32;
+       } else {
+               c->min_scaled_width =
+                       (max(48, c->rect.width >> 4) + 3) & ~3;
+               c->min_scaled_height =
+                       max(32, c->rect.height >> 4);
+       }
+
+       c->max_scaled_width  = c->rect.width & ~3;
+       c->max_scaled_height = c->rect.height;
+}
+
+static void
+bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
+{
+       c->rect = bttv_tvnorms[norm].cropcap.defrect;
+       bttv_crop_calc_limits(c);
+}
+
+/* Call with btv->lock down. */
+static int
+set_tvnorm(struct bttv *btv, unsigned int norm)
+{
+       const struct bttv_tvnorm *tvnorm;
+       v4l2_std_id id;
+
+       BUG_ON(norm >= BTTV_TVNORMS);
+       BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
+
+       tvnorm = &bttv_tvnorms[norm];
+
+       if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
+                   sizeof (tvnorm->cropcap))) {
+               bttv_crop_reset(&btv->crop[0], norm);
+               btv->crop[1] = btv->crop[0]; /* current = default */
+
+               if (0 == (btv->resources & VIDEO_RESOURCES)) {
+                       btv->crop_start = tvnorm->cropcap.bounds.top
+                               + tvnorm->cropcap.bounds.height;
+               }
+       }
+
+       btv->tvnorm = norm;
+
+       btwrite(tvnorm->adelay, BT848_ADELAY);
+       btwrite(tvnorm->bdelay, BT848_BDELAY);
+       btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
+             BT848_IFORM);
+       btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
+       btwrite(1, BT848_VBI_PACK_DEL);
+       bt848A_set_timing(btv);
+
+       switch (btv->c.type) {
+       case BTTV_BOARD_VOODOOTV_FM:
+       case BTTV_BOARD_VOODOOTV_200:
+               bttv_tda9880_setnorm(btv, gpio_read());
+               break;
+       }
+       id = tvnorm->v4l2_id;
+       bttv_call_all(btv, core, s_std, id);
+
+       return 0;
+}
+
+/* Call with btv->lock down. */
+static void
+set_input(struct bttv *btv, unsigned int input, unsigned int norm)
+{
+       unsigned long flags;
+
+       btv->input = input;
+       if (irq_iswitch) {
+               spin_lock_irqsave(&btv->s_lock,flags);
+               if (btv->curr.frame_irq) {
+                       /* active capture -> delayed input switch */
+                       btv->new_input = input;
+               } else {
+                       video_mux(btv,input);
+               }
+               spin_unlock_irqrestore(&btv->s_lock,flags);
+       } else {
+               video_mux(btv,input);
+       }
+       audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
+                        TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
+       set_tvnorm(btv, norm);
+}
+
+static void init_irqreg(struct bttv *btv)
+{
+       /* clear status */
+       btwrite(0xfffffUL, BT848_INT_STAT);
+
+       if (bttv_tvcards[btv->c.type].no_video) {
+               /* i2c only */
+               btwrite(BT848_INT_I2CDONE,
+                       BT848_INT_MASK);
+       } else {
+               /* full video */
+               btwrite((btv->triton1)  |
+                       (btv->gpioirq ? BT848_INT_GPINT : 0) |
+                       BT848_INT_SCERR |
+                       (fdsr ? BT848_INT_FDSR : 0) |
+                       BT848_INT_RISCI | BT848_INT_OCERR |
+                       BT848_INT_FMTCHG|BT848_INT_HLOCK|
+                       BT848_INT_I2CDONE,
+                       BT848_INT_MASK);
+       }
+}
+
+static void init_bt848(struct bttv *btv)
+{
+       int val;
+
+       if (bttv_tvcards[btv->c.type].no_video) {
+               /* very basic init only */
+               init_irqreg(btv);
+               return;
+       }
+
+       btwrite(0x00, BT848_CAP_CTL);
+       btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
+       btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
+
+       /* set planar and packed mode trigger points and         */
+       /* set rising edge of inverted GPINTR pin as irq trigger */
+       btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
+               BT848_GPIO_DMA_CTL_PLTP1_16|
+               BT848_GPIO_DMA_CTL_PLTP23_16|
+               BT848_GPIO_DMA_CTL_GPINTC|
+               BT848_GPIO_DMA_CTL_GPINTI,
+               BT848_GPIO_DMA_CTL);
+
+       val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
+       btwrite(val, BT848_E_SCLOOP);
+       btwrite(val, BT848_O_SCLOOP);
+
+       btwrite(0x20, BT848_E_VSCALE_HI);
+       btwrite(0x20, BT848_O_VSCALE_HI);
+       btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+               BT848_ADC);
+
+       btwrite(whitecrush_upper, BT848_WC_UP);
+       btwrite(whitecrush_lower, BT848_WC_DOWN);
+
+       if (btv->opt_lumafilter) {
+               btwrite(0, BT848_E_CONTROL);
+               btwrite(0, BT848_O_CONTROL);
+       } else {
+               btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
+               btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+       }
+
+       bt848_bright(btv,   btv->bright);
+       bt848_hue(btv,      btv->hue);
+       bt848_contrast(btv, btv->contrast);
+       bt848_sat(btv,      btv->saturation);
+
+       /* interrupt */
+       init_irqreg(btv);
+}
+
+static void bttv_reinit_bt848(struct bttv *btv)
+{
+       unsigned long flags;
+
+       if (bttv_verbose)
+               pr_info("%d: reset, reinitialize\n", btv->c.nr);
+       spin_lock_irqsave(&btv->s_lock,flags);
+       btv->errors=0;
+       bttv_set_dma(btv,0);
+       spin_unlock_irqrestore(&btv->s_lock,flags);
+
+       init_bt848(btv);
+       btv->pll.pll_current = -1;
+       set_input(btv, btv->input, btv->tvnorm);
+}
+
+static int bttv_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *c)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = btv->bright;
+               break;
+       case V4L2_CID_HUE:
+               c->value = btv->hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->value = btv->contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               c->value = btv->saturation;
+               break;
+
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+               bttv_call_all(btv, core, g_ctrl, c);
+               break;
+
+       case V4L2_CID_PRIVATE_CHROMA_AGC:
+               c->value = btv->opt_chroma_agc;
+               break;
+       case V4L2_CID_PRIVATE_COMBFILTER:
+               c->value = btv->opt_combfilter;
+               break;
+       case V4L2_CID_PRIVATE_LUMAFILTER:
+               c->value = btv->opt_lumafilter;
+               break;
+       case V4L2_CID_PRIVATE_AUTOMUTE:
+               c->value = btv->opt_automute;
+               break;
+       case V4L2_CID_PRIVATE_AGC_CRUSH:
+               c->value = btv->opt_adc_crush;
+               break;
+       case V4L2_CID_PRIVATE_VCR_HACK:
+               c->value = btv->opt_vcr_hack;
+               break;
+       case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+               c->value = btv->opt_whitecrush_upper;
+               break;
+       case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+               c->value = btv->opt_whitecrush_lower;
+               break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               c->value = btv->opt_uv_ratio;
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               c->value = btv->opt_full_luma_range;
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               c->value = btv->opt_coring;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int bttv_s_ctrl(struct file *file, void *f,
+                                       struct v4l2_control *c)
+{
+       int err;
+       int val;
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       err = v4l2_prio_check(&btv->prio, fh->prio);
+       if (0 != err)
+               return err;
+
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               bt848_bright(btv, c->value);
+               break;
+       case V4L2_CID_HUE:
+               bt848_hue(btv, c->value);
+               break;
+       case V4L2_CID_CONTRAST:
+               bt848_contrast(btv, c->value);
+               break;
+       case V4L2_CID_SATURATION:
+               bt848_sat(btv, c->value);
+               break;
+       case V4L2_CID_AUDIO_MUTE:
+               audio_mute(btv, c->value);
+               /* fall through */
+       case V4L2_CID_AUDIO_VOLUME:
+               if (btv->volume_gpio)
+                       btv->volume_gpio(btv, c->value);
+
+               bttv_call_all(btv, core, s_ctrl, c);
+               break;
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+               bttv_call_all(btv, core, s_ctrl, c);
+               break;
+
+       case V4L2_CID_PRIVATE_CHROMA_AGC:
+               btv->opt_chroma_agc = c->value;
+               val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
+               btwrite(val, BT848_E_SCLOOP);
+               btwrite(val, BT848_O_SCLOOP);
+               break;
+       case V4L2_CID_PRIVATE_COMBFILTER:
+               btv->opt_combfilter = c->value;
+               break;
+       case V4L2_CID_PRIVATE_LUMAFILTER:
+               btv->opt_lumafilter = c->value;
+               if (btv->opt_lumafilter) {
+                       btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
+                       btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
+               } else {
+                       btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
+                       btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+               }
+               break;
+       case V4L2_CID_PRIVATE_AUTOMUTE:
+               btv->opt_automute = c->value;
+               break;
+       case V4L2_CID_PRIVATE_AGC_CRUSH:
+               btv->opt_adc_crush = c->value;
+               btwrite(BT848_ADC_RESERVED |
+                               (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+                               BT848_ADC);
+               break;
+       case V4L2_CID_PRIVATE_VCR_HACK:
+               btv->opt_vcr_hack = c->value;
+               break;
+       case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+               btv->opt_whitecrush_upper = c->value;
+               btwrite(c->value, BT848_WC_UP);
+               break;
+       case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+               btv->opt_whitecrush_lower = c->value;
+               btwrite(c->value, BT848_WC_DOWN);
+               break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               btv->opt_uv_ratio = c->value;
+               bt848_sat(btv, btv->saturation);
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               btv->opt_full_luma_range = c->value;
+               btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               btv->opt_coring = c->value;
+               btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void bttv_gpio_tracking(struct bttv *btv, char *comment)
+{
+       unsigned int outbits, data;
+       outbits = btread(BT848_GPIO_OUT_EN);
+       data    = btread(BT848_GPIO_DATA);
+       pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+                btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
+}
+
+static void bttv_field_count(struct bttv *btv)
+{
+       int need_count = 0;
+
+       if (btv->users)
+               need_count++;
+
+       if (need_count) {
+               /* start field counter */
+               btor(BT848_INT_VSYNC,BT848_INT_MASK);
+       } else {
+               /* stop field counter */
+               btand(~BT848_INT_VSYNC,BT848_INT_MASK);
+               btv->field_count = 0;
+       }
+}
+
+static const struct bttv_format*
+format_by_fourcc(int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < FORMATS; i++) {
+               if (-1 == formats[i].fourcc)
+                       continue;
+               if (formats[i].fourcc == fourcc)
+                       return formats+i;
+       }
+       return NULL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* misc helpers                                                            */
+
+static int
+bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
+                   struct bttv_buffer *new)
+{
+       struct bttv_buffer *old;
+       unsigned long flags;
+       int retval = 0;
+
+       dprintk("switch_overlay: enter [new=%p]\n", new);
+       if (new)
+               new->vb.state = VIDEOBUF_DONE;
+       spin_lock_irqsave(&btv->s_lock,flags);
+       old = btv->screen;
+       btv->screen = new;
+       btv->loop_irq |= 1;
+       bttv_set_dma(btv, 0x03);
+       spin_unlock_irqrestore(&btv->s_lock,flags);
+       if (NULL != old) {
+               dprintk("switch_overlay: old=%p state is %d\n",
+                       old, old->vb.state);
+               bttv_dma_free(&fh->cap,btv, old);
+               kfree(old);
+       }
+       if (NULL == new)
+               free_btres_lock(btv,fh,RESOURCE_OVERLAY);
+       dprintk("switch_overlay: done\n");
+       return retval;
+}
+
+/* ----------------------------------------------------------------------- */
+/* video4linux (1) interface                                               */
+
+static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
+                              struct bttv_buffer *buf,
+                              const struct bttv_format *fmt,
+                              unsigned int width, unsigned int height,
+                              enum v4l2_field field)
+{
+       struct bttv_fh *fh = q->priv_data;
+       int redo_dma_risc = 0;
+       struct bttv_crop c;
+       int norm;
+       int rc;
+
+       /* check settings */
+       if (NULL == fmt)
+               return -EINVAL;
+       if (fmt->btformat == BT848_COLOR_FMT_RAW) {
+               width  = RAW_BPL;
+               height = RAW_LINES*2;
+               if (width*height > buf->vb.bsize)
+                       return -EINVAL;
+               buf->vb.size = buf->vb.bsize;
+
+               /* Make sure tvnorm and vbi_end remain consistent
+                  until we're done. */
+
+               norm = btv->tvnorm;
+
+               /* In this mode capturing always starts at defrect.top
+                  (default VDELAY), ignoring cropping parameters. */
+               if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
+                       return -EINVAL;
+               }
+
+               c.rect = bttv_tvnorms[norm].cropcap.defrect;
+       } else {
+               norm = btv->tvnorm;
+               c = btv->crop[!!fh->do_crop];
+
+               if (width < c.min_scaled_width ||
+                   width > c.max_scaled_width ||
+                   height < c.min_scaled_height)
+                       return -EINVAL;
+
+               switch (field) {
+               case V4L2_FIELD_TOP:
+               case V4L2_FIELD_BOTTOM:
+               case V4L2_FIELD_ALTERNATE:
+                       /* btv->crop counts frame lines. Max. scale
+                          factor is 16:1 for frames, 8:1 for fields. */
+                       if (height * 2 > c.max_scaled_height)
+                               return -EINVAL;
+                       break;
+
+               default:
+                       if (height > c.max_scaled_height)
+                               return -EINVAL;
+                       break;
+               }
+
+               buf->vb.size = (width * height * fmt->depth) >> 3;
+               if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+                       return -EINVAL;
+       }
+
+       /* alloc + fill struct bttv_buffer (if changed) */
+       if (buf->vb.width != width || buf->vb.height != height ||
+           buf->vb.field != field ||
+           buf->tvnorm != norm || buf->fmt != fmt ||
+           buf->crop.top != c.rect.top ||
+           buf->crop.left != c.rect.left ||
+           buf->crop.width != c.rect.width ||
+           buf->crop.height != c.rect.height) {
+               buf->vb.width  = width;
+               buf->vb.height = height;
+               buf->vb.field  = field;
+               buf->tvnorm    = norm;
+               buf->fmt       = fmt;
+               buf->crop      = c.rect;
+               redo_dma_risc = 1;
+       }
+
+       /* alloc risc memory */
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               redo_dma_risc = 1;
+               if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
+                       goto fail;
+       }
+
+       if (redo_dma_risc)
+               if (0 != (rc = bttv_buffer_risc(btv,buf)))
+                       goto fail;
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       bttv_dma_free(q,btv,buf);
+       return rc;
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       struct bttv_fh *fh = q->priv_data;
+
+       *size = fh->fmt->depth*fh->width*fh->height >> 3;
+       if (0 == *count)
+               *count = gbuffers;
+       if (*size * *count > gbuffers * gbufsize)
+               *count = (gbuffers * gbufsize) / *size;
+       return 0;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+              enum v4l2_field field)
+{
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+       struct bttv_fh *fh = q->priv_data;
+
+       return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
+                                  fh->width, fh->height, field);
+}
+
+static void
+buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+       struct bttv_fh *fh = q->priv_data;
+       struct bttv    *btv = fh->btv;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue,&btv->capture);
+       if (!btv->curr.frame_irq) {
+               btv->loop_irq |= 1;
+               bttv_set_dma(btv, 0x03);
+       }
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+       struct bttv_fh *fh = q->priv_data;
+
+       bttv_dma_free(q,fh->btv,buf);
+}
+
+static struct videobuf_queue_ops bttv_video_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct bttv_fh *fh  = priv;
+       struct bttv *btv = fh->btv;
+       unsigned int i;
+       int err;
+
+       err = v4l2_prio_check(&btv->prio, fh->prio);
+       if (err)
+               goto err;
+
+       for (i = 0; i < BTTV_TVNORMS; i++)
+               if (*id & bttv_tvnorms[i].v4l2_id)
+                       break;
+       if (i == BTTV_TVNORMS) {
+               err = -EINVAL;
+               goto err;
+       }
+
+       set_tvnorm(btv, i);
+
+err:
+
+       return err;
+}
+
+static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
+               *id = V4L2_STD_625_50;
+       else
+               *id = V4L2_STD_525_60;
+       return 0;
+}
+
+static int bttv_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       int rc = 0;
+
+       if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       i->type     = V4L2_INPUT_TYPE_CAMERA;
+       i->audioset = 1;
+
+       if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
+               sprintf(i->name, "Television");
+               i->type  = V4L2_INPUT_TYPE_TUNER;
+               i->tuner = 0;
+       } else if (i->index == btv->svhs) {
+               sprintf(i->name, "S-Video");
+       } else {
+               sprintf(i->name, "Composite%d", i->index);
+       }
+
+       if (i->index == btv->input) {
+               __u32 dstatus = btread(BT848_DSTATUS);
+               if (0 == (dstatus & BT848_DSTATUS_PRES))
+                       i->status |= V4L2_IN_ST_NO_SIGNAL;
+               if (0 == (dstatus & BT848_DSTATUS_HLOC))
+                       i->status |= V4L2_IN_ST_NO_H_LOCK;
+       }
+
+       i->std = BTTV_NORMS;
+
+err:
+
+       return rc;
+}
+
+static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       *i = btv->input;
+
+       return 0;
+}
+
+static int bttv_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct bttv_fh *fh  = priv;
+       struct bttv *btv = fh->btv;
+
+       int err;
+
+       err = v4l2_prio_check(&btv->prio, fh->prio);
+       if (unlikely(err))
+               goto err;
+
+       if (i > bttv_tvcards[btv->c.type].video_inputs) {
+               err = -EINVAL;
+               goto err;
+       }
+
+       set_input(btv, i, btv->tvnorm);
+
+err:
+       return 0;
+}
+
+static int bttv_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct bttv_fh *fh  = priv;
+       struct bttv *btv = fh->btv;
+       int err;
+
+       if (unlikely(0 != t->index))
+               return -EINVAL;
+
+       if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
+               err = -EINVAL;
+               goto err;
+       }
+
+       err = v4l2_prio_check(&btv->prio, fh->prio);
+       if (unlikely(err))
+               goto err;
+
+       bttv_call_all(btv, tuner, s_tuner, t);
+
+       if (btv->audio_mode_gpio)
+               btv->audio_mode_gpio(btv, t, 1);
+
+err:
+
+       return 0;
+}
+
+static int bttv_g_frequency(struct file *file, void *priv,
+                                       struct v4l2_frequency *f)
+{
+       struct bttv_fh *fh  = priv;
+       struct bttv *btv = fh->btv;
+
+       f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = btv->freq;
+
+       return 0;
+}
+
+static int bttv_s_frequency(struct file *file, void *priv,
+                                       struct v4l2_frequency *f)
+{
+       struct bttv_fh *fh  = priv;
+       struct bttv *btv = fh->btv;
+       int err;
+
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+
+       err = v4l2_prio_check(&btv->prio, fh->prio);
+       if (unlikely(err))
+               goto err;
+
+       if (unlikely(f->type != (btv->radio_user
+               ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
+               err = -EINVAL;
+               goto err;
+       }
+       btv->freq = f->frequency;
+       bttv_call_all(btv, tuner, s_frequency, f);
+       if (btv->has_matchbox && btv->radio_user)
+               tea5757_set_freq(btv, btv->freq);
+err:
+
+       return 0;
+}
+
+static int bttv_log_status(struct file *file, void *f)
+{
+       struct bttv_fh *fh  = f;
+       struct bttv *btv = fh->btv;
+
+       bttv_call_all(btv, core, log_status);
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int bttv_g_register(struct file *file, void *f,
+                                       struct v4l2_dbg_register *reg)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+
+       /* bt848 has a 12-bit register space */
+       reg->reg &= 0xfff;
+       reg->val = btread(reg->reg);
+       reg->size = 1;
+
+       return 0;
+}
+
+static int bttv_s_register(struct file *file, void *f,
+                                       struct v4l2_dbg_register *reg)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+
+       /* bt848 has a 12-bit register space */
+       reg->reg &= 0xfff;
+       btwrite(reg->val, reg->reg);
+
+       return 0;
+}
+#endif
+
+/* Given cropping boundaries b and the scaled width and height of a
+   single field or frame, which must not exceed hardware limits, this
+   function adjusts the cropping parameters c. */
+static void
+bttv_crop_adjust       (struct bttv_crop *             c,
+                        const struct v4l2_rect *       b,
+                        __s32                          width,
+                        __s32                          height,
+                        enum v4l2_field                field)
+{
+       __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
+       __s32 max_left;
+       __s32 max_top;
+
+       if (width < c->min_scaled_width) {
+               /* Max. hor. scale factor 16:1. */
+               c->rect.width = width * 16;
+       } else if (width > c->max_scaled_width) {
+               /* Min. hor. scale factor 1:1. */
+               c->rect.width = width;
+
+               max_left = b->left + b->width - width;
+               max_left = min(max_left, (__s32) MAX_HDELAY);
+               if (c->rect.left > max_left)
+                       c->rect.left = max_left;
+       }
+
+       if (height < c->min_scaled_height) {
+               /* Max. vert. scale factor 16:1, single fields 8:1. */
+               c->rect.height = height * 16;
+       } else if (frame_height > c->max_scaled_height) {
+               /* Min. vert. scale factor 1:1.
+                  Top and height count field lines times two. */
+               c->rect.height = (frame_height + 1) & ~1;
+
+               max_top = b->top + b->height - c->rect.height;
+               if (c->rect.top > max_top)
+                       c->rect.top = max_top;
+       }
+
+       bttv_crop_calc_limits(c);
+}
+
+/* Returns an error if scaling to a frame or single field with the given
+   width and height is not possible with the current cropping parameters
+   and width aligned according to width_mask. If adjust_size is TRUE the
+   function may adjust the width and/or height instead, rounding width
+   to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
+   also adjust the current cropping parameters to get closer to the
+   desired image size. */
+static int
+limit_scaled_size_lock       (struct bttv_fh *               fh,
+                        __s32 *                        width,
+                        __s32 *                        height,
+                        enum v4l2_field                field,
+                        unsigned int                   width_mask,
+                        unsigned int                   width_bias,
+                        int                            adjust_size,
+                        int                            adjust_crop)
+{
+       struct bttv *btv = fh->btv;
+       const struct v4l2_rect *b;
+       struct bttv_crop *c;
+       __s32 min_width;
+       __s32 min_height;
+       __s32 max_width;
+       __s32 max_height;
+       int rc;
+
+       BUG_ON((int) width_mask >= 0 ||
+              width_bias >= (unsigned int) -width_mask);
+
+       /* Make sure tvnorm, vbi_end and the current cropping parameters
+          remain consistent until we're done. */
+
+       b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+       /* Do crop - use current, don't - use default parameters. */
+       c = &btv->crop[!!fh->do_crop];
+
+       if (fh->do_crop
+           && adjust_size
+           && adjust_crop
+           && !locked_btres(btv, VIDEO_RESOURCES)) {
+               min_width = 48;
+               min_height = 32;
+
+               /* We cannot scale up. When the scaled image is larger
+                  than crop.rect we adjust the crop.rect as required
+                  by the V4L2 spec, hence cropcap.bounds are our limit. */
+               max_width = min(b->width, (__s32) MAX_HACTIVE);
+               max_height = b->height;
+
+               /* We cannot capture the same line as video and VBI data.
+                  Note btv->vbi_end is really a minimum, see
+                  bttv_vbi_try_fmt(). */
+               if (btv->vbi_end > b->top) {
+                       max_height -= btv->vbi_end - b->top;
+                       rc = -EBUSY;
+                       if (min_height > max_height)
+                               goto fail;
+               }
+       } else {
+               rc = -EBUSY;
+               if (btv->vbi_end > c->rect.top)
+                       goto fail;
+
+               min_width  = c->min_scaled_width;
+               min_height = c->min_scaled_height;
+               max_width  = c->max_scaled_width;
+               max_height = c->max_scaled_height;
+
+               adjust_crop = 0;
+       }
+
+       min_width = (min_width - width_mask - 1) & width_mask;
+       max_width = max_width & width_mask;
+
+       /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
+       min_height = min_height;
+       /* Min. scale factor is 1:1. */
+       max_height >>= !V4L2_FIELD_HAS_BOTH(field);
+
+       if (adjust_size) {
+               *width = clamp(*width, min_width, max_width);
+               *height = clamp(*height, min_height, max_height);
+
+               /* Round after clamping to avoid overflow. */
+               *width = (*width + width_bias) & width_mask;
+
+               if (adjust_crop) {
+                       bttv_crop_adjust(c, b, *width, *height, field);
+
+                       if (btv->vbi_end > c->rect.top) {
+                               /* Move the crop window out of the way. */
+                               c->rect.top = btv->vbi_end;
+                       }
+               }
+       } else {
+               rc = -EINVAL;
+               if (*width  < min_width ||
+                   *height < min_height ||
+                   *width  > max_width ||
+                   *height > max_height ||
+                   0 != (*width & ~width_mask))
+                       goto fail;
+       }
+
+       rc = 0; /* success */
+
+ fail:
+
+       return rc;
+}
+
+/* Returns an error if the given overlay window dimensions are not
+   possible with the current cropping parameters. If adjust_size is
+   TRUE the function may adjust the window width and/or height
+   instead, however it always rounds the horizontal position and
+   width as btcx_align() does. If adjust_crop is TRUE the function
+   may also adjust the current cropping parameters to get closer
+   to the desired window size. */
+static int
+verify_window_lock             (struct bttv_fh *               fh,
+                        struct v4l2_window *           win,
+                        int                            adjust_size,
+                        int                            adjust_crop)
+{
+       enum v4l2_field field;
+       unsigned int width_mask;
+       int rc;
+
+       if (win->w.width  < 48 || win->w.height < 32)
+               return -EINVAL;
+       if (win->clipcount > 2048)
+               return -EINVAL;
+
+       field = win->field;
+
+       if (V4L2_FIELD_ANY == field) {
+               __s32 height2;
+
+               height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
+               field = (win->w.height > height2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_TOP;
+       }
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* 4-byte alignment. */
+       if (NULL == fh->ovfmt)
+               return -EINVAL;
+       width_mask = ~0;
+       switch (fh->ovfmt->depth) {
+       case 8:
+       case 24:
+               width_mask = ~3;
+               break;
+       case 16:
+               width_mask = ~1;
+               break;
+       case 32:
+               break;
+       default:
+               BUG();
+       }
+
+       win->w.width -= win->w.left & ~width_mask;
+       win->w.left = (win->w.left - width_mask - 1) & width_mask;
+
+       rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
+                              field, width_mask,
+                              /* width_bias: round down */ 0,
+                              adjust_size, adjust_crop);
+       if (0 != rc)
+               return rc;
+
+       win->field = field;
+       return 0;
+}
+
+static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
+                       struct v4l2_window *win, int fixup)
+{
+       struct v4l2_clip *clips = NULL;
+       int n,size,retval = 0;
+
+       if (NULL == fh->ovfmt)
+               return -EINVAL;
+       if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
+               return -EINVAL;
+       retval = verify_window_lock(fh, win,
+                              /* adjust_size */ fixup,
+                              /* adjust_crop */ fixup);
+       if (0 != retval)
+               return retval;
+
+       /* copy clips  --  luckily v4l1 + v4l2 are binary
+          compatible here ...*/
+       n = win->clipcount;
+       size = sizeof(*clips)*(n+4);
+       clips = kmalloc(size,GFP_KERNEL);
+       if (NULL == clips)
+               return -ENOMEM;
+       if (n > 0) {
+               if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
+                       kfree(clips);
+                       return -EFAULT;
+               }
+       }
+
+       /* clip against screen */
+       if (NULL != btv->fbuf.base)
+               n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
+                                     &win->w, clips, n);
+       btcx_sort_clips(clips,n);
+
+       /* 4-byte alignments */
+       switch (fh->ovfmt->depth) {
+       case 8:
+       case 24:
+               btcx_align(&win->w, clips, n, 3);
+               break;
+       case 16:
+               btcx_align(&win->w, clips, n, 1);
+               break;
+       case 32:
+               /* no alignment fixups needed */
+               break;
+       default:
+               BUG();
+       }
+
+       kfree(fh->ov.clips);
+       fh->ov.clips    = clips;
+       fh->ov.nclips   = n;
+
+       fh->ov.w        = win->w;
+       fh->ov.field    = win->field;
+       fh->ov.setup_ok = 1;
+
+       btv->init.ov.w.width   = win->w.width;
+       btv->init.ov.w.height  = win->w.height;
+       btv->init.ov.field     = win->field;
+
+       /* update overlay if needed */
+       retval = 0;
+       if (check_btres(fh, RESOURCE_OVERLAY)) {
+               struct bttv_buffer *new;
+
+               new = videobuf_sg_alloc(sizeof(*new));
+               new->crop = btv->crop[!!fh->do_crop].rect;
+               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+               retval = bttv_switch_overlay(btv,fh,new);
+       }
+       return retval;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
+{
+       struct videobuf_queue* q = NULL;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               q = &fh->cap;
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               q = &fh->vbi;
+               break;
+       default:
+               BUG();
+       }
+       return q;
+}
+
+static int bttv_resource(struct bttv_fh *fh)
+{
+       int res = 0;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               res = RESOURCE_VIDEO_STREAM;
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               res = RESOURCE_VBI;
+               break;
+       default:
+               BUG();
+       }
+       return res;
+}
+
+static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
+{
+       struct videobuf_queue *q = bttv_queue(fh);
+       int res = bttv_resource(fh);
+
+       if (check_btres(fh,res))
+               return -EBUSY;
+       if (videobuf_queue_is_busy(q))
+               return -EBUSY;
+       fh->type = type;
+       return 0;
+}
+
+static void
+pix_format_set_size     (struct v4l2_pix_format *       f,
+                        const struct bttv_format *     fmt,
+                        unsigned int                   width,
+                        unsigned int                   height)
+{
+       f->width = width;
+       f->height = height;
+
+       if (fmt->flags & FORMAT_FLAGS_PLANAR) {
+               f->bytesperline = width; /* Y plane */
+               f->sizeimage = (width * height * fmt->depth) >> 3;
+       } else {
+               f->bytesperline = (width * fmt->depth) >> 3;
+               f->sizeimage = height * f->bytesperline;
+       }
+}
+
+static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct bttv_fh *fh  = priv;
+
+       pix_format_set_size(&f->fmt.pix, fh->fmt,
+                               fh->width, fh->height);
+       f->fmt.pix.field        = fh->cap.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+
+       return 0;
+}
+
+static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct bttv_fh *fh  = priv;
+
+       f->fmt.win.w     = fh->ov.w;
+       f->fmt.win.field = fh->ov.field;
+
+       return 0;
+}
+
+static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       const struct bttv_format *fmt;
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       enum v4l2_field field;
+       __s32 width, height;
+       int rc;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+
+       if (V4L2_FIELD_ANY == field) {
+               __s32 height2;
+
+               height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+               field = (f->fmt.pix.height > height2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       }
+
+       if (V4L2_FIELD_SEQ_BT == field)
+               field = V4L2_FIELD_SEQ_TB;
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+       case V4L2_FIELD_ALTERNATE:
+       case V4L2_FIELD_INTERLACED:
+               break;
+       case V4L2_FIELD_SEQ_TB:
+               if (fmt->flags & FORMAT_FLAGS_PLANAR)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       width = f->fmt.pix.width;
+       height = f->fmt.pix.height;
+
+       rc = limit_scaled_size_lock(fh, &width, &height, field,
+                              /* width_mask: 4 pixels */ ~3,
+                              /* width_bias: nearest */ 2,
+                              /* adjust_size */ 1,
+                              /* adjust_crop */ 0);
+       if (0 != rc)
+               return rc;
+
+       /* update data for the application */
+       f->fmt.pix.field = field;
+       pix_format_set_size(&f->fmt.pix, fmt, width, height);
+
+       return 0;
+}
+
+static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct bttv_fh *fh = priv;
+
+       return verify_window_lock(fh, &f->fmt.win,
+                       /* adjust_size */ 1,
+                       /* adjust_crop */ 0);
+}
+
+static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int retval;
+       const struct bttv_format *fmt;
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       __s32 width, height;
+       enum v4l2_field field;
+
+       retval = bttv_switch_type(fh, f->type);
+       if (0 != retval)
+               return retval;
+
+       retval = bttv_try_fmt_vid_cap(file, priv, f);
+       if (0 != retval)
+               return retval;
+
+       width = f->fmt.pix.width;
+       height = f->fmt.pix.height;
+       field = f->fmt.pix.field;
+
+       retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
+                              /* width_mask: 4 pixels */ ~3,
+                              /* width_bias: nearest */ 2,
+                              /* adjust_size */ 1,
+                              /* adjust_crop */ 1);
+       if (0 != retval)
+               return retval;
+
+       f->fmt.pix.field = field;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+
+       /* update our state informations */
+       fh->fmt              = fmt;
+       fh->cap.field        = f->fmt.pix.field;
+       fh->cap.last         = V4L2_FIELD_NONE;
+       fh->width            = f->fmt.pix.width;
+       fh->height           = f->fmt.pix.height;
+       btv->init.fmt        = fmt;
+       btv->init.width      = f->fmt.pix.width;
+       btv->init.height     = f->fmt.pix.height;
+
+       return 0;
+}
+
+static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (no_overlay > 0) {
+               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+
+       return setup_window_lock(fh, btv, &f->fmt.win, 1);
+}
+
+static int bttv_querycap(struct file *file, void  *priv,
+                               struct v4l2_capability *cap)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (0 == v4l2)
+               return -EINVAL;
+
+       strlcpy(cap->driver, "bttv", sizeof(cap->driver));
+       strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "PCI:%s", pci_name(btv->c.pci));
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_VBI_CAPTURE |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING;
+       if (no_overlay <= 0)
+               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
+       /*
+        * No need to lock here: those vars are initialized during board
+        * probe and remains untouched during the rest of the driver lifecycle
+        */
+       if (btv->has_saa6588)
+               cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
+       if (btv->tuner_type != TUNER_ABSENT)
+               cap->capabilities |= V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
+{
+       int index = -1, i;
+
+       for (i = 0; i < FORMATS; i++) {
+               if (formats[i].fourcc != -1)
+                       index++;
+               if ((unsigned int)index == f->index)
+                       break;
+       }
+       if (FORMATS == i)
+               return -EINVAL;
+
+       f->pixelformat = formats[i].fourcc;
+       strlcpy(f->description, formats[i].name, sizeof(f->description));
+
+       return i;
+}
+
+static int bttv_enum_fmt_vid_cap(struct file *file, void  *priv,
+                               struct v4l2_fmtdesc *f)
+{
+       int rc = bttv_enum_fmt_cap_ovr(f);
+
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int bttv_enum_fmt_vid_overlay(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       int rc;
+
+       if (no_overlay > 0) {
+               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+
+       rc = bttv_enum_fmt_cap_ovr(f);
+
+       if (rc < 0)
+               return rc;
+
+       if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int bttv_g_fbuf(struct file *file, void *f,
+                               struct v4l2_framebuffer *fb)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       *fb = btv->fbuf;
+       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+       if (fh->ovfmt)
+               fb->fmt.pixelformat  = fh->ovfmt->fourcc;
+       return 0;
+}
+
+static int bttv_overlay(struct file *file, void *f, unsigned int on)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       struct bttv_buffer *new;
+       int retval = 0;
+
+       if (on) {
+               /* verify args */
+               if (unlikely(!btv->fbuf.base)) {
+                       return -EINVAL;
+               }
+               if (unlikely(!fh->ov.setup_ok)) {
+                       dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
+                       retval = -EINVAL;
+               }
+               if (retval)
+                       return retval;
+       }
+
+       if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
+               return -EBUSY;
+
+       if (on) {
+               fh->ov.tvnorm = btv->tvnorm;
+               new = videobuf_sg_alloc(sizeof(*new));
+               new->crop = btv->crop[!!fh->do_crop].rect;
+               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+       } else {
+               new = NULL;
+       }
+
+       /* switch over */
+       retval = bttv_switch_overlay(btv, fh, new);
+       return retval;
+}
+
+static int bttv_s_fbuf(struct file *file, void *f,
+                               struct v4l2_framebuffer *fb)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       const struct bttv_format *fmt;
+       int retval;
+
+       if (!capable(CAP_SYS_ADMIN) &&
+               !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       /* check args */
+       fmt = format_by_fourcc(fb->fmt.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+       if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
+               return -EINVAL;
+
+       retval = -EINVAL;
+       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+               __s32 width = fb->fmt.width;
+               __s32 height = fb->fmt.height;
+
+               retval = limit_scaled_size_lock(fh, &width, &height,
+                                          V4L2_FIELD_INTERLACED,
+                                          /* width_mask */ ~3,
+                                          /* width_bias */ 2,
+                                          /* adjust_size */ 0,
+                                          /* adjust_crop */ 0);
+               if (0 != retval)
+                       return retval;
+       }
+
+       /* ok, accept it */
+       btv->fbuf.base       = fb->base;
+       btv->fbuf.fmt.width  = fb->fmt.width;
+       btv->fbuf.fmt.height = fb->fmt.height;
+       if (0 != fb->fmt.bytesperline)
+               btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
+       else
+               btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
+
+       retval = 0;
+       fh->ovfmt = fmt;
+       btv->init.ovfmt = fmt;
+       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+               fh->ov.w.left   = 0;
+               fh->ov.w.top    = 0;
+               fh->ov.w.width  = fb->fmt.width;
+               fh->ov.w.height = fb->fmt.height;
+               btv->init.ov.w.width  = fb->fmt.width;
+               btv->init.ov.w.height = fb->fmt.height;
+                       kfree(fh->ov.clips);
+               fh->ov.clips = NULL;
+               fh->ov.nclips = 0;
+
+               if (check_btres(fh, RESOURCE_OVERLAY)) {
+                       struct bttv_buffer *new;
+
+                       new = videobuf_sg_alloc(sizeof(*new));
+                       new->crop = btv->crop[!!fh->do_crop].rect;
+                       bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+                       retval = bttv_switch_overlay(btv, fh, new);
+               }
+       }
+       return retval;
+}
+
+static int bttv_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *p)
+{
+       struct bttv_fh *fh = priv;
+       return videobuf_reqbufs(bttv_queue(fh), p);
+}
+
+static int bttv_querybuf(struct file *file, void *priv,
+                               struct v4l2_buffer *b)
+{
+       struct bttv_fh *fh = priv;
+       return videobuf_querybuf(bttv_queue(fh), b);
+}
+
+static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       int res = bttv_resource(fh);
+
+       if (!check_alloc_btres_lock(btv, fh, res))
+               return -EBUSY;
+
+       return videobuf_qbuf(bttv_queue(fh), b);
+}
+
+static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct bttv_fh *fh = priv;
+       return videobuf_dqbuf(bttv_queue(fh), b,
+                       file->f_flags & O_NONBLOCK);
+}
+
+static int bttv_streamon(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       int res = bttv_resource(fh);
+
+       if (!check_alloc_btres_lock(btv, fh, res))
+               return -EBUSY;
+       return videobuf_streamon(bttv_queue(fh));
+}
+
+
+static int bttv_streamoff(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       int retval;
+       int res = bttv_resource(fh);
+
+
+       retval = videobuf_streamoff(bttv_queue(fh));
+       if (retval < 0)
+               return retval;
+       free_btres_lock(btv, fh, res);
+       return 0;
+}
+
+static int bttv_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+       const struct v4l2_queryctrl *ctrl;
+
+       if ((c->id <  V4L2_CID_BASE ||
+            c->id >= V4L2_CID_LASTP1) &&
+           (c->id <  V4L2_CID_PRIVATE_BASE ||
+            c->id >= V4L2_CID_PRIVATE_LASTP1))
+               return -EINVAL;
+
+       if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
+               *c = no_ctl;
+       else {
+               ctrl = ctrl_by_id(c->id);
+
+               *c = (NULL != ctrl) ? *ctrl : no_ctl;
+       }
+
+       return 0;
+}
+
+static int bttv_g_parm(struct file *file, void *f,
+                               struct v4l2_streamparm *parm)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
+                                   &parm->parm.capture.timeperframe);
+
+       return 0;
+}
+
+static int bttv_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (btv->tuner_type == TUNER_ABSENT)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       t->rxsubchans = V4L2_TUNER_SUB_MONO;
+       bttv_call_all(btv, tuner, g_tuner, t);
+       strcpy(t->name, "Television");
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->type       = V4L2_TUNER_ANALOG_TV;
+       if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
+               t->signal = 0xffff;
+
+       if (btv->audio_mode_gpio)
+               btv->audio_mode_gpio(btv, t, 0);
+
+       return 0;
+}
+
+static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       *p = v4l2_prio_max(&btv->prio);
+
+       return 0;
+}
+
+static int bttv_s_priority(struct file *file, void *f,
+                                       enum v4l2_priority prio)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       int     rc;
+
+       rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
+
+       return rc;
+}
+
+static int bttv_cropcap(struct file *file, void *priv,
+                               struct v4l2_cropcap *cap)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+
+       *cap = bttv_tvnorms[btv->tvnorm].cropcap;
+
+       return 0;
+}
+
+static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+
+       /* No fh->do_crop = 1; because btv->crop[1] may be
+          inconsistent with fh->width or fh->height and apps
+          do not expect a change here. */
+
+       crop->c = btv->crop[!!fh->do_crop].rect;
+
+       return 0;
+}
+
+static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       const struct v4l2_rect *b;
+       int retval;
+       struct bttv_crop c;
+       __s32 b_left;
+       __s32 b_top;
+       __s32 b_right;
+       __s32 b_bottom;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+
+       /* Make sure tvnorm, vbi_end and the current cropping
+          parameters remain consistent until we're done. Note
+          read() may change vbi_end in check_alloc_btres_lock(). */
+       retval = v4l2_prio_check(&btv->prio, fh->prio);
+       if (0 != retval) {
+               return retval;
+       }
+
+       retval = -EBUSY;
+
+       if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
+               return retval;
+       }
+
+       b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+       b_left = b->left;
+       b_right = b_left + b->width;
+       b_bottom = b->top + b->height;
+
+       b_top = max(b->top, btv->vbi_end);
+       if (b_top + 32 >= b_bottom) {
+               return retval;
+       }
+
+       /* Min. scaled size 48 x 32. */
+       c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+       c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+
+       c.rect.width = clamp(crop->c.width,
+                            48, b_right - c.rect.left);
+
+       c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+       /* Top and height must be a multiple of two. */
+       c.rect.top = (c.rect.top + 1) & ~1;
+
+       c.rect.height = clamp(crop->c.height,
+                             32, b_bottom - c.rect.top);
+       c.rect.height = (c.rect.height + 1) & ~1;
+
+       bttv_crop_calc_limits(&c);
+
+       btv->crop[1] = c;
+
+       fh->do_crop = 1;
+
+       if (fh->width < c.min_scaled_width) {
+               fh->width = c.min_scaled_width;
+               btv->init.width = c.min_scaled_width;
+       } else if (fh->width > c.max_scaled_width) {
+               fh->width = c.max_scaled_width;
+               btv->init.width = c.max_scaled_width;
+       }
+
+       if (fh->height < c.min_scaled_height) {
+               fh->height = c.min_scaled_height;
+               btv->init.height = c.min_scaled_height;
+       } else if (fh->height > c.max_scaled_height) {
+               fh->height = c.max_scaled_height;
+               btv->init.height = c.max_scaled_height;
+       }
+
+       return 0;
+}
+
+static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       strcpy(a->name, "audio");
+       return 0;
+}
+
+static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       return 0;
+}
+
+static ssize_t bttv_read(struct file *file, char __user *data,
+                        size_t count, loff_t *ppos)
+{
+       struct bttv_fh *fh = file->private_data;
+       int retval = 0;
+
+       if (fh->btv->errors)
+               bttv_reinit_bt848(fh->btv);
+       dprintk("%d: read count=%d type=%s\n",
+               fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
+                       /* VIDEO_READ in use by another fh,
+                          or VIDEO_STREAM by any fh. */
+                       return -EBUSY;
+               }
+               retval = videobuf_read_one(&fh->cap, data, count, ppos,
+                                          file->f_flags & O_NONBLOCK);
+               free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
+                       return -EBUSY;
+               retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
+                                             file->f_flags & O_NONBLOCK);
+               break;
+       default:
+               BUG();
+       }
+       return retval;
+}
+
+static unsigned int bttv_poll(struct file *file, poll_table *wait)
+{
+       struct bttv_fh *fh = file->private_data;
+       struct bttv_buffer *buf;
+       enum v4l2_field field;
+       unsigned int rc = POLLERR;
+
+       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+               if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
+                       return POLLERR;
+               return videobuf_poll_stream(file, &fh->vbi, wait);
+       }
+
+       if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
+               /* streaming capture */
+               if (list_empty(&fh->cap.stream))
+                       goto err;
+               buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
+       } else {
+               /* read() capture */
+               if (NULL == fh->cap.read_buf) {
+                       /* need to capture a new frame */
+                       if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
+                               goto err;
+                       fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
+                       if (NULL == fh->cap.read_buf)
+                               goto err;
+                       fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
+                       field = videobuf_next_field(&fh->cap);
+                       if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
+                               kfree (fh->cap.read_buf);
+                               fh->cap.read_buf = NULL;
+                               goto err;
+                       }
+                       fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
+                       fh->cap.read_off = 0;
+               }
+               buf = (struct bttv_buffer*)fh->cap.read_buf;
+       }
+
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               rc =  POLLIN|POLLRDNORM;
+       else
+               rc = 0;
+err:
+       return rc;
+}
+
+static int bttv_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct bttv *btv = video_drvdata(file);
+       struct bttv_fh *fh;
+       enum v4l2_buf_type type = 0;
+
+       dprintk("open dev=%s\n", video_device_node_name(vdev));
+
+       if (vdev->vfl_type == VFL_TYPE_GRABBER) {
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       } else if (vdev->vfl_type == VFL_TYPE_VBI) {
+               type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       } else {
+               WARN_ON(1);
+               return -ENODEV;
+       }
+
+       dprintk("%d: open called (type=%s)\n",
+               btv->c.nr, v4l2_type_names[type]);
+
+       /* allocate per filehandle data */
+       fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+       if (unlikely(!fh))
+               return -ENOMEM;
+       file->private_data = fh;
+
+       *fh = btv->init;
+
+       fh->type = type;
+       fh->ov.setup_ok = 0;
+
+       v4l2_prio_open(&btv->prio, &fh->prio);
+
+       videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                           V4L2_FIELD_INTERLACED,
+                           sizeof(struct bttv_buffer),
+                           fh, &btv->lock);
+       videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
+                           &btv->c.pci->dev, &btv->s_lock,
+                           V4L2_BUF_TYPE_VBI_CAPTURE,
+                           V4L2_FIELD_SEQ_TB,
+                           sizeof(struct bttv_buffer),
+                           fh, &btv->lock);
+       set_tvnorm(btv,btv->tvnorm);
+       set_input(btv, btv->input, btv->tvnorm);
+
+       btv->users++;
+
+       /* The V4L2 spec requires one global set of cropping parameters
+          which only change on request. These are stored in btv->crop[1].
+          However for compatibility with V4L apps and cropping unaware
+          V4L2 apps we now reset the cropping parameters as seen through
+          this fh, which is to say VIDIOC_G_CROP and scaling limit checks
+          will use btv->crop[0], the default cropping parameters for the
+          current video standard, and VIDIOC_S_FMT will not implicitely
+          change the cropping parameters until VIDIOC_S_CROP has been
+          called. */
+       fh->do_crop = !reset_crop; /* module parameter */
+
+       /* Likewise there should be one global set of VBI capture
+          parameters, but for compatibility with V4L apps and earlier
+          driver versions each fh has its own parameters. */
+       bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
+
+       bttv_field_count(btv);
+       return 0;
+}
+
+static int bttv_release(struct file *file)
+{
+       struct bttv_fh *fh = file->private_data;
+       struct bttv *btv = fh->btv;
+
+       /* turn off overlay */
+       if (check_btres(fh, RESOURCE_OVERLAY))
+               bttv_switch_overlay(btv,fh,NULL);
+
+       /* stop video capture */
+       if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
+               videobuf_streamoff(&fh->cap);
+               free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
+       }
+       if (fh->cap.read_buf) {
+               buffer_release(&fh->cap,fh->cap.read_buf);
+               kfree(fh->cap.read_buf);
+       }
+       if (check_btres(fh, RESOURCE_VIDEO_READ)) {
+               free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
+       }
+
+       /* stop vbi capture */
+       if (check_btres(fh, RESOURCE_VBI)) {
+               videobuf_stop(&fh->vbi);
+               free_btres_lock(btv,fh,RESOURCE_VBI);
+       }
+
+       /* free stuff */
+
+       videobuf_mmap_free(&fh->cap);
+       videobuf_mmap_free(&fh->vbi);
+       v4l2_prio_close(&btv->prio, fh->prio);
+       file->private_data = NULL;
+       kfree(fh);
+
+       btv->users--;
+       bttv_field_count(btv);
+
+       if (!btv->users)
+               audio_mute(btv, 1);
+
+       return 0;
+}
+
+static int
+bttv_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct bttv_fh *fh = file->private_data;
+
+       dprintk("%d: mmap type=%s 0x%lx+%ld\n",
+               fh->btv->c.nr, v4l2_type_names[fh->type],
+               vma->vm_start, vma->vm_end - vma->vm_start);
+       return videobuf_mmap_mapper(bttv_queue(fh),vma);
+}
+
+static const struct v4l2_file_operations bttv_fops =
+{
+       .owner            = THIS_MODULE,
+       .open             = bttv_open,
+       .release          = bttv_release,
+       .unlocked_ioctl   = video_ioctl2,
+       .read             = bttv_read,
+       .mmap             = bttv_mmap,
+       .poll             = bttv_poll,
+};
+
+static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
+       .vidioc_querycap                = bttv_querycap,
+       .vidioc_enum_fmt_vid_cap        = bttv_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap         = bttv_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap           = bttv_s_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_overlay    = bttv_enum_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_overlay       = bttv_g_fmt_vid_overlay,
+       .vidioc_try_fmt_vid_overlay     = bttv_try_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_overlay       = bttv_s_fmt_vid_overlay,
+       .vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
+       .vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
+       .vidioc_g_audio                 = bttv_g_audio,
+       .vidioc_s_audio                 = bttv_s_audio,
+       .vidioc_cropcap                 = bttv_cropcap,
+       .vidioc_reqbufs                 = bttv_reqbufs,
+       .vidioc_querybuf                = bttv_querybuf,
+       .vidioc_qbuf                    = bttv_qbuf,
+       .vidioc_dqbuf                   = bttv_dqbuf,
+       .vidioc_s_std                   = bttv_s_std,
+       .vidioc_enum_input              = bttv_enum_input,
+       .vidioc_g_input                 = bttv_g_input,
+       .vidioc_s_input                 = bttv_s_input,
+       .vidioc_queryctrl               = bttv_queryctrl,
+       .vidioc_g_ctrl                  = bttv_g_ctrl,
+       .vidioc_s_ctrl                  = bttv_s_ctrl,
+       .vidioc_streamon                = bttv_streamon,
+       .vidioc_streamoff               = bttv_streamoff,
+       .vidioc_g_tuner                 = bttv_g_tuner,
+       .vidioc_s_tuner                 = bttv_s_tuner,
+       .vidioc_g_crop                  = bttv_g_crop,
+       .vidioc_s_crop                  = bttv_s_crop,
+       .vidioc_g_fbuf                  = bttv_g_fbuf,
+       .vidioc_s_fbuf                  = bttv_s_fbuf,
+       .vidioc_overlay                 = bttv_overlay,
+       .vidioc_g_priority              = bttv_g_priority,
+       .vidioc_s_priority              = bttv_s_priority,
+       .vidioc_g_parm                  = bttv_g_parm,
+       .vidioc_g_frequency             = bttv_g_frequency,
+       .vidioc_s_frequency             = bttv_s_frequency,
+       .vidioc_log_status              = bttv_log_status,
+       .vidioc_querystd                = bttv_querystd,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register              = bttv_g_register,
+       .vidioc_s_register              = bttv_s_register,
+#endif
+};
+
+static struct video_device bttv_video_template = {
+       .fops         = &bttv_fops,
+       .ioctl_ops    = &bttv_ioctl_ops,
+       .tvnorms      = BTTV_NORMS,
+       .current_norm = V4L2_STD_PAL,
+};
+
+/* ----------------------------------------------------------------------- */
+/* radio interface                                                         */
+
+static int radio_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct bttv *btv = video_drvdata(file);
+       struct bttv_fh *fh;
+
+       dprintk("open dev=%s\n", video_device_node_name(vdev));
+
+       dprintk("%d: open called (radio)\n", btv->c.nr);
+
+       /* allocate per filehandle data */
+       fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+       if (unlikely(!fh))
+               return -ENOMEM;
+       file->private_data = fh;
+       *fh = btv->init;
+
+       v4l2_prio_open(&btv->prio, &fh->prio);
+
+       btv->radio_user++;
+
+       bttv_call_all(btv, tuner, s_radio);
+       audio_input(btv,TVAUDIO_INPUT_RADIO);
+
+       return 0;
+}
+
+static int radio_release(struct file *file)
+{
+       struct bttv_fh *fh = file->private_data;
+       struct bttv *btv = fh->btv;
+       struct saa6588_command cmd;
+
+       v4l2_prio_close(&btv->prio, fh->prio);
+       file->private_data = NULL;
+       kfree(fh);
+
+       btv->radio_user--;
+
+       bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+
+       return 0;
+}
+
+static int radio_querycap(struct file *file, void *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       strcpy(cap->driver, "bttv");
+       strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
+       cap->capabilities = V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (btv->tuner_type == TUNER_ABSENT)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+
+       bttv_call_all(btv, tuner, g_tuner, t);
+
+       if (btv->audio_mode_gpio)
+               btv->audio_mode_gpio(btv, t, 0);
+
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       strcpy(a->name, "Radio");
+
+       return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct bttv_fh *fh = priv;
+       struct bttv *btv = fh->btv;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       bttv_call_all(btv, tuner, s_tuner, t);
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (unlikely(i))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       const struct v4l2_queryctrl *ctrl;
+
+       if (c->id <  V4L2_CID_BASE ||
+                       c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               ctrl = ctrl_by_id(c->id);
+               *c = *ctrl;
+       } else
+               *c = no_ctl;
+
+       return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static ssize_t radio_read(struct file *file, char __user *data,
+                        size_t count, loff_t *ppos)
+{
+       struct bttv_fh *fh = file->private_data;
+       struct bttv *btv = fh->btv;
+       struct saa6588_command cmd;
+       cmd.block_count = count/3;
+       cmd.buffer = data;
+       cmd.instance = file;
+       cmd.result = -ENODEV;
+
+       bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
+
+       return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+       struct bttv_fh *fh = file->private_data;
+       struct bttv *btv = fh->btv;
+       struct saa6588_command cmd;
+       cmd.instance = file;
+       cmd.event_list = wait;
+       cmd.result = -ENODEV;
+       bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
+
+       return cmd.result;
+}
+
+static const struct v4l2_file_operations radio_fops =
+{
+       .owner    = THIS_MODULE,
+       .open     = radio_open,
+       .read     = radio_read,
+       .release  = radio_release,
+       .unlocked_ioctl = video_ioctl2,
+       .poll     = radio_poll,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap        = radio_querycap,
+       .vidioc_g_tuner         = radio_g_tuner,
+       .vidioc_enum_input      = radio_enum_input,
+       .vidioc_g_audio         = radio_g_audio,
+       .vidioc_s_tuner         = radio_s_tuner,
+       .vidioc_s_audio         = radio_s_audio,
+       .vidioc_s_input         = radio_s_input,
+       .vidioc_s_std           = radio_s_std,
+       .vidioc_queryctrl       = radio_queryctrl,
+       .vidioc_g_input         = radio_g_input,
+       .vidioc_g_ctrl          = bttv_g_ctrl,
+       .vidioc_s_ctrl          = bttv_s_ctrl,
+       .vidioc_g_frequency     = bttv_g_frequency,
+       .vidioc_s_frequency     = bttv_s_frequency,
+};
+
+static struct video_device radio_template = {
+       .fops      = &radio_fops,
+       .ioctl_ops = &radio_ioctl_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+/* some debug code                                                         */
+
+static int bttv_risc_decode(u32 risc)
+{
+       static char *instr[16] = {
+               [ BT848_RISC_WRITE     >> 28 ] = "write",
+               [ BT848_RISC_SKIP      >> 28 ] = "skip",
+               [ BT848_RISC_WRITEC    >> 28 ] = "writec",
+               [ BT848_RISC_JUMP      >> 28 ] = "jump",
+               [ BT848_RISC_SYNC      >> 28 ] = "sync",
+               [ BT848_RISC_WRITE123  >> 28 ] = "write123",
+               [ BT848_RISC_SKIP123   >> 28 ] = "skip123",
+               [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
+       };
+       static int incr[16] = {
+               [ BT848_RISC_WRITE     >> 28 ] = 2,
+               [ BT848_RISC_JUMP      >> 28 ] = 2,
+               [ BT848_RISC_SYNC      >> 28 ] = 2,
+               [ BT848_RISC_WRITE123  >> 28 ] = 5,
+               [ BT848_RISC_SKIP123   >> 28 ] = 2,
+               [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
+       };
+       static char *bits[] = {
+               "be0",  "be1",  "be2",  "be3/resync",
+               "set0", "set1", "set2", "set3",
+               "clr0", "clr1", "clr2", "clr3",
+               "irq",  "res",  "eol",  "sol",
+       };
+       int i;
+
+       pr_cont("0x%08x [ %s", risc,
+              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+       for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+               if (risc & (1 << (i + 12)))
+                       pr_cont(" %s", bits[i]);
+       pr_cont(" count=%d ]\n", risc & 0xfff);
+       return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static void bttv_risc_disasm(struct bttv *btv,
+                            struct btcx_riscmem *risc)
+{
+       unsigned int i,j,n;
+
+       pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+               btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+       for (i = 0; i < (risc->size >> 2); i += n) {
+               pr_info("%s:   0x%lx: ",
+                       btv->c.v4l2_dev.name,
+                       (unsigned long)(risc->dma + (i<<2)));
+               n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
+               for (j = 1; j < n; j++)
+                       pr_info("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
+                               btv->c.v4l2_dev.name,
+                               (unsigned long)(risc->dma + ((i+j)<<2)),
+                               risc->cpu[i+j], j);
+               if (0 == risc->cpu[i])
+                       break;
+       }
+}
+
+static void bttv_print_riscaddr(struct bttv *btv)
+{
+       pr_info("  main: %08llx\n", (unsigned long long)btv->main.dma);
+       pr_info("  vbi : o=%08llx e=%08llx\n",
+               btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+               btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+       pr_info("  cap : o=%08llx e=%08llx\n",
+               btv->curr.top
+               ? (unsigned long long)btv->curr.top->top.dma : 0,
+               btv->curr.bottom
+               ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+       pr_info("  scr : o=%08llx e=%08llx\n",
+               btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+               btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+       bttv_risc_disasm(btv, &btv->main);
+}
+
+/* ----------------------------------------------------------------------- */
+/* irq handler                                                             */
+
+static char *irq_name[] = {
+       "FMTCHG",  // format change detected (525 vs. 625)
+       "VSYNC",   // vertical sync (new field)
+       "HSYNC",   // horizontal sync
+       "OFLOW",   // chroma/luma AGC overflow
+       "HLOCK",   // horizontal lock changed
+       "VPRES",   // video presence changed
+       "6", "7",
+       "I2CDONE", // hw irc operation finished
+       "GPINT",   // gpio port triggered irq
+       "10",
+       "RISCI",   // risc instruction triggered irq
+       "FBUS",    // pixel data fifo dropped data (high pci bus latencies)
+       "FTRGT",   // pixel data fifo overrun
+       "FDSR",    // fifo data stream resyncronisation
+       "PPERR",   // parity error (data transfer)
+       "RIPERR",  // parity error (read risc instructions)
+       "PABORT",  // pci abort
+       "OCERR",   // risc instruction error
+       "SCERR",   // syncronisation error
+};
+
+static void bttv_print_irqbits(u32 print, u32 mark)
+{
+       unsigned int i;
+
+       pr_cont("bits:");
+       for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
+               if (print & (1 << i))
+                       pr_cont(" %s", irq_name[i]);
+               if (mark & (1 << i))
+                       pr_cont("*");
+       }
+}
+
+static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
+{
+       pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+               btv->c.nr,
+               (unsigned long)btv->main.dma,
+               (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+               (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+               (unsigned long)rc);
+
+       if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
+               pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+                         "Ok, then this is harmless, don't worry ;)\n",
+                         btv->c.nr);
+               return;
+       }
+       pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+                 btv->c.nr);
+       pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+                 btv->c.nr);
+       dump_stack();
+}
+
+static int
+bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
+{
+       struct bttv_buffer *item;
+
+       memset(set,0,sizeof(*set));
+
+       /* capture request ? */
+       if (!list_empty(&btv->capture)) {
+               set->frame_irq = 1;
+               item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+               if (V4L2_FIELD_HAS_TOP(item->vb.field))
+                       set->top    = item;
+               if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
+                       set->bottom = item;
+
+               /* capture request for other field ? */
+               if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
+                   (item->vb.queue.next != &btv->capture)) {
+                       item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
+                       /* Mike Isely <isely@pobox.com> - Only check
+                        * and set up the bottom field in the logic
+                        * below.  Don't ever do the top field.  This
+                        * of course means that if we set up the
+                        * bottom field in the above code that we'll
+                        * actually skip a field.  But that's OK.
+                        * Having processed only a single buffer this
+                        * time, then the next time around the first
+                        * available buffer should be for a top field.
+                        * That will then cause us here to set up a
+                        * top then a bottom field in the normal way.
+                        * The alternative to this understanding is
+                        * that we set up the second available buffer
+                        * as a top field, but that's out of order
+                        * since this driver always processes the top
+                        * field first - the effect will be the two
+                        * buffers being returned in the wrong order,
+                        * with the second buffer also being delayed
+                        * by one field time (owing to the fifo nature
+                        * of videobuf).  Worse still, we'll be stuck
+                        * doing fields out of order now every time
+                        * until something else causes a field to be
+                        * dropped.  By effectively forcing a field to
+                        * drop this way then we always get back into
+                        * sync within a single frame time.  (Out of
+                        * order fields can screw up deinterlacing
+                        * algorithms.) */
+                       if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
+                               if (NULL == set->bottom &&
+                                   V4L2_FIELD_BOTTOM == item->vb.field) {
+                                       set->bottom = item;
+                               }
+                               if (NULL != set->top  &&  NULL != set->bottom)
+                                       set->top_irq = 2;
+                       }
+               }
+       }
+
+       /* screen overlay ? */
+       if (NULL != btv->screen) {
+               if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
+                       if (NULL == set->top && NULL == set->bottom) {
+                               set->top    = btv->screen;
+                               set->bottom = btv->screen;
+                       }
+               } else {
+                       if (V4L2_FIELD_TOP == btv->screen->vb.field &&
+                           NULL == set->top) {
+                               set->top = btv->screen;
+                       }
+                       if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
+                           NULL == set->bottom) {
+                               set->bottom = btv->screen;
+                       }
+               }
+       }
+
+       dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+               btv->c.nr, set->top, set->bottom,
+               btv->screen, set->frame_irq, set->top_irq);
+       return 0;
+}
+
+static void
+bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
+                     struct bttv_buffer_set *curr, unsigned int state)
+{
+       struct timeval ts;
+
+       do_gettimeofday(&ts);
+
+       if (wakeup->top == wakeup->bottom) {
+               if (NULL != wakeup->top && curr->top != wakeup->top) {
+                       if (irq_debug > 1)
+                               pr_debug("%d: wakeup: both=%p\n",
+                                        btv->c.nr, wakeup->top);
+                       wakeup->top->vb.ts = ts;
+                       wakeup->top->vb.field_count = btv->field_count;
+                       wakeup->top->vb.state = state;
+                       wake_up(&wakeup->top->vb.done);
+               }
+       } else {
+               if (NULL != wakeup->top && curr->top != wakeup->top) {
+                       if (irq_debug > 1)
+                               pr_debug("%d: wakeup: top=%p\n",
+                                        btv->c.nr, wakeup->top);
+                       wakeup->top->vb.ts = ts;
+                       wakeup->top->vb.field_count = btv->field_count;
+                       wakeup->top->vb.state = state;
+                       wake_up(&wakeup->top->vb.done);
+               }
+               if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
+                       if (irq_debug > 1)
+                               pr_debug("%d: wakeup: bottom=%p\n",
+                                        btv->c.nr, wakeup->bottom);
+                       wakeup->bottom->vb.ts = ts;
+                       wakeup->bottom->vb.field_count = btv->field_count;
+                       wakeup->bottom->vb.state = state;
+                       wake_up(&wakeup->bottom->vb.done);
+               }
+       }
+}
+
+static void
+bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
+                   unsigned int state)
+{
+       struct timeval ts;
+
+       if (NULL == wakeup)
+               return;
+
+       do_gettimeofday(&ts);
+       wakeup->vb.ts = ts;
+       wakeup->vb.field_count = btv->field_count;
+       wakeup->vb.state = state;
+       wake_up(&wakeup->vb.done);
+}
+
+static void bttv_irq_timeout(unsigned long data)
+{
+       struct bttv *btv = (struct bttv *)data;
+       struct bttv_buffer_set old,new;
+       struct bttv_buffer *ovbi;
+       struct bttv_buffer *item;
+       unsigned long flags;
+
+       if (bttv_verbose) {
+               pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+                       btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+                       btread(BT848_RISC_COUNT));
+               bttv_print_irqbits(btread(BT848_INT_STAT),0);
+               pr_cont("\n");
+       }
+
+       spin_lock_irqsave(&btv->s_lock,flags);
+
+       /* deactivate stuff */
+       memset(&new,0,sizeof(new));
+       old  = btv->curr;
+       ovbi = btv->cvbi;
+       btv->curr = new;
+       btv->cvbi = NULL;
+       btv->loop_irq = 0;
+       bttv_buffer_activate_video(btv, &new);
+       bttv_buffer_activate_vbi(btv,   NULL);
+       bttv_set_dma(btv, 0);
+
+       /* wake up */
+       bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
+       bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
+
+       /* cancel all outstanding capture / vbi requests */
+       while (!list_empty(&btv->capture)) {
+               item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+               list_del(&item->vb.queue);
+               item->vb.state = VIDEOBUF_ERROR;
+               wake_up(&item->vb.done);
+       }
+       while (!list_empty(&btv->vcapture)) {
+               item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+               list_del(&item->vb.queue);
+               item->vb.state = VIDEOBUF_ERROR;
+               wake_up(&item->vb.done);
+       }
+
+       btv->errors++;
+       spin_unlock_irqrestore(&btv->s_lock,flags);
+}
+
+static void
+bttv_irq_wakeup_top(struct bttv *btv)
+{
+       struct bttv_buffer *wakeup = btv->curr.top;
+
+       if (NULL == wakeup)
+               return;
+
+       spin_lock(&btv->s_lock);
+       btv->curr.top_irq = 0;
+       btv->curr.top = NULL;
+       bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+
+       do_gettimeofday(&wakeup->vb.ts);
+       wakeup->vb.field_count = btv->field_count;
+       wakeup->vb.state = VIDEOBUF_DONE;
+       wake_up(&wakeup->vb.done);
+       spin_unlock(&btv->s_lock);
+}
+
+static inline int is_active(struct btcx_riscmem *risc, u32 rc)
+{
+       if (rc < risc->dma)
+               return 0;
+       if (rc > risc->dma + risc->size)
+               return 0;
+       return 1;
+}
+
+static void
+bttv_irq_switch_video(struct bttv *btv)
+{
+       struct bttv_buffer_set new;
+       struct bttv_buffer_set old;
+       dma_addr_t rc;
+
+       spin_lock(&btv->s_lock);
+
+       /* new buffer set */
+       bttv_irq_next_video(btv, &new);
+       rc = btread(BT848_RISC_COUNT);
+       if ((btv->curr.top    && is_active(&btv->curr.top->top,       rc)) ||
+           (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
+               btv->framedrop++;
+               if (debug_latency)
+                       bttv_irq_debug_low_latency(btv, rc);
+               spin_unlock(&btv->s_lock);
+               return;
+       }
+
+       /* switch over */
+       old = btv->curr;
+       btv->curr = new;
+       btv->loop_irq &= ~1;
+       bttv_buffer_activate_video(btv, &new);
+       bttv_set_dma(btv, 0);
+
+       /* switch input */
+       if (UNSET != btv->new_input) {
+               video_mux(btv,btv->new_input);
+               btv->new_input = UNSET;
+       }
+
+       /* wake up finished buffers */
+       bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
+       spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_switch_vbi(struct bttv *btv)
+{
+       struct bttv_buffer *new = NULL;
+       struct bttv_buffer *old;
+       u32 rc;
+
+       spin_lock(&btv->s_lock);
+
+       if (!list_empty(&btv->vcapture))
+               new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+       old = btv->cvbi;
+
+       rc = btread(BT848_RISC_COUNT);
+       if (NULL != old && (is_active(&old->top,    rc) ||
+                           is_active(&old->bottom, rc))) {
+               btv->framedrop++;
+               if (debug_latency)
+                       bttv_irq_debug_low_latency(btv, rc);
+               spin_unlock(&btv->s_lock);
+               return;
+       }
+
+       /* switch */
+       btv->cvbi = new;
+       btv->loop_irq &= ~4;
+       bttv_buffer_activate_vbi(btv, new);
+       bttv_set_dma(btv, 0);
+
+       bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
+       spin_unlock(&btv->s_lock);
+}
+
+static irqreturn_t bttv_irq(int irq, void *dev_id)
+{
+       u32 stat,astat;
+       u32 dstat;
+       int count;
+       struct bttv *btv;
+       int handled = 0;
+
+       btv=(struct bttv *)dev_id;
+
+       count=0;
+       while (1) {
+               /* get/clear interrupt status bits */
+               stat=btread(BT848_INT_STAT);
+               astat=stat&btread(BT848_INT_MASK);
+               if (!astat)
+                       break;
+               handled = 1;
+               btwrite(stat,BT848_INT_STAT);
+
+               /* get device status bits */
+               dstat=btread(BT848_DSTATUS);
+
+               if (irq_debug) {
+                       pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+                                btv->c.nr, count, btv->field_count,
+                                stat>>28, btread(BT848_RISC_COUNT));
+                       bttv_print_irqbits(stat,astat);
+                       if (stat & BT848_INT_HLOCK)
+                               pr_cont("   HLOC => %s",
+                                       dstat & BT848_DSTATUS_HLOC
+                                       ? "yes" : "no");
+                       if (stat & BT848_INT_VPRES)
+                               pr_cont("   PRES => %s",
+                                       dstat & BT848_DSTATUS_PRES
+                                       ? "yes" : "no");
+                       if (stat & BT848_INT_FMTCHG)
+                               pr_cont("   NUML => %s",
+                                       dstat & BT848_DSTATUS_NUML
+                                       ? "625" : "525");
+                       pr_cont("\n");
+               }
+
+               if (astat&BT848_INT_VSYNC)
+                       btv->field_count++;
+
+               if ((astat & BT848_INT_GPINT) && btv->remote) {
+                       bttv_input_irq(btv);
+               }
+
+               if (astat & BT848_INT_I2CDONE) {
+                       btv->i2c_done = stat;
+                       wake_up(&btv->i2c_queue);
+               }
+
+               if ((astat & BT848_INT_RISCI)  &&  (stat & (4<<28)))
+                       bttv_irq_switch_vbi(btv);
+
+               if ((astat & BT848_INT_RISCI)  &&  (stat & (2<<28)))
+                       bttv_irq_wakeup_top(btv);
+
+               if ((astat & BT848_INT_RISCI)  &&  (stat & (1<<28)))
+                       bttv_irq_switch_video(btv);
+
+               if ((astat & BT848_INT_HLOCK)  &&  btv->opt_automute)
+                       audio_mute(btv, btv->mute);  /* trigger automute */
+
+               if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
+                       pr_info("%d: %s%s @ %08x,",
+                               btv->c.nr,
+                               (astat & BT848_INT_SCERR) ? "SCERR" : "",
+                               (astat & BT848_INT_OCERR) ? "OCERR" : "",
+                               btread(BT848_RISC_COUNT));
+                       bttv_print_irqbits(stat,astat);
+                       pr_cont("\n");
+                       if (bttv_debug)
+                               bttv_print_riscaddr(btv);
+               }
+               if (fdsr && astat & BT848_INT_FDSR) {
+                       pr_info("%d: FDSR @ %08x\n",
+                               btv->c.nr, btread(BT848_RISC_COUNT));
+                       if (bttv_debug)
+                               bttv_print_riscaddr(btv);
+               }
+
+               count++;
+               if (count > 4) {
+
+                       if (count > 8 || !(astat & BT848_INT_GPINT)) {
+                               btwrite(0, BT848_INT_MASK);
+
+                               pr_err("%d: IRQ lockup, cleared int mask [",
+                                      btv->c.nr);
+                       } else {
+                               pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+                                      btv->c.nr);
+
+                               btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
+                                               BT848_INT_MASK);
+                       };
+
+                       bttv_print_irqbits(stat,astat);
+
+                       pr_cont("]\n");
+               }
+       }
+       btv->irq_total++;
+       if (handled)
+               btv->irq_me++;
+       return IRQ_RETVAL(handled);
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* initialitation                                                          */
+
+static struct video_device *vdev_init(struct bttv *btv,
+                                     const struct video_device *template,
+                                     const char *type_name)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->v4l2_dev = &btv->c.v4l2_dev;
+       vfd->release = video_device_release;
+       vfd->debug   = bttv_debug;
+       video_set_drvdata(vfd, btv);
+       snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
+                btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
+                type_name, bttv_tvcards[btv->c.type].name);
+       return vfd;
+}
+
+static void bttv_unregister_video(struct bttv *btv)
+{
+       if (btv->video_dev) {
+               if (video_is_registered(btv->video_dev))
+                       video_unregister_device(btv->video_dev);
+               else
+                       video_device_release(btv->video_dev);
+               btv->video_dev = NULL;
+       }
+       if (btv->vbi_dev) {
+               if (video_is_registered(btv->vbi_dev))
+                       video_unregister_device(btv->vbi_dev);
+               else
+                       video_device_release(btv->vbi_dev);
+               btv->vbi_dev = NULL;
+       }
+       if (btv->radio_dev) {
+               if (video_is_registered(btv->radio_dev))
+                       video_unregister_device(btv->radio_dev);
+               else
+                       video_device_release(btv->radio_dev);
+               btv->radio_dev = NULL;
+       }
+}
+
+/* register video4linux devices */
+static int __devinit bttv_register_video(struct bttv *btv)
+{
+       if (no_overlay > 0)
+               pr_notice("Overlay support disabled\n");
+
+       /* video */
+       btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
+
+       if (NULL == btv->video_dev)
+               goto err;
+       if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
+                                 video_nr[btv->c.nr]) < 0)
+               goto err;
+       pr_info("%d: registered device %s\n",
+               btv->c.nr, video_device_node_name(btv->video_dev));
+       if (device_create_file(&btv->video_dev->dev,
+                                    &dev_attr_card)<0) {
+               pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
+               goto err;
+       }
+
+       /* vbi */
+       btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
+
+       if (NULL == btv->vbi_dev)
+               goto err;
+       if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
+                                 vbi_nr[btv->c.nr]) < 0)
+               goto err;
+       pr_info("%d: registered device %s\n",
+               btv->c.nr, video_device_node_name(btv->vbi_dev));
+
+       if (!btv->has_radio)
+               return 0;
+       /* radio */
+       btv->radio_dev = vdev_init(btv, &radio_template, "radio");
+       if (NULL == btv->radio_dev)
+               goto err;
+       if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
+                                 radio_nr[btv->c.nr]) < 0)
+               goto err;
+       pr_info("%d: registered device %s\n",
+               btv->c.nr, video_device_node_name(btv->radio_dev));
+
+       /* all done */
+       return 0;
+
+ err:
+       bttv_unregister_video(btv);
+       return -1;
+}
+
+
+/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
+/* response on cards with no firmware is not enabled by OF */
+static void pci_set_command(struct pci_dev *dev)
+{
+#if defined(__powerpc__)
+       unsigned int cmd;
+
+       pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+       cmd = (cmd | PCI_COMMAND_MEMORY );
+       pci_write_config_dword(dev, PCI_COMMAND, cmd);
+#endif
+}
+
+static int __devinit bttv_probe(struct pci_dev *dev,
+                               const struct pci_device_id *pci_id)
+{
+       int result;
+       unsigned char lat;
+       struct bttv *btv;
+
+       if (bttv_num == BTTV_MAX)
+               return -ENOMEM;
+       pr_info("Bt8xx card found (%d)\n", bttv_num);
+       bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
+       if (btv == NULL) {
+               pr_err("out of memory\n");
+               return -ENOMEM;
+       }
+       btv->c.nr  = bttv_num;
+       snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
+                       "bttv%d", btv->c.nr);
+
+       /* initialize structs / fill in defaults */
+       mutex_init(&btv->lock);
+       spin_lock_init(&btv->s_lock);
+       spin_lock_init(&btv->gpio_lock);
+       init_waitqueue_head(&btv->i2c_queue);
+       INIT_LIST_HEAD(&btv->c.subs);
+       INIT_LIST_HEAD(&btv->capture);
+       INIT_LIST_HEAD(&btv->vcapture);
+       v4l2_prio_init(&btv->prio);
+
+       init_timer(&btv->timeout);
+       btv->timeout.function = bttv_irq_timeout;
+       btv->timeout.data     = (unsigned long)btv;
+
+       btv->i2c_rc = -1;
+       btv->tuner_type  = UNSET;
+       btv->new_input   = UNSET;
+       btv->has_radio=radio[btv->c.nr];
+
+       /* pci stuff (init, get irq/mmio, ... */
+       btv->c.pci = dev;
+       btv->id  = dev->device;
+       if (pci_enable_device(dev)) {
+               pr_warn("%d: Can't enable device\n", btv->c.nr);
+               return -EIO;
+       }
+       if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
+               pr_warn("%d: No suitable DMA available\n", btv->c.nr);
+               return -EIO;
+       }
+       if (!request_mem_region(pci_resource_start(dev,0),
+                               pci_resource_len(dev,0),
+                               btv->c.v4l2_dev.name)) {
+               pr_warn("%d: can't request iomem (0x%llx)\n",
+                       btv->c.nr,
+                       (unsigned long long)pci_resource_start(dev, 0));
+               return -EBUSY;
+       }
+       pci_set_master(dev);
+       pci_set_command(dev);
+
+       result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
+       if (result < 0) {
+               pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
+               goto fail0;
+       }
+
+       btv->revision = dev->revision;
+       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+       pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+               bttv_num, btv->id, btv->revision, pci_name(dev),
+               btv->c.pci->irq, lat,
+               (unsigned long long)pci_resource_start(dev, 0));
+       schedule();
+
+       btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+       if (NULL == btv->bt848_mmio) {
+               pr_err("%d: ioremap() failed\n", btv->c.nr);
+               result = -EIO;
+               goto fail1;
+       }
+
+       /* identify card */
+       bttv_idcard(btv);
+
+       /* disable irqs, register irq handler */
+       btwrite(0, BT848_INT_MASK);
+       result = request_irq(btv->c.pci->irq, bttv_irq,
+           IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
+       if (result < 0) {
+               pr_err("%d: can't get IRQ %d\n",
+                      bttv_num, btv->c.pci->irq);
+               goto fail1;
+       }
+
+       if (0 != bttv_handle_chipset(btv)) {
+               result = -EIO;
+               goto fail2;
+       }
+
+       /* init options from insmod args */
+       btv->opt_combfilter = combfilter;
+       btv->opt_lumafilter = lumafilter;
+       btv->opt_automute   = automute;
+       btv->opt_chroma_agc = chroma_agc;
+       btv->opt_adc_crush  = adc_crush;
+       btv->opt_vcr_hack   = vcr_hack;
+       btv->opt_whitecrush_upper  = whitecrush_upper;
+       btv->opt_whitecrush_lower  = whitecrush_lower;
+       btv->opt_uv_ratio   = uv_ratio;
+       btv->opt_full_luma_range   = full_luma_range;
+       btv->opt_coring     = coring;
+
+       /* fill struct bttv with some useful defaults */
+       btv->init.btv         = btv;
+       btv->init.ov.w.width  = 320;
+       btv->init.ov.w.height = 240;
+       btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+       btv->init.width       = 320;
+       btv->init.height      = 240;
+       btv->input = 0;
+
+       /* initialize hardware */
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"pre-init");
+
+       bttv_risc_init_main(btv);
+       init_bt848(btv);
+
+       /* gpio */
+       btwrite(0x00, BT848_GPIO_REG_INP);
+       btwrite(0x00, BT848_GPIO_OUT_EN);
+       if (bttv_verbose)
+               bttv_gpio_tracking(btv,"init");
+
+       /* needs to be done before i2c is registered */
+       bttv_init_card1(btv);
+
+       /* register i2c + gpio */
+       init_bttv_i2c(btv);
+
+       /* some card-specific stuff (needs working i2c) */
+       bttv_init_card2(btv);
+       bttv_init_tuner(btv);
+       init_irqreg(btv);
+
+       /* register video4linux + input */
+       if (!bttv_tvcards[btv->c.type].no_video) {
+               bttv_register_video(btv);
+               bt848_bright(btv,32768);
+               bt848_contrast(btv, 27648);
+               bt848_hue(btv,32768);
+               bt848_sat(btv,32768);
+               audio_mute(btv, 1);
+               set_input(btv, 0, btv->tvnorm);
+               bttv_crop_reset(&btv->crop[0], btv->tvnorm);
+               btv->crop[1] = btv->crop[0]; /* current = default */
+               disclaim_vbi_lines(btv);
+               disclaim_video_lines(btv);
+       }
+
+       /* add subdevices and autoload dvb-bt8xx if needed */
+       if (bttv_tvcards[btv->c.type].has_dvb) {
+               bttv_sub_add_device(&btv->c, "dvb");
+               request_modules(btv);
+       }
+
+       if (!disable_ir) {
+               init_bttv_i2c_ir(btv);
+               bttv_input_init(btv);
+       }
+
+       /* everything is fine */
+       bttv_num++;
+       return 0;
+
+fail2:
+       free_irq(btv->c.pci->irq,btv);
+
+fail1:
+       v4l2_device_unregister(&btv->c.v4l2_dev);
+
+fail0:
+       if (btv->bt848_mmio)
+               iounmap(btv->bt848_mmio);
+       release_mem_region(pci_resource_start(btv->c.pci,0),
+                          pci_resource_len(btv->c.pci,0));
+       return result;
+}
+
+static void __devexit bttv_remove(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct bttv *btv = to_bttv(v4l2_dev);
+
+       if (bttv_verbose)
+               pr_info("%d: unloading\n", btv->c.nr);
+
+       if (bttv_tvcards[btv->c.type].has_dvb)
+               flush_request_modules(btv);
+
+       /* shutdown everything (DMA+IRQs) */
+       btand(~15, BT848_GPIO_DMA_CTL);
+       btwrite(0, BT848_INT_MASK);
+       btwrite(~0x0, BT848_INT_STAT);
+       btwrite(0x0, BT848_GPIO_OUT_EN);
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"cleanup");
+
+       /* tell gpio modules we are leaving ... */
+       btv->shutdown=1;
+       bttv_input_fini(btv);
+       bttv_sub_del_devices(&btv->c);
+
+       /* unregister i2c_bus + input */
+       fini_bttv_i2c(btv);
+
+       /* unregister video4linux */
+       bttv_unregister_video(btv);
+
+       /* free allocated memory */
+       btcx_riscmem_free(btv->c.pci,&btv->main);
+
+       /* free ressources */
+       free_irq(btv->c.pci->irq,btv);
+       iounmap(btv->bt848_mmio);
+       release_mem_region(pci_resource_start(btv->c.pci,0),
+                          pci_resource_len(btv->c.pci,0));
+
+       v4l2_device_unregister(&btv->c.v4l2_dev);
+       bttvs[btv->c.nr] = NULL;
+       kfree(btv);
+
+       return;
+}
+
+#ifdef CONFIG_PM
+static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct bttv *btv = to_bttv(v4l2_dev);
+       struct bttv_buffer_set idle;
+       unsigned long flags;
+
+       dprintk("%d: suspend %d\n", btv->c.nr, state.event);
+
+       /* stop dma + irqs */
+       spin_lock_irqsave(&btv->s_lock,flags);
+       memset(&idle, 0, sizeof(idle));
+       btv->state.video = btv->curr;
+       btv->state.vbi   = btv->cvbi;
+       btv->state.loop_irq = btv->loop_irq;
+       btv->curr = idle;
+       btv->loop_irq = 0;
+       bttv_buffer_activate_video(btv, &idle);
+       bttv_buffer_activate_vbi(btv, NULL);
+       bttv_set_dma(btv, 0);
+       btwrite(0, BT848_INT_MASK);
+       spin_unlock_irqrestore(&btv->s_lock,flags);
+
+       /* save bt878 state */
+       btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
+       btv->state.gpio_data   = gpio_read();
+
+       /* save pci state */
+       pci_save_state(pci_dev);
+       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+               pci_disable_device(pci_dev);
+               btv->state.disabled = 1;
+       }
+       return 0;
+}
+
+static int bttv_resume(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct bttv *btv = to_bttv(v4l2_dev);
+       unsigned long flags;
+       int err;
+
+       dprintk("%d: resume\n", btv->c.nr);
+
+       /* restore pci state */
+       if (btv->state.disabled) {
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       pr_warn("%d: Can't enable device\n", btv->c.nr);
+                       return err;
+               }
+               btv->state.disabled = 0;
+       }
+       err=pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               pci_disable_device(pci_dev);
+               pr_warn("%d: Can't enable device\n", btv->c.nr);
+               btv->state.disabled = 1;
+               return err;
+       }
+
+       pci_restore_state(pci_dev);
+
+       /* restore bt878 state */
+       bttv_reinit_bt848(btv);
+       gpio_inout(0xffffff, btv->state.gpio_enable);
+       gpio_write(btv->state.gpio_data);
+
+       /* restart dma */
+       spin_lock_irqsave(&btv->s_lock,flags);
+       btv->curr = btv->state.video;
+       btv->cvbi = btv->state.vbi;
+       btv->loop_irq = btv->state.loop_irq;
+       bttv_buffer_activate_video(btv, &btv->curr);
+       bttv_buffer_activate_vbi(btv, btv->cvbi);
+       bttv_set_dma(btv, 0);
+       spin_unlock_irqrestore(&btv->s_lock,flags);
+       return 0;
+}
+#endif
+
+static struct pci_device_id bttv_pci_tbl[] = {
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
+       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
+
+static struct pci_driver bttv_pci_driver = {
+       .name     = "bttv",
+       .id_table = bttv_pci_tbl,
+       .probe    = bttv_probe,
+       .remove   = __devexit_p(bttv_remove),
+#ifdef CONFIG_PM
+       .suspend  = bttv_suspend,
+       .resume   = bttv_resume,
+#endif
+};
+
+static int __init bttv_init_module(void)
+{
+       int ret;
+
+       bttv_num = 0;
+
+       pr_info("driver version %s loaded\n", BTTV_VERSION);
+       if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
+               gbuffers = 2;
+       if (gbufsize > BTTV_MAX_FBUF)
+               gbufsize = BTTV_MAX_FBUF;
+       gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
+       if (bttv_verbose)
+               pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+                       gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+
+       bttv_check_chipset();
+
+       ret = bus_register(&bttv_sub_bus_type);
+       if (ret < 0) {
+               pr_warn("bus_register error: %d\n", ret);
+               return ret;
+       }
+       ret = pci_register_driver(&bttv_pci_driver);
+       if (ret < 0)
+               bus_unregister(&bttv_sub_bus_type);
+
+       return ret;
+}
+
+static void __exit bttv_cleanup_module(void)
+{
+       pci_unregister_driver(&bttv_pci_driver);
+       bus_unregister(&bttv_sub_bus_type);
+}
+
+module_init(bttv_init_module);
+module_exit(bttv_cleanup_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c
new file mode 100644 (file)
index 0000000..922e823
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+
+    bttv-gpio.c  --  gpio sub drivers
+
+    sysfs-based sub driver interface for bttv
+    mainly intended for gpio access
+
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                          & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+
+/* ----------------------------------------------------------------------- */
+/* internal: the bttv "bus"                                                */
+
+static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
+       int len = strlen(sub->wanted);
+
+       if (0 == strncmp(dev_name(dev), sub->wanted, len))
+               return 1;
+       return 0;
+}
+
+static int bttv_sub_probe(struct device *dev)
+{
+       struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+       struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+       return sub->probe ? sub->probe(sdev) : -ENODEV;
+}
+
+static int bttv_sub_remove(struct device *dev)
+{
+       struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+       struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+       if (sub->remove)
+               sub->remove(sdev);
+       return 0;
+}
+
+struct bus_type bttv_sub_bus_type = {
+       .name   = "bttv-sub",
+       .match  = &bttv_sub_bus_match,
+       .probe  = bttv_sub_probe,
+       .remove = bttv_sub_remove,
+};
+
+static void release_sub_device(struct device *dev)
+{
+       struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
+       kfree(sub);
+}
+
+int bttv_sub_add_device(struct bttv_core *core, char *name)
+{
+       struct bttv_sub_device *sub;
+       int err;
+
+       sub = kzalloc(sizeof(*sub),GFP_KERNEL);
+       if (NULL == sub)
+               return -ENOMEM;
+
+       sub->core        = core;
+       sub->dev.parent  = &core->pci->dev;
+       sub->dev.bus     = &bttv_sub_bus_type;
+       sub->dev.release = release_sub_device;
+       dev_set_name(&sub->dev, "%s%d", name, core->nr);
+
+       err = device_register(&sub->dev);
+       if (0 != err) {
+               kfree(sub);
+               return err;
+       }
+       pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+       list_add_tail(&sub->list,&core->subs);
+       return 0;
+}
+
+int bttv_sub_del_devices(struct bttv_core *core)
+{
+       struct bttv_sub_device *sub, *save;
+
+       list_for_each_entry_safe(sub, save, &core->subs, list) {
+               list_del(&sub->list);
+               device_unregister(&sub->dev);
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/* external: sub-driver register/unregister                                */
+
+int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted)
+{
+       sub->drv.bus = &bttv_sub_bus_type;
+       snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
+       return driver_register(&sub->drv);
+}
+EXPORT_SYMBOL(bttv_sub_register);
+
+int bttv_sub_unregister(struct bttv_sub_driver *sub)
+{
+       driver_unregister(&sub->drv);
+       return 0;
+}
+EXPORT_SYMBOL(bttv_sub_unregister);
+
+/* ----------------------------------------------------------------------- */
+/* external: gpio access functions                                         */
+
+void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits)
+{
+       struct bttv *btv = container_of(core, struct bttv, c);
+       unsigned long flags;
+       u32 data;
+
+       spin_lock_irqsave(&btv->gpio_lock,flags);
+       data = btread(BT848_GPIO_OUT_EN);
+       data = data & ~mask;
+       data = data | (mask & outbits);
+       btwrite(data,BT848_GPIO_OUT_EN);
+       spin_unlock_irqrestore(&btv->gpio_lock,flags);
+}
+
+u32 bttv_gpio_read(struct bttv_core *core)
+{
+       struct bttv *btv = container_of(core, struct bttv, c);
+       u32 value;
+
+       value = btread(BT848_GPIO_DATA);
+       return value;
+}
+
+void bttv_gpio_write(struct bttv_core *core, u32 value)
+{
+       struct bttv *btv = container_of(core, struct bttv, c);
+
+       btwrite(value,BT848_GPIO_DATA);
+}
+
+void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
+{
+       struct bttv *btv = container_of(core, struct bttv, c);
+       unsigned long flags;
+       u32 data;
+
+       spin_lock_irqsave(&btv->gpio_lock,flags);
+       data = btread(BT848_GPIO_DATA);
+       data = data & ~mask;
+       data = data | (mask & bits);
+       btwrite(data,BT848_GPIO_DATA);
+       spin_unlock_irqrestore(&btv->gpio_lock,flags);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c
new file mode 100644 (file)
index 0000000..580c8e6
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+
+    bttv-i2c.c  --  all the i2c code is here
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                          & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+       - Multituner support and i2c address binding
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
+
+static int i2c_debug;
+static int i2c_hw;
+static int i2c_scan;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
+module_param(i2c_hw,    int, 0444);
+MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
+                       "instead of software bitbang");
+module_param(i2c_scan,  int, 0444);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0444);
+MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
+               "(should be 5 or higher). Lower value means higher bus speed.");
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - bitbanging adapter (software i2c)                       */
+
+static void bttv_bit_setscl(void *data, int state)
+{
+       struct bttv *btv = (struct bttv*)data;
+
+       if (state)
+               btv->i2c_state |= 0x02;
+       else
+               btv->i2c_state &= ~0x02;
+       btwrite(btv->i2c_state, BT848_I2C);
+       btread(BT848_I2C);
+}
+
+static void bttv_bit_setsda(void *data, int state)
+{
+       struct bttv *btv = (struct bttv*)data;
+
+       if (state)
+               btv->i2c_state |= 0x01;
+       else
+               btv->i2c_state &= ~0x01;
+       btwrite(btv->i2c_state, BT848_I2C);
+       btread(BT848_I2C);
+}
+
+static int bttv_bit_getscl(void *data)
+{
+       struct bttv *btv = (struct bttv*)data;
+       int state;
+
+       state = btread(BT848_I2C) & 0x02 ? 1 : 0;
+       return state;
+}
+
+static int bttv_bit_getsda(void *data)
+{
+       struct bttv *btv = (struct bttv*)data;
+       int state;
+
+       state = btread(BT848_I2C) & 0x01;
+       return state;
+}
+
+static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
+       .setsda  = bttv_bit_setsda,
+       .setscl  = bttv_bit_setscl,
+       .getsda  = bttv_bit_getsda,
+       .getscl  = bttv_bit_getscl,
+       .udelay  = 16,
+       .timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - hardware i2c                                            */
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static int
+bttv_i2c_wait_done(struct bttv *btv)
+{
+       int rc = 0;
+
+       /* timeout */
+       if (wait_event_interruptible_timeout(btv->i2c_queue,
+           btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
+               rc = -EIO;
+
+       if (btv->i2c_done & BT848_INT_RACK)
+               rc = 1;
+       btv->i2c_done = 0;
+       return rc;
+}
+
+#define I2C_HW (BT878_I2C_MODE  | BT848_I2C_SYNC |\
+               BT848_I2C_SCL | BT848_I2C_SDA)
+
+static int
+bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
+{
+       u32 xmit;
+       int retval,cnt;
+
+       /* sanity checks */
+       if (0 == msg->len)
+               return -EINVAL;
+
+       /* start, address + first byte */
+       xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
+       if (msg->len > 1 || !last)
+               xmit |= BT878_I2C_NOSTOP;
+       btwrite(xmit, BT848_I2C);
+       retval = bttv_i2c_wait_done(btv);
+       if (retval < 0)
+               goto err;
+       if (retval == 0)
+               goto eio;
+       if (i2c_debug) {
+               pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
+       }
+
+       for (cnt = 1; cnt < msg->len; cnt++ ) {
+               /* following bytes */
+               xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
+               if (cnt < msg->len-1 || !last)
+                       xmit |= BT878_I2C_NOSTOP;
+               btwrite(xmit, BT848_I2C);
+               retval = bttv_i2c_wait_done(btv);
+               if (retval < 0)
+                       goto err;
+               if (retval == 0)
+                       goto eio;
+               if (i2c_debug)
+                       pr_cont(" %02x", msg->buf[cnt]);
+       }
+       if (!(xmit & BT878_I2C_NOSTOP))
+               pr_cont(">\n");
+       return msg->len;
+
+ eio:
+       retval = -EIO;
+ err:
+       if (i2c_debug)
+               pr_cont(" ERR: %d\n",retval);
+       return retval;
+}
+
+static int
+bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
+{
+       u32 xmit;
+       u32 cnt;
+       int retval;
+
+       for (cnt = 0; cnt < msg->len; cnt++) {
+               xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
+               if (cnt < msg->len-1)
+                       xmit |= BT848_I2C_W3B;
+               if (cnt < msg->len-1 || !last)
+                       xmit |= BT878_I2C_NOSTOP;
+               if (cnt)
+                       xmit |= BT878_I2C_NOSTART;
+
+               if (i2c_debug) {
+                       if (!(xmit & BT878_I2C_NOSTART))
+                               pr_cont(" <R %02x", (msg->addr << 1) +1);
+               }
+
+               btwrite(xmit, BT848_I2C);
+               retval = bttv_i2c_wait_done(btv);
+               if (retval < 0)
+                       goto err;
+               if (retval == 0)
+                       goto eio;
+               msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
+               if (i2c_debug) {
+                       pr_cont(" =%02x", msg->buf[cnt]);
+               }
+               if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+                       pr_cont(" >\n");
+       }
+
+
+       return msg->len;
+
+ eio:
+       retval = -EIO;
+ err:
+       if (i2c_debug)
+               pr_cont(" ERR: %d\n",retval);
+       return retval;
+}
+
+static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+       struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+       struct bttv *btv = to_bttv(v4l2_dev);
+       int retval = 0;
+       int i;
+
+       if (i2c_debug)
+               pr_debug("bt-i2c:");
+
+       btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
+       for (i = 0 ; i < num; i++) {
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read */
+                       retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
+                       if (retval < 0)
+                               goto err;
+               } else {
+                       /* write */
+                       retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
+                       if (retval < 0)
+                               goto err;
+               }
+       }
+       return num;
+
+ err:
+       return retval;
+}
+
+static const struct i2c_algorithm bttv_algo = {
+       .master_xfer   = bttv_i2c_xfer,
+       .functionality = functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - common stuff                                            */
+
+/* read I2C */
+int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
+{
+       unsigned char buffer = 0;
+
+       if (0 != btv->i2c_rc)
+               return -1;
+       if (bttv_verbose && NULL != probe_for)
+               pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+                       btv->c.nr, probe_for, addr);
+       btv->i2c_client.addr = addr >> 1;
+       if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
+               if (NULL != probe_for) {
+                       if (bttv_verbose)
+                               pr_cont("not found\n");
+               } else
+                       pr_warn("%d: i2c read 0x%x: error\n",
+                               btv->c.nr, addr);
+               return -1;
+       }
+       if (bttv_verbose && NULL != probe_for)
+               pr_cont("found\n");
+       return buffer;
+}
+
+/* write I2C */
+int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+                   unsigned char b2, int both)
+{
+       unsigned char buffer[2];
+       int bytes = both ? 2 : 1;
+
+       if (0 != btv->i2c_rc)
+               return -1;
+       btv->i2c_client.addr = addr >> 1;
+       buffer[0] = b1;
+       buffer[1] = b2;
+       if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
+               return -1;
+       return 0;
+}
+
+/* read EEPROM content */
+void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
+{
+       memset(eedata, 0, 256);
+       if (0 != btv->i2c_rc)
+               return;
+       btv->i2c_client.addr = addr >> 1;
+       tveeprom_read(&btv->i2c_client, eedata, 256);
+}
+
+static char *i2c_devs[128] = {
+       [ 0x1c >> 1 ] = "lgdt330x",
+       [ 0x30 >> 1 ] = "IR (hauppauge)",
+       [ 0x80 >> 1 ] = "msp34xx",
+       [ 0x86 >> 1 ] = "tda9887",
+       [ 0xa0 >> 1 ] = "eeprom",
+       [ 0xc0 >> 1 ] = "tuner (analog)",
+       [ 0xc2 >> 1 ] = "tuner (analog)",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i,rc;
+
+       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c,&buf,0);
+               if (rc < 0)
+                       continue;
+               pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+                       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+}
+
+/* init + register i2c adapter */
+int __devinit init_bttv_i2c(struct bttv *btv)
+{
+       strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
+
+       if (i2c_hw)
+               btv->use_i2c_hw = 1;
+       if (btv->use_i2c_hw) {
+               /* bt878 */
+               strlcpy(btv->c.i2c_adap.name, "bt878",
+                       sizeof(btv->c.i2c_adap.name));
+               btv->c.i2c_adap.algo = &bttv_algo;
+       } else {
+               /* bt848 */
+       /* Prevents usage of invalid delay values */
+               if (i2c_udelay<5)
+                       i2c_udelay=5;
+
+               strlcpy(btv->c.i2c_adap.name, "bttv",
+                       sizeof(btv->c.i2c_adap.name));
+               memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
+                      sizeof(bttv_i2c_algo_bit_template));
+               btv->i2c_algo.udelay = i2c_udelay;
+               btv->i2c_algo.data = btv;
+               btv->c.i2c_adap.algo_data = &btv->i2c_algo;
+       }
+       btv->c.i2c_adap.owner = THIS_MODULE;
+
+       btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
+       snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
+                "bt%d #%d [%s]", btv->id, btv->c.nr,
+                btv->use_i2c_hw ? "hw" : "sw");
+
+       i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev);
+       btv->i2c_client.adapter = &btv->c.i2c_adap;
+
+
+       if (btv->use_i2c_hw) {
+               btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
+       } else {
+               bttv_bit_setscl(btv,1);
+               bttv_bit_setsda(btv,1);
+               btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
+       }
+       if (0 == btv->i2c_rc && i2c_scan)
+               do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
+
+       return btv->i2c_rc;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-if.c b/drivers/media/pci/bt8xx/bttv-if.c
new file mode 100644 (file)
index 0000000..a6a540d
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+
+    bttv-if.c  --  old gpio interface to other kernel modules
+                  don't use in new code, will go away in 2.7
+                  have a look at bttv-gpio.c instead.
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                          & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+
+EXPORT_SYMBOL(bttv_get_pcidev);
+EXPORT_SYMBOL(bttv_gpio_enable);
+EXPORT_SYMBOL(bttv_read_gpio);
+EXPORT_SYMBOL(bttv_write_gpio);
+
+/* ----------------------------------------------------------------------- */
+/* Exported functions - for other modules which want to access the         */
+/*                      gpio ports (IR for example)                        */
+/*                      see bttv.h for comments                            */
+
+struct pci_dev* bttv_get_pcidev(unsigned int card)
+{
+       if (card >= bttv_num)
+               return NULL;
+       if (!bttvs[card])
+               return NULL;
+
+       return bttvs[card]->c.pci;
+}
+
+
+int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
+{
+       struct bttv *btv;
+
+       if (card >= bttv_num) {
+               return -EINVAL;
+       }
+
+       btv = bttvs[card];
+       if (!btv)
+               return -ENODEV;
+
+       gpio_inout(mask,data);
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"extern enable");
+       return 0;
+}
+
+int bttv_read_gpio(unsigned int card, unsigned long *data)
+{
+       struct bttv *btv;
+
+       if (card >= bttv_num) {
+               return -EINVAL;
+       }
+
+       btv = bttvs[card];
+       if (!btv)
+               return -ENODEV;
+
+       if(btv->shutdown) {
+               return -ENODEV;
+       }
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+   because we set direct input on init */
+       *data = gpio_read();
+       return 0;
+}
+
+int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
+{
+       struct bttv *btv;
+
+       if (card >= bttv_num) {
+               return -EINVAL;
+       }
+
+       btv = bttvs[card];
+       if (!btv)
+               return -ENODEV;
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+   because direct input is set on init */
+       gpio_bits(mask,data);
+       if (bttv_gpio)
+               bttv_gpio_tracking(btv,"extern write");
+       return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
new file mode 100644 (file)
index 0000000..ef4c7cd
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ *
+ * Copyright (c) 2003 Gerd Knorr
+ * Copyright (c) 2003 Pavel Machek
+ *
+ * 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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include "bttv.h"
+#include "bttvp.h"
+
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);
+
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+
+#undef dprintk
+#define dprintk(fmt, ...)                      \
+do {                                           \
+       if (ir_debug >= 1)                      \
+               pr_info(fmt, ##__VA_ARGS__);    \
+} while (0)
+
+#define DEVNAME "bttv-input"
+
+#define MODULE_NAME "bttv"
+
+/* ---------------------------------------------------------------------- */
+
+static void ir_handle_key(struct bttv *btv)
+{
+       struct bttv_ir *ir = btv->remote;
+       u32 gpio,data;
+
+       /* read gpio value */
+       gpio = bttv_gpio_read(&btv->c);
+       if (ir->polling) {
+               if (ir->last_gpio == gpio)
+                       return;
+               ir->last_gpio = gpio;
+       }
+
+       /* extract data */
+       data = ir_extract_bits(gpio, ir->mask_keycode);
+       dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
+               gpio, data,
+               ir->polling               ? "poll"  : "irq",
+               (gpio & ir->mask_keydown) ? " down" : "",
+               (gpio & ir->mask_keyup)   ? " up"   : "");
+
+       if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
+           (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
+               rc_keydown_notimeout(ir->dev, data, 0);
+       } else {
+               /* HACK: Probably, ir->mask_keydown is missing
+                  for this board */
+               if (btv->c.type == BTTV_BOARD_WINFAST2000)
+                       rc_keydown_notimeout(ir->dev, data, 0);
+
+               rc_keyup(ir->dev);
+       }
+}
+
+static void ir_enltv_handle_key(struct bttv *btv)
+{
+       struct bttv_ir *ir = btv->remote;
+       u32 gpio, data, keyup;
+
+       /* read gpio value */
+       gpio = bttv_gpio_read(&btv->c);
+
+       /* extract data */
+       data = ir_extract_bits(gpio, ir->mask_keycode);
+
+       /* Check if it is keyup */
+       keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
+
+       if ((ir->last_gpio & 0x7f) != data) {
+               dprintk("gpio=0x%x code=%d | %s\n",
+                       gpio, data,
+                       (gpio & ir->mask_keyup) ? " up" : "up/down");
+
+               rc_keydown_notimeout(ir->dev, data, 0);
+               if (keyup)
+                       rc_keyup(ir->dev);
+       } else {
+               if ((ir->last_gpio & 1 << 31) == keyup)
+                       return;
+
+               dprintk("(cnt) gpio=0x%x code=%d | %s\n",
+                       gpio, data,
+                       (gpio & ir->mask_keyup) ? " up" : "down");
+
+               if (keyup)
+                       rc_keyup(ir->dev);
+               else
+                       rc_keydown_notimeout(ir->dev, data, 0);
+       }
+
+       ir->last_gpio = data | keyup;
+}
+
+static int bttv_rc5_irq(struct bttv *btv);
+
+void bttv_input_irq(struct bttv *btv)
+{
+       struct bttv_ir *ir = btv->remote;
+
+       if (ir->rc5_gpio)
+               bttv_rc5_irq(btv);
+       else if (!ir->polling)
+               ir_handle_key(btv);
+}
+
+static void bttv_input_timer(unsigned long data)
+{
+       struct bttv *btv = (struct bttv*)data;
+       struct bttv_ir *ir = btv->remote;
+
+       if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
+               ir_enltv_handle_key(btv);
+       else
+               ir_handle_key(btv);
+       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+}
+
+/*
+ * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying
+ * on the rc-core way. As we need to be sure that both IRQ transitions are
+ * properly triggered, Better to touch it only with this hardware for
+ * testing.
+ */
+
+#define RC5_START(x)   (((x) >> 12) & 3)
+#define RC5_TOGGLE(x)  (((x) >> 11) & 1)
+#define RC5_ADDR(x)    (((x) >> 6) & 31)
+#define RC5_INSTR(x)   ((x) & 63)
+
+/* decode raw bit pattern to RC5 code */
+static u32 bttv_rc5_decode(unsigned int code)
+{
+       unsigned int org_code = code;
+       unsigned int pair;
+       unsigned int rc5 = 0;
+       int i;
+
+       for (i = 0; i < 14; ++i) {
+               pair = code & 0x3;
+               code >>= 2;
+
+               rc5 <<= 1;
+               switch (pair) {
+               case 0:
+               case 2:
+                       break;
+               case 1:
+                       rc5 |= 1;
+               break;
+               case 3:
+                       dprintk("rc5_decode(%x) bad code\n",
+                               org_code);
+                       return 0;
+               }
+       }
+       dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+               "instr=%x\n", rc5, org_code, RC5_START(rc5),
+               RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+       return rc5;
+}
+
+static void bttv_rc5_timer_end(unsigned long data)
+{
+       struct bttv_ir *ir = (struct bttv_ir *)data;
+       struct timeval tv;
+       u32 gap;
+       u32 rc5 = 0;
+
+       /* get time */
+       do_gettimeofday(&tv);
+
+       /* avoid overflow with gap >1s */
+       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+               gap = 200000;
+       } else {
+               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+                   tv.tv_usec - ir->base_time.tv_usec;
+       }
+
+       /* signal we're ready to start a new code */
+       ir->active = false;
+
+       /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
+       if (gap < 28000) {
+               dprintk("spurious timer_end\n");
+               return;
+       }
+
+       if (ir->last_bit < 20) {
+               /* ignore spurious codes (caused by light/other remotes) */
+               dprintk("short code: %x\n", ir->code);
+       } else {
+               ir->code = (ir->code << ir->shift_by) | 1;
+               rc5 = bttv_rc5_decode(ir->code);
+
+               /* two start bits? */
+               if (RC5_START(rc5) != ir->start) {
+                       pr_info(DEVNAME ":"
+                              " rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+                       /* right address? */
+               } else if (RC5_ADDR(rc5) == ir->addr) {
+                       u32 toggle = RC5_TOGGLE(rc5);
+                       u32 instr = RC5_INSTR(rc5);
+
+                       /* Good code */
+                       rc_keydown(ir->dev, instr, toggle);
+                       dprintk("instruction %x, toggle %x\n",
+                               instr, toggle);
+               }
+       }
+}
+
+static int bttv_rc5_irq(struct bttv *btv)
+{
+       struct bttv_ir *ir = btv->remote;
+       struct timeval tv;
+       u32 gpio;
+       u32 gap;
+       unsigned long current_jiffies;
+
+       /* read gpio port */
+       gpio = bttv_gpio_read(&btv->c);
+
+       /* get time of bit */
+       current_jiffies = jiffies;
+       do_gettimeofday(&tv);
+
+       /* avoid overflow with gap >1s */
+       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+               gap = 200000;
+       } else {
+               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+                   tv.tv_usec - ir->base_time.tv_usec;
+       }
+
+       dprintk("RC5 IRQ: gap %d us for %s\n",
+               gap, (gpio & 0x20) ? "mark" : "space");
+
+       /* remote IRQ? */
+       if (!(gpio & 0x20))
+               return 0;
+
+       /* active code => add bit */
+       if (ir->active) {
+               /* only if in the code (otherwise spurious IRQ or timer
+                  late) */
+               if (ir->last_bit < 28) {
+                       ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+                           ir_rc5_remote_gap;
+                       ir->code |= 1 << ir->last_bit;
+               }
+               /* starting new code */
+       } else {
+               ir->active = true;
+               ir->code = 0;
+               ir->base_time = tv;
+               ir->last_bit = 0;
+
+               mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30));
+       }
+
+       /* toggle GPIO pin 4 to reset the irq */
+       bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+       bttv_gpio_write(&btv->c, gpio | (1 << 4));
+       return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+{
+       if (ir->polling) {
+               setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
+               ir->timer.expires  = jiffies + msecs_to_jiffies(1000);
+               add_timer(&ir->timer);
+       } else if (ir->rc5_gpio) {
+               /* set timer_end for code completion */
+               setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
+               ir->shift_by = 1;
+               ir->start = 3;
+               ir->addr = 0x0;
+               ir->rc5_remote_gap = ir_rc5_remote_gap;
+       }
+}
+
+static void bttv_ir_stop(struct bttv *btv)
+{
+       if (btv->remote->polling)
+               del_timer_sync(&btv->remote->timer);
+
+       if (btv->remote->rc5_gpio) {
+               u32 gpio;
+
+               del_timer_sync(&btv->remote->timer);
+
+               gpio = bttv_gpio_read(&btv->c);
+               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+       }
+}
+
+/*
+ * Get_key functions used by I2C remotes
+ */
+
+static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char b;
+
+       /* poll IR chip */
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
+               dprintk("read error\n");
+               return -EIO;
+       }
+
+       /* ignore 0xaa */
+       if (b==0xaa)
+               return 0;
+       dprintk("key %02x\n", b);
+
+       /*
+        * NOTE:
+        * lirc_i2c maps the pv951 code as:
+        *      addr = 0x61D6
+        *      cmd = bit_reverse (b)
+        * So, it seems that this device uses NEC extended
+        * I decided to not fix the table, due to two reasons:
+        *      1) Without the actual device, this is only a guess;
+        *      2) As the addr is not reported via I2C, nor can be changed,
+        *         the device is bound to the vendor-provided RC.
+        */
+
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+/* Instantiate the I2C IR receiver device, if present */
+void __devinit init_bttv_i2c_ir(struct bttv *btv)
+{
+       const unsigned short addr_list[] = {
+               0x1a, 0x18, 0x64, 0x30, 0x71,
+               I2C_CLIENT_END
+       };
+       struct i2c_board_info info;
+
+       if (0 != btv->i2c_rc)
+               return;
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       memset(&btv->init_data, 0, sizeof(btv->init_data));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+       switch (btv->c.type) {
+       case BTTV_BOARD_PV951:
+               btv->init_data.name = "PV951";
+               btv->init_data.get_key = get_key_pv951;
+               btv->init_data.ir_codes = RC_MAP_PV951;
+               info.addr = 0x4b;
+               break;
+       default:
+               /*
+                * The external IR receiver is at i2c address 0x34 (0x35 for
+                * reads).  Future Hauppauge cards will have an internal
+                * receiver at 0x30 (0x31 for reads).  In theory, both can be
+                * fitted, and Hauppauge suggest an external overrides an
+                * internal.
+                * That's why we probe 0x1a (~0x34) first. CB
+                */
+
+               i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
+               return;
+       }
+
+       if (btv->init_data.name)
+               info.platform_data = &btv->init_data;
+       i2c_new_device(&btv->c.i2c_adap, &info);
+
+       return;
+}
+
+int __devexit fini_bttv_i2c(struct bttv *btv)
+{
+       if (0 != btv->i2c_rc)
+               return 0;
+
+       return i2c_del_adapter(&btv->c.i2c_adap);
+}
+
+int bttv_input_init(struct bttv *btv)
+{
+       struct bttv_ir *ir;
+       char *ir_codes = NULL;
+       struct rc_dev *rc;
+       int err = -ENOMEM;
+
+       if (!btv->has_remote)
+               return -ENODEV;
+
+       ir = kzalloc(sizeof(*ir),GFP_KERNEL);
+       rc = rc_allocate_device();
+       if (!ir || !rc)
+               goto err_out_free;
+
+       /* detect & configure */
+       switch (btv->c.type) {
+       case BTTV_BOARD_AVERMEDIA:
+       case BTTV_BOARD_AVPHONE98:
+       case BTTV_BOARD_AVERMEDIA98:
+               ir_codes         = RC_MAP_AVERMEDIA;
+               ir->mask_keycode = 0xf88000;
+               ir->mask_keydown = 0x010000;
+               ir->polling      = 50; // ms
+               break;
+
+       case BTTV_BOARD_AVDVBT_761:
+       case BTTV_BOARD_AVDVBT_771:
+               ir_codes         = RC_MAP_AVERMEDIA_DVBT;
+               ir->mask_keycode = 0x0f00c0;
+               ir->mask_keydown = 0x000020;
+               ir->polling      = 50; // ms
+               break;
+
+       case BTTV_BOARD_PXELVWPLTVPAK:
+               ir_codes         = RC_MAP_PIXELVIEW;
+               ir->mask_keycode = 0x003e00;
+               ir->mask_keyup   = 0x010000;
+               ir->polling      = 50; // ms
+               break;
+       case BTTV_BOARD_PV_M4900:
+       case BTTV_BOARD_PV_BT878P_9B:
+       case BTTV_BOARD_PV_BT878P_PLUS:
+               ir_codes         = RC_MAP_PIXELVIEW;
+               ir->mask_keycode = 0x001f00;
+               ir->mask_keyup   = 0x008000;
+               ir->polling      = 50; // ms
+               break;
+
+       case BTTV_BOARD_WINFAST2000:
+               ir_codes         = RC_MAP_WINFAST;
+               ir->mask_keycode = 0x1f8;
+               break;
+       case BTTV_BOARD_MAGICTVIEW061:
+       case BTTV_BOARD_MAGICTVIEW063:
+               ir_codes         = RC_MAP_WINFAST;
+               ir->mask_keycode = 0x0008e000;
+               ir->mask_keydown = 0x00200000;
+               break;
+       case BTTV_BOARD_APAC_VIEWCOMP:
+               ir_codes         = RC_MAP_APAC_VIEWCOMP;
+               ir->mask_keycode = 0x001f00;
+               ir->mask_keyup   = 0x008000;
+               ir->polling      = 50; // ms
+               break;
+       case BTTV_BOARD_ASKEY_CPH03X:
+       case BTTV_BOARD_CONCEPTRONIC_CTVFMI2:
+       case BTTV_BOARD_CONTVFMI:
+               ir_codes         = RC_MAP_PIXELVIEW;
+               ir->mask_keycode = 0x001F00;
+               ir->mask_keyup   = 0x006000;
+               ir->polling      = 50; // ms
+               break;
+       case BTTV_BOARD_NEBULA_DIGITV:
+               ir_codes = RC_MAP_NEBULA;
+               ir->rc5_gpio = true;
+               break;
+       case BTTV_BOARD_MACHTV_MAGICTV:
+               ir_codes         = RC_MAP_APAC_VIEWCOMP;
+               ir->mask_keycode = 0x001F00;
+               ir->mask_keyup   = 0x004000;
+               ir->polling      = 50; /* ms */
+               break;
+       case BTTV_BOARD_KOZUMI_KTV_01C:
+               ir_codes         = RC_MAP_PCTV_SEDNA;
+               ir->mask_keycode = 0x001f00;
+               ir->mask_keyup   = 0x006000;
+               ir->polling      = 50; /* ms */
+               break;
+       case BTTV_BOARD_ENLTV_FM_2:
+               ir_codes         = RC_MAP_ENCORE_ENLTV2;
+               ir->mask_keycode = 0x00fd00;
+               ir->mask_keyup   = 0x000080;
+               ir->polling      = 1; /* ms */
+               ir->last_gpio    = ir_extract_bits(bttv_gpio_read(&btv->c),
+                                                  ir->mask_keycode);
+               break;
+       }
+       if (NULL == ir_codes) {
+               dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
+               err = -ENODEV;
+               goto err_out_free;
+       }
+
+       if (ir->rc5_gpio) {
+               u32 gpio;
+               /* enable remote irq */
+               bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
+               gpio = bttv_gpio_read(&btv->c);
+               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+               bttv_gpio_write(&btv->c, gpio | (1 << 4));
+       } else {
+               /* init hardware-specific stuff */
+               bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
+       }
+
+       /* init input device */
+       ir->dev = rc;
+
+       snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
+                btv->c.type);
+       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
+                pci_name(btv->c.pci));
+
+       rc->input_name = ir->name;
+       rc->input_phys = ir->phys;
+       rc->input_id.bustype = BUS_PCI;
+       rc->input_id.version = 1;
+       if (btv->c.pci->subsystem_vendor) {
+               rc->input_id.vendor  = btv->c.pci->subsystem_vendor;
+               rc->input_id.product = btv->c.pci->subsystem_device;
+       } else {
+               rc->input_id.vendor  = btv->c.pci->vendor;
+               rc->input_id.product = btv->c.pci->device;
+       }
+       rc->dev.parent = &btv->c.pci->dev;
+       rc->map_name = ir_codes;
+       rc->driver_name = MODULE_NAME;
+
+       btv->remote = ir;
+       bttv_ir_start(btv, ir);
+
+       /* all done */
+       err = rc_register_device(rc);
+       if (err)
+               goto err_out_stop;
+
+       return 0;
+
+ err_out_stop:
+       bttv_ir_stop(btv);
+       btv->remote = NULL;
+ err_out_free:
+       rc_free_device(rc);
+       kfree(ir);
+       return err;
+}
+
+void bttv_input_fini(struct bttv *btv)
+{
+       if (btv->remote == NULL)
+               return;
+
+       bttv_ir_stop(btv);
+       rc_unregister_device(btv->remote->dev);
+       kfree(btv->remote);
+       btv->remote = NULL;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
new file mode 100644 (file)
index 0000000..82cc47d
--- /dev/null
@@ -0,0 +1,909 @@
+/*
+
+    bttv-risc.c  --  interfaces to other kernel modules
+
+    bttv risc code handling
+       - memory management
+       - generation
+
+    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <media/v4l2-ioctl.h>
+
+#include "bttvp.h"
+
+#define VCR_HACK_LINES 4
+
+/* ---------------------------------------------------------- */
+/* risc code generators                                       */
+
+int
+bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
+                struct scatterlist *sglist,
+                unsigned int offset, unsigned int bpl,
+                unsigned int padding, unsigned int skip_lines,
+                unsigned int store_lines)
+{
+       u32 instructions,line,todo;
+       struct scatterlist *sg;
+       __le32 *rp;
+       int rc;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + sync + jump (all 2 dwords).  padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       instructions  = skip_lines * 4;
+       instructions += (1 + ((bpl + padding) * store_lines)
+                        / PAGE_SIZE + store_lines) * 8;
+       instructions += 2 * 8;
+       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
+               return rc;
+
+       /* sync instruction */
+       rp = risc->cpu;
+       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+       *(rp++) = cpu_to_le32(0);
+
+       while (skip_lines-- > 0) {
+               *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
+                                     BT848_RISC_EOL | bpl);
+       }
+
+       /* scan lines */
+       sg = sglist;
+       for (line = 0; line < store_lines; line++) {
+               if ((btv->opt_vcr_hack) &&
+                   (line >= (store_lines - VCR_HACK_LINES)))
+                       continue;
+               while (offset && offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
+                       sg++;
+               }
+               if (bpl <= sg_dma_len(sg)-offset) {
+                       /* fits into current chunk */
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+                                           BT848_RISC_EOL|bpl);
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       offset+=bpl;
+               } else {
+                       /* scanline needs to be splitted */
+                       todo = bpl;
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+                                           (sg_dma_len(sg)-offset));
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       todo -= (sg_dma_len(sg)-offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
+                                                   sg_dma_len(sg));
+                               *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                               todo -= sg_dma_len(sg);
+                               sg++;
+                       }
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
+                                           todo);
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                       offset += todo;
+               }
+               offset += padding;
+       }
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+
+static int
+bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
+                struct scatterlist *sglist,
+                unsigned int yoffset,  unsigned int ybpl,
+                unsigned int ypadding, unsigned int ylines,
+                unsigned int uoffset,  unsigned int voffset,
+                unsigned int hshift,   unsigned int vshift,
+                unsigned int cpadding)
+{
+       unsigned int instructions,line,todo,ylen,chroma;
+       __le32 *rp;
+       u32 ri;
+       struct scatterlist *ysg;
+       struct scatterlist *usg;
+       struct scatterlist *vsg;
+       int topfield = (0 == yoffset);
+       int rc;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line (5 dwords)
+          plus sync + jump (2 dwords) */
+       instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
+                        / PAGE_SIZE) + ylines;
+       instructions += 2;
+       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
+               return rc;
+
+       /* sync instruction */
+       rp = risc->cpu;
+       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
+       *(rp++) = cpu_to_le32(0);
+
+       /* scan lines */
+       ysg = sglist;
+       usg = sglist;
+       vsg = sglist;
+       for (line = 0; line < ylines; line++) {
+               if ((btv->opt_vcr_hack) &&
+                   (line >= (ylines - VCR_HACK_LINES)))
+                       continue;
+               switch (vshift) {
+               case 0:
+                       chroma = 1;
+                       break;
+               case 1:
+                       if (topfield)
+                               chroma = ((line & 1) == 0);
+                       else
+                               chroma = ((line & 1) == 1);
+                       break;
+               case 2:
+                       if (topfield)
+                               chroma = ((line & 3) == 0);
+                       else
+                               chroma = ((line & 3) == 2);
+                       break;
+               default:
+                       chroma = 0;
+                       break;
+               }
+
+               for (todo = ybpl; todo > 0; todo -= ylen) {
+                       /* go to next sg entry if needed */
+                       while (yoffset && yoffset >= sg_dma_len(ysg)) {
+                               yoffset -= sg_dma_len(ysg);
+                               ysg++;
+                       }
+                       while (uoffset && uoffset >= sg_dma_len(usg)) {
+                               uoffset -= sg_dma_len(usg);
+                               usg++;
+                       }
+                       while (voffset && voffset >= sg_dma_len(vsg)) {
+                               voffset -= sg_dma_len(vsg);
+                               vsg++;
+                       }
+
+                       /* calculate max number of bytes we can write */
+                       ylen = todo;
+                       if (yoffset + ylen > sg_dma_len(ysg))
+                               ylen = sg_dma_len(ysg) - yoffset;
+                       if (chroma) {
+                               if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
+                                       ylen = (sg_dma_len(usg) - uoffset) << hshift;
+                               if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
+                                       ylen = (sg_dma_len(vsg) - voffset) << hshift;
+                               ri = BT848_RISC_WRITE123;
+                       } else {
+                               ri = BT848_RISC_WRITE1S23;
+                       }
+                       if (ybpl == todo)
+                               ri |= BT848_RISC_SOL;
+                       if (ylen == todo)
+                               ri |= BT848_RISC_EOL;
+
+                       /* write risc instruction */
+                       *(rp++)=cpu_to_le32(ri | ylen);
+                       *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
+                                           (ylen >> hshift));
+                       *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
+                       yoffset += ylen;
+                       if (chroma) {
+                               *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
+                               uoffset += ylen >> hshift;
+                               *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
+                               voffset += ylen >> hshift;
+                       }
+               }
+               yoffset += ypadding;
+               if (chroma) {
+                       uoffset += cpadding;
+                       voffset += cpadding;
+               }
+       }
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+
+static int
+bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
+                 const struct bttv_format *fmt, struct bttv_overlay *ov,
+                 int skip_even, int skip_odd)
+{
+       int dwords, rc, line, maxy, start, end;
+       unsigned skip, nskips;
+       struct btcx_skiplist *skips;
+       __le32 *rp;
+       u32 ri,ra;
+       u32 addr;
+
+       /* skip list for window clipping */
+       if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
+               return -ENOMEM;
+
+       /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
+          + sync + jump (all 2 dwords) */
+       dwords  = (3 * ov->nclips + 2) *
+               ((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
+       dwords += 4;
+       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
+               kfree(skips);
+               return rc;
+       }
+
+       /* sync instruction */
+       rp = risc->cpu;
+       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+       *(rp++) = cpu_to_le32(0);
+
+       addr  = (unsigned long)btv->fbuf.base;
+       addr += btv->fbuf.fmt.bytesperline * ov->w.top;
+       addr += (fmt->depth >> 3)          * ov->w.left;
+
+       /* scan lines */
+       for (maxy = -1, line = 0; line < ov->w.height;
+            line++, addr += btv->fbuf.fmt.bytesperline) {
+               if ((btv->opt_vcr_hack) &&
+                    (line >= (ov->w.height - VCR_HACK_LINES)))
+                       continue;
+               if ((line%2) == 0  &&  skip_even)
+                       continue;
+               if ((line%2) == 1  &&  skip_odd)
+                       continue;
+
+               /* calculate clipping */
+               if (line > maxy)
+                       btcx_calc_skips(line, ov->w.width, &maxy,
+                                       skips, &nskips, ov->clips, ov->nclips);
+
+               /* write out risc code */
+               for (start = 0, skip = 0; start < ov->w.width; start = end) {
+                       if (skip >= nskips) {
+                               ri  = BT848_RISC_WRITE;
+                               end = ov->w.width;
+                       } else if (start < skips[skip].start) {
+                               ri  = BT848_RISC_WRITE;
+                               end = skips[skip].start;
+                       } else {
+                               ri  = BT848_RISC_SKIP;
+                               end = skips[skip].end;
+                               skip++;
+                       }
+                       if (BT848_RISC_WRITE == ri)
+                               ra = addr + (fmt->depth>>3)*start;
+                       else
+                               ra = 0;
+
+                       if (0 == start)
+                               ri |= BT848_RISC_SOL;
+                       if (ov->w.width == end)
+                               ri |= BT848_RISC_EOL;
+                       ri |= (fmt->depth>>3) * (end-start);
+
+                       *(rp++)=cpu_to_le32(ri);
+                       if (0 != ra)
+                               *(rp++)=cpu_to_le32(ra);
+               }
+       }
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       kfree(skips);
+       return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+static void
+bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
+                 int width, int height, int interleaved,
+                 const struct bttv_tvnorm *tvnorm)
+{
+       u32 xsf, sr;
+       int vdelay;
+
+       int swidth       = tvnorm->swidth;
+       int totalwidth   = tvnorm->totalwidth;
+       int scaledtwidth = tvnorm->scaledtwidth;
+
+       if (btv->input == btv->dig) {
+               swidth       = 720;
+               totalwidth   = 858;
+               scaledtwidth = 858;
+       }
+
+       vdelay = tvnorm->vdelay;
+
+       xsf = (width*scaledtwidth)/swidth;
+       geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
+       geo->hdelay =  tvnorm->hdelayx1;
+       geo->hdelay =  (geo->hdelay*width)/swidth;
+       geo->hdelay &= 0x3fe;
+       sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
+       geo->vscale =  (0x10000UL-sr) & 0x1fff;
+       geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
+               ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
+       geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
+       geo->vdelay  =  vdelay;
+       geo->width   =  width;
+       geo->sheight =  tvnorm->sheight;
+       geo->vtotal  =  tvnorm->vtotal;
+
+       if (btv->opt_combfilter) {
+               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+               geo->comb = (width < 769) ? 1 : 0;
+       } else {
+               geo->vtc  = 0;
+               geo->comb = 0;
+       }
+}
+
+static void
+bttv_calc_geo          (struct bttv *                  btv,
+                        struct bttv_geometry *         geo,
+                        unsigned int                   width,
+                        unsigned int                   height,
+                        int                            both_fields,
+                        const struct bttv_tvnorm *     tvnorm,
+                        const struct v4l2_rect *       crop)
+{
+       unsigned int c_width;
+       unsigned int c_height;
+       u32 sr;
+
+       if ((crop->left == tvnorm->cropcap.defrect.left
+            && crop->top == tvnorm->cropcap.defrect.top
+            && crop->width == tvnorm->cropcap.defrect.width
+            && crop->height == tvnorm->cropcap.defrect.height
+            && width <= tvnorm->swidth /* see PAL-Nc et al */)
+           || btv->input == btv->dig) {
+               bttv_calc_geo_old(btv, geo, width, height,
+                                 both_fields, tvnorm);
+               return;
+       }
+
+       /* For bug compatibility the image size checks permit scale
+          factors > 16. See bttv_crop_calc_limits(). */
+       c_width = min((unsigned int) crop->width, width * 16);
+       c_height = min((unsigned int) crop->height, height * 16);
+
+       geo->width = width;
+       geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
+       /* Even to store Cb first, odd for Cr. */
+       geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
+
+       geo->sheight = c_height;
+       geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
+       sr = c_height >> !both_fields;
+       sr = (sr * 512U + (height >> 1)) / height - 512;
+       geo->vscale = (0x10000UL - sr) & 0x1fff;
+       geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
+       geo->vtotal = tvnorm->vtotal;
+
+       geo->crop = (((geo->width   >> 8) & 0x03) |
+                    ((geo->hdelay  >> 6) & 0x0c) |
+                    ((geo->sheight >> 4) & 0x30) |
+                    ((geo->vdelay  >> 2) & 0xc0));
+
+       if (btv->opt_combfilter) {
+               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+               geo->comb = (width < 769) ? 1 : 0;
+       } else {
+               geo->vtc  = 0;
+               geo->comb = 0;
+       }
+}
+
+static void
+bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
+{
+       int off = odd ? 0x80 : 0x00;
+
+       if (geo->comb)
+               btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
+       else
+               btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
+
+       btwrite(geo->vtc,             BT848_E_VTC+off);
+       btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
+       btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
+       btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
+       btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
+       btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
+       btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
+       btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
+       btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
+       btwrite(geo->crop,            BT848_E_CROP+off);
+       btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
+       btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
+}
+
+/* ---------------------------------------------------------- */
+/* risc group / risc main loop / dma management               */
+
+void
+bttv_set_dma(struct bttv *btv, int override)
+{
+       unsigned long cmd;
+       int capctl;
+
+       btv->cap_ctl = 0;
+       if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
+       if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
+       if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
+
+       capctl  = 0;
+       capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
+       capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
+       capctl |= override;
+
+       d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
+                btv->c.nr,capctl,btv->loop_irq,
+                btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
+                btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
+                btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
+                btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
+
+       cmd = BT848_RISC_JUMP;
+       if (btv->loop_irq) {
+               cmd |= BT848_RISC_IRQ;
+               cmd |= (btv->loop_irq  & 0x0f) << 16;
+               cmd |= (~btv->loop_irq & 0x0f) << 20;
+       }
+       if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
+               mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
+       } else {
+               del_timer(&btv->timeout);
+       }
+       btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
+
+       btaor(capctl, ~0x0f, BT848_CAP_CTL);
+       if (capctl) {
+               if (btv->dma_on)
+                       return;
+               btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
+               btor(3, BT848_GPIO_DMA_CTL);
+               btv->dma_on = 1;
+       } else {
+               if (!btv->dma_on)
+                       return;
+               btand(~3, BT848_GPIO_DMA_CTL);
+               btv->dma_on = 0;
+       }
+       return;
+}
+
+int
+bttv_risc_init_main(struct bttv *btv)
+{
+       int rc;
+
+       if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
+               return rc;
+       dprintk("%d: risc main @ %08llx\n",
+               btv->c.nr, (unsigned long long)btv->main.dma);
+
+       btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
+                                      BT848_FIFO_STATUS_VRE);
+       btv->main.cpu[1] = cpu_to_le32(0);
+       btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
+
+       /* top field */
+       btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
+       btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
+
+       btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
+                                      BT848_FIFO_STATUS_VRO);
+       btv->main.cpu[9] = cpu_to_le32(0);
+
+       /* bottom field */
+       btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
+       btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
+
+       /* jump back to top field */
+       btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
+
+       return 0;
+}
+
+int
+bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
+              int irqflags)
+{
+       unsigned long cmd;
+       unsigned long next = btv->main.dma + ((slot+2) << 2);
+
+       if (NULL == risc) {
+               d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
+               btv->main.cpu[slot+1] = cpu_to_le32(next);
+       } else {
+               d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+                        btv->c.nr, risc, slot,
+                        (unsigned long long)risc->dma, irqflags);
+               cmd = BT848_RISC_JUMP;
+               if (irqflags) {
+                       cmd |= BT848_RISC_IRQ;
+                       cmd |= (irqflags  & 0x0f) << 16;
+                       cmd |= (~irqflags & 0x0f) << 20;
+               }
+               risc->jmp[0] = cpu_to_le32(cmd);
+               risc->jmp[1] = cpu_to_le32(next);
+               btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
+       }
+       return 0;
+}
+
+void
+bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
+{
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+       BUG_ON(in_interrupt());
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_dma_unmap(q->dev, dma);
+       videobuf_dma_free(dma);
+       btcx_riscmem_free(btv->c.pci,&buf->bottom);
+       btcx_riscmem_free(btv->c.pci,&buf->top);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+int
+bttv_buffer_activate_vbi(struct bttv *btv,
+                        struct bttv_buffer *vbi)
+{
+       struct btcx_riscmem *top;
+       struct btcx_riscmem *bottom;
+       int top_irq_flags;
+       int bottom_irq_flags;
+
+       top = NULL;
+       bottom = NULL;
+       top_irq_flags = 0;
+       bottom_irq_flags = 0;
+
+       if (vbi) {
+               unsigned int crop, vdelay;
+
+               vbi->vb.state = VIDEOBUF_ACTIVE;
+               list_del(&vbi->vb.queue);
+
+               /* VDELAY is start of video, end of VBI capturing. */
+               crop = btread(BT848_E_CROP);
+               vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
+
+               if (vbi->geo.vdelay > vdelay) {
+                       vdelay = vbi->geo.vdelay & 0xfe;
+                       crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
+
+                       btwrite(vdelay, BT848_E_VDELAY_LO);
+                       btwrite(crop,   BT848_E_CROP);
+                       btwrite(vdelay, BT848_O_VDELAY_LO);
+                       btwrite(crop,   BT848_O_CROP);
+               }
+
+               if (vbi->vbi_count[0] > 0) {
+                       top = &vbi->top;
+                       top_irq_flags = 4;
+               }
+
+               if (vbi->vbi_count[1] > 0) {
+                       top_irq_flags = 0;
+                       bottom = &vbi->bottom;
+                       bottom_irq_flags = 4;
+               }
+       }
+
+       bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
+       bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
+
+       return 0;
+}
+
+int
+bttv_buffer_activate_video(struct bttv *btv,
+                          struct bttv_buffer_set *set)
+{
+       /* video capture */
+       if (NULL != set->top  &&  NULL != set->bottom) {
+               if (set->top == set->bottom) {
+                       set->top->vb.state    = VIDEOBUF_ACTIVE;
+                       if (set->top->vb.queue.next)
+                               list_del(&set->top->vb.queue);
+               } else {
+                       set->top->vb.state    = VIDEOBUF_ACTIVE;
+                       set->bottom->vb.state = VIDEOBUF_ACTIVE;
+                       if (set->top->vb.queue.next)
+                               list_del(&set->top->vb.queue);
+                       if (set->bottom->vb.queue.next)
+                               list_del(&set->bottom->vb.queue);
+               }
+               bttv_apply_geo(btv, &set->top->geo, 1);
+               bttv_apply_geo(btv, &set->bottom->geo,0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+                              set->top_irq);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+                              set->frame_irq);
+               btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
+                     ~0xff, BT848_COLOR_FMT);
+               btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
+                     ~0x0f, BT848_COLOR_CTL);
+       } else if (NULL != set->top) {
+               set->top->vb.state  = VIDEOBUF_ACTIVE;
+               if (set->top->vb.queue.next)
+                       list_del(&set->top->vb.queue);
+               bttv_apply_geo(btv, &set->top->geo,1);
+               bttv_apply_geo(btv, &set->top->geo,0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+                              set->frame_irq);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
+               btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+               btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
+       } else if (NULL != set->bottom) {
+               set->bottom->vb.state = VIDEOBUF_ACTIVE;
+               if (set->bottom->vb.queue.next)
+                       list_del(&set->bottom->vb.queue);
+               bttv_apply_geo(btv, &set->bottom->geo,1);
+               bttv_apply_geo(btv, &set->bottom->geo,0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+                              set->frame_irq);
+               btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+               btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
+       } else {
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
+       }
+       return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+/* calculate geometry, build risc code */
+int
+bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
+{
+       const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+       dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
+               btv->c.nr, v4l2_field_names[buf->vb.field],
+               buf->fmt->name, buf->vb.width, buf->vb.height);
+
+       /* packed pixel modes */
+       if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
+               int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
+               int bpf = bpl * (buf->vb.height >> 1);
+
+               bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
+                             V4L2_FIELD_HAS_BOTH(buf->vb.field),
+                             tvnorm,&buf->crop);
+
+               switch (buf->vb.field) {
+               case V4L2_FIELD_TOP:
+                       bttv_risc_packed(btv,&buf->top,dma->sglist,
+                                        /* offset */ 0,bpl,
+                                        /* padding */ 0,/* skip_lines */ 0,
+                                        buf->vb.height);
+                       break;
+               case V4L2_FIELD_BOTTOM:
+                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+                                        0,bpl,0,0,buf->vb.height);
+                       break;
+               case V4L2_FIELD_INTERLACED:
+                       bttv_risc_packed(btv,&buf->top,dma->sglist,
+                                        0,bpl,bpl,0,buf->vb.height >> 1);
+                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+                                        bpl,bpl,bpl,0,buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_TB:
+                       bttv_risc_packed(btv,&buf->top,dma->sglist,
+                                        0,bpl,0,0,buf->vb.height >> 1);
+                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+                                        bpf,bpl,0,0,buf->vb.height >> 1);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       /* planar modes */
+       if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
+               int uoffset, voffset;
+               int ypadding, cpadding, lines;
+
+               /* calculate chroma offsets */
+               uoffset = buf->vb.width * buf->vb.height;
+               voffset = buf->vb.width * buf->vb.height;
+               if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
+                       /* Y-Cr-Cb plane order */
+                       uoffset >>= buf->fmt->hshift;
+                       uoffset >>= buf->fmt->vshift;
+                       uoffset  += voffset;
+               } else {
+                       /* Y-Cb-Cr plane order */
+                       voffset >>= buf->fmt->hshift;
+                       voffset >>= buf->fmt->vshift;
+                       voffset  += uoffset;
+               }
+
+               switch (buf->vb.field) {
+               case V4L2_FIELD_TOP:
+                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+                                     buf->vb.height,/* both_fields */ 0,
+                                     tvnorm,&buf->crop);
+                       bttv_risc_planar(btv, &buf->top, dma->sglist,
+                                        0,buf->vb.width,0,buf->vb.height,
+                                        uoffset,voffset,buf->fmt->hshift,
+                                        buf->fmt->vshift,0);
+                       break;
+               case V4L2_FIELD_BOTTOM:
+                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+                                     buf->vb.height,0,
+                                     tvnorm,&buf->crop);
+                       bttv_risc_planar(btv, &buf->bottom, dma->sglist,
+                                        0,buf->vb.width,0,buf->vb.height,
+                                        uoffset,voffset,buf->fmt->hshift,
+                                        buf->fmt->vshift,0);
+                       break;
+               case V4L2_FIELD_INTERLACED:
+                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+                                     buf->vb.height,1,
+                                     tvnorm,&buf->crop);
+                       lines    = buf->vb.height >> 1;
+                       ypadding = buf->vb.width;
+                       cpadding = buf->vb.width >> buf->fmt->hshift;
+                       bttv_risc_planar(btv,&buf->top,
+                                        dma->sglist,
+                                        0,buf->vb.width,ypadding,lines,
+                                        uoffset,voffset,
+                                        buf->fmt->hshift,
+                                        buf->fmt->vshift,
+                                        cpadding);
+                       bttv_risc_planar(btv,&buf->bottom,
+                                        dma->sglist,
+                                        ypadding,buf->vb.width,ypadding,lines,
+                                        uoffset+cpadding,
+                                        voffset+cpadding,
+                                        buf->fmt->hshift,
+                                        buf->fmt->vshift,
+                                        cpadding);
+                       break;
+               case V4L2_FIELD_SEQ_TB:
+                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+                                     buf->vb.height,1,
+                                     tvnorm,&buf->crop);
+                       lines    = buf->vb.height >> 1;
+                       ypadding = buf->vb.width;
+                       cpadding = buf->vb.width >> buf->fmt->hshift;
+                       bttv_risc_planar(btv,&buf->top,
+                                        dma->sglist,
+                                        0,buf->vb.width,0,lines,
+                                        uoffset >> 1,
+                                        voffset >> 1,
+                                        buf->fmt->hshift,
+                                        buf->fmt->vshift,
+                                        0);
+                       bttv_risc_planar(btv,&buf->bottom,
+                                        dma->sglist,
+                                        lines * ypadding,buf->vb.width,0,lines,
+                                        lines * ypadding + (uoffset >> 1),
+                                        lines * ypadding + (voffset >> 1),
+                                        buf->fmt->hshift,
+                                        buf->fmt->vshift,
+                                        0);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       /* raw data */
+       if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
+               /* build risc code */
+               buf->vb.field = V4L2_FIELD_SEQ_TB;
+               bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
+                             1,tvnorm,&buf->crop);
+               bttv_risc_packed(btv, &buf->top,  dma->sglist,
+                                /* offset */ 0, RAW_BPL, /* padding */ 0,
+                                /* skip_lines */ 0, RAW_LINES);
+               bttv_risc_packed(btv, &buf->bottom, dma->sglist,
+                                buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
+       }
+
+       /* copy format info */
+       buf->btformat = buf->fmt->btformat;
+       buf->btswap   = buf->fmt->btswap;
+       return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+/* calculate geometry, build risc code */
+int
+bttv_overlay_risc(struct bttv *btv,
+                 struct bttv_overlay *ov,
+                 const struct bttv_format *fmt,
+                 struct bttv_buffer *buf)
+{
+       /* check interleave, bottom+top fields */
+       dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
+               btv->c.nr, v4l2_field_names[buf->vb.field],
+               fmt->name, ov->w.width, ov->w.height);
+
+       /* calculate geometry */
+       bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
+                     V4L2_FIELD_HAS_BOTH(ov->field),
+                     &bttv_tvnorms[ov->tvnorm],&buf->crop);
+
+       /* build risc code */
+       switch (ov->field) {
+       case V4L2_FIELD_TOP:
+               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
+               break;
+       case V4L2_FIELD_BOTTOM:
+               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
+               break;
+       case V4L2_FIELD_INTERLACED:
+               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
+               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
+               break;
+       default:
+               BUG();
+       }
+
+       /* copy format info */
+       buf->btformat = fmt->btformat;
+       buf->btswap   = fmt->btswap;
+       buf->vb.field = ov->field;
+       return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c
new file mode 100644 (file)
index 0000000..b433267
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+    vbi interface
+
+    (c) 2002 Gerd Knorr <kraxel@bytesex.org>
+
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <media/v4l2-ioctl.h>
+#include <asm/io.h>
+#include "bttvp.h"
+
+/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
+   in fCLKx2 pixels.  According to the datasheet, VBI capture starts
+   VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
+   is 64 fCLKx1 pixels wide.  VBI_HDELAY is set to 0, so this should be
+   (64 + 0) * 2 = 128 fCLKx2 pixels.  But it's not!  The datasheet is
+   Just Plain Wrong.  The real value appears to be different for
+   different revisions of the bt8x8 chips, and to be affected by the
+   horizontal scaling factor.  Experimentally, the value is measured
+   to be about 244.  */
+#define VBI_OFFSET 244
+
+/* 2048 for compatibility with earlier driver versions. The driver
+   really stores 1024 + tvnorm->vbipack * 4 samples per line in the
+   buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
+   is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
+   four bytes of the VBI image. */
+#define VBI_BPL 2048
+
+/* Compatibility. */
+#define VBI_DEFLINES 16
+
+static unsigned int vbibufs = 4;
+static unsigned int vbi_debug;
+
+module_param(vbibufs,   int, 0444);
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4");
+MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
+
+#ifdef dprintk
+# undef dprintk
+#endif
+#define dprintk(fmt, ...)                                              \
+do {                                                                   \
+       if (vbi_debug)                                                  \
+               pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);         \
+} while (0)
+
+#define IMAGE_SIZE(fmt) \
+       (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
+
+/* ----------------------------------------------------------------------- */
+/* vbi risc code + mm                                                      */
+
+static int vbi_buffer_setup(struct videobuf_queue *q,
+                           unsigned int *count, unsigned int *size)
+{
+       struct bttv_fh *fh = q->priv_data;
+       struct bttv *btv = fh->btv;
+
+       if (0 == *count)
+               *count = vbibufs;
+
+       *size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+
+       dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
+               fh->vbi_fmt.fmt.samples_per_line,
+               fh->vbi_fmt.fmt.start[0],
+               fh->vbi_fmt.fmt.start[1],
+               fh->vbi_fmt.fmt.count[0],
+               fh->vbi_fmt.fmt.count[1]);
+
+       return 0;
+}
+
+static int vbi_buffer_prepare(struct videobuf_queue *q,
+                             struct videobuf_buffer *vb,
+                             enum v4l2_field field)
+{
+       struct bttv_fh *fh = q->priv_data;
+       struct bttv *btv = fh->btv;
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+       const struct bttv_tvnorm *tvnorm;
+       unsigned int skip_lines0, skip_lines1, min_vdelay;
+       int redo_dma_risc;
+       int rc;
+
+       buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       tvnorm = fh->vbi_fmt.tvnorm;
+
+       /* There's no VBI_VDELAY register, RISC must skip the lines
+          we don't want. With default parameters we skip zero lines
+          as earlier driver versions did. The driver permits video
+          standard changes while capturing, so we use vbi_fmt.tvnorm
+          instead of btv->tvnorm to skip zero lines after video
+          standard changes as well. */
+
+       skip_lines0 = 0;
+       skip_lines1 = 0;
+
+       if (fh->vbi_fmt.fmt.count[0] > 0)
+               skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
+                                     - tvnorm->vbistart[0]));
+       if (fh->vbi_fmt.fmt.count[1] > 0)
+               skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
+                                     - tvnorm->vbistart[1]));
+
+       redo_dma_risc = 0;
+
+       if (buf->vbi_skip[0] != skip_lines0 ||
+           buf->vbi_skip[1] != skip_lines1 ||
+           buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
+           buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
+               buf->vbi_skip[0] = skip_lines0;
+               buf->vbi_skip[1] = skip_lines1;
+               buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
+               buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
+               redo_dma_risc = 1;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               redo_dma_risc = 1;
+               if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+                       goto fail;
+       }
+
+       if (redo_dma_risc) {
+               unsigned int bpl, padding, offset;
+               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+               bpl = 2044; /* max. vbipack */
+               padding = VBI_BPL - bpl;
+
+               if (fh->vbi_fmt.fmt.count[0] > 0) {
+                       rc = bttv_risc_packed(btv, &buf->top,
+                                             dma->sglist,
+                                             /* offset */ 0, bpl,
+                                             padding, skip_lines0,
+                                             fh->vbi_fmt.fmt.count[0]);
+                       if (0 != rc)
+                               goto fail;
+               }
+
+               if (fh->vbi_fmt.fmt.count[1] > 0) {
+                       offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
+
+                       rc = bttv_risc_packed(btv, &buf->bottom,
+                                             dma->sglist,
+                                             offset, bpl,
+                                             padding, skip_lines1,
+                                             fh->vbi_fmt.fmt.count[1]);
+                       if (0 != rc)
+                               goto fail;
+               }
+       }
+
+       /* VBI capturing ends at VDELAY, start of video capturing,
+          no matter where the RISC program ends. VDELAY minimum is 2,
+          bounds.top is the corresponding first field line number
+          times two. VDELAY counts half field lines. */
+       min_vdelay = MIN_VDELAY;
+       if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
+               min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
+
+       /* For bttv_buffer_activate_vbi(). */
+       buf->geo.vdelay = min_vdelay;
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       buf->vb.field = field;
+       dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
+               vb, &buf->top, &buf->bottom,
+               v4l2_field_names[buf->vb.field]);
+       return 0;
+
+ fail:
+       bttv_dma_free(q,btv,buf);
+       return rc;
+}
+
+static void
+vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct bttv_fh *fh = q->priv_data;
+       struct bttv *btv = fh->btv;
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+
+       dprintk("queue %p\n",vb);
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue,&btv->vcapture);
+       if (NULL == btv->cvbi) {
+               fh->btv->loop_irq |= 4;
+               bttv_set_dma(btv,0x0c);
+       }
+}
+
+static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct bttv_fh *fh = q->priv_data;
+       struct bttv *btv = fh->btv;
+       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+
+       dprintk("free %p\n",vb);
+       bttv_dma_free(q,fh->btv,buf);
+}
+
+struct videobuf_queue_ops bttv_vbi_qops = {
+       .buf_setup    = vbi_buffer_setup,
+       .buf_prepare  = vbi_buffer_prepare,
+       .buf_queue    = vbi_buffer_queue,
+       .buf_release  = vbi_buffer_release,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
+                       __s32 crop_start)
+{
+       __s32 min_start, max_start, max_end, f2_offset;
+       unsigned int i;
+
+       /* For compatibility with earlier driver versions we must pretend
+          the VBI and video capture window may overlap. In reality RISC
+          magic aborts VBI capturing at the first line of video capturing,
+          leaving the rest of the buffer unchanged, usually all zero.
+          VBI capturing must always start before video capturing. >> 1
+          because cropping counts field lines times two. */
+       min_start = tvnorm->vbistart[0];
+       max_start = (crop_start >> 1) - 1;
+       max_end = (tvnorm->cropcap.bounds.top
+                  + tvnorm->cropcap.bounds.height) >> 1;
+
+       if (min_start > max_start)
+               return -EBUSY;
+
+       BUG_ON(max_start >= max_end);
+
+       f->sampling_rate    = tvnorm->Fsc;
+       f->samples_per_line = VBI_BPL;
+       f->sample_format    = V4L2_PIX_FMT_GREY;
+       f->offset           = VBI_OFFSET;
+
+       f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
+
+       for (i = 0; i < 2; ++i) {
+               if (0 == f->count[i]) {
+                       /* No data from this field. We leave f->start[i]
+                          alone because VIDIOCSVBIFMT is w/o and EINVALs
+                          when a driver does not support exactly the
+                          requested parameters. */
+               } else {
+                       s64 start, count;
+
+                       start = clamp(f->start[i], min_start, max_start);
+                       /* s64 to prevent overflow. */
+                       count = (s64) f->start[i] + f->count[i] - start;
+                       f->start[i] = start;
+                       f->count[i] = clamp(count, (s64) 1,
+                                           max_end - start);
+               }
+
+               min_start += f2_offset;
+               max_start += f2_offset;
+               max_end += f2_offset;
+       }
+
+       if (0 == (f->count[0] | f->count[1])) {
+               /* As in earlier driver versions. */
+               f->start[0] = tvnorm->vbistart[0];
+               f->start[1] = tvnorm->vbistart[1];
+               f->count[0] = 1;
+               f->count[1] = 1;
+       }
+
+       f->flags = 0;
+
+       f->reserved[0] = 0;
+       f->reserved[1] = 0;
+
+       return 0;
+}
+
+int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       const struct bttv_tvnorm *tvnorm;
+       __s32 crop_start;
+
+       mutex_lock(&btv->lock);
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+       crop_start = btv->crop_start;
+
+       mutex_unlock(&btv->lock);
+
+       return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
+}
+
+
+int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+       struct bttv_fh *fh = f;
+       struct bttv *btv = fh->btv;
+       const struct bttv_tvnorm *tvnorm;
+       __s32 start1, end;
+       int rc;
+
+       mutex_lock(&btv->lock);
+
+       rc = -EBUSY;
+       if (fh->resources & RESOURCE_VBI)
+               goto fail;
+
+       tvnorm = &bttv_tvnorms[btv->tvnorm];
+
+       rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
+       if (0 != rc)
+               goto fail;
+
+       start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
+               tvnorm->vbistart[0];
+
+       /* First possible line of video capturing. Should be
+          max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
+          when capturing both fields. But for compatibility we must
+          pretend the VBI and video capture window may overlap,
+          so end = start + 1, the lowest possible value, times two
+          because vbi_fmt.end counts field lines times two. */
+       end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
+
+       mutex_lock(&fh->vbi.vb_lock);
+
+       fh->vbi_fmt.fmt    = frt->fmt.vbi;
+       fh->vbi_fmt.tvnorm = tvnorm;
+       fh->vbi_fmt.end    = end;
+
+       mutex_unlock(&fh->vbi.vb_lock);
+
+       rc = 0;
+
+ fail:
+       mutex_unlock(&btv->lock);
+
+       return rc;
+}
+
+
+int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+       struct bttv_fh *fh = f;
+       const struct bttv_tvnorm *tvnorm;
+
+       frt->fmt.vbi = fh->vbi_fmt.fmt;
+
+       tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
+
+       if (tvnorm != fh->vbi_fmt.tvnorm) {
+               __s32 max_end;
+               unsigned int i;
+
+               /* As in vbi_buffer_prepare() this imitates the
+                  behaviour of earlier driver versions after video
+                  standard changes, with default parameters anyway. */
+
+               max_end = (tvnorm->cropcap.bounds.top
+                          + tvnorm->cropcap.bounds.height) >> 1;
+
+               frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
+
+               for (i = 0; i < 2; ++i) {
+                       __s32 new_start;
+
+                       new_start = frt->fmt.vbi.start[i]
+                               + tvnorm->vbistart[i]
+                               - fh->vbi_fmt.tvnorm->vbistart[i];
+
+                       frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
+                       frt->fmt.vbi.count[i] =
+                               min((__s32) frt->fmt.vbi.count[i],
+                                         max_end - frt->fmt.vbi.start[i]);
+
+                       max_end += tvnorm->vbistart[1]
+                               - tvnorm->vbistart[0];
+               }
+       }
+       return 0;
+}
+
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
+{
+       const struct bttv_tvnorm *tvnorm;
+       unsigned int real_samples_per_line;
+       unsigned int real_count;
+
+       tvnorm = &bttv_tvnorms[norm];
+
+       f->fmt.sampling_rate    = tvnorm->Fsc;
+       f->fmt.samples_per_line = VBI_BPL;
+       f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
+       f->fmt.offset           = VBI_OFFSET;
+       f->fmt.start[0]         = tvnorm->vbistart[0];
+       f->fmt.start[1]         = tvnorm->vbistart[1];
+       f->fmt.count[0]         = VBI_DEFLINES;
+       f->fmt.count[1]         = VBI_DEFLINES;
+       f->fmt.flags            = 0;
+       f->fmt.reserved[0]      = 0;
+       f->fmt.reserved[1]      = 0;
+
+       /* For compatibility the buffer size must be 2 * VBI_DEFLINES *
+          VBI_BPL regardless of the current video standard. */
+       real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
+       real_count              = ((tvnorm->cropcap.defrect.top >> 1)
+                                  - tvnorm->vbistart[0]);
+
+       BUG_ON(real_samples_per_line > VBI_BPL);
+       BUG_ON(real_count > VBI_DEFLINES);
+
+       f->tvnorm               = tvnorm;
+
+       /* See bttv_vbi_fmt_set(). */
+       f->end                  = tvnorm->vbistart[0] * 2 + 2;
+}
+
+/* ----------------------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
new file mode 100644 (file)
index 0000000..79a1124
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ *
+ *  bttv - Bt848 frame grabber driver
+ *
+ *  card ID's and external interfaces of the bttv driver
+ *  basically stuff needed by other drivers (i2c, lirc, ...)
+ *  and is supported not to change much over time.
+ *
+ *  Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
+ *  (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#ifndef _BTTV_H_
+#define _BTTV_H_
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/i2c-addr.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------- */
+/* exported by bttv-cards.c                                   */
+
+#define BTTV_BOARD_UNKNOWN                 0x00
+#define BTTV_BOARD_MIRO                    0x01
+#define BTTV_BOARD_HAUPPAUGE               0x02
+#define BTTV_BOARD_STB                     0x03
+#define BTTV_BOARD_INTEL                   0x04
+#define BTTV_BOARD_DIAMOND                 0x05
+#define BTTV_BOARD_AVERMEDIA               0x06
+#define BTTV_BOARD_MATRIX_VISION           0x07
+#define BTTV_BOARD_FLYVIDEO                0x08
+#define BTTV_BOARD_TURBOTV                 0x09
+#define BTTV_BOARD_HAUPPAUGE878            0x0a
+#define BTTV_BOARD_MIROPRO                 0x0b
+#define BTTV_BOARD_ADSTECH_TV              0x0c
+#define BTTV_BOARD_AVERMEDIA98             0x0d
+#define BTTV_BOARD_VHX                     0x0e
+#define BTTV_BOARD_ZOLTRIX                 0x0f
+#define BTTV_BOARD_PIXVIEWPLAYTV           0x10
+#define BTTV_BOARD_WINVIEW_601             0x11
+#define BTTV_BOARD_AVEC_INTERCAP           0x12
+#define BTTV_BOARD_LIFE_FLYKIT             0x13
+#define BTTV_BOARD_CEI_RAFFLES             0x14
+#define BTTV_BOARD_CONFERENCETV            0x15
+#define BTTV_BOARD_PHOEBE_TVMAS            0x16
+#define BTTV_BOARD_MODTEC_205              0x17
+#define BTTV_BOARD_MAGICTVIEW061           0x18
+#define BTTV_BOARD_VOBIS_BOOSTAR           0x19
+#define BTTV_BOARD_HAUPPAUG_WCAM           0x1a
+#define BTTV_BOARD_MAXI                    0x1b
+#define BTTV_BOARD_TERRATV                 0x1c
+#define BTTV_BOARD_PXC200                  0x1d
+#define BTTV_BOARD_FLYVIDEO_98             0x1e
+#define BTTV_BOARD_IPROTV                  0x1f
+#define BTTV_BOARD_INTEL_C_S_PCI           0x20
+#define BTTV_BOARD_TERRATVALUE             0x21
+#define BTTV_BOARD_WINFAST2000             0x22
+#define BTTV_BOARD_CHRONOS_VS2             0x23
+#define BTTV_BOARD_TYPHOON_TVIEW           0x24
+#define BTTV_BOARD_PXELVWPLTVPRO           0x25
+#define BTTV_BOARD_MAGICTVIEW063           0x26
+#define BTTV_BOARD_PINNACLE                0x27
+#define BTTV_BOARD_STB2                    0x28
+#define BTTV_BOARD_AVPHONE98               0x29
+#define BTTV_BOARD_PV951                   0x2a
+#define BTTV_BOARD_ONAIR_TV                0x2b
+#define BTTV_BOARD_SIGMA_TVII_FM           0x2c
+#define BTTV_BOARD_MATRIX_VISION2          0x2d
+#define BTTV_BOARD_ZOLTRIX_GENIE           0x2e
+#define BTTV_BOARD_TERRATVRADIO            0x2f
+#define BTTV_BOARD_DYNALINK                0x30
+#define BTTV_BOARD_GVBCTV3PCI              0x31
+#define BTTV_BOARD_PXELVWPLTVPAK           0x32
+#define BTTV_BOARD_EAGLE                   0x33
+#define BTTV_BOARD_PINNACLEPRO             0x34
+#define BTTV_BOARD_TVIEW_RDS_FM            0x35
+#define BTTV_BOARD_LIFETEC_9415            0x36
+#define BTTV_BOARD_BESTBUY_EASYTV          0x37
+#define BTTV_BOARD_FLYVIDEO_98FM           0x38
+#define BTTV_BOARD_GRANDTEC                0x39
+#define BTTV_BOARD_ASKEY_CPH060            0x3a
+#define BTTV_BOARD_ASKEY_CPH03X            0x3b
+#define BTTV_BOARD_MM100PCTV               0x3c
+#define BTTV_BOARD_GMV1                    0x3d
+#define BTTV_BOARD_BESTBUY_EASYTV2         0x3e
+#define BTTV_BOARD_ATI_TVWONDER            0x3f
+#define BTTV_BOARD_ATI_TVWONDERVE          0x40
+#define BTTV_BOARD_FLYVIDEO2000            0x41
+#define BTTV_BOARD_TERRATVALUER            0x42
+#define BTTV_BOARD_GVBCTV4PCI              0x43
+#define BTTV_BOARD_VOODOOTV_FM             0x44
+#define BTTV_BOARD_AIMMS                   0x45
+#define BTTV_BOARD_PV_BT878P_PLUS          0x46
+#define BTTV_BOARD_FLYVIDEO98EZ            0x47
+#define BTTV_BOARD_PV_BT878P_9B            0x48
+#define BTTV_BOARD_SENSORAY311_611         0x49
+#define BTTV_BOARD_RV605                   0x4a
+#define BTTV_BOARD_POWERCLR_MTV878         0x4b
+#define BTTV_BOARD_WINDVR                  0x4c
+#define BTTV_BOARD_GRANDTEC_MULTI          0x4d
+#define BTTV_BOARD_KWORLD                  0x4e
+#define BTTV_BOARD_DSP_TCVIDEO             0x4f
+#define BTTV_BOARD_HAUPPAUGEPVR            0x50
+#define BTTV_BOARD_GVBCTV5PCI              0x51
+#define BTTV_BOARD_OSPREY1x0               0x52
+#define BTTV_BOARD_OSPREY1x0_848           0x53
+#define BTTV_BOARD_OSPREY101_848           0x54
+#define BTTV_BOARD_OSPREY1x1               0x55
+#define BTTV_BOARD_OSPREY1x1_SVID          0x56
+#define BTTV_BOARD_OSPREY2xx               0x57
+#define BTTV_BOARD_OSPREY2x0_SVID          0x58
+#define BTTV_BOARD_OSPREY2x0               0x59
+#define BTTV_BOARD_OSPREY500               0x5a
+#define BTTV_BOARD_OSPREY540               0x5b
+#define BTTV_BOARD_OSPREY2000              0x5c
+#define BTTV_BOARD_IDS_EAGLE               0x5d
+#define BTTV_BOARD_PINNACLESAT             0x5e
+#define BTTV_BOARD_FORMAC_PROTV            0x5f
+#define BTTV_BOARD_MACHTV                  0x60
+#define BTTV_BOARD_EURESYS_PICOLO          0x61
+#define BTTV_BOARD_PV150                   0x62
+#define BTTV_BOARD_AD_TVK503               0x63
+#define BTTV_BOARD_HERCULES_SM_TV          0x64
+#define BTTV_BOARD_PACETV                  0x65
+#define BTTV_BOARD_IVC200                  0x66
+#define BTTV_BOARD_XGUARD                  0x67
+#define BTTV_BOARD_NEBULA_DIGITV           0x68
+#define BTTV_BOARD_PV143                   0x69
+#define BTTV_BOARD_VD009X1_VD011_MINIDIN   0x6a
+#define BTTV_BOARD_VD009X1_VD011_COMBI     0x6b
+#define BTTV_BOARD_VD009_MINIDIN           0x6c
+#define BTTV_BOARD_VD009_COMBI             0x6d
+#define BTTV_BOARD_IVC100                  0x6e
+#define BTTV_BOARD_IVC120                  0x6f
+#define BTTV_BOARD_PC_HDTV                 0x70
+#define BTTV_BOARD_TWINHAN_DST             0x71
+#define BTTV_BOARD_WINFASTVC100            0x72
+#define BTTV_BOARD_TEV560                  0x73
+#define BTTV_BOARD_SIMUS_GVC1100           0x74
+#define BTTV_BOARD_NGSTV_PLUS              0x75
+#define BTTV_BOARD_LMLBT4                  0x76
+#define BTTV_BOARD_TEKRAM_M205             0x77
+#define BTTV_BOARD_CONTVFMI                0x78
+#define BTTV_BOARD_PICOLO_TETRA_CHIP       0x79
+#define BTTV_BOARD_SPIRIT_TV               0x7a
+#define BTTV_BOARD_AVDVBT_771              0x7b
+#define BTTV_BOARD_AVDVBT_761              0x7c
+#define BTTV_BOARD_MATRIX_VISIONSQ         0x7d
+#define BTTV_BOARD_MATRIX_VISIONSLC        0x7e
+#define BTTV_BOARD_APAC_VIEWCOMP           0x7f
+#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
+#define BTTV_BOARD_VGEAR_MYVCD             0x81
+#define BTTV_BOARD_SUPER_TV                0x82
+#define BTTV_BOARD_TIBET_CS16              0x83
+#define BTTV_BOARD_KODICOM_4400R           0x84
+#define BTTV_BOARD_KODICOM_4400R_SL        0x85
+#define BTTV_BOARD_ADLINK_RTV24            0x86
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+#define BTTV_BOARD_ACORP_Y878F             0x88
+#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2    0x89
+#define BTTV_BOARD_PV_BT878P_2E            0x8a
+#define BTTV_BOARD_PV_M4900                0x8b
+#define BTTV_BOARD_OSPREY440               0x8c
+#define BTTV_BOARD_ASOUND_SKYEYE          0x8d
+#define BTTV_BOARD_SABRENT_TVFM           0x8e
+#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB     0x8f
+#define BTTV_BOARD_MACHTV_MAGICTV          0x90
+#define BTTV_BOARD_SSAI_SECURITY          0x91
+#define BTTV_BOARD_SSAI_ULTRASOUND        0x92
+#define BTTV_BOARD_VOODOOTV_200                   0x93
+#define BTTV_BOARD_DVICO_FUSIONHDTV_2     0x94
+#define BTTV_BOARD_TYPHOON_TVTUNERPCI     0x95
+#define BTTV_BOARD_GEOVISION_GV600        0x96
+#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
+#define BTTV_BOARD_ENLTV_FM_2             0x98
+#define BTTV_BOARD_VD012                  0x99
+#define BTTV_BOARD_VD012_X1               0x9a
+#define BTTV_BOARD_VD012_X2               0x9b
+#define BTTV_BOARD_IVCE8784               0x9c
+#define BTTV_BOARD_GEOVISION_GV800S       0x9d
+#define BTTV_BOARD_GEOVISION_GV800S_SL    0x9e
+#define BTTV_BOARD_PV183                   0x9f
+#define BTTV_BOARD_TVT_TD3116             0xa0
+#define BTTV_BOARD_APOSONIC_WDVR           0xa1
+
+/* more card-specific defines */
+#define PT2254_L_CHANNEL 0x10
+#define PT2254_R_CHANNEL 0x08
+#define PT2254_DBS_IN_2 0x400
+#define PT2254_DBS_IN_10 0x20000
+#define WINVIEW_PT2254_CLK  0x40
+#define WINVIEW_PT2254_DATA 0x20
+#define WINVIEW_PT2254_STROBE 0x80
+
+struct bttv_core {
+       /* device structs */
+       struct v4l2_device   v4l2_dev;
+       struct pci_dev       *pci;
+       struct i2c_adapter   i2c_adap;
+       struct list_head     subs;     /* struct bttv_sub_device */
+
+       /* device config */
+       unsigned int         nr;       /* dev nr (for printk("bttv%d: ...");  */
+       unsigned int         type;     /* card type (pointer into tvcards[])  */
+};
+
+struct bttv;
+
+struct tvcard {
+       char *name;
+       void (*volume_gpio)(struct bttv *btv, __u16 volume);
+       void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+       void (*muxsel_hook)(struct bttv *btv, unsigned int input);
+
+       /* MUX bits for each input, two bits per input starting with the LSB */
+       u32 muxsel; /* Use MUXSEL() to set */
+
+       u32 gpiomask;
+       u32 gpiomux[4];  /* Tuner, Radio, external, internal */
+       u32 gpiomute;    /* GPIO mute setting */
+       u32 gpiomask2;   /* GPIO MUX mask */
+
+       unsigned int tuner_type;
+       u8 tuner_addr;
+       u8 video_inputs;        /* Number of inputs */
+       unsigned int svhs:4;    /* Which input is s-video */
+#define NO_SVHS        15
+       unsigned int pll:2;
+#define PLL_NONE 0
+#define PLL_28   1
+#define PLL_35   2
+
+       /* i2c audio flags */
+       unsigned int no_msp34xx:1;
+       unsigned int no_tda7432:1;
+       unsigned int msp34xx_alt:1;
+       /* Note: currently no card definition needs to mark the presence
+          of a RDS saa6588 chip. If this is ever needed, then add a new
+          'has_saa6588' bit here. */
+
+       unsigned int no_video:1; /* video pci function is unused */
+       unsigned int has_dvb:1;
+       unsigned int has_remote:1;
+       unsigned int has_radio:1;
+       unsigned int has_dig_in:1; /* Has digital input (always last input) */
+       unsigned int no_gpioirq:1;
+};
+
+extern struct tvcard bttv_tvcards[];
+
+/*
+ * This bit of cpp voodoo is used to create a macro with a variable number of
+ * arguments (1 to 16).  It will pack each argument into a word two bits at a
+ * time.  It can't be a function because it needs to be compile time constant to
+ * initialize structures.  Since each argument must fit in two bits, it's ok
+ * that they are changed to octal.  One should not use hex number, macros, or
+ * anything else with this macro.  Just use plain integers from 0 to 3.
+ */
+#define _MUXSELf(a)            0##a << 30
+#define _MUXSELe(a, b...)      0##a << 28 | _MUXSELf(b)
+#define _MUXSELd(a, b...)      0##a << 26 | _MUXSELe(b)
+#define _MUXSELc(a, b...)      0##a << 24 | _MUXSELd(b)
+#define _MUXSELb(a, b...)      0##a << 22 | _MUXSELc(b)
+#define _MUXSELa(a, b...)      0##a << 20 | _MUXSELb(b)
+#define _MUXSEL9(a, b...)      0##a << 18 | _MUXSELa(b)
+#define _MUXSEL8(a, b...)      0##a << 16 | _MUXSEL9(b)
+#define _MUXSEL7(a, b...)      0##a << 14 | _MUXSEL8(b)
+#define _MUXSEL6(a, b...)      0##a << 12 | _MUXSEL7(b)
+#define _MUXSEL5(a, b...)      0##a << 10 | _MUXSEL6(b)
+#define _MUXSEL4(a, b...)      0##a << 8  | _MUXSEL5(b)
+#define _MUXSEL3(a, b...)      0##a << 6  | _MUXSEL4(b)
+#define _MUXSEL2(a, b...)      0##a << 4  | _MUXSEL3(b)
+#define _MUXSEL1(a, b...)      0##a << 2  | _MUXSEL2(b)
+#define MUXSEL(a, b...)                (a | _MUXSEL1(b))
+
+/* identification / initialization of the card */
+extern void bttv_idcard(struct bttv *btv);
+extern void bttv_init_card1(struct bttv *btv);
+extern void bttv_init_card2(struct bttv *btv);
+extern void bttv_init_tuner(struct bttv *btv);
+
+/* card-specific funtions */
+extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
+extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits);
+
+/* extra tweaks for some chipsets */
+extern void bttv_check_chipset(void);
+extern int bttv_handle_chipset(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* exported by bttv-if.c                                      */
+
+/* this obsolete -- please use the sysfs-based
+   interface below for new code */
+
+extern struct pci_dev* bttv_get_pcidev(unsigned int card);
+
+/* sets GPOE register (BT848_GPIO_OUT_EN) to new value:
+   data | (current_GPOE_value & ~mask)
+   returns negative value if error occurred
+*/
+extern int bttv_gpio_enable(unsigned int card,
+                           unsigned long mask, unsigned long data);
+
+/* fills data with GPDATA register contents
+   returns negative value if error occurred
+*/
+extern int bttv_read_gpio(unsigned int card, unsigned long *data);
+
+/* sets GPDATA register to new value:
+  (data & mask) | (current_GPDATA_value & ~mask)
+  returns negative value if error occurred
+*/
+extern int bttv_write_gpio(unsigned int card,
+                          unsigned long mask, unsigned long data);
+
+
+
+
+/* ---------------------------------------------------------- */
+/* sysfs/driver-moded based gpio access interface             */
+
+struct bttv_sub_device {
+       struct device    dev;
+       struct bttv_core *core;
+       struct list_head list;
+};
+#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev)
+
+struct bttv_sub_driver {
+       struct device_driver   drv;
+       char                   wanted[20];
+       int                    (*probe)(struct bttv_sub_device *sub);
+       void                   (*remove)(struct bttv_sub_device *sub);
+};
+#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
+
+int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted);
+int bttv_sub_unregister(struct bttv_sub_driver *drv);
+
+/* gpio access functions */
+void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits);
+u32 bttv_gpio_read(struct bttv_core *core);
+void bttv_gpio_write(struct bttv_core *core, u32 value);
+void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
+
+#define gpio_inout(mask,bits)  bttv_gpio_inout(&btv->c, mask, bits)
+#define gpio_read()            bttv_gpio_read(&btv->c)
+#define gpio_write(value)      bttv_gpio_write(&btv->c, value)
+#define gpio_bits(mask,bits)   bttv_gpio_bits(&btv->c, mask, bits)
+
+
+/* ---------------------------------------------------------- */
+/* i2c                                                        */
+
+#define bttv_call_all(btv, o, f, args...) \
+       v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
+
+extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
+extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+                        unsigned char b2, int both);
+extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
+
+extern int bttv_input_init(struct bttv *dev);
+extern void bttv_input_fini(struct bttv *dev);
+extern void bttv_input_irq(struct bttv *dev);
+
+#endif /* _BTTV_H_ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
new file mode 100644 (file)
index 0000000..70fd4f2
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+
+    bttv's *private* header file  --  nobody other than bttv itself
+    should ever include this file.
+
+    (c) 2000-2002 Gerd Knorr <kraxel@bytesex.org>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _BTTVP_H_
+#define _BTTVP_H_
+
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/pci.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/tveeprom.h>
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
+
+#include "bt848.h"
+#include "bttv.h"
+#include "btcx-risc.h"
+
+#ifdef __KERNEL__
+
+#define FORMAT_FLAGS_DITHER       0x01
+#define FORMAT_FLAGS_PACKED       0x02
+#define FORMAT_FLAGS_PLANAR       0x04
+#define FORMAT_FLAGS_RAW          0x08
+#define FORMAT_FLAGS_CrCb         0x10
+
+#define RISC_SLOT_O_VBI        4
+#define RISC_SLOT_O_FIELD      6
+#define RISC_SLOT_E_VBI       10
+#define RISC_SLOT_E_FIELD     12
+#define RISC_SLOT_LOOP        14
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO_STREAM  2
+#define RESOURCE_VBI           4
+#define RESOURCE_VIDEO_READ    8
+
+#define RAW_LINES            640
+#define RAW_BPL             1024
+
+#define UNSET (-1U)
+
+/* Min. value in VDELAY register. */
+#define MIN_VDELAY 2
+/* Even to get Cb first, odd for Cr. */
+#define MAX_HDELAY (0x3FF & -2)
+/* Limits scaled width, which must be a multiple of 4. */
+#define MAX_HACTIVE (0x3FF & -4)
+
+#define BTTV_NORMS    (\
+               V4L2_STD_PAL    | V4L2_STD_PAL_N | \
+               V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
+               V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
+               V4L2_STD_PAL_60)
+/* ---------------------------------------------------------- */
+
+struct bttv_tvnorm {
+       int   v4l2_id;
+       char  *name;
+       u32   Fsc;
+       u16   swidth, sheight; /* scaled standard width, height */
+       u16   totalwidth;
+       u8    adelay, bdelay, iform;
+       u32   scaledtwidth;
+       u16   hdelayx1, hactivex1;
+       u16   vdelay;
+       u8    vbipack;
+       u16   vtotal;
+       int   sram;
+       /* ITU-R frame line number of the first VBI line we can
+          capture, of the first and second field. The last possible line
+          is determined by cropcap.bounds. */
+       u16   vbistart[2];
+       /* Horizontally this counts fCLKx1 samples following the leading
+          edge of the horizontal sync pulse, vertically ITU-R frame line
+          numbers of the first field times two (2, 4, 6, ... 524 or 624). */
+       struct v4l2_cropcap cropcap;
+};
+extern const struct bttv_tvnorm bttv_tvnorms[];
+
+struct bttv_format {
+       char *name;
+       int  fourcc;          /* video4linux 2      */
+       int  btformat;        /* BT848_COLOR_FMT_*  */
+       int  btswap;          /* BT848_COLOR_CTL_*  */
+       int  depth;           /* bit/pixel          */
+       int  flags;
+       int  hshift,vshift;   /* for planar modes   */
+};
+
+struct bttv_ir {
+       struct rc_dev           *dev;
+       struct timer_list       timer;
+
+       char                    name[32];
+       char                    phys[32];
+
+       /* Usual gpio signalling */
+       u32                     mask_keycode;
+       u32                     mask_keydown;
+       u32                     mask_keyup;
+       u32                     polling;
+       u32                     last_gpio;
+       int                     shift_by;
+       int                     start; // What should RC5_START() be
+       int                     addr; // What RC5_ADDR() should be.
+       int                     rc5_remote_gap;
+
+       /* RC5 gpio */
+       bool                    rc5_gpio;   /* Is RC5 legacy GPIO enabled? */
+       u32                     last_bit;   /* last raw bit seen */
+       u32                     code;       /* raw code under construction */
+       struct timeval          base_time;  /* time of last seen code */
+       bool                    active;     /* building raw code */
+};
+
+
+/* ---------------------------------------------------------- */
+
+struct bttv_geometry {
+       u8  vtc,crop,comb;
+       u16 width,hscale,hdelay;
+       u16 sheight,vscale,vdelay,vtotal;
+};
+
+struct bttv_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer     vb;
+
+       /* bttv specific */
+       const struct bttv_format   *fmt;
+       unsigned int               tvnorm;
+       int                        btformat;
+       int                        btswap;
+       struct bttv_geometry       geo;
+       struct btcx_riscmem        top;
+       struct btcx_riscmem        bottom;
+       struct v4l2_rect           crop;
+       unsigned int               vbi_skip[2];
+       unsigned int               vbi_count[2];
+};
+
+struct bttv_buffer_set {
+       struct bttv_buffer     *top;       /* top field buffer    */
+       struct bttv_buffer     *bottom;    /* bottom field buffer */
+       unsigned int           top_irq;
+       unsigned int           frame_irq;
+};
+
+struct bttv_overlay {
+       unsigned int           tvnorm;
+       struct v4l2_rect       w;
+       enum v4l2_field        field;
+       struct v4l2_clip       *clips;
+       int                    nclips;
+       int                    setup_ok;
+};
+
+struct bttv_vbi_fmt {
+       struct v4l2_vbi_format fmt;
+
+       /* fmt.start[] and count[] refer to this video standard. */
+       const struct bttv_tvnorm *tvnorm;
+
+       /* Earliest possible start of video capturing with this
+          v4l2_vbi_format, in struct bttv_crop.rect units. */
+       __s32                  end;
+};
+
+/* bttv-vbi.c */
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
+
+struct bttv_crop {
+       /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */
+       struct v4l2_rect       rect;
+
+       /* Scaled image size limits with this crop rect. Divide
+          max_height, but not min_height, by two when capturing
+          single fields. See also bttv_crop_reset() and
+          bttv_crop_adjust() in bttv-driver.c. */
+       __s32                  min_scaled_width;
+       __s32                  min_scaled_height;
+       __s32                  max_scaled_width;
+       __s32                  max_scaled_height;
+};
+
+struct bttv_fh {
+       struct bttv              *btv;
+       int resources;
+#ifdef VIDIOC_G_PRIORITY
+       enum v4l2_priority       prio;
+#endif
+       enum v4l2_buf_type       type;
+
+       /* video capture */
+       struct videobuf_queue    cap;
+       const struct bttv_format *fmt;
+       int                      width;
+       int                      height;
+
+       /* video overlay */
+       const struct bttv_format *ovfmt;
+       struct bttv_overlay      ov;
+
+       /* Application called VIDIOC_S_CROP. */
+       int                      do_crop;
+
+       /* vbi capture */
+       struct videobuf_queue    vbi;
+       /* Current VBI capture window as seen through this fh (cannot
+          be global for compatibility with earlier drivers). Protected
+          by struct bttv.lock and struct bttv_fh.vbi.lock. */
+       struct bttv_vbi_fmt      vbi_fmt;
+};
+
+/* ---------------------------------------------------------- */
+/* bttv-risc.c                                                */
+
+/* risc code generators - capture */
+int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
+                    struct scatterlist *sglist,
+                    unsigned int offset, unsigned int bpl,
+                    unsigned int pitch, unsigned int skip_lines,
+                    unsigned int store_lines);
+
+/* control dma register + risc main loop */
+void bttv_set_dma(struct bttv *btv, int override);
+int bttv_risc_init_main(struct bttv *btv);
+int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
+                  int irqflags);
+
+/* capture buffer handling */
+int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
+int bttv_buffer_activate_video(struct bttv *btv,
+                              struct bttv_buffer_set *set);
+int bttv_buffer_activate_vbi(struct bttv *btv,
+                            struct bttv_buffer *vbi);
+void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
+                  struct bttv_buffer *buf);
+
+/* overlay handling */
+int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
+                     const struct bttv_format *fmt,
+                     struct bttv_buffer *buf);
+
+
+/* ---------------------------------------------------------- */
+/* bttv-vbi.c                                                 */
+
+int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+
+extern struct videobuf_queue_ops bttv_vbi_qops;
+
+/* ---------------------------------------------------------- */
+/* bttv-gpio.c */
+
+extern struct bus_type bttv_sub_bus_type;
+int bttv_sub_add_device(struct bttv_core *core, char *name);
+int bttv_sub_del_devices(struct bttv_core *core);
+
+/* ---------------------------------------------------------- */
+/* bttv-cards.c                                               */
+
+extern int no_overlay;
+
+/* ---------------------------------------------------------- */
+/* bttv-input.c                                               */
+
+extern void init_bttv_i2c_ir(struct bttv *btv);
+extern int fini_bttv_i2c(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* bttv-driver.c                                              */
+
+/* insmod options */
+extern unsigned int bttv_verbose;
+extern unsigned int bttv_debug;
+extern unsigned int bttv_gpio;
+extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
+extern int init_bttv_i2c(struct bttv *btv);
+
+#define dprintk(fmt, ...)                      \
+do {                                           \
+       if (bttv_debug >= 1)                    \
+               pr_debug(fmt, ##__VA_ARGS__);   \
+} while (0)
+#define dprintk_cont(fmt, ...)                 \
+do {                                           \
+       if (bttv_debug >= 1)                    \
+               pr_cont(fmt, ##__VA_ARGS__);    \
+} while (0)
+#define d2printk(fmt, ...)                     \
+do {                                           \
+       if (bttv_debug >= 2)                    \
+               printk(fmt, ##__VA_ARGS__);     \
+} while (0)
+
+#define BTTV_MAX_FBUF   0x208000
+#define BTTV_TIMEOUT    msecs_to_jiffies(500)    /* 0.5 seconds */
+#define BTTV_FREE_IDLE  msecs_to_jiffies(1000)   /* one second */
+
+
+struct bttv_pll_info {
+       unsigned int pll_ifreq;    /* PLL input frequency        */
+       unsigned int pll_ofreq;    /* PLL output frequency       */
+       unsigned int pll_crystal;  /* Crystal used for input     */
+       unsigned int pll_current;  /* Currently programmed ofreq */
+};
+
+/* for gpio-connected remote control */
+struct bttv_input {
+       struct input_dev      *dev;
+       char                  name[32];
+       char                  phys[32];
+       u32                   mask_keycode;
+       u32                   mask_keydown;
+};
+
+struct bttv_suspend_state {
+       u32  gpio_enable;
+       u32  gpio_data;
+       int  disabled;
+       int  loop_irq;
+       struct bttv_buffer_set video;
+       struct bttv_buffer     *vbi;
+};
+
+struct bttv {
+       struct bttv_core c;
+
+       /* pci device config */
+       unsigned short id;
+       unsigned char revision;
+       unsigned char __iomem *bt848_mmio;   /* pointer to mmio */
+
+       /* card configuration info */
+       unsigned int cardid;   /* pci subsystem id (bt878 based ones) */
+       unsigned int tuner_type;  /* tuner chip type */
+       unsigned int tda9887_conf;
+       unsigned int svhs, dig;
+       unsigned int has_saa6588:1;
+       struct bttv_pll_info pll;
+       int triton1;
+       int gpioirq;
+
+       int use_i2c_hw;
+
+       /* old gpio interface */
+       int shutdown;
+
+       void (*volume_gpio)(struct bttv *btv, __u16 volume);
+       void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+
+       /* new gpio interface */
+       spinlock_t gpio_lock;
+
+       /* i2c layer */
+       struct i2c_algo_bit_data   i2c_algo;
+       struct i2c_client          i2c_client;
+       int                        i2c_state, i2c_rc;
+       int                        i2c_done;
+       wait_queue_head_t          i2c_queue;
+       struct v4l2_subdev        *sd_msp34xx;
+       struct v4l2_subdev        *sd_tvaudio;
+
+       /* video4linux (1) */
+       struct video_device *video_dev;
+       struct video_device *radio_dev;
+       struct video_device *vbi_dev;
+
+       /* infrared remote */
+       int has_remote;
+       struct bttv_ir *remote;
+
+       /* I2C remote data */
+       struct IR_i2c_init_data    init_data;
+
+       /* locking */
+       spinlock_t s_lock;
+       struct mutex lock;
+       int resources;
+#ifdef VIDIOC_G_PRIORITY
+       struct v4l2_prio_state prio;
+#endif
+
+       /* video state */
+       unsigned int input;
+       unsigned int audio;
+       unsigned int mute;
+       unsigned long freq;
+       unsigned int tvnorm;
+       int hue, contrast, bright, saturation;
+       struct v4l2_framebuffer fbuf;
+       unsigned int field_count;
+
+       /* various options */
+       int opt_combfilter;
+       int opt_lumafilter;
+       int opt_automute;
+       int opt_chroma_agc;
+       int opt_adc_crush;
+       int opt_vcr_hack;
+       int opt_whitecrush_upper;
+       int opt_whitecrush_lower;
+       int opt_uv_ratio;
+       int opt_full_luma_range;
+       int opt_coring;
+
+       /* radio data/state */
+       int has_radio;
+       int radio_user;
+       int radio_uses_msp_demodulator;
+
+       /* miro/pinnacle + Aimslab VHX
+          philips matchbox (tea5757 radio tuner) support */
+       int has_matchbox;
+       int mbox_we;
+       int mbox_data;
+       int mbox_clk;
+       int mbox_most;
+       int mbox_mask;
+
+       /* ISA stuff (Terratec Active Radio Upgrade) */
+       int mbox_ior;
+       int mbox_iow;
+       int mbox_csel;
+
+       /* risc memory management data
+          - must acquire s_lock before changing these
+          - only the irq handler is supported to touch top + bottom + vcurr */
+       struct btcx_riscmem     main;
+       struct bttv_buffer      *screen;    /* overlay             */
+       struct list_head        capture;    /* video capture queue */
+       struct list_head        vcapture;   /* vbi capture queue   */
+       struct bttv_buffer_set  curr;       /* active buffers      */
+       struct bttv_buffer      *cvbi;      /* active vbi buffer   */
+       int                     loop_irq;
+       int                     new_input;
+
+       unsigned long cap_ctl;
+       unsigned long dma_on;
+       struct timer_list timeout;
+       struct bttv_suspend_state state;
+
+       /* stats */
+       unsigned int errors;
+       unsigned int framedrop;
+       unsigned int irq_total;
+       unsigned int irq_me;
+
+       unsigned int users;
+       struct bttv_fh init;
+
+       /* used to make dvb-bt8xx autoloadable */
+       struct work_struct request_module_wk;
+
+       /* Default (0) and current (1) video capturing and overlay
+          cropping parameters in bttv_tvnorm.cropcap units. Protected
+          by bttv.lock. */
+       struct bttv_crop crop[2];
+
+       /* Earliest possible start of video capturing in
+          bttv_tvnorm.cropcap line units. Set by check_alloc_btres()
+          and free_btres(). Protected by bttv.lock. */
+       __s32                   vbi_end;
+
+       /* Latest possible end of VBI capturing (= crop[x].rect.top when
+          VIDEO_RESOURCES are locked). Set by check_alloc_btres()
+          and free_btres(). Protected by bttv.lock. */
+       __s32                   crop_start;
+};
+
+static inline struct bttv *to_bttv(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct bttv, c.v4l2_dev);
+}
+
+/* our devices */
+#define BTTV_MAX 32
+extern unsigned int bttv_num;
+extern struct bttv *bttvs[BTTV_MAX];
+
+static inline unsigned int bttv_muxsel(const struct bttv *btv,
+                                      unsigned int input)
+{
+       return (bttv_tvcards[btv->c.type].muxsel >> (input * 2)) & 3;
+}
+
+#endif
+
+#define btwrite(dat,adr)    writel((dat), btv->bt848_mmio+(adr))
+#define btread(adr)         readl(btv->bt848_mmio+(adr))
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#endif /* _BTTVP_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index f52799232029074809ac1329405afecdf55cf112..f3d4228dbb0e493b4ecd0bc97ac278ad5b83c862 100644 (file)
@@ -619,8 +619,6 @@ menuconfig V4L_PCI_DRIVERS
 
 if V4L_PCI_DRIVERS
 
-source "drivers/media/video/bt8xx/Kconfig"
-
 source "drivers/media/video/cx18/Kconfig"
 
 source "drivers/media/video/cx23885/Kconfig"
index 4ad5bd9246bf13ccaa8ac544de3ed6e117355b48..df60ffacdc581ebd1e2a4e0ce2975741a0c1b52b 100644 (file)
@@ -87,7 +87,6 @@ obj-$(CONFIG_SOC_CAMERA_TW9910)               += tw9910.o
 
 # And now the v4l2 drivers:
 
-obj-$(CONFIG_VIDEO_BT848) += bt8xx/
 obj-$(CONFIG_VIDEO_ZORAN) += zoran/
 obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
 obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
deleted file mode 100644 (file)
index 7da5c2e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-config VIDEO_BT848
-       tristate "BT848 Video For Linux"
-       depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEOBUF_DMA_SG
-       depends on RC_CORE
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         Support for BT848 based frame grabber/overlay boards. This includes
-         the Miro, Hauppauge and STB boards. Please read the material in
-         <file:Documentation/video4linux/bttv/> for more information.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bttv.
-
-config VIDEO_BT848_DVB
-       bool "DVB/ATSC Support for bt878 based TV cards"
-       depends on VIDEO_BT848 && DVB_CORE
-       select DVB_BT8XX
-       ---help---
-         This adds support for DVB/ATSC cards based on the BT878 chip.
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
deleted file mode 100644 (file)
index f6351a2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Makefile for the video capture/playback device drivers.
-#
-
-bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
-                      bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
-                      bttv-input.o bttv-audio-hook.o
-
-obj-$(CONFIG_VIDEO_BT848) += bttv.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/video/bt8xx/bt848.h
deleted file mode 100644 (file)
index c37e6ac..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
-    bt848.h - Bt848 register offsets
-
-    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _BT848_H_
-#define _BT848_H_
-
-#ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e
-#endif
-#ifndef PCI_DEVICE_ID_BT848
-#define PCI_DEVICE_ID_BT848     0x350
-#endif
-#ifndef PCI_DEVICE_ID_BT849
-#define PCI_DEVICE_ID_BT849     0x351
-#endif
-#ifndef PCI_DEVICE_ID_FUSION879
-#define PCI_DEVICE_ID_FUSION879        0x36c
-#endif
-
-#ifndef PCI_DEVICE_ID_BT878
-#define PCI_DEVICE_ID_BT878     0x36e
-#endif
-#ifndef PCI_DEVICE_ID_BT879
-#define PCI_DEVICE_ID_BT879     0x36f
-#endif
-
-/* Brooktree 848 registers */
-
-#define BT848_DSTATUS          0x000
-#define BT848_DSTATUS_PRES     (1<<7)
-#define BT848_DSTATUS_HLOC     (1<<6)
-#define BT848_DSTATUS_FIELD    (1<<5)
-#define BT848_DSTATUS_NUML     (1<<4)
-#define BT848_DSTATUS_CSEL     (1<<3)
-#define BT848_DSTATUS_PLOCK    (1<<2)
-#define BT848_DSTATUS_LOF      (1<<1)
-#define BT848_DSTATUS_COF      (1<<0)
-
-#define BT848_IFORM            0x004
-#define BT848_IFORM_HACTIVE    (1<<7)
-#define BT848_IFORM_MUXSEL     (3<<5)
-#define BT848_IFORM_MUX0       (2<<5)
-#define BT848_IFORM_MUX1       (3<<5)
-#define BT848_IFORM_MUX2       (1<<5)
-#define BT848_IFORM_XTSEL      (3<<3)
-#define BT848_IFORM_XT0        (1<<3)
-#define BT848_IFORM_XT1        (2<<3)
-#define BT848_IFORM_XTAUTO     (3<<3)
-#define BT848_IFORM_XTBOTH     (3<<3)
-#define BT848_IFORM_NTSC       1
-#define BT848_IFORM_NTSC_J     2
-#define BT848_IFORM_PAL_BDGHI  3
-#define BT848_IFORM_PAL_M      4
-#define BT848_IFORM_PAL_N      5
-#define BT848_IFORM_SECAM      6
-#define BT848_IFORM_PAL_NC     7
-#define BT848_IFORM_AUTO       0
-#define BT848_IFORM_NORM       7
-
-#define BT848_TDEC             0x008
-#define BT848_TDEC_DEC_FIELD   (1<<7)
-#define BT848_TDEC_FLDALIGN    (1<<6)
-#define BT848_TDEC_DEC_RAT     (0x1f)
-
-#define BT848_E_CROP           0x00C
-#define BT848_O_CROP           0x08C
-
-#define BT848_E_VDELAY_LO      0x010
-#define BT848_O_VDELAY_LO      0x090
-
-#define BT848_E_VACTIVE_LO     0x014
-#define BT848_O_VACTIVE_LO     0x094
-
-#define BT848_E_HDELAY_LO      0x018
-#define BT848_O_HDELAY_LO      0x098
-
-#define BT848_E_HACTIVE_LO     0x01C
-#define BT848_O_HACTIVE_LO     0x09C
-
-#define BT848_E_HSCALE_HI      0x020
-#define BT848_O_HSCALE_HI      0x0A0
-
-#define BT848_E_HSCALE_LO      0x024
-#define BT848_O_HSCALE_LO      0x0A4
-
-#define BT848_BRIGHT           0x028
-
-#define BT848_E_CONTROL        0x02C
-#define BT848_O_CONTROL        0x0AC
-#define BT848_CONTROL_LNOTCH    (1<<7)
-#define BT848_CONTROL_COMP      (1<<6)
-#define BT848_CONTROL_LDEC      (1<<5)
-#define BT848_CONTROL_CBSENSE   (1<<4)
-#define BT848_CONTROL_CON_MSB   (1<<2)
-#define BT848_CONTROL_SAT_U_MSB (1<<1)
-#define BT848_CONTROL_SAT_V_MSB (1<<0)
-
-#define BT848_CONTRAST_LO      0x030
-#define BT848_SAT_U_LO         0x034
-#define BT848_SAT_V_LO         0x038
-#define BT848_HUE              0x03C
-
-#define BT848_E_SCLOOP         0x040
-#define BT848_O_SCLOOP         0x0C0
-#define BT848_SCLOOP_CAGC       (1<<6)
-#define BT848_SCLOOP_CKILL      (1<<5)
-#define BT848_SCLOOP_HFILT_AUTO (0<<3)
-#define BT848_SCLOOP_HFILT_CIF  (1<<3)
-#define BT848_SCLOOP_HFILT_QCIF (2<<3)
-#define BT848_SCLOOP_HFILT_ICON (3<<3)
-
-#define BT848_SCLOOP_PEAK       (1<<7)
-#define BT848_SCLOOP_HFILT_MINP (1<<3)
-#define BT848_SCLOOP_HFILT_MEDP (2<<3)
-#define BT848_SCLOOP_HFILT_MAXP (3<<3)
-
-
-#define BT848_OFORM            0x048
-#define BT848_OFORM_RANGE      (1<<7)
-#define BT848_OFORM_CORE0      (0<<5)
-#define BT848_OFORM_CORE8      (1<<5)
-#define BT848_OFORM_CORE16     (2<<5)
-#define BT848_OFORM_CORE32     (3<<5)
-
-#define BT848_E_VSCALE_HI      0x04C
-#define BT848_O_VSCALE_HI      0x0CC
-#define BT848_VSCALE_YCOMB     (1<<7)
-#define BT848_VSCALE_COMB      (1<<6)
-#define BT848_VSCALE_INT       (1<<5)
-#define BT848_VSCALE_HI        15
-
-#define BT848_E_VSCALE_LO      0x050
-#define BT848_O_VSCALE_LO      0x0D0
-#define BT848_TEST             0x054
-#define BT848_ADELAY           0x060
-#define BT848_BDELAY           0x064
-
-#define BT848_ADC              0x068
-#define BT848_ADC_RESERVED     (2<<6)
-#define BT848_ADC_SYNC_T       (1<<5)
-#define BT848_ADC_AGC_EN       (1<<4)
-#define BT848_ADC_CLK_SLEEP    (1<<3)
-#define BT848_ADC_Y_SLEEP      (1<<2)
-#define BT848_ADC_C_SLEEP      (1<<1)
-#define BT848_ADC_CRUSH        (1<<0)
-
-#define BT848_WC_UP            0x044
-#define BT848_WC_DOWN          0x078
-
-#define BT848_E_VTC            0x06C
-#define BT848_O_VTC            0x0EC
-#define BT848_VTC_HSFMT        (1<<7)
-#define BT848_VTC_VFILT_2TAP   0
-#define BT848_VTC_VFILT_3TAP   1
-#define BT848_VTC_VFILT_4TAP   2
-#define BT848_VTC_VFILT_5TAP   3
-
-#define BT848_SRESET           0x07C
-
-#define BT848_COLOR_FMT             0x0D4
-#define BT848_COLOR_FMT_O_RGB32     (0<<4)
-#define BT848_COLOR_FMT_O_RGB24     (1<<4)
-#define BT848_COLOR_FMT_O_RGB16     (2<<4)
-#define BT848_COLOR_FMT_O_RGB15     (3<<4)
-#define BT848_COLOR_FMT_O_YUY2      (4<<4)
-#define BT848_COLOR_FMT_O_BtYUV     (5<<4)
-#define BT848_COLOR_FMT_O_Y8        (6<<4)
-#define BT848_COLOR_FMT_O_RGB8      (7<<4)
-#define BT848_COLOR_FMT_O_YCrCb422  (8<<4)
-#define BT848_COLOR_FMT_O_YCrCb411  (9<<4)
-#define BT848_COLOR_FMT_O_RAW       (14<<4)
-#define BT848_COLOR_FMT_E_RGB32     0
-#define BT848_COLOR_FMT_E_RGB24     1
-#define BT848_COLOR_FMT_E_RGB16     2
-#define BT848_COLOR_FMT_E_RGB15     3
-#define BT848_COLOR_FMT_E_YUY2      4
-#define BT848_COLOR_FMT_E_BtYUV     5
-#define BT848_COLOR_FMT_E_Y8        6
-#define BT848_COLOR_FMT_E_RGB8      7
-#define BT848_COLOR_FMT_E_YCrCb422  8
-#define BT848_COLOR_FMT_E_YCrCb411  9
-#define BT848_COLOR_FMT_E_RAW       14
-
-#define BT848_COLOR_FMT_RGB32       0x00
-#define BT848_COLOR_FMT_RGB24       0x11
-#define BT848_COLOR_FMT_RGB16       0x22
-#define BT848_COLOR_FMT_RGB15       0x33
-#define BT848_COLOR_FMT_YUY2        0x44
-#define BT848_COLOR_FMT_BtYUV       0x55
-#define BT848_COLOR_FMT_Y8          0x66
-#define BT848_COLOR_FMT_RGB8        0x77
-#define BT848_COLOR_FMT_YCrCb422    0x88
-#define BT848_COLOR_FMT_YCrCb411    0x99
-#define BT848_COLOR_FMT_RAW         0xee
-
-#define BT848_VTOTAL_LO             0xB0
-#define BT848_VTOTAL_HI             0xB4
-
-#define BT848_COLOR_CTL                0x0D8
-#define BT848_COLOR_CTL_EXT_FRMRATE    (1<<7)
-#define BT848_COLOR_CTL_COLOR_BARS     (1<<6)
-#define BT848_COLOR_CTL_RGB_DED        (1<<5)
-#define BT848_COLOR_CTL_GAMMA          (1<<4)
-#define BT848_COLOR_CTL_WSWAP_ODD      (1<<3)
-#define BT848_COLOR_CTL_WSWAP_EVEN     (1<<2)
-#define BT848_COLOR_CTL_BSWAP_ODD      (1<<1)
-#define BT848_COLOR_CTL_BSWAP_EVEN     (1<<0)
-
-#define BT848_CAP_CTL                  0x0DC
-#define BT848_CAP_CTL_DITH_FRAME       (1<<4)
-#define BT848_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
-#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
-#define BT848_CAP_CTL_CAPTURE_ODD      (1<<1)
-#define BT848_CAP_CTL_CAPTURE_EVEN     (1<<0)
-
-#define BT848_VBI_PACK_SIZE    0x0E0
-
-#define BT848_VBI_PACK_DEL     0x0E4
-#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc
-#define BT848_VBI_PACK_DEL_EXT_FRAME  2
-#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1
-
-
-#define BT848_INT_STAT         0x100
-#define BT848_INT_MASK         0x104
-
-#define BT848_INT_ETBF         (1<<23)
-
-#define BT848_INT_RISCS   (0xf<<28)
-#define BT848_INT_RISC_EN (1<<27)
-#define BT848_INT_RACK    (1<<25)
-#define BT848_INT_FIELD   (1<<24)
-#define BT848_INT_SCERR   (1<<19)
-#define BT848_INT_OCERR   (1<<18)
-#define BT848_INT_PABORT  (1<<17)
-#define BT848_INT_RIPERR  (1<<16)
-#define BT848_INT_PPERR   (1<<15)
-#define BT848_INT_FDSR    (1<<14)
-#define BT848_INT_FTRGT   (1<<13)
-#define BT848_INT_FBUS    (1<<12)
-#define BT848_INT_RISCI   (1<<11)
-#define BT848_INT_GPINT   (1<<9)
-#define BT848_INT_I2CDONE (1<<8)
-#define BT848_INT_VPRES   (1<<5)
-#define BT848_INT_HLOCK   (1<<4)
-#define BT848_INT_OFLOW   (1<<3)
-#define BT848_INT_HSYNC   (1<<2)
-#define BT848_INT_VSYNC   (1<<1)
-#define BT848_INT_FMTCHG  (1<<0)
-
-
-#define BT848_GPIO_DMA_CTL             0x10C
-#define BT848_GPIO_DMA_CTL_GPINTC      (1<<15)
-#define BT848_GPIO_DMA_CTL_GPINTI      (1<<14)
-#define BT848_GPIO_DMA_CTL_GPWEC       (1<<13)
-#define BT848_GPIO_DMA_CTL_GPIOMODE    (3<<11)
-#define BT848_GPIO_DMA_CTL_GPCLKMODE   (1<<10)
-#define BT848_GPIO_DMA_CTL_PLTP23_4    (0<<6)
-#define BT848_GPIO_DMA_CTL_PLTP23_8    (1<<6)
-#define BT848_GPIO_DMA_CTL_PLTP23_16   (2<<6)
-#define BT848_GPIO_DMA_CTL_PLTP23_32   (3<<6)
-#define BT848_GPIO_DMA_CTL_PLTP1_4     (0<<4)
-#define BT848_GPIO_DMA_CTL_PLTP1_8     (1<<4)
-#define BT848_GPIO_DMA_CTL_PLTP1_16    (2<<4)
-#define BT848_GPIO_DMA_CTL_PLTP1_32    (3<<4)
-#define BT848_GPIO_DMA_CTL_PKTP_4      (0<<2)
-#define BT848_GPIO_DMA_CTL_PKTP_8      (1<<2)
-#define BT848_GPIO_DMA_CTL_PKTP_16     (2<<2)
-#define BT848_GPIO_DMA_CTL_PKTP_32     (3<<2)
-#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1)
-#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
-
-#define BT848_I2C              0x110
-#define BT878_I2C_MODE         (1<<7)
-#define BT878_I2C_RATE         (1<<6)
-#define BT878_I2C_NOSTOP       (1<<5)
-#define BT878_I2C_NOSTART      (1<<4)
-#define BT848_I2C_DIV          (0xf<<4)
-#define BT848_I2C_SYNC         (1<<3)
-#define BT848_I2C_W3B         (1<<2)
-#define BT848_I2C_SCL          (1<<1)
-#define BT848_I2C_SDA          (1<<0)
-
-#define BT848_RISC_STRT_ADD    0x114
-#define BT848_GPIO_OUT_EN      0x118
-#define BT848_GPIO_REG_INP     0x11C
-#define BT848_RISC_COUNT       0x120
-#define BT848_GPIO_DATA        0x200
-
-
-/* Bt848 RISC commands */
-
-/* only for the SYNC RISC command */
-#define BT848_FIFO_STATUS_FM1  0x06
-#define BT848_FIFO_STATUS_FM3  0x0e
-#define BT848_FIFO_STATUS_SOL  0x02
-#define BT848_FIFO_STATUS_EOL4 0x01
-#define BT848_FIFO_STATUS_EOL3 0x0d
-#define BT848_FIFO_STATUS_EOL2 0x09
-#define BT848_FIFO_STATUS_EOL1 0x05
-#define BT848_FIFO_STATUS_VRE  0x04
-#define BT848_FIFO_STATUS_VRO  0x0c
-#define BT848_FIFO_STATUS_PXV  0x00
-
-#define BT848_RISC_RESYNC      (1<<15)
-
-/* WRITE and SKIP */
-/* disable which bytes of each DWORD */
-#define BT848_RISC_BYTE0       (1U<<12)
-#define BT848_RISC_BYTE1       (1U<<13)
-#define BT848_RISC_BYTE2       (1U<<14)
-#define BT848_RISC_BYTE3       (1U<<15)
-#define BT848_RISC_BYTE_ALL    (0x0fU<<12)
-#define BT848_RISC_BYTE_NONE   0
-/* cause RISCI */
-#define BT848_RISC_IRQ         (1U<<24)
-/* RISC command is last one in this line */
-#define BT848_RISC_EOL         (1U<<26)
-/* RISC command is first one in this line */
-#define BT848_RISC_SOL         (1U<<27)
-
-#define BT848_RISC_WRITE       (0x01U<<28)
-#define BT848_RISC_SKIP        (0x02U<<28)
-#define BT848_RISC_WRITEC      (0x05U<<28)
-#define BT848_RISC_JUMP        (0x07U<<28)
-#define BT848_RISC_SYNC        (0x08U<<28)
-
-#define BT848_RISC_WRITE123    (0x09U<<28)
-#define BT848_RISC_SKIP123     (0x0aU<<28)
-#define BT848_RISC_WRITE1S23   (0x0bU<<28)
-
-
-/* Bt848A and higher only !! */
-#define BT848_TGLB             0x080
-#define BT848_TGCTRL           0x084
-#define BT848_FCAP             0x0E8
-#define BT848_PLL_F_LO         0x0F0
-#define BT848_PLL_F_HI         0x0F4
-
-#define BT848_PLL_XCI          0x0F8
-#define BT848_PLL_X            (1<<7)
-#define BT848_PLL_C            (1<<6)
-
-#define BT848_DVSIF            0x0FC
-
-/* Bt878 register */
-
-#define BT878_DEVCTRL 0x40
-#define BT878_EN_TBFX 0x02
-#define BT878_EN_VSFX 0x04
-
-#endif
diff --git a/drivers/media/video/bt8xx/bttv-audio-hook.c b/drivers/media/video/bt8xx/bttv-audio-hook.c
deleted file mode 100644 (file)
index 2364d16..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Handlers for board audio hooks, splitted from bttv-cards
- *
- * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- */
-
-#include "bttv-audio-hook.h"
-
-#include <linux/delay.h>
-
-/* ----------------------------------------------------------------------- */
-/* winview                                                                 */
-
-void winview_volume(struct bttv *btv, __u16 volume)
-{
-       /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
-       int bits_out, loops, vol, data;
-
-       /* 32 levels logarithmic */
-       vol = 32 - ((volume>>11));
-       /* units */
-       bits_out = (PT2254_DBS_IN_2>>(vol%5));
-       /* tens */
-       bits_out |= (PT2254_DBS_IN_10>>(vol/5));
-       bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
-       data = gpio_read();
-       data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
-                 WINVIEW_PT2254_STROBE);
-       for (loops = 17; loops >= 0 ; loops--) {
-               if (bits_out & (1<<loops))
-                       data |=  WINVIEW_PT2254_DATA;
-               else
-                       data &= ~WINVIEW_PT2254_DATA;
-               gpio_write(data);
-               udelay(5);
-               data |= WINVIEW_PT2254_CLK;
-               gpio_write(data);
-               udelay(5);
-               data &= ~WINVIEW_PT2254_CLK;
-               gpio_write(data);
-       }
-       data |=  WINVIEW_PT2254_STROBE;
-       data &= ~WINVIEW_PT2254_DATA;
-       gpio_write(data);
-       udelay(10);
-       data &= ~WINVIEW_PT2254_STROBE;
-       gpio_write(data);
-}
-
-/* ----------------------------------------------------------------------- */
-/* mono/stereo control for various cards (which don't use i2c chips but    */
-/* connect something to the GPIO pins                                      */
-
-void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned int con = 0;
-
-       if (set) {
-               gpio_inout(0x300, 0x300);
-               if (t->audmode & V4L2_TUNER_MODE_LANG1)
-                       con = 0x000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)
-                       con = 0x300;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)
-                       con = 0x200;
-/*             if (t->audmode & V4L2_TUNER_MODE_MONO)
- *                     con = 0x100; */
-               gpio_bits(0x300, con);
-       } else {
-               t->audmode = V4L2_TUNER_MODE_STEREO |
-                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned int val, con;
-
-       if (btv->radio_user)
-               return;
-
-       val = gpio_read();
-       if (set) {
-               con = 0x000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG2) {
-                       if (t->audmode & V4L2_TUNER_MODE_LANG1) {
-                               /* LANG1 + LANG2 */
-                               con = 0x100;
-                       }
-                       else {
-                               /* LANG2 */
-                               con = 0x300;
-                       }
-               }
-               if (con != (val & 0x300)) {
-                       gpio_bits(0x300, con);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"gvbctv5pci");
-               }
-       } else {
-               switch (val & 0x70) {
-                 case 0x10:
-                       t->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
-                       break;
-                 case 0x30:
-                       t->rxsubchans = V4L2_TUNER_SUB_LANG2;
-                       break;
-                 case 0x50:
-                       t->rxsubchans = V4L2_TUNER_SUB_LANG1;
-                       break;
-                 case 0x60:
-                       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-                       break;
-                 case 0x70:
-                       t->rxsubchans = V4L2_TUNER_SUB_MONO;
-                       break;
-                 default:
-                       t->rxsubchans = V4L2_TUNER_SUB_MONO |
-                                        V4L2_TUNER_SUB_STEREO |
-                                        V4L2_TUNER_SUB_LANG1 |
-                                        V4L2_TUNER_SUB_LANG2;
-               }
-               t->audmode = V4L2_TUNER_MODE_STEREO |
-                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-/*
- * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
- *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
- *  0xdde enables mono and 0xccd enables sap
- *
- * Petr Vandrovec <VANDROVE@vc.cvut.cz>
- *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
- *  input/output sound connection, so both must be set for output mode.
- *
- * Looks like it's needed only for the "tvphone", the "tvphone 98"
- * handles this with a tda9840
- *
- */
-
-void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       int val = 0;
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
-                       val = 0x02;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)
-                       val = 0x01;
-               if (val) {
-                       gpio_bits(0x03,val);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"avermedia");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1;
-               return;
-       }
-}
-
-
-void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       int val = 0;
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
-                       val = 0x01;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
-                       val = 0x02;
-               btaor(val, ~0x03, BT848_GPIO_DATA);
-               if (bttv_gpio)
-                       bttv_gpio_tracking(btv,"avermedia");
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-               return;
-       }
-}
-
-/* Lifetec 9415 handling */
-
-void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       int val = 0;
-
-       if (gpio_read() & 0x4000) {
-               t->audmode = V4L2_TUNER_MODE_MONO;
-               return;
-       }
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
-                       val = 0x0080;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
-                       val = 0x0880;
-               if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
-                   (t->audmode & V4L2_TUNER_MODE_MONO))
-                       val = 0;
-               gpio_bits(0x0880, val);
-               if (bttv_gpio)
-                       bttv_gpio_tracking(btv,"lt9415");
-       } else {
-               /* autodetect doesn't work with this card :-( */
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-               return;
-       }
-}
-
-/* TDA9821 on TerraTV+ Bt848, Bt878 */
-void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
-{
-       unsigned int con = 0;
-
-       if (set) {
-               gpio_inout(0x180000,0x180000);
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)
-                       con = 0x080000;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)
-                       con = 0x180000;
-               gpio_bits(0x180000, con);
-               if (bttv_gpio)
-                       bttv_gpio_tracking(btv,"terratv");
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-
-void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned long val = 0;
-
-       if (set) {
-               /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
-               if (t->audmode & V4L2_TUNER_MODE_MONO)          /* Mono */
-                       val = 0x420000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
-                       val = 0x420000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
-                       val = 0x410000;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)        /* Stereo */
-                       val = 0x020000;
-               if (val) {
-                       gpio_bits(0x430000, val);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"winfast2000");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-/*
- * Dariusz Kowalewski <darekk@automex.pl>
- * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
- * revision 9B has on-board TDA9874A sound decoder).
- *
- * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
- *       will mute this cards.
- */
-void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned int val = 0;
-
-       if (btv->radio_user)
-               return;
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_MONO)  {
-                       val = 0x01;
-               }
-               if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
-                   || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
-                       val = 0x02;
-               }
-               if (val) {
-                       gpio_bits(0x03,val);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"pvbt878p9b");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-/*
- * Dariusz Kowalewski <darekk@automex.pl>
- * sound control for FlyVideo 2000S (with tda9874 decoder)
- * based on pvbt878p9b_audio() - this is not tested, please fix!!!
- */
-void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned int val = 0xffff;
-
-       if (btv->radio_user)
-               return;
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_MONO)  {
-                       val = 0x0000;
-               }
-               if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
-                   || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
-                       val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
-               }
-               if (val != 0xffff) {
-                       gpio_bits(0x1800, val);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"fv2000s");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                       V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-/*
- * sound control for Canopus WinDVR PCI
- * Masaki Suzuki <masaki@btree.org>
- */
-void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned long val = 0;
-
-       if (set) {
-               if (t->audmode & V4L2_TUNER_MODE_MONO)
-                       val = 0x040000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG1)
-                       val = 0;
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)
-                       val = 0x100000;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)
-                       val = 0;
-               if (val) {
-                       gpio_bits(0x140000, val);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv,"windvr");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
-       }
-}
-
-/*
- * sound control for AD-TVK503
- * Hiroshi Takekawa <sian@big.or.jp>
- */
-void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
-{
-       unsigned int con = 0xffffff;
-
-       /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
-
-       if (set) {
-               /* btor(***, BT848_GPIO_OUT_EN); */
-               if (t->audmode & V4L2_TUNER_MODE_LANG1)
-                       con = 0x00000000;
-               if (t->audmode & V4L2_TUNER_MODE_LANG2)
-                       con = 0x00180000;
-               if (t->audmode & V4L2_TUNER_MODE_STEREO)
-                       con = 0x00000000;
-               if (t->audmode & V4L2_TUNER_MODE_MONO)
-                       con = 0x00060000;
-               if (con != 0xffffff) {
-                       gpio_bits(0x1e0000,con);
-                       if (bttv_gpio)
-                               bttv_gpio_tracking(btv, "adtvk503");
-               }
-       } else {
-               t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
-                         V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
-       }
-}
diff --git a/drivers/media/video/bt8xx/bttv-audio-hook.h b/drivers/media/video/bt8xx/bttv-audio-hook.h
deleted file mode 100644 (file)
index 159d07a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Handlers for board audio hooks, splitted from bttv-cards
- *
- * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- */
-
-#include "bttvp.h"
-
-void winview_volume (struct bttv *btv, __u16 volume);
-
-void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void terratv_audio(struct bttv *btv,  struct v4l2_tuner *tuner, int set);
-void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
deleted file mode 100644 (file)
index 38952fa..0000000
+++ /dev/null
@@ -1,4895 +0,0 @@
-/*
-
-    bttv-cards.c
-
-    this file has configuration informations - card-specific stuff
-    like the big tvcards array for the most part
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-                          & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/firmware.h>
-#include <net/checksum.h>
-
-#include <asm/unaligned.h>
-#include <asm/io.h>
-
-#include "bttvp.h"
-#include <media/v4l2-common.h>
-#include <media/tvaudio.h>
-#include "bttv-audio-hook.h"
-
-/* fwd decl */
-static void boot_msp34xx(struct bttv *btv, int pin);
-static void hauppauge_eeprom(struct bttv *btv);
-static void avermedia_eeprom(struct bttv *btv);
-static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
-static void modtec_eeprom(struct bttv *btv);
-static void init_PXC200(struct bttv *btv);
-static void init_RTV24(struct bttv *btv);
-
-static void rv605_muxsel(struct bttv *btv, unsigned int input);
-static void eagle_muxsel(struct bttv *btv, unsigned int input);
-static void xguard_muxsel(struct bttv *btv, unsigned int input);
-static void ivc120_muxsel(struct bttv *btv, unsigned int input);
-static void gvc1100_muxsel(struct bttv *btv, unsigned int input);
-
-static void PXC200_muxsel(struct bttv *btv, unsigned int input);
-
-static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
-static void picolo_tetra_init(struct bttv *btv);
-
-static void tibetCS16_muxsel(struct bttv *btv, unsigned int input);
-static void tibetCS16_init(struct bttv *btv);
-
-static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input);
-static void kodicom4400r_init(struct bttv *btv);
-
-static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
-static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
-
-static void geovision_muxsel(struct bttv *btv, unsigned int input);
-
-static void phytec_muxsel(struct bttv *btv, unsigned int input);
-
-static void gv800s_muxsel(struct bttv *btv, unsigned int input);
-static void gv800s_init(struct bttv *btv);
-
-static void td3116_muxsel(struct bttv *btv, unsigned int input);
-
-static int terratec_active_radio_upgrade(struct bttv *btv);
-static int tea5757_read(struct bttv *btv);
-static int tea5757_write(struct bttv *btv, int value);
-static void identify_by_eeprom(struct bttv *btv,
-                              unsigned char eeprom_data[256]);
-static int __devinit pvr_boot(struct bttv *btv);
-
-/* config variables */
-static unsigned int triton1;
-static unsigned int vsfx;
-static unsigned int latency = UNSET;
-int no_overlay=-1;
-
-static unsigned int card[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
-static unsigned int pll[BTTV_MAX]    = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
-static unsigned int tuner[BTTV_MAX]  = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
-static unsigned int svhs[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
-static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
-static unsigned int audiodev[BTTV_MAX];
-static unsigned int saa6588[BTTV_MAX];
-static struct bttv  *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
-static unsigned int autoload = UNSET;
-static unsigned int gpiomask = UNSET;
-static unsigned int audioall = UNSET;
-static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
-
-/* insmod options */
-module_param(triton1,    int, 0444);
-module_param(vsfx,       int, 0444);
-module_param(no_overlay, int, 0444);
-module_param(latency,    int, 0444);
-module_param(gpiomask,   int, 0444);
-module_param(audioall,   int, 0444);
-module_param(autoload,   int, 0444);
-
-module_param_array(card,     int, NULL, 0444);
-module_param_array(pll,      int, NULL, 0444);
-module_param_array(tuner,    int, NULL, 0444);
-module_param_array(svhs,     int, NULL, 0444);
-module_param_array(remote,   int, NULL, 0444);
-module_param_array(audiodev, int, NULL, 0444);
-module_param_array(audiomux, int, NULL, 0444);
-
-MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
-                "[enable bug compatibility for triton1 + others]");
-MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
-                "[yet another chipset flaw workaround]");
-MODULE_PARM_DESC(latency,"pci latency timer");
-MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
-MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)");
-MODULE_PARM_DESC(tuner,"specify installed tuner type");
-MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore");
-MODULE_PARM_DESC(audiodev, "specify audio device:\n"
-               "\t\t-1 = no audio\n"
-               "\t\t 0 = autodetect (default)\n"
-               "\t\t 1 = msp3400\n"
-               "\t\t 2 = tda7432\n"
-               "\t\t 3 = tvaudio");
-MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition.");
-MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
-               " [some VIA/SIS chipsets are known to have problem with overlay]");
-
-/* ----------------------------------------------------------------------- */
-/* list of card IDs for bt878+ cards                                       */
-
-static struct CARD {
-       unsigned id;
-       int cardnr;
-       char *name;
-} cards[] __devinitdata = {
-       { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV" },
-       { 0x39000070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV-D" },
-       { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR,  "Hauppauge WinTV/PVR" },
-       { 0xff000070, BTTV_BOARD_OSPREY1x0,     "Osprey-100" },
-       { 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" },
-       { 0xff020070, BTTV_BOARD_OSPREY500,     "Osprey-500" },
-       { 0xff030070, BTTV_BOARD_OSPREY2000,    "Osprey-2000" },
-       { 0xff040070, BTTV_BOARD_OSPREY540,     "Osprey-540" },
-       { 0xff070070, BTTV_BOARD_OSPREY440,     "Osprey-440" },
-
-       { 0x00011002, BTTV_BOARD_ATI_TVWONDER,  "ATI TV Wonder" },
-       { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" },
-
-       { 0x6606107d, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
-       { 0x6607107d, BTTV_BOARD_WINFASTVC100,  "Leadtek WinFast VC 100" },
-       { 0x6609107d, BTTV_BOARD_WINFAST2000,   "Leadtek TV 2000 XP" },
-       { 0x263610b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
-       { 0x264510b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
-       { 0x402010fc, BTTV_BOARD_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
-       { 0x405010fc, BTTV_BOARD_GVBCTV4PCI,    "I-O Data Co. GV-BCTV4/PCI" },
-       { 0x407010fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
-       { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
-
-       { 0x001211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
-       /* some cards ship with byteswapped IDs ... */
-       { 0x1200bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
-       { 0xff00bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
-       /* this seems to happen as well ... */
-       { 0xff1211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
-
-       { 0x3000121a, BTTV_BOARD_VOODOOTV_200,  "3Dfx VoodooTV 200" },
-       { 0x263710b4, BTTV_BOARD_VOODOOTV_FM,   "3Dfx VoodooTV FM" },
-       { 0x3060121a, BTTV_BOARD_STB2,    "3Dfx VoodooTV 100/ STB OEM" },
-
-       { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
-       { 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" },
-       { 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
-       { 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
-       { 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" },
-       { 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" },
-       { 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS,  "Phoebe TV Master (CPH060)" },
-
-       { 0x00011461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
-       { 0x00021461, BTTV_BOARD_AVERMEDIA98,   "AVermedia TVCapture 98" },
-       { 0x00031461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
-       { 0x00041461, BTTV_BOARD_AVERMEDIA98,   "AVerMedia TVCapture 98" },
-       { 0x03001461, BTTV_BOARD_AVERMEDIA98,   "VDOMATE TV TUNER CARD" },
-
-       { 0x1117153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL B/G)" },
-       { 0x1118153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL B/G)" },
-       { 0x1119153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL I)" },
-       { 0x111a153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL I)" },
-
-       { 0x1123153b, BTTV_BOARD_TERRATVRADIO,  "Terratec TV Radio+" },
-       { 0x1127153b, BTTV_BOARD_TERRATV,       "Terratec TV+ (V1.05)"    },
-       /* clashes with FlyVideo
-        *{ 0x18521852, BTTV_BOARD_TERRATV,     "Terratec TV+ (V1.10)"    }, */
-       { 0x1134153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (LR102)" },
-       { 0x1135153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* LR102 */
-       { 0x5018153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue" },       /* ?? */
-       { 0xff3b153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* ?? */
-
-       { 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
-       { 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
-       { 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
-       { 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
-       { 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
-
-       { 0x1430aa00, BTTV_BOARD_PV143,         "Provideo PV143A" },
-       { 0x1431aa00, BTTV_BOARD_PV143,         "Provideo PV143B" },
-       { 0x1432aa00, BTTV_BOARD_PV143,         "Provideo PV143C" },
-       { 0x1433aa00, BTTV_BOARD_PV143,         "Provideo PV143D" },
-       { 0x1433aa03, BTTV_BOARD_PV143,         "Security Eyes" },
-
-       { 0x1460aa00, BTTV_BOARD_PV150,         "Provideo PV150A-1" },
-       { 0x1461aa01, BTTV_BOARD_PV150,         "Provideo PV150A-2" },
-       { 0x1462aa02, BTTV_BOARD_PV150,         "Provideo PV150A-3" },
-       { 0x1463aa03, BTTV_BOARD_PV150,         "Provideo PV150A-4" },
-
-       { 0x1464aa04, BTTV_BOARD_PV150,         "Provideo PV150B-1" },
-       { 0x1465aa05, BTTV_BOARD_PV150,         "Provideo PV150B-2" },
-       { 0x1466aa06, BTTV_BOARD_PV150,         "Provideo PV150B-3" },
-       { 0x1467aa07, BTTV_BOARD_PV150,         "Provideo PV150B-4" },
-
-       { 0xa132ff00, BTTV_BOARD_IVC100,        "IVC-100"  },
-       { 0xa1550000, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550001, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550002, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550003, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550100, BTTV_BOARD_IVC200,        "IVC-200G" },
-       { 0xa1550101, BTTV_BOARD_IVC200,        "IVC-200G" },
-       { 0xa1550102, BTTV_BOARD_IVC200,        "IVC-200G" },
-       { 0xa1550103, BTTV_BOARD_IVC200,        "IVC-200G" },
-       { 0xa1550800, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550801, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550802, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa1550803, BTTV_BOARD_IVC200,        "IVC-200"  },
-       { 0xa182ff00, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff01, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff02, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff03, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff04, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff05, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff06, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff07, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff08, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff09, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0a, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0b, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0c, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0d, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0e, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xa182ff0f, BTTV_BOARD_IVC120,        "IVC-120G" },
-       { 0xf0500000, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
-       { 0xf0500001, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
-       { 0xf0500002, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
-       { 0xf0500003, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
-
-       { 0x41424344, BTTV_BOARD_GRANDTEC,      "GrandTec Multi Capture" },
-       { 0x01020304, BTTV_BOARD_XGUARD,        "Grandtec Grand X-Guard" },
-
-       { 0x18501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
-       { 0xa0501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
-       { 0x18511851, BTTV_BOARD_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
-       { 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
-       { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
-       { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
-
-       { 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
-       { 0x010114c7, BTTV_BOARD_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
-
-       { 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
-       { 0x217d6606, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
-       { 0xfff6f6ff, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
-       { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" },
-       { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" },
-       { 0x00790e11, BTTV_BOARD_WINDVR,        "Canopus WinDVR PCI" },
-       { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX,       "Face to Face Tvmax" },
-       { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" },
-       { 0x146caa0c, BTTV_BOARD_PV951,         "ituner spectra8" },
-       { 0x200a1295, BTTV_BOARD_PXC200,        "ImageNation PXC200A" },
-
-       { 0x40111554, BTTV_BOARD_PV_BT878P_9B,  "Prolink Pixelview PV-BT" },
-       { 0x17de0a01, BTTV_BOARD_KWORLD,        "Mecer TV/FM/Video Tuner" },
-
-       { 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" },
-       { 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" },
-       { 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
-       { 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
-
-       { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" },
-
-       { 0x53534149, BTTV_BOARD_SSAI_SECURITY, "SSAI Security Video Interface" },
-       { 0x5353414a, BTTV_BOARD_SSAI_ULTRASOUND, "SSAI Ultrasound Video Interface" },
-
-       /* likely broken, vendor id doesn't match the other magic views ...
-        * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
-
-       /* Duplicate PCI ID, reconfigure for this board during the eeprom read.
-       * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB,  "Hauppauge ImpactVCB" }, */
-
-       { 0x109e036e, BTTV_BOARD_CONCEPTRONIC_CTVFMI2,  "Conceptronic CTVFMi v2"},
-
-       /* DVB cards (using pci function .1 for mpeg data xfer) */
-       { 0x001c11bd, BTTV_BOARD_PINNACLESAT,   "Pinnacle PCTV Sat" },
-       { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
-       { 0x20007063, BTTV_BOARD_PC_HDTV,       "pcHDTV HD-2000 TV"},
-       { 0x002611bd, BTTV_BOARD_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
-       { 0x00011822, BTTV_BOARD_TWINHAN_DST,   "Twinhan VisionPlus DVB" },
-       { 0xfc00270f, BTTV_BOARD_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
-       { 0x07711461, BTTV_BOARD_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
-       { 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
-       { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
-       { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,    "Ultraview DVB-T Lite" },
-       { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
-       { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
-       { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,    "DViCO FusionHDTV 2" },
-       { 0x763c008a, BTTV_BOARD_GEOVISION_GV600,       "GeoVision GV-600" },
-       { 0x18011000, BTTV_BOARD_ENLTV_FM_2,    "Encore ENL TV-FM-2" },
-       { 0x763d800a, BTTV_BOARD_GEOVISION_GV800S, "GeoVision GV-800(S) (master)" },
-       { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
-       { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
-       { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL,   "GeoVision GV-800(S) (slave)" },
-
-       { 0x15401830, BTTV_BOARD_PV183,         "Provideo PV183-1" },
-       { 0x15401831, BTTV_BOARD_PV183,         "Provideo PV183-2" },
-       { 0x15401832, BTTV_BOARD_PV183,         "Provideo PV183-3" },
-       { 0x15401833, BTTV_BOARD_PV183,         "Provideo PV183-4" },
-       { 0x15401834, BTTV_BOARD_PV183,         "Provideo PV183-5" },
-       { 0x15401835, BTTV_BOARD_PV183,         "Provideo PV183-6" },
-       { 0x15401836, BTTV_BOARD_PV183,         "Provideo PV183-7" },
-       { 0x15401837, BTTV_BOARD_PV183,         "Provideo PV183-8" },
-       { 0x3116f200, BTTV_BOARD_TVT_TD3116,    "Tongwei Video Technology TD-3116" },
-       { 0x02280279, BTTV_BOARD_APOSONIC_WDVR, "Aposonic W-DVR" },
-       { 0, -1, NULL }
-};
-
-/* ----------------------------------------------------------------------- */
-/* array with description for bt848 / bt878 tv/grabber cards               */
-
-struct tvcard bttv_tvcards[] = {
-       /* ---- card 0x00 ---------------------------------- */
-       [BTTV_BOARD_UNKNOWN] = {
-               .name           = " *** UNKNOWN/GENERIC *** ",
-               .video_inputs   = 4,
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MIRO] = {
-               .name           = "MIRO PCTV",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 0, 0, 0 },
-               .gpiomute       = 10,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_HAUPPAUGE] = {
-               .name           = "Hauppauge (bt848)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_STB] = {
-               .name           = "STB, Gateway P/N 6000699 (bt848)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 4, 0, 2, 3 },
-               .gpiomute       = 1,
-               .no_msp34xx     = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-       },
-
-       /* ---- card 0x04 ---------------------------------- */
-       [BTTV_BOARD_INTEL] = {
-               .name           = "Intel Create and Share PCI/ Smart Video Recorder III",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 2,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0 },
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_DIAMOND] = {
-               .name           = "Diamond DTV2000",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 3,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0, 1, 0, 1 },
-               .gpiomute       = 3,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_AVERMEDIA] = {
-               .name           = "AVerMedia TVPhone",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomask       = 0x0f,
-               .gpiomux        = { 0x0c, 0x04, 0x08, 0x04 },
-               /*                0x04 for some cards ?? */
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= avermedia_tvphone_audio,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_MATRIX_VISION] = {
-               .name           = "MATRIX-Vision MV-Delta",
-               .video_inputs   = 5,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
-               .gpiomux        = { 0 },
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x08 ---------------------------------- */
-       [BTTV_BOARD_FLYVIDEO] = {
-               .name           = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xc00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0xc00, 0x800, 0x400 },
-               .gpiomute       = 0xc00,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TURBOTV] = {
-               .name           = "IMS/IXmicro TurboTV",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 3,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 1, 2, 3 },
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_HAUPPAUGE878] = {
-               .name           = "Hauppauge (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x0f, /* old: 7 */
-               .muxsel         = MUXSEL(2, 0, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MIROPRO] = {
-               .name           = "MIRO PCTV pro",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x3014f,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x20001,0x10001, 0, 0 },
-               .gpiomute       = 10,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x0c ---------------------------------- */
-       [BTTV_BOARD_ADSTECH_TV] = {
-               .name           = "ADS Technologies Channel Surfer TV (bt848)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 13, 14, 11, 7 },
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_AVERMEDIA98] = {
-               .name           = "AVerMedia TVCapture 98",
-               .video_inputs   = 3,
-               /* .audio_inputs= 4, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 13, 14, 11, 7 },
-               .msp34xx_alt    = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= avermedia_tv_stereo_audio,
-               .no_gpioirq     = 1,
-       },
-       [BTTV_BOARD_VHX] = {
-               .name           = "Aimslab Video Highway Xtreme (VHX)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */
-               .gpiomute       = 4,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ZOLTRIX] = {
-               .name           = "Zoltrix TV-Max",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 1, 0 },
-               .gpiomute       = 10,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x10 ---------------------------------- */
-       [BTTV_BOARD_PIXVIEWPLAYTV] = {
-               .name           = "Prolink Pixelview PlayTV (bt878)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x01fe00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
-               .gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
-               .gpiomute       = 0x002000,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_WINVIEW_601] = {
-               .name           = "Leadtek WinView 601",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x8300f8,
-               .muxsel         = MUXSEL(2, 3, 1, 1, 0),
-               .gpiomux        = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
-               .gpiomute       = 0xcfa007,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .volume_gpio    = winview_volume,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_AVEC_INTERCAP] = {
-               .name           = "AVEC Intercapture",
-               .video_inputs   = 3,
-               /* .audio_inputs= 2, */
-               .svhs           = 2,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 0, 0, 0 },
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_LIFE_FLYKIT] = {
-               .name           = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x8dff00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x14 ---------------------------------- */
-       [BTTV_BOARD_CEI_RAFFLES] = {
-               .name           = "CEI Raffles Card",
-               .video_inputs   = 3,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_CONFERENCETV] = {
-               .name           = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
-               .video_inputs   = 4,
-               /* .audio_inputs= 2,  tuner, line in */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_PHOEBE_TVMAS] = {
-               .name           = "Askey CPH050/ Phoebe Tv Master + FM",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xc00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 0x800, 0x400 },
-               .gpiomute       = 0xc00,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MODTEC_205] = {
-               .name           = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .has_dig_in     = 1,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 0), /* input 2 is digital */
-               /* .digital_mode= DIGITAL_MODE_CAMERA, */
-               .gpiomux        = { 0, 0, 0, 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ALPS_TSBB5_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x18 ---------------------------------- */
-       [BTTV_BOARD_MAGICTVIEW061] = {
-               .name           = "Askey CPH05X/06X (bt878) [many vendors]",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xe00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = {0x400, 0x400, 0x400, 0x400 },
-               .gpiomute       = 0xc00,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-               .has_radio      = 1,  /* not every card has radio */
-       },
-       [BTTV_BOARD_VOBIS_BOOSTAR] = {
-               .name           = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x1f0fff,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
-               .gpiomute       = 0x40000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= terratv_audio,
-       },
-       [BTTV_BOARD_HAUPPAUG_WCAM] = {
-               .name           = "Hauppauge WinCam newer (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 0, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MAXI] = {
-               .name           = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
-               .video_inputs   = 4,
-               /* .audio_inputs= 2, */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x1c ---------------------------------- */
-       [BTTV_BOARD_TERRATV] = {
-               .name           = "Terratec TerraTV+ Version 1.1 (bt878)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x1f0fff,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0x00000 },
-               .gpiomute       = 0x40000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= terratv_audio,
-               /* GPIO wiring:
-               External 20 pin connector (for Active Radio Upgrade board)
-               gpio00: i2c-sda
-               gpio01: i2c-scl
-               gpio02: om5610-data
-               gpio03: om5610-clk
-               gpio04: om5610-wre
-               gpio05: om5610-stereo
-               gpio06: rds6588-davn
-               gpio07: Pin 7 n.c.
-               gpio08: nIOW
-               gpio09+10: nIOR, nSEL ?? (bt878)
-                       gpio09: nIOR (bt848)
-                       gpio10: nSEL (bt848)
-               Sound Routing:
-               gpio16: u2-A0 (1st 4052bt)
-               gpio17: u2-A1
-               gpio18: u2-nEN
-               gpio19: u4-A0 (2nd 4052)
-               gpio20: u4-A1
-                       u4-nEN - GND
-               Btspy:
-                       00000 : Cdrom (internal audio input)
-                       10000 : ext. Video audio input
-                       20000 : TV Mono
-                       a0000 : TV Mono/2
-               1a0000 : TV Stereo
-                       30000 : Radio
-                       40000 : Mute
-       */
-
-       },
-       [BTTV_BOARD_PXC200] = {
-               /* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
-               .name           = "Imagenation PXC200",
-               .video_inputs   = 5,
-               /* .audio_inputs= 1, */
-               .svhs           = 1, /* was: 4 */
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
-               .gpiomux        = { 0 },
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .muxsel_hook    = PXC200_muxsel,
-
-       },
-       [BTTV_BOARD_FLYVIDEO_98] = {
-               .name           = "Lifeview FlyVideo 98 LR50",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,  /* 0x8dfe00 */
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x0800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_IPROTV] = {
-               .name           = "Formac iProTV, Formac ProTV I (bt848)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 1,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 0, 0, 0 },
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x20 ---------------------------------- */
-       [BTTV_BOARD_INTEL_C_S_PCI] = {
-               .name           = "Intel Create and Share PCI/ Smart Video Recorder III",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 2,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0 },
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TERRATVALUE] = {
-               .name           = "Terratec TerraTValue Version Bt878",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xffff00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x500, 0, 0x300, 0x900 },
-               .gpiomute       = 0x900,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_WINFAST2000] = {
-               .name           = "Leadtek WinFast 2000/ WinFast 2000 XP",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               /* TV, CVid, SVid, CVid over SVid connector */
-               .muxsel         = MUXSEL(2, 3, 1, 1, 0),
-               /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
-               .gpiomask       = 0xb33000,
-               .gpiomux        = { 0x122000,0x1000,0x0000,0x620000 },
-               .gpiomute       = 0x800000,
-               /* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
-                       gpio23 -- hef4052:nEnable (0x800000)
-                       gpio12 -- hef4052:A1
-                       gpio13 -- hef4052:A0
-               0x0000: external audio
-               0x1000: FM
-               0x2000: TV
-               0x3000: n.c.
-               Note: There exists another variant "Winfast 2000" with tv stereo !?
-               Note: eeprom only contains FF and pci subsystem id 107d:6606
-               */
-               .pll            = PLL_28,
-               .has_radio      = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= winfast2000_audio,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_CHRONOS_VS2] = {
-               .name           = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II",
-               .video_inputs   = 4,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x24 ---------------------------------- */
-       [BTTV_BOARD_TYPHOON_TVIEW] = {
-               .name           = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner",
-               .video_inputs   = 4,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_PXELVWPLTVPRO] = {
-               .name           = "Prolink PixelView PlayTV pro",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xff,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x21, 0x20, 0x24, 0x2c },
-               .gpiomute       = 0x29,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MAGICTVIEW063] = {
-               .name           = "Askey CPH06X TView99",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x551e00,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0x551400, 0x551200, 0, 0 },
-               .gpiomute       = 0x551c00,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_PINNACLE] = {
-               .name           = "Pinnacle PCTV Studio/Rave",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x03000F,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 0xd0001, 0, 0 },
-               .gpiomute       = 1,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x28 ---------------------------------- */
-       [BTTV_BOARD_STB2] = {
-               .name           = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 4, 0, 2, 3 },
-               .gpiomute       = 1,
-               .no_msp34xx     = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_AVPHONE98] = {
-               .name           = "AVerMedia TVPhone 98",
-               .video_inputs   = 3,
-               /* .audio_inputs= 4, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 13, 4, 11, 7 },
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-               .audio_mode_gpio= avermedia_tvphone_audio,
-       },
-       [BTTV_BOARD_PV951] = {
-               .name           = "ProVideo PV951", /* pic16c54 */
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 0, 0},
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ONAIR_TV] = {
-               .name           = "Little OnAir TV",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xe00b,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
-               .gpiomute       = 0xff3ffc,
-               .no_msp34xx     = 1,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x2c ---------------------------------- */
-       [BTTV_BOARD_SIGMA_TVII_FM] = {
-               .name           = "Sigma TVII-FM",
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 3,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 1, 0, 2 },
-               .gpiomute       = 3,
-               .no_msp34xx     = 1,
-               .pll            = PLL_NONE,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MATRIX_VISION2] = {
-               .name           = "MATRIX-Vision MV-Delta 2",
-               .video_inputs   = 5,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ZOLTRIX_GENIE] = {
-               .name           = "Zoltrix Genie TV/FM",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xbcf03f,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0xbc803f, 0xbc903f, 0xbcb03f, 0 },
-               .gpiomute       = 0xbcb03f,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_4039FR5_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TERRATVRADIO] = {
-               .name           = "Terratec TV/Radio+",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x70000,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
-               .gpiomute       = 0x40000,
-               .no_msp34xx     = 1,
-               .pll            = PLL_35,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-       },
-
-       /* ---- card 0x30 ---------------------------------- */
-       [BTTV_BOARD_DYNALINK] = {
-               .name           = "Askey CPH03x/ Dynalink Magic TView",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = {2,0,0,0 },
-               .gpiomute       = 1,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_GVBCTV3PCI] = {
-               .name           = "IODATA GV-BCTV3/PCI",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x010f00,
-               .muxsel         = MUXSEL(2, 3, 0, 0),
-               .gpiomux        = {0x10000, 0, 0x10000, 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ALPS_TSHC6_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= gvbctv3pci_audio,
-       },
-       [BTTV_BOARD_PXELVWPLTVPAK] = {
-               .name           = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
-               .video_inputs   = 5,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .has_dig_in     = 1,
-               .gpiomask       = 0xAA0000,
-               .muxsel         = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
-               /* .digital_mode= DIGITAL_MODE_CAMERA, */
-               .gpiomux        = { 0x20000, 0, 0x80000, 0x80000 },
-               .gpiomute       = 0xa8000,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-               /* GPIO wiring: (different from Rev.4C !)
-                       GPIO17: U4.A0 (first hef4052bt)
-                       GPIO19: U4.A1
-                       GPIO20: U5.A1 (second hef4052bt)
-                       GPIO21: U4.nEN
-                       GPIO22: BT832 Reset Line
-                       GPIO23: A5,A0, U5,nEN
-               Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
-               */
-       },
-       [BTTV_BOARD_EAGLE] = {
-               .name           = "Eagle Wireless Capricorn2 (bt878A)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 0, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .pll            = PLL_28,
-               .tuner_type     = UNSET /* TUNER_ALPS_TMDH2_NTSC */,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x34 ---------------------------------- */
-       [BTTV_BOARD_PINNACLEPRO] = {
-               /* David Härdeman <david@2gen.com> */
-               .name           = "Pinnacle PCTV Studio Pro",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 0x03000F,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 0xd0001, 0, 0 },
-               .gpiomute       = 10,
-                               /* sound path (5 sources):
-                               MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
-                                       0= ext. Audio IN
-                                       1= from MUX2
-                                       2= Mono TV sound from Tuner
-                                       3= not connected
-                               MUX2 (mask 0x30000):
-                                       0,2,3= from MSP34xx
-                                       1= FM stereo Radio from Tuner */
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TVIEW_RDS_FM] = {
-               /* Claas Langbehn <claas@bigfoot.com>,
-               Sven Grothklags <sven@upb.de> */
-               .name           = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
-               .video_inputs   = 4,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 0x1c,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 0x10, 8 },
-               .gpiomute       = 4,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_LIFETEC_9415] = {
-               /* Tim Röstermundt <rosterm@uni-muenster.de>
-               in de.comp.os.unix.linux.hardware:
-                       options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
-                       gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
-                       options tuner type=5 */
-               .name           = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x18e0,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x0000,0x0800,0x1000,0x1000 },
-               .gpiomute       = 0x18e0,
-                       /* For cards with tda9820/tda9821:
-                               0x0000: Tuner normal stereo
-                               0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
-                               0x0880: Tuner A2 stereo */
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_BESTBUY_EASYTV] = {
-               /* Miguel Angel Alvarez <maacruz@navegalia.com>
-               old Easy TV BT848 version (model CPH031) */
-               .name           = "Askey CPH031/ BESTBUY Easy TV",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xF,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 2, 0, 0, 0 },
-               .gpiomute       = 10,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x38 ---------------------------------- */
-       [BTTV_BOARD_FLYVIDEO_98FM] = {
-               /* Gordon Heydon <gjheydon@bigfoot.com ('98) */
-               .name           = "Lifeview FlyVideo 98FM LR50",
-               .video_inputs   = 4,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 0x1800,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
-               .gpiomute       = 0x1800,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               /* This is the ultimate cheapo capture card
-               * just a BT848A on a small PCB!
-               * Steve Hosgood <steve@equiinet.com> */
-       [BTTV_BOARD_GRANDTEC] = {
-               .name           = "GrandTec 'Grand Video Capture' (Bt848)",
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(3, 1),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_35,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ASKEY_CPH060] = {
-               /* Daniel Herrington <daniel.herrington@home.com> */
-               .name           = "Askey CPH060/ Phoebe TV Master Only (No FM)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xe00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x400, 0x400, 0x400, 0x400 },
-               .gpiomute       = 0x800,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ASKEY_CPH03X] = {
-               /* Matti Mottus <mottus@physic.ut.ee> */
-               .name           = "Askey CPH03x TV Capturer",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x03000F,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 2, 0, 0, 0 },
-               .gpiomute       = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-       },
-
-       /* ---- card 0x3c ---------------------------------- */
-       [BTTV_BOARD_MM100PCTV] = {
-               /* Philip Blundell <philb@gnu.org> */
-               .name           = "Modular Technology MM100PCTV",
-               .video_inputs   = 2,
-               /* .audio_inputs= 2, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 11,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 0, 0, 1 },
-               .gpiomute       = 8,
-               .pll            = PLL_35,
-               .tuner_type     = TUNER_TEMIC_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_GMV1] = {
-               /* Adrian Cox <adrian@humboldt.co.uk */
-               .name           = "AG Electronics GMV1",
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .gpiomask       = 0xF,
-               .muxsel         = MUXSEL(2, 2),
-               .gpiomux        = { },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_BESTBUY_EASYTV2] = {
-               /* Miguel Angel Alvarez <maacruz@navegalia.com>
-               new Easy TV BT878 version (model CPH061)
-               special thanks to Informatica Mieres for providing the card */
-               .name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 2, */
-               .svhs           = 2,
-               .gpiomask       = 0xFF,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 1, 0, 4, 4 },
-               .gpiomute       = 9,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_ATI_TVWONDER] = {
-               /* Lukas Gebauer <geby@volny.cz> */
-               .name           = "ATI TV-Wonder",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xf03f,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0xbffe, 0, 0xbfff, 0 },
-               .gpiomute       = 0xbffe,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x40 ---------------------------------- */
-       [BTTV_BOARD_ATI_TVWONDERVE] = {
-               /* Lukas Gebauer <geby@volny.cz> */
-               .name           = "ATI TV-Wonder VE",
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 1,
-               .muxsel         = MUXSEL(2, 3, 0, 1),
-               .gpiomux        = { 0, 0, 1, 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_FLYVIDEO2000] = {
-               /* DeeJay <deejay@westel900.net (2000S) */
-               .name           = "Lifeview FlyVideo 2000S LR90",
-               .video_inputs   = 3,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 0x18e0,
-               .muxsel         = MUXSEL(2, 3, 0, 1),
-                               /* Radio changed from 1e80 to 0x800 to make
-                               FlyVideo2000S in .hu happy (gm)*/
-                               /* -dk-???: set mute=0x1800 for tda9874h daughterboard */
-               .gpiomux        = { 0x0000,0x0800,0x1000,0x1000 },
-               .gpiomute       = 0x1800,
-               .audio_mode_gpio= fv2000s_audio,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TERRATVALUER] = {
-               .name           = "Terratec TValueRadio",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0xffff00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x500, 0x500, 0x300, 0x900 },
-               .gpiomute       = 0x900,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_GVBCTV4PCI] = {
-               /* TANAKA Kei <peg00625@nifty.com> */
-               .name           = "IODATA GV-BCTV4/PCI",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x010f00,
-               .muxsel         = MUXSEL(2, 3, 0, 0),
-               .gpiomux        = {0x10000, 0, 0x10000, 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_SHARP_2U5JF5540_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= gvbctv3pci_audio,
-       },
-
-       /* ---- card 0x44 ---------------------------------- */
-       [BTTV_BOARD_VOODOOTV_FM] = {
-               .name           = "3Dfx VoodooTV FM (Euro)",
-               /* try "insmod msp3400 simple=0" if you have
-               * sound problems with this card. */
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x4f8a00,
-               /* 0x100000: 1=MSP enabled (0=disable again)
-               * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
-               .gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
-               .gpiomute       = 0x947fff,
-               /* tvtuner, radio,   external,internal, mute,  stereo
-               * tuner, Composit, SVid, Composit-on-Svid-adapter */
-               .muxsel         = MUXSEL(2, 3, 0, 1),
-               .tuner_type     = TUNER_MT2032,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_VOODOOTV_200] = {
-               .name           = "VoodooTV 200 (USA)",
-               /* try "insmod msp3400 simple=0" if you have
-               * sound problems with this card. */
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x4f8a00,
-               /* 0x100000: 1=MSP enabled (0=disable again)
-               * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
-               .gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
-               .gpiomute       = 0x947fff,
-               /* tvtuner, radio,   external,internal, mute,  stereo
-               * tuner, Composit, SVid, Composit-on-Svid-adapter */
-               .muxsel         = MUXSEL(2, 3, 0, 1),
-               .tuner_type     = TUNER_MT2032,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_AIMMS] = {
-               /* Philip Blundell <pb@nexus.co.uk> */
-               .name           = "Active Imaging AIMMS",
-               .video_inputs   = 1,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .muxsel         = MUXSEL(2),
-               .gpiomask       = 0
-       },
-       [BTTV_BOARD_PV_BT878P_PLUS] = {
-               /* Tomasz Pyra <hellfire@sedez.iq.pl> */
-               .name           = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 4, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */
-               .gpiomute       = 13,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_LG_PAL_I_FM,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-               /* GPIO wiring:
-                       GPIO0: U4.A0 (hef4052bt)
-                       GPIO1: U4.A1
-                       GPIO2: U4.A1 (second hef4052bt)
-                       GPIO3: U4.nEN, U5.A0, A5.nEN
-                       GPIO8-15: vrd866b ?
-               */
-       },
-       [BTTV_BOARD_FLYVIDEO98EZ] = {
-               .name           = "Lifeview FlyVideo 98EZ (capture only) LR51",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 2,
-               /* AV1, AV2, SVHS, CVid adapter on SVHS */
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-       /* ---- card 0x48 ---------------------------------- */
-       [BTTV_BOARD_PV_BT878P_9B] = {
-               /* Dariusz Kowalewski <darekk@automex.pl> */
-               .name           = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x3f,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x01, 0x00, 0x03, 0x03 },
-               .gpiomute       = 0x09,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */
-               .has_radio      = 1,  /* Note: not all cards have radio */
-               .has_remote     = 1,
-               /* GPIO wiring:
-                       GPIO0: A0 hef4052
-                       GPIO1: A1 hef4052
-                       GPIO3: nEN hef4052
-                       GPIO8-15: vrd866b
-                       GPIO20,22,23: R30,R29,R28
-               */
-       },
-       [BTTV_BOARD_SENSORAY311_611] = {
-               /* Clay Kunz <ckunz@mail.arc.nasa.gov> */
-               /* you must jumper JP5 for the 311 card (PC/104+) to work */
-               .name           = "Sensoray 311/611",
-               .video_inputs   = 5,
-               /* .audio_inputs= 0, */
-               .svhs           = 4,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0, 0),
-               .gpiomux        = { 0 },
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_RV605] = {
-               /* Miguel Freitas <miguel@cetuc.puc-rio.br> */
-               .name           = "RemoteVision MX (RV605)",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x00,
-               .gpiomask2      = 0x07ff,
-               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
-               .no_msp34xx     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .muxsel_hook    = rv605_muxsel,
-       },
-       [BTTV_BOARD_POWERCLR_MTV878] = {
-               .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
-               .video_inputs   = 3,
-               /* .audio_inputs= 2, */
-               .svhs           = 2,
-               .gpiomask       = 0x1C800F,  /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
-               .muxsel         = MUXSEL(2, 1, 1),
-               .gpiomux        = { 0, 1, 2, 2 },
-               .gpiomute       = 4,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-       },
-
-       /* ---- card 0x4c ---------------------------------- */
-       [BTTV_BOARD_WINDVR] = {
-               /* Masaki Suzuki <masaki@btree.org> */
-               .name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x140007,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= windvr_audio,
-       },
-       [BTTV_BOARD_GRANDTEC_MULTI] = {
-               .name           = "GrandTec Multi Capture Card (Bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_KWORLD] = {
-               .name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
-               .video_inputs   = 4,
-               /* .audio_inputs= 3, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               /* Tuner, SVid, SVHS, SVid to SVHS connector */
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio!
-                                               * This card lacks external Audio In, so we mute it on Ext. & Int.
-                                               * The PCB can take a sbx1637/sbx1673, wiring unknown.
-                                               * This card lacks PCI subsystem ID, sigh.
-                                               * gpiomux =1: lower volume, 2+3: mute
-                                               * btwincap uses 0x80000/0x80003
-                                               */
-               .gpiomute       = 4,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
-               radio signal strength indicators work fine. */
-               .has_radio      = 1,
-               /* GPIO Info:
-                       GPIO0,1:   HEF4052 A0,A1
-                       GPIO2:     HEF4052 nENABLE
-                       GPIO3-7:   n.c.
-                       GPIO8-13:  IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card]
-                       GPIO14,15: ??
-                       GPIO16-21: n.c.
-                       GPIO22,23: ??
-                       ??       : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
-       },
-       [BTTV_BOARD_DSP_TCVIDEO] = {
-               /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
-               .name           = "DSP Design TCVIDEO",
-               .video_inputs   = 4,
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-               /* ---- card 0x50 ---------------------------------- */
-       [BTTV_BOARD_HAUPPAUGEPVR] = {
-               .name           = "Hauppauge WinTV PVR",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 0, 1, 1),
-               .pll            = PLL_28,
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-
-               .gpiomask       = 7,
-               .gpiomux        = {7},
-       },
-       [BTTV_BOARD_GVBCTV5PCI] = {
-               .name           = "IODATA GV-BCTV5/PCI",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x0f0f80,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = {0x030000, 0x010000, 0, 0 },
-               .gpiomute       = 0x020000,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= gvbctv5pci_audio,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_OSPREY1x0] = {
-               .name           = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */
-               .video_inputs   = 4,                  /* id-inputs-clock */
-               /* .audio_inputs= 0, */
-               .svhs           = 3,
-               .muxsel         = MUXSEL(3, 2, 0, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY1x0_848] = {
-               .name           = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
-               .video_inputs   = 3,
-               /* .audio_inputs= 0, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-
-               /* ---- card 0x54 ---------------------------------- */
-       [BTTV_BOARD_OSPREY101_848] = {
-               .name           = "Osprey 101 (848)", /* 0x05-40C0-C1 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(3, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY1x1] = {
-               .name           = "Osprey 101/151",       /* 0x1(4|5)-0004-C4 */
-               .video_inputs   = 1,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(0),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY1x1_SVID] = {
-               .name           = "Osprey 101/151 w/ svid",  /* 0x(16|17|20)-00C4-C1 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(0, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY2xx] = {
-               .name           = "Osprey 200/201/250/251",  /* 0x1(8|9|E|F)-0004-C4 */
-               .video_inputs   = 1,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(0),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-
-               /* ---- card 0x58 ---------------------------------- */
-       [BTTV_BOARD_OSPREY2x0_SVID] = {
-               .name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(0, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY2x0] = {
-               .name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(2, 3),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY500] = {
-               .name           = "Osprey 500",   /* 500 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(2, 3),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       [BTTV_BOARD_OSPREY540] = {
-               .name           = "Osprey 540",   /* 540 */
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-
-               /* ---- card 0x5C ---------------------------------- */
-       [BTTV_BOARD_OSPREY2000] = {
-               .name           = "Osprey 2000",  /* 2000 */
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(2, 3),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
-       },
-       [BTTV_BOARD_IDS_EAGLE] = {
-               /* M G Berberich <berberic@forwiss.uni-passau.de> */
-               .name           = "IDS Eagle",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .muxsel_hook    = eagle_muxsel,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_PINNACLESAT] = {
-               .name           = "Pinnacle PCTV Sat",
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel         = MUXSEL(3, 1),
-               .pll            = PLL_28,
-               .no_gpioirq     = 1,
-               .has_dvb        = 1,
-       },
-       [BTTV_BOARD_FORMAC_PROTV] = {
-               .name           = "Formac ProTV II (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .gpiomask       = 2,
-               /* TV, Comp1, Composite over SVID con, SVID */
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 2, 0, 0 },
-               .pll            = PLL_28,
-               .has_radio      = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-       /* sound routing:
-               GPIO=0x00,0x01,0x03: mute (?)
-               0x02: both TV and radio (tuner: FM1216/I)
-               The card has onboard audio connectors labeled "cdrom" and "board",
-               not soldered here, though unknown wiring.
-               Card lacks: external audio in, pci subsystem id.
-       */
-       },
-
-               /* ---- card 0x60 ---------------------------------- */
-       [BTTV_BOARD_MACHTV] = {
-               .name           = "MachTV",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3},
-               .gpiomute       = 4,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_EURESYS_PICOLO] = {
-               .name           = "Euresys Picolo",
-               .video_inputs   = 3,
-               /* .audio_inputs= 0, */
-               .svhs           = 2,
-               .gpiomask       = 0,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel         = MUXSEL(2, 0, 1),
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_PV150] = {
-               /* Luc Van Hoeylandt <luc@e-magic.be> */
-               .name           = "ProVideo PV150", /* 0x4f */
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_AD_TVK503] = {
-               /* Hiroshi Takekawa <sian@big.or.jp> */
-               /* This card lacks subsystem ID */
-               .name           = "AD-TVK503", /* 0x63 */
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x001e8007,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               /*                  Tuner, Radio, external, internal, off,  on */
-               .gpiomux        = { 0x08,  0x0f,  0x0a,     0x08 },
-               .gpiomute       = 0x0f,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .audio_mode_gpio= adtvk503_audio,
-       },
-
-               /* ---- card 0x64 ---------------------------------- */
-       [BTTV_BOARD_HERCULES_SM_TV] = {
-               .name           = "Hercules Smart TV Stereo",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               /* Notes:
-               - card lacks subsystem ID
-               - stereo variant w/ daughter board with tda9874a @0xb0
-               - Audio Routing:
-                       always from tda9874 independent of GPIO (?)
-                       external line in: unknown
-               - Other chips: em78p156elp @ 0x96 (probably IR remote control)
-                       hef4053 (instead 4052) for unknown function
-               */
-       },
-       [BTTV_BOARD_PACETV] = {
-               .name           = "Pace TV & Radio Card",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               /* Tuner, CVid, SVid, CVid over SVid connector */
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomask       = 0,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-               .pll            = PLL_28,
-               /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
-               only internal line out: (4pin header) RGGL
-               Radio must be decoded by msp3410d (not routed through)*/
-               /*
-               .digital_mode   = DIGITAL_MODE_CAMERA,  todo!
-               */
-       },
-       [BTTV_BOARD_IVC200] = {
-               /* Chris Willing <chris@vislab.usyd.edu.au> */
-               .name           = "IVC-200",
-               .video_inputs   = 1,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0xdf,
-               .muxsel         = MUXSEL(2),
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_IVCE8784] = {
-               .name           = "IVCE-8784",
-               .video_inputs   = 1,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0xdf,
-               .muxsel         = MUXSEL(2),
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_XGUARD] = {
-               .name           = "Grand X-Guard / Trust 814PCI",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .gpiomask2      = 0xff,
-               .muxsel         = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0),
-               .muxsel_hook    = xguard_muxsel,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-       },
-
-               /* ---- card 0x68 ---------------------------------- */
-       [BTTV_BOARD_NEBULA_DIGITV] = {
-               .name           = "Nebula Electronics DigiTV",
-               .video_inputs   = 1,
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .has_dvb        = 1,
-               .has_remote     = 1,
-               .gpiomask       = 0x1b,
-               .no_gpioirq     = 1,
-       },
-       [BTTV_BOARD_PV143] = {
-               /* Jorge Boncompte - DTI2 <jorge@dti2.net> */
-               .name           = "ProVideo PV143",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_VD009X1_VD011_MINIDIN] = {
-               /* M.Klahr@phytec.de */
-               .name           = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 3,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_VD009X1_VD011_COMBI] = {
-               .name           = "PHYTEC VD-009-X1 VD-011 Combi (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 3,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-
-               /* ---- card 0x6c ---------------------------------- */
-       [BTTV_BOARD_VD009_MINIDIN] = {
-               .name           = "PHYTEC VD-009 MiniDIN (bt878)",
-               .video_inputs   = 10,
-               /* .audio_inputs= 0, */
-               .svhs           = 9,
-               .gpiomask       = 0x00,
-               .gpiomask2      = 0x03, /* used for external vodeo mux */
-               .muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 0),
-               .muxsel_hook    = phytec_muxsel,
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_VD009_COMBI] = {
-               .name           = "PHYTEC VD-009 Combi (bt878)",
-               .video_inputs   = 10,
-               /* .audio_inputs= 0, */
-               .svhs           = 9,
-               .gpiomask       = 0x00,
-               .gpiomask2      = 0x03, /* used for external vodeo mux */
-               .muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 1),
-               .muxsel_hook    = phytec_muxsel,
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_IVC100] = {
-               .name           = "IVC-100",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0xdf,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_IVC120] = {
-               /* IVC-120G - Alan Garfield <alan@fromorbit.com> */
-               .name           = "IVC-120G",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,   /* card has no svhs */
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
-               .muxsel_hook    = ivc120_muxsel,
-               .pll            = PLL_28,
-       },
-
-               /* ---- card 0x70 ---------------------------------- */
-       [BTTV_BOARD_PC_HDTV] = {
-               .name           = "pcHDTV HD-2000 TV",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .tuner_type     = TUNER_PHILIPS_FCV1236D,
-               .tuner_addr     = ADDR_UNSET,
-               .has_dvb        = 1,
-       },
-       [BTTV_BOARD_TWINHAN_DST] = {
-               .name           = "Twinhan DST + clones",
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_video       = 1,
-               .has_dvb        = 1,
-       },
-       [BTTV_BOARD_WINFASTVC100] = {
-               .name           = "Winfast VC100",
-               .video_inputs   = 3,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               /* Vid In, SVid In, Vid over SVid in connector */
-               .muxsel         = MUXSEL(3, 1, 1, 3),
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-       },
-       [BTTV_BOARD_TEV560] = {
-               .name           = "Teppro TEV-560/InterVision IV-560",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 3,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 1, 1, 1, 1 },
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_35,
-       },
-
-               /* ---- card 0x74 ---------------------------------- */
-       [BTTV_BOARD_SIMUS_GVC1100] = {
-               .name           = "SIMUS GVC1100",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .gpiomask       = 0x3F,
-               .muxsel_hook    = gvc1100_muxsel,
-       },
-       [BTTV_BOARD_NGSTV_PLUS] = {
-               /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
-               .name           = "NGS NGSTV+",
-               .video_inputs   = 3,
-               .svhs           = 2,
-               .gpiomask       = 0x008007,
-               .muxsel         = MUXSEL(2, 3, 0, 0),
-               .gpiomux        = { 0, 0, 0, 0 },
-               .gpiomute       = 0x000003,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_LMLBT4] = {
-               /* http://linuxmedialabs.com */
-               .name           = "LMLBT4",
-               .video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TEKRAM_M205] = {
-               /* Helmroos Harri <harri.helmroos@pp.inet.fi> */
-               .name           = "Tekram M205 PRO",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = 2,
-               .gpiomask       = 0x68,
-               .muxsel         = MUXSEL(2, 3, 1),
-               .gpiomux        = { 0x68, 0x68, 0x61, 0x61 },
-               .pll            = PLL_28,
-       },
-
-               /* ---- card 0x78 ---------------------------------- */
-       [BTTV_BOARD_CONTVFMI] = {
-               /* Javier Cendan Ares <jcendan@lycos.es> */
-               /* bt878 TV + FM without subsystem ID */
-               .name           = "Conceptronic CONTVFMi",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x008007,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 2 },
-               .gpiomute       = 3,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_PICOLO_TETRA_CHIP] = {
-               /*Eric DEBIEF <debief@telemsa.com>*/
-               /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controlled*/
-               /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the following declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/
-               /*0x79 in bttv.h*/
-               .name           = "Euresys Picolo Tetra",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .gpiomask2      = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               /*878A input is always MUX0, see above.*/
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_SPIRIT_TV] = {
-               /* Spirit TV Tuner from http://spiritmodems.com.au */
-               /* Stafford Goodsell <surge@goliath.homeunix.org> */
-               .name           = "Spirit TV Tuner",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x0000000f,
-               .muxsel         = MUXSEL(2, 1, 1),
-               .gpiomux        = { 0x02, 0x00, 0x00, 0x00 },
-               .tuner_type     = TUNER_TEMIC_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-       },
-       [BTTV_BOARD_AVDVBT_771] = {
-               /* Wolfram Joost <wojo@frokaschwei.de> */
-               .name           = "AVerMedia AVerTV DVB-T 771",
-               .video_inputs   = 2,
-               .svhs           = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .muxsel         = MUXSEL(3, 3),
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-               .has_dvb        = 1,
-               .no_gpioirq     = 1,
-               .has_remote     = 1,
-       },
-               /* ---- card 0x7c ---------------------------------- */
-       [BTTV_BOARD_AVDVBT_761] = {
-               /* Matt Jesson <dvb@jesson.eclipse.co.uk> */
-               /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */
-               .name           = "AverMedia AverTV DVB-T 761",
-               .video_inputs   = 2,
-               .svhs           = 1,
-               .muxsel         = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .has_dvb        = 1,
-               .no_gpioirq     = 1,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_MATRIX_VISIONSQ] = {
-               /* andre.schwarz@matrix-vision.de */
-               .name           = "MATRIX Vision Sigma-SQ",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x0,
-               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3),
-               .muxsel_hook    = sigmaSQ_muxsel,
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MATRIX_VISIONSLC] = {
-               /* andre.schwarz@matrix-vision.de */
-               .name           = "MATRIX Vision Sigma-SLC",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x0,
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .muxsel_hook    = sigmaSLC_muxsel,
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               /* BTTV_BOARD_APAC_VIEWCOMP */
-       [BTTV_BOARD_APAC_VIEWCOMP] = {
-               /* Attila Kondoros <attila.kondoros@chello.hu> */
-               /* bt878 TV + FM 0x00000000 subsystem ID */
-               .name           = "APAC Viewcomp 878(AMAX)",
-               .video_inputs   = 2,
-               /* .audio_inputs= 1, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0xFF,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 0, 0, 0 },
-               .gpiomute       = 10,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
-               .has_radio      = 1,   /* not every card has radio */
-       },
-
-               /* ---- card 0x80 ---------------------------------- */
-       [BTTV_BOARD_DVICO_DVBT_LITE] = {
-               /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
-               .name           = "DViCO FusionHDTV DVB-T Lite",
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-               .no_video       = 1,
-               .has_dvb        = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_VGEAR_MYVCD] = {
-               /* Steven <photon38@pchome.com.tw> */
-               .name           = "V-Gear MyVCD",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x3f,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .gpiomux        = {0x31, 0x31, 0x31, 0x31 },
-               .gpiomute       = 0x31,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 0,
-       },
-       [BTTV_BOARD_SUPER_TV] = {
-               /* Rick C <cryptdragoon@gmail.com> */
-               .name           = "Super TV Tuner",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-               .gpiomask       = 0x008007,
-               .gpiomux        = { 0, 0x000001,0,0 },
-               .has_radio      = 1,
-       },
-       [BTTV_BOARD_TIBET_CS16] = {
-               /* Chris Fanning <video4linux@haydon.net> */
-               .name           = "Tibet Systems 'Progress DVR' CS16",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .muxsel_hook    = tibetCS16_muxsel,
-       },
-       [BTTV_BOARD_KODICOM_4400R] = {
-               /* Bill Brack <wbrack@mmm.com.hk> */
-               /*
-               * Note that, because of the card's wiring, the "master"
-               * BT878A chip (i.e. the one which controls the analog switch
-               * and must use this card type) is the 2nd one detected.  The
-               * other 3 chips should use card type 0x85, whose description
-               * follows this one.  There is a EEPROM on the card (which is
-               * connected to the I2C of one of those other chips), but is
-               * not currently handled.  There is also a facility for a
-               * "monitor", which is also not currently implemented.
-               */
-               .name           = "Kodicom 4400R (master)",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               /* GPIO bits 0-9 used for analog switch:
-               *   00 - 03:    camera selector
-               *   04 - 06:    channel (controller) selector
-               *   07: data (1->on, 0->off)
-               *   08: strobe
-               *   09: reset
-               * bit 16 is input from sync separator for the channel
-               */
-               .gpiomask       = 0x0003ff,
-               .no_gpioirq     = 1,
-               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel_hook    = kodicom4400r_muxsel,
-       },
-       [BTTV_BOARD_KODICOM_4400R_SL] = {
-               /* Bill Brack <wbrack@mmm.com.hk> */
-               /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
-               * one which controls the analog switch, and must use the card type)
-               * is the 2nd one detected.  The other 3 chips should use this card
-               * type
-               */
-               .name           = "Kodicom 4400R (slave)",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x010000,
-               .no_gpioirq     = 1,
-               .muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel_hook    = kodicom4400r_muxsel,
-       },
-               /* ---- card 0x86---------------------------------- */
-       [BTTV_BOARD_ADLINK_RTV24] = {
-               /* Michael Henson <mhenson@clarityvi.com> */
-               /* Adlink RTV24 with special unlock codes */
-               .name           = "Adlink RTV24",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .tuner_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-       },
-               /* ---- card 0x87---------------------------------- */
-       [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
-               /* Michael Krufky <mkrufky@m1k.net> */
-               .name           = "DViCO FusionHDTV 5 Lite",
-               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
-               .tuner_addr     = ADDR_UNSET,
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1),
-               .gpiomask       = 0x00e00007,
-               .gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
-               .gpiomute       = 0x00c00007,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .has_dvb        = 1,
-       },
-               /* ---- card 0x88---------------------------------- */
-       [BTTV_BOARD_ACORP_Y878F] = {
-               /* Mauro Carvalho Chehab <mchehab@infradead.org> */
-               .name           = "Acorp Y878F",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x01fe00,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
-               .gpiomute       = 0x002000,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_YMEC_TVF66T5_B_DFF,
-               .tuner_addr     = 0xc1 >>1,
-               .has_radio      = 1,
-       },
-               /* ---- card 0x89 ---------------------------------- */
-       [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = {
-               .name           = "Conceptronic CTVFMi v2",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x001c0007,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 2 },
-               .gpiomute       = 3,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TENA_9533_DI,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-               .has_radio      = 1,
-       },
-               /* ---- card 0x8a ---------------------------------- */
-       [BTTV_BOARD_PV_BT878P_2E] = {
-               .name           = "Prolink Pixelview PV-BT878P+ (Rev.2E)",
-               .video_inputs   = 5,
-               /* .audio_inputs= 1, */
-               .svhs           = 3,
-               .has_dig_in     = 1,
-               .gpiomask       = 0x01fe00,
-               .muxsel         = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
-               /* .digital_mode= DIGITAL_MODE_CAMERA, */
-               .gpiomux        = { 0x00400, 0x10400, 0x04400, 0x80000 },
-               .gpiomute       = 0x12400,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_LG_PAL_FM,
-               .tuner_addr     = ADDR_UNSET,
-               .has_remote     = 1,
-       },
-               /* ---- card 0x8b ---------------------------------- */
-       [BTTV_BOARD_PV_M4900] = {
-               /* Sérgio Fortier <sergiofortier@yahoo.com.br> */
-               .name           = "Prolink PixelView PlayTV MPEG2 PV-M4900",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x3f,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x21, 0x20, 0x24, 0x2c },
-               .gpiomute       = 0x29,
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_YMEC_TVF_5533MF,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-               .has_remote     = 1,
-       },
-               /* ---- card 0x8c ---------------------------------- */
-       /* Has four Bt878 chips behind a PCI bridge, each chip has:
-            one external BNC composite input (mux 2)
-            three internal composite inputs (unknown muxes)
-            an 18-bit stereo A/D (CS5331A), which has:
-              one external stereo unblanced (RCA) audio connection
-              one (or 3?) internal stereo balanced (XLR) audio connection
-              input is selected via gpio to a 14052B mux
-                (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300)
-              gain is controlled via an X9221A chip on the I2C bus @0x28
-              sample rate is controlled via gpio to an MK1413S
-                (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3)
-            There is neither a tuner nor an svideo input. */
-       [BTTV_BOARD_OSPREY440]  = {
-               .name           = "Osprey 440",
-               .video_inputs   = 4,
-               /* .audio_inputs= 2, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 3, 0, 1), /* 3,0,1 are guesses */
-               .gpiomask       = 0x303,
-               .gpiomute       = 0x000, /* int + 32kHz */
-               .gpiomux        = { 0, 0, 0x000, 0x100},
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-               /* ---- card 0x8d ---------------------------------- */
-       [BTTV_BOARD_ASOUND_SKYEYE] = {
-               .name           = "Asound Skyeye PCTV",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 15,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 2, 0, 0, 0 },
-               .gpiomute       = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               /* ---- card 0x8e ---------------------------------- */
-       [BTTV_BOARD_SABRENT_TVFM] = {
-               .name           = "Sabrent TV-FM (bttv version)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x108007,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 100000, 100002, 100002, 100000 },
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_TNF_5335MF,
-               .tuner_addr     = ADDR_UNSET,
-               .has_radio      = 1,
-       },
-       /* ---- card 0x8f ---------------------------------- */
-       [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
-               .name           = "Hauppauge ImpactVCB (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x0f, /* old: 7 */
-               .muxsel         = MUXSEL(0, 1, 3, 2), /* Composite 0-3 */
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_MACHTV_MAGICTV] = {
-               /* Julian Calaby <julian.calaby@gmail.com>
-                * Slightly different from original MachTV definition (0x60)
-
-                * FIXME: RegSpy says gpiomask should be "0x001c800f", but it
-                * stuffs up remote chip. Bug is a pin on the jaecs is not set
-                * properly (methinks) causing no keyup bits being set */
-
-               .name           = "MagicTV", /* rebranded MachTV */
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 7,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 3 },
-               .gpiomute       = 4,
-               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_SSAI_SECURITY] = {
-               .name           = "SSAI Security Video Interface",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(0, 1, 2, 3),
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_SSAI_ULTRASOUND] = {
-               .name           = "SSAI Ultrasound Video Interface",
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = 1,
-               .muxsel         = MUXSEL(2, 0, 1, 3),
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       /* ---- card 0x94---------------------------------- */
-       [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
-               .name           = "DViCO FusionHDTV 2",
-               .tuner_type     = TUNER_PHILIPS_FCV1236D,
-               .tuner_addr     = ADDR_UNSET,
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .muxsel         = MUXSEL(2, 3, 1),
-               .gpiomask       = 0x00e00007,
-               .gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
-               .gpiomute       = 0x00c00007,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-       },
-       /* ---- card 0x95---------------------------------- */
-       [BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
-               .name           = "Typhoon TV-Tuner PCI (50684)",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x3014f,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0x20001,0x10001, 0, 0 },
-               .gpiomute       = 10,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_GEOVISION_GV600] = {
-               /* emhn@usb.ve */
-               .name           = "Geovision GV-600",
-               .video_inputs   = 16,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x0,
-               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
-               .muxsel_hook    = geovision_muxsel,
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_KOZUMI_KTV_01C] = {
-               /* Mauro Lacy <mauro@lacy.com.ar>
-                * Based on MagicTV and Conceptronic CONTVFMi */
-
-               .name           = "Kozumi KTV-01C",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               .gpiomask       = 0x008007,
-               .muxsel         = MUXSEL(2, 3, 1, 1),
-               .gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
-               .gpiomute       = 3, /* CONTVFMi */
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-               .has_remote     = 1,
-       },
-       [BTTV_BOARD_ENLTV_FM_2] = {
-               /* Encore TV Tuner Pro ENL TV-FM-2
-                  Mauro Carvalho Chehab <mchehab@infradead.org */
-               .name           = "Encore ENL TV-FM-2",
-               .video_inputs   = 3,
-               /* .audio_inputs= 1, */
-               .svhs           = 2,
-               /* bit 6          -> IR disabled
-                  bit 18/17 = 00 -> mute
-                              01 -> enable external audio input
-                              10 -> internal audio input (mono?)
-                              11 -> internal audio input
-                */
-               .gpiomask       = 0x060040,
-               .muxsel         = MUXSEL(2, 3, 3),
-               .gpiomux        = { 0x60000, 0x60000, 0x20000, 0x20000 },
-               .gpiomute       = 0,
-               .tuner_type     = TUNER_TCL_MF02GIP_5N,
-               .tuner_addr     = ADDR_UNSET,
-               .pll            = PLL_28,
-               .has_radio      = 1,
-               .has_remote     = 1,
-       },
-               [BTTV_BOARD_VD012] = {
-               /* D.Heer@Phytec.de */
-               .name           = "PHYTEC VD-012 (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(0, 2, 3, 1),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               [BTTV_BOARD_VD012_X1] = {
-               /* D.Heer@Phytec.de */
-               .name           = "PHYTEC VD-012-X1 (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 3,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(2, 3, 1),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               [BTTV_BOARD_VD012_X2] = {
-               /* D.Heer@Phytec.de */
-               .name           = "PHYTEC VD-012-X2 (bt878)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 0, */
-               .svhs           = 3,
-               .gpiomask       = 0x00,
-               .muxsel         = MUXSEL(3, 2, 1),
-               .gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-               [BTTV_BOARD_GEOVISION_GV800S] = {
-               /* Bruno Christo <bchristo@inf.ufsm.br>
-                *
-                * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
-                *      1 audio input  per BT878A = 4 audio inputs
-                *      4 video inputs per BT878A = 16 video inputs
-                * This is the first BT878A chip of the GV-800(S). It's the
-                * "master" chip and it controls the video inputs through an
-                * analog multiplexer (a CD22M3494) via some GPIO pins. The
-                * slaves should use card type 0x9e (following this one).
-                * There is a EEPROM on the card which is currently not handled.
-                * The audio input is not working yet.
-                */
-               .name           = "Geovision GV-800(S) (master)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0xf107f,
-               .no_gpioirq     = 1,
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel_hook    = gv800s_muxsel,
-       },
-               [BTTV_BOARD_GEOVISION_GV800S_SL] = {
-               /* Bruno Christo <bchristo@inf.ufsm.br>
-                *
-                * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
-                *      1 audio input  per BT878A = 4 audio inputs
-                *      4 video inputs per BT878A = 16 video inputs
-                * The 3 other BT878A chips are "slave" chips of the GV-800(S)
-                * and should use this card type.
-                * The audio input is not working yet.
-                */
-               .name           = "Geovision GV-800(S) (slave)",
-               .video_inputs   = 4,
-               /* .audio_inputs= 1, */
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0x00,
-               .no_gpioirq     = 1,
-               .muxsel         = MUXSEL(2, 2, 2, 2),
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda7432     = 1,
-               .muxsel_hook    = gv800s_muxsel,
-       },
-       [BTTV_BOARD_PV183] = {
-               .name           = "ProVideo PV183", /* 0x9f */
-               .video_inputs   = 2,
-               /* .audio_inputs= 0, */
-               .svhs           = NO_SVHS,
-               .gpiomask       = 0,
-               .muxsel         = MUXSEL(2, 3),
-               .gpiomux        = { 0 },
-               .no_msp34xx     = 1,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = ADDR_UNSET,
-       },
-       [BTTV_BOARD_TVT_TD3116] = {
-               .name           = "Tongwei Video Technology TD-3116",
-               .video_inputs   = 16,
-               .gpiomask       = 0xc00ff,
-               .muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
-               .muxsel_hook    = td3116_muxsel,
-               .svhs           = NO_SVHS,
-               .pll            = PLL_28,
-               .tuner_type     = TUNER_ABSENT,
-       },
-       [BTTV_BOARD_APOSONIC_WDVR] = {
-               .name           = "Aposonic W-DVR",
-               .video_inputs   = 4,
-               .svhs           = NO_SVHS,
-               .muxsel         = MUXSEL(2, 3, 1, 0),
-               .tuner_type     = TUNER_ABSENT,
-       },
-
-};
-
-static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
-
-/* ----------------------------------------------------------------------- */
-
-static unsigned char eeprom_data[256];
-
-/*
- * identify card
- */
-void __devinit bttv_idcard(struct bttv *btv)
-{
-       unsigned int gpiobits;
-       int i,type;
-
-       /* read PCI subsystem ID */
-       btv->cardid  = btv->c.pci->subsystem_device << 16;
-       btv->cardid |= btv->c.pci->subsystem_vendor;
-
-       if (0 != btv->cardid && 0xffffffff != btv->cardid) {
-               /* look for the card */
-               for (type = -1, i = 0; cards[i].id != 0; i++)
-                       if (cards[i].id  == btv->cardid)
-                               type = i;
-
-               if (type != -1) {
-                       /* found it */
-                       pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
-                               btv->c.nr, cards[type].name, cards[type].cardnr,
-                               btv->cardid & 0xffff,
-                               (btv->cardid >> 16) & 0xffff);
-                       btv->c.type = cards[type].cardnr;
-               } else {
-                       /* 404 */
-                       pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
-                               btv->c.nr, btv->cardid & 0xffff,
-                               (btv->cardid >> 16) & 0xffff);
-                       pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
-               }
-       }
-
-       /* let the user override the autodetected type */
-       if (card[btv->c.nr] < bttv_num_tvcards)
-               btv->c.type=card[btv->c.nr];
-
-       /* print which card config we are using */
-       pr_info("%d: using: %s [card=%d,%s]\n",
-               btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
-               card[btv->c.nr] < bttv_num_tvcards
-               ? "insmod option" : "autodetected");
-
-       /* overwrite gpio stuff ?? */
-       if (UNSET == audioall && UNSET == audiomux[0])
-               return;
-
-       if (UNSET != audiomux[0]) {
-               gpiobits = 0;
-               for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
-                       bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
-                       gpiobits |= audiomux[i];
-               }
-       } else {
-               gpiobits = audioall;
-               for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
-                       bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
-               }
-       }
-       bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
-       pr_info("%d: gpio config override: mask=0x%x, mux=",
-               btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
-       for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
-               pr_cont("%s0x%x",
-                       i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
-       }
-       pr_cont("\n");
-}
-
-/*
- * (most) board specific initialisations goes here
- */
-
-/* Some Modular Technology cards have an eeprom, but no subsystem ID */
-static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
-{
-       int type = -1;
-
-       if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13))
-               type = BTTV_BOARD_MODTEC_205;
-       else if (0 == strncmp(eeprom_data+20,"Picolo",7))
-               type = BTTV_BOARD_EURESYS_PICOLO;
-       else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0)
-               type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */
-
-       if (-1 != type) {
-               btv->c.type = type;
-               pr_info("%d: detected by eeprom: %s [card=%d]\n",
-                       btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
-       }
-}
-
-static void flyvideo_gpio(struct bttv *btv)
-{
-       int gpio, has_remote, has_radio, is_capture_only;
-       int is_lr90, has_tda9820_tda9821;
-       int tuner_type = UNSET, ttype;
-
-       gpio_inout(0xffffff, 0);
-       udelay(8);  /* without this we would see the 0x1800 mask */
-       gpio = gpio_read();
-       /* FIXME: must restore OUR_EN ??? */
-
-       /* all cards provide GPIO info, some have an additional eeprom
-        * LR50: GPIO coding can be found lower right CP1 .. CP9
-        *       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
-        *       GPIO14-12: n.c.
-        * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-
-        * lowest 3 bytes are remote control codes (no handshake needed)
-        * xxxFFF: No remote control chip soldered
-        * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
-        * Note: Some bits are Audio_Mask !
-        */
-       ttype = (gpio & 0x0f0000) >> 16;
-       switch (ttype) {
-       case 0x0:
-               tuner_type = 2;  /* NTSC, e.g. TPI8NSR11P */
-               break;
-       case 0x2:
-               tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
-               break;
-       case 0x4:
-               tuner_type = 5;  /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
-               break;
-       case 0x6:
-               tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
-               break;
-       case 0xC:
-               tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
-               break;
-       default:
-               pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
-               break;
-       }
-
-       has_remote          =   gpio & 0x800000;
-       has_radio           =   gpio & 0x400000;
-       /*   unknown                   0x200000;
-        *   unknown2                  0x100000; */
-       is_capture_only     = !(gpio & 0x008000); /* GPIO15 */
-       has_tda9820_tda9821 = !(gpio & 0x004000);
-       is_lr90             = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
-       /*
-        * gpio & 0x001000    output bit for audio routing */
-
-       if (is_capture_only)
-               tuner_type = TUNER_ABSENT; /* No tuner present */
-
-       pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
-               btv->c.nr, has_radio ? "yes" : "no",
-               has_remote ? "yes" : "no", tuner_type, gpio);
-       pr_info("%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-               btv->c.nr, is_lr90 ? "yes" : "no",
-               has_tda9820_tda9821 ? "yes" : "no",
-               is_capture_only ? "yes" : "no");
-
-       if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
-               btv->tuner_type = tuner_type;
-       btv->has_radio = has_radio;
-
-       /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
-        * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
-        * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
-       if (has_tda9820_tda9821)
-               btv->audio_mode_gpio = lt9415_audio;
-       /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
-}
-
-static int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
-                              14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
-static int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
-                              1,1,1,1,   1,1,1,0,  0,0,0,0,  0,1,0,0 };
-
-static void miro_pinnacle_gpio(struct bttv *btv)
-{
-       int id,msp,gpio;
-       char *info;
-
-       gpio_inout(0xffffff, 0);
-       gpio = gpio_read();
-       id   = ((gpio>>10) & 63) -1;
-       msp  = bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx");
-       if (id < 32) {
-               btv->tuner_type = miro_tunermap[id];
-               if (0 == (gpio & 0x20)) {
-                       btv->has_radio = 1;
-                       if (!miro_fmtuner[id]) {
-                               btv->has_matchbox = 1;
-                               btv->mbox_we    = (1<<6);
-                               btv->mbox_most  = (1<<7);
-                               btv->mbox_clk   = (1<<8);
-                               btv->mbox_data  = (1<<9);
-                               btv->mbox_mask  = (1<<6)|(1<<7)|(1<<8)|(1<<9);
-                       }
-               } else {
-                       btv->has_radio = 0;
-               }
-               if (-1 != msp) {
-                       if (btv->c.type == BTTV_BOARD_MIRO)
-                               btv->c.type = BTTV_BOARD_MIROPRO;
-                       if (btv->c.type == BTTV_BOARD_PINNACLE)
-                               btv->c.type = BTTV_BOARD_PINNACLEPRO;
-               }
-               pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
-                       btv->c.nr, id+1, btv->tuner_type,
-                       !btv->has_radio ? "no" :
-                       (btv->has_matchbox ? "matchbox" : "fmtuner"),
-                       (-1 == msp) ? "no" : "yes");
-       } else {
-               /* new cards with microtune tuner */
-               id = 63 - id;
-               btv->has_radio = 0;
-               switch (id) {
-               case 1:
-                       info = "PAL / mono";
-                       btv->tda9887_conf = TDA9887_INTERCARRIER;
-                       break;
-               case 2:
-                       info = "PAL+SECAM / stereo";
-                       btv->has_radio = 1;
-                       btv->tda9887_conf = TDA9887_QSS;
-                       break;
-               case 3:
-                       info = "NTSC / stereo";
-                       btv->has_radio = 1;
-                       btv->tda9887_conf = TDA9887_QSS;
-                       break;
-               case 4:
-                       info = "PAL+SECAM / mono";
-                       btv->tda9887_conf = TDA9887_QSS;
-                       break;
-               case 5:
-                       info = "NTSC / mono";
-                       btv->tda9887_conf = TDA9887_INTERCARRIER;
-                       break;
-               case 6:
-                       info = "NTSC / stereo";
-                       btv->tda9887_conf = TDA9887_INTERCARRIER;
-                       break;
-               case 7:
-                       info = "PAL / stereo";
-                       btv->tda9887_conf = TDA9887_INTERCARRIER;
-                       break;
-               default:
-                       info = "oops: unknown card";
-                       break;
-               }
-               if (-1 != msp)
-                       btv->c.type = BTTV_BOARD_PINNACLEPRO;
-               pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
-                       btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
-               btv->tuner_type = TUNER_MT2032;
-       }
-}
-
-/* GPIO21   L: Buffer aktiv, H: Buffer inaktiv */
-#define LM1882_SYNC_DRIVE     0x200000L
-
-static void init_ids_eagle(struct bttv *btv)
-{
-       gpio_inout(0xffffff,0xFFFF37);
-       gpio_write(0x200020);
-
-       /* flash strobe inverter ?! */
-       gpio_write(0x200024);
-
-       /* switch sync drive off */
-       gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
-
-       /* set BT848 muxel to 2 */
-       btaor((2)<<5, ~(2<<5), BT848_IFORM);
-}
-
-/* Muxsel helper for the IDS Eagle.
- * the eagles does not use the standard muxsel-bits but
- * has its own multiplexer */
-static void eagle_muxsel(struct bttv *btv, unsigned int input)
-{
-       gpio_bits(3, input & 3);
-
-       /* composite */
-       /* set chroma ADC to sleep */
-       btor(BT848_ADC_C_SLEEP, BT848_ADC);
-       /* set to composite video */
-       btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
-       btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
-
-       /* switch sync drive off */
-       gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
-}
-
-static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
-{
-       static const int masks[] = {0x30, 0x01, 0x12, 0x23};
-       gpio_write(masks[input%4]);
-}
-
-/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and
-   alarms output
-
-   GPIObit    | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-   assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1|   |   |
-
-   IN - sensor inputs, INx - sensor inputs and TI XORed together
-   O1,O2,O3 - alarm outputs (relays)
-
-   OUT ENABLE   1    1   0  . 1  1   0   0 . 0   0   0    0   = 0x6C0
-
-*/
-
-static void init_lmlbt4x(struct bttv *btv)
-{
-       pr_debug("LMLBT4x init\n");
-       btwrite(0x000000, BT848_GPIO_REG_INP);
-       gpio_inout(0xffffff, 0x0006C0);
-       gpio_write(0x000000);
-}
-
-static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input)
-{
-       unsigned int inmux = input % 8;
-       gpio_inout( 0xf, 0xf );
-       gpio_bits( 0xf, inmux );
-}
-
-static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
-{
-       unsigned int inmux = input % 4;
-       gpio_inout( 3<<9, 3<<9 );
-       gpio_bits( 3<<9, inmux<<9 );
-}
-
-static void geovision_muxsel(struct bttv *btv, unsigned int input)
-{
-       unsigned int inmux = input % 16;
-       gpio_inout(0xf, 0xf);
-       gpio_bits(0xf, inmux);
-}
-
-/*
- * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878.
- * The first 74HC4051 has the lower 8 inputs, the second one the higher 8.
- * The muxes are controlled via a 74HC373 latch which is connected to
- * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch.
- * Q0 of the latch is connected to the Enable (~E) input of the first
- * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051.
- * Q4 - Q7 are connected to the second 74HC4051 in the same way.
- */
-
-static void td3116_latch_value(struct bttv *btv, u32 value)
-{
-       gpio_bits((1<<18) | 0xff, value);
-       gpio_bits((1<<18) | 0xff, (1<<18) | value);
-       udelay(1);
-       gpio_bits((1<<18) | 0xff, value);
-}
-
-static void td3116_muxsel(struct bttv *btv, unsigned int input)
-{
-       u32 value;
-       u32 highbit;
-
-       highbit = (input & 0x8) >> 3 ;
-
-       /* Disable outputs and set value in the mux */
-       value = 0x11; /* Disable outputs */
-       value |= ((input & 0x7) << 1)  << (4 * highbit);
-       td3116_latch_value(btv, value);
-
-       /* Enable the correct output */
-       value &= ~0x11;
-       value |= ((highbit ^ 0x1) << 4) | highbit;
-       td3116_latch_value(btv, value);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void bttv_reset_audio(struct bttv *btv)
-{
-       /*
-        * BT878A has a audio-reset register.
-        * 1. This register is an audio reset function but it is in
-        *    function-0 (video capture) address space.
-        * 2. It is enough to do this once per power-up of the card.
-        * 3. There is a typo in the Conexant doc -- it is not at
-        *    0x5B, but at 0x058. (B is an odd-number, obviously a typo!).
-        * --//Shrikumar 030609
-        */
-       if (btv->id != 878)
-               return;
-
-       if (bttv_debug)
-               pr_debug("%d: BT878A ARESET\n", btv->c.nr);
-       btwrite((1<<7), 0x058);
-       udelay(10);
-       btwrite(     0, 0x058);
-}
-
-/* initialization part one -- before registering i2c bus */
-void __devinit bttv_init_card1(struct bttv *btv)
-{
-       switch (btv->c.type) {
-       case BTTV_BOARD_HAUPPAUGE:
-       case BTTV_BOARD_HAUPPAUGE878:
-               boot_msp34xx(btv,5);
-               break;
-       case BTTV_BOARD_VOODOOTV_200:
-       case BTTV_BOARD_VOODOOTV_FM:
-               boot_msp34xx(btv,20);
-               break;
-       case BTTV_BOARD_AVERMEDIA98:
-               boot_msp34xx(btv,11);
-               break;
-       case BTTV_BOARD_HAUPPAUGEPVR:
-               pvr_boot(btv);
-               break;
-       case BTTV_BOARD_TWINHAN_DST:
-       case BTTV_BOARD_AVDVBT_771:
-       case BTTV_BOARD_PINNACLESAT:
-               btv->use_i2c_hw = 1;
-               break;
-       case BTTV_BOARD_ADLINK_RTV24:
-               init_RTV24( btv );
-               break;
-
-       }
-       if (!bttv_tvcards[btv->c.type].has_dvb)
-               bttv_reset_audio(btv);
-}
-
-/* initialization part two -- after registering i2c bus */
-void __devinit bttv_init_card2(struct bttv *btv)
-{
-       btv->tuner_type = UNSET;
-
-       if (BTTV_BOARD_UNKNOWN == btv->c.type) {
-               bttv_readee(btv,eeprom_data,0xa0);
-               identify_by_eeprom(btv,eeprom_data);
-       }
-
-       switch (btv->c.type) {
-       case BTTV_BOARD_MIRO:
-       case BTTV_BOARD_MIROPRO:
-       case BTTV_BOARD_PINNACLE:
-       case BTTV_BOARD_PINNACLEPRO:
-               /* miro/pinnacle */
-               miro_pinnacle_gpio(btv);
-               break;
-       case BTTV_BOARD_FLYVIDEO_98:
-       case BTTV_BOARD_MAXI:
-       case BTTV_BOARD_LIFE_FLYKIT:
-       case BTTV_BOARD_FLYVIDEO:
-       case BTTV_BOARD_TYPHOON_TVIEW:
-       case BTTV_BOARD_CHRONOS_VS2:
-       case BTTV_BOARD_FLYVIDEO_98FM:
-       case BTTV_BOARD_FLYVIDEO2000:
-       case BTTV_BOARD_FLYVIDEO98EZ:
-       case BTTV_BOARD_CONFERENCETV:
-       case BTTV_BOARD_LIFETEC_9415:
-               flyvideo_gpio(btv);
-               break;
-       case BTTV_BOARD_HAUPPAUGE:
-       case BTTV_BOARD_HAUPPAUGE878:
-       case BTTV_BOARD_HAUPPAUGEPVR:
-               /* pick up some config infos from the eeprom */
-               bttv_readee(btv,eeprom_data,0xa0);
-               hauppauge_eeprom(btv);
-               break;
-       case BTTV_BOARD_AVERMEDIA98:
-       case BTTV_BOARD_AVPHONE98:
-               bttv_readee(btv,eeprom_data,0xa0);
-               avermedia_eeprom(btv);
-               break;
-       case BTTV_BOARD_PXC200:
-               init_PXC200(btv);
-               break;
-       case BTTV_BOARD_PICOLO_TETRA_CHIP:
-               picolo_tetra_init(btv);
-               break;
-       case BTTV_BOARD_VHX:
-               btv->has_radio    = 1;
-               btv->has_matchbox = 1;
-               btv->mbox_we      = 0x20;
-               btv->mbox_most    = 0;
-               btv->mbox_clk     = 0x08;
-               btv->mbox_data    = 0x10;
-               btv->mbox_mask    = 0x38;
-               break;
-       case BTTV_BOARD_VOBIS_BOOSTAR:
-       case BTTV_BOARD_TERRATV:
-               terratec_active_radio_upgrade(btv);
-               break;
-       case BTTV_BOARD_MAGICTVIEW061:
-               if (btv->cardid == 0x3002144f) {
-                       btv->has_radio=1;
-                       pr_info("%d: radio detected by subsystem id (CPH05x)\n",
-                               btv->c.nr);
-               }
-               break;
-       case BTTV_BOARD_STB2:
-               if (btv->cardid == 0x3060121a) {
-                       /* Fix up entry for 3DFX VoodooTV 100,
-                          which is an OEM STB card variant. */
-                       btv->has_radio=0;
-                       btv->tuner_type=TUNER_TEMIC_NTSC;
-               }
-               break;
-       case BTTV_BOARD_OSPREY1x0:
-       case BTTV_BOARD_OSPREY1x0_848:
-       case BTTV_BOARD_OSPREY101_848:
-       case BTTV_BOARD_OSPREY1x1:
-       case BTTV_BOARD_OSPREY1x1_SVID:
-       case BTTV_BOARD_OSPREY2xx:
-       case BTTV_BOARD_OSPREY2x0_SVID:
-       case BTTV_BOARD_OSPREY2x0:
-       case BTTV_BOARD_OSPREY440:
-       case BTTV_BOARD_OSPREY500:
-       case BTTV_BOARD_OSPREY540:
-       case BTTV_BOARD_OSPREY2000:
-               bttv_readee(btv,eeprom_data,0xa0);
-               osprey_eeprom(btv, eeprom_data);
-               break;
-       case BTTV_BOARD_IDS_EAGLE:
-               init_ids_eagle(btv);
-               break;
-       case BTTV_BOARD_MODTEC_205:
-               bttv_readee(btv,eeprom_data,0xa0);
-               modtec_eeprom(btv);
-               break;
-       case BTTV_BOARD_LMLBT4:
-               init_lmlbt4x(btv);
-               break;
-       case BTTV_BOARD_TIBET_CS16:
-               tibetCS16_init(btv);
-               break;
-       case BTTV_BOARD_KODICOM_4400R:
-               kodicom4400r_init(btv);
-               break;
-       case BTTV_BOARD_GEOVISION_GV800S:
-               gv800s_init(btv);
-               break;
-       }
-
-       /* pll configuration */
-       if (!(btv->id==848 && btv->revision==0x11)) {
-               /* defaults from card list */
-               if (PLL_28 == bttv_tvcards[btv->c.type].pll) {
-                       btv->pll.pll_ifreq=28636363;
-                       btv->pll.pll_crystal=BT848_IFORM_XT0;
-               }
-               if (PLL_35 == bttv_tvcards[btv->c.type].pll) {
-                       btv->pll.pll_ifreq=35468950;
-                       btv->pll.pll_crystal=BT848_IFORM_XT1;
-               }
-               /* insmod options can override */
-               switch (pll[btv->c.nr]) {
-               case 0: /* none */
-                       btv->pll.pll_crystal = 0;
-                       btv->pll.pll_ifreq   = 0;
-                       btv->pll.pll_ofreq   = 0;
-                       break;
-               case 1: /* 28 MHz */
-               case 28:
-                       btv->pll.pll_ifreq   = 28636363;
-                       btv->pll.pll_ofreq   = 0;
-                       btv->pll.pll_crystal = BT848_IFORM_XT0;
-                       break;
-               case 2: /* 35 MHz */
-               case 35:
-                       btv->pll.pll_ifreq   = 35468950;
-                       btv->pll.pll_ofreq   = 0;
-                       btv->pll.pll_crystal = BT848_IFORM_XT1;
-                       break;
-               }
-       }
-       btv->pll.pll_current = -1;
-
-       /* tuner configuration (from card list / autodetect / insmod option) */
-       if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
-               if (UNSET == btv->tuner_type)
-                       btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
-       if (UNSET != tuner[btv->c.nr])
-               btv->tuner_type = tuner[btv->c.nr];
-
-       if (btv->tuner_type == TUNER_ABSENT)
-               pr_info("%d: tuner absent\n", btv->c.nr);
-       else if (btv->tuner_type == UNSET)
-               pr_warn("%d: tuner type unset\n", btv->c.nr);
-       else
-               pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
-
-       if (autoload != UNSET) {
-               pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
-               pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
-                       btv->c.nr);
-       }
-
-       if (UNSET == btv->tuner_type)
-               btv->tuner_type = TUNER_ABSENT;
-
-       btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
-                  bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
-       btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
-                   UNSET : bttv_tvcards[btv->c.type].svhs;
-       if (svhs[btv->c.nr] != UNSET)
-               btv->svhs = svhs[btv->c.nr];
-       if (remote[btv->c.nr] != UNSET)
-               btv->has_remote = remote[btv->c.nr];
-
-       if (bttv_tvcards[btv->c.type].has_radio)
-               btv->has_radio = 1;
-       if (bttv_tvcards[btv->c.type].has_remote)
-               btv->has_remote = 1;
-       if (!bttv_tvcards[btv->c.type].no_gpioirq)
-               btv->gpioirq = 1;
-       if (bttv_tvcards[btv->c.type].volume_gpio)
-               btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
-       if (bttv_tvcards[btv->c.type].audio_mode_gpio)
-               btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
-
-       if (btv->tuner_type == TUNER_ABSENT)
-               return;  /* no tuner or related drivers to load */
-
-       if (btv->has_saa6588 || saa6588[btv->c.nr]) {
-               /* Probe for RDS receiver chip */
-               static const unsigned short addrs[] = {
-                       0x20 >> 1,
-                       0x22 >> 1,
-                       I2C_CLIENT_END
-               };
-               struct v4l2_subdev *sd;
-
-               sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, "saa6588", 0, addrs);
-               btv->has_saa6588 = (sd != NULL);
-       }
-
-       /* try to detect audio/fader chips */
-
-       /* First check if the user specified the audio chip via a module
-          option. */
-
-       switch (audiodev[btv->c.nr]) {
-       case -1:
-               return; /* do not load any audio module */
-
-       case 0: /* autodetect */
-               break;
-
-       case 1: {
-               /* The user specified that we should probe for msp3400 */
-               static const unsigned short addrs[] = {
-                       I2C_ADDR_MSP3400 >> 1,
-                       I2C_ADDR_MSP3400_ALT >> 1,
-                       I2C_CLIENT_END
-               };
-
-               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, "msp3400", 0, addrs);
-               if (btv->sd_msp34xx)
-                       return;
-               goto no_audio;
-       }
-
-       case 2: {
-               /* The user specified that we should probe for tda7432 */
-               static const unsigned short addrs[] = {
-                       I2C_ADDR_TDA7432 >> 1,
-                       I2C_CLIENT_END
-               };
-
-               if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tda7432", 0, addrs))
-                       return;
-               goto no_audio;
-       }
-
-       case 3: {
-               /* The user specified that we should probe for tvaudio */
-               btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
-               if (btv->sd_tvaudio)
-                       return;
-               goto no_audio;
-       }
-
-       default:
-               pr_warn("%d: unknown audiodev value!\n", btv->c.nr);
-               return;
-       }
-
-       /* There were no overrides, so now we try to discover this through the
-          card definition */
-
-       /* probe for msp3400 first: this driver can detect whether or not
-          it really is a msp3400, so it will return NULL when the device
-          found is really something else (e.g. a tea6300). */
-       if (!bttv_tvcards[btv->c.type].no_msp34xx) {
-               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, "msp3400",
-                       0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1));
-       } else if (bttv_tvcards[btv->c.type].msp34xx_alt) {
-               btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                       &btv->c.i2c_adap, "msp3400",
-                       0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1));
-       }
-
-       /* If we found a msp34xx, then we're done. */
-       if (btv->sd_msp34xx)
-               return;
-
-       /* it might also be a tda7432. */
-       if (!bttv_tvcards[btv->c.type].no_tda7432) {
-               static const unsigned short addrs[] = {
-                       I2C_ADDR_TDA7432 >> 1,
-                       I2C_CLIENT_END
-               };
-
-               if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tda7432", 0, addrs))
-                       return;
-       }
-
-       /* Now see if we can find one of the tvaudio devices. */
-       btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-               &btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
-       if (btv->sd_tvaudio)
-               return;
-
-no_audio:
-       pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
-}
-
-
-/* initialize the tuner */
-void __devinit bttv_init_tuner(struct bttv *btv)
-{
-       int addr = ADDR_UNSET;
-
-       if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
-               addr = bttv_tvcards[btv->c.type].tuner_addr;
-
-       if (btv->tuner_type != TUNER_ABSENT) {
-               struct tuner_setup tun_setup;
-
-               /* Load tuner module before issuing tuner config call! */
-               if (btv->has_radio)
-                       v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
-               v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
-
-               tun_setup.mode_mask = T_ANALOG_TV;
-               tun_setup.type = btv->tuner_type;
-               tun_setup.addr = addr;
-
-               if (btv->has_radio)
-                       tun_setup.mode_mask |= T_RADIO;
-
-               bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
-       }
-
-       if (btv->tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv = &btv->tda9887_conf;
-
-               bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
-       }
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void modtec_eeprom(struct bttv *btv)
-{
-       if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
-               btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
-               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
-                       btv->c.nr, &eeprom_data[0x1e]);
-       } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
-               btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
-               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
-                       btv->c.nr, &eeprom_data[0x1e]);
-       } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
-               btv->tuner_type=TUNER_PHILIPS_NTSC;
-               pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
-                       btv->c.nr, &eeprom_data[0x1e]);
-       } else {
-               pr_info("%d: Modtec: Unknown TunerString: %s\n",
-                       btv->c.nr, &eeprom_data[0x1e]);
-       }
-}
-
-static void __devinit hauppauge_eeprom(struct bttv *btv)
-{
-       struct tveeprom tv;
-
-       tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
-       btv->tuner_type = tv.tuner_type;
-       btv->has_radio  = tv.has_radio;
-
-       pr_info("%d: Hauppauge eeprom indicates model#%d\n",
-               btv->c.nr, tv.model);
-
-       /*
-        * Some of the 878 boards have duplicate PCI IDs. Switch the board
-        * type based on model #.
-        */
-       if(tv.model == 64900) {
-               pr_info("%d: Switching board type from %s to %s\n",
-                       btv->c.nr,
-                       bttv_tvcards[btv->c.type].name,
-                       bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
-               btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
-       }
-
-       /* The 61334 needs the msp3410 to do the radio demod to get sound */
-       if (tv.model == 61334)
-               btv->radio_uses_msp_demodulator = 1;
-}
-
-static int terratec_active_radio_upgrade(struct bttv *btv)
-{
-       int freq;
-
-       btv->has_radio    = 1;
-       btv->has_matchbox = 1;
-       btv->mbox_we      = 0x10;
-       btv->mbox_most    = 0x20;
-       btv->mbox_clk     = 0x08;
-       btv->mbox_data    = 0x04;
-       btv->mbox_mask    = 0x3c;
-
-       btv->mbox_iow     = 1 <<  8;
-       btv->mbox_ior     = 1 <<  9;
-       btv->mbox_csel    = 1 << 10;
-
-       freq=88000/62.5;
-       tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
-       if (0x1ed8 == tea5757_read(btv)) {
-               pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
-               btv->has_radio    = 1;
-               btv->has_saa6588  = 1;
-               btv->has_matchbox = 1;
-       } else {
-               btv->has_radio    = 0;
-               btv->has_matchbox = 0;
-       }
-       return 0;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-/*
- * minimal bootstrap for the WinTV/PVR -- upload altera firmware.
- *
- * The hcwamc.rbf firmware file is on the Hauppauge driver CD.  Have
- * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be
- * unpacked with unzip).
- */
-#define PVR_GPIO_DELAY         10
-
-#define BTTV_ALT_DATA          0x000001
-#define BTTV_ALT_DCLK          0x100000
-#define BTTV_ALT_NCONFIG       0x800000
-
-static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
-                                    u32 microlen)
-{
-       u32 n;
-       u8 bits;
-       int i;
-
-       gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG);
-       gpio_write(0);
-       udelay(PVR_GPIO_DELAY);
-
-       gpio_write(BTTV_ALT_NCONFIG);
-       udelay(PVR_GPIO_DELAY);
-
-       for (n = 0; n < microlen; n++) {
-               bits = micro[n];
-               for (i = 0 ; i < 8 ; i++) {
-                       gpio_bits(BTTV_ALT_DCLK,0);
-                       if (bits & 0x01)
-                               gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
-                       else
-                               gpio_bits(BTTV_ALT_DATA,0);
-                       gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
-                       bits >>= 1;
-               }
-       }
-       gpio_bits(BTTV_ALT_DCLK,0);
-       udelay(PVR_GPIO_DELAY);
-
-       /* begin Altera init loop (Not necessary,but doesn't hurt) */
-       for (i = 0 ; i < 30 ; i++) {
-               gpio_bits(BTTV_ALT_DCLK,0);
-               gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
-       }
-       gpio_bits(BTTV_ALT_DCLK,0);
-       return 0;
-}
-
-static int __devinit pvr_boot(struct bttv *btv)
-{
-       const struct firmware *fw_entry;
-       int rc;
-
-       rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
-       if (rc != 0) {
-               pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
-               return rc;
-       }
-       rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
-       pr_info("%d: altera firmware upload %s\n",
-               btv->c.nr, (rc < 0) ? "failed" : "ok");
-       release_firmware(fw_entry);
-       return rc;
-}
-
-/* ----------------------------------------------------------------------- */
-/* some osprey specific stuff                                              */
-
-static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
-{
-       int i;
-       u32 serial = 0;
-       int cardid = -1;
-
-       /* This code will nevery actually get called in this case.... */
-       if (btv->c.type == BTTV_BOARD_UNKNOWN) {
-               /* this might be an antique... check for MMAC label in eeprom */
-               if (!strncmp(ee, "MMAC", 4)) {
-                       u8 checksum = 0;
-                       for (i = 0; i < 21; i++)
-                               checksum += ee[i];
-                       if (checksum != ee[21])
-                               return;
-                       cardid = BTTV_BOARD_OSPREY1x0_848;
-                       for (i = 12; i < 21; i++)
-                               serial *= 10, serial += ee[i] - '0';
-               }
-       } else {
-               unsigned short type;
-
-               for (i = 4*16; i < 8*16; i += 16) {
-                       u16 checksum = ip_compute_csum(ee + i, 16);
-
-                       if ((checksum&0xff) + (checksum>>8) == 0xff)
-                               break;
-               }
-               if (i >= 8*16)
-                       return;
-               ee += i;
-
-               /* found a valid descriptor */
-               type = get_unaligned_be16((__be16 *)(ee+4));
-
-               switch(type) {
-               /* 848 based */
-               case 0x0004:
-                       cardid = BTTV_BOARD_OSPREY1x0_848;
-                       break;
-               case 0x0005:
-                       cardid = BTTV_BOARD_OSPREY101_848;
-                       break;
-
-               /* 878 based */
-               case 0x0012:
-               case 0x0013:
-                       cardid = BTTV_BOARD_OSPREY1x0;
-                       break;
-               case 0x0014:
-               case 0x0015:
-                       cardid = BTTV_BOARD_OSPREY1x1;
-                       break;
-               case 0x0016:
-               case 0x0017:
-               case 0x0020:
-                       cardid = BTTV_BOARD_OSPREY1x1_SVID;
-                       break;
-               case 0x0018:
-               case 0x0019:
-               case 0x001E:
-               case 0x001F:
-                       cardid = BTTV_BOARD_OSPREY2xx;
-                       break;
-               case 0x001A:
-               case 0x001B:
-                       cardid = BTTV_BOARD_OSPREY2x0_SVID;
-                       break;
-               case 0x0040:
-                       cardid = BTTV_BOARD_OSPREY500;
-                       break;
-               case 0x0050:
-               case 0x0056:
-                       cardid = BTTV_BOARD_OSPREY540;
-                       /* bttv_osprey_540_init(btv); */
-                       break;
-               case 0x0060:
-               case 0x0070:
-               case 0x00A0:
-                       cardid = BTTV_BOARD_OSPREY2x0;
-                       /* enable output on select control lines */
-                       gpio_inout(0xffffff,0x000303);
-                       break;
-               case 0x00D8:
-                       cardid = BTTV_BOARD_OSPREY440;
-                       break;
-               default:
-                       /* unknown...leave generic, but get serial # */
-                       pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
-                               btv->c.nr, type);
-                       break;
-               }
-               serial = get_unaligned_be32((__be32 *)(ee+6));
-       }
-
-       pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
-               btv->c.nr, cardid,
-               cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
-
-       if (cardid<0 || btv->c.type == cardid)
-               return;
-
-       /* card type isn't set correctly */
-       if (card[btv->c.nr] < bttv_num_tvcards) {
-               pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
-                       btv->c.nr);
-       } else {
-               pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
-                       btv->c.nr, btv->c.type, cardid);
-               btv->c.type = cardid;
-       }
-}
-
-/* ----------------------------------------------------------------------- */
-/* AVermedia specific stuff, from  bktr_card.c                             */
-
-static int tuner_0_table[] = {
-       TUNER_PHILIPS_NTSC,  TUNER_PHILIPS_PAL /* PAL-BG*/,
-       TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL /* PAL-I*/,
-       TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
-       TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
-       TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL,
-       TUNER_PHILIPS_FM1216ME_MK3 };
-
-static int tuner_1_table[] = {
-       TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
-       TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
-       TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
-       TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
-       TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
-
-static void __devinit avermedia_eeprom(struct bttv *btv)
-{
-       int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
-
-       tuner_make      = (eeprom_data[0x41] & 0x7);
-       tuner_tv_fm     = (eeprom_data[0x41] & 0x18) >> 3;
-       tuner_format    = (eeprom_data[0x42] & 0xf0) >> 4;
-       btv->has_remote = (eeprom_data[0x42] & 0x01);
-
-       if (tuner_make == 0 || tuner_make == 2)
-               if (tuner_format <= 0x0a)
-                       tuner_type = tuner_0_table[tuner_format];
-       if (tuner_make == 1)
-               if (tuner_format <= 9)
-                       tuner_type = tuner_1_table[tuner_format];
-
-       if (tuner_make == 4)
-               if (tuner_format == 0x09)
-                       tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
-
-       pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
-               btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
-       if (tuner_type) {
-               btv->tuner_type = tuner_type;
-               pr_cont("%d", tuner_type);
-       } else
-               pr_cont("Unknown type");
-       pr_cont(" radio:%s remote control:%s\n",
-              tuner_tv_fm     ? "yes" : "no",
-              btv->has_remote ? "yes" : "no");
-}
-
-/*
- * For Voodoo TV/FM and Voodoo 200.  These cards' tuners use a TDA9880
- * analog demod, which is not I2C controlled like the newer and more common
- * TDA9887 series.  Instead is has two tri-state input pins, S0 and S1,
- * that control the IF for the video and audio.  Apparently, bttv GPIO
- * 0x10000 is connected to S0.  S0 low selects a 38.9 MHz VIF for B/G/D/K/I
- * (i.e., PAL) while high selects 45.75 MHz for M/N (i.e., NTSC).
- */
-u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
-{
-
-       if (btv->audio == TVAUDIO_INPUT_TUNER) {
-               if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
-                       gpiobits |= 0x10000;
-               else
-                       gpiobits &= ~0x10000;
-       }
-
-       gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits);
-       return gpiobits;
-}
-
-
-/*
- * reset/enable the MSP on some Hauppauge cards
- * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
- *
- * Hauppauge:  pin  5
- * Voodoo:     pin 20
- */
-static void __devinit boot_msp34xx(struct bttv *btv, int pin)
-{
-       int mask = (1 << pin);
-
-       gpio_inout(mask,mask);
-       gpio_bits(mask,0);
-       mdelay(2);
-       udelay(500);
-       gpio_bits(mask,mask);
-
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"msp34xx");
-       if (bttv_verbose)
-               pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
-                       btv->c.nr, pin);
-}
-
-/* ----------------------------------------------------------------------- */
-/*  Imagenation L-Model PXC200 Framegrabber */
-/*  This is basically the same procedure as
- *  used by Alessandro Rubini in his pxc200
- *  driver, but using BTTV functions */
-
-static void __devinit init_PXC200(struct bttv *btv)
-{
-       static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
-                                           0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-                                           0x00 };
-       unsigned int i;
-       int tmp;
-       u32 val;
-
-       /* Initialise GPIO-connevted stuff */
-       gpio_inout(0xffffff, (1<<13));
-       gpio_write(0);
-       udelay(3);
-       gpio_write(1<<13);
-       /* GPIO inputs are pulled up, so no need to drive
-        * reset pin any longer */
-       gpio_bits(0xffffff, 0);
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"pxc200");
-
-       /*  we could/should try and reset/control the AD pots? but
-           right now  we simply  turned off the crushing.  Without
-           this the AGC drifts drifts
-           remember the EN is reverse logic -->
-           setting BT848_ADC_AGC_EN disable the AGC
-           tboult@eecs.lehigh.edu
-       */
-
-       btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
-
-       /*      Initialise MAX517 DAC */
-       pr_info("Setting DAC reference voltage level ...\n");
-       bttv_I2CWrite(btv,0x5E,0,0x80,1);
-
-       /*      Initialise 12C508 PIC */
-       /*      The I2CWrite and I2CRead commmands are actually to the
-        *      same chips - but the R/W bit is included in the address
-        *      argument so the numbers are different */
-
-
-       pr_info("Initialising 12C508 PIC chip ...\n");
-
-       /* First of all, enable the clock line. This is used in the PXC200-F */
-       val = btread(BT848_GPIO_DMA_CTL);
-       val |= BT848_GPIO_DMA_CTL_GPCLKMODE;
-       btwrite(val, BT848_GPIO_DMA_CTL);
-
-       /* Then, push to 0 the reset pin long enough to reset the *
-        * device same as above for the reset line, but not the same
-        * value sent to the GPIO-connected stuff
-        * which one is the good one? */
-       gpio_inout(0xffffff,(1<<2));
-       gpio_write(0);
-       udelay(10);
-       gpio_write(1<<2);
-
-       for (i = 0; i < ARRAY_SIZE(vals); i++) {
-               tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
-               if (tmp != -1) {
-                       pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
-                              vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
-               }
-       }
-
-       pr_info("PXC200 Initialised\n");
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-/*
- *  The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
- *  it. This apparently involves the following procedure for each 878 chip:
- *
- *  1) write 0x00C3FEFF to the GPIO_OUT_EN register
- *
- *  2)  write to GPIO_DATA
- *      - 0x0E
- *      - sleep 1ms
- *      - 0x10 + 0x0E
- *      - sleep 10ms
- *      - 0x0E
- *     read from GPIO_DATA into buf (uint_32)
- *      - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
- *                 error. ERROR_CPLD_Check_Failed stop.
- *
- *  3) write to GPIO_DATA
- *      - write 0x4400 + 0x0E
- *      - sleep 10ms
- *      - write 0x4410 + 0x0E
- *      - sleep 1ms
- *      - write 0x0E
- *     read from GPIO_DATA into buf (uint_32)
- *      - if ( buf>>18 & 0x01 ) || ( buf>>19 & 0x01 != 0 )
- *                error. ERROR_CPLD_Check_Failed.
- */
-/* ----------------------------------------------------------------------- */
-static void
-init_RTV24 (struct bttv *btv)
-{
-       uint32_t dataRead = 0;
-       long watchdog_value = 0x0E;
-
-       pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
-               btv->c.nr);
-
-       btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
-
-       btwrite (0 + watchdog_value, BT848_GPIO_DATA);
-       msleep (1);
-       btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
-       msleep (10);
-       btwrite (0 + watchdog_value, BT848_GPIO_DATA);
-
-       dataRead = btread (BT848_GPIO_DATA);
-
-       if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
-               pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
-                       btv->c.nr, dataRead);
-       }
-
-       btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
-       msleep (10);
-       btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
-       msleep (1);
-       btwrite (watchdog_value, BT848_GPIO_DATA);
-       msleep (1);
-       dataRead = btread (BT848_GPIO_DATA);
-
-       if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
-               pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
-                       btv->c.nr, dataRead);
-
-               return;
-       }
-
-       pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
-/*
- * Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
- * This code is placed under the terms of the GNU General Public License
- *
- * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
- */
-
-static void bus_low(struct bttv *btv, int bit)
-{
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-               udelay(5);
-       }
-
-       gpio_bits(bit,0);
-       udelay(5);
-
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-               udelay(5);
-       }
-}
-
-static void bus_high(struct bttv *btv, int bit)
-{
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-               udelay(5);
-       }
-
-       gpio_bits(bit,bit);
-       udelay(5);
-
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-               udelay(5);
-       }
-}
-
-static int bus_in(struct bttv *btv, int bit)
-{
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-               udelay(5);
-
-               gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
-               udelay(5);
-       }
-       return gpio_read() & (bit);
-}
-
-/* TEA5757 register bits */
-#define TEA_FREQ               0:14
-#define TEA_BUFFER             15:15
-
-#define TEA_SIGNAL_STRENGTH    16:17
-
-#define TEA_PORT1              18:18
-#define TEA_PORT0              19:19
-
-#define TEA_BAND               20:21
-#define TEA_BAND_FM            0
-#define TEA_BAND_MW            1
-#define TEA_BAND_LW            2
-#define TEA_BAND_SW            3
-
-#define TEA_MONO               22:22
-#define TEA_ALLOW_STEREO       0
-#define TEA_FORCE_MONO         1
-
-#define TEA_SEARCH_DIRECTION   23:23
-#define TEA_SEARCH_DOWN                0
-#define TEA_SEARCH_UP          1
-
-#define TEA_STATUS             24:24
-#define TEA_STATUS_TUNED       0
-#define TEA_STATUS_SEARCHING   1
-
-/* Low-level stuff */
-static int tea5757_read(struct bttv *btv)
-{
-       unsigned long timeout;
-       int value = 0;
-       int i;
-
-       /* better safe than sorry */
-       gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
-
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-               udelay(5);
-       }
-
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"tea5757 read");
-
-       bus_low(btv,btv->mbox_we);
-       bus_low(btv,btv->mbox_clk);
-
-       udelay(10);
-       timeout= jiffies + msecs_to_jiffies(1000);
-
-       /* wait for DATA line to go low; error if it doesn't */
-       while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
-               schedule();
-       if (bus_in(btv,btv->mbox_data)) {
-               pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
-               return -1;
-       }
-
-       dprintk("%d: tea5757:", btv->c.nr);
-       for (i = 0; i < 24; i++) {
-               udelay(5);
-               bus_high(btv,btv->mbox_clk);
-               udelay(5);
-               dprintk_cont("%c",
-                            bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
-               bus_low(btv,btv->mbox_clk);
-               value <<= 1;
-               value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
-               dprintk_cont("%c",
-                            bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
-       }
-       dprintk_cont("\n");
-       dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
-       return value;
-}
-
-static int tea5757_write(struct bttv *btv, int value)
-{
-       int i;
-       int reg = value;
-
-       gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
-
-       if (btv->mbox_ior) {
-               gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
-                         btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
-               udelay(5);
-       }
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"tea5757 write");
-
-       dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
-       bus_low(btv,btv->mbox_clk);
-       bus_high(btv,btv->mbox_we);
-       for (i = 0; i < 25; i++) {
-               if (reg & 0x1000000)
-                       bus_high(btv,btv->mbox_data);
-               else
-                       bus_low(btv,btv->mbox_data);
-               reg <<= 1;
-               bus_high(btv,btv->mbox_clk);
-               udelay(10);
-               bus_low(btv,btv->mbox_clk);
-               udelay(10);
-       }
-       bus_low(btv,btv->mbox_we);  /* unmute !!! */
-       return 0;
-}
-
-void tea5757_set_freq(struct bttv *btv, unsigned short freq)
-{
-       dprintk("tea5757_set_freq %d\n",freq);
-       tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
-}
-
-/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
- *
- * This is needed because rv605 don't use a normal multiplex, but a crosspoint
- * switch instead (CD22M3494E). This IC can have multiple active connections
- * between Xn (input) and Yn (output) pins. We need to clear any existing
- * connection prior to establish a new one, pulsing the STROBE pin.
- *
- * The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin.
- * GPIO pins are wired as:
- *  GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroller)
- *  GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroller)
- *  GPIO[7]   - DATA (xpoint)    - P1[7] (microcontroller)
- *  GPIO[8]   -                  - P3[5] (microcontroller)
- *  GPIO[9]   - RESET (xpoint)   - P3[6] (microcontroller)
- *  GPIO[10]  - STROBE (xpoint)  - P3[7] (microcontroller)
- *  GPINTR    -                  - P3[4] (microcontroller)
- *
- * The microcontroller is a 80C32 like. It should be possible to change xpoint
- * configuration either directly (as we are doing) or using the microcontroller
- * which is also wired to I2C interface. I have no further info on the
- * microcontroller features, one would need to disassembly the firmware.
- * note: the vendor refused to give any information on this product, all
- *       that stuff was found using a multimeter! :)
- */
-static void rv605_muxsel(struct bttv *btv, unsigned int input)
-{
-       static const u8 muxgpio[] = { 0x3, 0x1, 0x2, 0x4, 0xf, 0x7, 0xe, 0x0,
-                                     0xd, 0xb, 0xc, 0x6, 0x9, 0x5, 0x8, 0xa };
-
-       gpio_bits(0x07f, muxgpio[input]);
-
-       /* reset all conections */
-       gpio_bits(0x200,0x200);
-       mdelay(1);
-       gpio_bits(0x200,0x000);
-       mdelay(1);
-
-       /* create a new connection */
-       gpio_bits(0x480,0x480);
-       mdelay(1);
-       gpio_bits(0x480,0x080);
-       mdelay(1);
-}
-
-/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning]
- *
- * The CS16 (available on eBay cheap) is a PCI board with four Fusion
- * 878A chips, a PCI bridge, an Atmel microcontroller, four sync separator
- * chips, ten eight input analog multiplexors, a not chip and a few
- * other components.
- *
- * 16 inputs on a secondary bracket are provided and can be selected
- * from each of the four capture chips.  Two of the eight input
- * multiplexors are used to select from any of the 16 input signals.
- *
- * Unsupported hardware capabilities:
- *  . A video output monitor on the secondary bracket can be selected from
- *    one of the 878A chips.
- *  . Another passthrough but I haven't spent any time investigating it.
- *  . Digital I/O (logic level connected to GPIO) is available from an
- *    onboard header.
- *
- * The on chip input mux should always be set to 2.
- * GPIO[16:19] - Video input selection
- * GPIO[0:3]   - Video output monitor select (only available from one 878A)
- * GPIO[?:?]   - Digital I/O.
- *
- * There is an ATMEL microcontroller with an 8031 core on board.  I have not
- * determined what function (if any) it provides.  With the microcontroller
- * and sync separator chips a guess is that it might have to do with video
- * switching and maybe some digital I/O.
- */
-static void tibetCS16_muxsel(struct bttv *btv, unsigned int input)
-{
-       /* video mux */
-       gpio_bits(0x0f0000, input << 16);
-}
-
-static void tibetCS16_init(struct bttv *btv)
-{
-       /* enable gpio bits, mask obtained via btSpy */
-       gpio_inout(0xffffff, 0x0f7fff);
-       gpio_write(0x0f7fff);
-}
-
-/*
- * The following routines for the Kodicom-4400r get a little mind-twisting.
- * There is a "master" controller and three "slave" controllers, together
- * an analog switch which connects any of 16 cameras to any of the BT87A's.
- * The analog switch is controlled by the "master", but the detection order
- * of the four BT878A chips is in an order which I just don't understand.
- * The "master" is actually the second controller to be detected.  The
- * logic on the board uses logical numbers for the 4 controllers, but
- * those numbers are different from the detection sequence.  When working
- * with the analog switch, we need to "map" from the detection sequence
- * over to the board's logical controller number.  This mapping sequence
- * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
- * unit 3, the second (which is the master) is logical unit 0, etc.
- * We need to maintain the status of the analog switch (which of the 16
- * cameras is connected to which of the 4 controllers).  Rather than
- * add to the bttv structure for this, we use the data reserved for
- * the mbox (unused for this card type).
- */
-
-/*
- * First a routine to set the analog switch, which controls which camera
- * is routed to which controller.  The switch comprises an X-address
- * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
- * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
- * A data value (gpio bit 7) of '1' enables the switch, and '0' disables
- * the switch.  A STROBE bit (gpio bit 8) latches the data value into the
- * specified address.  The idea is to set the address and data, then bring
- * STROBE high, and finally bring STROBE back to low.
- */
-static void kodicom4400r_write(struct bttv *btv,
-                              unsigned char xaddr,
-                              unsigned char yaddr,
-                              unsigned char data) {
-       unsigned int udata;
-
-       udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf);
-       gpio_bits(0x1ff, udata);                /* write ADDR and DAT */
-       gpio_bits(0x1ff, udata | (1 << 8));     /* strobe high */
-       gpio_bits(0x1ff, udata);                /* strobe low */
-}
-
-/*
- * Next the mux select.  Both the "master" and "slave" 'cards' (controllers)
- * use this routine.  The routine finds the "master" for the card, maps
- * the controller number from the detected position over to the logical
- * number, writes the appropriate data to the analog switch, and housekeeps
- * the local copy of the switch information.  The parameter 'input' is the
- * requested camera number (0 - 15).
- */
-static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
-{
-       char *sw_status;
-       int xaddr, yaddr;
-       struct bttv *mctlr;
-       static unsigned char map[4] = {3, 0, 2, 1};
-
-       mctlr = master[btv->c.nr];
-       if (mctlr == NULL) {    /* ignore if master not yet detected */
-               return;
-       }
-       yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
-       yaddr = map[yaddr];
-       sw_status = (char *)(&mctlr->mbox_we);
-       xaddr = input & 0xf;
-       /* Check if the controller/camera pair has changed, else ignore */
-       if (sw_status[yaddr] != xaddr)
-       {
-               /* "open" the old switch, "close" the new one, save the new */
-               kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
-               sw_status[yaddr] = xaddr;
-               kodicom4400r_write(mctlr, xaddr, yaddr, 1);
-       }
-}
-
-/*
- * During initialisation, we need to reset the analog switch.  We
- * also preset the switch to map the 4 connectors on the card to the
- * *user's* (see above description of kodicom4400r_muxsel) channels
- * 0 through 3
- */
-static void kodicom4400r_init(struct bttv *btv)
-{
-       char *sw_status = (char *)(&btv->mbox_we);
-       int ix;
-
-       gpio_inout(0x0003ff, 0x0003ff);
-       gpio_write(1 << 9);     /* reset MUX */
-       gpio_write(0);
-       /* Preset camera 0 to the 4 controllers */
-       for (ix = 0; ix < 4; ix++) {
-               sw_status[ix] = ix;
-               kodicom4400r_write(btv, ix, ix, 1);
-       }
-       /*
-        * Since this is the "master", we need to set up the
-        * other three controller chips' pointers to this structure
-        * for later use in the muxsel routine.
-        */
-       if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3))
-           return;
-       master[btv->c.nr-1] = btv;
-       master[btv->c.nr]   = btv;
-       master[btv->c.nr+1] = btv;
-       master[btv->c.nr+2] = btv;
-}
-
-/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
- * video multiplexers to provide up to 16 video inputs. These
- * multiplexers are controlled by the lower 8 GPIO pins of the
- * bt878. The multiplexers probably Pericom PI5V331Q or similar.
-
- * xxx0 is pin xxx of multiplexer U5,
- * yyy1 is pin yyy of multiplexer U2
- */
-#define ENA0    0x01
-#define ENB0    0x02
-#define ENA1    0x04
-#define ENB1    0x08
-
-#define IN10    0x10
-#define IN00    0x20
-#define IN11    0x40
-#define IN01    0x80
-
-static void xguard_muxsel(struct bttv *btv, unsigned int input)
-{
-       static const int masks[] = {
-               ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10,
-               ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10,
-               ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11,
-               ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11,
-       };
-       gpio_write(masks[input%16]);
-}
-static void picolo_tetra_init(struct bttv *btv)
-{
-       /*This is the video input redirection fonctionality : I DID NOT USED IT. */
-       btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */
-       btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A]  set to 1*/
-}
-static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
-{
-
-       dprintk("%d : picolo_tetra_muxsel =>  input = %d\n", btv->c.nr, input);
-       /*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
-       /*GPIO[20]&GPIO[21] used to choose the right input*/
-       btwrite (input<<20,BT848_GPIO_DATA);
-
-}
-
-/*
- * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
- *
- * The IVC120G security card has 4 i2c controlled TDA8540 matrix
- * swichers to provide 16 channels to MUX0. The TDA8540's have
- * 4 independent outputs and as such the IVC120G also has the
- * optional "Monitor Out" bus. This allows the card to be looking
- * at one input while the monitor is looking at another.
- *
- * Since I've couldn't be bothered figuring out how to add an
- * independent muxsel for the monitor bus, I've just set it to
- * whatever the card is looking at.
- *
- *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
- *  OUT1 of the TDA8540's is connected to "Monitor Out"        (0x0C)
- *
- *  TDA8540_ALT3 IN0-3 = Channel 13 - 16       (0x03)
- *  TDA8540_ALT4 IN0-3 = Channel 1 - 4         (0x03)
- *  TDA8540_ALT5 IN0-3 = Channel 5 - 8         (0x03)
- *  TDA8540_ALT6 IN0-3 = Channel 9 - 12                (0x03)
- *
- */
-
-/* All 7 possible sub-ids for the TDA8540 Matrix Switcher */
-#define I2C_TDA8540        0x90
-#define I2C_TDA8540_ALT1   0x92
-#define I2C_TDA8540_ALT2   0x94
-#define I2C_TDA8540_ALT3   0x96
-#define I2C_TDA8540_ALT4   0x98
-#define I2C_TDA8540_ALT5   0x9a
-#define I2C_TDA8540_ALT6   0x9c
-
-static void ivc120_muxsel(struct bttv *btv, unsigned int input)
-{
-       /* Simple maths */
-       int key = input % 4;
-       int matrix = input / 4;
-
-       dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
-               btv->c.nr, input, matrix, key);
-
-       /* Handles the input selection on the TDA8540's */
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
-                     ((matrix == 3) ? (key | key << 2) : 0x00), 1);
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
-                     ((matrix == 0) ? (key | key << 2) : 0x00), 1);
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x00,
-                     ((matrix == 1) ? (key | key << 2) : 0x00), 1);
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
-                     ((matrix == 2) ? (key | key << 2) : 0x00), 1);
-
-       /* Handles the output enables on the TDA8540's */
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
-                     ((matrix == 3) ? 0x03 : 0x00), 1);  /* 13 - 16 */
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
-                     ((matrix == 0) ? 0x03 : 0x00), 1);  /* 1-4 */
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
-                     ((matrix == 1) ? 0x03 : 0x00), 1);  /* 5-8 */
-       bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
-                     ((matrix == 2) ? 0x03 : 0x00), 1);  /* 9-12 */
-
-       /* 878's MUX0 is already selected for input via muxsel values */
-}
-
-
-/* PXC200 muxsel helper
- * luke@syseng.anu.edu.au
- * another transplant
- * from Alessandro Rubini (rubini@linux.it)
- *
- * There are 4 kinds of cards:
- * PXC200L which is bt848
- * PXC200F which is bt848 with PIC controlling mux
- * PXC200AL which is bt878
- * PXC200AF which is bt878 with PIC controlling mux
- */
-#define PX_CFG_PXC200F 0x01
-#define PX_FLAG_PXC200A  0x00001000 /* a pxc200A is bt-878 based */
-#define PX_I2C_PIC       0x0f
-#define PX_PXC200A_CARDID 0x200a1295
-#define PX_I2C_CMD_CFG   0x00
-
-static void PXC200_muxsel(struct bttv *btv, unsigned int input)
-{
-       int rc;
-       long mux;
-       int bitmask;
-       unsigned char buf[2];
-
-       /* Read PIC config to determine if this is a PXC200F */
-       /* PX_I2C_CMD_CFG*/
-       buf[0]=0;
-       buf[1]=0;
-       rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
-       if (rc) {
-               pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
-                        btv->c.nr, rc);
-         /* not PXC ? do nothing */
-               return;
-       }
-
-       rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
-       if (!(rc & PX_CFG_PXC200F)) {
-               pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
-                        btv->c.nr, rc);
-               return;
-       }
-
-
-       /* The multiplexer in the 200F is handled by the GPIO port */
-       /* get correct mapping between inputs  */
-       /*  mux = bttv_tvcards[btv->type].muxsel[input] & 3; */
-       /* ** not needed!?   */
-       mux = input;
-
-       /* make sure output pins are enabled */
-       /* bitmask=0x30f; */
-       bitmask=0x302;
-       /* check whether we have a PXC200A */
-       if (btv->cardid == PX_PXC200A_CARDID)  {
-          bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */
-          bitmask |= 7<<4; /* the DAC */
-       }
-       btwrite(bitmask, BT848_GPIO_OUT_EN);
-
-       bitmask = btread(BT848_GPIO_DATA);
-       if (btv->cardid == PX_PXC200A_CARDID)
-         bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7);
-       else /* older device */
-         bitmask = (bitmask & ~0x300) | ((mux & 3) << 8);
-       btwrite(bitmask,BT848_GPIO_DATA);
-
-       /*
-        * Was "to be safe, set the bt848 to input 0"
-        * Actually, since it's ok at load time, better not messing
-        * with these bits (on PXC200AF you need to set mux 2 here)
-        *
-        * needed because bttv-driver sets mux before calling this function
-        */
-       if (btv->cardid == PX_PXC200A_CARDID)
-         btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM);
-       else /* older device */
-         btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
-
-       pr_debug("%d: setting input channel to:%d\n", btv->c.nr, (int)mux);
-}
-
-static void phytec_muxsel(struct bttv *btv, unsigned int input)
-{
-       unsigned int mux = input % 4;
-
-       if (input == btv->svhs)
-               mux = 0;
-
-       gpio_bits(0x3, mux);
-}
-
-/*
- * GeoVision GV-800(S) functions
- * Bruno Christo <bchristo@inf.ufsm.br>
-*/
-
-/* This is a function to control the analog switch, which determines which
- * camera is routed to which controller.  The switch comprises an X-address
- * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
- * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
- * A data value (gpio bit 18) of '1' enables the switch, and '0' disables
- * the switch.  A STROBE bit (gpio bit 17) latches the data value into the
- * specified address. There is also a chip select (gpio bit 16).
- * The idea is to set the address and chip select together, bring
- * STROBE high, write the data, and finally bring STROBE back to low.
- */
-static void gv800s_write(struct bttv *btv,
-                        unsigned char xaddr,
-                        unsigned char yaddr,
-                        unsigned char data) {
-       /* On the "master" 878A:
-       * GPIO bits 0-9 are used for the analog switch:
-       *   00 - 03:    camera selector
-       *   04 - 06:    878A (controller) selector
-       *   16:         cselect
-       *   17:         strobe
-       *   18:         data (1->on, 0->off)
-       *   19:         reset
-       */
-       const u32 ADDRESS = ((xaddr&0xf) | (yaddr&3)<<4);
-       const u32 CSELECT = 1<<16;
-       const u32 STROBE = 1<<17;
-       const u32 DATA = data<<18;
-
-       gpio_bits(0x1007f, ADDRESS | CSELECT);  /* write ADDRESS and CSELECT */
-       gpio_bits(0x20000, STROBE);             /* STROBE high */
-       gpio_bits(0x40000, DATA);               /* write DATA */
-       gpio_bits(0x20000, ~STROBE);            /* STROBE low */
-}
-
-/*
- * GeoVision GV-800(S) muxsel
- *
- * Each of the 4 cards (controllers) use this function.
- * The controller using this function selects the input through the GPIO pins
- * of the "master" card. A pointer to this card is stored in master[btv->c.nr].
- *
- * The parameter 'input' is the requested camera number (0-4) on the controller.
- * The map array has the address of each input. Note that the addresses in the
- * array are in the sequence the original GeoVision driver uses, that is, set
- * every controller to input 0, then to input 1, 2, 3, repeat. This means that
- * the physical "camera 1" connector corresponds to controller 0 input 0,
- * "camera 2" corresponds to controller 1 input 0, and so on.
- *
- * After getting the input address, the function then writes the appropriate
- * data to the analog switch, and housekeeps the local copy of the switch
- * information.
- */
-static void gv800s_muxsel(struct bttv *btv, unsigned int input)
-{
-       struct bttv *mctlr;
-       char *sw_status;
-       int xaddr, yaddr;
-       static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
-                                         { 0x1, 0x5, 0xb, 0x7 },
-                                         { 0x2, 0x8, 0xc, 0xe },
-                                         { 0x3, 0x9, 0xd, 0xf } };
-       input = input%4;
-       mctlr = master[btv->c.nr];
-       if (mctlr == NULL) {
-               /* do nothing until the "master" is detected */
-               return;
-       }
-       yaddr = (btv->c.nr - mctlr->c.nr) & 3;
-       sw_status = (char *)(&mctlr->mbox_we);
-       xaddr = map[yaddr][input] & 0xf;
-
-       /* Check if the controller/camera pair has changed, ignore otherwise */
-       if (sw_status[yaddr] != xaddr) {
-               /* disable the old switch, enable the new one and save status */
-               gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
-               sw_status[yaddr] = xaddr;
-               gv800s_write(mctlr, xaddr, yaddr, 1);
-       }
-}
-
-/* GeoVision GV-800(S) "master" chip init */
-static void gv800s_init(struct bttv *btv)
-{
-       char *sw_status = (char *)(&btv->mbox_we);
-       int ix;
-
-       gpio_inout(0xf107f, 0xf107f);
-       gpio_write(1<<19); /* reset the analog MUX */
-       gpio_write(0);
-
-       /* Preset camera 0 to the 4 controllers */
-       for (ix = 0; ix < 4; ix++) {
-               sw_status[ix] = ix;
-               gv800s_write(btv, ix, ix, 1);
-       }
-
-       /* Inputs on the "master" controller need this brightness fix */
-       bttv_I2CWrite(btv, 0x18, 0x5, 0x90, 1);
-
-       if (btv->c.nr > BTTV_MAX-4)
-               return;
-       /*
-        * Store the "master" controller pointer in the master
-        * array for later use in the muxsel function.
-        */
-       master[btv->c.nr]   = btv;
-       master[btv->c.nr+1] = btv;
-       master[btv->c.nr+2] = btv;
-       master[btv->c.nr+3] = btv;
-}
-
-/* ----------------------------------------------------------------------- */
-/* motherboard chipset specific stuff                                      */
-
-void __init bttv_check_chipset(void)
-{
-       int pcipci_fail = 0;
-       struct pci_dev *dev = NULL;
-
-       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))       /* should check if target is AGP */
-               pcipci_fail = 1;
-       if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
-               triton1 = 1;
-       if (pci_pci_problems & PCIPCI_VSFX)
-               vsfx = 1;
-#ifdef PCIPCI_ALIMAGIK
-       if (pci_pci_problems & PCIPCI_ALIMAGIK)
-               latency = 0x0A;
-#endif
-
-
-       /* print warnings about any quirks found */
-       if (triton1)
-               pr_info("Host bridge needs ETBF enabled\n");
-       if (vsfx)
-               pr_info("Host bridge needs VSFX enabled\n");
-       if (pcipci_fail) {
-               pr_info("bttv and your chipset may not work together\n");
-               if (!no_overlay) {
-                       pr_info("overlay will be disabled\n");
-                       no_overlay = 1;
-               } else {
-                       pr_info("overlay forced. Use this option at your own risk.\n");
-               }
-       }
-       if (UNSET != latency)
-               pr_info("pci latency fixup [%d]\n", latency);
-       while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                     PCI_DEVICE_ID_INTEL_82441, dev))) {
-               unsigned char b;
-               pci_read_config_byte(dev, 0x53, &b);
-               if (bttv_debug)
-                       pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
-                               b);
-       }
-}
-
-int __devinit bttv_handle_chipset(struct bttv *btv)
-{
-       unsigned char command;
-
-       if (!triton1 && !vsfx && UNSET == latency)
-               return 0;
-
-       if (bttv_verbose) {
-               if (triton1)
-                       pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
-                               btv->c.nr);
-               if (vsfx && btv->id >= 878)
-                       pr_info("%d: enabling VSFX\n", btv->c.nr);
-               if (UNSET != latency)
-                       pr_info("%d: setting pci timer to %d\n",
-                               btv->c.nr, latency);
-       }
-
-       if (btv->id < 878) {
-               /* bt848 (mis)uses a bit in the irq mask for etbf */
-               if (triton1)
-                       btv->triton1 = BT848_INT_ETBF;
-       } else {
-               /* bt878 has a bit in the pci config space for it */
-               pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command);
-               if (triton1)
-                       command |= BT878_EN_TBFX;
-               if (vsfx)
-                       command |= BT878_EN_VSFX;
-               pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command);
-       }
-       if (UNSET != latency)
-               pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
-       return 0;
-}
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
deleted file mode 100644 (file)
index b58ff87..0000000
+++ /dev/null
@@ -1,4630 +0,0 @@
-/*
-
-    bttv - Bt848 frame grabber driver
-
-    Copyright (C) 1996,97,98 Ralph  Metzler <rjkm@thp.uni-koeln.de>
-                          & Marcus Metzler <mocm@thp.uni-koeln.de>
-    (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
-
-    some v4l2 code lines are taken from Justin's bttv2 driver which is
-    (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
-
-    V4L1 removal from:
-    (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
-
-    Fixes to be fully V4L2 compliant by
-    (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
-
-    Cropping and overscan support
-    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
-    Sponsored by OPQ Systems AB
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/kdev_t.h>
-#include "bttvp.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/tvaudio.h>
-#include <media/msp3400.h>
-
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-#include <media/saa6588.h>
-
-#define BTTV_VERSION "0.9.19"
-
-unsigned int bttv_num;                 /* number of Bt848s in use */
-struct bttv *bttvs[BTTV_MAX];
-
-unsigned int bttv_debug;
-unsigned int bttv_verbose = 1;
-unsigned int bttv_gpio;
-
-/* config variables */
-#ifdef __BIG_ENDIAN
-static unsigned int bigendian=1;
-#else
-static unsigned int bigendian;
-#endif
-static unsigned int radio[BTTV_MAX];
-static unsigned int irq_debug;
-static unsigned int gbuffers = 8;
-static unsigned int gbufsize = 0x208000;
-static unsigned int reset_crop = 1;
-
-static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
-static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
-static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
-static int debug_latency;
-static int disable_ir;
-
-static unsigned int fdsr;
-
-/* options */
-static unsigned int combfilter;
-static unsigned int lumafilter;
-static unsigned int automute    = 1;
-static unsigned int chroma_agc;
-static unsigned int adc_crush   = 1;
-static unsigned int whitecrush_upper = 0xCF;
-static unsigned int whitecrush_lower = 0x7F;
-static unsigned int vcr_hack;
-static unsigned int irq_iswitch;
-static unsigned int uv_ratio    = 50;
-static unsigned int full_luma_range;
-static unsigned int coring;
-
-/* API features (turn on/off stuff for testing) */
-static unsigned int v4l2        = 1;
-
-/* insmod args */
-module_param(bttv_verbose,      int, 0644);
-module_param(bttv_gpio,         int, 0644);
-module_param(bttv_debug,        int, 0644);
-module_param(irq_debug,         int, 0644);
-module_param(debug_latency,     int, 0644);
-module_param(disable_ir,        int, 0444);
-
-module_param(fdsr,              int, 0444);
-module_param(gbuffers,          int, 0444);
-module_param(gbufsize,          int, 0444);
-module_param(reset_crop,        int, 0444);
-
-module_param(v4l2,              int, 0644);
-module_param(bigendian,         int, 0644);
-module_param(irq_iswitch,       int, 0644);
-module_param(combfilter,        int, 0444);
-module_param(lumafilter,        int, 0444);
-module_param(automute,          int, 0444);
-module_param(chroma_agc,        int, 0444);
-module_param(adc_crush,         int, 0444);
-module_param(whitecrush_upper,  int, 0444);
-module_param(whitecrush_lower,  int, 0444);
-module_param(vcr_hack,          int, 0444);
-module_param(uv_ratio,          int, 0444);
-module_param(full_luma_range,   int, 0444);
-module_param(coring,            int, 0444);
-
-module_param_array(radio,       int, NULL, 0444);
-module_param_array(video_nr,    int, NULL, 0444);
-module_param_array(radio_nr,    int, NULL, 0444);
-module_param_array(vbi_nr,      int, NULL, 0444);
-
-MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
-MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
-MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
-MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
-MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
-MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
-MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
-MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
-MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
-                "is 1 (yes) for compatibility with older applications");
-MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
-MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
-MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
-MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
-MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
-MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
-MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
-MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
-MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
-MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
-
-MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
-MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(BTTV_VERSION);
-
-/* ----------------------------------------------------------------------- */
-/* sysfs                                                                   */
-
-static ssize_t show_card(struct device *cd,
-                        struct device_attribute *attr, char *buf)
-{
-       struct video_device *vfd = container_of(cd, struct video_device, dev);
-       struct bttv *btv = video_get_drvdata(vfd);
-       return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
-}
-static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
-
-/* ----------------------------------------------------------------------- */
-/* dvb auto-load setup                                                     */
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       request_module("dvb-bt8xx");
-}
-
-static void request_modules(struct bttv *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct bttv *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-
-/* ----------------------------------------------------------------------- */
-/* static data                                                             */
-
-/* special timing tables from conexant... */
-static u8 SRAM_Table[][60] =
-{
-       /* PAL digital input over GPIO[7:0] */
-       {
-               45, // 45 bytes following
-               0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
-               0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
-               0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
-               0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
-               0x37,0x00,0xAF,0x21,0x00
-       },
-       /* NTSC digital input over GPIO[7:0] */
-       {
-               51, // 51 bytes following
-               0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
-               0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
-               0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
-               0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
-               0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
-               0x00,
-       },
-       // TGB_NTSC392 // quartzsight
-       // This table has been modified to be used for Fusion Rev D
-       {
-               0x2A, // size of table = 42
-               0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
-               0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
-               0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
-               0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
-               0x20, 0x00
-       }
-};
-
-/* minhdelayx1 first video pixel we can capture on a line and
-   hdelayx1    start of active video, both relative to rising edge of
-               /HRESET pulse (0H) in 1 / fCLKx1.
-   swidth      width of active video and
-   totalwidth  total line width, both in 1 / fCLKx1.
-   sqwidth     total line width in square pixels.
-   vdelay      start of active video in 2 * field lines relative to
-               trailing edge of /VRESET pulse (VDELAY register).
-   sheight     height of active video in 2 * field lines.
-   videostart0 ITU-R frame line number of the line corresponding
-               to vdelay in the first field. */
-#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,     \
-               vdelay, sheight, videostart0)                            \
-       .cropcap.bounds.left = minhdelayx1,                              \
-       /* * 2 because vertically we count field lines times two, */     \
-       /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */           \
-       .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
-       /* 4 is a safety margin at the end of the line. */               \
-       .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,        \
-       .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,      \
-       .cropcap.defrect.left = hdelayx1,                                \
-       .cropcap.defrect.top = (videostart0) * 2,                        \
-       .cropcap.defrect.width = swidth,                                 \
-       .cropcap.defrect.height = sheight,                               \
-       .cropcap.pixelaspect.numerator = totalwidth,                     \
-       .cropcap.pixelaspect.denominator = sqwidth,
-
-const struct bttv_tvnorm bttv_tvnorms[] = {
-       /* PAL-BDGHI */
-       /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
-       /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
-       {
-               .v4l2_id        = V4L2_STD_PAL,
-               .name           = "PAL",
-               .Fsc            = 35468950,
-               .swidth         = 924,
-               .sheight        = 576,
-               .totalwidth     = 1135,
-               .adelay         = 0x7f,
-               .bdelay         = 0x72,
-               .iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-               .scaledtwidth   = 1135,
-               .hdelayx1       = 186,
-               .hactivex1      = 924,
-               .vdelay         = 0x20,
-               .vbipack        = 255, /* min (2048 / 4, 0x1ff) & 0xff */
-               .sram           = 0,
-               /* ITU-R frame line number of the first VBI line
-                  we can capture, of the first and second field.
-                  The last line is determined by cropcap.bounds. */
-               .vbistart       = { 7, 320 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 186,
-                       /* Should be (768 * 1135 + 944 / 2) / 944.
-                          cropcap.defrect is used for image width
-                          checks, so we keep the old value 924. */
-                       /* swidth */ 924,
-                       /* totalwidth */ 1135,
-                       /* sqwidth */ 944,
-                       /* vdelay */ 0x20,
-                       /* sheight */ 576,
-                       /* videostart0 */ 23)
-               /* bt878 (and bt848?) can capture another
-                  line below active video. */
-               .cropcap.bounds.height = (576 + 2) + 0x20 - 2,
-       },{
-               .v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
-               .name           = "NTSC",
-               .Fsc            = 28636363,
-               .swidth         = 768,
-               .sheight        = 480,
-               .totalwidth     = 910,
-               .adelay         = 0x68,
-               .bdelay         = 0x5d,
-               .iform          = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
-               .scaledtwidth   = 910,
-               .hdelayx1       = 128,
-               .hactivex1      = 910,
-               .vdelay         = 0x1a,
-               .vbipack        = 144, /* min (1600 / 4, 0x1ff) & 0xff */
-               .sram           = 1,
-               .vbistart       = { 10, 273 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 128,
-                       /* Should be (640 * 910 + 780 / 2) / 780? */
-                       /* swidth */ 768,
-                       /* totalwidth */ 910,
-                       /* sqwidth */ 780,
-                       /* vdelay */ 0x1a,
-                       /* sheight */ 480,
-                       /* videostart0 */ 23)
-       },{
-               .v4l2_id        = V4L2_STD_SECAM,
-               .name           = "SECAM",
-               .Fsc            = 35468950,
-               .swidth         = 924,
-               .sheight        = 576,
-               .totalwidth     = 1135,
-               .adelay         = 0x7f,
-               .bdelay         = 0xb0,
-               .iform          = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
-               .scaledtwidth   = 1135,
-               .hdelayx1       = 186,
-               .hactivex1      = 922,
-               .vdelay         = 0x20,
-               .vbipack        = 255,
-               .sram           = 0, /* like PAL, correct? */
-               .vbistart       = { 7, 320 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 186,
-                       /* swidth */ 924,
-                       /* totalwidth */ 1135,
-                       /* sqwidth */ 944,
-                       /* vdelay */ 0x20,
-                       /* sheight */ 576,
-                       /* videostart0 */ 23)
-       },{
-               .v4l2_id        = V4L2_STD_PAL_Nc,
-               .name           = "PAL-Nc",
-               .Fsc            = 28636363,
-               .swidth         = 640,
-               .sheight        = 576,
-               .totalwidth     = 910,
-               .adelay         = 0x68,
-               .bdelay         = 0x5d,
-               .iform          = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
-               .scaledtwidth   = 780,
-               .hdelayx1       = 130,
-               .hactivex1      = 734,
-               .vdelay         = 0x1a,
-               .vbipack        = 144,
-               .sram           = -1,
-               .vbistart       = { 7, 320 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 130,
-                       /* swidth */ (640 * 910 + 780 / 2) / 780,
-                       /* totalwidth */ 910,
-                       /* sqwidth */ 780,
-                       /* vdelay */ 0x1a,
-                       /* sheight */ 576,
-                       /* videostart0 */ 23)
-       },{
-               .v4l2_id        = V4L2_STD_PAL_M,
-               .name           = "PAL-M",
-               .Fsc            = 28636363,
-               .swidth         = 640,
-               .sheight        = 480,
-               .totalwidth     = 910,
-               .adelay         = 0x68,
-               .bdelay         = 0x5d,
-               .iform          = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
-               .scaledtwidth   = 780,
-               .hdelayx1       = 135,
-               .hactivex1      = 754,
-               .vdelay         = 0x1a,
-               .vbipack        = 144,
-               .sram           = -1,
-               .vbistart       = { 10, 273 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 135,
-                       /* swidth */ (640 * 910 + 780 / 2) / 780,
-                       /* totalwidth */ 910,
-                       /* sqwidth */ 780,
-                       /* vdelay */ 0x1a,
-                       /* sheight */ 480,
-                       /* videostart0 */ 23)
-       },{
-               .v4l2_id        = V4L2_STD_PAL_N,
-               .name           = "PAL-N",
-               .Fsc            = 35468950,
-               .swidth         = 768,
-               .sheight        = 576,
-               .totalwidth     = 1135,
-               .adelay         = 0x7f,
-               .bdelay         = 0x72,
-               .iform          = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
-               .scaledtwidth   = 944,
-               .hdelayx1       = 186,
-               .hactivex1      = 922,
-               .vdelay         = 0x20,
-               .vbipack        = 144,
-               .sram           = -1,
-               .vbistart       = { 7, 320 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 186,
-                       /* swidth */ (768 * 1135 + 944 / 2) / 944,
-                       /* totalwidth */ 1135,
-                       /* sqwidth */ 944,
-                       /* vdelay */ 0x20,
-                       /* sheight */ 576,
-                       /* videostart0 */ 23)
-       },{
-               .v4l2_id        = V4L2_STD_NTSC_M_JP,
-               .name           = "NTSC-JP",
-               .Fsc            = 28636363,
-               .swidth         = 640,
-               .sheight        = 480,
-               .totalwidth     = 910,
-               .adelay         = 0x68,
-               .bdelay         = 0x5d,
-               .iform          = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
-               .scaledtwidth   = 780,
-               .hdelayx1       = 135,
-               .hactivex1      = 754,
-               .vdelay         = 0x16,
-               .vbipack        = 144,
-               .sram           = -1,
-               .vbistart       = { 10, 273 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 135,
-                       /* swidth */ (640 * 910 + 780 / 2) / 780,
-                       /* totalwidth */ 910,
-                       /* sqwidth */ 780,
-                       /* vdelay */ 0x16,
-                       /* sheight */ 480,
-                       /* videostart0 */ 23)
-       },{
-               /* that one hopefully works with the strange timing
-                * which video recorders produce when playing a NTSC
-                * tape on a PAL TV ... */
-               .v4l2_id        = V4L2_STD_PAL_60,
-               .name           = "PAL-60",
-               .Fsc            = 35468950,
-               .swidth         = 924,
-               .sheight        = 480,
-               .totalwidth     = 1135,
-               .adelay         = 0x7f,
-               .bdelay         = 0x72,
-               .iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-               .scaledtwidth   = 1135,
-               .hdelayx1       = 186,
-               .hactivex1      = 924,
-               .vdelay         = 0x1a,
-               .vbipack        = 255,
-               .vtotal         = 524,
-               .sram           = -1,
-               .vbistart       = { 10, 273 },
-               CROPCAP(/* minhdelayx1 */ 68,
-                       /* hdelayx1 */ 186,
-                       /* swidth */ 924,
-                       /* totalwidth */ 1135,
-                       /* sqwidth */ 944,
-                       /* vdelay */ 0x1a,
-                       /* sheight */ 480,
-                       /* videostart0 */ 23)
-       }
-};
-static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
-
-/* ----------------------------------------------------------------------- */
-/* bttv format list
-   packed pixel formats must come first */
-static const struct bttv_format formats[] = {
-       {
-               .name     = "8 bpp, gray",
-               .fourcc   = V4L2_PIX_FMT_GREY,
-               .btformat = BT848_COLOR_FMT_Y8,
-               .depth    = 8,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "8 bpp, dithered color",
-               .fourcc   = V4L2_PIX_FMT_HI240,
-               .btformat = BT848_COLOR_FMT_RGB8,
-               .depth    = 8,
-               .flags    = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
-       },{
-               .name     = "15 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB555,
-               .btformat = BT848_COLOR_FMT_RGB15,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "15 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB555X,
-               .btformat = BT848_COLOR_FMT_RGB15,
-               .btswap   = 0x03, /* byteswap */
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "16 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB565,
-               .btformat = BT848_COLOR_FMT_RGB16,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "16 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB565X,
-               .btformat = BT848_COLOR_FMT_RGB16,
-               .btswap   = 0x03, /* byteswap */
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "24 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR24,
-               .btformat = BT848_COLOR_FMT_RGB24,
-               .depth    = 24,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "32 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR32,
-               .btformat = BT848_COLOR_FMT_RGB32,
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "32 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB32,
-               .btformat = BT848_COLOR_FMT_RGB32,
-               .btswap   = 0x0f, /* byte+word swap */
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "4:2:2, packed, YUYV",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .btformat = BT848_COLOR_FMT_YUY2,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .btformat = BT848_COLOR_FMT_YUY2,
-               .btswap   = 0x03, /* byteswap */
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "4:2:2, planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV422P,
-               .btformat = BT848_COLOR_FMT_YCrCb422,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PLANAR,
-               .hshift   = 1,
-               .vshift   = 0,
-       },{
-               .name     = "4:2:0, planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV420,
-               .btformat = BT848_COLOR_FMT_YCrCb422,
-               .depth    = 12,
-               .flags    = FORMAT_FLAGS_PLANAR,
-               .hshift   = 1,
-               .vshift   = 1,
-       },{
-               .name     = "4:2:0, planar, Y-Cr-Cb",
-               .fourcc   = V4L2_PIX_FMT_YVU420,
-               .btformat = BT848_COLOR_FMT_YCrCb422,
-               .depth    = 12,
-               .flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
-               .hshift   = 1,
-               .vshift   = 1,
-       },{
-               .name     = "4:1:1, planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV411P,
-               .btformat = BT848_COLOR_FMT_YCrCb411,
-               .depth    = 12,
-               .flags    = FORMAT_FLAGS_PLANAR,
-               .hshift   = 2,
-               .vshift   = 0,
-       },{
-               .name     = "4:1:0, planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV410,
-               .btformat = BT848_COLOR_FMT_YCrCb411,
-               .depth    = 9,
-               .flags    = FORMAT_FLAGS_PLANAR,
-               .hshift   = 2,
-               .vshift   = 2,
-       },{
-               .name     = "4:1:0, planar, Y-Cr-Cb",
-               .fourcc   = V4L2_PIX_FMT_YVU410,
-               .btformat = BT848_COLOR_FMT_YCrCb411,
-               .depth    = 9,
-               .flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
-               .hshift   = 2,
-               .vshift   = 2,
-       },{
-               .name     = "raw scanlines",
-               .fourcc   = -1,
-               .btformat = BT848_COLOR_FMT_RAW,
-               .depth    = 8,
-               .flags    = FORMAT_FLAGS_RAW,
-       }
-};
-static const unsigned int FORMATS = ARRAY_SIZE(formats);
-
-/* ----------------------------------------------------------------------- */
-
-#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)
-#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
-#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
-#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
-#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
-#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
-
-static const struct v4l2_queryctrl no_ctl = {
-       .name  = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl bttv_ctls[] = {
-       /* --- video --- */
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 256,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_CONTRAST,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 128,
-               .default_value = 27648,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_SATURATION,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 128,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_HUE,
-               .name          = "Hue",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 256,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },
-       /* --- audio --- */
-       {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .name          = "Volume",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 65535,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_BALANCE,
-               .name          = "Balance",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_BASS,
-               .name          = "Bass",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_TREBLE,
-               .name          = "Treble",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },
-       /* --- private --- */
-       {
-               .id            = V4L2_CID_PRIVATE_CHROMA_AGC,
-               .name          = "chroma agc",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_COMBFILTER,
-               .name          = "combfilter",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_AUTOMUTE,
-               .name          = "automute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_LUMAFILTER,
-               .name          = "luma decimation filter",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_AGC_CRUSH,
-               .name          = "agc crush",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_VCR_HACK,
-               .name          = "vcr hack",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
-               .name          = "whitecrush upper",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 0xCF,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
-               .name          = "whitecrush lower",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 0x7F,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_PRIVATE_UV_RATIO,
-               .name          = "uv ratio",
-               .minimum       = 0,
-               .maximum       = 100,
-               .step          = 1,
-               .default_value = 50,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
-               .name          = "full luma range",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_CORING,
-               .name          = "coring",
-               .minimum       = 0,
-               .maximum       = 3,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       }
-
-
-
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(int id)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
-               if (bttv_ctls[i].id == id)
-                       return bttv_ctls+i;
-
-       return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
-/* resource management                                                     */
-
-/*
-   RESOURCE_    allocated by                freed by
-
-   VIDEO_READ   bttv_read 1)                bttv_read 2)
-
-   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF
-                VIDIOC_QBUF 1)              bttv_release
-                VIDIOCMCAPTURE 1)
-
-   OVERLAY      VIDIOCCAPTURE on            VIDIOCCAPTURE off
-                VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
-                3)                          bttv_release
-
-   VBI          VIDIOC_STREAMON             VIDIOC_STREAMOFF
-                VIDIOC_QBUF 1)              bttv_release
-                bttv_read, bttv_poll 1) 4)
-
-   1) The resource must be allocated when we enter buffer prepare functions
-      and remain allocated while buffers are in the DMA queue.
-   2) This is a single frame read.
-   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
-      RESOURCE_OVERLAY is allocated.
-   4) This is a continuous read, implies VIDIOC_STREAMON.
-
-   Note this driver permits video input and standard changes regardless if
-   resources are allocated.
-*/
-
-#define VBI_RESOURCES (RESOURCE_VBI)
-#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
-                        RESOURCE_VIDEO_STREAM | \
-                        RESOURCE_OVERLAY)
-
-static
-int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
-{
-       int xbits; /* mutual exclusive resources */
-
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       xbits = bit;
-       if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
-               xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
-
-       /* is it free? */
-       if (btv->resources & xbits) {
-               /* no, someone else uses it */
-               goto fail;
-       }
-
-       if ((bit & VIDEO_RESOURCES)
-           && 0 == (btv->resources & VIDEO_RESOURCES)) {
-               /* Do crop - use current, don't - use default parameters. */
-               __s32 top = btv->crop[!!fh->do_crop].rect.top;
-
-               if (btv->vbi_end > top)
-                       goto fail;
-
-               /* We cannot capture the same line as video and VBI data.
-                  Claim scan lines crop[].rect.top to bottom. */
-               btv->crop_start = top;
-       } else if (bit & VBI_RESOURCES) {
-               __s32 end = fh->vbi_fmt.end;
-
-               if (end > btv->crop_start)
-                       goto fail;
-
-               /* Claim scan lines above fh->vbi_fmt.end. */
-               btv->vbi_end = end;
-       }
-
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       btv->resources |= bit;
-       return 1;
-
- fail:
-       return 0;
-}
-
-static
-int check_btres(struct bttv_fh *fh, int bit)
-{
-       return (fh->resources & bit);
-}
-
-static
-int locked_btres(struct bttv *btv, int bit)
-{
-       return (btv->resources & bit);
-}
-
-/* Call with btv->lock down. */
-static void
-disclaim_vbi_lines(struct bttv *btv)
-{
-       btv->vbi_end = 0;
-}
-
-/* Call with btv->lock down. */
-static void
-disclaim_video_lines(struct bttv *btv)
-{
-       const struct bttv_tvnorm *tvnorm;
-       u8 crop;
-
-       tvnorm = &bttv_tvnorms[btv->tvnorm];
-       btv->crop_start = tvnorm->cropcap.bounds.top
-               + tvnorm->cropcap.bounds.height;
-
-       /* VBI capturing ends at VDELAY, start of video capturing, no
-          matter how many lines the VBI RISC program expects. When video
-          capturing is off, it shall no longer "preempt" VBI capturing,
-          so we set VDELAY to maximum. */
-       crop = btread(BT848_E_CROP) | 0xc0;
-       btwrite(crop, BT848_E_CROP);
-       btwrite(0xfe, BT848_E_VDELAY_LO);
-       btwrite(crop, BT848_O_CROP);
-       btwrite(0xfe, BT848_O_VDELAY_LO);
-}
-
-static
-void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
-{
-       if ((fh->resources & bits) != bits) {
-               /* trying to free resources not allocated by us ... */
-               pr_err("BUG! (btres)\n");
-       }
-       fh->resources  &= ~bits;
-       btv->resources &= ~bits;
-
-       bits = btv->resources;
-
-       if (0 == (bits & VIDEO_RESOURCES))
-               disclaim_video_lines(btv);
-
-       if (0 == (bits & VBI_RESOURCES))
-               disclaim_vbi_lines(btv);
-}
-
-/* ----------------------------------------------------------------------- */
-/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC          */
-
-/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
-   PLL_X = Reference pre-divider (0=1, 1=2)
-   PLL_C = Post divider (0=6, 1=4)
-   PLL_I = Integer input
-   PLL_F = Fractional input
-
-   F_input = 28.636363 MHz:
-   PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
-*/
-
-static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
-{
-       unsigned char fl, fh, fi;
-
-       /* prevent overflows */
-       fin/=4;
-       fout/=4;
-
-       fout*=12;
-       fi=fout/fin;
-
-       fout=(fout%fin)*256;
-       fh=fout/fin;
-
-       fout=(fout%fin)*256;
-       fl=fout/fin;
-
-       btwrite(fl, BT848_PLL_F_LO);
-       btwrite(fh, BT848_PLL_F_HI);
-       btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
-}
-
-static void set_pll(struct bttv *btv)
-{
-       int i;
-
-       if (!btv->pll.pll_crystal)
-               return;
-
-       if (btv->pll.pll_ofreq == btv->pll.pll_current) {
-               dprintk("%d: PLL: no change required\n", btv->c.nr);
-               return;
-       }
-
-       if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
-               /* no PLL needed */
-               if (btv->pll.pll_current == 0)
-                       return;
-               if (bttv_verbose)
-                       pr_info("%d: PLL can sleep, using XTAL (%d)\n",
-                               btv->c.nr, btv->pll.pll_ifreq);
-               btwrite(0x00,BT848_TGCTRL);
-               btwrite(0x00,BT848_PLL_XCI);
-               btv->pll.pll_current = 0;
-               return;
-       }
-
-       if (bttv_verbose)
-               pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
-                       btv->c.nr,
-                       btv->pll.pll_ifreq, btv->pll.pll_ofreq);
-       set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
-
-       for (i=0; i<10; i++) {
-               /*  Let other people run while the PLL stabilizes */
-               msleep(10);
-
-               if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
-                       btwrite(0,BT848_DSTATUS);
-               } else {
-                       btwrite(0x08,BT848_TGCTRL);
-                       btv->pll.pll_current = btv->pll.pll_ofreq;
-                       if (bttv_verbose)
-                               pr_info("PLL set ok\n");
-                       return;
-               }
-       }
-       btv->pll.pll_current = -1;
-       if (bttv_verbose)
-               pr_info("Setting PLL failed\n");
-       return;
-}
-
-/* used to switch between the bt848's analog/digital video capture modes */
-static void bt848A_set_timing(struct bttv *btv)
-{
-       int i, len;
-       int table_idx = bttv_tvnorms[btv->tvnorm].sram;
-       int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
-
-       if (btv->input == btv->dig) {
-               dprintk("%d: load digital timing table (table_idx=%d)\n",
-                       btv->c.nr,table_idx);
-
-               /* timing change...reset timing generator address */
-               btwrite(0x00, BT848_TGCTRL);
-               btwrite(0x02, BT848_TGCTRL);
-               btwrite(0x00, BT848_TGCTRL);
-
-               len=SRAM_Table[table_idx][0];
-               for(i = 1; i <= len; i++)
-                       btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
-               btv->pll.pll_ofreq = 27000000;
-
-               set_pll(btv);
-               btwrite(0x11, BT848_TGCTRL);
-               btwrite(0x41, BT848_DVSIF);
-       } else {
-               btv->pll.pll_ofreq = fsc;
-               set_pll(btv);
-               btwrite(0x0, BT848_DVSIF);
-       }
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void bt848_bright(struct bttv *btv, int bright)
-{
-       int value;
-
-       // printk("set bright: %d\n", bright); // DEBUG
-       btv->bright = bright;
-
-       /* We want -128 to 127 we get 0-65535 */
-       value = (bright >> 8) - 128;
-       btwrite(value & 0xff, BT848_BRIGHT);
-}
-
-static void bt848_hue(struct bttv *btv, int hue)
-{
-       int value;
-
-       btv->hue = hue;
-
-       /* -128 to 127 */
-       value = (hue >> 8) - 128;
-       btwrite(value & 0xff, BT848_HUE);
-}
-
-static void bt848_contrast(struct bttv *btv, int cont)
-{
-       int value,hibit;
-
-       btv->contrast = cont;
-
-       /* 0-511 */
-       value = (cont  >> 7);
-       hibit = (value >> 6) & 4;
-       btwrite(value & 0xff, BT848_CONTRAST_LO);
-       btaor(hibit, ~4, BT848_E_CONTROL);
-       btaor(hibit, ~4, BT848_O_CONTROL);
-}
-
-static void bt848_sat(struct bttv *btv, int color)
-{
-       int val_u,val_v,hibits;
-
-       btv->saturation = color;
-
-       /* 0-511 for the color */
-       val_u   = ((color * btv->opt_uv_ratio) / 50) >> 7;
-       val_v   = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
-       hibits  = (val_u >> 7) & 2;
-       hibits |= (val_v >> 8) & 1;
-       btwrite(val_u & 0xff, BT848_SAT_U_LO);
-       btwrite(val_v & 0xff, BT848_SAT_V_LO);
-       btaor(hibits, ~3, BT848_E_CONTROL);
-       btaor(hibits, ~3, BT848_O_CONTROL);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int
-video_mux(struct bttv *btv, unsigned int input)
-{
-       int mux,mask2;
-
-       if (input >= bttv_tvcards[btv->c.type].video_inputs)
-               return -EINVAL;
-
-       /* needed by RemoteVideo MX */
-       mask2 = bttv_tvcards[btv->c.type].gpiomask2;
-       if (mask2)
-               gpio_inout(mask2,mask2);
-
-       if (input == btv->svhs)  {
-               btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
-               btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
-       } else {
-               btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
-               btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
-       }
-       mux = bttv_muxsel(btv, input);
-       btaor(mux<<5, ~(3<<5), BT848_IFORM);
-       dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
-
-       /* card specific hook */
-       if(bttv_tvcards[btv->c.type].muxsel_hook)
-               bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
-       return 0;
-}
-
-static char *audio_modes[] = {
-       "audio: tuner", "audio: radio", "audio: extern",
-       "audio: intern", "audio: mute"
-};
-
-static int
-audio_mux(struct bttv *btv, int input, int mute)
-{
-       int gpio_val, signal;
-       struct v4l2_control ctrl;
-
-       gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
-                  bttv_tvcards[btv->c.type].gpiomask);
-       signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
-
-       btv->mute = mute;
-       btv->audio = input;
-
-       /* automute */
-       mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
-
-       if (mute)
-               gpio_val = bttv_tvcards[btv->c.type].gpiomute;
-       else
-               gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
-
-       switch (btv->c.type) {
-       case BTTV_BOARD_VOODOOTV_FM:
-       case BTTV_BOARD_VOODOOTV_200:
-               gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
-               break;
-
-       default:
-               gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
-       }
-
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
-       if (in_interrupt())
-               return 0;
-
-       ctrl.id = V4L2_CID_AUDIO_MUTE;
-       ctrl.value = btv->mute;
-       bttv_call_all(btv, core, s_ctrl, &ctrl);
-       if (btv->sd_msp34xx) {
-               u32 in;
-
-               /* Note: the inputs tuner/radio/extern/intern are translated
-                  to msp routings. This assumes common behavior for all msp3400
-                  based TV cards. When this assumption fails, then the
-                  specific MSP routing must be added to the card table.
-                  For now this is sufficient. */
-               switch (input) {
-               case TVAUDIO_INPUT_RADIO:
-                       /* Some boards need the msp do to the radio demod */
-                       if (btv->radio_uses_msp_demodulator) {
-                               in = MSP_INPUT_DEFAULT;
-                               break;
-                       }
-                       in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
-                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
-                       break;
-               case TVAUDIO_INPUT_EXTERN:
-                       in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
-                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
-                       break;
-               case TVAUDIO_INPUT_INTERN:
-                       /* Yes, this is the same input as for RADIO. I doubt
-                          if this is ever used. The only board with an INTERN
-                          input is the BTTV_BOARD_AVERMEDIA98. I wonder how
-                          that was tested. My guess is that the whole INTERN
-                          input does not work. */
-                       in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
-                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
-                       break;
-               case TVAUDIO_INPUT_TUNER:
-               default:
-                       /* This is the only card that uses TUNER2, and afaik,
-                          is the only difference between the VOODOOTV_FM
-                          and VOODOOTV_200 */
-                       if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
-                               in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
-                                       MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
-                       else
-                               in = MSP_INPUT_DEFAULT;
-                       break;
-               }
-               v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
-                              in, MSP_OUTPUT_DEFAULT, 0);
-       }
-       if (btv->sd_tvaudio) {
-               v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
-                               input, 0, 0);
-       }
-       return 0;
-}
-
-static inline int
-audio_mute(struct bttv *btv, int mute)
-{
-       return audio_mux(btv, btv->audio, mute);
-}
-
-static inline int
-audio_input(struct bttv *btv, int input)
-{
-       return audio_mux(btv, input, btv->mute);
-}
-
-static void
-bttv_crop_calc_limits(struct bttv_crop *c)
-{
-       /* Scale factor min. 1:1, max. 16:1. Min. image size
-          48 x 32. Scaled width must be a multiple of 4. */
-
-       if (1) {
-               /* For bug compatibility with VIDIOCGCAP and image
-                  size checks in earlier driver versions. */
-               c->min_scaled_width = 48;
-               c->min_scaled_height = 32;
-       } else {
-               c->min_scaled_width =
-                       (max(48, c->rect.width >> 4) + 3) & ~3;
-               c->min_scaled_height =
-                       max(32, c->rect.height >> 4);
-       }
-
-       c->max_scaled_width  = c->rect.width & ~3;
-       c->max_scaled_height = c->rect.height;
-}
-
-static void
-bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
-{
-       c->rect = bttv_tvnorms[norm].cropcap.defrect;
-       bttv_crop_calc_limits(c);
-}
-
-/* Call with btv->lock down. */
-static int
-set_tvnorm(struct bttv *btv, unsigned int norm)
-{
-       const struct bttv_tvnorm *tvnorm;
-       v4l2_std_id id;
-
-       BUG_ON(norm >= BTTV_TVNORMS);
-       BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
-
-       tvnorm = &bttv_tvnorms[norm];
-
-       if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
-                   sizeof (tvnorm->cropcap))) {
-               bttv_crop_reset(&btv->crop[0], norm);
-               btv->crop[1] = btv->crop[0]; /* current = default */
-
-               if (0 == (btv->resources & VIDEO_RESOURCES)) {
-                       btv->crop_start = tvnorm->cropcap.bounds.top
-                               + tvnorm->cropcap.bounds.height;
-               }
-       }
-
-       btv->tvnorm = norm;
-
-       btwrite(tvnorm->adelay, BT848_ADELAY);
-       btwrite(tvnorm->bdelay, BT848_BDELAY);
-       btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
-             BT848_IFORM);
-       btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
-       btwrite(1, BT848_VBI_PACK_DEL);
-       bt848A_set_timing(btv);
-
-       switch (btv->c.type) {
-       case BTTV_BOARD_VOODOOTV_FM:
-       case BTTV_BOARD_VOODOOTV_200:
-               bttv_tda9880_setnorm(btv, gpio_read());
-               break;
-       }
-       id = tvnorm->v4l2_id;
-       bttv_call_all(btv, core, s_std, id);
-
-       return 0;
-}
-
-/* Call with btv->lock down. */
-static void
-set_input(struct bttv *btv, unsigned int input, unsigned int norm)
-{
-       unsigned long flags;
-
-       btv->input = input;
-       if (irq_iswitch) {
-               spin_lock_irqsave(&btv->s_lock,flags);
-               if (btv->curr.frame_irq) {
-                       /* active capture -> delayed input switch */
-                       btv->new_input = input;
-               } else {
-                       video_mux(btv,input);
-               }
-               spin_unlock_irqrestore(&btv->s_lock,flags);
-       } else {
-               video_mux(btv,input);
-       }
-       audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
-                        TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
-       set_tvnorm(btv, norm);
-}
-
-static void init_irqreg(struct bttv *btv)
-{
-       /* clear status */
-       btwrite(0xfffffUL, BT848_INT_STAT);
-
-       if (bttv_tvcards[btv->c.type].no_video) {
-               /* i2c only */
-               btwrite(BT848_INT_I2CDONE,
-                       BT848_INT_MASK);
-       } else {
-               /* full video */
-               btwrite((btv->triton1)  |
-                       (btv->gpioirq ? BT848_INT_GPINT : 0) |
-                       BT848_INT_SCERR |
-                       (fdsr ? BT848_INT_FDSR : 0) |
-                       BT848_INT_RISCI | BT848_INT_OCERR |
-                       BT848_INT_FMTCHG|BT848_INT_HLOCK|
-                       BT848_INT_I2CDONE,
-                       BT848_INT_MASK);
-       }
-}
-
-static void init_bt848(struct bttv *btv)
-{
-       int val;
-
-       if (bttv_tvcards[btv->c.type].no_video) {
-               /* very basic init only */
-               init_irqreg(btv);
-               return;
-       }
-
-       btwrite(0x00, BT848_CAP_CTL);
-       btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
-       btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
-
-       /* set planar and packed mode trigger points and         */
-       /* set rising edge of inverted GPINTR pin as irq trigger */
-       btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
-               BT848_GPIO_DMA_CTL_PLTP1_16|
-               BT848_GPIO_DMA_CTL_PLTP23_16|
-               BT848_GPIO_DMA_CTL_GPINTC|
-               BT848_GPIO_DMA_CTL_GPINTI,
-               BT848_GPIO_DMA_CTL);
-
-       val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-       btwrite(val, BT848_E_SCLOOP);
-       btwrite(val, BT848_O_SCLOOP);
-
-       btwrite(0x20, BT848_E_VSCALE_HI);
-       btwrite(0x20, BT848_O_VSCALE_HI);
-       btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
-               BT848_ADC);
-
-       btwrite(whitecrush_upper, BT848_WC_UP);
-       btwrite(whitecrush_lower, BT848_WC_DOWN);
-
-       if (btv->opt_lumafilter) {
-               btwrite(0, BT848_E_CONTROL);
-               btwrite(0, BT848_O_CONTROL);
-       } else {
-               btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
-               btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
-       }
-
-       bt848_bright(btv,   btv->bright);
-       bt848_hue(btv,      btv->hue);
-       bt848_contrast(btv, btv->contrast);
-       bt848_sat(btv,      btv->saturation);
-
-       /* interrupt */
-       init_irqreg(btv);
-}
-
-static void bttv_reinit_bt848(struct bttv *btv)
-{
-       unsigned long flags;
-
-       if (bttv_verbose)
-               pr_info("%d: reset, reinitialize\n", btv->c.nr);
-       spin_lock_irqsave(&btv->s_lock,flags);
-       btv->errors=0;
-       bttv_set_dma(btv,0);
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-
-       init_bt848(btv);
-       btv->pll.pll_current = -1;
-       set_input(btv, btv->input, btv->tvnorm);
-}
-
-static int bttv_g_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *c)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               c->value = btv->bright;
-               break;
-       case V4L2_CID_HUE:
-               c->value = btv->hue;
-               break;
-       case V4L2_CID_CONTRAST:
-               c->value = btv->contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               c->value = btv->saturation;
-               break;
-
-       case V4L2_CID_AUDIO_MUTE:
-       case V4L2_CID_AUDIO_VOLUME:
-       case V4L2_CID_AUDIO_BALANCE:
-       case V4L2_CID_AUDIO_BASS:
-       case V4L2_CID_AUDIO_TREBLE:
-               bttv_call_all(btv, core, g_ctrl, c);
-               break;
-
-       case V4L2_CID_PRIVATE_CHROMA_AGC:
-               c->value = btv->opt_chroma_agc;
-               break;
-       case V4L2_CID_PRIVATE_COMBFILTER:
-               c->value = btv->opt_combfilter;
-               break;
-       case V4L2_CID_PRIVATE_LUMAFILTER:
-               c->value = btv->opt_lumafilter;
-               break;
-       case V4L2_CID_PRIVATE_AUTOMUTE:
-               c->value = btv->opt_automute;
-               break;
-       case V4L2_CID_PRIVATE_AGC_CRUSH:
-               c->value = btv->opt_adc_crush;
-               break;
-       case V4L2_CID_PRIVATE_VCR_HACK:
-               c->value = btv->opt_vcr_hack;
-               break;
-       case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-               c->value = btv->opt_whitecrush_upper;
-               break;
-       case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-               c->value = btv->opt_whitecrush_lower;
-               break;
-       case V4L2_CID_PRIVATE_UV_RATIO:
-               c->value = btv->opt_uv_ratio;
-               break;
-       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-               c->value = btv->opt_full_luma_range;
-               break;
-       case V4L2_CID_PRIVATE_CORING:
-               c->value = btv->opt_coring;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int bttv_s_ctrl(struct file *file, void *f,
-                                       struct v4l2_control *c)
-{
-       int err;
-       int val;
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       err = v4l2_prio_check(&btv->prio, fh->prio);
-       if (0 != err)
-               return err;
-
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               bt848_bright(btv, c->value);
-               break;
-       case V4L2_CID_HUE:
-               bt848_hue(btv, c->value);
-               break;
-       case V4L2_CID_CONTRAST:
-               bt848_contrast(btv, c->value);
-               break;
-       case V4L2_CID_SATURATION:
-               bt848_sat(btv, c->value);
-               break;
-       case V4L2_CID_AUDIO_MUTE:
-               audio_mute(btv, c->value);
-               /* fall through */
-       case V4L2_CID_AUDIO_VOLUME:
-               if (btv->volume_gpio)
-                       btv->volume_gpio(btv, c->value);
-
-               bttv_call_all(btv, core, s_ctrl, c);
-               break;
-       case V4L2_CID_AUDIO_BALANCE:
-       case V4L2_CID_AUDIO_BASS:
-       case V4L2_CID_AUDIO_TREBLE:
-               bttv_call_all(btv, core, s_ctrl, c);
-               break;
-
-       case V4L2_CID_PRIVATE_CHROMA_AGC:
-               btv->opt_chroma_agc = c->value;
-               val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-               btwrite(val, BT848_E_SCLOOP);
-               btwrite(val, BT848_O_SCLOOP);
-               break;
-       case V4L2_CID_PRIVATE_COMBFILTER:
-               btv->opt_combfilter = c->value;
-               break;
-       case V4L2_CID_PRIVATE_LUMAFILTER:
-               btv->opt_lumafilter = c->value;
-               if (btv->opt_lumafilter) {
-                       btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
-                       btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
-               } else {
-                       btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
-                       btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
-               }
-               break;
-       case V4L2_CID_PRIVATE_AUTOMUTE:
-               btv->opt_automute = c->value;
-               break;
-       case V4L2_CID_PRIVATE_AGC_CRUSH:
-               btv->opt_adc_crush = c->value;
-               btwrite(BT848_ADC_RESERVED |
-                               (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
-                               BT848_ADC);
-               break;
-       case V4L2_CID_PRIVATE_VCR_HACK:
-               btv->opt_vcr_hack = c->value;
-               break;
-       case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-               btv->opt_whitecrush_upper = c->value;
-               btwrite(c->value, BT848_WC_UP);
-               break;
-       case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-               btv->opt_whitecrush_lower = c->value;
-               btwrite(c->value, BT848_WC_DOWN);
-               break;
-       case V4L2_CID_PRIVATE_UV_RATIO:
-               btv->opt_uv_ratio = c->value;
-               bt848_sat(btv, btv->saturation);
-               break;
-       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-               btv->opt_full_luma_range = c->value;
-               btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
-               break;
-       case V4L2_CID_PRIVATE_CORING:
-               btv->opt_coring = c->value;
-               btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-void bttv_gpio_tracking(struct bttv *btv, char *comment)
-{
-       unsigned int outbits, data;
-       outbits = btread(BT848_GPIO_OUT_EN);
-       data    = btread(BT848_GPIO_DATA);
-       pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
-                btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
-}
-
-static void bttv_field_count(struct bttv *btv)
-{
-       int need_count = 0;
-
-       if (btv->users)
-               need_count++;
-
-       if (need_count) {
-               /* start field counter */
-               btor(BT848_INT_VSYNC,BT848_INT_MASK);
-       } else {
-               /* stop field counter */
-               btand(~BT848_INT_VSYNC,BT848_INT_MASK);
-               btv->field_count = 0;
-       }
-}
-
-static const struct bttv_format*
-format_by_fourcc(int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < FORMATS; i++) {
-               if (-1 == formats[i].fourcc)
-                       continue;
-               if (formats[i].fourcc == fourcc)
-                       return formats+i;
-       }
-       return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
-/* misc helpers                                                            */
-
-static int
-bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
-                   struct bttv_buffer *new)
-{
-       struct bttv_buffer *old;
-       unsigned long flags;
-       int retval = 0;
-
-       dprintk("switch_overlay: enter [new=%p]\n", new);
-       if (new)
-               new->vb.state = VIDEOBUF_DONE;
-       spin_lock_irqsave(&btv->s_lock,flags);
-       old = btv->screen;
-       btv->screen = new;
-       btv->loop_irq |= 1;
-       bttv_set_dma(btv, 0x03);
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-       if (NULL != old) {
-               dprintk("switch_overlay: old=%p state is %d\n",
-                       old, old->vb.state);
-               bttv_dma_free(&fh->cap,btv, old);
-               kfree(old);
-       }
-       if (NULL == new)
-               free_btres_lock(btv,fh,RESOURCE_OVERLAY);
-       dprintk("switch_overlay: done\n");
-       return retval;
-}
-
-/* ----------------------------------------------------------------------- */
-/* video4linux (1) interface                                               */
-
-static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
-                              struct bttv_buffer *buf,
-                              const struct bttv_format *fmt,
-                              unsigned int width, unsigned int height,
-                              enum v4l2_field field)
-{
-       struct bttv_fh *fh = q->priv_data;
-       int redo_dma_risc = 0;
-       struct bttv_crop c;
-       int norm;
-       int rc;
-
-       /* check settings */
-       if (NULL == fmt)
-               return -EINVAL;
-       if (fmt->btformat == BT848_COLOR_FMT_RAW) {
-               width  = RAW_BPL;
-               height = RAW_LINES*2;
-               if (width*height > buf->vb.bsize)
-                       return -EINVAL;
-               buf->vb.size = buf->vb.bsize;
-
-               /* Make sure tvnorm and vbi_end remain consistent
-                  until we're done. */
-
-               norm = btv->tvnorm;
-
-               /* In this mode capturing always starts at defrect.top
-                  (default VDELAY), ignoring cropping parameters. */
-               if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
-                       return -EINVAL;
-               }
-
-               c.rect = bttv_tvnorms[norm].cropcap.defrect;
-       } else {
-               norm = btv->tvnorm;
-               c = btv->crop[!!fh->do_crop];
-
-               if (width < c.min_scaled_width ||
-                   width > c.max_scaled_width ||
-                   height < c.min_scaled_height)
-                       return -EINVAL;
-
-               switch (field) {
-               case V4L2_FIELD_TOP:
-               case V4L2_FIELD_BOTTOM:
-               case V4L2_FIELD_ALTERNATE:
-                       /* btv->crop counts frame lines. Max. scale
-                          factor is 16:1 for frames, 8:1 for fields. */
-                       if (height * 2 > c.max_scaled_height)
-                               return -EINVAL;
-                       break;
-
-               default:
-                       if (height > c.max_scaled_height)
-                               return -EINVAL;
-                       break;
-               }
-
-               buf->vb.size = (width * height * fmt->depth) >> 3;
-               if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-                       return -EINVAL;
-       }
-
-       /* alloc + fill struct bttv_buffer (if changed) */
-       if (buf->vb.width != width || buf->vb.height != height ||
-           buf->vb.field != field ||
-           buf->tvnorm != norm || buf->fmt != fmt ||
-           buf->crop.top != c.rect.top ||
-           buf->crop.left != c.rect.left ||
-           buf->crop.width != c.rect.width ||
-           buf->crop.height != c.rect.height) {
-               buf->vb.width  = width;
-               buf->vb.height = height;
-               buf->vb.field  = field;
-               buf->tvnorm    = norm;
-               buf->fmt       = fmt;
-               buf->crop      = c.rect;
-               redo_dma_risc = 1;
-       }
-
-       /* alloc risc memory */
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               redo_dma_risc = 1;
-               if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
-                       goto fail;
-       }
-
-       if (redo_dma_risc)
-               if (0 != (rc = bttv_buffer_risc(btv,buf)))
-                       goto fail;
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       bttv_dma_free(q,btv,buf);
-       return rc;
-}
-
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       struct bttv_fh *fh = q->priv_data;
-
-       *size = fh->fmt->depth*fh->width*fh->height >> 3;
-       if (0 == *count)
-               *count = gbuffers;
-       if (*size * *count > gbuffers * gbufsize)
-               *count = (gbuffers * gbufsize) / *size;
-       return 0;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-              enum v4l2_field field)
-{
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-       struct bttv_fh *fh = q->priv_data;
-
-       return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
-                                  fh->width, fh->height, field);
-}
-
-static void
-buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-       struct bttv_fh *fh = q->priv_data;
-       struct bttv    *btv = fh->btv;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue,&btv->capture);
-       if (!btv->curr.frame_irq) {
-               btv->loop_irq |= 1;
-               bttv_set_dma(btv, 0x03);
-       }
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-       struct bttv_fh *fh = q->priv_data;
-
-       bttv_dma_free(q,fh->btv,buf);
-}
-
-static struct videobuf_queue_ops bttv_video_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct bttv_fh *fh  = priv;
-       struct bttv *btv = fh->btv;
-       unsigned int i;
-       int err;
-
-       err = v4l2_prio_check(&btv->prio, fh->prio);
-       if (err)
-               goto err;
-
-       for (i = 0; i < BTTV_TVNORMS; i++)
-               if (*id & bttv_tvnorms[i].v4l2_id)
-                       break;
-       if (i == BTTV_TVNORMS) {
-               err = -EINVAL;
-               goto err;
-       }
-
-       set_tvnorm(btv, i);
-
-err:
-
-       return err;
-}
-
-static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
-               *id = V4L2_STD_625_50;
-       else
-               *id = V4L2_STD_525_60;
-       return 0;
-}
-
-static int bttv_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       int rc = 0;
-
-       if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
-               rc = -EINVAL;
-               goto err;
-       }
-
-       i->type     = V4L2_INPUT_TYPE_CAMERA;
-       i->audioset = 1;
-
-       if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
-               sprintf(i->name, "Television");
-               i->type  = V4L2_INPUT_TYPE_TUNER;
-               i->tuner = 0;
-       } else if (i->index == btv->svhs) {
-               sprintf(i->name, "S-Video");
-       } else {
-               sprintf(i->name, "Composite%d", i->index);
-       }
-
-       if (i->index == btv->input) {
-               __u32 dstatus = btread(BT848_DSTATUS);
-               if (0 == (dstatus & BT848_DSTATUS_PRES))
-                       i->status |= V4L2_IN_ST_NO_SIGNAL;
-               if (0 == (dstatus & BT848_DSTATUS_HLOC))
-                       i->status |= V4L2_IN_ST_NO_H_LOCK;
-       }
-
-       i->std = BTTV_NORMS;
-
-err:
-
-       return rc;
-}
-
-static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       *i = btv->input;
-
-       return 0;
-}
-
-static int bttv_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct bttv_fh *fh  = priv;
-       struct bttv *btv = fh->btv;
-
-       int err;
-
-       err = v4l2_prio_check(&btv->prio, fh->prio);
-       if (unlikely(err))
-               goto err;
-
-       if (i > bttv_tvcards[btv->c.type].video_inputs) {
-               err = -EINVAL;
-               goto err;
-       }
-
-       set_input(btv, i, btv->tvnorm);
-
-err:
-       return 0;
-}
-
-static int bttv_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct bttv_fh *fh  = priv;
-       struct bttv *btv = fh->btv;
-       int err;
-
-       if (unlikely(0 != t->index))
-               return -EINVAL;
-
-       if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
-               err = -EINVAL;
-               goto err;
-       }
-
-       err = v4l2_prio_check(&btv->prio, fh->prio);
-       if (unlikely(err))
-               goto err;
-
-       bttv_call_all(btv, tuner, s_tuner, t);
-
-       if (btv->audio_mode_gpio)
-               btv->audio_mode_gpio(btv, t, 1);
-
-err:
-
-       return 0;
-}
-
-static int bttv_g_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct bttv_fh *fh  = priv;
-       struct bttv *btv = fh->btv;
-
-       f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = btv->freq;
-
-       return 0;
-}
-
-static int bttv_s_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct bttv_fh *fh  = priv;
-       struct bttv *btv = fh->btv;
-       int err;
-
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-
-       err = v4l2_prio_check(&btv->prio, fh->prio);
-       if (unlikely(err))
-               goto err;
-
-       if (unlikely(f->type != (btv->radio_user
-               ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
-               err = -EINVAL;
-               goto err;
-       }
-       btv->freq = f->frequency;
-       bttv_call_all(btv, tuner, s_frequency, f);
-       if (btv->has_matchbox && btv->radio_user)
-               tea5757_set_freq(btv, btv->freq);
-err:
-
-       return 0;
-}
-
-static int bttv_log_status(struct file *file, void *f)
-{
-       struct bttv_fh *fh  = f;
-       struct bttv *btv = fh->btv;
-
-       bttv_call_all(btv, core, log_status);
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int bttv_g_register(struct file *file, void *f,
-                                       struct v4l2_dbg_register *reg)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       /* bt848 has a 12-bit register space */
-       reg->reg &= 0xfff;
-       reg->val = btread(reg->reg);
-       reg->size = 1;
-
-       return 0;
-}
-
-static int bttv_s_register(struct file *file, void *f,
-                                       struct v4l2_dbg_register *reg)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       /* bt848 has a 12-bit register space */
-       reg->reg &= 0xfff;
-       btwrite(reg->val, reg->reg);
-
-       return 0;
-}
-#endif
-
-/* Given cropping boundaries b and the scaled width and height of a
-   single field or frame, which must not exceed hardware limits, this
-   function adjusts the cropping parameters c. */
-static void
-bttv_crop_adjust       (struct bttv_crop *             c,
-                        const struct v4l2_rect *       b,
-                        __s32                          width,
-                        __s32                          height,
-                        enum v4l2_field                field)
-{
-       __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
-       __s32 max_left;
-       __s32 max_top;
-
-       if (width < c->min_scaled_width) {
-               /* Max. hor. scale factor 16:1. */
-               c->rect.width = width * 16;
-       } else if (width > c->max_scaled_width) {
-               /* Min. hor. scale factor 1:1. */
-               c->rect.width = width;
-
-               max_left = b->left + b->width - width;
-               max_left = min(max_left, (__s32) MAX_HDELAY);
-               if (c->rect.left > max_left)
-                       c->rect.left = max_left;
-       }
-
-       if (height < c->min_scaled_height) {
-               /* Max. vert. scale factor 16:1, single fields 8:1. */
-               c->rect.height = height * 16;
-       } else if (frame_height > c->max_scaled_height) {
-               /* Min. vert. scale factor 1:1.
-                  Top and height count field lines times two. */
-               c->rect.height = (frame_height + 1) & ~1;
-
-               max_top = b->top + b->height - c->rect.height;
-               if (c->rect.top > max_top)
-                       c->rect.top = max_top;
-       }
-
-       bttv_crop_calc_limits(c);
-}
-
-/* Returns an error if scaling to a frame or single field with the given
-   width and height is not possible with the current cropping parameters
-   and width aligned according to width_mask. If adjust_size is TRUE the
-   function may adjust the width and/or height instead, rounding width
-   to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
-   also adjust the current cropping parameters to get closer to the
-   desired image size. */
-static int
-limit_scaled_size_lock       (struct bttv_fh *               fh,
-                        __s32 *                        width,
-                        __s32 *                        height,
-                        enum v4l2_field                field,
-                        unsigned int                   width_mask,
-                        unsigned int                   width_bias,
-                        int                            adjust_size,
-                        int                            adjust_crop)
-{
-       struct bttv *btv = fh->btv;
-       const struct v4l2_rect *b;
-       struct bttv_crop *c;
-       __s32 min_width;
-       __s32 min_height;
-       __s32 max_width;
-       __s32 max_height;
-       int rc;
-
-       BUG_ON((int) width_mask >= 0 ||
-              width_bias >= (unsigned int) -width_mask);
-
-       /* Make sure tvnorm, vbi_end and the current cropping parameters
-          remain consistent until we're done. */
-
-       b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
-
-       /* Do crop - use current, don't - use default parameters. */
-       c = &btv->crop[!!fh->do_crop];
-
-       if (fh->do_crop
-           && adjust_size
-           && adjust_crop
-           && !locked_btres(btv, VIDEO_RESOURCES)) {
-               min_width = 48;
-               min_height = 32;
-
-               /* We cannot scale up. When the scaled image is larger
-                  than crop.rect we adjust the crop.rect as required
-                  by the V4L2 spec, hence cropcap.bounds are our limit. */
-               max_width = min(b->width, (__s32) MAX_HACTIVE);
-               max_height = b->height;
-
-               /* We cannot capture the same line as video and VBI data.
-                  Note btv->vbi_end is really a minimum, see
-                  bttv_vbi_try_fmt(). */
-               if (btv->vbi_end > b->top) {
-                       max_height -= btv->vbi_end - b->top;
-                       rc = -EBUSY;
-                       if (min_height > max_height)
-                               goto fail;
-               }
-       } else {
-               rc = -EBUSY;
-               if (btv->vbi_end > c->rect.top)
-                       goto fail;
-
-               min_width  = c->min_scaled_width;
-               min_height = c->min_scaled_height;
-               max_width  = c->max_scaled_width;
-               max_height = c->max_scaled_height;
-
-               adjust_crop = 0;
-       }
-
-       min_width = (min_width - width_mask - 1) & width_mask;
-       max_width = max_width & width_mask;
-
-       /* Max. scale factor is 16:1 for frames, 8:1 for fields. */
-       min_height = min_height;
-       /* Min. scale factor is 1:1. */
-       max_height >>= !V4L2_FIELD_HAS_BOTH(field);
-
-       if (adjust_size) {
-               *width = clamp(*width, min_width, max_width);
-               *height = clamp(*height, min_height, max_height);
-
-               /* Round after clamping to avoid overflow. */
-               *width = (*width + width_bias) & width_mask;
-
-               if (adjust_crop) {
-                       bttv_crop_adjust(c, b, *width, *height, field);
-
-                       if (btv->vbi_end > c->rect.top) {
-                               /* Move the crop window out of the way. */
-                               c->rect.top = btv->vbi_end;
-                       }
-               }
-       } else {
-               rc = -EINVAL;
-               if (*width  < min_width ||
-                   *height < min_height ||
-                   *width  > max_width ||
-                   *height > max_height ||
-                   0 != (*width & ~width_mask))
-                       goto fail;
-       }
-
-       rc = 0; /* success */
-
- fail:
-
-       return rc;
-}
-
-/* Returns an error if the given overlay window dimensions are not
-   possible with the current cropping parameters. If adjust_size is
-   TRUE the function may adjust the window width and/or height
-   instead, however it always rounds the horizontal position and
-   width as btcx_align() does. If adjust_crop is TRUE the function
-   may also adjust the current cropping parameters to get closer
-   to the desired window size. */
-static int
-verify_window_lock             (struct bttv_fh *               fh,
-                        struct v4l2_window *           win,
-                        int                            adjust_size,
-                        int                            adjust_crop)
-{
-       enum v4l2_field field;
-       unsigned int width_mask;
-       int rc;
-
-       if (win->w.width  < 48 || win->w.height < 32)
-               return -EINVAL;
-       if (win->clipcount > 2048)
-               return -EINVAL;
-
-       field = win->field;
-
-       if (V4L2_FIELD_ANY == field) {
-               __s32 height2;
-
-               height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-               field = (win->w.height > height2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-       }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* 4-byte alignment. */
-       if (NULL == fh->ovfmt)
-               return -EINVAL;
-       width_mask = ~0;
-       switch (fh->ovfmt->depth) {
-       case 8:
-       case 24:
-               width_mask = ~3;
-               break;
-       case 16:
-               width_mask = ~1;
-               break;
-       case 32:
-               break;
-       default:
-               BUG();
-       }
-
-       win->w.width -= win->w.left & ~width_mask;
-       win->w.left = (win->w.left - width_mask - 1) & width_mask;
-
-       rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
-                              field, width_mask,
-                              /* width_bias: round down */ 0,
-                              adjust_size, adjust_crop);
-       if (0 != rc)
-               return rc;
-
-       win->field = field;
-       return 0;
-}
-
-static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
-                       struct v4l2_window *win, int fixup)
-{
-       struct v4l2_clip *clips = NULL;
-       int n,size,retval = 0;
-
-       if (NULL == fh->ovfmt)
-               return -EINVAL;
-       if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-       retval = verify_window_lock(fh, win,
-                              /* adjust_size */ fixup,
-                              /* adjust_crop */ fixup);
-       if (0 != retval)
-               return retval;
-
-       /* copy clips  --  luckily v4l1 + v4l2 are binary
-          compatible here ...*/
-       n = win->clipcount;
-       size = sizeof(*clips)*(n+4);
-       clips = kmalloc(size,GFP_KERNEL);
-       if (NULL == clips)
-               return -ENOMEM;
-       if (n > 0) {
-               if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
-                       kfree(clips);
-                       return -EFAULT;
-               }
-       }
-
-       /* clip against screen */
-       if (NULL != btv->fbuf.base)
-               n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
-                                     &win->w, clips, n);
-       btcx_sort_clips(clips,n);
-
-       /* 4-byte alignments */
-       switch (fh->ovfmt->depth) {
-       case 8:
-       case 24:
-               btcx_align(&win->w, clips, n, 3);
-               break;
-       case 16:
-               btcx_align(&win->w, clips, n, 1);
-               break;
-       case 32:
-               /* no alignment fixups needed */
-               break;
-       default:
-               BUG();
-       }
-
-       kfree(fh->ov.clips);
-       fh->ov.clips    = clips;
-       fh->ov.nclips   = n;
-
-       fh->ov.w        = win->w;
-       fh->ov.field    = win->field;
-       fh->ov.setup_ok = 1;
-
-       btv->init.ov.w.width   = win->w.width;
-       btv->init.ov.w.height  = win->w.height;
-       btv->init.ov.field     = win->field;
-
-       /* update overlay if needed */
-       retval = 0;
-       if (check_btres(fh, RESOURCE_OVERLAY)) {
-               struct bttv_buffer *new;
-
-               new = videobuf_sg_alloc(sizeof(*new));
-               new->crop = btv->crop[!!fh->do_crop].rect;
-               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-               retval = bttv_switch_overlay(btv,fh,new);
-       }
-       return retval;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
-{
-       struct videobuf_queue* q = NULL;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               q = &fh->cap;
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               q = &fh->vbi;
-               break;
-       default:
-               BUG();
-       }
-       return q;
-}
-
-static int bttv_resource(struct bttv_fh *fh)
-{
-       int res = 0;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               res = RESOURCE_VIDEO_STREAM;
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               res = RESOURCE_VBI;
-               break;
-       default:
-               BUG();
-       }
-       return res;
-}
-
-static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
-{
-       struct videobuf_queue *q = bttv_queue(fh);
-       int res = bttv_resource(fh);
-
-       if (check_btres(fh,res))
-               return -EBUSY;
-       if (videobuf_queue_is_busy(q))
-               return -EBUSY;
-       fh->type = type;
-       return 0;
-}
-
-static void
-pix_format_set_size     (struct v4l2_pix_format *       f,
-                        const struct bttv_format *     fmt,
-                        unsigned int                   width,
-                        unsigned int                   height)
-{
-       f->width = width;
-       f->height = height;
-
-       if (fmt->flags & FORMAT_FLAGS_PLANAR) {
-               f->bytesperline = width; /* Y plane */
-               f->sizeimage = (width * height * fmt->depth) >> 3;
-       } else {
-               f->bytesperline = (width * fmt->depth) >> 3;
-               f->sizeimage = height * f->bytesperline;
-       }
-}
-
-static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct bttv_fh *fh  = priv;
-
-       pix_format_set_size(&f->fmt.pix, fh->fmt,
-                               fh->width, fh->height);
-       f->fmt.pix.field        = fh->cap.field;
-       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-
-       return 0;
-}
-
-static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct bttv_fh *fh  = priv;
-
-       f->fmt.win.w     = fh->ov.w;
-       f->fmt.win.field = fh->ov.field;
-
-       return 0;
-}
-
-static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       const struct bttv_format *fmt;
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       enum v4l2_field field;
-       __s32 width, height;
-       int rc;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-
-       if (V4L2_FIELD_ANY == field) {
-               __s32 height2;
-
-               height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-               field = (f->fmt.pix.height > height2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_BOTTOM;
-       }
-
-       if (V4L2_FIELD_SEQ_BT == field)
-               field = V4L2_FIELD_SEQ_TB;
-
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-       case V4L2_FIELD_ALTERNATE:
-       case V4L2_FIELD_INTERLACED:
-               break;
-       case V4L2_FIELD_SEQ_TB:
-               if (fmt->flags & FORMAT_FLAGS_PLANAR)
-                       return -EINVAL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       width = f->fmt.pix.width;
-       height = f->fmt.pix.height;
-
-       rc = limit_scaled_size_lock(fh, &width, &height, field,
-                              /* width_mask: 4 pixels */ ~3,
-                              /* width_bias: nearest */ 2,
-                              /* adjust_size */ 1,
-                              /* adjust_crop */ 0);
-       if (0 != rc)
-               return rc;
-
-       /* update data for the application */
-       f->fmt.pix.field = field;
-       pix_format_set_size(&f->fmt.pix, fmt, width, height);
-
-       return 0;
-}
-
-static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct bttv_fh *fh = priv;
-
-       return verify_window_lock(fh, &f->fmt.win,
-                       /* adjust_size */ 1,
-                       /* adjust_crop */ 0);
-}
-
-static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       int retval;
-       const struct bttv_format *fmt;
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       __s32 width, height;
-       enum v4l2_field field;
-
-       retval = bttv_switch_type(fh, f->type);
-       if (0 != retval)
-               return retval;
-
-       retval = bttv_try_fmt_vid_cap(file, priv, f);
-       if (0 != retval)
-               return retval;
-
-       width = f->fmt.pix.width;
-       height = f->fmt.pix.height;
-       field = f->fmt.pix.field;
-
-       retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
-                              /* width_mask: 4 pixels */ ~3,
-                              /* width_bias: nearest */ 2,
-                              /* adjust_size */ 1,
-                              /* adjust_crop */ 1);
-       if (0 != retval)
-               return retval;
-
-       f->fmt.pix.field = field;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-
-       /* update our state informations */
-       fh->fmt              = fmt;
-       fh->cap.field        = f->fmt.pix.field;
-       fh->cap.last         = V4L2_FIELD_NONE;
-       fh->width            = f->fmt.pix.width;
-       fh->height           = f->fmt.pix.height;
-       btv->init.fmt        = fmt;
-       btv->init.width      = f->fmt.pix.width;
-       btv->init.height     = f->fmt.pix.height;
-
-       return 0;
-}
-
-static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       return setup_window_lock(fh, btv, &f->fmt.win, 1);
-}
-
-static int bttv_querycap(struct file *file, void  *priv,
-                               struct v4l2_capability *cap)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (0 == v4l2)
-               return -EINVAL;
-
-       strlcpy(cap->driver, "bttv", sizeof(cap->driver));
-       strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info),
-                "PCI:%s", pci_name(btv->c.pci));
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_VBI_CAPTURE |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING;
-       if (no_overlay <= 0)
-               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
-
-       /*
-        * No need to lock here: those vars are initialized during board
-        * probe and remains untouched during the rest of the driver lifecycle
-        */
-       if (btv->has_saa6588)
-               cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
-       if (btv->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
-{
-       int index = -1, i;
-
-       for (i = 0; i < FORMATS; i++) {
-               if (formats[i].fourcc != -1)
-                       index++;
-               if ((unsigned int)index == f->index)
-                       break;
-       }
-       if (FORMATS == i)
-               return -EINVAL;
-
-       f->pixelformat = formats[i].fourcc;
-       strlcpy(f->description, formats[i].name, sizeof(f->description));
-
-       return i;
-}
-
-static int bttv_enum_fmt_vid_cap(struct file *file, void  *priv,
-                               struct v4l2_fmtdesc *f)
-{
-       int rc = bttv_enum_fmt_cap_ovr(f);
-
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-static int bttv_enum_fmt_vid_overlay(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       int rc;
-
-       if (no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       rc = bttv_enum_fmt_cap_ovr(f);
-
-       if (rc < 0)
-               return rc;
-
-       if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-
-       return 0;
-}
-
-static int bttv_g_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       *fb = btv->fbuf;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-       if (fh->ovfmt)
-               fb->fmt.pixelformat  = fh->ovfmt->fourcc;
-       return 0;
-}
-
-static int bttv_overlay(struct file *file, void *f, unsigned int on)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       struct bttv_buffer *new;
-       int retval = 0;
-
-       if (on) {
-               /* verify args */
-               if (unlikely(!btv->fbuf.base)) {
-                       return -EINVAL;
-               }
-               if (unlikely(!fh->ov.setup_ok)) {
-                       dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
-                       retval = -EINVAL;
-               }
-               if (retval)
-                       return retval;
-       }
-
-       if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
-               return -EBUSY;
-
-       if (on) {
-               fh->ov.tvnorm = btv->tvnorm;
-               new = videobuf_sg_alloc(sizeof(*new));
-               new->crop = btv->crop[!!fh->do_crop].rect;
-               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-       } else {
-               new = NULL;
-       }
-
-       /* switch over */
-       retval = bttv_switch_overlay(btv, fh, new);
-       return retval;
-}
-
-static int bttv_s_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       const struct bttv_format *fmt;
-       int retval;
-
-       if (!capable(CAP_SYS_ADMIN) &&
-               !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = format_by_fourcc(fb->fmt.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-       if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-
-       retval = -EINVAL;
-       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-               __s32 width = fb->fmt.width;
-               __s32 height = fb->fmt.height;
-
-               retval = limit_scaled_size_lock(fh, &width, &height,
-                                          V4L2_FIELD_INTERLACED,
-                                          /* width_mask */ ~3,
-                                          /* width_bias */ 2,
-                                          /* adjust_size */ 0,
-                                          /* adjust_crop */ 0);
-               if (0 != retval)
-                       return retval;
-       }
-
-       /* ok, accept it */
-       btv->fbuf.base       = fb->base;
-       btv->fbuf.fmt.width  = fb->fmt.width;
-       btv->fbuf.fmt.height = fb->fmt.height;
-       if (0 != fb->fmt.bytesperline)
-               btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
-       else
-               btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-
-       retval = 0;
-       fh->ovfmt = fmt;
-       btv->init.ovfmt = fmt;
-       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-               fh->ov.w.left   = 0;
-               fh->ov.w.top    = 0;
-               fh->ov.w.width  = fb->fmt.width;
-               fh->ov.w.height = fb->fmt.height;
-               btv->init.ov.w.width  = fb->fmt.width;
-               btv->init.ov.w.height = fb->fmt.height;
-                       kfree(fh->ov.clips);
-               fh->ov.clips = NULL;
-               fh->ov.nclips = 0;
-
-               if (check_btres(fh, RESOURCE_OVERLAY)) {
-                       struct bttv_buffer *new;
-
-                       new = videobuf_sg_alloc(sizeof(*new));
-                       new->crop = btv->crop[!!fh->do_crop].rect;
-                       bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-                       retval = bttv_switch_overlay(btv, fh, new);
-               }
-       }
-       return retval;
-}
-
-static int bttv_reqbufs(struct file *file, void *priv,
-                               struct v4l2_requestbuffers *p)
-{
-       struct bttv_fh *fh = priv;
-       return videobuf_reqbufs(bttv_queue(fh), p);
-}
-
-static int bttv_querybuf(struct file *file, void *priv,
-                               struct v4l2_buffer *b)
-{
-       struct bttv_fh *fh = priv;
-       return videobuf_querybuf(bttv_queue(fh), b);
-}
-
-static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       int res = bttv_resource(fh);
-
-       if (!check_alloc_btres_lock(btv, fh, res))
-               return -EBUSY;
-
-       return videobuf_qbuf(bttv_queue(fh), b);
-}
-
-static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct bttv_fh *fh = priv;
-       return videobuf_dqbuf(bttv_queue(fh), b,
-                       file->f_flags & O_NONBLOCK);
-}
-
-static int bttv_streamon(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       int res = bttv_resource(fh);
-
-       if (!check_alloc_btres_lock(btv, fh, res))
-               return -EBUSY;
-       return videobuf_streamon(bttv_queue(fh));
-}
-
-
-static int bttv_streamoff(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       int retval;
-       int res = bttv_resource(fh);
-
-
-       retval = videobuf_streamoff(bttv_queue(fh));
-       if (retval < 0)
-               return retval;
-       free_btres_lock(btv, fh, res);
-       return 0;
-}
-
-static int bttv_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-       const struct v4l2_queryctrl *ctrl;
-
-       if ((c->id <  V4L2_CID_BASE ||
-            c->id >= V4L2_CID_LASTP1) &&
-           (c->id <  V4L2_CID_PRIVATE_BASE ||
-            c->id >= V4L2_CID_PRIVATE_LASTP1))
-               return -EINVAL;
-
-       if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
-               *c = no_ctl;
-       else {
-               ctrl = ctrl_by_id(c->id);
-
-               *c = (NULL != ctrl) ? *ctrl : no_ctl;
-       }
-
-       return 0;
-}
-
-static int bttv_g_parm(struct file *file, void *f,
-                               struct v4l2_streamparm *parm)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
-                                   &parm->parm.capture.timeperframe);
-
-       return 0;
-}
-
-static int bttv_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (btv->tuner_type == TUNER_ABSENT)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       t->rxsubchans = V4L2_TUNER_SUB_MONO;
-       bttv_call_all(btv, tuner, g_tuner, t);
-       strcpy(t->name, "Television");
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->type       = V4L2_TUNER_ANALOG_TV;
-       if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
-               t->signal = 0xffff;
-
-       if (btv->audio_mode_gpio)
-               btv->audio_mode_gpio(btv, t, 0);
-
-       return 0;
-}
-
-static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       *p = v4l2_prio_max(&btv->prio);
-
-       return 0;
-}
-
-static int bttv_s_priority(struct file *file, void *f,
-                                       enum v4l2_priority prio)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       int     rc;
-
-       rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-
-       return rc;
-}
-
-static int bttv_cropcap(struct file *file, void *priv,
-                               struct v4l2_cropcap *cap)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-
-       *cap = bttv_tvnorms[btv->tvnorm].cropcap;
-
-       return 0;
-}
-
-static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-
-       /* No fh->do_crop = 1; because btv->crop[1] may be
-          inconsistent with fh->width or fh->height and apps
-          do not expect a change here. */
-
-       crop->c = btv->crop[!!fh->do_crop].rect;
-
-       return 0;
-}
-
-static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       const struct v4l2_rect *b;
-       int retval;
-       struct bttv_crop c;
-       __s32 b_left;
-       __s32 b_top;
-       __s32 b_right;
-       __s32 b_bottom;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-
-       /* Make sure tvnorm, vbi_end and the current cropping
-          parameters remain consistent until we're done. Note
-          read() may change vbi_end in check_alloc_btres_lock(). */
-       retval = v4l2_prio_check(&btv->prio, fh->prio);
-       if (0 != retval) {
-               return retval;
-       }
-
-       retval = -EBUSY;
-
-       if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
-               return retval;
-       }
-
-       b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
-
-       b_left = b->left;
-       b_right = b_left + b->width;
-       b_bottom = b->top + b->height;
-
-       b_top = max(b->top, btv->vbi_end);
-       if (b_top + 32 >= b_bottom) {
-               return retval;
-       }
-
-       /* Min. scaled size 48 x 32. */
-       c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
-       c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
-
-       c.rect.width = clamp(crop->c.width,
-                            48, b_right - c.rect.left);
-
-       c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
-       /* Top and height must be a multiple of two. */
-       c.rect.top = (c.rect.top + 1) & ~1;
-
-       c.rect.height = clamp(crop->c.height,
-                             32, b_bottom - c.rect.top);
-       c.rect.height = (c.rect.height + 1) & ~1;
-
-       bttv_crop_calc_limits(&c);
-
-       btv->crop[1] = c;
-
-       fh->do_crop = 1;
-
-       if (fh->width < c.min_scaled_width) {
-               fh->width = c.min_scaled_width;
-               btv->init.width = c.min_scaled_width;
-       } else if (fh->width > c.max_scaled_width) {
-               fh->width = c.max_scaled_width;
-               btv->init.width = c.max_scaled_width;
-       }
-
-       if (fh->height < c.min_scaled_height) {
-               fh->height = c.min_scaled_height;
-               btv->init.height = c.min_scaled_height;
-       } else if (fh->height > c.max_scaled_height) {
-               fh->height = c.max_scaled_height;
-               btv->init.height = c.max_scaled_height;
-       }
-
-       return 0;
-}
-
-static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       strcpy(a->name, "audio");
-       return 0;
-}
-
-static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       return 0;
-}
-
-static ssize_t bttv_read(struct file *file, char __user *data,
-                        size_t count, loff_t *ppos)
-{
-       struct bttv_fh *fh = file->private_data;
-       int retval = 0;
-
-       if (fh->btv->errors)
-               bttv_reinit_bt848(fh->btv);
-       dprintk("%d: read count=%d type=%s\n",
-               fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
-                       /* VIDEO_READ in use by another fh,
-                          or VIDEO_STREAM by any fh. */
-                       return -EBUSY;
-               }
-               retval = videobuf_read_one(&fh->cap, data, count, ppos,
-                                          file->f_flags & O_NONBLOCK);
-               free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
-                       return -EBUSY;
-               retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
-                                             file->f_flags & O_NONBLOCK);
-               break;
-       default:
-               BUG();
-       }
-       return retval;
-}
-
-static unsigned int bttv_poll(struct file *file, poll_table *wait)
-{
-       struct bttv_fh *fh = file->private_data;
-       struct bttv_buffer *buf;
-       enum v4l2_field field;
-       unsigned int rc = POLLERR;
-
-       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
-               if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
-                       return POLLERR;
-               return videobuf_poll_stream(file, &fh->vbi, wait);
-       }
-
-       if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
-               /* streaming capture */
-               if (list_empty(&fh->cap.stream))
-                       goto err;
-               buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
-       } else {
-               /* read() capture */
-               if (NULL == fh->cap.read_buf) {
-                       /* need to capture a new frame */
-                       if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
-                               goto err;
-                       fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
-                       if (NULL == fh->cap.read_buf)
-                               goto err;
-                       fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
-                       field = videobuf_next_field(&fh->cap);
-                       if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
-                               kfree (fh->cap.read_buf);
-                               fh->cap.read_buf = NULL;
-                               goto err;
-                       }
-                       fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
-                       fh->cap.read_off = 0;
-               }
-               buf = (struct bttv_buffer*)fh->cap.read_buf;
-       }
-
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE ||
-           buf->vb.state == VIDEOBUF_ERROR)
-               rc =  POLLIN|POLLRDNORM;
-       else
-               rc = 0;
-err:
-       return rc;
-}
-
-static int bttv_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct bttv *btv = video_drvdata(file);
-       struct bttv_fh *fh;
-       enum v4l2_buf_type type = 0;
-
-       dprintk("open dev=%s\n", video_device_node_name(vdev));
-
-       if (vdev->vfl_type == VFL_TYPE_GRABBER) {
-               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       } else if (vdev->vfl_type == VFL_TYPE_VBI) {
-               type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       } else {
-               WARN_ON(1);
-               return -ENODEV;
-       }
-
-       dprintk("%d: open called (type=%s)\n",
-               btv->c.nr, v4l2_type_names[type]);
-
-       /* allocate per filehandle data */
-       fh = kmalloc(sizeof(*fh), GFP_KERNEL);
-       if (unlikely(!fh))
-               return -ENOMEM;
-       file->private_data = fh;
-
-       *fh = btv->init;
-
-       fh->type = type;
-       fh->ov.setup_ok = 0;
-
-       v4l2_prio_open(&btv->prio, &fh->prio);
-
-       videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
-                           &btv->c.pci->dev, &btv->s_lock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                           V4L2_FIELD_INTERLACED,
-                           sizeof(struct bttv_buffer),
-                           fh, &btv->lock);
-       videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
-                           &btv->c.pci->dev, &btv->s_lock,
-                           V4L2_BUF_TYPE_VBI_CAPTURE,
-                           V4L2_FIELD_SEQ_TB,
-                           sizeof(struct bttv_buffer),
-                           fh, &btv->lock);
-       set_tvnorm(btv,btv->tvnorm);
-       set_input(btv, btv->input, btv->tvnorm);
-
-       btv->users++;
-
-       /* The V4L2 spec requires one global set of cropping parameters
-          which only change on request. These are stored in btv->crop[1].
-          However for compatibility with V4L apps and cropping unaware
-          V4L2 apps we now reset the cropping parameters as seen through
-          this fh, which is to say VIDIOC_G_CROP and scaling limit checks
-          will use btv->crop[0], the default cropping parameters for the
-          current video standard, and VIDIOC_S_FMT will not implicitely
-          change the cropping parameters until VIDIOC_S_CROP has been
-          called. */
-       fh->do_crop = !reset_crop; /* module parameter */
-
-       /* Likewise there should be one global set of VBI capture
-          parameters, but for compatibility with V4L apps and earlier
-          driver versions each fh has its own parameters. */
-       bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
-
-       bttv_field_count(btv);
-       return 0;
-}
-
-static int bttv_release(struct file *file)
-{
-       struct bttv_fh *fh = file->private_data;
-       struct bttv *btv = fh->btv;
-
-       /* turn off overlay */
-       if (check_btres(fh, RESOURCE_OVERLAY))
-               bttv_switch_overlay(btv,fh,NULL);
-
-       /* stop video capture */
-       if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
-               videobuf_streamoff(&fh->cap);
-               free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
-       }
-       if (fh->cap.read_buf) {
-               buffer_release(&fh->cap,fh->cap.read_buf);
-               kfree(fh->cap.read_buf);
-       }
-       if (check_btres(fh, RESOURCE_VIDEO_READ)) {
-               free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
-       }
-
-       /* stop vbi capture */
-       if (check_btres(fh, RESOURCE_VBI)) {
-               videobuf_stop(&fh->vbi);
-               free_btres_lock(btv,fh,RESOURCE_VBI);
-       }
-
-       /* free stuff */
-
-       videobuf_mmap_free(&fh->cap);
-       videobuf_mmap_free(&fh->vbi);
-       v4l2_prio_close(&btv->prio, fh->prio);
-       file->private_data = NULL;
-       kfree(fh);
-
-       btv->users--;
-       bttv_field_count(btv);
-
-       if (!btv->users)
-               audio_mute(btv, 1);
-
-       return 0;
-}
-
-static int
-bttv_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct bttv_fh *fh = file->private_data;
-
-       dprintk("%d: mmap type=%s 0x%lx+%ld\n",
-               fh->btv->c.nr, v4l2_type_names[fh->type],
-               vma->vm_start, vma->vm_end - vma->vm_start);
-       return videobuf_mmap_mapper(bttv_queue(fh),vma);
-}
-
-static const struct v4l2_file_operations bttv_fops =
-{
-       .owner            = THIS_MODULE,
-       .open             = bttv_open,
-       .release          = bttv_release,
-       .unlocked_ioctl   = video_ioctl2,
-       .read             = bttv_read,
-       .mmap             = bttv_mmap,
-       .poll             = bttv_poll,
-};
-
-static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
-       .vidioc_querycap                = bttv_querycap,
-       .vidioc_enum_fmt_vid_cap        = bttv_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap         = bttv_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap           = bttv_s_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_overlay    = bttv_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay       = bttv_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay     = bttv_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay       = bttv_s_fmt_vid_overlay,
-       .vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
-       .vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
-       .vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
-       .vidioc_g_audio                 = bttv_g_audio,
-       .vidioc_s_audio                 = bttv_s_audio,
-       .vidioc_cropcap                 = bttv_cropcap,
-       .vidioc_reqbufs                 = bttv_reqbufs,
-       .vidioc_querybuf                = bttv_querybuf,
-       .vidioc_qbuf                    = bttv_qbuf,
-       .vidioc_dqbuf                   = bttv_dqbuf,
-       .vidioc_s_std                   = bttv_s_std,
-       .vidioc_enum_input              = bttv_enum_input,
-       .vidioc_g_input                 = bttv_g_input,
-       .vidioc_s_input                 = bttv_s_input,
-       .vidioc_queryctrl               = bttv_queryctrl,
-       .vidioc_g_ctrl                  = bttv_g_ctrl,
-       .vidioc_s_ctrl                  = bttv_s_ctrl,
-       .vidioc_streamon                = bttv_streamon,
-       .vidioc_streamoff               = bttv_streamoff,
-       .vidioc_g_tuner                 = bttv_g_tuner,
-       .vidioc_s_tuner                 = bttv_s_tuner,
-       .vidioc_g_crop                  = bttv_g_crop,
-       .vidioc_s_crop                  = bttv_s_crop,
-       .vidioc_g_fbuf                  = bttv_g_fbuf,
-       .vidioc_s_fbuf                  = bttv_s_fbuf,
-       .vidioc_overlay                 = bttv_overlay,
-       .vidioc_g_priority              = bttv_g_priority,
-       .vidioc_s_priority              = bttv_s_priority,
-       .vidioc_g_parm                  = bttv_g_parm,
-       .vidioc_g_frequency             = bttv_g_frequency,
-       .vidioc_s_frequency             = bttv_s_frequency,
-       .vidioc_log_status              = bttv_log_status,
-       .vidioc_querystd                = bttv_querystd,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register              = bttv_g_register,
-       .vidioc_s_register              = bttv_s_register,
-#endif
-};
-
-static struct video_device bttv_video_template = {
-       .fops         = &bttv_fops,
-       .ioctl_ops    = &bttv_ioctl_ops,
-       .tvnorms      = BTTV_NORMS,
-       .current_norm = V4L2_STD_PAL,
-};
-
-/* ----------------------------------------------------------------------- */
-/* radio interface                                                         */
-
-static int radio_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct bttv *btv = video_drvdata(file);
-       struct bttv_fh *fh;
-
-       dprintk("open dev=%s\n", video_device_node_name(vdev));
-
-       dprintk("%d: open called (radio)\n", btv->c.nr);
-
-       /* allocate per filehandle data */
-       fh = kmalloc(sizeof(*fh), GFP_KERNEL);
-       if (unlikely(!fh))
-               return -ENOMEM;
-       file->private_data = fh;
-       *fh = btv->init;
-
-       v4l2_prio_open(&btv->prio, &fh->prio);
-
-       btv->radio_user++;
-
-       bttv_call_all(btv, tuner, s_radio);
-       audio_input(btv,TVAUDIO_INPUT_RADIO);
-
-       return 0;
-}
-
-static int radio_release(struct file *file)
-{
-       struct bttv_fh *fh = file->private_data;
-       struct bttv *btv = fh->btv;
-       struct saa6588_command cmd;
-
-       v4l2_prio_close(&btv->prio, fh->prio);
-       file->private_data = NULL;
-       kfree(fh);
-
-       btv->radio_user--;
-
-       bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
-
-       return 0;
-}
-
-static int radio_querycap(struct file *file, void *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       strcpy(cap->driver, "bttv");
-       strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
-       cap->capabilities = V4L2_CAP_TUNER;
-
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (btv->tuner_type == TUNER_ABSENT)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-
-       bttv_call_all(btv, tuner, g_tuner, t);
-
-       if (btv->audio_mode_gpio)
-               btv->audio_mode_gpio(btv, t, 0);
-
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       strcpy(a->name, "Radio");
-
-       return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       bttv_call_all(btv, tuner, s_tuner, t);
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       if (unlikely(i))
-               return -EINVAL;
-
-       return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       const struct v4l2_queryctrl *ctrl;
-
-       if (c->id <  V4L2_CID_BASE ||
-                       c->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
-               ctrl = ctrl_by_id(c->id);
-               *c = *ctrl;
-       } else
-               *c = no_ctl;
-
-       return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static ssize_t radio_read(struct file *file, char __user *data,
-                        size_t count, loff_t *ppos)
-{
-       struct bttv_fh *fh = file->private_data;
-       struct bttv *btv = fh->btv;
-       struct saa6588_command cmd;
-       cmd.block_count = count/3;
-       cmd.buffer = data;
-       cmd.instance = file;
-       cmd.result = -ENODEV;
-
-       bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
-
-       return cmd.result;
-}
-
-static unsigned int radio_poll(struct file *file, poll_table *wait)
-{
-       struct bttv_fh *fh = file->private_data;
-       struct bttv *btv = fh->btv;
-       struct saa6588_command cmd;
-       cmd.instance = file;
-       cmd.event_list = wait;
-       cmd.result = -ENODEV;
-       bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
-
-       return cmd.result;
-}
-
-static const struct v4l2_file_operations radio_fops =
-{
-       .owner    = THIS_MODULE,
-       .open     = radio_open,
-       .read     = radio_read,
-       .release  = radio_release,
-       .unlocked_ioctl = video_ioctl2,
-       .poll     = radio_poll,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap        = radio_querycap,
-       .vidioc_g_tuner         = radio_g_tuner,
-       .vidioc_enum_input      = radio_enum_input,
-       .vidioc_g_audio         = radio_g_audio,
-       .vidioc_s_tuner         = radio_s_tuner,
-       .vidioc_s_audio         = radio_s_audio,
-       .vidioc_s_input         = radio_s_input,
-       .vidioc_s_std           = radio_s_std,
-       .vidioc_queryctrl       = radio_queryctrl,
-       .vidioc_g_input         = radio_g_input,
-       .vidioc_g_ctrl          = bttv_g_ctrl,
-       .vidioc_s_ctrl          = bttv_s_ctrl,
-       .vidioc_g_frequency     = bttv_g_frequency,
-       .vidioc_s_frequency     = bttv_s_frequency,
-};
-
-static struct video_device radio_template = {
-       .fops      = &radio_fops,
-       .ioctl_ops = &radio_ioctl_ops,
-};
-
-/* ----------------------------------------------------------------------- */
-/* some debug code                                                         */
-
-static int bttv_risc_decode(u32 risc)
-{
-       static char *instr[16] = {
-               [ BT848_RISC_WRITE     >> 28 ] = "write",
-               [ BT848_RISC_SKIP      >> 28 ] = "skip",
-               [ BT848_RISC_WRITEC    >> 28 ] = "writec",
-               [ BT848_RISC_JUMP      >> 28 ] = "jump",
-               [ BT848_RISC_SYNC      >> 28 ] = "sync",
-               [ BT848_RISC_WRITE123  >> 28 ] = "write123",
-               [ BT848_RISC_SKIP123   >> 28 ] = "skip123",
-               [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
-       };
-       static int incr[16] = {
-               [ BT848_RISC_WRITE     >> 28 ] = 2,
-               [ BT848_RISC_JUMP      >> 28 ] = 2,
-               [ BT848_RISC_SYNC      >> 28 ] = 2,
-               [ BT848_RISC_WRITE123  >> 28 ] = 5,
-               [ BT848_RISC_SKIP123   >> 28 ] = 2,
-               [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
-       };
-       static char *bits[] = {
-               "be0",  "be1",  "be2",  "be3/resync",
-               "set0", "set1", "set2", "set3",
-               "clr0", "clr1", "clr2", "clr3",
-               "irq",  "res",  "eol",  "sol",
-       };
-       int i;
-
-       pr_cont("0x%08x [ %s", risc,
-              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
-       for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
-               if (risc & (1 << (i + 12)))
-                       pr_cont(" %s", bits[i]);
-       pr_cont(" count=%d ]\n", risc & 0xfff);
-       return incr[risc >> 28] ? incr[risc >> 28] : 1;
-}
-
-static void bttv_risc_disasm(struct bttv *btv,
-                            struct btcx_riscmem *risc)
-{
-       unsigned int i,j,n;
-
-       pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
-               btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
-       for (i = 0; i < (risc->size >> 2); i += n) {
-               pr_info("%s:   0x%lx: ",
-                       btv->c.v4l2_dev.name,
-                       (unsigned long)(risc->dma + (i<<2)));
-               n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
-               for (j = 1; j < n; j++)
-                       pr_info("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
-                               btv->c.v4l2_dev.name,
-                               (unsigned long)(risc->dma + ((i+j)<<2)),
-                               risc->cpu[i+j], j);
-               if (0 == risc->cpu[i])
-                       break;
-       }
-}
-
-static void bttv_print_riscaddr(struct bttv *btv)
-{
-       pr_info("  main: %08llx\n", (unsigned long long)btv->main.dma);
-       pr_info("  vbi : o=%08llx e=%08llx\n",
-               btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
-               btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
-       pr_info("  cap : o=%08llx e=%08llx\n",
-               btv->curr.top
-               ? (unsigned long long)btv->curr.top->top.dma : 0,
-               btv->curr.bottom
-               ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
-       pr_info("  scr : o=%08llx e=%08llx\n",
-               btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
-               btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
-       bttv_risc_disasm(btv, &btv->main);
-}
-
-/* ----------------------------------------------------------------------- */
-/* irq handler                                                             */
-
-static char *irq_name[] = {
-       "FMTCHG",  // format change detected (525 vs. 625)
-       "VSYNC",   // vertical sync (new field)
-       "HSYNC",   // horizontal sync
-       "OFLOW",   // chroma/luma AGC overflow
-       "HLOCK",   // horizontal lock changed
-       "VPRES",   // video presence changed
-       "6", "7",
-       "I2CDONE", // hw irc operation finished
-       "GPINT",   // gpio port triggered irq
-       "10",
-       "RISCI",   // risc instruction triggered irq
-       "FBUS",    // pixel data fifo dropped data (high pci bus latencies)
-       "FTRGT",   // pixel data fifo overrun
-       "FDSR",    // fifo data stream resyncronisation
-       "PPERR",   // parity error (data transfer)
-       "RIPERR",  // parity error (read risc instructions)
-       "PABORT",  // pci abort
-       "OCERR",   // risc instruction error
-       "SCERR",   // syncronisation error
-};
-
-static void bttv_print_irqbits(u32 print, u32 mark)
-{
-       unsigned int i;
-
-       pr_cont("bits:");
-       for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
-               if (print & (1 << i))
-                       pr_cont(" %s", irq_name[i]);
-               if (mark & (1 << i))
-                       pr_cont("*");
-       }
-}
-
-static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
-{
-       pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
-               btv->c.nr,
-               (unsigned long)btv->main.dma,
-               (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
-               (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
-               (unsigned long)rc);
-
-       if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
-               pr_notice("%d: Oh, there (temporarily?) is no input signal. "
-                         "Ok, then this is harmless, don't worry ;)\n",
-                         btv->c.nr);
-               return;
-       }
-       pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
-                 btv->c.nr);
-       pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
-                 btv->c.nr);
-       dump_stack();
-}
-
-static int
-bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
-{
-       struct bttv_buffer *item;
-
-       memset(set,0,sizeof(*set));
-
-       /* capture request ? */
-       if (!list_empty(&btv->capture)) {
-               set->frame_irq = 1;
-               item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
-               if (V4L2_FIELD_HAS_TOP(item->vb.field))
-                       set->top    = item;
-               if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
-                       set->bottom = item;
-
-               /* capture request for other field ? */
-               if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
-                   (item->vb.queue.next != &btv->capture)) {
-                       item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
-                       /* Mike Isely <isely@pobox.com> - Only check
-                        * and set up the bottom field in the logic
-                        * below.  Don't ever do the top field.  This
-                        * of course means that if we set up the
-                        * bottom field in the above code that we'll
-                        * actually skip a field.  But that's OK.
-                        * Having processed only a single buffer this
-                        * time, then the next time around the first
-                        * available buffer should be for a top field.
-                        * That will then cause us here to set up a
-                        * top then a bottom field in the normal way.
-                        * The alternative to this understanding is
-                        * that we set up the second available buffer
-                        * as a top field, but that's out of order
-                        * since this driver always processes the top
-                        * field first - the effect will be the two
-                        * buffers being returned in the wrong order,
-                        * with the second buffer also being delayed
-                        * by one field time (owing to the fifo nature
-                        * of videobuf).  Worse still, we'll be stuck
-                        * doing fields out of order now every time
-                        * until something else causes a field to be
-                        * dropped.  By effectively forcing a field to
-                        * drop this way then we always get back into
-                        * sync within a single frame time.  (Out of
-                        * order fields can screw up deinterlacing
-                        * algorithms.) */
-                       if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
-                               if (NULL == set->bottom &&
-                                   V4L2_FIELD_BOTTOM == item->vb.field) {
-                                       set->bottom = item;
-                               }
-                               if (NULL != set->top  &&  NULL != set->bottom)
-                                       set->top_irq = 2;
-                       }
-               }
-       }
-
-       /* screen overlay ? */
-       if (NULL != btv->screen) {
-               if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
-                       if (NULL == set->top && NULL == set->bottom) {
-                               set->top    = btv->screen;
-                               set->bottom = btv->screen;
-                       }
-               } else {
-                       if (V4L2_FIELD_TOP == btv->screen->vb.field &&
-                           NULL == set->top) {
-                               set->top = btv->screen;
-                       }
-                       if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
-                           NULL == set->bottom) {
-                               set->bottom = btv->screen;
-                       }
-               }
-       }
-
-       dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
-               btv->c.nr, set->top, set->bottom,
-               btv->screen, set->frame_irq, set->top_irq);
-       return 0;
-}
-
-static void
-bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
-                     struct bttv_buffer_set *curr, unsigned int state)
-{
-       struct timeval ts;
-
-       do_gettimeofday(&ts);
-
-       if (wakeup->top == wakeup->bottom) {
-               if (NULL != wakeup->top && curr->top != wakeup->top) {
-                       if (irq_debug > 1)
-                               pr_debug("%d: wakeup: both=%p\n",
-                                        btv->c.nr, wakeup->top);
-                       wakeup->top->vb.ts = ts;
-                       wakeup->top->vb.field_count = btv->field_count;
-                       wakeup->top->vb.state = state;
-                       wake_up(&wakeup->top->vb.done);
-               }
-       } else {
-               if (NULL != wakeup->top && curr->top != wakeup->top) {
-                       if (irq_debug > 1)
-                               pr_debug("%d: wakeup: top=%p\n",
-                                        btv->c.nr, wakeup->top);
-                       wakeup->top->vb.ts = ts;
-                       wakeup->top->vb.field_count = btv->field_count;
-                       wakeup->top->vb.state = state;
-                       wake_up(&wakeup->top->vb.done);
-               }
-               if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
-                       if (irq_debug > 1)
-                               pr_debug("%d: wakeup: bottom=%p\n",
-                                        btv->c.nr, wakeup->bottom);
-                       wakeup->bottom->vb.ts = ts;
-                       wakeup->bottom->vb.field_count = btv->field_count;
-                       wakeup->bottom->vb.state = state;
-                       wake_up(&wakeup->bottom->vb.done);
-               }
-       }
-}
-
-static void
-bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
-                   unsigned int state)
-{
-       struct timeval ts;
-
-       if (NULL == wakeup)
-               return;
-
-       do_gettimeofday(&ts);
-       wakeup->vb.ts = ts;
-       wakeup->vb.field_count = btv->field_count;
-       wakeup->vb.state = state;
-       wake_up(&wakeup->vb.done);
-}
-
-static void bttv_irq_timeout(unsigned long data)
-{
-       struct bttv *btv = (struct bttv *)data;
-       struct bttv_buffer_set old,new;
-       struct bttv_buffer *ovbi;
-       struct bttv_buffer *item;
-       unsigned long flags;
-
-       if (bttv_verbose) {
-               pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
-                       btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
-                       btread(BT848_RISC_COUNT));
-               bttv_print_irqbits(btread(BT848_INT_STAT),0);
-               pr_cont("\n");
-       }
-
-       spin_lock_irqsave(&btv->s_lock,flags);
-
-       /* deactivate stuff */
-       memset(&new,0,sizeof(new));
-       old  = btv->curr;
-       ovbi = btv->cvbi;
-       btv->curr = new;
-       btv->cvbi = NULL;
-       btv->loop_irq = 0;
-       bttv_buffer_activate_video(btv, &new);
-       bttv_buffer_activate_vbi(btv,   NULL);
-       bttv_set_dma(btv, 0);
-
-       /* wake up */
-       bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
-       bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
-
-       /* cancel all outstanding capture / vbi requests */
-       while (!list_empty(&btv->capture)) {
-               item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
-               list_del(&item->vb.queue);
-               item->vb.state = VIDEOBUF_ERROR;
-               wake_up(&item->vb.done);
-       }
-       while (!list_empty(&btv->vcapture)) {
-               item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
-               list_del(&item->vb.queue);
-               item->vb.state = VIDEOBUF_ERROR;
-               wake_up(&item->vb.done);
-       }
-
-       btv->errors++;
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-}
-
-static void
-bttv_irq_wakeup_top(struct bttv *btv)
-{
-       struct bttv_buffer *wakeup = btv->curr.top;
-
-       if (NULL == wakeup)
-               return;
-
-       spin_lock(&btv->s_lock);
-       btv->curr.top_irq = 0;
-       btv->curr.top = NULL;
-       bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
-
-       do_gettimeofday(&wakeup->vb.ts);
-       wakeup->vb.field_count = btv->field_count;
-       wakeup->vb.state = VIDEOBUF_DONE;
-       wake_up(&wakeup->vb.done);
-       spin_unlock(&btv->s_lock);
-}
-
-static inline int is_active(struct btcx_riscmem *risc, u32 rc)
-{
-       if (rc < risc->dma)
-               return 0;
-       if (rc > risc->dma + risc->size)
-               return 0;
-       return 1;
-}
-
-static void
-bttv_irq_switch_video(struct bttv *btv)
-{
-       struct bttv_buffer_set new;
-       struct bttv_buffer_set old;
-       dma_addr_t rc;
-
-       spin_lock(&btv->s_lock);
-
-       /* new buffer set */
-       bttv_irq_next_video(btv, &new);
-       rc = btread(BT848_RISC_COUNT);
-       if ((btv->curr.top    && is_active(&btv->curr.top->top,       rc)) ||
-           (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
-               btv->framedrop++;
-               if (debug_latency)
-                       bttv_irq_debug_low_latency(btv, rc);
-               spin_unlock(&btv->s_lock);
-               return;
-       }
-
-       /* switch over */
-       old = btv->curr;
-       btv->curr = new;
-       btv->loop_irq &= ~1;
-       bttv_buffer_activate_video(btv, &new);
-       bttv_set_dma(btv, 0);
-
-       /* switch input */
-       if (UNSET != btv->new_input) {
-               video_mux(btv,btv->new_input);
-               btv->new_input = UNSET;
-       }
-
-       /* wake up finished buffers */
-       bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
-       spin_unlock(&btv->s_lock);
-}
-
-static void
-bttv_irq_switch_vbi(struct bttv *btv)
-{
-       struct bttv_buffer *new = NULL;
-       struct bttv_buffer *old;
-       u32 rc;
-
-       spin_lock(&btv->s_lock);
-
-       if (!list_empty(&btv->vcapture))
-               new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
-       old = btv->cvbi;
-
-       rc = btread(BT848_RISC_COUNT);
-       if (NULL != old && (is_active(&old->top,    rc) ||
-                           is_active(&old->bottom, rc))) {
-               btv->framedrop++;
-               if (debug_latency)
-                       bttv_irq_debug_low_latency(btv, rc);
-               spin_unlock(&btv->s_lock);
-               return;
-       }
-
-       /* switch */
-       btv->cvbi = new;
-       btv->loop_irq &= ~4;
-       bttv_buffer_activate_vbi(btv, new);
-       bttv_set_dma(btv, 0);
-
-       bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
-       spin_unlock(&btv->s_lock);
-}
-
-static irqreturn_t bttv_irq(int irq, void *dev_id)
-{
-       u32 stat,astat;
-       u32 dstat;
-       int count;
-       struct bttv *btv;
-       int handled = 0;
-
-       btv=(struct bttv *)dev_id;
-
-       count=0;
-       while (1) {
-               /* get/clear interrupt status bits */
-               stat=btread(BT848_INT_STAT);
-               astat=stat&btread(BT848_INT_MASK);
-               if (!astat)
-                       break;
-               handled = 1;
-               btwrite(stat,BT848_INT_STAT);
-
-               /* get device status bits */
-               dstat=btread(BT848_DSTATUS);
-
-               if (irq_debug) {
-                       pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
-                                btv->c.nr, count, btv->field_count,
-                                stat>>28, btread(BT848_RISC_COUNT));
-                       bttv_print_irqbits(stat,astat);
-                       if (stat & BT848_INT_HLOCK)
-                               pr_cont("   HLOC => %s",
-                                       dstat & BT848_DSTATUS_HLOC
-                                       ? "yes" : "no");
-                       if (stat & BT848_INT_VPRES)
-                               pr_cont("   PRES => %s",
-                                       dstat & BT848_DSTATUS_PRES
-                                       ? "yes" : "no");
-                       if (stat & BT848_INT_FMTCHG)
-                               pr_cont("   NUML => %s",
-                                       dstat & BT848_DSTATUS_NUML
-                                       ? "625" : "525");
-                       pr_cont("\n");
-               }
-
-               if (astat&BT848_INT_VSYNC)
-                       btv->field_count++;
-
-               if ((astat & BT848_INT_GPINT) && btv->remote) {
-                       bttv_input_irq(btv);
-               }
-
-               if (astat & BT848_INT_I2CDONE) {
-                       btv->i2c_done = stat;
-                       wake_up(&btv->i2c_queue);
-               }
-
-               if ((astat & BT848_INT_RISCI)  &&  (stat & (4<<28)))
-                       bttv_irq_switch_vbi(btv);
-
-               if ((astat & BT848_INT_RISCI)  &&  (stat & (2<<28)))
-                       bttv_irq_wakeup_top(btv);
-
-               if ((astat & BT848_INT_RISCI)  &&  (stat & (1<<28)))
-                       bttv_irq_switch_video(btv);
-
-               if ((astat & BT848_INT_HLOCK)  &&  btv->opt_automute)
-                       audio_mute(btv, btv->mute);  /* trigger automute */
-
-               if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
-                       pr_info("%d: %s%s @ %08x,",
-                               btv->c.nr,
-                               (astat & BT848_INT_SCERR) ? "SCERR" : "",
-                               (astat & BT848_INT_OCERR) ? "OCERR" : "",
-                               btread(BT848_RISC_COUNT));
-                       bttv_print_irqbits(stat,astat);
-                       pr_cont("\n");
-                       if (bttv_debug)
-                               bttv_print_riscaddr(btv);
-               }
-               if (fdsr && astat & BT848_INT_FDSR) {
-                       pr_info("%d: FDSR @ %08x\n",
-                               btv->c.nr, btread(BT848_RISC_COUNT));
-                       if (bttv_debug)
-                               bttv_print_riscaddr(btv);
-               }
-
-               count++;
-               if (count > 4) {
-
-                       if (count > 8 || !(astat & BT848_INT_GPINT)) {
-                               btwrite(0, BT848_INT_MASK);
-
-                               pr_err("%d: IRQ lockup, cleared int mask [",
-                                      btv->c.nr);
-                       } else {
-                               pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
-                                      btv->c.nr);
-
-                               btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
-                                               BT848_INT_MASK);
-                       };
-
-                       bttv_print_irqbits(stat,astat);
-
-                       pr_cont("]\n");
-               }
-       }
-       btv->irq_total++;
-       if (handled)
-               btv->irq_me++;
-       return IRQ_RETVAL(handled);
-}
-
-
-/* ----------------------------------------------------------------------- */
-/* initialitation                                                          */
-
-static struct video_device *vdev_init(struct bttv *btv,
-                                     const struct video_device *template,
-                                     const char *type_name)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template;
-       vfd->v4l2_dev = &btv->c.v4l2_dev;
-       vfd->release = video_device_release;
-       vfd->debug   = bttv_debug;
-       video_set_drvdata(vfd, btv);
-       snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
-                btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
-                type_name, bttv_tvcards[btv->c.type].name);
-       return vfd;
-}
-
-static void bttv_unregister_video(struct bttv *btv)
-{
-       if (btv->video_dev) {
-               if (video_is_registered(btv->video_dev))
-                       video_unregister_device(btv->video_dev);
-               else
-                       video_device_release(btv->video_dev);
-               btv->video_dev = NULL;
-       }
-       if (btv->vbi_dev) {
-               if (video_is_registered(btv->vbi_dev))
-                       video_unregister_device(btv->vbi_dev);
-               else
-                       video_device_release(btv->vbi_dev);
-               btv->vbi_dev = NULL;
-       }
-       if (btv->radio_dev) {
-               if (video_is_registered(btv->radio_dev))
-                       video_unregister_device(btv->radio_dev);
-               else
-                       video_device_release(btv->radio_dev);
-               btv->radio_dev = NULL;
-       }
-}
-
-/* register video4linux devices */
-static int __devinit bttv_register_video(struct bttv *btv)
-{
-       if (no_overlay > 0)
-               pr_notice("Overlay support disabled\n");
-
-       /* video */
-       btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
-
-       if (NULL == btv->video_dev)
-               goto err;
-       if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
-                                 video_nr[btv->c.nr]) < 0)
-               goto err;
-       pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->video_dev));
-       if (device_create_file(&btv->video_dev->dev,
-                                    &dev_attr_card)<0) {
-               pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
-               goto err;
-       }
-
-       /* vbi */
-       btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
-
-       if (NULL == btv->vbi_dev)
-               goto err;
-       if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
-                                 vbi_nr[btv->c.nr]) < 0)
-               goto err;
-       pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->vbi_dev));
-
-       if (!btv->has_radio)
-               return 0;
-       /* radio */
-       btv->radio_dev = vdev_init(btv, &radio_template, "radio");
-       if (NULL == btv->radio_dev)
-               goto err;
-       if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
-                                 radio_nr[btv->c.nr]) < 0)
-               goto err;
-       pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->radio_dev));
-
-       /* all done */
-       return 0;
-
- err:
-       bttv_unregister_video(btv);
-       return -1;
-}
-
-
-/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
-/* response on cards with no firmware is not enabled by OF */
-static void pci_set_command(struct pci_dev *dev)
-{
-#if defined(__powerpc__)
-       unsigned int cmd;
-
-       pci_read_config_dword(dev, PCI_COMMAND, &cmd);
-       cmd = (cmd | PCI_COMMAND_MEMORY );
-       pci_write_config_dword(dev, PCI_COMMAND, cmd);
-#endif
-}
-
-static int __devinit bttv_probe(struct pci_dev *dev,
-                               const struct pci_device_id *pci_id)
-{
-       int result;
-       unsigned char lat;
-       struct bttv *btv;
-
-       if (bttv_num == BTTV_MAX)
-               return -ENOMEM;
-       pr_info("Bt8xx card found (%d)\n", bttv_num);
-       bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
-       if (btv == NULL) {
-               pr_err("out of memory\n");
-               return -ENOMEM;
-       }
-       btv->c.nr  = bttv_num;
-       snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
-                       "bttv%d", btv->c.nr);
-
-       /* initialize structs / fill in defaults */
-       mutex_init(&btv->lock);
-       spin_lock_init(&btv->s_lock);
-       spin_lock_init(&btv->gpio_lock);
-       init_waitqueue_head(&btv->i2c_queue);
-       INIT_LIST_HEAD(&btv->c.subs);
-       INIT_LIST_HEAD(&btv->capture);
-       INIT_LIST_HEAD(&btv->vcapture);
-       v4l2_prio_init(&btv->prio);
-
-       init_timer(&btv->timeout);
-       btv->timeout.function = bttv_irq_timeout;
-       btv->timeout.data     = (unsigned long)btv;
-
-       btv->i2c_rc = -1;
-       btv->tuner_type  = UNSET;
-       btv->new_input   = UNSET;
-       btv->has_radio=radio[btv->c.nr];
-
-       /* pci stuff (init, get irq/mmio, ... */
-       btv->c.pci = dev;
-       btv->id  = dev->device;
-       if (pci_enable_device(dev)) {
-               pr_warn("%d: Can't enable device\n", btv->c.nr);
-               return -EIO;
-       }
-       if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
-               pr_warn("%d: No suitable DMA available\n", btv->c.nr);
-               return -EIO;
-       }
-       if (!request_mem_region(pci_resource_start(dev,0),
-                               pci_resource_len(dev,0),
-                               btv->c.v4l2_dev.name)) {
-               pr_warn("%d: can't request iomem (0x%llx)\n",
-                       btv->c.nr,
-                       (unsigned long long)pci_resource_start(dev, 0));
-               return -EBUSY;
-       }
-       pci_set_master(dev);
-       pci_set_command(dev);
-
-       result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
-       if (result < 0) {
-               pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
-               goto fail0;
-       }
-
-       btv->revision = dev->revision;
-       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-       pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
-               bttv_num, btv->id, btv->revision, pci_name(dev),
-               btv->c.pci->irq, lat,
-               (unsigned long long)pci_resource_start(dev, 0));
-       schedule();
-
-       btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
-       if (NULL == btv->bt848_mmio) {
-               pr_err("%d: ioremap() failed\n", btv->c.nr);
-               result = -EIO;
-               goto fail1;
-       }
-
-       /* identify card */
-       bttv_idcard(btv);
-
-       /* disable irqs, register irq handler */
-       btwrite(0, BT848_INT_MASK);
-       result = request_irq(btv->c.pci->irq, bttv_irq,
-           IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
-       if (result < 0) {
-               pr_err("%d: can't get IRQ %d\n",
-                      bttv_num, btv->c.pci->irq);
-               goto fail1;
-       }
-
-       if (0 != bttv_handle_chipset(btv)) {
-               result = -EIO;
-               goto fail2;
-       }
-
-       /* init options from insmod args */
-       btv->opt_combfilter = combfilter;
-       btv->opt_lumafilter = lumafilter;
-       btv->opt_automute   = automute;
-       btv->opt_chroma_agc = chroma_agc;
-       btv->opt_adc_crush  = adc_crush;
-       btv->opt_vcr_hack   = vcr_hack;
-       btv->opt_whitecrush_upper  = whitecrush_upper;
-       btv->opt_whitecrush_lower  = whitecrush_lower;
-       btv->opt_uv_ratio   = uv_ratio;
-       btv->opt_full_luma_range   = full_luma_range;
-       btv->opt_coring     = coring;
-
-       /* fill struct bttv with some useful defaults */
-       btv->init.btv         = btv;
-       btv->init.ov.w.width  = 320;
-       btv->init.ov.w.height = 240;
-       btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-       btv->init.width       = 320;
-       btv->init.height      = 240;
-       btv->input = 0;
-
-       /* initialize hardware */
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"pre-init");
-
-       bttv_risc_init_main(btv);
-       init_bt848(btv);
-
-       /* gpio */
-       btwrite(0x00, BT848_GPIO_REG_INP);
-       btwrite(0x00, BT848_GPIO_OUT_EN);
-       if (bttv_verbose)
-               bttv_gpio_tracking(btv,"init");
-
-       /* needs to be done before i2c is registered */
-       bttv_init_card1(btv);
-
-       /* register i2c + gpio */
-       init_bttv_i2c(btv);
-
-       /* some card-specific stuff (needs working i2c) */
-       bttv_init_card2(btv);
-       bttv_init_tuner(btv);
-       init_irqreg(btv);
-
-       /* register video4linux + input */
-       if (!bttv_tvcards[btv->c.type].no_video) {
-               bttv_register_video(btv);
-               bt848_bright(btv,32768);
-               bt848_contrast(btv, 27648);
-               bt848_hue(btv,32768);
-               bt848_sat(btv,32768);
-               audio_mute(btv, 1);
-               set_input(btv, 0, btv->tvnorm);
-               bttv_crop_reset(&btv->crop[0], btv->tvnorm);
-               btv->crop[1] = btv->crop[0]; /* current = default */
-               disclaim_vbi_lines(btv);
-               disclaim_video_lines(btv);
-       }
-
-       /* add subdevices and autoload dvb-bt8xx if needed */
-       if (bttv_tvcards[btv->c.type].has_dvb) {
-               bttv_sub_add_device(&btv->c, "dvb");
-               request_modules(btv);
-       }
-
-       if (!disable_ir) {
-               init_bttv_i2c_ir(btv);
-               bttv_input_init(btv);
-       }
-
-       /* everything is fine */
-       bttv_num++;
-       return 0;
-
-fail2:
-       free_irq(btv->c.pci->irq,btv);
-
-fail1:
-       v4l2_device_unregister(&btv->c.v4l2_dev);
-
-fail0:
-       if (btv->bt848_mmio)
-               iounmap(btv->bt848_mmio);
-       release_mem_region(pci_resource_start(btv->c.pci,0),
-                          pci_resource_len(btv->c.pci,0));
-       return result;
-}
-
-static void __devexit bttv_remove(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct bttv *btv = to_bttv(v4l2_dev);
-
-       if (bttv_verbose)
-               pr_info("%d: unloading\n", btv->c.nr);
-
-       if (bttv_tvcards[btv->c.type].has_dvb)
-               flush_request_modules(btv);
-
-       /* shutdown everything (DMA+IRQs) */
-       btand(~15, BT848_GPIO_DMA_CTL);
-       btwrite(0, BT848_INT_MASK);
-       btwrite(~0x0, BT848_INT_STAT);
-       btwrite(0x0, BT848_GPIO_OUT_EN);
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"cleanup");
-
-       /* tell gpio modules we are leaving ... */
-       btv->shutdown=1;
-       bttv_input_fini(btv);
-       bttv_sub_del_devices(&btv->c);
-
-       /* unregister i2c_bus + input */
-       fini_bttv_i2c(btv);
-
-       /* unregister video4linux */
-       bttv_unregister_video(btv);
-
-       /* free allocated memory */
-       btcx_riscmem_free(btv->c.pci,&btv->main);
-
-       /* free ressources */
-       free_irq(btv->c.pci->irq,btv);
-       iounmap(btv->bt848_mmio);
-       release_mem_region(pci_resource_start(btv->c.pci,0),
-                          pci_resource_len(btv->c.pci,0));
-
-       v4l2_device_unregister(&btv->c.v4l2_dev);
-       bttvs[btv->c.nr] = NULL;
-       kfree(btv);
-
-       return;
-}
-
-#ifdef CONFIG_PM
-static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct bttv *btv = to_bttv(v4l2_dev);
-       struct bttv_buffer_set idle;
-       unsigned long flags;
-
-       dprintk("%d: suspend %d\n", btv->c.nr, state.event);
-
-       /* stop dma + irqs */
-       spin_lock_irqsave(&btv->s_lock,flags);
-       memset(&idle, 0, sizeof(idle));
-       btv->state.video = btv->curr;
-       btv->state.vbi   = btv->cvbi;
-       btv->state.loop_irq = btv->loop_irq;
-       btv->curr = idle;
-       btv->loop_irq = 0;
-       bttv_buffer_activate_video(btv, &idle);
-       bttv_buffer_activate_vbi(btv, NULL);
-       bttv_set_dma(btv, 0);
-       btwrite(0, BT848_INT_MASK);
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-
-       /* save bt878 state */
-       btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
-       btv->state.gpio_data   = gpio_read();
-
-       /* save pci state */
-       pci_save_state(pci_dev);
-       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
-               pci_disable_device(pci_dev);
-               btv->state.disabled = 1;
-       }
-       return 0;
-}
-
-static int bttv_resume(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct bttv *btv = to_bttv(v4l2_dev);
-       unsigned long flags;
-       int err;
-
-       dprintk("%d: resume\n", btv->c.nr);
-
-       /* restore pci state */
-       if (btv->state.disabled) {
-               err=pci_enable_device(pci_dev);
-               if (err) {
-                       pr_warn("%d: Can't enable device\n", btv->c.nr);
-                       return err;
-               }
-               btv->state.disabled = 0;
-       }
-       err=pci_set_power_state(pci_dev, PCI_D0);
-       if (err) {
-               pci_disable_device(pci_dev);
-               pr_warn("%d: Can't enable device\n", btv->c.nr);
-               btv->state.disabled = 1;
-               return err;
-       }
-
-       pci_restore_state(pci_dev);
-
-       /* restore bt878 state */
-       bttv_reinit_bt848(btv);
-       gpio_inout(0xffffff, btv->state.gpio_enable);
-       gpio_write(btv->state.gpio_data);
-
-       /* restart dma */
-       spin_lock_irqsave(&btv->s_lock,flags);
-       btv->curr = btv->state.video;
-       btv->cvbi = btv->state.vbi;
-       btv->loop_irq = btv->state.loop_irq;
-       bttv_buffer_activate_video(btv, &btv->curr);
-       bttv_buffer_activate_vbi(btv, btv->cvbi);
-       bttv_set_dma(btv, 0);
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-       return 0;
-}
-#endif
-
-static struct pci_device_id bttv_pci_tbl[] = {
-       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
-       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
-       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
-       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
-       {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
-       {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
-
-static struct pci_driver bttv_pci_driver = {
-       .name     = "bttv",
-       .id_table = bttv_pci_tbl,
-       .probe    = bttv_probe,
-       .remove   = __devexit_p(bttv_remove),
-#ifdef CONFIG_PM
-       .suspend  = bttv_suspend,
-       .resume   = bttv_resume,
-#endif
-};
-
-static int __init bttv_init_module(void)
-{
-       int ret;
-
-       bttv_num = 0;
-
-       pr_info("driver version %s loaded\n", BTTV_VERSION);
-       if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
-               gbuffers = 2;
-       if (gbufsize > BTTV_MAX_FBUF)
-               gbufsize = BTTV_MAX_FBUF;
-       gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
-       if (bttv_verbose)
-               pr_info("using %d buffers with %dk (%d pages) each for capture\n",
-                       gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
-
-       bttv_check_chipset();
-
-       ret = bus_register(&bttv_sub_bus_type);
-       if (ret < 0) {
-               pr_warn("bus_register error: %d\n", ret);
-               return ret;
-       }
-       ret = pci_register_driver(&bttv_pci_driver);
-       if (ret < 0)
-               bus_unregister(&bttv_sub_bus_type);
-
-       return ret;
-}
-
-static void __exit bttv_cleanup_module(void)
-{
-       pci_unregister_driver(&bttv_pci_driver);
-       bus_unregister(&bttv_sub_bus_type);
-}
-
-module_init(bttv_init_module);
-module_exit(bttv_cleanup_module);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
deleted file mode 100644 (file)
index 922e823..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-
-    bttv-gpio.c  --  gpio sub drivers
-
-    sysfs-based sub driver interface for bttv
-    mainly intended for gpio access
-
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-                          & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include "bttvp.h"
-
-/* ----------------------------------------------------------------------- */
-/* internal: the bttv "bus"                                                */
-
-static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
-{
-       struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
-       int len = strlen(sub->wanted);
-
-       if (0 == strncmp(dev_name(dev), sub->wanted, len))
-               return 1;
-       return 0;
-}
-
-static int bttv_sub_probe(struct device *dev)
-{
-       struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
-       struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
-
-       return sub->probe ? sub->probe(sdev) : -ENODEV;
-}
-
-static int bttv_sub_remove(struct device *dev)
-{
-       struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
-       struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
-
-       if (sub->remove)
-               sub->remove(sdev);
-       return 0;
-}
-
-struct bus_type bttv_sub_bus_type = {
-       .name   = "bttv-sub",
-       .match  = &bttv_sub_bus_match,
-       .probe  = bttv_sub_probe,
-       .remove = bttv_sub_remove,
-};
-
-static void release_sub_device(struct device *dev)
-{
-       struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
-       kfree(sub);
-}
-
-int bttv_sub_add_device(struct bttv_core *core, char *name)
-{
-       struct bttv_sub_device *sub;
-       int err;
-
-       sub = kzalloc(sizeof(*sub),GFP_KERNEL);
-       if (NULL == sub)
-               return -ENOMEM;
-
-       sub->core        = core;
-       sub->dev.parent  = &core->pci->dev;
-       sub->dev.bus     = &bttv_sub_bus_type;
-       sub->dev.release = release_sub_device;
-       dev_set_name(&sub->dev, "%s%d", name, core->nr);
-
-       err = device_register(&sub->dev);
-       if (0 != err) {
-               kfree(sub);
-               return err;
-       }
-       pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
-       list_add_tail(&sub->list,&core->subs);
-       return 0;
-}
-
-int bttv_sub_del_devices(struct bttv_core *core)
-{
-       struct bttv_sub_device *sub, *save;
-
-       list_for_each_entry_safe(sub, save, &core->subs, list) {
-               list_del(&sub->list);
-               device_unregister(&sub->dev);
-       }
-       return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-/* external: sub-driver register/unregister                                */
-
-int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted)
-{
-       sub->drv.bus = &bttv_sub_bus_type;
-       snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
-       return driver_register(&sub->drv);
-}
-EXPORT_SYMBOL(bttv_sub_register);
-
-int bttv_sub_unregister(struct bttv_sub_driver *sub)
-{
-       driver_unregister(&sub->drv);
-       return 0;
-}
-EXPORT_SYMBOL(bttv_sub_unregister);
-
-/* ----------------------------------------------------------------------- */
-/* external: gpio access functions                                         */
-
-void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits)
-{
-       struct bttv *btv = container_of(core, struct bttv, c);
-       unsigned long flags;
-       u32 data;
-
-       spin_lock_irqsave(&btv->gpio_lock,flags);
-       data = btread(BT848_GPIO_OUT_EN);
-       data = data & ~mask;
-       data = data | (mask & outbits);
-       btwrite(data,BT848_GPIO_OUT_EN);
-       spin_unlock_irqrestore(&btv->gpio_lock,flags);
-}
-
-u32 bttv_gpio_read(struct bttv_core *core)
-{
-       struct bttv *btv = container_of(core, struct bttv, c);
-       u32 value;
-
-       value = btread(BT848_GPIO_DATA);
-       return value;
-}
-
-void bttv_gpio_write(struct bttv_core *core, u32 value)
-{
-       struct bttv *btv = container_of(core, struct bttv, c);
-
-       btwrite(value,BT848_GPIO_DATA);
-}
-
-void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
-{
-       struct bttv *btv = container_of(core, struct bttv, c);
-       unsigned long flags;
-       u32 data;
-
-       spin_lock_irqsave(&btv->gpio_lock,flags);
-       data = btread(BT848_GPIO_DATA);
-       data = data & ~mask;
-       data = data | (mask & bits);
-       btwrite(data,BT848_GPIO_DATA);
-       spin_unlock_irqrestore(&btv->gpio_lock,flags);
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
deleted file mode 100644 (file)
index 580c8e6..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
-
-    bttv-i2c.c  --  all the i2c code is here
-
-    bttv - Bt848 frame grabber driver
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-                          & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
-       - Multituner support and i2c address binding
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include "bttvp.h"
-#include <media/v4l2-common.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
-
-static int i2c_debug;
-static int i2c_hw;
-static int i2c_scan;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
-module_param(i2c_hw,    int, 0444);
-MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
-                       "instead of software bitbang");
-module_param(i2c_scan,  int, 0444);
-MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
-
-static unsigned int i2c_udelay = 5;
-module_param(i2c_udelay, int, 0444);
-MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
-               "(should be 5 or higher). Lower value means higher bus speed.");
-
-/* ----------------------------------------------------------------------- */
-/* I2C functions - bitbanging adapter (software i2c)                       */
-
-static void bttv_bit_setscl(void *data, int state)
-{
-       struct bttv *btv = (struct bttv*)data;
-
-       if (state)
-               btv->i2c_state |= 0x02;
-       else
-               btv->i2c_state &= ~0x02;
-       btwrite(btv->i2c_state, BT848_I2C);
-       btread(BT848_I2C);
-}
-
-static void bttv_bit_setsda(void *data, int state)
-{
-       struct bttv *btv = (struct bttv*)data;
-
-       if (state)
-               btv->i2c_state |= 0x01;
-       else
-               btv->i2c_state &= ~0x01;
-       btwrite(btv->i2c_state, BT848_I2C);
-       btread(BT848_I2C);
-}
-
-static int bttv_bit_getscl(void *data)
-{
-       struct bttv *btv = (struct bttv*)data;
-       int state;
-
-       state = btread(BT848_I2C) & 0x02 ? 1 : 0;
-       return state;
-}
-
-static int bttv_bit_getsda(void *data)
-{
-       struct bttv *btv = (struct bttv*)data;
-       int state;
-
-       state = btread(BT848_I2C) & 0x01;
-       return state;
-}
-
-static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
-       .setsda  = bttv_bit_setsda,
-       .setscl  = bttv_bit_setscl,
-       .getsda  = bttv_bit_getsda,
-       .getscl  = bttv_bit_getscl,
-       .udelay  = 16,
-       .timeout = 200,
-};
-
-/* ----------------------------------------------------------------------- */
-/* I2C functions - hardware i2c                                            */
-
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static int
-bttv_i2c_wait_done(struct bttv *btv)
-{
-       int rc = 0;
-
-       /* timeout */
-       if (wait_event_interruptible_timeout(btv->i2c_queue,
-           btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
-               rc = -EIO;
-
-       if (btv->i2c_done & BT848_INT_RACK)
-               rc = 1;
-       btv->i2c_done = 0;
-       return rc;
-}
-
-#define I2C_HW (BT878_I2C_MODE  | BT848_I2C_SYNC |\
-               BT848_I2C_SCL | BT848_I2C_SDA)
-
-static int
-bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
-{
-       u32 xmit;
-       int retval,cnt;
-
-       /* sanity checks */
-       if (0 == msg->len)
-               return -EINVAL;
-
-       /* start, address + first byte */
-       xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
-       if (msg->len > 1 || !last)
-               xmit |= BT878_I2C_NOSTOP;
-       btwrite(xmit, BT848_I2C);
-       retval = bttv_i2c_wait_done(btv);
-       if (retval < 0)
-               goto err;
-       if (retval == 0)
-               goto eio;
-       if (i2c_debug) {
-               pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
-       }
-
-       for (cnt = 1; cnt < msg->len; cnt++ ) {
-               /* following bytes */
-               xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
-               if (cnt < msg->len-1 || !last)
-                       xmit |= BT878_I2C_NOSTOP;
-               btwrite(xmit, BT848_I2C);
-               retval = bttv_i2c_wait_done(btv);
-               if (retval < 0)
-                       goto err;
-               if (retval == 0)
-                       goto eio;
-               if (i2c_debug)
-                       pr_cont(" %02x", msg->buf[cnt]);
-       }
-       if (!(xmit & BT878_I2C_NOSTOP))
-               pr_cont(">\n");
-       return msg->len;
-
- eio:
-       retval = -EIO;
- err:
-       if (i2c_debug)
-               pr_cont(" ERR: %d\n",retval);
-       return retval;
-}
-
-static int
-bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
-{
-       u32 xmit;
-       u32 cnt;
-       int retval;
-
-       for (cnt = 0; cnt < msg->len; cnt++) {
-               xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
-               if (cnt < msg->len-1)
-                       xmit |= BT848_I2C_W3B;
-               if (cnt < msg->len-1 || !last)
-                       xmit |= BT878_I2C_NOSTOP;
-               if (cnt)
-                       xmit |= BT878_I2C_NOSTART;
-
-               if (i2c_debug) {
-                       if (!(xmit & BT878_I2C_NOSTART))
-                               pr_cont(" <R %02x", (msg->addr << 1) +1);
-               }
-
-               btwrite(xmit, BT848_I2C);
-               retval = bttv_i2c_wait_done(btv);
-               if (retval < 0)
-                       goto err;
-               if (retval == 0)
-                       goto eio;
-               msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
-               if (i2c_debug) {
-                       pr_cont(" =%02x", msg->buf[cnt]);
-               }
-               if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
-                       pr_cont(" >\n");
-       }
-
-
-       return msg->len;
-
- eio:
-       retval = -EIO;
- err:
-       if (i2c_debug)
-               pr_cont(" ERR: %d\n",retval);
-       return retval;
-}
-
-static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
-       struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
-       struct bttv *btv = to_bttv(v4l2_dev);
-       int retval = 0;
-       int i;
-
-       if (i2c_debug)
-               pr_debug("bt-i2c:");
-
-       btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
-       for (i = 0 ; i < num; i++) {
-               if (msgs[i].flags & I2C_M_RD) {
-                       /* read */
-                       retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
-                       if (retval < 0)
-                               goto err;
-               } else {
-                       /* write */
-                       retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
-                       if (retval < 0)
-                               goto err;
-               }
-       }
-       return num;
-
- err:
-       return retval;
-}
-
-static const struct i2c_algorithm bttv_algo = {
-       .master_xfer   = bttv_i2c_xfer,
-       .functionality = functionality,
-};
-
-/* ----------------------------------------------------------------------- */
-/* I2C functions - common stuff                                            */
-
-/* read I2C */
-int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
-{
-       unsigned char buffer = 0;
-
-       if (0 != btv->i2c_rc)
-               return -1;
-       if (bttv_verbose && NULL != probe_for)
-               pr_info("%d: i2c: checking for %s @ 0x%02x... ",
-                       btv->c.nr, probe_for, addr);
-       btv->i2c_client.addr = addr >> 1;
-       if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
-               if (NULL != probe_for) {
-                       if (bttv_verbose)
-                               pr_cont("not found\n");
-               } else
-                       pr_warn("%d: i2c read 0x%x: error\n",
-                               btv->c.nr, addr);
-               return -1;
-       }
-       if (bttv_verbose && NULL != probe_for)
-               pr_cont("found\n");
-       return buffer;
-}
-
-/* write I2C */
-int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
-                   unsigned char b2, int both)
-{
-       unsigned char buffer[2];
-       int bytes = both ? 2 : 1;
-
-       if (0 != btv->i2c_rc)
-               return -1;
-       btv->i2c_client.addr = addr >> 1;
-       buffer[0] = b1;
-       buffer[1] = b2;
-       if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
-               return -1;
-       return 0;
-}
-
-/* read EEPROM content */
-void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
-{
-       memset(eedata, 0, 256);
-       if (0 != btv->i2c_rc)
-               return;
-       btv->i2c_client.addr = addr >> 1;
-       tveeprom_read(&btv->i2c_client, eedata, 256);
-}
-
-static char *i2c_devs[128] = {
-       [ 0x1c >> 1 ] = "lgdt330x",
-       [ 0x30 >> 1 ] = "IR (hauppauge)",
-       [ 0x80 >> 1 ] = "msp34xx",
-       [ 0x86 >> 1 ] = "tda9887",
-       [ 0xa0 >> 1 ] = "eeprom",
-       [ 0xc0 >> 1 ] = "tuner (analog)",
-       [ 0xc2 >> 1 ] = "tuner (analog)",
-};
-
-static void do_i2c_scan(char *name, struct i2c_client *c)
-{
-       unsigned char buf;
-       int i,rc;
-
-       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
-               c->addr = i;
-               rc = i2c_master_recv(c,&buf,0);
-               if (rc < 0)
-                       continue;
-               pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
-                       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
-       }
-}
-
-/* init + register i2c adapter */
-int __devinit init_bttv_i2c(struct bttv *btv)
-{
-       strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
-
-       if (i2c_hw)
-               btv->use_i2c_hw = 1;
-       if (btv->use_i2c_hw) {
-               /* bt878 */
-               strlcpy(btv->c.i2c_adap.name, "bt878",
-                       sizeof(btv->c.i2c_adap.name));
-               btv->c.i2c_adap.algo = &bttv_algo;
-       } else {
-               /* bt848 */
-       /* Prevents usage of invalid delay values */
-               if (i2c_udelay<5)
-                       i2c_udelay=5;
-
-               strlcpy(btv->c.i2c_adap.name, "bttv",
-                       sizeof(btv->c.i2c_adap.name));
-               memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
-                      sizeof(bttv_i2c_algo_bit_template));
-               btv->i2c_algo.udelay = i2c_udelay;
-               btv->i2c_algo.data = btv;
-               btv->c.i2c_adap.algo_data = &btv->i2c_algo;
-       }
-       btv->c.i2c_adap.owner = THIS_MODULE;
-
-       btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
-       snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
-                "bt%d #%d [%s]", btv->id, btv->c.nr,
-                btv->use_i2c_hw ? "hw" : "sw");
-
-       i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev);
-       btv->i2c_client.adapter = &btv->c.i2c_adap;
-
-
-       if (btv->use_i2c_hw) {
-               btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
-       } else {
-               bttv_bit_setscl(btv,1);
-               bttv_bit_setsda(btv,1);
-               btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
-       }
-       if (0 == btv->i2c_rc && i2c_scan)
-               do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
-
-       return btv->i2c_rc;
-}
diff --git a/drivers/media/video/bt8xx/bttv-if.c b/drivers/media/video/bt8xx/bttv-if.c
deleted file mode 100644 (file)
index a6a540d..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-
-    bttv-if.c  --  old gpio interface to other kernel modules
-                  don't use in new code, will go away in 2.7
-                  have a look at bttv-gpio.c instead.
-
-    bttv - Bt848 frame grabber driver
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-                          & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#include "bttvp.h"
-
-EXPORT_SYMBOL(bttv_get_pcidev);
-EXPORT_SYMBOL(bttv_gpio_enable);
-EXPORT_SYMBOL(bttv_read_gpio);
-EXPORT_SYMBOL(bttv_write_gpio);
-
-/* ----------------------------------------------------------------------- */
-/* Exported functions - for other modules which want to access the         */
-/*                      gpio ports (IR for example)                        */
-/*                      see bttv.h for comments                            */
-
-struct pci_dev* bttv_get_pcidev(unsigned int card)
-{
-       if (card >= bttv_num)
-               return NULL;
-       if (!bttvs[card])
-               return NULL;
-
-       return bttvs[card]->c.pci;
-}
-
-
-int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
-{
-       struct bttv *btv;
-
-       if (card >= bttv_num) {
-               return -EINVAL;
-       }
-
-       btv = bttvs[card];
-       if (!btv)
-               return -ENODEV;
-
-       gpio_inout(mask,data);
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"extern enable");
-       return 0;
-}
-
-int bttv_read_gpio(unsigned int card, unsigned long *data)
-{
-       struct bttv *btv;
-
-       if (card >= bttv_num) {
-               return -EINVAL;
-       }
-
-       btv = bttvs[card];
-       if (!btv)
-               return -ENODEV;
-
-       if(btv->shutdown) {
-               return -ENODEV;
-       }
-
-/* prior setting BT848_GPIO_REG_INP is (probably) not needed
-   because we set direct input on init */
-       *data = gpio_read();
-       return 0;
-}
-
-int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
-{
-       struct bttv *btv;
-
-       if (card >= bttv_num) {
-               return -EINVAL;
-       }
-
-       btv = bttvs[card];
-       if (!btv)
-               return -ENODEV;
-
-/* prior setting BT848_GPIO_REG_INP is (probably) not needed
-   because direct input is set on init */
-       gpio_bits(mask,data);
-       if (bttv_gpio)
-               bttv_gpio_tracking(btv,"extern write");
-       return 0;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
deleted file mode 100644 (file)
index ef4c7cd..0000000
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- *
- * Copyright (c) 2003 Gerd Knorr
- * Copyright (c) 2003 Pavel Machek
- *
- * 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
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-
-#include "bttv.h"
-#include "bttvp.h"
-
-
-static int ir_debug;
-module_param(ir_debug, int, 0644);
-
-static int ir_rc5_remote_gap = 885;
-module_param(ir_rc5_remote_gap, int, 0644);
-
-#undef dprintk
-#define dprintk(fmt, ...)                      \
-do {                                           \
-       if (ir_debug >= 1)                      \
-               pr_info(fmt, ##__VA_ARGS__);    \
-} while (0)
-
-#define DEVNAME "bttv-input"
-
-#define MODULE_NAME "bttv"
-
-/* ---------------------------------------------------------------------- */
-
-static void ir_handle_key(struct bttv *btv)
-{
-       struct bttv_ir *ir = btv->remote;
-       u32 gpio,data;
-
-       /* read gpio value */
-       gpio = bttv_gpio_read(&btv->c);
-       if (ir->polling) {
-               if (ir->last_gpio == gpio)
-                       return;
-               ir->last_gpio = gpio;
-       }
-
-       /* extract data */
-       data = ir_extract_bits(gpio, ir->mask_keycode);
-       dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
-               gpio, data,
-               ir->polling               ? "poll"  : "irq",
-               (gpio & ir->mask_keydown) ? " down" : "",
-               (gpio & ir->mask_keyup)   ? " up"   : "");
-
-       if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
-           (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
-               rc_keydown_notimeout(ir->dev, data, 0);
-       } else {
-               /* HACK: Probably, ir->mask_keydown is missing
-                  for this board */
-               if (btv->c.type == BTTV_BOARD_WINFAST2000)
-                       rc_keydown_notimeout(ir->dev, data, 0);
-
-               rc_keyup(ir->dev);
-       }
-}
-
-static void ir_enltv_handle_key(struct bttv *btv)
-{
-       struct bttv_ir *ir = btv->remote;
-       u32 gpio, data, keyup;
-
-       /* read gpio value */
-       gpio = bttv_gpio_read(&btv->c);
-
-       /* extract data */
-       data = ir_extract_bits(gpio, ir->mask_keycode);
-
-       /* Check if it is keyup */
-       keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
-
-       if ((ir->last_gpio & 0x7f) != data) {
-               dprintk("gpio=0x%x code=%d | %s\n",
-                       gpio, data,
-                       (gpio & ir->mask_keyup) ? " up" : "up/down");
-
-               rc_keydown_notimeout(ir->dev, data, 0);
-               if (keyup)
-                       rc_keyup(ir->dev);
-       } else {
-               if ((ir->last_gpio & 1 << 31) == keyup)
-                       return;
-
-               dprintk("(cnt) gpio=0x%x code=%d | %s\n",
-                       gpio, data,
-                       (gpio & ir->mask_keyup) ? " up" : "down");
-
-               if (keyup)
-                       rc_keyup(ir->dev);
-               else
-                       rc_keydown_notimeout(ir->dev, data, 0);
-       }
-
-       ir->last_gpio = data | keyup;
-}
-
-static int bttv_rc5_irq(struct bttv *btv);
-
-void bttv_input_irq(struct bttv *btv)
-{
-       struct bttv_ir *ir = btv->remote;
-
-       if (ir->rc5_gpio)
-               bttv_rc5_irq(btv);
-       else if (!ir->polling)
-               ir_handle_key(btv);
-}
-
-static void bttv_input_timer(unsigned long data)
-{
-       struct bttv *btv = (struct bttv*)data;
-       struct bttv_ir *ir = btv->remote;
-
-       if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
-               ir_enltv_handle_key(btv);
-       else
-               ir_handle_key(btv);
-       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
-}
-
-/*
- * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying
- * on the rc-core way. As we need to be sure that both IRQ transitions are
- * properly triggered, Better to touch it only with this hardware for
- * testing.
- */
-
-#define RC5_START(x)   (((x) >> 12) & 3)
-#define RC5_TOGGLE(x)  (((x) >> 11) & 1)
-#define RC5_ADDR(x)    (((x) >> 6) & 31)
-#define RC5_INSTR(x)   ((x) & 63)
-
-/* decode raw bit pattern to RC5 code */
-static u32 bttv_rc5_decode(unsigned int code)
-{
-       unsigned int org_code = code;
-       unsigned int pair;
-       unsigned int rc5 = 0;
-       int i;
-
-       for (i = 0; i < 14; ++i) {
-               pair = code & 0x3;
-               code >>= 2;
-
-               rc5 <<= 1;
-               switch (pair) {
-               case 0:
-               case 2:
-                       break;
-               case 1:
-                       rc5 |= 1;
-               break;
-               case 3:
-                       dprintk("rc5_decode(%x) bad code\n",
-                               org_code);
-                       return 0;
-               }
-       }
-       dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
-               "instr=%x\n", rc5, org_code, RC5_START(rc5),
-               RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-       return rc5;
-}
-
-static void bttv_rc5_timer_end(unsigned long data)
-{
-       struct bttv_ir *ir = (struct bttv_ir *)data;
-       struct timeval tv;
-       u32 gap;
-       u32 rc5 = 0;
-
-       /* get time */
-       do_gettimeofday(&tv);
-
-       /* avoid overflow with gap >1s */
-       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-               gap = 200000;
-       } else {
-               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-                   tv.tv_usec - ir->base_time.tv_usec;
-       }
-
-       /* signal we're ready to start a new code */
-       ir->active = false;
-
-       /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
-       if (gap < 28000) {
-               dprintk("spurious timer_end\n");
-               return;
-       }
-
-       if (ir->last_bit < 20) {
-               /* ignore spurious codes (caused by light/other remotes) */
-               dprintk("short code: %x\n", ir->code);
-       } else {
-               ir->code = (ir->code << ir->shift_by) | 1;
-               rc5 = bttv_rc5_decode(ir->code);
-
-               /* two start bits? */
-               if (RC5_START(rc5) != ir->start) {
-                       pr_info(DEVNAME ":"
-                              " rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-                       /* right address? */
-               } else if (RC5_ADDR(rc5) == ir->addr) {
-                       u32 toggle = RC5_TOGGLE(rc5);
-                       u32 instr = RC5_INSTR(rc5);
-
-                       /* Good code */
-                       rc_keydown(ir->dev, instr, toggle);
-                       dprintk("instruction %x, toggle %x\n",
-                               instr, toggle);
-               }
-       }
-}
-
-static int bttv_rc5_irq(struct bttv *btv)
-{
-       struct bttv_ir *ir = btv->remote;
-       struct timeval tv;
-       u32 gpio;
-       u32 gap;
-       unsigned long current_jiffies;
-
-       /* read gpio port */
-       gpio = bttv_gpio_read(&btv->c);
-
-       /* get time of bit */
-       current_jiffies = jiffies;
-       do_gettimeofday(&tv);
-
-       /* avoid overflow with gap >1s */
-       if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-               gap = 200000;
-       } else {
-               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-                   tv.tv_usec - ir->base_time.tv_usec;
-       }
-
-       dprintk("RC5 IRQ: gap %d us for %s\n",
-               gap, (gpio & 0x20) ? "mark" : "space");
-
-       /* remote IRQ? */
-       if (!(gpio & 0x20))
-               return 0;
-
-       /* active code => add bit */
-       if (ir->active) {
-               /* only if in the code (otherwise spurious IRQ or timer
-                  late) */
-               if (ir->last_bit < 28) {
-                       ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
-                           ir_rc5_remote_gap;
-                       ir->code |= 1 << ir->last_bit;
-               }
-               /* starting new code */
-       } else {
-               ir->active = true;
-               ir->code = 0;
-               ir->base_time = tv;
-               ir->last_bit = 0;
-
-               mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30));
-       }
-
-       /* toggle GPIO pin 4 to reset the irq */
-       bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
-       bttv_gpio_write(&btv->c, gpio | (1 << 4));
-       return 1;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
-{
-       if (ir->polling) {
-               setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
-               ir->timer.expires  = jiffies + msecs_to_jiffies(1000);
-               add_timer(&ir->timer);
-       } else if (ir->rc5_gpio) {
-               /* set timer_end for code completion */
-               setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
-               ir->shift_by = 1;
-               ir->start = 3;
-               ir->addr = 0x0;
-               ir->rc5_remote_gap = ir_rc5_remote_gap;
-       }
-}
-
-static void bttv_ir_stop(struct bttv *btv)
-{
-       if (btv->remote->polling)
-               del_timer_sync(&btv->remote->timer);
-
-       if (btv->remote->rc5_gpio) {
-               u32 gpio;
-
-               del_timer_sync(&btv->remote->timer);
-
-               gpio = bttv_gpio_read(&btv->c);
-               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
-       }
-}
-
-/*
- * Get_key functions used by I2C remotes
- */
-
-static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char b;
-
-       /* poll IR chip */
-       if (1 != i2c_master_recv(ir->c, &b, 1)) {
-               dprintk("read error\n");
-               return -EIO;
-       }
-
-       /* ignore 0xaa */
-       if (b==0xaa)
-               return 0;
-       dprintk("key %02x\n", b);
-
-       /*
-        * NOTE:
-        * lirc_i2c maps the pv951 code as:
-        *      addr = 0x61D6
-        *      cmd = bit_reverse (b)
-        * So, it seems that this device uses NEC extended
-        * I decided to not fix the table, due to two reasons:
-        *      1) Without the actual device, this is only a guess;
-        *      2) As the addr is not reported via I2C, nor can be changed,
-        *         the device is bound to the vendor-provided RC.
-        */
-
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-/* Instantiate the I2C IR receiver device, if present */
-void __devinit init_bttv_i2c_ir(struct bttv *btv)
-{
-       const unsigned short addr_list[] = {
-               0x1a, 0x18, 0x64, 0x30, 0x71,
-               I2C_CLIENT_END
-       };
-       struct i2c_board_info info;
-
-       if (0 != btv->i2c_rc)
-               return;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       memset(&btv->init_data, 0, sizeof(btv->init_data));
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-
-       switch (btv->c.type) {
-       case BTTV_BOARD_PV951:
-               btv->init_data.name = "PV951";
-               btv->init_data.get_key = get_key_pv951;
-               btv->init_data.ir_codes = RC_MAP_PV951;
-               info.addr = 0x4b;
-               break;
-       default:
-               /*
-                * The external IR receiver is at i2c address 0x34 (0x35 for
-                * reads).  Future Hauppauge cards will have an internal
-                * receiver at 0x30 (0x31 for reads).  In theory, both can be
-                * fitted, and Hauppauge suggest an external overrides an
-                * internal.
-                * That's why we probe 0x1a (~0x34) first. CB
-                */
-
-               i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
-               return;
-       }
-
-       if (btv->init_data.name)
-               info.platform_data = &btv->init_data;
-       i2c_new_device(&btv->c.i2c_adap, &info);
-
-       return;
-}
-
-int __devexit fini_bttv_i2c(struct bttv *btv)
-{
-       if (0 != btv->i2c_rc)
-               return 0;
-
-       return i2c_del_adapter(&btv->c.i2c_adap);
-}
-
-int bttv_input_init(struct bttv *btv)
-{
-       struct bttv_ir *ir;
-       char *ir_codes = NULL;
-       struct rc_dev *rc;
-       int err = -ENOMEM;
-
-       if (!btv->has_remote)
-               return -ENODEV;
-
-       ir = kzalloc(sizeof(*ir),GFP_KERNEL);
-       rc = rc_allocate_device();
-       if (!ir || !rc)
-               goto err_out_free;
-
-       /* detect & configure */
-       switch (btv->c.type) {
-       case BTTV_BOARD_AVERMEDIA:
-       case BTTV_BOARD_AVPHONE98:
-       case BTTV_BOARD_AVERMEDIA98:
-               ir_codes         = RC_MAP_AVERMEDIA;
-               ir->mask_keycode = 0xf88000;
-               ir->mask_keydown = 0x010000;
-               ir->polling      = 50; // ms
-               break;
-
-       case BTTV_BOARD_AVDVBT_761:
-       case BTTV_BOARD_AVDVBT_771:
-               ir_codes         = RC_MAP_AVERMEDIA_DVBT;
-               ir->mask_keycode = 0x0f00c0;
-               ir->mask_keydown = 0x000020;
-               ir->polling      = 50; // ms
-               break;
-
-       case BTTV_BOARD_PXELVWPLTVPAK:
-               ir_codes         = RC_MAP_PIXELVIEW;
-               ir->mask_keycode = 0x003e00;
-               ir->mask_keyup   = 0x010000;
-               ir->polling      = 50; // ms
-               break;
-       case BTTV_BOARD_PV_M4900:
-       case BTTV_BOARD_PV_BT878P_9B:
-       case BTTV_BOARD_PV_BT878P_PLUS:
-               ir_codes         = RC_MAP_PIXELVIEW;
-               ir->mask_keycode = 0x001f00;
-               ir->mask_keyup   = 0x008000;
-               ir->polling      = 50; // ms
-               break;
-
-       case BTTV_BOARD_WINFAST2000:
-               ir_codes         = RC_MAP_WINFAST;
-               ir->mask_keycode = 0x1f8;
-               break;
-       case BTTV_BOARD_MAGICTVIEW061:
-       case BTTV_BOARD_MAGICTVIEW063:
-               ir_codes         = RC_MAP_WINFAST;
-               ir->mask_keycode = 0x0008e000;
-               ir->mask_keydown = 0x00200000;
-               break;
-       case BTTV_BOARD_APAC_VIEWCOMP:
-               ir_codes         = RC_MAP_APAC_VIEWCOMP;
-               ir->mask_keycode = 0x001f00;
-               ir->mask_keyup   = 0x008000;
-               ir->polling      = 50; // ms
-               break;
-       case BTTV_BOARD_ASKEY_CPH03X:
-       case BTTV_BOARD_CONCEPTRONIC_CTVFMI2:
-       case BTTV_BOARD_CONTVFMI:
-               ir_codes         = RC_MAP_PIXELVIEW;
-               ir->mask_keycode = 0x001F00;
-               ir->mask_keyup   = 0x006000;
-               ir->polling      = 50; // ms
-               break;
-       case BTTV_BOARD_NEBULA_DIGITV:
-               ir_codes = RC_MAP_NEBULA;
-               ir->rc5_gpio = true;
-               break;
-       case BTTV_BOARD_MACHTV_MAGICTV:
-               ir_codes         = RC_MAP_APAC_VIEWCOMP;
-               ir->mask_keycode = 0x001F00;
-               ir->mask_keyup   = 0x004000;
-               ir->polling      = 50; /* ms */
-               break;
-       case BTTV_BOARD_KOZUMI_KTV_01C:
-               ir_codes         = RC_MAP_PCTV_SEDNA;
-               ir->mask_keycode = 0x001f00;
-               ir->mask_keyup   = 0x006000;
-               ir->polling      = 50; /* ms */
-               break;
-       case BTTV_BOARD_ENLTV_FM_2:
-               ir_codes         = RC_MAP_ENCORE_ENLTV2;
-               ir->mask_keycode = 0x00fd00;
-               ir->mask_keyup   = 0x000080;
-               ir->polling      = 1; /* ms */
-               ir->last_gpio    = ir_extract_bits(bttv_gpio_read(&btv->c),
-                                                  ir->mask_keycode);
-               break;
-       }
-       if (NULL == ir_codes) {
-               dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
-               err = -ENODEV;
-               goto err_out_free;
-       }
-
-       if (ir->rc5_gpio) {
-               u32 gpio;
-               /* enable remote irq */
-               bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
-               gpio = bttv_gpio_read(&btv->c);
-               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
-               bttv_gpio_write(&btv->c, gpio | (1 << 4));
-       } else {
-               /* init hardware-specific stuff */
-               bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
-       }
-
-       /* init input device */
-       ir->dev = rc;
-
-       snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
-                btv->c.type);
-       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
-                pci_name(btv->c.pci));
-
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_PCI;
-       rc->input_id.version = 1;
-       if (btv->c.pci->subsystem_vendor) {
-               rc->input_id.vendor  = btv->c.pci->subsystem_vendor;
-               rc->input_id.product = btv->c.pci->subsystem_device;
-       } else {
-               rc->input_id.vendor  = btv->c.pci->vendor;
-               rc->input_id.product = btv->c.pci->device;
-       }
-       rc->dev.parent = &btv->c.pci->dev;
-       rc->map_name = ir_codes;
-       rc->driver_name = MODULE_NAME;
-
-       btv->remote = ir;
-       bttv_ir_start(btv, ir);
-
-       /* all done */
-       err = rc_register_device(rc);
-       if (err)
-               goto err_out_stop;
-
-       return 0;
-
- err_out_stop:
-       bttv_ir_stop(btv);
-       btv->remote = NULL;
- err_out_free:
-       rc_free_device(rc);
-       kfree(ir);
-       return err;
-}
-
-void bttv_input_fini(struct bttv *btv)
-{
-       if (btv->remote == NULL)
-               return;
-
-       bttv_ir_stop(btv);
-       rc_unregister_device(btv->remote->dev);
-       kfree(btv->remote);
-       btv->remote = NULL;
-}
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
deleted file mode 100644 (file)
index 82cc47d..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
-
-    bttv-risc.c  --  interfaces to other kernel modules
-
-    bttv risc code handling
-       - memory management
-       - generation
-
-    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <media/v4l2-ioctl.h>
-
-#include "bttvp.h"
-
-#define VCR_HACK_LINES 4
-
-/* ---------------------------------------------------------- */
-/* risc code generators                                       */
-
-int
-bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
-                struct scatterlist *sglist,
-                unsigned int offset, unsigned int bpl,
-                unsigned int padding, unsigned int skip_lines,
-                unsigned int store_lines)
-{
-       u32 instructions,line,todo;
-       struct scatterlist *sg;
-       __le32 *rp;
-       int rc;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + sync + jump (all 2 dwords).  padding
-          can cause next bpl to start close to a page border.  First DMA
-          region may be smaller than PAGE_SIZE */
-       instructions  = skip_lines * 4;
-       instructions += (1 + ((bpl + padding) * store_lines)
-                        / PAGE_SIZE + store_lines) * 8;
-       instructions += 2 * 8;
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
-               return rc;
-
-       /* sync instruction */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
-       *(rp++) = cpu_to_le32(0);
-
-       while (skip_lines-- > 0) {
-               *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
-                                     BT848_RISC_EOL | bpl);
-       }
-
-       /* scan lines */
-       sg = sglist;
-       for (line = 0; line < store_lines; line++) {
-               if ((btv->opt_vcr_hack) &&
-                   (line >= (store_lines - VCR_HACK_LINES)))
-                       continue;
-               while (offset && offset >= sg_dma_len(sg)) {
-                       offset -= sg_dma_len(sg);
-                       sg++;
-               }
-               if (bpl <= sg_dma_len(sg)-offset) {
-                       /* fits into current chunk */
-                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
-                                           BT848_RISC_EOL|bpl);
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                       offset+=bpl;
-               } else {
-                       /* scanline needs to be splitted */
-                       todo = bpl;
-                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
-                                           (sg_dma_len(sg)-offset));
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                       todo -= (sg_dma_len(sg)-offset);
-                       offset = 0;
-                       sg++;
-                       while (todo > sg_dma_len(sg)) {
-                               *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
-                                                   sg_dma_len(sg));
-                               *(rp++)=cpu_to_le32(sg_dma_address(sg));
-                               todo -= sg_dma_len(sg);
-                               sg++;
-                       }
-                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
-                                           todo);
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg));
-                       offset += todo;
-               }
-               offset += padding;
-       }
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-
-static int
-bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
-                struct scatterlist *sglist,
-                unsigned int yoffset,  unsigned int ybpl,
-                unsigned int ypadding, unsigned int ylines,
-                unsigned int uoffset,  unsigned int voffset,
-                unsigned int hshift,   unsigned int vshift,
-                unsigned int cpadding)
-{
-       unsigned int instructions,line,todo,ylen,chroma;
-       __le32 *rp;
-       u32 ri;
-       struct scatterlist *ysg;
-       struct scatterlist *usg;
-       struct scatterlist *vsg;
-       int topfield = (0 == yoffset);
-       int rc;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line (5 dwords)
-          plus sync + jump (2 dwords) */
-       instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
-                        / PAGE_SIZE) + ylines;
-       instructions += 2;
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
-               return rc;
-
-       /* sync instruction */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
-       *(rp++) = cpu_to_le32(0);
-
-       /* scan lines */
-       ysg = sglist;
-       usg = sglist;
-       vsg = sglist;
-       for (line = 0; line < ylines; line++) {
-               if ((btv->opt_vcr_hack) &&
-                   (line >= (ylines - VCR_HACK_LINES)))
-                       continue;
-               switch (vshift) {
-               case 0:
-                       chroma = 1;
-                       break;
-               case 1:
-                       if (topfield)
-                               chroma = ((line & 1) == 0);
-                       else
-                               chroma = ((line & 1) == 1);
-                       break;
-               case 2:
-                       if (topfield)
-                               chroma = ((line & 3) == 0);
-                       else
-                               chroma = ((line & 3) == 2);
-                       break;
-               default:
-                       chroma = 0;
-                       break;
-               }
-
-               for (todo = ybpl; todo > 0; todo -= ylen) {
-                       /* go to next sg entry if needed */
-                       while (yoffset && yoffset >= sg_dma_len(ysg)) {
-                               yoffset -= sg_dma_len(ysg);
-                               ysg++;
-                       }
-                       while (uoffset && uoffset >= sg_dma_len(usg)) {
-                               uoffset -= sg_dma_len(usg);
-                               usg++;
-                       }
-                       while (voffset && voffset >= sg_dma_len(vsg)) {
-                               voffset -= sg_dma_len(vsg);
-                               vsg++;
-                       }
-
-                       /* calculate max number of bytes we can write */
-                       ylen = todo;
-                       if (yoffset + ylen > sg_dma_len(ysg))
-                               ylen = sg_dma_len(ysg) - yoffset;
-                       if (chroma) {
-                               if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
-                                       ylen = (sg_dma_len(usg) - uoffset) << hshift;
-                               if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
-                                       ylen = (sg_dma_len(vsg) - voffset) << hshift;
-                               ri = BT848_RISC_WRITE123;
-                       } else {
-                               ri = BT848_RISC_WRITE1S23;
-                       }
-                       if (ybpl == todo)
-                               ri |= BT848_RISC_SOL;
-                       if (ylen == todo)
-                               ri |= BT848_RISC_EOL;
-
-                       /* write risc instruction */
-                       *(rp++)=cpu_to_le32(ri | ylen);
-                       *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
-                                           (ylen >> hshift));
-                       *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
-                       yoffset += ylen;
-                       if (chroma) {
-                               *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
-                               uoffset += ylen >> hshift;
-                               *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
-                               voffset += ylen >> hshift;
-                       }
-               }
-               yoffset += ypadding;
-               if (chroma) {
-                       uoffset += cpadding;
-                       voffset += cpadding;
-               }
-       }
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-
-static int
-bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
-                 const struct bttv_format *fmt, struct bttv_overlay *ov,
-                 int skip_even, int skip_odd)
-{
-       int dwords, rc, line, maxy, start, end;
-       unsigned skip, nskips;
-       struct btcx_skiplist *skips;
-       __le32 *rp;
-       u32 ri,ra;
-       u32 addr;
-
-       /* skip list for window clipping */
-       if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
-               return -ENOMEM;
-
-       /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
-          + sync + jump (all 2 dwords) */
-       dwords  = (3 * ov->nclips + 2) *
-               ((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
-       dwords += 4;
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
-               kfree(skips);
-               return rc;
-       }
-
-       /* sync instruction */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
-       *(rp++) = cpu_to_le32(0);
-
-       addr  = (unsigned long)btv->fbuf.base;
-       addr += btv->fbuf.fmt.bytesperline * ov->w.top;
-       addr += (fmt->depth >> 3)          * ov->w.left;
-
-       /* scan lines */
-       for (maxy = -1, line = 0; line < ov->w.height;
-            line++, addr += btv->fbuf.fmt.bytesperline) {
-               if ((btv->opt_vcr_hack) &&
-                    (line >= (ov->w.height - VCR_HACK_LINES)))
-                       continue;
-               if ((line%2) == 0  &&  skip_even)
-                       continue;
-               if ((line%2) == 1  &&  skip_odd)
-                       continue;
-
-               /* calculate clipping */
-               if (line > maxy)
-                       btcx_calc_skips(line, ov->w.width, &maxy,
-                                       skips, &nskips, ov->clips, ov->nclips);
-
-               /* write out risc code */
-               for (start = 0, skip = 0; start < ov->w.width; start = end) {
-                       if (skip >= nskips) {
-                               ri  = BT848_RISC_WRITE;
-                               end = ov->w.width;
-                       } else if (start < skips[skip].start) {
-                               ri  = BT848_RISC_WRITE;
-                               end = skips[skip].start;
-                       } else {
-                               ri  = BT848_RISC_SKIP;
-                               end = skips[skip].end;
-                               skip++;
-                       }
-                       if (BT848_RISC_WRITE == ri)
-                               ra = addr + (fmt->depth>>3)*start;
-                       else
-                               ra = 0;
-
-                       if (0 == start)
-                               ri |= BT848_RISC_SOL;
-                       if (ov->w.width == end)
-                               ri |= BT848_RISC_EOL;
-                       ri |= (fmt->depth>>3) * (end-start);
-
-                       *(rp++)=cpu_to_le32(ri);
-                       if (0 != ra)
-                               *(rp++)=cpu_to_le32(ra);
-               }
-       }
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       kfree(skips);
-       return 0;
-}
-
-/* ---------------------------------------------------------- */
-
-static void
-bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
-                 int width, int height, int interleaved,
-                 const struct bttv_tvnorm *tvnorm)
-{
-       u32 xsf, sr;
-       int vdelay;
-
-       int swidth       = tvnorm->swidth;
-       int totalwidth   = tvnorm->totalwidth;
-       int scaledtwidth = tvnorm->scaledtwidth;
-
-       if (btv->input == btv->dig) {
-               swidth       = 720;
-               totalwidth   = 858;
-               scaledtwidth = 858;
-       }
-
-       vdelay = tvnorm->vdelay;
-
-       xsf = (width*scaledtwidth)/swidth;
-       geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
-       geo->hdelay =  tvnorm->hdelayx1;
-       geo->hdelay =  (geo->hdelay*width)/swidth;
-       geo->hdelay &= 0x3fe;
-       sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
-       geo->vscale =  (0x10000UL-sr) & 0x1fff;
-       geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
-               ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
-       geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
-       geo->vdelay  =  vdelay;
-       geo->width   =  width;
-       geo->sheight =  tvnorm->sheight;
-       geo->vtotal  =  tvnorm->vtotal;
-
-       if (btv->opt_combfilter) {
-               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
-               geo->comb = (width < 769) ? 1 : 0;
-       } else {
-               geo->vtc  = 0;
-               geo->comb = 0;
-       }
-}
-
-static void
-bttv_calc_geo          (struct bttv *                  btv,
-                        struct bttv_geometry *         geo,
-                        unsigned int                   width,
-                        unsigned int                   height,
-                        int                            both_fields,
-                        const struct bttv_tvnorm *     tvnorm,
-                        const struct v4l2_rect *       crop)
-{
-       unsigned int c_width;
-       unsigned int c_height;
-       u32 sr;
-
-       if ((crop->left == tvnorm->cropcap.defrect.left
-            && crop->top == tvnorm->cropcap.defrect.top
-            && crop->width == tvnorm->cropcap.defrect.width
-            && crop->height == tvnorm->cropcap.defrect.height
-            && width <= tvnorm->swidth /* see PAL-Nc et al */)
-           || btv->input == btv->dig) {
-               bttv_calc_geo_old(btv, geo, width, height,
-                                 both_fields, tvnorm);
-               return;
-       }
-
-       /* For bug compatibility the image size checks permit scale
-          factors > 16. See bttv_crop_calc_limits(). */
-       c_width = min((unsigned int) crop->width, width * 16);
-       c_height = min((unsigned int) crop->height, height * 16);
-
-       geo->width = width;
-       geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
-       /* Even to store Cb first, odd for Cr. */
-       geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
-
-       geo->sheight = c_height;
-       geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
-       sr = c_height >> !both_fields;
-       sr = (sr * 512U + (height >> 1)) / height - 512;
-       geo->vscale = (0x10000UL - sr) & 0x1fff;
-       geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
-       geo->vtotal = tvnorm->vtotal;
-
-       geo->crop = (((geo->width   >> 8) & 0x03) |
-                    ((geo->hdelay  >> 6) & 0x0c) |
-                    ((geo->sheight >> 4) & 0x30) |
-                    ((geo->vdelay  >> 2) & 0xc0));
-
-       if (btv->opt_combfilter) {
-               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
-               geo->comb = (width < 769) ? 1 : 0;
-       } else {
-               geo->vtc  = 0;
-               geo->comb = 0;
-       }
-}
-
-static void
-bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
-{
-       int off = odd ? 0x80 : 0x00;
-
-       if (geo->comb)
-               btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
-       else
-               btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
-
-       btwrite(geo->vtc,             BT848_E_VTC+off);
-       btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
-       btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
-       btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
-       btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
-       btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
-       btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
-       btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
-       btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
-       btwrite(geo->crop,            BT848_E_CROP+off);
-       btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
-       btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
-}
-
-/* ---------------------------------------------------------- */
-/* risc group / risc main loop / dma management               */
-
-void
-bttv_set_dma(struct bttv *btv, int override)
-{
-       unsigned long cmd;
-       int capctl;
-
-       btv->cap_ctl = 0;
-       if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
-       if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
-       if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
-
-       capctl  = 0;
-       capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
-       capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
-       capctl |= override;
-
-       d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
-                btv->c.nr,capctl,btv->loop_irq,
-                btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
-                btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
-                btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
-                btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
-
-       cmd = BT848_RISC_JUMP;
-       if (btv->loop_irq) {
-               cmd |= BT848_RISC_IRQ;
-               cmd |= (btv->loop_irq  & 0x0f) << 16;
-               cmd |= (~btv->loop_irq & 0x0f) << 20;
-       }
-       if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
-               mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
-       } else {
-               del_timer(&btv->timeout);
-       }
-       btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
-
-       btaor(capctl, ~0x0f, BT848_CAP_CTL);
-       if (capctl) {
-               if (btv->dma_on)
-                       return;
-               btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
-               btor(3, BT848_GPIO_DMA_CTL);
-               btv->dma_on = 1;
-       } else {
-               if (!btv->dma_on)
-                       return;
-               btand(~3, BT848_GPIO_DMA_CTL);
-               btv->dma_on = 0;
-       }
-       return;
-}
-
-int
-bttv_risc_init_main(struct bttv *btv)
-{
-       int rc;
-
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
-               return rc;
-       dprintk("%d: risc main @ %08llx\n",
-               btv->c.nr, (unsigned long long)btv->main.dma);
-
-       btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
-                                      BT848_FIFO_STATUS_VRE);
-       btv->main.cpu[1] = cpu_to_le32(0);
-       btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
-
-       /* top field */
-       btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
-       btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
-
-       btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
-                                      BT848_FIFO_STATUS_VRO);
-       btv->main.cpu[9] = cpu_to_le32(0);
-
-       /* bottom field */
-       btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
-       btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
-
-       /* jump back to top field */
-       btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
-       btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
-
-       return 0;
-}
-
-int
-bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
-              int irqflags)
-{
-       unsigned long cmd;
-       unsigned long next = btv->main.dma + ((slot+2) << 2);
-
-       if (NULL == risc) {
-               d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
-               btv->main.cpu[slot+1] = cpu_to_le32(next);
-       } else {
-               d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
-                        btv->c.nr, risc, slot,
-                        (unsigned long long)risc->dma, irqflags);
-               cmd = BT848_RISC_JUMP;
-               if (irqflags) {
-                       cmd |= BT848_RISC_IRQ;
-                       cmd |= (irqflags  & 0x0f) << 16;
-                       cmd |= (~irqflags & 0x0f) << 20;
-               }
-               risc->jmp[0] = cpu_to_le32(cmd);
-               risc->jmp[1] = cpu_to_le32(next);
-               btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
-       }
-       return 0;
-}
-
-void
-bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
-{
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-       BUG_ON(in_interrupt());
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       btcx_riscmem_free(btv->c.pci,&buf->bottom);
-       btcx_riscmem_free(btv->c.pci,&buf->top);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-int
-bttv_buffer_activate_vbi(struct bttv *btv,
-                        struct bttv_buffer *vbi)
-{
-       struct btcx_riscmem *top;
-       struct btcx_riscmem *bottom;
-       int top_irq_flags;
-       int bottom_irq_flags;
-
-       top = NULL;
-       bottom = NULL;
-       top_irq_flags = 0;
-       bottom_irq_flags = 0;
-
-       if (vbi) {
-               unsigned int crop, vdelay;
-
-               vbi->vb.state = VIDEOBUF_ACTIVE;
-               list_del(&vbi->vb.queue);
-
-               /* VDELAY is start of video, end of VBI capturing. */
-               crop = btread(BT848_E_CROP);
-               vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
-
-               if (vbi->geo.vdelay > vdelay) {
-                       vdelay = vbi->geo.vdelay & 0xfe;
-                       crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
-
-                       btwrite(vdelay, BT848_E_VDELAY_LO);
-                       btwrite(crop,   BT848_E_CROP);
-                       btwrite(vdelay, BT848_O_VDELAY_LO);
-                       btwrite(crop,   BT848_O_CROP);
-               }
-
-               if (vbi->vbi_count[0] > 0) {
-                       top = &vbi->top;
-                       top_irq_flags = 4;
-               }
-
-               if (vbi->vbi_count[1] > 0) {
-                       top_irq_flags = 0;
-                       bottom = &vbi->bottom;
-                       bottom_irq_flags = 4;
-               }
-       }
-
-       bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
-       bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
-
-       return 0;
-}
-
-int
-bttv_buffer_activate_video(struct bttv *btv,
-                          struct bttv_buffer_set *set)
-{
-       /* video capture */
-       if (NULL != set->top  &&  NULL != set->bottom) {
-               if (set->top == set->bottom) {
-                       set->top->vb.state    = VIDEOBUF_ACTIVE;
-                       if (set->top->vb.queue.next)
-                               list_del(&set->top->vb.queue);
-               } else {
-                       set->top->vb.state    = VIDEOBUF_ACTIVE;
-                       set->bottom->vb.state = VIDEOBUF_ACTIVE;
-                       if (set->top->vb.queue.next)
-                               list_del(&set->top->vb.queue);
-                       if (set->bottom->vb.queue.next)
-                               list_del(&set->bottom->vb.queue);
-               }
-               bttv_apply_geo(btv, &set->top->geo, 1);
-               bttv_apply_geo(btv, &set->bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
-                              set->top_irq);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
-                              set->frame_irq);
-               btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
-                     ~0xff, BT848_COLOR_FMT);
-               btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
-                     ~0x0f, BT848_COLOR_CTL);
-       } else if (NULL != set->top) {
-               set->top->vb.state  = VIDEOBUF_ACTIVE;
-               if (set->top->vb.queue.next)
-                       list_del(&set->top->vb.queue);
-               bttv_apply_geo(btv, &set->top->geo,1);
-               bttv_apply_geo(btv, &set->top->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
-                              set->frame_irq);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
-               btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
-               btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
-       } else if (NULL != set->bottom) {
-               set->bottom->vb.state = VIDEOBUF_ACTIVE;
-               if (set->bottom->vb.queue.next)
-                       list_del(&set->bottom->vb.queue);
-               bttv_apply_geo(btv, &set->bottom->geo,1);
-               bttv_apply_geo(btv, &set->bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
-                              set->frame_irq);
-               btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
-               btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
-       } else {
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
-       }
-       return 0;
-}
-
-/* ---------------------------------------------------------- */
-
-/* calculate geometry, build risc code */
-int
-bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
-{
-       const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-       dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
-               btv->c.nr, v4l2_field_names[buf->vb.field],
-               buf->fmt->name, buf->vb.width, buf->vb.height);
-
-       /* packed pixel modes */
-       if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
-               int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
-               int bpf = bpl * (buf->vb.height >> 1);
-
-               bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
-                             V4L2_FIELD_HAS_BOTH(buf->vb.field),
-                             tvnorm,&buf->crop);
-
-               switch (buf->vb.field) {
-               case V4L2_FIELD_TOP:
-                       bttv_risc_packed(btv,&buf->top,dma->sglist,
-                                        /* offset */ 0,bpl,
-                                        /* padding */ 0,/* skip_lines */ 0,
-                                        buf->vb.height);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
-                                        0,bpl,0,0,buf->vb.height);
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       bttv_risc_packed(btv,&buf->top,dma->sglist,
-                                        0,bpl,bpl,0,buf->vb.height >> 1);
-                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
-                                        bpl,bpl,bpl,0,buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_TB:
-                       bttv_risc_packed(btv,&buf->top,dma->sglist,
-                                        0,bpl,0,0,buf->vb.height >> 1);
-                       bttv_risc_packed(btv,&buf->bottom,dma->sglist,
-                                        bpf,bpl,0,0,buf->vb.height >> 1);
-                       break;
-               default:
-                       BUG();
-               }
-       }
-
-       /* planar modes */
-       if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
-               int uoffset, voffset;
-               int ypadding, cpadding, lines;
-
-               /* calculate chroma offsets */
-               uoffset = buf->vb.width * buf->vb.height;
-               voffset = buf->vb.width * buf->vb.height;
-               if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
-                       /* Y-Cr-Cb plane order */
-                       uoffset >>= buf->fmt->hshift;
-                       uoffset >>= buf->fmt->vshift;
-                       uoffset  += voffset;
-               } else {
-                       /* Y-Cb-Cr plane order */
-                       voffset >>= buf->fmt->hshift;
-                       voffset >>= buf->fmt->vshift;
-                       voffset  += uoffset;
-               }
-
-               switch (buf->vb.field) {
-               case V4L2_FIELD_TOP:
-                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,/* both_fields */ 0,
-                                     tvnorm,&buf->crop);
-                       bttv_risc_planar(btv, &buf->top, dma->sglist,
-                                        0,buf->vb.width,0,buf->vb.height,
-                                        uoffset,voffset,buf->fmt->hshift,
-                                        buf->fmt->vshift,0);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,0,
-                                     tvnorm,&buf->crop);
-                       bttv_risc_planar(btv, &buf->bottom, dma->sglist,
-                                        0,buf->vb.width,0,buf->vb.height,
-                                        uoffset,voffset,buf->fmt->hshift,
-                                        buf->fmt->vshift,0);
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,1,
-                                     tvnorm,&buf->crop);
-                       lines    = buf->vb.height >> 1;
-                       ypadding = buf->vb.width;
-                       cpadding = buf->vb.width >> buf->fmt->hshift;
-                       bttv_risc_planar(btv,&buf->top,
-                                        dma->sglist,
-                                        0,buf->vb.width,ypadding,lines,
-                                        uoffset,voffset,
-                                        buf->fmt->hshift,
-                                        buf->fmt->vshift,
-                                        cpadding);
-                       bttv_risc_planar(btv,&buf->bottom,
-                                        dma->sglist,
-                                        ypadding,buf->vb.width,ypadding,lines,
-                                        uoffset+cpadding,
-                                        voffset+cpadding,
-                                        buf->fmt->hshift,
-                                        buf->fmt->vshift,
-                                        cpadding);
-                       break;
-               case V4L2_FIELD_SEQ_TB:
-                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
-                                     buf->vb.height,1,
-                                     tvnorm,&buf->crop);
-                       lines    = buf->vb.height >> 1;
-                       ypadding = buf->vb.width;
-                       cpadding = buf->vb.width >> buf->fmt->hshift;
-                       bttv_risc_planar(btv,&buf->top,
-                                        dma->sglist,
-                                        0,buf->vb.width,0,lines,
-                                        uoffset >> 1,
-                                        voffset >> 1,
-                                        buf->fmt->hshift,
-                                        buf->fmt->vshift,
-                                        0);
-                       bttv_risc_planar(btv,&buf->bottom,
-                                        dma->sglist,
-                                        lines * ypadding,buf->vb.width,0,lines,
-                                        lines * ypadding + (uoffset >> 1),
-                                        lines * ypadding + (voffset >> 1),
-                                        buf->fmt->hshift,
-                                        buf->fmt->vshift,
-                                        0);
-                       break;
-               default:
-                       BUG();
-               }
-       }
-
-       /* raw data */
-       if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
-               /* build risc code */
-               buf->vb.field = V4L2_FIELD_SEQ_TB;
-               bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
-                             1,tvnorm,&buf->crop);
-               bttv_risc_packed(btv, &buf->top,  dma->sglist,
-                                /* offset */ 0, RAW_BPL, /* padding */ 0,
-                                /* skip_lines */ 0, RAW_LINES);
-               bttv_risc_packed(btv, &buf->bottom, dma->sglist,
-                                buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
-       }
-
-       /* copy format info */
-       buf->btformat = buf->fmt->btformat;
-       buf->btswap   = buf->fmt->btswap;
-       return 0;
-}
-
-/* ---------------------------------------------------------- */
-
-/* calculate geometry, build risc code */
-int
-bttv_overlay_risc(struct bttv *btv,
-                 struct bttv_overlay *ov,
-                 const struct bttv_format *fmt,
-                 struct bttv_buffer *buf)
-{
-       /* check interleave, bottom+top fields */
-       dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
-               btv->c.nr, v4l2_field_names[buf->vb.field],
-               fmt->name, ov->w.width, ov->w.height);
-
-       /* calculate geometry */
-       bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
-                     V4L2_FIELD_HAS_BOTH(ov->field),
-                     &bttv_tvnorms[ov->tvnorm],&buf->crop);
-
-       /* build risc code */
-       switch (ov->field) {
-       case V4L2_FIELD_TOP:
-               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
-               break;
-       case V4L2_FIELD_BOTTOM:
-               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
-               break;
-       case V4L2_FIELD_INTERLACED:
-               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
-               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
-               break;
-       default:
-               BUG();
-       }
-
-       /* copy format info */
-       buf->btformat = fmt->btformat;
-       buf->btswap   = fmt->btswap;
-       buf->vb.field = ov->field;
-       return 0;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
deleted file mode 100644 (file)
index b433267..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
-
-    bttv - Bt848 frame grabber driver
-    vbi interface
-
-    (c) 2002 Gerd Knorr <kraxel@bytesex.org>
-
-    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
-    Sponsored by OPQ Systems AB
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/kdev_t.h>
-#include <media/v4l2-ioctl.h>
-#include <asm/io.h>
-#include "bttvp.h"
-
-/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
-   in fCLKx2 pixels.  According to the datasheet, VBI capture starts
-   VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
-   is 64 fCLKx1 pixels wide.  VBI_HDELAY is set to 0, so this should be
-   (64 + 0) * 2 = 128 fCLKx2 pixels.  But it's not!  The datasheet is
-   Just Plain Wrong.  The real value appears to be different for
-   different revisions of the bt8x8 chips, and to be affected by the
-   horizontal scaling factor.  Experimentally, the value is measured
-   to be about 244.  */
-#define VBI_OFFSET 244
-
-/* 2048 for compatibility with earlier driver versions. The driver
-   really stores 1024 + tvnorm->vbipack * 4 samples per line in the
-   buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
-   is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
-   four bytes of the VBI image. */
-#define VBI_BPL 2048
-
-/* Compatibility. */
-#define VBI_DEFLINES 16
-
-static unsigned int vbibufs = 4;
-static unsigned int vbi_debug;
-
-module_param(vbibufs,   int, 0444);
-module_param(vbi_debug, int, 0644);
-MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4");
-MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
-
-#ifdef dprintk
-# undef dprintk
-#endif
-#define dprintk(fmt, ...)                                              \
-do {                                                                   \
-       if (vbi_debug)                                                  \
-               pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);         \
-} while (0)
-
-#define IMAGE_SIZE(fmt) \
-       (((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
-
-/* ----------------------------------------------------------------------- */
-/* vbi risc code + mm                                                      */
-
-static int vbi_buffer_setup(struct videobuf_queue *q,
-                           unsigned int *count, unsigned int *size)
-{
-       struct bttv_fh *fh = q->priv_data;
-       struct bttv *btv = fh->btv;
-
-       if (0 == *count)
-               *count = vbibufs;
-
-       *size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
-
-       dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
-               fh->vbi_fmt.fmt.samples_per_line,
-               fh->vbi_fmt.fmt.start[0],
-               fh->vbi_fmt.fmt.start[1],
-               fh->vbi_fmt.fmt.count[0],
-               fh->vbi_fmt.fmt.count[1]);
-
-       return 0;
-}
-
-static int vbi_buffer_prepare(struct videobuf_queue *q,
-                             struct videobuf_buffer *vb,
-                             enum v4l2_field field)
-{
-       struct bttv_fh *fh = q->priv_data;
-       struct bttv *btv = fh->btv;
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-       const struct bttv_tvnorm *tvnorm;
-       unsigned int skip_lines0, skip_lines1, min_vdelay;
-       int redo_dma_risc;
-       int rc;
-
-       buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       tvnorm = fh->vbi_fmt.tvnorm;
-
-       /* There's no VBI_VDELAY register, RISC must skip the lines
-          we don't want. With default parameters we skip zero lines
-          as earlier driver versions did. The driver permits video
-          standard changes while capturing, so we use vbi_fmt.tvnorm
-          instead of btv->tvnorm to skip zero lines after video
-          standard changes as well. */
-
-       skip_lines0 = 0;
-       skip_lines1 = 0;
-
-       if (fh->vbi_fmt.fmt.count[0] > 0)
-               skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
-                                     - tvnorm->vbistart[0]));
-       if (fh->vbi_fmt.fmt.count[1] > 0)
-               skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
-                                     - tvnorm->vbistart[1]));
-
-       redo_dma_risc = 0;
-
-       if (buf->vbi_skip[0] != skip_lines0 ||
-           buf->vbi_skip[1] != skip_lines1 ||
-           buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
-           buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
-               buf->vbi_skip[0] = skip_lines0;
-               buf->vbi_skip[1] = skip_lines1;
-               buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
-               buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
-               redo_dma_risc = 1;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               redo_dma_risc = 1;
-               if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
-                       goto fail;
-       }
-
-       if (redo_dma_risc) {
-               unsigned int bpl, padding, offset;
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-               bpl = 2044; /* max. vbipack */
-               padding = VBI_BPL - bpl;
-
-               if (fh->vbi_fmt.fmt.count[0] > 0) {
-                       rc = bttv_risc_packed(btv, &buf->top,
-                                             dma->sglist,
-                                             /* offset */ 0, bpl,
-                                             padding, skip_lines0,
-                                             fh->vbi_fmt.fmt.count[0]);
-                       if (0 != rc)
-                               goto fail;
-               }
-
-               if (fh->vbi_fmt.fmt.count[1] > 0) {
-                       offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
-
-                       rc = bttv_risc_packed(btv, &buf->bottom,
-                                             dma->sglist,
-                                             offset, bpl,
-                                             padding, skip_lines1,
-                                             fh->vbi_fmt.fmt.count[1]);
-                       if (0 != rc)
-                               goto fail;
-               }
-       }
-
-       /* VBI capturing ends at VDELAY, start of video capturing,
-          no matter where the RISC program ends. VDELAY minimum is 2,
-          bounds.top is the corresponding first field line number
-          times two. VDELAY counts half field lines. */
-       min_vdelay = MIN_VDELAY;
-       if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
-               min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
-
-       /* For bttv_buffer_activate_vbi(). */
-       buf->geo.vdelay = min_vdelay;
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       buf->vb.field = field;
-       dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
-               vb, &buf->top, &buf->bottom,
-               v4l2_field_names[buf->vb.field]);
-       return 0;
-
- fail:
-       bttv_dma_free(q,btv,buf);
-       return rc;
-}
-
-static void
-vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct bttv_fh *fh = q->priv_data;
-       struct bttv *btv = fh->btv;
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-
-       dprintk("queue %p\n",vb);
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue,&btv->vcapture);
-       if (NULL == btv->cvbi) {
-               fh->btv->loop_irq |= 4;
-               bttv_set_dma(btv,0x0c);
-       }
-}
-
-static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct bttv_fh *fh = q->priv_data;
-       struct bttv *btv = fh->btv;
-       struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
-
-       dprintk("free %p\n",vb);
-       bttv_dma_free(q,fh->btv,buf);
-}
-
-struct videobuf_queue_ops bttv_vbi_qops = {
-       .buf_setup    = vbi_buffer_setup,
-       .buf_prepare  = vbi_buffer_prepare,
-       .buf_queue    = vbi_buffer_queue,
-       .buf_release  = vbi_buffer_release,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
-                       __s32 crop_start)
-{
-       __s32 min_start, max_start, max_end, f2_offset;
-       unsigned int i;
-
-       /* For compatibility with earlier driver versions we must pretend
-          the VBI and video capture window may overlap. In reality RISC
-          magic aborts VBI capturing at the first line of video capturing,
-          leaving the rest of the buffer unchanged, usually all zero.
-          VBI capturing must always start before video capturing. >> 1
-          because cropping counts field lines times two. */
-       min_start = tvnorm->vbistart[0];
-       max_start = (crop_start >> 1) - 1;
-       max_end = (tvnorm->cropcap.bounds.top
-                  + tvnorm->cropcap.bounds.height) >> 1;
-
-       if (min_start > max_start)
-               return -EBUSY;
-
-       BUG_ON(max_start >= max_end);
-
-       f->sampling_rate    = tvnorm->Fsc;
-       f->samples_per_line = VBI_BPL;
-       f->sample_format    = V4L2_PIX_FMT_GREY;
-       f->offset           = VBI_OFFSET;
-
-       f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
-
-       for (i = 0; i < 2; ++i) {
-               if (0 == f->count[i]) {
-                       /* No data from this field. We leave f->start[i]
-                          alone because VIDIOCSVBIFMT is w/o and EINVALs
-                          when a driver does not support exactly the
-                          requested parameters. */
-               } else {
-                       s64 start, count;
-
-                       start = clamp(f->start[i], min_start, max_start);
-                       /* s64 to prevent overflow. */
-                       count = (s64) f->start[i] + f->count[i] - start;
-                       f->start[i] = start;
-                       f->count[i] = clamp(count, (s64) 1,
-                                           max_end - start);
-               }
-
-               min_start += f2_offset;
-               max_start += f2_offset;
-               max_end += f2_offset;
-       }
-
-       if (0 == (f->count[0] | f->count[1])) {
-               /* As in earlier driver versions. */
-               f->start[0] = tvnorm->vbistart[0];
-               f->start[1] = tvnorm->vbistart[1];
-               f->count[0] = 1;
-               f->count[1] = 1;
-       }
-
-       f->flags = 0;
-
-       f->reserved[0] = 0;
-       f->reserved[1] = 0;
-
-       return 0;
-}
-
-int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       const struct bttv_tvnorm *tvnorm;
-       __s32 crop_start;
-
-       mutex_lock(&btv->lock);
-
-       tvnorm = &bttv_tvnorms[btv->tvnorm];
-       crop_start = btv->crop_start;
-
-       mutex_unlock(&btv->lock);
-
-       return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
-}
-
-
-int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       const struct bttv_tvnorm *tvnorm;
-       __s32 start1, end;
-       int rc;
-
-       mutex_lock(&btv->lock);
-
-       rc = -EBUSY;
-       if (fh->resources & RESOURCE_VBI)
-               goto fail;
-
-       tvnorm = &bttv_tvnorms[btv->tvnorm];
-
-       rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
-       if (0 != rc)
-               goto fail;
-
-       start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
-               tvnorm->vbistart[0];
-
-       /* First possible line of video capturing. Should be
-          max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
-          when capturing both fields. But for compatibility we must
-          pretend the VBI and video capture window may overlap,
-          so end = start + 1, the lowest possible value, times two
-          because vbi_fmt.end counts field lines times two. */
-       end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
-
-       mutex_lock(&fh->vbi.vb_lock);
-
-       fh->vbi_fmt.fmt    = frt->fmt.vbi;
-       fh->vbi_fmt.tvnorm = tvnorm;
-       fh->vbi_fmt.end    = end;
-
-       mutex_unlock(&fh->vbi.vb_lock);
-
-       rc = 0;
-
- fail:
-       mutex_unlock(&btv->lock);
-
-       return rc;
-}
-
-
-int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
-{
-       struct bttv_fh *fh = f;
-       const struct bttv_tvnorm *tvnorm;
-
-       frt->fmt.vbi = fh->vbi_fmt.fmt;
-
-       tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
-
-       if (tvnorm != fh->vbi_fmt.tvnorm) {
-               __s32 max_end;
-               unsigned int i;
-
-               /* As in vbi_buffer_prepare() this imitates the
-                  behaviour of earlier driver versions after video
-                  standard changes, with default parameters anyway. */
-
-               max_end = (tvnorm->cropcap.bounds.top
-                          + tvnorm->cropcap.bounds.height) >> 1;
-
-               frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
-
-               for (i = 0; i < 2; ++i) {
-                       __s32 new_start;
-
-                       new_start = frt->fmt.vbi.start[i]
-                               + tvnorm->vbistart[i]
-                               - fh->vbi_fmt.tvnorm->vbistart[i];
-
-                       frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
-                       frt->fmt.vbi.count[i] =
-                               min((__s32) frt->fmt.vbi.count[i],
-                                         max_end - frt->fmt.vbi.start[i]);
-
-                       max_end += tvnorm->vbistart[1]
-                               - tvnorm->vbistart[0];
-               }
-       }
-       return 0;
-}
-
-void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
-{
-       const struct bttv_tvnorm *tvnorm;
-       unsigned int real_samples_per_line;
-       unsigned int real_count;
-
-       tvnorm = &bttv_tvnorms[norm];
-
-       f->fmt.sampling_rate    = tvnorm->Fsc;
-       f->fmt.samples_per_line = VBI_BPL;
-       f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
-       f->fmt.offset           = VBI_OFFSET;
-       f->fmt.start[0]         = tvnorm->vbistart[0];
-       f->fmt.start[1]         = tvnorm->vbistart[1];
-       f->fmt.count[0]         = VBI_DEFLINES;
-       f->fmt.count[1]         = VBI_DEFLINES;
-       f->fmt.flags            = 0;
-       f->fmt.reserved[0]      = 0;
-       f->fmt.reserved[1]      = 0;
-
-       /* For compatibility the buffer size must be 2 * VBI_DEFLINES *
-          VBI_BPL regardless of the current video standard. */
-       real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
-       real_count              = ((tvnorm->cropcap.defrect.top >> 1)
-                                  - tvnorm->vbistart[0]);
-
-       BUG_ON(real_samples_per_line > VBI_BPL);
-       BUG_ON(real_count > VBI_DEFLINES);
-
-       f->tvnorm               = tvnorm;
-
-       /* See bttv_vbi_fmt_set(). */
-       f->end                  = tvnorm->vbistart[0] * 2 + 2;
-}
-
-/* ----------------------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
deleted file mode 100644 (file)
index 79a1124..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- *
- *  bttv - Bt848 frame grabber driver
- *
- *  card ID's and external interfaces of the bttv driver
- *  basically stuff needed by other drivers (i2c, lirc, ...)
- *  and is supported not to change much over time.
- *
- *  Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
- *  (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#ifndef _BTTV_H_
-#define _BTTV_H_
-
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-#include <media/v4l2-device.h>
-#include <media/i2c-addr.h>
-#include <media/tuner.h>
-
-/* ---------------------------------------------------------- */
-/* exported by bttv-cards.c                                   */
-
-#define BTTV_BOARD_UNKNOWN                 0x00
-#define BTTV_BOARD_MIRO                    0x01
-#define BTTV_BOARD_HAUPPAUGE               0x02
-#define BTTV_BOARD_STB                     0x03
-#define BTTV_BOARD_INTEL                   0x04
-#define BTTV_BOARD_DIAMOND                 0x05
-#define BTTV_BOARD_AVERMEDIA               0x06
-#define BTTV_BOARD_MATRIX_VISION           0x07
-#define BTTV_BOARD_FLYVIDEO                0x08
-#define BTTV_BOARD_TURBOTV                 0x09
-#define BTTV_BOARD_HAUPPAUGE878            0x0a
-#define BTTV_BOARD_MIROPRO                 0x0b
-#define BTTV_BOARD_ADSTECH_TV              0x0c
-#define BTTV_BOARD_AVERMEDIA98             0x0d
-#define BTTV_BOARD_VHX                     0x0e
-#define BTTV_BOARD_ZOLTRIX                 0x0f
-#define BTTV_BOARD_PIXVIEWPLAYTV           0x10
-#define BTTV_BOARD_WINVIEW_601             0x11
-#define BTTV_BOARD_AVEC_INTERCAP           0x12
-#define BTTV_BOARD_LIFE_FLYKIT             0x13
-#define BTTV_BOARD_CEI_RAFFLES             0x14
-#define BTTV_BOARD_CONFERENCETV            0x15
-#define BTTV_BOARD_PHOEBE_TVMAS            0x16
-#define BTTV_BOARD_MODTEC_205              0x17
-#define BTTV_BOARD_MAGICTVIEW061           0x18
-#define BTTV_BOARD_VOBIS_BOOSTAR           0x19
-#define BTTV_BOARD_HAUPPAUG_WCAM           0x1a
-#define BTTV_BOARD_MAXI                    0x1b
-#define BTTV_BOARD_TERRATV                 0x1c
-#define BTTV_BOARD_PXC200                  0x1d
-#define BTTV_BOARD_FLYVIDEO_98             0x1e
-#define BTTV_BOARD_IPROTV                  0x1f
-#define BTTV_BOARD_INTEL_C_S_PCI           0x20
-#define BTTV_BOARD_TERRATVALUE             0x21
-#define BTTV_BOARD_WINFAST2000             0x22
-#define BTTV_BOARD_CHRONOS_VS2             0x23
-#define BTTV_BOARD_TYPHOON_TVIEW           0x24
-#define BTTV_BOARD_PXELVWPLTVPRO           0x25
-#define BTTV_BOARD_MAGICTVIEW063           0x26
-#define BTTV_BOARD_PINNACLE                0x27
-#define BTTV_BOARD_STB2                    0x28
-#define BTTV_BOARD_AVPHONE98               0x29
-#define BTTV_BOARD_PV951                   0x2a
-#define BTTV_BOARD_ONAIR_TV                0x2b
-#define BTTV_BOARD_SIGMA_TVII_FM           0x2c
-#define BTTV_BOARD_MATRIX_VISION2          0x2d
-#define BTTV_BOARD_ZOLTRIX_GENIE           0x2e
-#define BTTV_BOARD_TERRATVRADIO            0x2f
-#define BTTV_BOARD_DYNALINK                0x30
-#define BTTV_BOARD_GVBCTV3PCI              0x31
-#define BTTV_BOARD_PXELVWPLTVPAK           0x32
-#define BTTV_BOARD_EAGLE                   0x33
-#define BTTV_BOARD_PINNACLEPRO             0x34
-#define BTTV_BOARD_TVIEW_RDS_FM            0x35
-#define BTTV_BOARD_LIFETEC_9415            0x36
-#define BTTV_BOARD_BESTBUY_EASYTV          0x37
-#define BTTV_BOARD_FLYVIDEO_98FM           0x38
-#define BTTV_BOARD_GRANDTEC                0x39
-#define BTTV_BOARD_ASKEY_CPH060            0x3a
-#define BTTV_BOARD_ASKEY_CPH03X            0x3b
-#define BTTV_BOARD_MM100PCTV               0x3c
-#define BTTV_BOARD_GMV1                    0x3d
-#define BTTV_BOARD_BESTBUY_EASYTV2         0x3e
-#define BTTV_BOARD_ATI_TVWONDER            0x3f
-#define BTTV_BOARD_ATI_TVWONDERVE          0x40
-#define BTTV_BOARD_FLYVIDEO2000            0x41
-#define BTTV_BOARD_TERRATVALUER            0x42
-#define BTTV_BOARD_GVBCTV4PCI              0x43
-#define BTTV_BOARD_VOODOOTV_FM             0x44
-#define BTTV_BOARD_AIMMS                   0x45
-#define BTTV_BOARD_PV_BT878P_PLUS          0x46
-#define BTTV_BOARD_FLYVIDEO98EZ            0x47
-#define BTTV_BOARD_PV_BT878P_9B            0x48
-#define BTTV_BOARD_SENSORAY311_611         0x49
-#define BTTV_BOARD_RV605                   0x4a
-#define BTTV_BOARD_POWERCLR_MTV878         0x4b
-#define BTTV_BOARD_WINDVR                  0x4c
-#define BTTV_BOARD_GRANDTEC_MULTI          0x4d
-#define BTTV_BOARD_KWORLD                  0x4e
-#define BTTV_BOARD_DSP_TCVIDEO             0x4f
-#define BTTV_BOARD_HAUPPAUGEPVR            0x50
-#define BTTV_BOARD_GVBCTV5PCI              0x51
-#define BTTV_BOARD_OSPREY1x0               0x52
-#define BTTV_BOARD_OSPREY1x0_848           0x53
-#define BTTV_BOARD_OSPREY101_848           0x54
-#define BTTV_BOARD_OSPREY1x1               0x55
-#define BTTV_BOARD_OSPREY1x1_SVID          0x56
-#define BTTV_BOARD_OSPREY2xx               0x57
-#define BTTV_BOARD_OSPREY2x0_SVID          0x58
-#define BTTV_BOARD_OSPREY2x0               0x59
-#define BTTV_BOARD_OSPREY500               0x5a
-#define BTTV_BOARD_OSPREY540               0x5b
-#define BTTV_BOARD_OSPREY2000              0x5c
-#define BTTV_BOARD_IDS_EAGLE               0x5d
-#define BTTV_BOARD_PINNACLESAT             0x5e
-#define BTTV_BOARD_FORMAC_PROTV            0x5f
-#define BTTV_BOARD_MACHTV                  0x60
-#define BTTV_BOARD_EURESYS_PICOLO          0x61
-#define BTTV_BOARD_PV150                   0x62
-#define BTTV_BOARD_AD_TVK503               0x63
-#define BTTV_BOARD_HERCULES_SM_TV          0x64
-#define BTTV_BOARD_PACETV                  0x65
-#define BTTV_BOARD_IVC200                  0x66
-#define BTTV_BOARD_XGUARD                  0x67
-#define BTTV_BOARD_NEBULA_DIGITV           0x68
-#define BTTV_BOARD_PV143                   0x69
-#define BTTV_BOARD_VD009X1_VD011_MINIDIN   0x6a
-#define BTTV_BOARD_VD009X1_VD011_COMBI     0x6b
-#define BTTV_BOARD_VD009_MINIDIN           0x6c
-#define BTTV_BOARD_VD009_COMBI             0x6d
-#define BTTV_BOARD_IVC100                  0x6e
-#define BTTV_BOARD_IVC120                  0x6f
-#define BTTV_BOARD_PC_HDTV                 0x70
-#define BTTV_BOARD_TWINHAN_DST             0x71
-#define BTTV_BOARD_WINFASTVC100            0x72
-#define BTTV_BOARD_TEV560                  0x73
-#define BTTV_BOARD_SIMUS_GVC1100           0x74
-#define BTTV_BOARD_NGSTV_PLUS              0x75
-#define BTTV_BOARD_LMLBT4                  0x76
-#define BTTV_BOARD_TEKRAM_M205             0x77
-#define BTTV_BOARD_CONTVFMI                0x78
-#define BTTV_BOARD_PICOLO_TETRA_CHIP       0x79
-#define BTTV_BOARD_SPIRIT_TV               0x7a
-#define BTTV_BOARD_AVDVBT_771              0x7b
-#define BTTV_BOARD_AVDVBT_761              0x7c
-#define BTTV_BOARD_MATRIX_VISIONSQ         0x7d
-#define BTTV_BOARD_MATRIX_VISIONSLC        0x7e
-#define BTTV_BOARD_APAC_VIEWCOMP           0x7f
-#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
-#define BTTV_BOARD_VGEAR_MYVCD             0x81
-#define BTTV_BOARD_SUPER_TV                0x82
-#define BTTV_BOARD_TIBET_CS16              0x83
-#define BTTV_BOARD_KODICOM_4400R           0x84
-#define BTTV_BOARD_KODICOM_4400R_SL        0x85
-#define BTTV_BOARD_ADLINK_RTV24            0x86
-#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
-#define BTTV_BOARD_ACORP_Y878F             0x88
-#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2    0x89
-#define BTTV_BOARD_PV_BT878P_2E            0x8a
-#define BTTV_BOARD_PV_M4900                0x8b
-#define BTTV_BOARD_OSPREY440               0x8c
-#define BTTV_BOARD_ASOUND_SKYEYE          0x8d
-#define BTTV_BOARD_SABRENT_TVFM           0x8e
-#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB     0x8f
-#define BTTV_BOARD_MACHTV_MAGICTV          0x90
-#define BTTV_BOARD_SSAI_SECURITY          0x91
-#define BTTV_BOARD_SSAI_ULTRASOUND        0x92
-#define BTTV_BOARD_VOODOOTV_200                   0x93
-#define BTTV_BOARD_DVICO_FUSIONHDTV_2     0x94
-#define BTTV_BOARD_TYPHOON_TVTUNERPCI     0x95
-#define BTTV_BOARD_GEOVISION_GV600        0x96
-#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
-#define BTTV_BOARD_ENLTV_FM_2             0x98
-#define BTTV_BOARD_VD012                  0x99
-#define BTTV_BOARD_VD012_X1               0x9a
-#define BTTV_BOARD_VD012_X2               0x9b
-#define BTTV_BOARD_IVCE8784               0x9c
-#define BTTV_BOARD_GEOVISION_GV800S       0x9d
-#define BTTV_BOARD_GEOVISION_GV800S_SL    0x9e
-#define BTTV_BOARD_PV183                   0x9f
-#define BTTV_BOARD_TVT_TD3116             0xa0
-#define BTTV_BOARD_APOSONIC_WDVR           0xa1
-
-/* more card-specific defines */
-#define PT2254_L_CHANNEL 0x10
-#define PT2254_R_CHANNEL 0x08
-#define PT2254_DBS_IN_2 0x400
-#define PT2254_DBS_IN_10 0x20000
-#define WINVIEW_PT2254_CLK  0x40
-#define WINVIEW_PT2254_DATA 0x20
-#define WINVIEW_PT2254_STROBE 0x80
-
-struct bttv_core {
-       /* device structs */
-       struct v4l2_device   v4l2_dev;
-       struct pci_dev       *pci;
-       struct i2c_adapter   i2c_adap;
-       struct list_head     subs;     /* struct bttv_sub_device */
-
-       /* device config */
-       unsigned int         nr;       /* dev nr (for printk("bttv%d: ...");  */
-       unsigned int         type;     /* card type (pointer into tvcards[])  */
-};
-
-struct bttv;
-
-struct tvcard {
-       char *name;
-       void (*volume_gpio)(struct bttv *btv, __u16 volume);
-       void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-       void (*muxsel_hook)(struct bttv *btv, unsigned int input);
-
-       /* MUX bits for each input, two bits per input starting with the LSB */
-       u32 muxsel; /* Use MUXSEL() to set */
-
-       u32 gpiomask;
-       u32 gpiomux[4];  /* Tuner, Radio, external, internal */
-       u32 gpiomute;    /* GPIO mute setting */
-       u32 gpiomask2;   /* GPIO MUX mask */
-
-       unsigned int tuner_type;
-       u8 tuner_addr;
-       u8 video_inputs;        /* Number of inputs */
-       unsigned int svhs:4;    /* Which input is s-video */
-#define NO_SVHS        15
-       unsigned int pll:2;
-#define PLL_NONE 0
-#define PLL_28   1
-#define PLL_35   2
-
-       /* i2c audio flags */
-       unsigned int no_msp34xx:1;
-       unsigned int no_tda7432:1;
-       unsigned int msp34xx_alt:1;
-       /* Note: currently no card definition needs to mark the presence
-          of a RDS saa6588 chip. If this is ever needed, then add a new
-          'has_saa6588' bit here. */
-
-       unsigned int no_video:1; /* video pci function is unused */
-       unsigned int has_dvb:1;
-       unsigned int has_remote:1;
-       unsigned int has_radio:1;
-       unsigned int has_dig_in:1; /* Has digital input (always last input) */
-       unsigned int no_gpioirq:1;
-};
-
-extern struct tvcard bttv_tvcards[];
-
-/*
- * This bit of cpp voodoo is used to create a macro with a variable number of
- * arguments (1 to 16).  It will pack each argument into a word two bits at a
- * time.  It can't be a function because it needs to be compile time constant to
- * initialize structures.  Since each argument must fit in two bits, it's ok
- * that they are changed to octal.  One should not use hex number, macros, or
- * anything else with this macro.  Just use plain integers from 0 to 3.
- */
-#define _MUXSELf(a)            0##a << 30
-#define _MUXSELe(a, b...)      0##a << 28 | _MUXSELf(b)
-#define _MUXSELd(a, b...)      0##a << 26 | _MUXSELe(b)
-#define _MUXSELc(a, b...)      0##a << 24 | _MUXSELd(b)
-#define _MUXSELb(a, b...)      0##a << 22 | _MUXSELc(b)
-#define _MUXSELa(a, b...)      0##a << 20 | _MUXSELb(b)
-#define _MUXSEL9(a, b...)      0##a << 18 | _MUXSELa(b)
-#define _MUXSEL8(a, b...)      0##a << 16 | _MUXSEL9(b)
-#define _MUXSEL7(a, b...)      0##a << 14 | _MUXSEL8(b)
-#define _MUXSEL6(a, b...)      0##a << 12 | _MUXSEL7(b)
-#define _MUXSEL5(a, b...)      0##a << 10 | _MUXSEL6(b)
-#define _MUXSEL4(a, b...)      0##a << 8  | _MUXSEL5(b)
-#define _MUXSEL3(a, b...)      0##a << 6  | _MUXSEL4(b)
-#define _MUXSEL2(a, b...)      0##a << 4  | _MUXSEL3(b)
-#define _MUXSEL1(a, b...)      0##a << 2  | _MUXSEL2(b)
-#define MUXSEL(a, b...)                (a | _MUXSEL1(b))
-
-/* identification / initialization of the card */
-extern void bttv_idcard(struct bttv *btv);
-extern void bttv_init_card1(struct bttv *btv);
-extern void bttv_init_card2(struct bttv *btv);
-extern void bttv_init_tuner(struct bttv *btv);
-
-/* card-specific funtions */
-extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
-extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits);
-
-/* extra tweaks for some chipsets */
-extern void bttv_check_chipset(void);
-extern int bttv_handle_chipset(struct bttv *btv);
-
-/* ---------------------------------------------------------- */
-/* exported by bttv-if.c                                      */
-
-/* this obsolete -- please use the sysfs-based
-   interface below for new code */
-
-extern struct pci_dev* bttv_get_pcidev(unsigned int card);
-
-/* sets GPOE register (BT848_GPIO_OUT_EN) to new value:
-   data | (current_GPOE_value & ~mask)
-   returns negative value if error occurred
-*/
-extern int bttv_gpio_enable(unsigned int card,
-                           unsigned long mask, unsigned long data);
-
-/* fills data with GPDATA register contents
-   returns negative value if error occurred
-*/
-extern int bttv_read_gpio(unsigned int card, unsigned long *data);
-
-/* sets GPDATA register to new value:
-  (data & mask) | (current_GPDATA_value & ~mask)
-  returns negative value if error occurred
-*/
-extern int bttv_write_gpio(unsigned int card,
-                          unsigned long mask, unsigned long data);
-
-
-
-
-/* ---------------------------------------------------------- */
-/* sysfs/driver-moded based gpio access interface             */
-
-struct bttv_sub_device {
-       struct device    dev;
-       struct bttv_core *core;
-       struct list_head list;
-};
-#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev)
-
-struct bttv_sub_driver {
-       struct device_driver   drv;
-       char                   wanted[20];
-       int                    (*probe)(struct bttv_sub_device *sub);
-       void                   (*remove)(struct bttv_sub_device *sub);
-};
-#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
-
-int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted);
-int bttv_sub_unregister(struct bttv_sub_driver *drv);
-
-/* gpio access functions */
-void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits);
-u32 bttv_gpio_read(struct bttv_core *core);
-void bttv_gpio_write(struct bttv_core *core, u32 value);
-void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
-
-#define gpio_inout(mask,bits)  bttv_gpio_inout(&btv->c, mask, bits)
-#define gpio_read()            bttv_gpio_read(&btv->c)
-#define gpio_write(value)      bttv_gpio_write(&btv->c, value)
-#define gpio_bits(mask,bits)   bttv_gpio_bits(&btv->c, mask, bits)
-
-
-/* ---------------------------------------------------------- */
-/* i2c                                                        */
-
-#define bttv_call_all(btv, o, f, args...) \
-       v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
-
-extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
-extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
-                        unsigned char b2, int both);
-extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
-
-extern int bttv_input_init(struct bttv *dev);
-extern void bttv_input_fini(struct bttv *dev);
-extern void bttv_input_irq(struct bttv *dev);
-
-#endif /* _BTTV_H_ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
deleted file mode 100644 (file)
index 70fd4f2..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
-
-    bttv - Bt848 frame grabber driver
-
-    bttv's *private* header file  --  nobody other than bttv itself
-    should ever include this file.
-
-    (c) 2000-2002 Gerd Knorr <kraxel@bytesex.org>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _BTTVP_H_
-#define _BTTVP_H_
-
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/pci.h>
-#include <linux/input.h>
-#include <linux/mutex.h>
-#include <linux/scatterlist.h>
-#include <asm/io.h>
-#include <media/v4l2-common.h>
-#include <linux/device.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/tveeprom.h>
-#include <media/rc-core.h>
-#include <media/ir-kbd-i2c.h>
-
-#include "bt848.h"
-#include "bttv.h"
-#include "btcx-risc.h"
-
-#ifdef __KERNEL__
-
-#define FORMAT_FLAGS_DITHER       0x01
-#define FORMAT_FLAGS_PACKED       0x02
-#define FORMAT_FLAGS_PLANAR       0x04
-#define FORMAT_FLAGS_RAW          0x08
-#define FORMAT_FLAGS_CrCb         0x10
-
-#define RISC_SLOT_O_VBI        4
-#define RISC_SLOT_O_FIELD      6
-#define RISC_SLOT_E_VBI       10
-#define RISC_SLOT_E_FIELD     12
-#define RISC_SLOT_LOOP        14
-
-#define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO_STREAM  2
-#define RESOURCE_VBI           4
-#define RESOURCE_VIDEO_READ    8
-
-#define RAW_LINES            640
-#define RAW_BPL             1024
-
-#define UNSET (-1U)
-
-/* Min. value in VDELAY register. */
-#define MIN_VDELAY 2
-/* Even to get Cb first, odd for Cr. */
-#define MAX_HDELAY (0x3FF & -2)
-/* Limits scaled width, which must be a multiple of 4. */
-#define MAX_HACTIVE (0x3FF & -4)
-
-#define BTTV_NORMS    (\
-               V4L2_STD_PAL    | V4L2_STD_PAL_N | \
-               V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
-               V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
-               V4L2_STD_PAL_60)
-/* ---------------------------------------------------------- */
-
-struct bttv_tvnorm {
-       int   v4l2_id;
-       char  *name;
-       u32   Fsc;
-       u16   swidth, sheight; /* scaled standard width, height */
-       u16   totalwidth;
-       u8    adelay, bdelay, iform;
-       u32   scaledtwidth;
-       u16   hdelayx1, hactivex1;
-       u16   vdelay;
-       u8    vbipack;
-       u16   vtotal;
-       int   sram;
-       /* ITU-R frame line number of the first VBI line we can
-          capture, of the first and second field. The last possible line
-          is determined by cropcap.bounds. */
-       u16   vbistart[2];
-       /* Horizontally this counts fCLKx1 samples following the leading
-          edge of the horizontal sync pulse, vertically ITU-R frame line
-          numbers of the first field times two (2, 4, 6, ... 524 or 624). */
-       struct v4l2_cropcap cropcap;
-};
-extern const struct bttv_tvnorm bttv_tvnorms[];
-
-struct bttv_format {
-       char *name;
-       int  fourcc;          /* video4linux 2      */
-       int  btformat;        /* BT848_COLOR_FMT_*  */
-       int  btswap;          /* BT848_COLOR_CTL_*  */
-       int  depth;           /* bit/pixel          */
-       int  flags;
-       int  hshift,vshift;   /* for planar modes   */
-};
-
-struct bttv_ir {
-       struct rc_dev           *dev;
-       struct timer_list       timer;
-
-       char                    name[32];
-       char                    phys[32];
-
-       /* Usual gpio signalling */
-       u32                     mask_keycode;
-       u32                     mask_keydown;
-       u32                     mask_keyup;
-       u32                     polling;
-       u32                     last_gpio;
-       int                     shift_by;
-       int                     start; // What should RC5_START() be
-       int                     addr; // What RC5_ADDR() should be.
-       int                     rc5_remote_gap;
-
-       /* RC5 gpio */
-       bool                    rc5_gpio;   /* Is RC5 legacy GPIO enabled? */
-       u32                     last_bit;   /* last raw bit seen */
-       u32                     code;       /* raw code under construction */
-       struct timeval          base_time;  /* time of last seen code */
-       bool                    active;     /* building raw code */
-};
-
-
-/* ---------------------------------------------------------- */
-
-struct bttv_geometry {
-       u8  vtc,crop,comb;
-       u16 width,hscale,hdelay;
-       u16 sheight,vscale,vdelay,vtotal;
-};
-
-struct bttv_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer     vb;
-
-       /* bttv specific */
-       const struct bttv_format   *fmt;
-       unsigned int               tvnorm;
-       int                        btformat;
-       int                        btswap;
-       struct bttv_geometry       geo;
-       struct btcx_riscmem        top;
-       struct btcx_riscmem        bottom;
-       struct v4l2_rect           crop;
-       unsigned int               vbi_skip[2];
-       unsigned int               vbi_count[2];
-};
-
-struct bttv_buffer_set {
-       struct bttv_buffer     *top;       /* top field buffer    */
-       struct bttv_buffer     *bottom;    /* bottom field buffer */
-       unsigned int           top_irq;
-       unsigned int           frame_irq;
-};
-
-struct bttv_overlay {
-       unsigned int           tvnorm;
-       struct v4l2_rect       w;
-       enum v4l2_field        field;
-       struct v4l2_clip       *clips;
-       int                    nclips;
-       int                    setup_ok;
-};
-
-struct bttv_vbi_fmt {
-       struct v4l2_vbi_format fmt;
-
-       /* fmt.start[] and count[] refer to this video standard. */
-       const struct bttv_tvnorm *tvnorm;
-
-       /* Earliest possible start of video capturing with this
-          v4l2_vbi_format, in struct bttv_crop.rect units. */
-       __s32                  end;
-};
-
-/* bttv-vbi.c */
-void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
-
-struct bttv_crop {
-       /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */
-       struct v4l2_rect       rect;
-
-       /* Scaled image size limits with this crop rect. Divide
-          max_height, but not min_height, by two when capturing
-          single fields. See also bttv_crop_reset() and
-          bttv_crop_adjust() in bttv-driver.c. */
-       __s32                  min_scaled_width;
-       __s32                  min_scaled_height;
-       __s32                  max_scaled_width;
-       __s32                  max_scaled_height;
-};
-
-struct bttv_fh {
-       struct bttv              *btv;
-       int resources;
-#ifdef VIDIOC_G_PRIORITY
-       enum v4l2_priority       prio;
-#endif
-       enum v4l2_buf_type       type;
-
-       /* video capture */
-       struct videobuf_queue    cap;
-       const struct bttv_format *fmt;
-       int                      width;
-       int                      height;
-
-       /* video overlay */
-       const struct bttv_format *ovfmt;
-       struct bttv_overlay      ov;
-
-       /* Application called VIDIOC_S_CROP. */
-       int                      do_crop;
-
-       /* vbi capture */
-       struct videobuf_queue    vbi;
-       /* Current VBI capture window as seen through this fh (cannot
-          be global for compatibility with earlier drivers). Protected
-          by struct bttv.lock and struct bttv_fh.vbi.lock. */
-       struct bttv_vbi_fmt      vbi_fmt;
-};
-
-/* ---------------------------------------------------------- */
-/* bttv-risc.c                                                */
-
-/* risc code generators - capture */
-int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
-                    struct scatterlist *sglist,
-                    unsigned int offset, unsigned int bpl,
-                    unsigned int pitch, unsigned int skip_lines,
-                    unsigned int store_lines);
-
-/* control dma register + risc main loop */
-void bttv_set_dma(struct bttv *btv, int override);
-int bttv_risc_init_main(struct bttv *btv);
-int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
-                  int irqflags);
-
-/* capture buffer handling */
-int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
-int bttv_buffer_activate_video(struct bttv *btv,
-                              struct bttv_buffer_set *set);
-int bttv_buffer_activate_vbi(struct bttv *btv,
-                            struct bttv_buffer *vbi);
-void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
-                  struct bttv_buffer *buf);
-
-/* overlay handling */
-int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
-                     const struct bttv_format *fmt,
-                     struct bttv_buffer *buf);
-
-
-/* ---------------------------------------------------------- */
-/* bttv-vbi.c                                                 */
-
-int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
-
-extern struct videobuf_queue_ops bttv_vbi_qops;
-
-/* ---------------------------------------------------------- */
-/* bttv-gpio.c */
-
-extern struct bus_type bttv_sub_bus_type;
-int bttv_sub_add_device(struct bttv_core *core, char *name);
-int bttv_sub_del_devices(struct bttv_core *core);
-
-/* ---------------------------------------------------------- */
-/* bttv-cards.c                                               */
-
-extern int no_overlay;
-
-/* ---------------------------------------------------------- */
-/* bttv-input.c                                               */
-
-extern void init_bttv_i2c_ir(struct bttv *btv);
-extern int fini_bttv_i2c(struct bttv *btv);
-
-/* ---------------------------------------------------------- */
-/* bttv-driver.c                                              */
-
-/* insmod options */
-extern unsigned int bttv_verbose;
-extern unsigned int bttv_debug;
-extern unsigned int bttv_gpio;
-extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
-extern int init_bttv_i2c(struct bttv *btv);
-
-#define dprintk(fmt, ...)                      \
-do {                                           \
-       if (bttv_debug >= 1)                    \
-               pr_debug(fmt, ##__VA_ARGS__);   \
-} while (0)
-#define dprintk_cont(fmt, ...)                 \
-do {                                           \
-       if (bttv_debug >= 1)                    \
-               pr_cont(fmt, ##__VA_ARGS__);    \
-} while (0)
-#define d2printk(fmt, ...)                     \
-do {                                           \
-       if (bttv_debug >= 2)                    \
-               printk(fmt, ##__VA_ARGS__);     \
-} while (0)
-
-#define BTTV_MAX_FBUF   0x208000
-#define BTTV_TIMEOUT    msecs_to_jiffies(500)    /* 0.5 seconds */
-#define BTTV_FREE_IDLE  msecs_to_jiffies(1000)   /* one second */
-
-
-struct bttv_pll_info {
-       unsigned int pll_ifreq;    /* PLL input frequency        */
-       unsigned int pll_ofreq;    /* PLL output frequency       */
-       unsigned int pll_crystal;  /* Crystal used for input     */
-       unsigned int pll_current;  /* Currently programmed ofreq */
-};
-
-/* for gpio-connected remote control */
-struct bttv_input {
-       struct input_dev      *dev;
-       char                  name[32];
-       char                  phys[32];
-       u32                   mask_keycode;
-       u32                   mask_keydown;
-};
-
-struct bttv_suspend_state {
-       u32  gpio_enable;
-       u32  gpio_data;
-       int  disabled;
-       int  loop_irq;
-       struct bttv_buffer_set video;
-       struct bttv_buffer     *vbi;
-};
-
-struct bttv {
-       struct bttv_core c;
-
-       /* pci device config */
-       unsigned short id;
-       unsigned char revision;
-       unsigned char __iomem *bt848_mmio;   /* pointer to mmio */
-
-       /* card configuration info */
-       unsigned int cardid;   /* pci subsystem id (bt878 based ones) */
-       unsigned int tuner_type;  /* tuner chip type */
-       unsigned int tda9887_conf;
-       unsigned int svhs, dig;
-       unsigned int has_saa6588:1;
-       struct bttv_pll_info pll;
-       int triton1;
-       int gpioirq;
-
-       int use_i2c_hw;
-
-       /* old gpio interface */
-       int shutdown;
-
-       void (*volume_gpio)(struct bttv *btv, __u16 volume);
-       void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-
-       /* new gpio interface */
-       spinlock_t gpio_lock;
-
-       /* i2c layer */
-       struct i2c_algo_bit_data   i2c_algo;
-       struct i2c_client          i2c_client;
-       int                        i2c_state, i2c_rc;
-       int                        i2c_done;
-       wait_queue_head_t          i2c_queue;
-       struct v4l2_subdev        *sd_msp34xx;
-       struct v4l2_subdev        *sd_tvaudio;
-
-       /* video4linux (1) */
-       struct video_device *video_dev;
-       struct video_device *radio_dev;
-       struct video_device *vbi_dev;
-
-       /* infrared remote */
-       int has_remote;
-       struct bttv_ir *remote;
-
-       /* I2C remote data */
-       struct IR_i2c_init_data    init_data;
-
-       /* locking */
-       spinlock_t s_lock;
-       struct mutex lock;
-       int resources;
-#ifdef VIDIOC_G_PRIORITY
-       struct v4l2_prio_state prio;
-#endif
-
-       /* video state */
-       unsigned int input;
-       unsigned int audio;
-       unsigned int mute;
-       unsigned long freq;
-       unsigned int tvnorm;
-       int hue, contrast, bright, saturation;
-       struct v4l2_framebuffer fbuf;
-       unsigned int field_count;
-
-       /* various options */
-       int opt_combfilter;
-       int opt_lumafilter;
-       int opt_automute;
-       int opt_chroma_agc;
-       int opt_adc_crush;
-       int opt_vcr_hack;
-       int opt_whitecrush_upper;
-       int opt_whitecrush_lower;
-       int opt_uv_ratio;
-       int opt_full_luma_range;
-       int opt_coring;
-
-       /* radio data/state */
-       int has_radio;
-       int radio_user;
-       int radio_uses_msp_demodulator;
-
-       /* miro/pinnacle + Aimslab VHX
-          philips matchbox (tea5757 radio tuner) support */
-       int has_matchbox;
-       int mbox_we;
-       int mbox_data;
-       int mbox_clk;
-       int mbox_most;
-       int mbox_mask;
-
-       /* ISA stuff (Terratec Active Radio Upgrade) */
-       int mbox_ior;
-       int mbox_iow;
-       int mbox_csel;
-
-       /* risc memory management data
-          - must acquire s_lock before changing these
-          - only the irq handler is supported to touch top + bottom + vcurr */
-       struct btcx_riscmem     main;
-       struct bttv_buffer      *screen;    /* overlay             */
-       struct list_head        capture;    /* video capture queue */
-       struct list_head        vcapture;   /* vbi capture queue   */
-       struct bttv_buffer_set  curr;       /* active buffers      */
-       struct bttv_buffer      *cvbi;      /* active vbi buffer   */
-       int                     loop_irq;
-       int                     new_input;
-
-       unsigned long cap_ctl;
-       unsigned long dma_on;
-       struct timer_list timeout;
-       struct bttv_suspend_state state;
-
-       /* stats */
-       unsigned int errors;
-       unsigned int framedrop;
-       unsigned int irq_total;
-       unsigned int irq_me;
-
-       unsigned int users;
-       struct bttv_fh init;
-
-       /* used to make dvb-bt8xx autoloadable */
-       struct work_struct request_module_wk;
-
-       /* Default (0) and current (1) video capturing and overlay
-          cropping parameters in bttv_tvnorm.cropcap units. Protected
-          by bttv.lock. */
-       struct bttv_crop crop[2];
-
-       /* Earliest possible start of video capturing in
-          bttv_tvnorm.cropcap line units. Set by check_alloc_btres()
-          and free_btres(). Protected by bttv.lock. */
-       __s32                   vbi_end;
-
-       /* Latest possible end of VBI capturing (= crop[x].rect.top when
-          VIDEO_RESOURCES are locked). Set by check_alloc_btres()
-          and free_btres(). Protected by bttv.lock. */
-       __s32                   crop_start;
-};
-
-static inline struct bttv *to_bttv(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct bttv, c.v4l2_dev);
-}
-
-/* our devices */
-#define BTTV_MAX 32
-extern unsigned int bttv_num;
-extern struct bttv *bttvs[BTTV_MAX];
-
-static inline unsigned int bttv_muxsel(const struct bttv *btv,
-                                      unsigned int input)
-{
-       return (bttv_tvcards[btv->c.type].muxsel >> (input * 2)) & 3;
-}
-
-#endif
-
-#define btwrite(dat,adr)    writel((dat), btv->bt848_mmio+(adr))
-#define btread(adr)         readl(btv->bt848_mmio+(adr))
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-#endif /* _BTTVP_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */