]> git.hungrycats.org Git - linux/commitdiff
[PATCH] v4l: bttv driver update
authorGerd Knorr <kraxel@bytesex.org>
Thu, 7 Aug 2003 03:19:22 +0000 (20:19 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Thu, 7 Aug 2003 03:19:22 +0000 (20:19 -0700)
 * the usual pile of tv card database updates.
 * various signed/unsigned fixups (fix gcc 3.3 warnings)
   and releated cleanups (use ARRAY_SIZE macro, ...).
 * moved some code which can be shared with the new,
   upcoming cx2388x driver to a separate module.
 * split the irq handler into smaller functions.
 * some new features (field rate capture support for example).
 * simplified i2c code a bit by removing redundant
   bookkeeping of attached i2c clients.
 * merged i2c changes back into my tree, there are some no-op
   changes due to this.
 * various other bugfixes.
 * fix build failure with CONFIG_FW_LOADER enabled

drivers/media/video/Makefile
drivers/media/video/bt848.h
drivers/media/video/btcx-risc.c [new file with mode: 0644]
drivers/media/video/btcx-risc.h [new file with mode: 0644]
drivers/media/video/bttv-cards.c
drivers/media/video/bttv-driver.c
drivers/media/video/bttv-if.c
drivers/media/video/bttv-risc.c
drivers/media/video/bttv-vbi.c
drivers/media/video/bttv.h
drivers/media/video/bttvp.h

index be73952e187beffa909fd00b02df4f9090ec6800..4b853d292d055b0fbfba56bb6abb4f84cbc33e70 100644 (file)
@@ -38,4 +38,4 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
 obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o
 obj-$(CONFIG_VIDEO_BUF)   += video-buf.o
-
+obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
index 7015fd82566c891f10e6847f45cf1fb192782a53..529f394d72409e7a21661aac1a872895f22b7b60 100644 (file)
 #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)
 
 /* WRITE and SKIP */
 /* disable which bytes of each DWORD */
-#define BT848_RISC_BYTE0       (1<<12)
-#define BT848_RISC_BYTE1       (1<<13)
-#define BT848_RISC_BYTE2       (1<<14)
-#define BT848_RISC_BYTE3       (1<<15)
-#define BT848_RISC_BYTE_ALL    (0x0f<<12)
+#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         (1<<24)
+#define BT848_RISC_IRQ         (1U<<24)
 /* RISC command is last one in this line */
-#define BT848_RISC_EOL         (1<<26)
+#define BT848_RISC_EOL         (1U<<26)
 /* RISC command is first one in this line */
-#define BT848_RISC_SOL         (1<<27)
-
-#define BT848_RISC_WRITE       (0x01<<28)
-#define BT848_RISC_SKIP        (0x02<<28)
-#define BT848_RISC_WRITEC      (0x05<<28)
-#define BT848_RISC_JUMP        (0x07<<28)
-#define BT848_RISC_SYNC        (0x08<<28)
+#define BT848_RISC_SOL         (1U<<27)
 
-#define BT848_RISC_WRITE123    (0x09<<28)
-#define BT848_RISC_SKIP123     (0x0a<<28)
-#define BT848_RISC_WRITE1S23   (0x0b<<28)
+#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 !! */
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
new file mode 100644 (file)
index 0000000..e84fed4
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+    btcx-risc.c
+
+    bt848/bt878/cx2388x risc code generator.
+
+    (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+    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/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "btcx-risc.h"
+
+MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug = 0;
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
+
+/* ---------------------------------------------------------- */
+/* allocate/free risc memory                                  */
+
+static int memcnt;
+
+int btcx_riscmem_alloc(struct pci_dev *pci,
+                      struct btcx_riscmem *risc,
+                      unsigned int size)
+{
+       u32 *cpu;
+       dma_addr_t dma;
+       
+       cpu = pci_alloc_consistent(pci, size, &dma);
+       if (NULL == cpu)
+               return -ENOMEM;
+       memset(cpu,0,size);
+
+#if 0
+       if (risc->cpu && risc->size < size) {
+               /* realloc (enlarge buffer) -- copy old stuff */
+               memcpy(cpu,risc->cpu,risc->size);
+               btcx_riscmem_free(pci,risc);
+       }
+#else
+       BUG_ON(NULL != risc->cpu);
+#endif
+       risc->cpu  = cpu;
+       risc->dma  = dma;
+       risc->size = size;
+
+       if (debug) {
+               memcnt++;
+               printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
+       }
+
+       return 0;
+}
+
+void btcx_riscmem_free(struct pci_dev *pci,
+                      struct btcx_riscmem *risc)
+{
+       if (NULL == risc->cpu)
+               return;
+       pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+       memset(risc,0,sizeof(*risc));
+       if (debug) {
+               memcnt--;
+               printk("btcx: riscmem free [%d]\n",memcnt);
+       }
+}
+
+/* ---------------------------------------------------------- */
+/* screen overlay helpers                                     */
+
+int
+btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+                 struct v4l2_clip *clips, unsigned int n)
+{
+       if (win->left < 0) {
+               /* left */
+               clips[n].c.left = 0;
+               clips[n].c.top = 0;
+               clips[n].c.width  = -win->left;
+               clips[n].c.height = win->height;
+               n++;
+       }
+       if (win->left + win->width > swidth) {
+               /* right */
+               clips[n].c.left   = swidth - win->left;
+               clips[n].c.top    = 0;
+               clips[n].c.width  = win->width - clips[n].c.left;
+               clips[n].c.height = win->height;
+               n++;
+       }
+       if (win->top < 0) {
+               /* top */
+               clips[n].c.left = 0;
+               clips[n].c.top = 0;
+               clips[n].c.width  = win->width;
+               clips[n].c.height = -win->top;
+               n++;
+       }
+       if (win->top + win->height > sheight) {
+               /* bottom */
+               clips[n].c.left = 0;
+               clips[n].c.top = sheight - win->top;
+               clips[n].c.width  = win->width;
+               clips[n].c.height = win->height - clips[n].c.top;
+               n++;
+       }
+       return n;
+}
+
+int
+btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
+{
+       s32 nx,nw,dx;
+       unsigned int i;
+
+       /* fixup window */
+       nx = (win->left + mask) & ~mask;
+       nw = (win->width) & ~mask;
+       if (nx + nw > win->left + win->width)
+               nw -= mask+1;
+       dx = nx - win->left;
+       win->left  = nx;
+       win->width = nw;
+       if (debug)
+               printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
+                      win->width, win->height, win->left, win->top, dx);
+
+       /* fixup clips */
+       for (i = 0; i < n; i++) {
+               nx = (clips[i].c.left-dx) & ~mask;
+               nw = (clips[i].c.width) & ~mask;
+               if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
+                       nw += mask+1;
+               clips[i].c.left  = nx;
+               clips[i].c.width = nw;
+               if (debug)
+                       printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
+                              clips[i].c.width, clips[i].c.height,
+                              clips[i].c.left, clips[i].c.top);
+       }
+       return 0;
+}
+
+void
+btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
+{
+       struct v4l2_clip swap;
+       int i,j,n;
+
+       if (nclips < 2)
+               return;
+       for (i = nclips-2; i >= 0; i--) {
+               for (n = 0, j = 0; j <= i; j++) {
+                       if (clips[j].c.left > clips[j+1].c.left) {
+                               swap = clips[j];
+                               clips[j] = clips[j+1];
+                               clips[j+1] = swap;
+                               n++;
+                       }
+               }
+               if (0 == n)
+                       break;
+       }
+}
+
+void
+btcx_calc_skips(int line, int width, unsigned int *maxy,
+               struct btcx_skiplist *skips, unsigned int *nskips,
+               const struct v4l2_clip *clips, unsigned int nclips)
+{
+       unsigned int clip,skip;
+       int end,maxline;
+       
+       skip=0;
+       maxline = 9999;
+       for (clip = 0; clip < nclips; clip++) {
+
+               /* sanity checks */
+               if (clips[clip].c.left + clips[clip].c.width <= 0)
+                       continue;
+               if (clips[clip].c.left > (signed)width)
+                       break;
+               
+               /* vertical range */
+               if (line > clips[clip].c.top+clips[clip].c.height-1)
+                       continue;
+               if (line < clips[clip].c.top) {
+                       if (maxline > clips[clip].c.top-1)
+                               maxline = clips[clip].c.top-1;
+                       continue;
+               }
+               if (maxline > clips[clip].c.top+clips[clip].c.height-1)
+                       maxline = clips[clip].c.top+clips[clip].c.height-1;
+
+               /* horizontal range */
+               if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
+                       /* new one */
+                       skips[skip].start = clips[clip].c.left;
+                       if (skips[skip].start < 0)
+                               skips[skip].start = 0;
+                       skips[skip].end = clips[clip].c.left + clips[clip].c.width;
+                       if (skips[skip].end > width)
+                               skips[skip].end = width;
+                       skip++;
+               } else {
+                       /* overlaps -- expand last one */
+                       end = clips[clip].c.left + clips[clip].c.width;
+                       if (skips[skip-1].end < end)
+                               skips[skip-1].end = end;
+                       if (skips[skip-1].end > width)
+                               skips[skip-1].end = width;
+               }
+       }
+       *nskips = skip;
+       *maxy = maxline;
+
+       if (debug) {
+               printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
+               for (skip = 0; skip < *nskips; skip++) {
+                       printk(" %d-%d",skips[skip].start,skips[skip].end);
+               }
+               printk("\n");
+       }
+}
+
+/* ---------------------------------------------------------- */
+
+EXPORT_SYMBOL(btcx_riscmem_alloc);
+EXPORT_SYMBOL(btcx_riscmem_free);
+
+EXPORT_SYMBOL(btcx_screen_clips);
+EXPORT_SYMBOL(btcx_align);
+EXPORT_SYMBOL(btcx_sort_clips);
+EXPORT_SYMBOL(btcx_calc_skips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h
new file mode 100644 (file)
index 0000000..49daaad
--- /dev/null
@@ -0,0 +1,33 @@
+
+struct btcx_riscmem {
+       unsigned int   size;
+       u32            *cpu;
+       u32            *jmp;
+       dma_addr_t     dma;
+};
+
+struct btcx_skiplist {
+       int start;
+       int end;
+};
+
+int  btcx_riscmem_alloc(struct pci_dev *pci,
+                       struct btcx_riscmem *risc,
+                       unsigned int size);
+void btcx_riscmem_free(struct pci_dev *pci,
+                      struct btcx_riscmem *risc);
+
+int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+                     struct v4l2_clip *clips, unsigned int n);
+int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
+              unsigned int n, int mask);
+void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
+void btcx_calc_skips(int line, int width, unsigned int *maxy,
+                    struct btcx_skiplist *skips, unsigned int *nskips,
+                    const struct v4l2_clip *clips, unsigned int nclips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index 49dcf9365275e02278bde9f3712bab1fda361217..c61cd8a76a366799512dddaae915d5732ab5b990 100644 (file)
 */
 
 #include <linux/version.h>
+#include <linux/config.h>
 #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 <asm/io.h>
 
@@ -56,32 +58,34 @@ static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
 static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
 static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set);
 static void windvr_audio(struct bttv *btv, struct video_audio *v, int set);
+static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set);
 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 int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
-int is_MM20xPCTV(unsigned char eeprom_data[256]);
-
+static void identify_by_eeprom(struct bttv *btv,
+                              unsigned char eeprom_data[256]);
 
 /* config variables */
-static int triton1=0;
-static int vsfx=0;
-static int no_overlay=-1;
-static int latency = -1;
-
-static unsigned int card[BTTV_MAX]  = { [ 0 ... (BTTV_MAX-1) ] = -1};
-static unsigned int pll[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = -1};
-static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = -1};
+static unsigned int triton1=0;
+static unsigned int vsfx=0;
+static unsigned int latency = UNSET;
+unsigned 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};
 #ifdef MODULE
 static unsigned int autoload = 1;
 #else
 static unsigned int autoload = 0;
 #endif
-static unsigned int gpiomask = -1;
-static unsigned int audioall = -1;
-static unsigned int audiomux[5] = { -1, -1, -1, -1, -1 };
+static unsigned int gpiomask = UNSET;
+static unsigned int audioall = UNSET;
+static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
 
 /* insmod options */
 MODULE_PARM(triton1,"i");
@@ -150,13 +154,16 @@ static struct CARD {
        { 0x6606107d, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
        { 0x6607107d, BTTV_WINFAST2000,   "Leadtek WinFast VC 100" },
        { 0x263610b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
+       { 0x264510b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
        { 0x402010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
        { 0x405010fc, BTTV_GVBCTV4PCI,    "I-O Data Co. GV-BCTV4/PCI" },
        { 0x407010fc, BTTV_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
 
-       { 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV" },
        { 0x001211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
        { 0x001c11bd, BTTV_PINNACLESAT,   "Pinnacle PCTV Sat" },
+       // some cards ship with byteswapped IDs ...
+       { 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
+       { 0xff00bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
 
        { 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
        { 0x3060121a, BTTV_STB2,          "3Dfx VoodooTV 100/ STB OEM" },
@@ -164,6 +171,7 @@ static struct CARD {
        { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
        { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
        { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+       { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" },
        
        { 0x00011461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
        { 0x00021461, BTTV_AVERMEDIA98,   "AVermedia TVCapture 98" },
@@ -193,6 +201,30 @@ static struct CARD {
        { 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
        { 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
 
+       { 0x1430aa00, BTTV_PV143,         "Provideo PV143A" },
+       { 0x1431aa00, BTTV_PV143,         "Provideo PV143B" },
+       { 0x1432aa00, BTTV_PV143,         "Provideo PV143C" },
+       { 0x1433aa00, BTTV_PV143,         "Provideo PV143D" },
+
+       { 0x1460aa00, BTTV_PV150,         "Provideo PV150A-1" },
+       { 0x1461aa01, BTTV_PV150,         "Provideo PV150A-2" },
+       { 0x1462aa02, BTTV_PV150,         "Provideo PV150A-3" },
+       { 0x1463aa03, BTTV_PV150,         "Provideo PV150A-4" },
+
+       { 0x1464aa04, BTTV_PV150,         "Provideo PV150B-1" },
+       { 0x1465aa05, BTTV_PV150,         "Provideo PV150B-2" },
+       { 0x1466aa06, BTTV_PV150,         "Provideo PV150B-3" },
+       { 0x1467aa07, BTTV_PV150,         "Provideo PV150B-4" },
+
+
+       { 0xa1550000, BTTV_IVC200,        "IVC-200" },
+       { 0xa1550001, BTTV_IVC200,        "IVC-200" },
+       { 0xa1550002, BTTV_IVC200,        "IVC-200" },
+       { 0xa1550003, BTTV_IVC200,        "IVC-200" },  
+
+       { 0x41424344, BTTV_GRANDTEC,      "GrandTec Multi Capture" },
+       { 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
+       
        { 0x010115cb, BTTV_GMV1,          "AG GMV1" },
        { 0x010114c7, BTTV_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
        { 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
@@ -203,8 +235,11 @@ static struct CARD {
        { 0x03116000, BTTV_SENSORAY311,   "Sensoray 311" },
        { 0x00790e11, BTTV_WINDVR,        "Canopus WinDVR PCI" },
        { 0xa0fca1a0, BTTV_ZOLTRIX,       "Face to Face Tvmax" },
-       { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+       { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
 
+       // likely broken, vendor id doesn't match the other magic views ...
+       //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+       
        { 0, -1, NULL }
 };
 
@@ -308,7 +343,7 @@ struct tvcard bttv_tvcards[] = {
 },{
 
 /* ---- card 0x08 ---------------------------------- */
-       .name           = "Lifeview FlyVideo II (Bt848) LR26",
+       .name           = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26",
        .video_inputs   = 4,
        .audio_inputs   = 1,
        .tuner          = 0,
@@ -377,6 +412,7 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 2, 3, 1, 1},
        .audiomux       = { 13, 14, 11, 7, 0, 0},
        .needs_tvaudio  = 1,
+       .msp34xx_alt    = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
 },{
@@ -614,7 +650,7 @@ struct tvcard bttv_tvcards[] = {
        .pll            = PLL_28,
        .tuner_type     = -1,
 },{
-       .name           = "Formac iProTV",
+       .name           = "Formac iProTV, Formac ProTV I (bt848)",
        .video_inputs   = 4,
        .audio_inputs   = 1,
        .tuner          = 0,
@@ -722,7 +758,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
-       .tuner_type     = -1,
+       .tuner_type     = 1,
 },{
        .name           = "Pinnacle PCTV Studio/Rave",
        .video_inputs   = 3,
@@ -764,6 +800,7 @@ struct tvcard bttv_tvcards[] = {
        .pll            = PLL_28,
        .tuner_type     = -1,
        .has_radio      = 1,
+       .audio_hook     = avermedia_tvphone_audio,
 },{
        .name           = "ProVideo PV951", /* pic16c54 */
        .video_inputs   = 3,
@@ -905,10 +942,10 @@ struct tvcard bttv_tvcards[] = {
 /* ---- card 0x34 ---------------------------------- */
        /* David Härdeman <david@2gen.com> */
        .name           = "Pinnacle PCTV Studio Pro",
-       .video_inputs   = 3,
+       .video_inputs   = 4,
        .audio_inputs   = 1,
        .tuner          = 0,
-       .svhs           = 2,
+       .svhs           = 3,
        .gpiomask       = 0x03000F,
        .muxsel         = { 2, 3, 1, 1},
        .audiomux       = { 1, 0xd0001, 0, 0, 10},
@@ -1532,11 +1569,13 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
        .no_tda7432     = 1,   
+       .gpiomask       = 0x01,
+       .audiomux       = { 0, 0, 0, 0, 1 },
        .muxsel         = { 3, 0, 1, 2},
        .needs_tvaudio  = 0, 
        .pll            = PLL_28,
 },{
-        .name           = "Formac ProTV II",
+        .name           = "Formac ProTV II (bt878)",
         .video_inputs   = 4,
         .audio_inputs   = 1,
         .tuner          = 0,
@@ -1555,8 +1594,8 @@ struct tvcard bttv_tvcards[] = {
         not soldered here, though unknown wiring.
          Card lacks: external audio in, pci subsystem id.
        */
-
 },{
+
        /* ---- card 0x60 ---------------------------------- */
        .name           = "MachTV",
         .video_inputs   = 3,
@@ -1581,9 +1620,190 @@ struct tvcard bttv_tvcards[] = {
        .no_tda7432     = 1,
        .muxsel         = { 2, 0, 1},
        .pll            = PLL_28,
+},{
+       /* Luc Van Hoeylandt <luc@e-magic.be> */
+       .name           = "ProVideo PV150", /* 0x4f */
+       .video_inputs   = 2,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .gpiomask       = 0,
+       .muxsel         = { 2, 3 },
+       .audiomux       = { 0 },
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+},{
+       /* Hiroshi Takekawa <sian@big.or.jp> */
+       /* This card lacks subsystem ID */
+       .name           = "AD-TVK503", /* 0x63 */
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x001e8007,
+       .muxsel         = { 2, 3, 1, 0 },
+       /*                  Tuner, Radio, external, internal, off,  on */
+       .audiomux       = { 0x08,  0x0f,  0x0a,     0x08,     0x0f, 0x08 },
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = 2,
+       .audio_hook     = adtvk503_audio,
+},{
+
+       /* ---- card 0x64 ---------------------------------- */
+        .name           = "Hercules Smart TV Stereo",
+        .video_inputs   = 4,
+        .audio_inputs   = 1,
+        .tuner          = 0,
+        .svhs           = 2,
+        .gpiomask       = 0x00,
+        .muxsel         = { 2, 3, 1, 1 },
+        .needs_tvaudio  = 1,
+        .no_msp34xx     = 1,
+        .pll            = PLL_28,
+        .tuner_type     = 5,
+       /* 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
+       */
+},{
+        .name           = "Pace TV & Radio Card",
+        .video_inputs   = 4,
+        .audio_inputs   = 1,
+        .tuner          = 0,
+        .svhs           = 2,
+        .muxsel         = { 2, 3, 1, 1}, // Tuner, CVid, SVid, CVid over SVid connector
+        .gpiomask       = 0,
+        .no_tda9875     = 1,
+        .no_tda7432     = 1,
+        .tuner_type     = 1,
+        .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!
+},{
+        /* Chris Willing <chris@vislab.usyd.edu.au> */
+        .name           = "IVC-200",
+        .video_inputs   = 1,
+        .audio_inputs   = 0,
+        .tuner          = -1,
+        .tuner_type     = -1,
+        .svhs           = -1,
+        .gpiomask       = 0xdf,
+        .muxsel         = { 2 },
+        .pll            = PLL_28,
+},{
+       .name           = "Grand X-Guard / Trust 814PCI",
+       .video_inputs   = 16,
+        .audio_inputs   = 0,
+        .tuner          = -1,
+        .svhs           = -1,
+       .tuner_type     = 4,
+        .gpiomask2      = 0xff,
+       .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_tda9875     = 1,
+        .no_tda7432     = 1,
+       .pll            = PLL_28,
+},{
+
+       /* ---- card 0x68 ---------------------------------- */
+       .name           = "Nebula Electronics DigiTV",
+       .video_inputs   = 0,
+       .audio_inputs   = 0,
+       .svhs           = -1,
+       .muxsel         = { 2, 3, 1, 0},
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+},{
+       /* Jorge Boncompte - DTI2 <jorge@dti2.net> */
+       .name           = "ProVideo PV143",
+        .video_inputs   = 4,
+        .audio_inputs   = 0,
+        .tuner          = -1,
+        .svhs           = -1,
+        .gpiomask       = 0,
+        .muxsel         = { 2, 3, 1, 0 },
+        .audiomux       = { 0 },
+        .needs_tvaudio  = 0,
+        .no_msp34xx     = 1,
+        .pll            = PLL_28,
+        .tuner_type     = -1,
+},{
+       /* M.Klahr@phytec.de */
+       .name           = "PHYTEC VD-009-X1 MiniDIN (bt878)",
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1, /* card has no tuner */
+       .svhs           = 3,
+       .gpiomask       = 0x00, 
+       .muxsel         = { 2, 3, 1, 0},
+       .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+},{
+       .name           = "PHYTEC VD-009-X1 Combi (bt878)",
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1, /* card has no tuner */
+       .svhs           = 3,
+       .gpiomask       = 0x00,
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+},{
+
+       /* ---- card 0x6c ---------------------------------- */
+       .name           = "PHYTEC VD-009 MiniDIN (bt878)",
+       .video_inputs   = 10,
+       .audio_inputs   = 0,
+       .tuner          = -1, /* card has no tuner */
+       .svhs           = 9,
+       .gpiomask       = 0x00,
+       .gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
+                                  via the upper nibble of muxsel. here: used for
+                                  xternal video-mux */
+       .muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
+       .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+},{
+       .name           = "PHYTEC VD-009 Combi (bt878)",
+       .video_inputs   = 10,
+       .audio_inputs   = 0,
+       .tuner          = -1, /* card has no tuner */
+       .svhs           = 9,
+       .gpiomask       = 0x00,
+       .gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
+                                  via the upper nibble of muxsel. here: used for
+                                  xternal video-mux */
+       .muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
+       .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
 }};
 
-const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
+const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
 
 /* ----------------------------------------------------------------------- */
 
@@ -1615,19 +1835,21 @@ void __devinit bttv_idcard(struct bttv *btv)
                        printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
                               "PCI subsystem ID is %04x:%04x\n",
                               btv->nr,cards[type].name,cards[type].cardnr,
-                              btv->cardid & 0xffff, btv->cardid >> 16);
+                              btv->cardid & 0xffff,
+                              (btv->cardid >> 16) & 0xffff);
                        btv->type = cards[type].cardnr;
                } else {
                        /* 404 */
                        printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
-                              btv->nr, btv->cardid&0xffff, btv->cardid>>16);
+                              btv->nr, btv->cardid & 0xffff,
+                              (btv->cardid >> 16) & 0xffff);
                        printk(KERN_DEBUG "please mail id, board name and "
                               "the correct card= insmod option to kraxel@bytesex.org\n");
                }
        } 
 
        /* let the user override the autodetected type */
-       if (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards)
+       if (card[btv->nr] < bttv_num_tvcards)
                btv->type=card[btv->nr];
        
        /* print which card config we are using */
@@ -1637,14 +1859,14 @@ void __devinit bttv_idcard(struct bttv *btv)
                bttv_tvcards[btv->type].name);
        printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr,
               btv->video_dev.name,btv->type,
-              (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
-              "insmod option" : "autodetected");
+              card[btv->nr] < bttv_num_tvcards
+              ? "insmod option" : "autodetected");
 
        /* overwrite gpio stuff ?? */
-       if (-1 == audioall && -1 == audiomux[0])
+       if (UNSET == audioall && UNSET == audiomux[0])
                return;
 
-       if (-1 != audiomux[0]) {
+       if (UNSET != audiomux[0]) {
                gpiobits = 0;
                for (i = 0; i < 5; i++) {
                        bttv_tvcards[btv->type].audiomux[i] = audiomux[i];
@@ -1656,7 +1878,7 @@ void __devinit bttv_idcard(struct bttv *btv)
                        bttv_tvcards[btv->type].audiomux[i] = audioall;
                }
        }
-       bttv_tvcards[btv->type].gpiomask = (-1 != gpiomask) ? gpiomask : gpiobits;
+       bttv_tvcards[btv->type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
        printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
               btv->nr,bttv_tvcards[btv->type].gpiomask);
        for (i = 0; i < 5; i++) {
@@ -1670,13 +1892,22 @@ void __devinit bttv_idcard(struct bttv *btv)
  */
 
 /* Some Modular Technology cards have an eeprom, but no subsystem ID */
-int is_MM20xPCTV(unsigned char eeprom_data[256])
+void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
 {
-       if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13)) {
-               printk("bttv: GET.MM20xPCTV found\n");
-               return 1; // found
+       int type = -1;
+       
+       if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13))
+               type = BTTV_MODTEC_205;
+       else if (0 == strncmp(eeprom_data+20,"Picolo",7))
+               type = BTTV_EURESYS_PICOLO;
+       else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0)
+                type = BTTV_HAUPPAUGE; /* old bt848 */
+
+       if (-1 != type) {
+               btv->type = type;
+               printk("bttv%d: detected by eeprom: %s [card=%d]\n",
+                      btv->nr, bttv_tvcards[btv->type].name, btv->type);
        }
-       return 0;
 }
 
 static void flyvideo_gpio(struct bttv *btv)
@@ -1780,7 +2011,8 @@ static void miro_pinnacle_gpio(struct bttv *btv)
                        if (btv->type == BTTV_PINNACLE)
                                btv->type = BTTV_PINNACLEPRO;
                }
-               printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+               printk(KERN_INFO
+                      "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
                       btv->nr, id+1, btv->tuner_type,
                       !btv->has_radio ? "no" :
                       (btv->has_matchbox ? "matchbox" : "fmtuner"),
@@ -1814,13 +2046,13 @@ static void miro_pinnacle_gpio(struct bttv *btv)
                        info = "oops: unknown card";
                        break;
                }
+               if (-1 != msp)
+                       btv->type = BTTV_PINNACLEPRO;
                printk(KERN_INFO
                       "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
                       btv->nr, id, info, btv->has_radio ? "yes" : "no");
-               btv->tuner_type = 33;
-               if (autoload)
-                       request_module("tda9887");
-               bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,&id);
+               btv->tuner_type  = 33;
+               btv->pinnacle_id = id;
        }
 }
 
@@ -1886,6 +2118,9 @@ void __devinit bttv_init_card1(struct bttv *btv)
        case BTTV_VOODOOTV_FM:
                 boot_msp34xx(btv,20);
                break;
+       case BTTV_AVERMEDIA98:
+               boot_msp34xx(btv,11);
+               break;
        case BTTV_HAUPPAUGEPVR:
                pvr_boot(btv);
                break;
@@ -1898,13 +2133,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
         btv->tuner_type = -1;
 
        if (BTTV_UNKNOWN == btv->type) {
-               printk("bttv%d: Looking for eeprom\n",btv->nr);
                bttv_readee(btv,eeprom_data,0xa0);
-                if(is_MM20xPCTV(eeprom_data)) {
-                        btv->type = BTTV_MODTEC_205;
-                       printk("bttv%d: Autodetect by eeprom:(%s) [card=%d]\n",
-                              btv->nr, bttv_tvcards[btv->type].name, btv->type);
-               }
+               identify_by_eeprom(btv,eeprom_data);
        }
 
        switch (btv->type) {
@@ -2028,18 +2258,20 @@ void __devinit bttv_init_card2(struct bttv *btv)
        btv->pll.pll_current = -1;
 
        /* tuner configuration (from card list / autodetect / insmod option) */
-       if (-1 != bttv_tvcards[btv->type].tuner_type)
-               if( -1 == btv->tuner_type) 
+       if (UNSET != bttv_tvcards[btv->type].tuner_type)
+               if(UNSET == btv->tuner_type) 
                        btv->tuner_type = bttv_tvcards[btv->type].tuner_type;
-       if (-1 != tuner[btv->nr])
+       if (UNSET != tuner[btv->nr])
                btv->tuner_type = tuner[btv->nr];
-       if (btv->tuner_type != -1)
-               bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
        printk("bttv%d: using tuner=%d\n",btv->nr,btv->tuner_type);
+       if (btv->pinnacle_id != UNSET)
+               bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
+                                     &btv->pinnacle_id);
+       if (btv->tuner_type != UNSET)
+               bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
 
        if (bttv_tvcards[btv->type].has_radio)
                btv->has_radio=1;
-
        if (bttv_tvcards[btv->type].audio_hook)
                btv->audio_hook=bttv_tvcards[btv->type].audio_hook;
 
@@ -2057,6 +2289,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
                        request_module("msp3400");
        }
 
+       if (bttv_tvcards[btv->type].msp34xx_alt &&
+           bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) {
+               if (autoload)
+                       request_module("msp3400");
+       }
+
        if (!bttv_tvcards[btv->type].no_tda9875 &&
            bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
                if (autoload)
@@ -2074,7 +2312,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
                        request_module("tvaudio");
        }
 
-       if (bttv_tvcards[btv->type].tuner != -1) {
+       /* tuner modules */
+       if (btv->pinnacle_id != UNSET) {
+               if (autoload)
+                       request_module("tda9887");
+       }
+       if (btv->tuner_type != UNSET) {
                if (autoload)
                        request_module("tuner");
        }
@@ -2137,9 +2380,9 @@ hauppauge_tuner[] __devinitdata =
         { TUNER_TEMIC_4046FM5,     "Temic 4046FM5" },
        { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
        { TUNER_ABSENT,        "Philips TD1536D_FH_44"},
-       { TUNER_LG_NTSC_FM,    "LG TP18NSR01F"},
-       { TUNER_LG_PAL_FM,     "LG TP18PSB01D"},
-       { TUNER_LG_PAL,        "LG TP18PSB11D"},        
+       { TUNER_LG_NTSC_FM,    "LG TPI8NSR01F"},
+       { TUNER_LG_PAL_FM,     "LG TPI8PSB01D"},
+       { TUNER_LG_PAL,        "LG TPI8PSB11D"},        
        { TUNER_LG_PAL_I_FM,   "LG TAPC-I001D"},
        { TUNER_LG_PAL_I,      "LG TAPC-I701D"}
 };
@@ -2148,15 +2391,17 @@ 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;
-               printk("bttv Modtec: Tuner autodetected %s\n",&eeprom_data[0x1e]);
+               printk("bttv Modtec: Tuner autodetected %s\n",
+                      &eeprom_data[0x1e]);
+       } else {
+               printk("bttv Modtec: Unknown TunerString:%s\n",
+                      &eeprom_data[0x1e]);
        }
-       else
-               printk("bttv Modtec: Unknown TunerString:%s\n",&eeprom_data[0x1e]);
 }
 
 static void __devinit hauppauge_eeprom(struct bttv *btv)
 {
-       int blk2,tuner,radio,model;
+       unsigned int blk2,tuner,radio,model;
 
        if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
                printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
@@ -2170,9 +2415,8 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
        tuner = eeprom_data[9];
        radio = eeprom_data[blk2-1] & 0x01;
        
-        if (tuner >= ARRAY_SIZE(hauppauge_tuner))
-               tuner = 0;
-       btv->tuner_type = hauppauge_tuner[tuner].id;
+        if (tuner < ARRAY_SIZE(hauppauge_tuner))
+                btv->tuner_type = hauppauge_tuner[tuner].id;
        if (radio)
                btv->has_radio = 1;
        
@@ -2223,14 +2467,6 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
  * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be
  * unpacked with unzip).
  */
-static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
-MODULE_PARM(firm_altera,"s");
-MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware "
-                "(driver CD => unzip pvr45xxx.exe => hcwamc.rbf)");
-
-/* drivers/sound/sound_firmware.c => soundcore.o */
-extern int mod_firmware_load(const char *fn, char **fp);
-
 #define PVR_GPIO_DELAY         10
 
 #define BTTV_ALT_DATA          0x000001
@@ -2275,6 +2511,16 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
        return 0;
 }
 
+#ifndef CONFIG_FW_LOADER
+/* old 2.4.x way -- via soundcore's mod_firmware_load */
+   
+static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
+MODULE_PARM(firm_altera,"s");
+MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware "
+                "(driver CD => unzip pvr45xxx.exe => hcwamc.rbf)");
+
+extern int mod_firmware_load(const char *fn, char **fp);
+
 int __devinit pvr_boot(struct bttv *btv)
 {
        u32 microlen;
@@ -2282,8 +2528,11 @@ int __devinit pvr_boot(struct bttv *btv)
        int result;
 
        microlen = mod_firmware_load(firm_altera, (char**) &micro);
-       if (!microlen)
+       if (!microlen) {
+               printk(KERN_WARNING "bttv%d: altera firmware not found [%s]\n",
+                      btv->nr, firm_altera);
                return -1;
+       }
        
        printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n",
               btv->nr, firm_altera);
@@ -2293,6 +2542,28 @@ int __devinit pvr_boot(struct bttv *btv)
        vfree(micro);
        return result;
 }
+#else
+/* new 2.5.x way -- via hotplug firmware loader */
+
+int __devinit pvr_boot(struct bttv *btv)
+{
+        const struct firmware *fw_entry;
+       struct device *dev = &btv->dev->dev;
+       int rc;
+
+       rc = request_firmware(&fw_entry, "hcwamc.rbf", dev);
+       if (rc != 0) {
+               printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
+                      btv->nr);
+                return rc;
+        }
+       rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
+       printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
+              btv->nr, (rc < 0) ? "failed" : "ok");
+        release_firmware(fw_entry);
+       return rc;
+}      
+#endif
 
 /* ----------------------------------------------------------------------- */
 /* some osprey specific stuff                                              */
@@ -2541,8 +2812,10 @@ 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 };
-       int i,tmp;
-
+       unsigned int i;
+       int tmp;
+       u32 val;
+       
        /* Initialise GPIO-connevted stuff */
        btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */
        btwrite(0,BT848_GPIO_DATA);
@@ -2561,6 +2834,7 @@ static void __devinit init_PXC200(struct bttv *btv)
            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 */
@@ -2572,16 +2846,36 @@ static void __devinit init_PXC200(struct bttv *btv)
         *      same chips - but the R/W bit is included in the address
         *      argument so the numbers are different */
        
+
        printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
 
-       for (i = 0; i < sizeof(vals)/sizeof(int); i++) {
-               tmp=bttv_I2CWrite(btv,0x1E,vals[i],0,1);
-               printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",
-                      tmp,bttv_I2CRead(btv,0x1F,NULL));
+       /* 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? */
+       btwrite( (1<<2), BT848_GPIO_OUT_EN); /* only the reset pin */
+       btwrite(0, BT848_GPIO_DATA);
+       udelay(10);
+       btwrite(1<<2, BT848_GPIO_DATA);
+
+               for (i = 0; i < ARRAY_SIZE(vals); i++) {
+               tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
+               if (tmp != -1) {
+                       printk(KERN_INFO
+                              "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+                              vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
+               }
        }
+
        printk(KERN_INFO "PXC200 Initialised.\n");
 }
 
+
 /* ----------------------------------------------------------------------- */
 /* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
 /*
@@ -2671,8 +2965,8 @@ int bus_in(struct bttv *btv, int bit)
 /* Low-level stuff */
 static int tea5757_read(struct bttv *btv)
 {
-       int value = 0;
        unsigned long timeout;
+       int value = 0;
        int i;
        
        /* better safe than sorry */
@@ -2755,12 +3049,13 @@ static int tea5757_write(struct bttv *btv, int value)
 
 void tea5757_set_freq(struct bttv *btv, unsigned short freq)
 {
-       int value;
-       
        dprintk("tea5757_set_freq %d\n",freq);
        tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
+#if 0
+       /* breaks Miro PCTV */
        value = tea5757_read(btv);
-       dprintk("bttv%d: tea5757 readback =0x%x\n",btv->nr,value);
+       dprintk("bttv%d: tea5757 readback=0x%x\n",btv->nr,value);
+#endif
 }
 
 
@@ -3052,6 +3347,38 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set)
         }
 }
 
+/*
+ * sound control for AD-TVK503
+ * Hiroshi Takekawa <sian@big.or.jp>
+ */
+static void
+adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+       unsigned int con = 0xffffff;
+
+       //btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN);
+
+       if (set) {
+               //btor(***, BT848_GPIO_OUT_EN);
+               if (v->mode & VIDEO_SOUND_LANG1)
+                       con = 0x00000000;
+               if (v->mode & VIDEO_SOUND_LANG2)
+                       con = 0x00180000;
+               if (v->mode & VIDEO_SOUND_STEREO)
+                       con = 0x00000000;
+               if (v->mode & VIDEO_SOUND_MONO)
+                       con = 0x00060000;
+               if (con != 0xffffff) {
+                       btaor(con, ~0x1e0000, BT848_GPIO_DATA);
+                       if (bttv_gpio)
+                               bttv_gpio_tracking(btv, "adtvk503");
+               }
+       } else {
+               v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+                         VIDEO_SOUND_LANG1  | VIDEO_SOUND_LANG2;
+       }
+}
+
 /* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
  *
  * This is needed because rv605 don't use a normal multiplex, but a crosspoint
@@ -3092,6 +3419,34 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input)
        mdelay(1);
 }
 
+// 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,
+       };
+        btwrite(masks[input%16], BT848_GPIO_DATA);
+}
 
 /* ----------------------------------------------------------------------- */
 /* motherboard chipset specific stuff                                      */
@@ -3123,12 +3478,12 @@ void __devinit bttv_check_chipset(void)
                printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
        if (pcipci_fail) {
                printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
-               if (-1 == no_overlay) {
+               if (UNSET == no_overlay) {
                        printk(KERN_WARNING "bttv: going to disable overlay.\n");
                        no_overlay = 1;
                }
        }
-       if (-1 != latency)
+       if (UNSET != latency)
                printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
 
        while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
@@ -3145,7 +3500,7 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
 {
        unsigned char command;
 
-       if (!triton1 && !vsfx && -1 == latency)
+       if (!triton1 && !vsfx && UNSET == latency)
                return 0;
 
        if (bttv_verbose) {
@@ -3153,7 +3508,7 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
                        printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->nr);
                if (vsfx && btv->id >= 878)
                        printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->nr);
-               if (-1 != latency)
+               if (UNSET != latency)
                        printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
                               btv->nr,latency);
        }
@@ -3171,7 +3526,7 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
                        command |= BT878_EN_VSFX;
                 pci_write_config_byte(btv->dev, BT878_DEVCTRL, command);
         }
-       if (-1 != latency)
+       if (UNSET != latency)
                pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency);
        return 0;
 }
index dd30db9c26519516fa2ace6cb1523f90b61aeb50..a7f672037ac799aed6314bf707bcae1132838dac 100644 (file)
@@ -24,7 +24,6 @@
 */
 
 #include <linux/init.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/kdev_t.h>
 
 #include <asm/io.h>
+#include <asm/byteorder.h>
 
 #include "bttvp.h"
 
-int bttv_num;                  /* number of Bt848s in use */
+unsigned int bttv_num;                 /* number of Bt848s in use */
 struct bttv bttvs[BTTV_MAX];
 
 unsigned int bttv_debug = 0;
@@ -46,12 +46,12 @@ unsigned int bttv_verbose = 1;
 unsigned int bttv_gpio = 0;
 
 /* config variables */
-#if defined(__sparc__) || defined(__powerpc__) || defined(__hppa__)
+#ifdef __BIG_ENDIAN
 static unsigned int bigendian=1;
 #else
 static unsigned int bigendian=0;
 #endif
-static unsigned int radio[4];
+static unsigned int radio[BTTV_MAX];
 static unsigned int irq_debug = 0;
 static unsigned int gbuffers = 8;
 static unsigned int gbufsize = 0x208000;
@@ -275,9 +275,29 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                .vdelay         = 0x16,
                .vbipack        = 144,
                .sram           = -1,
+       },{
+               /* 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,
        }
 };
-const int BTTV_TVNORMS = (sizeof(bttv_tvnorms)/sizeof(struct bttv_tvnorm));
+const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
 
 /* ----------------------------------------------------------------------- */
 /* bttv format list
@@ -434,7 +454,7 @@ const struct bttv_format bttv_formats[] = {
                .flags    = FORMAT_FLAGS_RAW,
        }
 };
-const int BTTV_FORMATS = (sizeof(bttv_formats)/sizeof(struct bttv_format));
+const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
 
 /* ----------------------------------------------------------------------- */
 
@@ -557,7 +577,7 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
                .type          = V4L2_CTRL_TYPE_BOOLEAN,
        }
 };
-const int BTTV_CTLS = (sizeof(bttv_ctls)/sizeof(struct v4l2_queryctrl));
+const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
 
 /* ----------------------------------------------------------------------- */
 /* resource management                                                     */
@@ -1002,7 +1022,7 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
                break;
 
        case V4L2_CID_AUDIO_MUTE:
-               c->value =  (VIDEO_AUDIO_MUTE == va.flags) ? 1 : 0;
+               c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
                break;
        case V4L2_CID_AUDIO_VOLUME:
                c->value = va.volume;
@@ -1159,7 +1179,7 @@ void bttv_field_count(struct bttv *btv)
 static const struct bttv_format*
 format_by_palette(int palette)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < BTTV_FORMATS; i++) {
                if (-1 == bttv_formats[i].palette)
@@ -1173,7 +1193,7 @@ format_by_palette(int palette)
 static const struct bttv_format*
 format_by_fourcc(int fourcc)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < BTTV_FORMATS; i++) {
                if (-1 == bttv_formats[i].fourcc)
@@ -1195,6 +1215,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
        unsigned long flags;
        int retval = 0;
 
+       dprintk("switch_overlay: enter [new=%p]\n",new);
        if (new)
                new->vb.state = STATE_DONE;
        spin_lock_irqsave(&btv->s_lock,flags);
@@ -1204,8 +1225,12 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
        spin_unlock_irqrestore(&btv->s_lock,flags);
        if (NULL == new)
                free_btres(btv,fh,RESOURCE_OVERLAY);
-       if (NULL != old)
+       if (NULL != old) {
+               dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
                bttv_dma_free(btv, old);
+               kfree(old);
+       }
+       dprintk("switch_overlay: done\n");
        return retval;
 }
 
@@ -1214,7 +1239,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
 
 static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
                               const struct bttv_format *fmt,
-                              int width, int height,
+                              unsigned int width, unsigned int height,
                               enum v4l2_field field)
 {
        int redo_dma_risc = 0;
@@ -1252,13 +1277,6 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
                redo_dma_risc = 1;
        }
 
-#if 0
-       if (STATE_NEEDS_INIT == buf->vb.state) {
-               if (redo_dma_risc)
-                       bttv_dma_free(btv,buf);
-       }
-#endif
-
        /* alloc risc memory */
        if (STATE_NEEDS_INIT == buf->vb.state) {
                redo_dma_risc = 1;
@@ -1334,7 +1352,7 @@ static const char *v4l1_ioctls[] = {
        "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
        "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
        "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*))
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
 
 int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
 {
@@ -1365,7 +1383,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        {
                struct video_tuner *v = arg;
                
-               if (-1 == bttv_tvcards[btv->type].tuner)
+               if (UNSET == bttv_tvcards[btv->type].tuner)
                        return -EINVAL;
                if (v->tuner) /* Only tuner 0 */
                        return -EINVAL;
@@ -1397,38 +1415,39 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
         case VIDIOCGCHAN:
         {
                 struct video_channel *v = arg;
+               unsigned int channel = v->channel;
 
-                if (v->channel >= bttv_tvcards[btv->type].video_inputs)
+                if (channel >= bttv_tvcards[btv->type].video_inputs)
                         return -EINVAL;
                 v->tuners=0;
                 v->flags = VIDEO_VC_AUDIO;
                 v->type = VIDEO_TYPE_CAMERA;
                 v->norm = btv->tvnorm;
-                if(v->channel == bttv_tvcards[btv->type].tuner)  {
+               if (channel == bttv_tvcards[btv->type].tuner)  {
                         strcpy(v->name,"Television");
                         v->flags|=VIDEO_VC_TUNER;
                         v->type=VIDEO_TYPE_TV;
                         v->tuners=1;
-                } else if (v->channel == bttv_tvcards[btv->type].svhs) {
+                } else if (channel == bttv_tvcards[btv->type].svhs) {
                         strcpy(v->name,"S-Video");
                 } else {
-                        sprintf(v->name,"Composite%d",v->channel);
+                        sprintf(v->name,"Composite%d",channel);
                }
                return 0;
         }
         case VIDIOCSCHAN:
         {
                 struct video_channel *v = arg;
+               unsigned int channel = v->channel;
 
-               if (v->channel <  0 ||
-                   v->channel >= bttv_tvcards[btv->type].video_inputs)
+               if (channel >= bttv_tvcards[btv->type].video_inputs)
                        return -EINVAL;
                if (v->norm >= BTTV_TVNORMS)
                        return -EINVAL;
 
                down(&btv->lock);
-               if (v->channel == btv->input &&
-                   v->norm    == btv->tvnorm) {
+               if (channel == btv->input &&
+                   v->norm == btv->tvnorm) {
                        /* nothing to do */
                        up(&btv->lock);
                        return 0;
@@ -1462,9 +1481,9 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        case VIDIOCSAUDIO:
        {
                struct video_audio *v = arg;
+               unsigned int audio = v->audio;
 
-               if(v->audio <  0 ||
-                  v->audio >= bttv_tvcards[btv->type].audio_inputs)
+               if (audio >= bttv_tvcards[btv->type].audio_inputs)
                        return -EINVAL;
 
                down(&btv->lock);
@@ -1483,11 +1502,13 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        case VIDIOC_ENUMSTD:
        {
                struct v4l2_standard *e = arg;
+               unsigned int index = e->index;
                
-               if (e->index < 0 || e->index >= BTTV_TVNORMS)
+               if (index >= BTTV_TVNORMS)
                        return -EINVAL;
                v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
                                         bttv_tvnorms[e->index].name);
+               e->index = index;
                return 0;
        }
        case VIDIOC_G_STD:
@@ -1499,7 +1520,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        case VIDIOC_S_STD:
        {
                v4l2_std_id *id = arg;
-               int i;
+               unsigned int i;
 
                for (i = 0; i < BTTV_TVNORMS; i++)
                        if (*id & bttv_tvnorms[i].v4l2_id)
@@ -1527,7 +1548,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        case VIDIOC_ENUMINPUT:
        {
                struct v4l2_input *i = arg;
-               int n;
+               unsigned int n;
                
                n = i->index;
                if (n >= bttv_tvcards[btv->type].video_inputs)
@@ -1564,9 +1585,9 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        }
        case VIDIOC_S_INPUT:
        {
-               int *i = arg;
+               unsigned int *i = arg;
                
-               if (*i < 0 || *i > bttv_tvcards[btv->type].video_inputs)
+               if (*i > bttv_tvcards[btv->type].video_inputs)
                        return -EINVAL;
                down(&btv->lock);
                set_input(btv,*i);
@@ -1579,7 +1600,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        {
                struct v4l2_tuner *t = arg;
 
-               if (-1 == bttv_tvcards[btv->type].tuner)
+               if (UNSET == bttv_tvcards[btv->type].tuner)
                        return -EINVAL;
                if (0 != t->index)
                        return -EINVAL;
@@ -1587,8 +1608,8 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                memset(t,0,sizeof(*t));
                strcpy(t->name, "Television");
                t->type       = V4L2_TUNER_ANALOG_TV;
-               t->capability = V4L2_TUNER_CAP_NORM;
                t->rangehigh  = 0xffffffffUL;
+               t->capability = V4L2_TUNER_CAP_NORM;
                t->rxsubchans = V4L2_TUNER_SUB_MONO;
                if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
                        t->signal = 0xffff;
@@ -1599,12 +1620,15 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                        bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
                        if (btv->audio_hook)
                                btv->audio_hook(btv,&va,0);
-                       if(va.mode & VIDEO_SOUND_STEREO)
+                       if(va.mode & VIDEO_SOUND_STEREO) {
+                               t->audmode     = V4L2_TUNER_MODE_STEREO;
                                t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-                       if(va.mode & VIDEO_SOUND_LANG1)
-                               t->rxsubchans |= V4L2_TUNER_SUB_LANG1;
-                       if(va.mode & VIDEO_SOUND_LANG2)
-                               t->rxsubchans |= V4L2_TUNER_SUB_LANG2;
+                       }
+                       if(va.mode & VIDEO_SOUND_LANG1) {
+                               t->audmode    = V4L2_TUNER_MODE_LANG1;
+                               t->rxsubchans = V4L2_TUNER_SUB_LANG1
+                                       | V4L2_TUNER_SUB_LANG2;
+                       }
                }
                /* FIXME: fill capability+audmode */
                up(&btv->lock);
@@ -1614,7 +1638,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
        {
                struct v4l2_tuner *t = arg;
 
-               if (-1 == bttv_tvcards[btv->type].tuner)
+               if (UNSET == bttv_tvcards[btv->type].tuner)
                        return -EINVAL;
                if (0 != t->index)
                        return -EINVAL;
@@ -1622,6 +1646,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
                {
                        struct video_audio va;
                        memset(&va, 0, sizeof(struct video_audio));
+                       bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
                        if (t->audmode == V4L2_TUNER_MODE_MONO)
                                va.mode = VIDEO_SOUND_MONO;
                        else if (t->audmode == V4L2_TUNER_MODE_STEREO)
@@ -1676,7 +1701,7 @@ static int verify_window(const struct bttv_tvnorm *tvn,
 {
        enum v4l2_field field;
        int maxw, maxh;
-       
+
        if (win->w.width  < 48 || win->w.height < 32)
                return -EINVAL;
        if (win->clipcount > 2048)
@@ -1705,15 +1730,6 @@ static int verify_window(const struct bttv_tvnorm *tvn,
        if (!fixup && (win->w.width > maxw || win->w.height > maxh))
                return -EINVAL;
 
-       if (1 /* depth < 4bpp */) {
-               /* adjust and align writes */
-               int left     = (win->w.left + 3) & ~3;
-               int width    = win->w.width & ~3;
-               while (left + width > win->w.left + win->w.width)
-                       width -= 4;
-               win->w.left  = left;
-               win->w.width = width;
-       }
        if (win->w.width > maxw)
                win->w.width = maxw;
        if (win->w.height > maxh)
@@ -1728,6 +1744,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
        struct v4l2_clip *clips = NULL;
        int n,size,retval = 0;
 
+       if (NULL == fh->ovfmt)
+               return -EINVAL;
        retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
        if (0 != retval)
                return retval;
@@ -1735,33 +1753,50 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
        /* copy clips  --  luckily v4l1 + v4l2 are binary
           compatible here ...*/
        n = win->clipcount;
-       size = sizeof(struct video_clip)*(n+4);
+       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)*win->clipcount)) {
+               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 = bttv_screen_clips(btv->fbuf.width, btv->fbuf.width,
+               n = btcx_screen_clips(btv->fbuf.width, btv->fbuf.width,
                                      &win->w, clips, n);
-       bttv_sort_clips(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();
+       }
        
        down(&fh->cap.lock);
        if (fh->ov.clips)
                kfree(fh->ov.clips);
-       fh->ov.clips   = clips;
-       fh->ov.nclips  = n;
+       fh->ov.clips    = clips;
+       fh->ov.nclips   = n;
        
-       fh->ov.w       = win->w;
-       fh->ov.field   = win->field;
+       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;
@@ -1834,8 +1869,10 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
                f->fmt.pix.height       = fh->height;
                f->fmt.pix.field        = fh->cap.field;
                f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-               f->fmt.pix.sizeimage    =
-                       (fh->width * fh->height * fh->fmt->depth)/8;
+               f->fmt.pix.bytesperline =
+                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
+               f->fmt.pix.sizeimage =
+                       f->fmt.pix.height * f->fmt.pix.bytesperline;
                return 0;
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                memset(&f->fmt.win,0,sizeof(struct v4l2_window));
@@ -1843,7 +1880,7 @@ static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
                f->fmt.win.field = fh->ov.field;
                return 0;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
-               bttv_vbi_fmt(fh,f);
+               bttv_vbi_get_fmt(fh,f);
                return 0;
        default:
                return -EINVAL;
@@ -1858,14 +1895,11 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
        {
                const struct bttv_format *fmt;
                enum v4l2_field field;
-               int maxw,maxh;
+               unsigned int maxw,maxh;
 
                fmt = format_by_fourcc(f->fmt.pix.pixelformat);
                if (NULL == fmt)
                        return -EINVAL;
-               if (0 != f->fmt.pix.bytesperline)
-                       /* FIXME -- not implemented yet */
-                       return -EINVAL;
 
                /* fixup format */
                maxw  = bttv_tvnorms[btv->tvnorm].swidth;
@@ -1880,6 +1914,7 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
                switch (field) {
                case V4L2_FIELD_TOP:
                case V4L2_FIELD_BOTTOM:
+               case V4L2_FIELD_ALTERNATE:
                        maxh = maxh/2;
                        break;
                case V4L2_FIELD_INTERLACED:
@@ -1887,6 +1922,7 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
                case V4L2_FIELD_SEQ_TB:
                        if (fmt->flags & FORMAT_FLAGS_PLANAR)
                                return -EINVAL;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -1901,25 +1937,19 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
                        f->fmt.pix.width = maxw;
                if (f->fmt.pix.height > maxh)
                        f->fmt.pix.height = maxh;
+               f->fmt.pix.bytesperline =
+                       (f->fmt.pix.width * fmt->depth) >> 3;
                f->fmt.pix.sizeimage =
-                       (fh->width * fh->height * fmt->depth)/8;
+                       f->fmt.pix.height * f->fmt.pix.bytesperline;
                
                return 0;
        }
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                return verify_window(&bttv_tvnorms[btv->tvnorm],
                                     &f->fmt.win, 1);
-#if 0
        case V4L2_BUF_TYPE_VBI_CAPTURE:
-               retval = bttv_switch_type(fh,f->type);
-               if (0 != retval)
-                       return retval;
-               if (fh->vbi.reading || fh->vbi.streaming)
-                       return -EBUSY;
-               bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
-               bttv_vbi_fmt(fh,f);
+               bttv_vbi_try_fmt(fh,f);
                return 0;
-#endif
        default:
                return -EINVAL;
        }
@@ -1947,6 +1977,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                down(&fh->cap.lock);
                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;
@@ -1962,10 +1993,11 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
                retval = bttv_switch_type(fh,f->type);
                if (0 != retval)
                        return retval;
-               if (fh->vbi.reading || fh->vbi.streaming)
-                       return -EBUSY;
+               if (locked_btres(fh->btv, RESOURCE_VBI))
+                        return -EBUSY;
+               bttv_vbi_try_fmt(fh,f);
                bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
-               bttv_vbi_fmt(fh,f);
+               bttv_vbi_get_fmt(fh,f);
                return 0;
        default:
                return -EINVAL;
@@ -1978,7 +2010,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        struct bttv_fh *fh  = file->private_data;
        struct bttv    *btv = fh->btv;
        unsigned long flags;
-       int retval;
+       int retval = 0;
 
        if (bttv_debug > 1) {
                switch (_IOC_TYPE(cmd)) {
@@ -2052,9 +2084,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                if (NULL == fmt)
                        return -EINVAL;
                down(&fh->cap.lock);
-               retval = -EINVAL;
-               if (fmt->depth != pic->depth && !sloppy)
+               if (fmt->depth != pic->depth && !sloppy) {
+                       retval = -EINVAL;
                        goto fh_unlock_and_return;
+               }
                fh->ovfmt   = fmt;
                fh->fmt     = fmt;
                btv->init.ovfmt   = fmt;
@@ -2092,7 +2125,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                struct video_window *win = arg;
                struct v4l2_window w2;
 
-               w2.field     = V4L2_FIELD_ANY;
+               w2.field = V4L2_FIELD_ANY;
                w2.w.left    = win->x;
                w2.w.top     = win->y;
                w2.w.width   = win->width;
@@ -2181,12 +2214,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                        /* verify args */
                        if (NULL == btv->fbuf.base)
                                return -EINVAL;
-                       if (fh->ov.w.width <48 ||
-                           fh->ov.w.height<32 ||
-                           fh->ov.w.width >bttv_tvnorms[btv->tvnorm].swidth ||
-                           fh->ov.w.height>bttv_tvnorms[btv->tvnorm].sheight||
-                           NULL == fh->ovfmt)
+                       if (!fh->ov.setup_ok) {
+                               dprintk("bttv%d: overlay: !setup_ok\n",btv->nr);
                                return -EINVAL;
+                       }
                }
 
                if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
@@ -2210,7 +2241,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOCGMBUF:
        {
                struct video_mbuf *mbuf = arg;
-               int i;
+               unsigned int i;
 
                down(&fh->cap.lock);
                retval = videobuf_mmap_setup(file,&fh->cap,gbuffers,gbufsize);
@@ -2290,6 +2321,56 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                return retval;
        }
 
+       case VIDIOCGVBIFMT:
+       {
+               struct vbi_format *fmt = (void *) arg;
+               struct v4l2_format fmt2;
+
+               if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
+                       retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+                       if (0 != retval)
+                               return retval;
+               }
+               bttv_vbi_get_fmt(fh, &fmt2);
+
+               memset(fmt,0,sizeof(*fmt));
+               fmt->sampling_rate    = fmt2.fmt.vbi.sampling_rate;
+               fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
+               fmt->sample_format    = VIDEO_PALETTE_RAW;
+               fmt->start[0]         = fmt2.fmt.vbi.start[0];
+               fmt->count[0]         = fmt2.fmt.vbi.count[0];
+               fmt->start[1]         = fmt2.fmt.vbi.start[1];
+               fmt->count[1]         = fmt2.fmt.vbi.count[1];
+               if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
+                       fmt->flags   |= V4L2_VBI_UNSYNC;
+               if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
+                       fmt->flags   |= V4L2_VBI_INTERLACED;
+               return 0;
+       }
+       case VIDIOCSVBIFMT:
+       {
+               struct vbi_format *fmt = (void *) arg;
+               struct v4l2_format fmt2;
+
+               retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+               if (0 != retval)
+                       return retval;
+               bttv_vbi_get_fmt(fh, &fmt2);
+
+               if (fmt->sampling_rate    != fmt2.fmt.vbi.sampling_rate     ||
+                   fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line  ||
+                   fmt->sample_format    != VIDEO_PALETTE_RAW              ||
+                   fmt->start[0]         != fmt2.fmt.vbi.start[0]          ||
+                   fmt->start[1]         != fmt2.fmt.vbi.start[1]          ||
+                   fmt->count[0]         != fmt->count[1]                  ||
+                   fmt->count[0]         <  1                              ||
+                   fmt->count[0]         >  32 /* VBI_MAXLINES */)
+                       return -EINVAL;
+
+               bttv_vbi_setlines(fh,btv,fmt->count[0]);
+               return 0;
+       }
+
         case BTTV_VERSION:
         case VIDIOCGFREQ:
         case VIDIOCSFREQ:
@@ -2326,7 +2407,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
        {
                struct v4l2_fmtdesc *f = arg;
                enum v4l2_buf_type type;
-               int i, index;
+               unsigned int i;
+               int index;
 
                type  = f->type;
                if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
@@ -2347,7 +2429,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                for (i = 0; i < BTTV_FORMATS; i++) {
                        if (bttv_formats[i].fourcc != -1)
                                index++;
-                       if (index == f->index)
+                       if ((unsigned int)index == f->index)
                                break;
                }
                if (BTTV_FORMATS == i)
@@ -2604,8 +2686,8 @@ static ssize_t bttv_read(struct file *file, char *data,
 
        if (fh->btv->errors)
                bttv_reinit_bt848(fh->btv);
-       dprintk("read count=%d type=%s\n",
-               (int)count,v4l2_type_names[fh->type]);
+       dprintk("bttv%d: read count=%d type=%s\n",
+               fh->btv->nr,(int)count,v4l2_type_names[fh->type]);
 
        switch (fh->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -2628,6 +2710,7 @@ 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;
 
        if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
                if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
@@ -2654,7 +2737,8 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                                up(&fh->cap.lock);
                                return POLLERR;
                        }
-                       if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,fh->cap.field)) {
+                       field = videobuf_next_field(&fh->cap);
+                       if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,field)) {
                                up(&fh->cap.lock);
                                return POLLERR;
                        }
@@ -2674,11 +2758,11 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 
 static int bttv_open(struct inode *inode, struct file *file)
 {
-       unsigned int minor = minor(inode->i_rdev);
+       int minor = minor(inode->i_rdev);
        struct bttv *btv = NULL;
        struct bttv_fh *fh;
        enum v4l2_buf_type type = 0;
-       int i;
+       unsigned int i;
 
        dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
 
@@ -2707,6 +2791,7 @@ static int bttv_open(struct inode *inode, struct file *file)
        file->private_data = fh;
        *fh = btv->init;
        fh->type = type;
+       fh->ov.setup_ok = 0;
        videobuf_queue_init(&fh->cap, &bttv_video_qops,
                            btv->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -2720,6 +2805,8 @@ static int bttv_open(struct inode *inode, struct file *file)
        i2c_vidiocschan(btv);
 
        btv->users++;
+       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
+               bttv_vbi_setlines(fh,btv,16);
        bttv_field_count(btv);
        return 0;
 }
@@ -2807,10 +2894,10 @@ struct video_device bttv_vbi_template =
 
 static int radio_open(struct inode *inode, struct file *file)
 {
-       unsigned int minor = minor(inode->i_rdev);
+       int minor = minor(inode->i_rdev);
        struct bttv *btv = NULL;
-       unsigned long v = 400*16;
-       int i;
+       u32 v = 400*16;
+       unsigned int i;
 
        dprintk("bttv: open minor=%d\n",minor);
 
@@ -2934,10 +3021,10 @@ static char *irq_name[] = { "FMTCHG", "VSYNC", "HSYNC", "OFLOW", "HLOCK",
 
 static void bttv_print_irqbits(u32 print, u32 mark)
 {
-       int i;
+       unsigned int i;
        
        printk("bits:");
-       for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
+       for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
                if (print & (1 << i))
                        printk(" %s",irq_name[i]);
                if (mark & (1 << i))
@@ -2950,132 +3037,53 @@ static void bttv_print_riscaddr(struct bttv *btv)
        printk("  main: %08Lx\n",
               (unsigned long long)btv->main.dma);
        printk("  vbi : o=%08Lx e=%08Lx\n",
-              btv->vcurr ? (unsigned long long)btv->vcurr->top.dma : 0,
-              btv->vcurr ? (unsigned long long)btv->vcurr->bottom.dma : 0);
+              btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0,
+              btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0);
        printk("  cap : o=%08Lx e=%08Lx\n",
-              btv->top    ? (unsigned long long)btv->top->top.dma : 0,
-              btv->bottom ? (unsigned long long)btv->bottom->bottom.dma : 0);
+              btv->curr.top    ? (unsigned long long)btv->curr.top->top.dma : 0,
+              btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
        printk("  scr : o=%08Lx e=%08Lx\n",
               btv->screen ? (unsigned long long)btv->screen->top.dma  : 0,
               btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
 }
 
-static void bttv_irq_timeout(unsigned long data)
-{
-       struct bttv *btv = (struct bttv *)data;
-       struct bttv_buffer *o_bottom,*o_top,*o_vcurr;
-       struct bttv_buffer *capture;
-
-       if (bttv_verbose) {
-               printk(KERN_INFO "bttv%d: timeout: risc=%08x, ",
-                      btv->nr,btread(BT848_RISC_COUNT));
-               bttv_print_irqbits(btread(BT848_INT_STAT),0);
-               printk("\n");
-       }
-
-       spin_lock(&btv->s_lock);
-       o_top    = btv->top;
-       o_bottom = btv->bottom;
-       o_vcurr  = btv->vcurr;
-       btv->top    = NULL;
-       btv->bottom = NULL;
-       btv->vcurr  = NULL;
-       
-       /* deactivate stuff */
-       bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
-       bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
-       bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
-       bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
-       bttv_set_dma(btv, 0, 0);
-
-       /* wake up + free */
-       if (o_top == o_bottom) {
-               if (NULL != o_top) {
-                       o_top->vb.state = STATE_ERROR;
-                       wake_up(&o_top->vb.done);
-               }
-       } else {
-               if (NULL != o_top) {
-                       o_top->vb.state = STATE_ERROR;
-                       wake_up(&o_top->vb.done);
-               }
-               if (NULL != o_bottom) {
-                       o_bottom->vb.state = STATE_ERROR;
-                       wake_up(&o_bottom->vb.done);
-               }
-       }
-       if (NULL != o_vcurr) {
-               o_vcurr->vb.state = STATE_ERROR;
-               wake_up(&o_vcurr->vb.done);
-       }
-
-       /* cancel all outstanding capture / vbi requests */
-       while (!list_empty(&btv->capture)) {
-               capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
-               list_del(&capture->vb.queue);
-               capture->vb.state = STATE_ERROR;
-               wake_up(&capture->vb.done);
-       }
-       while (!list_empty(&btv->vcapture)) {
-               capture = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
-               list_del(&capture->vb.queue);
-               capture->vb.state = STATE_ERROR;
-               wake_up(&capture->vb.done);
-       }
-       
-       btv->errors++;
-       spin_unlock(&btv->s_lock);      
-}
-
-static void
-bttv_irq_switch_fields(struct bttv *btv)
+static int
+bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set)
 {
-       struct bttv_buffer *o_bottom,*o_top,*o_vcurr;
-       struct bttv_buffer *capture;
-       dma_addr_t rc;
-       int irqflags = 0;
-       struct timeval ts;
+       struct bttv_buffer *item;
 
-       spin_lock(&btv->s_lock);
-       o_top    = btv->top;
-       o_bottom = btv->bottom;
-       o_vcurr  = btv->vcurr;
-       btv->top    = NULL;
-       btv->bottom = NULL;
-       btv->vcurr  = NULL;
+       memset(set,0,sizeof(*set));
 
        /* vbi request ? */
        if (!list_empty(&btv->vcapture)) {
-               irqflags = 1;
-               btv->vcurr = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
-               list_del(&btv->vcurr->vb.queue);
+               set->irqflags = 1;
+               set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
        }
 
        /* capture request ? */
        if (!list_empty(&btv->capture)) {
-               irqflags = 1;
-               capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
-               list_del(&capture->vb.queue);
-               if (V4L2_FIELD_HAS_TOP(capture->vb.field))
-                       btv->top = capture;
-               if (V4L2_FIELD_HAS_BOTTOM(capture->vb.field))
-                       btv->bottom = capture;
+               set->irqflags = 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(capture->vb.field) &&
-                   !list_empty(&btv->capture)) {
-                       capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
-                       if (!V4L2_FIELD_HAS_BOTH(capture->vb.field)) {
-                               if (NULL == btv->top &&
-                                    V4L2_FIELD_TOP == capture->vb.field) {
-                                       btv->top = capture;
-                                       list_del(&capture->vb.queue);
+               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);
+                       if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
+                               if (NULL == set->top &&
+                                   V4L2_FIELD_TOP == item->vb.field) {
+                                       set->top = item;
                                }
-                               if (NULL == btv->bottom &&
-                                   V4L2_FIELD_BOTTOM == capture->vb.field) {
-                                       btv->bottom = capture;
-                                       list_del(&capture->vb.queue);
+                               if (NULL == set->bottom &&
+                                   V4L2_FIELD_BOTTOM == item->vb.field) {
+                                       set->bottom = item;
                                }
+                               if (NULL != set->top  &&  NULL != set->bottom)
+                                       set->topirq = 2;
                        }
                }
        }
@@ -3083,76 +3091,163 @@ bttv_irq_switch_fields(struct bttv *btv)
        /* screen overlay ? */
        if (NULL != btv->screen) {
                if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
-                       if (NULL == btv->top && NULL == btv->bottom) {
-                               btv->top  = btv->screen;
-                               btv->bottom = btv->screen;
+                       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 == btv->top) {
-                               btv->top = btv->screen;
+                           NULL == set->top) {
+                               set->top = btv->screen;
                        }
                        if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
-                           NULL == btv->bottom) {
-                               btv->bottom = btv->screen;
+                           NULL == set->bottom) {
+                               set->bottom = btv->screen;
                        }
                }
        }
 
-       if (irq_debug)
-               printk(KERN_DEBUG "bttv%d: irq top=0x%08x bottom=0x%08x"
-                      " vbi=0x%08x/0x%08x\n", btv->nr,
-                      btv->top    ? btv->top->top.dma       : 0,
-                      btv->bottom ? btv->bottom->bottom.dma : 0,
-                      btv->vcurr  ? btv->vcurr->top.dma     : 0,
-                      btv->vcurr  ? btv->vcurr->bottom.dma  : 0);
+       dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p "
+               "[screen=%p,irq=%d,%d]\n",
+               btv->nr,set->top, set->bottom, set->vbi,
+               btv->screen,set->irqflags,set->topirq);
+       return 0;
+}
+
+static void
+bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup,
+                   struct bttv_buffer_set *curr, unsigned int state)
+{
+       struct timeval ts;
 
-       rc = btread(BT848_RISC_COUNT);
-       if (rc < btv->main.dma || rc > btv->main.dma + 0x100)
-               printk("bttv%d: Huh? IRQ latency? main=0x%x rc=0x%x\n",
-                      btv->nr,btv->main.dma,rc);
-       
-       /* activate new fields */
-       bttv_buffer_activate(btv,btv->top,btv->bottom);
-       if (btv->vcurr) {
-               btv->vcurr->vb.state = STATE_ACTIVE;
-               bttv_risc_hook(btv, RISC_SLOT_O_VBI, &btv->vcurr->top, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_VBI, &btv->vcurr->bottom, 0);
-       } else {
-               bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
-       }
-       bttv_set_dma(btv, 0, irqflags);
-       
-       /* wake up + free */
        do_gettimeofday(&ts);
-       if (o_top == o_bottom) {
-               if (NULL != o_top && btv->top != o_top) {
-                       o_top->vb.ts = ts;
-                       o_top->vb.field_count = btv->field_count;
-                       o_top->vb.state = STATE_DONE;
-                       wake_up(&o_top->vb.done);
+
+       if (NULL != wakeup->vbi) {
+               wakeup->vbi->vb.ts = ts;
+               wakeup->vbi->vb.field_count = btv->field_count;
+               wakeup->vbi->vb.state = state;
+               wake_up(&wakeup->vbi->vb.done);
+       }
+       if (wakeup->top == wakeup->bottom) {
+               if (NULL != wakeup->top && curr->top != wakeup->top) {
+                       if (irq_debug)
+                               printk("bttv%d: wakeup: both=%p\n",btv->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 != o_top && btv->top != o_top) {
-                       o_top->vb.ts = ts;
-                       o_top->vb.field_count = btv->field_count;
-                       o_top->vb.state = STATE_DONE;
-                       wake_up(&o_top->vb.done);
+               if (NULL != wakeup->top && curr->top != wakeup->top) {
+                       if (irq_debug)
+                               printk("bttv%d: wakeup: top=%p\n",btv->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 != o_bottom && btv->bottom != o_bottom) {
-                       o_bottom->vb.ts = ts;
-                       o_bottom->vb.field_count = btv->field_count;
-                       o_bottom->vb.state = STATE_DONE;
-                       wake_up(&o_bottom->vb.done);
+               if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
+                       if (irq_debug)
+                               printk("bttv%d: wakeup: bottom=%p\n",btv->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);
                }
        }
-       if (NULL != o_vcurr) {
-               o_vcurr->vb.ts = ts;
-               o_vcurr->vb.field_count = btv->field_count;
-               o_vcurr->vb.state = STATE_DONE;
-               wake_up(&o_vcurr->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 *item;
+       
+       if (bttv_verbose) {
+               printk(KERN_INFO "bttv%d: timeout: risc=%08x, ",
+                      btv->nr,btread(BT848_RISC_COUNT));
+               bttv_print_irqbits(btread(BT848_INT_STAT),0);
+               printk("\n");
+       }
+
+       spin_lock(&btv->s_lock);
+       
+       /* deactivate stuff */
+       memset(&new,0,sizeof(new));
+       old = btv->curr;
+       btv->curr = new;
+       bttv_buffer_set_activate(btv, &new);
+       bttv_set_dma(btv, 0, 0);
+
+       /* wake up */
+       bttv_irq_wakeup_set(btv, &old, &new, STATE_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 = STATE_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 = STATE_ERROR;
+               wake_up(&item->vb.done);
+       }
+       
+       btv->errors++;
+       spin_unlock(&btv->s_lock);      
+}
+
+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.topirq = 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 = STATE_DONE;
+       wake_up(&wakeup->vb.done);
+       spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_switch_fields(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_set(btv, &new);
+       rc = btread(BT848_RISC_COUNT);
+       if (rc < btv->main.dma || rc > btv->main.dma + 0x100) {
+               if (1 /* irq_debug */)
+                       printk("bttv%d: skipped frame. no signal? high irq latency?\n",
+                              btv->nr);
+               spin_unlock(&btv->s_lock);
+               return;
+       }
+       
+       /* switch over */
+       old = btv->curr;
+       btv->curr = new;
+       bttv_buffer_set_activate(btv, &new);
+       bttv_set_dma(btv, 0, new.irqflags);
+
+       /* wake up finished buffers */
+       bttv_irq_wakeup_set(btv, &old, &new, STATE_DONE);
        spin_unlock(&btv->s_lock);
 }
 
@@ -3178,7 +3273,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                /* get device status bits */
                dstat=btread(BT848_DSTATUS);
 
-               if (irq_debug) {
+               if (0 /*irq_debug*/) {
                        printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
                               "riscs=%x, riscc=%08x, ",
                               btv->nr, count, btv->field_count,
@@ -3201,7 +3296,10 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
 
                if (astat & BT848_INT_GPINT)
                        wake_up(&btv->gpioq);
-               
+
+                if ((astat & BT848_INT_RISCI)  &&  (stat & (2<<28)))
+                       bttv_irq_wakeup_top(btv);
+
                 if ((astat & BT848_INT_RISCI)  &&  (stat & (1<<28)))
                        bttv_irq_switch_fields(btv);
 
@@ -3308,7 +3406,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
        btv->timeout.data     = (unsigned long)btv;
        
         btv->i2c_rc = -1;
-        btv->tuner_type = -1;
+        btv->tuner_type  = UNSET;
+        btv->pinnacle_id = UNSET;
 
        memcpy(&btv->video_dev, &bttv_video_template, sizeof(bttv_video_template));
        memcpy(&btv->radio_dev, &radio_template,      sizeof(radio_template));
@@ -3485,7 +3584,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
                 video_unregister_device(&btv->vbi_dev);
 
        /* free allocated memory */
-       bttv_riscmem_free(btv->dev,&btv->main);
+       btcx_riscmem_free(btv->dev,&btv->main);
 
        /* free ressources */
         free_irq(btv->dev->irq,btv);
@@ -3519,6 +3618,7 @@ static struct pci_driver bttv_pci_driver = {
 
 static int bttv_init_module(void)
 {
+       int rc;
        bttv_num = 0;
 
        printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
@@ -3536,7 +3636,13 @@ static int bttv_init_module(void)
 
        bttv_check_chipset();
 
-       return pci_module_init(&bttv_pci_driver);
+       rc = pci_module_init(&bttv_pci_driver);
+       if (-ENODEV == rc) {
+               /* plenty of people trying to use bttv for the cx2388x ... */
+               if (NULL != pci_find_device(0x14f1, 0x8800, NULL))
+                       printk("bttv doesn't support your Conexant 2388x card.\n");
+       }
+       return rc;
 }
 
 static void bttv_cleanup_module(void)
index a4a462ecb2faa415a9a69ef3688ed358fad8147e..bf561af34b1427b3d4dbbbb363279aa6550161dc 100644 (file)
@@ -25,7 +25,6 @@
     
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
@@ -198,6 +197,9 @@ static int attach_inform(struct i2c_client *client)
 
        if (btv->tuner_type != UNSET)
                bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
+       if (btv->pinnacle_id != UNSET)
+               bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
+                                     &btv->pinnacle_id);
 
         if (bttv_debug)
                printk("bttv%d: i2c attach [client=%s]\n",
@@ -231,9 +233,9 @@ static struct i2c_algo_bit_data bttv_i2c_algo_template = {
 
 static struct i2c_adapter bttv_i2c_adap_template = {
        .owner             = THIS_MODULE,
+       .class             = I2C_ADAP_CLASS_TV_ANALOG,
        I2C_DEVNAME("bt848"),
        .id                = I2C_HW_B_BT848,
-       .class             = I2C_ADAP_CLASS_TV_ANALOG,
        .client_register   = attach_inform,
 };
 
@@ -314,6 +316,7 @@ int __devinit init_bttv_i2c(struct bttv *btv)
               sizeof(struct i2c_client));
 
        sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr);
+       btv->i2c_adap.dev.parent = &btv->dev->dev;
 
         btv->i2c_algo.data = btv;
         i2c_set_adapdata(&btv->i2c_adap, btv);
index 9b31c6f129966be0dbf5e6153743c6b178542405..6c3aef4e0c6f7569a8102de093316aac99c4c803 100644 (file)
@@ -23,7 +23,6 @@
 
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 
 #include "bttvp.h"
 
-/* ---------------------------------------------------------- */
-/* allocate/free risc memory                                  */
-
-int  bttv_riscmem_alloc(struct pci_dev *pci,
-                       struct bttv_riscmem *risc,
-                       unsigned int size)
-{
-       u32 *cpu;
-       dma_addr_t dma;
-       
-       cpu = pci_alloc_consistent(pci, size, &dma);
-       if (NULL == cpu)
-               return -ENOMEM;
-       memset(cpu,0,size);
-
-       if (risc->cpu && risc->size < size) {
-               /* realloc (enlarge buffer) -- copy old stuff */
-               memcpy(cpu,risc->cpu,risc->size);
-               bttv_riscmem_free(pci,risc);
-       }
-       risc->cpu  = cpu;
-       risc->dma  = dma;
-       risc->size = size;
-
-       return 0;
-}
-
-void bttv_riscmem_free(struct pci_dev *pci,
-                      struct bttv_riscmem *risc)
-{
-       if (NULL == risc->cpu)
-               return;
-       pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
-       memset(risc,0,sizeof(*risc));
-}
-
 /* ---------------------------------------------------------- */
 /* risc code generators                                       */
 
 int
-bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
+bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
                 struct scatterlist *sglist,
-                int offset, int bpl, int padding, int lines)
+                unsigned int offset, unsigned int bpl,
+                unsigned int padding, unsigned int lines)
 {
-       int instructions,rc,line,todo;
+       u32 instructions,line,todo;
        struct scatterlist *sg;
        u32 *rp;
+       int rc;
 
        /* estimate risc mem: worst case is one write per page border +
           one write per scan line + sync + jump (all 2 dwords) */
        instructions  = (bpl * lines) / PAGE_SIZE + lines;
        instructions += 2;
-       if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
+       if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
                return rc;
 
        /* sync instruction */
@@ -130,6 +95,7 @@ bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
                }
                offset += padding;
        }
+       dprintk("bttv%d: risc planar: %d sglist elems\n", btv->nr, (int)(sg-sglist));
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
@@ -137,24 +103,27 @@ bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
 }
 
 int
-bttv_risc_planar(struct bttv *btv, struct bttv_riscmem *risc,
+bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
                 struct scatterlist *sglist,
-                int yoffset, int ybpl, int ypadding, int ylines,
-                int uoffset, int voffset, int hshift, int vshift,
-                int cpadding)
+                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)
 {
-       int instructions,rc,line,todo,ylen,chroma;
+       unsigned int instructions,line,todo,ylen,chroma;
        u32 *rp,ri;
        struct scatterlist *ysg;
        struct scatterlist *usg;
        struct scatterlist *vsg;
+       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  = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
        instructions += 2;
-       if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0)
+       if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0)
                return rc;
 
        /* sync instruction */
@@ -231,138 +200,13 @@ bttv_risc_planar(struct bttv *btv, struct bttv_riscmem *risc,
        return 0;
 }
 
-/* ---------------------------------------------------------- */
-
-struct SKIPLIST {
-       int start;
-       int end;
-};
-
-int
-bttv_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
-                 struct v4l2_clip *clips, int n)
-{
-       if (win->left < 0) {
-               /* left */
-               clips[n].c.left = 0;
-               clips[n].c.top = 0;
-               clips[n].c.width  = -win->left;
-               clips[n].c.height = win->height;
-               n++;
-       }
-       if (win->left + win->width > swidth) {
-               /* right */
-               clips[n].c.left   = swidth - win->left;
-               clips[n].c.top    = 0;
-               clips[n].c.width  = win->width - clips[n].c.left;
-               clips[n].c.height = win->height;
-               n++;
-       }
-       if (win->top < 0) {
-               /* top */
-               clips[n].c.left = 0;
-               clips[n].c.top = 0;
-               clips[n].c.width  = win->width;
-               clips[n].c.height = -win->top;
-               n++;
-       }
-       if (win->top + win->height > sheight) {
-               /* bottom */
-               clips[n].c.left = 0;
-               clips[n].c.top = sheight - win->top;
-               clips[n].c.width  = win->width;
-               clips[n].c.height = win->height - clips[n].c.top;
-               n++;
-       }
-       return n;
-}
-
-void
-bttv_sort_clips(struct v4l2_clip *clips, int nclips)
-{
-       struct v4l2_clip swap;
-       int i,j,n;
-
-       for (i = nclips-2; i >= 0; i--) {
-               for (n = 0, j = 0; j <= i; j++) {
-                       if (clips[j].c.left > clips[j+1].c.left) {
-                               swap = clips[j];
-                               clips[j] = clips[j+1];
-                               clips[j+1] = swap;
-                               n++;
-                       }
-               }
-               if (0 == n)
-                       break;
-       }
-}
-
-static void
-calc_skips(int line, int width, int *maxy,
-          struct SKIPLIST *skips, int *nskips,
-          const struct v4l2_clip *clips, int nclips)
-{
-       int clip,skip,maxline,end;
-
-       skip=0;
-       maxline = 9999;
-       for (clip = 0; clip < nclips; clip++) {
-
-               /* sanity checks */
-               if (clips[clip].c.left + clips[clip].c.width <= 0)
-                       continue;
-               if (clips[clip].c.left > width)
-                       break;
-               
-               /* vertical range */
-               if (line > clips[clip].c.top+clips[clip].c.height-1)
-                       continue;
-               if (line < clips[clip].c.top) {
-                       if (maxline > clips[clip].c.top-1)
-                               maxline = clips[clip].c.top-1;
-                       continue;
-               }
-               if (maxline > clips[clip].c.top+clips[clip].c.height-1)
-                       maxline = clips[clip].c.top+clips[clip].c.height-1;
-
-               /* horizontal range */
-               if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
-                       /* new one */
-                       skips[skip].start = clips[clip].c.left;
-                       if (skips[skip].start < 0)
-                               skips[skip].start = 0;
-                       skips[skip].end = clips[clip].c.left + clips[clip].c.width;
-                       if (skips[skip].end > width)
-                               skips[skip].end = width;
-                       skip++;
-               } else {
-                       /* overlaps -- expand last one */
-                       end = clips[clip].c.left + clips[clip].c.width;
-                       if (skips[skip-1].end < end)
-                               skips[skip-1].end = end;
-                       if (skips[skip-1].end > width)
-                               skips[skip-1].end = width;
-               }
-       }
-       *nskips = skip;
-       *maxy = maxline;
-
-       if (bttv_debug) {
-               printk(KERN_DEBUG "bttv: skips line %d-%d:",line,maxline);
-               for (skip = 0; skip < *nskips; skip++) {
-                       printk(" %d-%d",skips[skip].start,skips[skip].end);
-               }
-               printk("\n");
-       }
-}
-
 int
-bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
+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 instructions,rc,line,maxy,start,end,skip,nskips;
-       struct SKIPLIST *skips;
+       struct btcx_skiplist *skips;
        u32 *rp,ri,ra;
        u32 addr;
 
@@ -375,7 +219,7 @@ bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
        instructions  = (ov->nclips + 1) *
                ((skip_even || skip_odd) ? ov->w.height>>1 :  ov->w.height);
        instructions += 2;
-       if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
+       if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
                return rc;
 
        /* sync instruction */
@@ -397,8 +241,8 @@ bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
 
                /* calculate clipping */
                if (line > maxy)
-                       calc_skips(line, ov->w.width, &maxy,
-                                  skips, &nskips, ov->clips, ov->nclips);
+                       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) {
@@ -432,7 +276,6 @@ bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
-
        kfree(skips);
        return 0;
 }
@@ -476,6 +319,7 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
         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);
@@ -506,6 +350,8 @@ bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
         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);
 }
 
 /* ---------------------------------------------------------- */
@@ -518,9 +364,9 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
        int capctl;
 
        btv->cap_ctl = 0;
-       if (NULL != btv->top)      btv->cap_ctl |= 0x02;
-       if (NULL != btv->bottom)   btv->cap_ctl |= 0x01;
-       if (NULL != btv->vcurr)    btv->cap_ctl |= 0x0c;
+       if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
+       if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
+       if (NULL != btv->curr.vbi)      btv->cap_ctl |= 0x0c;
 
        capctl  = 0;
        capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
@@ -530,14 +376,16 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
        d2printk(KERN_DEBUG
                 "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
                 btv->nr,capctl,irqflags,
-                btv->vcurr   ? (unsigned long long)btv->vcurr->top.dma      : 0,
-                btv->top     ? (unsigned long long)btv->top->top.dma        : 0,
-                btv->vcurr   ? (unsigned long long)btv->vcurr->bottom.dma   : 0,
-                btv->bottom  ? (unsigned long long)btv->bottom->bottom.dma  : 0);
+                btv->curr.vbi     ? (unsigned long long)btv->curr.vbi->top.dma        : 0,
+                btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
+                btv->curr.vbi     ? (unsigned long long)btv->curr.vbi->bottom.dma     : 0,
+                btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
        
        cmd = BT848_RISC_JUMP;
        if (irqflags) {
-               cmd |= BT848_RISC_IRQ | (irqflags << 16);
+               cmd |= BT848_RISC_IRQ;
+               cmd |= (irqflags  & 0x0f) << 16;
+               cmd |= (~irqflags & 0x0f) << 20;
                mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
        } else {
                del_timer(&btv->timeout);
@@ -565,7 +413,7 @@ bttv_risc_init_main(struct bttv *btv)
 {
        int rc;
        
-       if ((rc = bttv_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0)
+       if ((rc = btcx_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0)
                return rc;
        dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
                btv->nr,(unsigned long long)btv->main.dma);
@@ -600,7 +448,7 @@ bttv_risc_init_main(struct bttv *btv)
 }
 
 int
-bttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc,
+bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
               int irqflags)
 {
        unsigned long cmd;
@@ -614,8 +462,11 @@ bttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc,
                d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
                         btv->nr,risc,slot,(unsigned long long)risc->dma,irqflags);
                cmd = BT848_RISC_JUMP;
-               if (irqflags)
-                       cmd |= BT848_RISC_IRQ | (irqflags << 16);
+               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);
@@ -631,43 +482,68 @@ bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
        videobuf_waiton(&buf->vb,0,0);
        videobuf_dma_pci_unmap(btv->dev, &buf->vb.dma);
        videobuf_dma_free(&buf->vb.dma);
-       bttv_riscmem_free(btv->dev,&buf->bottom);
-       bttv_riscmem_free(btv->dev,&buf->top);
+       btcx_riscmem_free(btv->dev,&buf->bottom);
+       btcx_riscmem_free(btv->dev,&buf->top);
        buf->vb.state = STATE_NEEDS_INIT;
 }
 
 int
-bttv_buffer_activate(struct bttv *btv,
-                    struct bttv_buffer *top,
-                    struct bttv_buffer *bottom)
+bttv_buffer_set_activate(struct bttv *btv,
+                        struct bttv_buffer_set *set)
 {
-       if (NULL != top  &&  NULL != bottom) {
-               top->vb.state  = STATE_ACTIVE;
-               bottom->vb.state = STATE_ACTIVE;
-               bttv_apply_geo(btv, &top->geo, 1);
-               bttv_apply_geo(btv, &bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &top->top,       0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &bottom->bottom, 0);
-               btaor((top->btformat & 0xf0) | (bottom->btformat & 0x0f),
+       /* vbi capture */
+       if (set->vbi) {
+               set->vbi->vb.state = STATE_ACTIVE;
+               list_del(&set->vbi->vb.queue);
+               bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top,    0);
+               bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0);
+       } else {
+               bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
+               bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
+       }
+
+       /* video capture */
+       if (NULL != set->top  &&  NULL != set->bottom) {
+               if (set->top == set->bottom) {
+                       set->top->vb.state    = STATE_ACTIVE;
+                       if (set->top->vb.queue.next)
+                               list_del(&set->top->vb.queue);
+               } else {
+                       set->top->vb.state    = STATE_ACTIVE;
+                       set->bottom->vb.state = STATE_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->topirq);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
+               btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
                      ~0xff, BT848_COLOR_FMT);
-               btaor((top->btswap & 0x0a) | (bottom->btswap & 0x05),
+               btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
                      ~0x0f, BT848_COLOR_CTL);
-       } else if (NULL != top) {
-               top->vb.state  = STATE_ACTIVE;
-               bttv_apply_geo(btv, &top->geo,1);
-               bttv_apply_geo(btv, &top->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &top->top, 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,      0);
-               btaor(top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
-               btaor(top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
-       } else if (NULL != bottom) {
-               bottom->vb.state = STATE_ACTIVE;
-               bttv_apply_geo(btv, &bottom->geo,1);
-               bttv_apply_geo(btv, &bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL,            0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &bottom->bottom, 0);
-               btaor(bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
-               btaor(bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
+       } else if (NULL != set->top) {
+               set->top->vb.state  = STATE_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, 0);
+               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 = STATE_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, 0);
+               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);
@@ -734,12 +610,12 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                        /* Y-Cr-Cb plane order */
                        uoffset >>= buf->fmt->hshift;
                        uoffset >>= buf->fmt->vshift;
-                       uoffset += voffset;
+                       uoffset  += voffset;
                } else {
                        /* Y-Cb-Cr plane order */
                        voffset >>= buf->fmt->hshift;
                        voffset >>= buf->fmt->vshift;
-                       voffset += uoffset;
+                       voffset  += uoffset;
                }
 
                switch (buf->vb.field) {
@@ -781,6 +657,29 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
                                         buf->fmt->vshift,
                                         cpadding);
                        break;
+               case V4L2_FIELD_SEQ_TB:
+                       bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+                                     buf->vb.height,1,buf->tvnorm);
+                       lines    = buf->vb.height >> 1;
+                       ypadding = buf->vb.width;
+                       cpadding = buf->vb.width >> buf->fmt->hshift;
+                       bttv_risc_planar(btv,&buf->top,
+                                        buf->vb.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,
+                                        buf->vb.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();
                }
@@ -826,7 +725,7 @@ bttv_overlay_risc(struct bttv *btv,
        /* build risc code */
        switch (ov->field) {
        case V4L2_FIELD_TOP:
-               bttv_risc_overlay(btv, &buf->top,   fmt, ov, 0, 0);
+               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);
index a3b2c3578b6212b3c6820a531472be7a0775ad81..368ad7a641135d6e22fd74ad1d3906851206d1c3 100644 (file)
@@ -19,7 +19,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -63,7 +62,7 @@ vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines)
 }
 
 static int vbi_buffer_setup(struct file *file,
-                       unsigned int *count, unsigned int *size)
+                           unsigned int *count, unsigned int *size)
 {
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
@@ -155,11 +154,53 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
        }
 }
 
-void bttv_vbi_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
 {
+       const struct bttv_tvnorm *tvnorm;
+       u32 start0,start1;
+       s32 count0,count1,count;
+
+       tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
+       f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
+       f->fmt.vbi.samples_per_line = 2048;
+       f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset           = 244;
+       f->fmt.vbi.flags            = 0;
+       switch (fh->btv->tvnorm) {
+       case 1: /* NTSC */
+               start0 = 10;
+               start1 = 273;
+               break;
+       case 0: /* PAL */
+       case 2: /* SECAM */
+       default:
+               start0 = 7;
+               start1 = 319;
+       }
+
+       count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0;
+       count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1;
+       count  = max(count0,count1);
+       if (count > VBI_MAXLINES)
+               count = VBI_MAXLINES;
+       if (count < 1)
+               count = 1;
+
+       f->fmt.vbi.start[0] = start0;
+       f->fmt.vbi.start[1] = start1;
+       f->fmt.vbi.count[0] = count;
+       f->fmt.vbi.count[1] = count;
+}
+
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+{
+       const struct bttv_tvnorm *tvnorm;
+
+       tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
        memset(f,0,sizeof(*f));
        f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       f->fmt.vbi.sampling_rate    = 35468950;
+       f->fmt.vbi.sampling_rate    = tvnorm->Fsc;
        f->fmt.vbi.samples_per_line = 2048;
        f->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
        f->fmt.vbi.offset           = 244;
index 230cb26bcf77d3875f474462cc1a971e0eb9dbca..98933c943d6af22f4439b11eeb14f9ab33a3ee00 100644 (file)
@@ -90,6 +90,7 @@
 #define BTTV_SENSORAY311    0x49
 #define BTTV_RV605          0x4a
 #define BTTV_WINDVR         0x4c
+#define BTTV_GRANDTEC       0x4d
 #define BTTV_KWORLD         0x4e
 #define BTTV_HAUPPAUGEPVR   0x50
 #define BTTV_GVBCTV5PCI     0x51
 #define BTTV_PINNACLESAT    0x5e
 #define BTTV_FORMAC_PROTV   0x5f
 #define BTTV_EURESYS_PICOLO 0x61
+#define BTTV_PV150          0x62
+#define BTTV_AD_TVK503      0x63
+#define BTTV_IVC200         0x66
+#define BTTV_XGUARD         0x67
+#define BTTV_NEBULA_DIGITV  0x68
+#define BTTV_PV143          0x69
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
 #define I2C_STBEE          0xae
 #define I2C_VHX            0xc0
 #define I2C_MSP3400        0x80
+#define I2C_MSP3400_ALT    0x88
 #define I2C_TEA6300        0x80
 #define I2C_DPL3518       0x84
 #define I2C_TDA9887       0x86
@@ -145,36 +153,37 @@ struct bttv;
 struct tvcard
 {
         char *name;
-        int video_inputs;
-        int audio_inputs;
-        int tuner;
-        int svhs;
-       int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
+        unsigned int video_inputs;
+        unsigned int audio_inputs;
+        unsigned int tuner;
+        unsigned int svhs;
+       unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
         u32 gpiomask;
         u32 muxsel[16];
         u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */
         u32 gpiomask2;   /* GPIO MUX mask */
 
        /* i2c audio flags */
-       int no_msp34xx:1;
-       int no_tda9875:1;
-       int no_tda7432:1;
-       int needs_tvaudio:1;
+       unsigned int no_msp34xx:1;
+       unsigned int no_tda9875:1;
+       unsigned int no_tda7432:1;
+       unsigned int needs_tvaudio:1;
+       unsigned int msp34xx_alt:1;
 
        /* other settings */
-       int pll;
+       unsigned int pll;
 #define PLL_NONE 0
 #define PLL_28   1
 #define PLL_35   2
 
-       int tuner_type;
-       int has_radio;
+       unsigned int tuner_type;
+       unsigned int has_radio;
        void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
        void (*muxsel_hook)(struct bttv *btv, unsigned int input);
 };
 
 extern struct tvcard bttv_tvcards[];
-extern const int bttv_num_tvcards;
+extern const unsigned int bttv_num_tvcards;
 
 /* identification / initialization of the card */
 extern void bttv_idcard(struct bttv *btv);
index 27a0450182dd842f3e900217cec657ee41de4986..5e18bad1fba3bc74e2f012f2917928d4cb6b4fed 100644 (file)
@@ -24,7 +24,8 @@
 #ifndef _BTTVP_H_
 #define _BTTVP_H_
 
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,4)
+#include <linux/version.h>
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11)
 
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -41,6 +42,7 @@
 
 #include "bt848.h"
 #include "bttv.h"
+#include "btcx-risc.h"
 
 #ifdef __KERNEL__
 
@@ -67,8 +69,7 @@
 
 /* ---------------------------------------------------------- */
 
-struct bttv_tvnorm 
-{
+struct bttv_tvnorm {
        int   v4l2_id;
        char  *name;
         u32   Fsc;
@@ -79,10 +80,11 @@ struct bttv_tvnorm
        u16   hdelayx1, hactivex1;
        u16   vdelay;
         u8    vbipack;
+       u16   vtotal;
        int   sram;
 };
 extern const struct bttv_tvnorm bttv_tvnorms[];
-extern const int BTTV_TVNORMS;
+extern const unsigned int BTTV_TVNORMS;
 
 struct bttv_format {
        char *name;
@@ -95,21 +97,14 @@ struct bttv_format {
        int  hshift,vshift;   /* for planar modes   */
 };
 extern const struct bttv_format bttv_formats[];
-extern const int BTTV_FORMATS;
+extern const unsigned int BTTV_FORMATS;
 
 /* ---------------------------------------------------------- */
 
 struct bttv_geometry {
        u8  vtc,crop,comb;
        u16 width,hscale,hdelay;
-       u16 sheight,vscale,vdelay;
-};
-
-struct bttv_riscmem {
-       unsigned int   size;
-       u32            *cpu;
-       u32            *jmp;
-       dma_addr_t     dma;
+       u16 sheight,vscale,vdelay,vtotal;
 };
 
 struct bttv_buffer {
@@ -122,16 +117,25 @@ struct bttv_buffer {
        int                        btformat;
        int                        btswap;
        struct bttv_geometry       geo;
-       struct bttv_riscmem        top;
-       struct bttv_riscmem        bottom;
+       struct btcx_riscmem        top;
+       struct btcx_riscmem        bottom;
+};
+
+struct bttv_buffer_set {
+       struct bttv_buffer     *top;       /* top field buffer    */
+       struct bttv_buffer     *bottom;    /* bottom field buffer */
+       struct bttv_buffer     *vbi;       /* vbi buffer */
+       unsigned int           irqflags;
+       unsigned int           topirq;
 };
 
 struct bttv_overlay {
-       int tvnorm;
+       int                    tvnorm;
        struct v4l2_rect       w;
        enum v4l2_field        field;
        struct v4l2_clip       *clips;
        int                    nclips;
+       int                    setup_ok;
 };
 
 struct bttv_fh {
@@ -141,7 +145,6 @@ struct bttv_fh {
 
        /* video capture */
        struct videobuf_queue    cap;
-       /* struct bttv_buffer       buf; */
        const struct bttv_format *fmt;
        int                      width;
        int                      height;
@@ -158,28 +161,19 @@ struct bttv_fh {
 /* ---------------------------------------------------------- */
 /* bttv-risc.c                                                */
 
-/* alloc/free memory */
-int  bttv_riscmem_alloc(struct pci_dev *pci,
-                       struct bttv_riscmem *risc,
-                       unsigned int size);
-void bttv_riscmem_free(struct pci_dev *pci,
-                      struct bttv_riscmem *risc);
-
 /* risc code generators - capture */
-int bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
+int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
                     struct scatterlist *sglist,
-                    int offset, int bpl, int pitch, int lines);
-int bttv_risc_planar(struct bttv *btv, struct bttv_riscmem *risc,
+                    unsigned int offset, unsigned int bpl,
+                    unsigned int pitch, unsigned int lines);
+int bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
                     struct scatterlist *sglist,
-                    int yoffset, int ybpl, int ypadding, int ylines,
-                    int uoffset, int voffset, int hshift, int vshift,
-                    int cpadding);
-
-/* risc code generator + helpers - screen overlay */
-int bttv_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
-                     struct v4l2_clip *clips, int n);
-void bttv_sort_clips(struct v4l2_clip *clips, int nclips);
-int bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
+                    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);
+int bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
                      const struct bttv_format *fmt,
                      struct bttv_overlay *ov,
                      int skip_top, int skip_bottom);
@@ -192,13 +186,13 @@ void bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int top);
 /* control dma register + risc main loop */
 void bttv_set_dma(struct bttv *btv, int override, int irqflags);
 int bttv_risc_init_main(struct bttv *btv);
-int bttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc,
+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(struct bttv *btv, struct bttv_buffer *top,
-                        struct bttv_buffer *bottom);
+int bttv_buffer_set_activate(struct bttv *btv,
+                            struct bttv_buffer_set *set);
 void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf);
 
 /* overlay handling */
@@ -210,7 +204,8 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
 /* ---------------------------------------------------------- */
 /* bttv-vbi.c                                                 */
 
-void bttv_vbi_fmt(struct bttv_fh *fh, struct v4l2_format *f);
+void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f);
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f);
 void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines);
 
 extern struct videobuf_queue_ops bttv_vbi_qops;
@@ -236,8 +231,8 @@ extern void bttv_field_count(struct bttv *btv);
 #define d2printk if (bttv_debug >= 2) printk
 
 /* our devices */
-#define BTTV_MAX 4
-extern int bttv_num;
+#define BTTV_MAX 16
+extern unsigned int bttv_num;
 extern struct bttv bttvs[BTTV_MAX];
 
 #define BTTV_MAX_FBUF   0x208000
@@ -264,8 +259,9 @@ struct bttv {
         unsigned int nr;       /* dev nr (for printk("bttv%d: ...");  */
        char name[8];          /* dev name */
        unsigned int cardid;   /* pci subsystem id (bt878 based ones) */
-       int type;              /* card type (pointer into tvcards[])  */
-        int tuner_type;        /* tuner chip type */
+       unsigned int type;     /* card type (pointer into tvcards[])  */
+        unsigned int tuner_type;  /* tuner chip type */
+        unsigned int pinnacle_id;
        struct bttv_pll_info pll;
        int triton1;
 
@@ -292,12 +288,12 @@ struct bttv {
         struct semaphore reslock;
 
        /* video state */
-       int input;
-       int audio;
+       unsigned int input;
+       unsigned int audio;
        unsigned long freq;
        int tvnorm,hue,contrast,bright,saturation;
        struct video_buffer fbuf;
-       int field_count;
+       unsigned int field_count;
 
        /* various options */
        int opt_combfilter;
@@ -326,21 +322,19 @@ struct bttv {
 
        /* risc memory management data
           - must aquire s_lock before changing these
-          - only the irq handler is supported to touch odd + even */
-       struct bttv_riscmem    main;
-       struct bttv_buffer     *top;       /* current active top field    */
-       struct bttv_buffer     *bottom;    /* current active bottom field */
-       struct bttv_buffer     *screen;    /* overlay                     */
-       struct list_head       capture;    /* capture buffer queue        */
-       struct bttv_buffer     *vcurr;
-       struct list_head       vcapture;
+          - 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      */
 
        unsigned long cap_ctl;
        unsigned long dma_on;
        struct timer_list timeout;
-       int errors;
+       unsigned int errors;
 
-       int users;
+       unsigned int users;
        struct bttv_fh init;
 };