vserver 1.9.5.x5
[linux-2.6.git] / drivers / media / video / bttv-cards.c
index a5a2430..4ee9026 100644 (file)
@@ -1,4 +1,6 @@
 /*
+    $Id: bttv-cards.c,v 1.42 2005/01/13 17:22:33 kraxel Exp $
+
     bttv-cards.c
 
     this file has configuration informations - card-specific stuff
 #include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-# include <linux/firmware.h>
-#endif
+#include <linux/firmware.h>
 
 #include <asm/io.h>
 
 #include "bttvp.h"
+#if 0 /* not working yet */
 #include "bt832.h"
+#endif
 
 /* fwd decl */
 static void boot_msp34xx(struct bttv *btv, int pin);
@@ -74,6 +77,9 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input);
 static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
 static void picolo_tetra_init(struct bttv *btv);
 
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input);
+static void tibetCS16_init(struct bttv *btv);
+
 static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
 static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
 
@@ -82,12 +88,13 @@ static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
 static void identify_by_eeprom(struct bttv *btv,
                               unsigned char eeprom_data[256]);
+static int __devinit pvr_boot(struct bttv *btv);
 
 /* config variables */
 static unsigned int triton1=0;
 static unsigned int vsfx=0;
 static unsigned int latency = UNSET;
-unsigned int no_overlay=-1;
+static 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 };
@@ -104,53 +111,31 @@ static unsigned int audioall = UNSET;
 static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
 
 /* insmod options */
-MODULE_PARM(triton1,"i");
+module_param(triton1,    int, 0444);
+module_param(vsfx,       int, 0444);
+module_param(no_overlay, int, 0444);
+module_param(latency,    int, 0444);
+module_param(gpiomask,   int, 0444);
+module_param(audioall,   int, 0444);
+module_param(autoload,   int, 0444);
+
+module_param_array(card,     int, NULL, 0444);
+module_param_array(pll,      int, NULL, 0444);
+module_param_array(tuner,    int, NULL, 0444);
+module_param_array(svhs,     int, NULL, 0444);
+module_param_array(remote,   int, NULL, 0444);
+module_param_array(audiomux, int, NULL, 0444);
+
 MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
                 "[enable bug compatibility for triton1 + others]");
-MODULE_PARM(vsfx,"i");
 MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
                 "[yet another chipset flaw workaround]");
-MODULE_PARM(no_overlay,"i");
-MODULE_PARM(latency,"i");
 MODULE_PARM_DESC(latency,"pci latency timer");
-MODULE_PARM(card,"1-" __stringify(BTTV_MAX) "i");
 MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
-MODULE_PARM(pll,"1-" __stringify(BTTV_MAX) "i");
 MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)");
-MODULE_PARM(tuner,"1-" __stringify(BTTV_MAX) "i");
 MODULE_PARM_DESC(tuner,"specify installed tuner type");
-MODULE_PARM(autoload,"i");
 MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)");
 
-MODULE_PARM(svhs,"1-" __stringify(BTTV_MAX) "i");
-MODULE_PARM(remote,"1-" __stringify(BTTV_MAX) "i");
-
-MODULE_PARM(gpiomask,"i");
-MODULE_PARM(audioall,"i");
-MODULE_PARM(audiomux,"1-6i");
-
-/* kernel args */
-#ifndef MODULE
-static int __init p_card(char *str)  { return bttv_parse(str,BTTV_MAX,card);  }
-static int __init p_pll(char *str)   { return bttv_parse(str,BTTV_MAX,pll);   }
-static int __init p_tuner(char *str) { return bttv_parse(str,BTTV_MAX,tuner); }
-__setup("bttv.card=",  p_card);
-__setup("bttv.pll=",   p_pll);
-__setup("bttv.tuner=", p_tuner);
-
-int __init bttv_parse(char *str, int max, int *vals)
-{
-       int i,number,res = 2;
-       
-       for (i = 0; res == 2 && i < max; i++) {
-               res = get_option(&str,&number);
-               if (res)
-                       vals[i] = number;
-       }
-       return 1;
-}
-#endif
-
 /* ----------------------------------------------------------------------- */
 /* list of card IDs for bt878+ cards                                       */
 
@@ -182,7 +167,6 @@ static struct CARD {
        { 0xd01810fc, BTTV_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
 
        { 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]" },
@@ -190,8 +174,9 @@ static struct CARD {
        { 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
        { 0x263710b4, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
        { 0x3060121a, BTTV_STB2,          "3Dfx VoodooTV 100/ STB OEM" },
-       
+
        { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
+       { 0xa005144f, BTTV_MAGICTVIEW063, "CPH06X TView99-Card" },
        { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
        { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
        { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" },
@@ -208,7 +193,7 @@ static struct CARD {
        { 0x1118153b, BTTV_TERRATVALUE,   "Terratec TValue (Temic PAL B/G)" },
        { 0x1119153b, BTTV_TERRATVALUE,   "Terratec TValue (Philips PAL I)" },
        { 0x111a153b, BTTV_TERRATVALUE,   "Terratec TValue (Temic PAL I)" },
+
        { 0x1123153b, BTTV_TERRATVRADIO,  "Terratec TV Radio+" },
        { 0x1127153b, BTTV_TERRATV,       "Terratec TV+ (V1.05)"    },
        // clashes with FlyVideo
@@ -244,7 +229,7 @@ static struct CARD {
        { 0xa1550000, BTTV_IVC200,        "IVC-200"  },
        { 0xa1550001, BTTV_IVC200,        "IVC-200"  },
        { 0xa1550002, BTTV_IVC200,        "IVC-200"  },
-       { 0xa1550003, BTTV_IVC200,        "IVC-200"  }, 
+       { 0xa1550003, BTTV_IVC200,        "IVC-200"  },
        { 0xa1550100, BTTV_IVC200,        "IVC-200G" },
        { 0xa1550101, BTTV_IVC200,        "IVC-200G" },
        { 0xa1550102, BTTV_IVC200,        "IVC-200G" },
@@ -265,10 +250,10 @@ static struct CARD {
        { 0xa182ff0d, BTTV_IVC120,        "IVC-120G" },
        { 0xa182ff0e, BTTV_IVC120,        "IVC-120G" },
        { 0xa182ff0f, BTTV_IVC120,        "IVC-120G" },
-       
+
        { 0x41424344, BTTV_GRANDTEC,      "GrandTec Multi Capture" },
        { 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
-       
+
        { 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
        { 0xa0501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
        { 0x18511851, BTTV_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
@@ -300,15 +285,17 @@ static struct CARD {
 
        // likely broken, vendor id doesn't match the other magic views ...
        //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
-       
+
        // DVB cards (using pci function .1 for mpeg data xfer)
        { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
-       { 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T" },
+       { 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
+       { 0x001c11bd, BTTV_PINNACLESAT,   "Pinnacle PCTV Sat" },
        { 0x002611bd, BTTV_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
        { 0x00011822, BTTV_TWINHAN_DST,   "Twinhan VisionPlus DVB-T" },
        { 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
-       { 0x07711461, BTTV_AVDVBT_771,    "AVermedia DVB-T 771" },
-       
+       { 0x07711461, BTTV_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
+       { 0xdb1018ac, BTTV_DVICO_DVBT_LITE,    "DVICO FusionHDTV DVB-T Lite" },
+
        { 0, -1, NULL }
 };
 
@@ -699,7 +686,7 @@ struct tvcard bttv_tvcards[] = {
                10000 : ext. Video audio input
                20000 : TV Mono
                a0000 : TV Mono/2
-              1a0000 : TV Stereo       
+              1a0000 : TV Stereo
                30000 : Radio
                40000 : Mute
        */
@@ -1114,7 +1101,7 @@ struct tvcard bttv_tvcards[] = {
        .pll            = PLL_28,
        .tuner_type     = 5,
 },{
-       /* This is the ultimate cheapo capture card 
+       /* This is the ultimate cheapo capture card
         * just a BT848A on a small PCB!
         * Steve Hosgood <steve@equiinet.com> */
        .name           = "GrandTec 'Grand Video Capture' (Bt848)",
@@ -1185,7 +1172,7 @@ struct tvcard bttv_tvcards[] = {
        .tuner_type     = -1,
 },{
        /* Miguel Angel Alvarez <maacruz@navegalia.com>
-          new Easy TV BT878 version (model CPH061) 
+          new Easy TV BT878 version (model CPH061)
           special thanks to Informatica Mieres for providing the card */
        .name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
        .video_inputs   = 3,
@@ -1389,7 +1376,7 @@ struct tvcard bttv_tvcards[] = {
 },{
         .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
         .video_inputs   = 3,
-        .audio_inputs   = 2, 
+        .audio_inputs   = 2,
        .tuner          = 0,
         .svhs           = 2,
         .gpiomask       = 0x1C800F,  // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
@@ -1567,7 +1554,7 @@ struct tvcard bttv_tvcards[] = {
         .no_tda9875     = 1,
         .no_tda7432     = 1,
 },{
-       
+
        /* ---- card 0x58 ---------------------------------- */
        .name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
        .video_inputs   = 2,
@@ -1660,13 +1647,14 @@ struct tvcard bttv_tvcards[] = {
        .tuner_type     = -1,
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
-       .no_tda7432     = 1,   
+       .no_tda7432     = 1,
        .gpiomask       = 0x01,
        .audiomux       = { 0, 0, 0, 0, 1 },
        .muxsel         = { 3, 0, 1, 2},
-       .needs_tvaudio  = 0, 
+       .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .no_gpioirq     = 1,
+       .has_dvb        = 1,
 },{
         .name           = "Formac ProTV II (bt878)",
         .video_inputs   = 4,
@@ -1676,7 +1664,7 @@ struct tvcard bttv_tvcards[] = {
         .gpiomask       = 2,
        // TV, Comp1, Composite over SVID con, SVID
         .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 2, 2, 0, 0, 0 }, 
+        .audiomux       = { 2, 2, 0, 0, 0 },
         .pll            = PLL_28,
        .has_radio      = 1,
         .tuner_type     = TUNER_PHILIPS_PAL,
@@ -1761,7 +1749,7 @@ struct tvcard bttv_tvcards[] = {
        /* Notes:
           - card lacks subsystem ID
           - stereo variant w/ daughter board with tda9874a @0xb0
-          - Audio Routing: 
+          - Audio Routing:
                always from tda9874 independent of GPIO (?)
                external line in: unknown
           - Other chips: em78p156elp @ 0x96 (probably IR remote control)
@@ -1845,7 +1833,7 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 0,
        .tuner          = -1, /* card has no tuner */
        .svhs           = 3,
-       .gpiomask       = 0x00, 
+       .gpiomask       = 0x00,
        .muxsel         = { 2, 3, 1, 0},
        .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
        .needs_tvaudio  = 1,
@@ -1918,7 +1906,7 @@ struct tvcard bttv_tvcards[] = {
        .no_tda9875     = 1,
        .no_tda7432     = 1,
        .gpiomask       = 0x00,
-       .muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
+       .muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                            0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
        .muxsel_hook    = ivc120_muxsel,
        .pll            = PLL_28,
@@ -2081,18 +2069,16 @@ struct tvcard bttv_tvcards[] = {
         .pll            = PLL_28,
         .has_dvb        = 1,
         .no_gpioirq     = 1,
-#if 0 /* untested */
         .has_remote     = 1,
-#endif
 },{
        /* ---- card 0x7c ---------------------------------- */
        /* Matt Jesson <dvb@jesson.eclipse.co.uk> */
        /* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */
        .name           = "AverMedia AverTV DVB-T 761",
-       .video_inputs   = 1,
+       .video_inputs   = 2,
        .tuner          = -1,
-       .svhs           = -1,
-       .muxsel         = { 2, 3, 1, 0},
+       .svhs           = 1,
+       .muxsel         = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
        .no_tda7432     = 1,
@@ -2147,9 +2133,64 @@ struct tvcard bttv_tvcards[] = {
        .tuner_type     = TUNER_PHILIPS_PAL,
        .has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
        .has_radio      = 1,   /* not every card has radio */
+},{
+
+       /* ---- card 0x80 ---------------------------------- */
+       /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
+       .name           = "DVICO FusionHDTV DVB-T Lite",
+       .tuner          = -1,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .pll            = PLL_28,
+       .no_video       = 1,
+       .has_dvb        = 1,
+       .tuner_type     = -1,
+},{
+       /* Steven <photon38@pchome.com.tw> */
+       .name           = "V-Gear MyVCD",
+       .video_inputs   = 3,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x3f,
+       .muxsel         = {2, 3, 1, 0},
+       .audiomux       = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31},
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = TUNER_PHILIPS_NTSC_M,
+       .has_radio      = 0,
+       // .has_remote     = 1,
+},{
+       /* Rick C <cryptdragoon@gmail.com> */
+        .name           = "Super TV Tuner",
+        .video_inputs   = 4,
+        .audio_inputs   = 1,
+        .tuner          = 0,
+        .svhs           = 2,
+        .muxsel         = { 2, 3, 1, 0},
+        .tuner_type     = TUNER_PHILIPS_NTSC,
+        .gpiomask       = 0x008007,
+        .audiomux       = { 0, 0x000001,0,0, 0},
+        .needs_tvaudio  = 1,
+        .has_radio      = 1,
+},{
+               /* Chris Fanning <video4linux@haydon.net> */
+               .name           = "Tibet Systems 'Progress DVR' CS16",
+               .video_inputs   = 16,
+               .audio_inputs   = 0,
+               .tuner          = -1,
+               .svhs           = -1,
+               .muxsel         = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+               .pll            = PLL_28,
+               .no_msp34xx     = 1,
+               .no_tda9875     = 1,
+               .no_tda7432     = 1,
+               .tuner_type     = -1,
+               .muxsel_hook    = tibetCS16_muxsel,
 }};
 
-const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
+static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
 
 /* ----------------------------------------------------------------------- */
 
@@ -2175,7 +2216,7 @@ void __devinit bttv_idcard(struct bttv *btv)
                for (type = -1, i = 0; cards[i].id != 0; i++)
                        if (cards[i].id  == btv->cardid)
                                type = i;
-               
+
                if (type != -1) {
                        /* found it */
                        printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
@@ -2192,12 +2233,12 @@ void __devinit bttv_idcard(struct bttv *btv)
                        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->c.nr] < bttv_num_tvcards)
                btv->c.type=card[btv->c.nr];
-       
+
        /* print which card config we are using */
        printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
               bttv_tvcards[btv->c.type].name, btv->c.type,
@@ -2237,7 +2278,7 @@ void __devinit bttv_idcard(struct bttv *btv)
 void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
 {
        int type = -1;
-       
+
        if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13))
                type = BTTV_MODTEC_205;
        else if (0 == strncmp(eeprom_data+20,"Picolo",7))
@@ -2253,7 +2294,7 @@ void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
 }
 
 static void flyvideo_gpio(struct bttv *btv)
-{ 
+{
        int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
        int tuner=-1,ttype;
 
@@ -2267,10 +2308,10 @@ static void flyvideo_gpio(struct bttv *btv)
        //       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
        //       GPIO14-12: n.c.
        // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-       
+
        // lowest 3 bytes are remote control codes (no handshake needed)
         // xxxFFF: No remote control chip soldered
-        // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered 
+        // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
        // Note: Some bits are Audio_Mask !
 
        ttype=(gpio&0x0f0000)>>16;
@@ -2298,18 +2339,18 @@ static void flyvideo_gpio(struct bttv *btv)
        is_lr90             = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only)
         //                     gpio & 0x001000 // output bit for audio routing
 
-       if(is_capture_only) 
-               tuner=4; // No tuner present 
+       if(is_capture_only)
+               tuner=4; // No tuner present
 
-       printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", 
-              btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); 
+       printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+              btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
        printk(KERN_INFO "bttv%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-               btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", 
+               btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
                is_capture_only?"yes":"no ");
 
        if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through
                btv->tuner_type = tuner;
-       btv->has_radio = has_radio;  
+       btv->has_radio = has_radio;
 
        // LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
         // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
@@ -2318,10 +2359,10 @@ static void flyvideo_gpio(struct bttv *btv)
        //todo: if(has_tda9874) btv->audio_hook = fv2000s_audio;
 }
 
-int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
-                       14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
-int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
-                       1,1,1,1,   1,1,1,0,  0,0,0,0,  0,1,0,0 };
+static int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
+                              14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
+static int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
+                              1,1,1,1,   1,1,1,0,  0,0,0,0,  0,1,0,0 };
 
 static void miro_pinnacle_gpio(struct bttv *btv)
 {
@@ -2408,13 +2449,13 @@ static void init_ids_eagle(struct bttv *btv)
 {
        gpio_inout(0xffffff,0xFFFF37);
        gpio_write(0x200020);
-       
+
        /* flash strobe inverter ?! */
        gpio_write(0x200024);
-       
+
        /* switch sync drive off */
        gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
-       
+
        /* set BT848 muxel to 2 */
        btaor((2)<<5, ~(2<<5), BT848_IFORM);
 }
@@ -2490,7 +2531,7 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
 
 /* ----------------------------------------------------------------------- */
 
-void bttv_reset_audio(struct bttv *btv)
+static void bttv_reset_audio(struct bttv *btv)
 {
        /*
         * BT878A has a audio-reset register.
@@ -2503,7 +2544,7 @@ void bttv_reset_audio(struct bttv *btv)
         */
        if (btv->id != 878)
                return;
-       
+
        if (bttv_debug)
                printk("bttv%d: BT878A ARESET\n",btv->c.nr);
        btwrite((1<<7), 0x058);
@@ -2533,11 +2574,14 @@ void __devinit bttv_init_card1(struct bttv *btv)
                btv->use_i2c_hw = 1;
                break;
        }
+       if (!bttv_tvcards[btv->c.type].has_dvb)
+               bttv_reset_audio(btv);
 }
 
 /* initialization part two -- after registering i2c bus */
 void __devinit bttv_init_card2(struct bttv *btv)
 {
+       int tda9887;
         btv->tuner_type = -1;
 
        if (BTTV_UNKNOWN == btv->c.type) {
@@ -2549,7 +2593,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
        case BTTV_MIRO:
        case BTTV_MIROPRO:
        case BTTV_PINNACLE:
-       case BTTV_PINNACLEPRO: 
+       case BTTV_PINNACLEPRO:
                /* miro/pinnacle */
                miro_pinnacle_gpio(btv);
                break;
@@ -2635,6 +2679,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
        case BTTV_LMLBT4:
                init_lmlbt4x(btv);
                break;
+       case BTTV_TIBET_CS16:
+               tibetCS16_init(btv);
+               break;
        }
 
        /* pll configuration */
@@ -2671,9 +2718,11 @@ void __devinit bttv_init_card2(struct bttv *btv)
         }
        btv->pll.pll_current = -1;
 
+       bttv_reset_audio(btv);
+
        /* tuner configuration (from card list / autodetect / insmod option) */
        if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
-               if(UNSET == btv->tuner_type) 
+               if(UNSET == btv->tuner_type)
                        btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
        if (UNSET != tuner[btv->c.nr])
                btv->tuner_type = tuner[btv->c.nr];
@@ -2705,110 +2754,47 @@ void __devinit bttv_init_card2(struct bttv *btv)
                        boot_bt832(btv);
        }
 
+       if (!autoload)
+               return;
+
        /* try to detect audio/fader chips */
        if (!bttv_tvcards[btv->c.type].no_msp34xx &&
-           bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) {
-               if (autoload)
-                       request_module("msp3400");
-       }
+           bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0)
+               request_module("msp3400");
 
        if (bttv_tvcards[btv->c.type].msp34xx_alt &&
-           bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) {
-               if (autoload)
-                       request_module("msp3400");
-       }
+           bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0)
+               request_module("msp3400");
 
        if (!bttv_tvcards[btv->c.type].no_tda9875 &&
-           bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
-               if (autoload)
-                       request_module("tda9875");
-       }
+           bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0)
+               request_module("tda9875");
 
-       if (!bttv_tvcards[btv->c.type].no_tda7432 && 
-           bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) {
-               if (autoload)
-                       request_module("tda7432");
-       }
+       if (!bttv_tvcards[btv->c.type].no_tda7432 &&
+           bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0)
+               request_module("tda7432");
 
-       if (bttv_tvcards[btv->c.type].needs_tvaudio) {
-               if (autoload)
-                       request_module("tvaudio");
-       }
+       if (bttv_tvcards[btv->c.type].needs_tvaudio)
+               request_module("tvaudio");
 
        /* tuner modules */
-       if (btv->pinnacle_id != UNSET) {
-               if (autoload)
-                       request_module("tda9887");
-       }
-       if (btv->tuner_type != UNSET) {
-               if (autoload)
-                       request_module("tuner");
-       }
+       tda9887 = 0;
+       if (btv->pinnacle_id != UNSET)
+               tda9887 = 1;
+       if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
+           bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
+               tda9887 = 1;
+       if((btv->tuner_type == TUNER_PHILIPS_FM1216ME_MK3) ||
+          (btv->tuner_type == TUNER_PHILIPS_FM1236_MK3) ||
+          (btv->tuner_type == TUNER_PHILIPS_FM1256_IH3) ||
+           tda9887)
+               request_module("tda9887");
+       if (btv->tuner_type != UNSET)
+               request_module("tuner");
 }
 
 
 /* ----------------------------------------------------------------------- */
-/* some hauppauge specific stuff                                           */
-
-static struct HAUPPAUGE_TUNER 
-{
-        int  id;
-        char *name;
-} 
-hauppauge_tuner[] __devinitdata = 
-{
-        { TUNER_ABSENT,        "" },
-        { TUNER_ABSENT,        "External" },
-        { TUNER_ABSENT,        "Unspecified" },
-        { TUNER_PHILIPS_PAL,   "Philips FI1216" },
-        { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
-        { TUNER_PHILIPS_NTSC,  "Philips FI1236" },
-        { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
-        { TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
-        { TUNER_PHILIPS_PAL,   "Philips FI1216 MK2" },
-        { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
-        { TUNER_PHILIPS_NTSC,  "Philips FI1236 MK2" },
-        { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
-        { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
-        { TUNER_TEMIC_NTSC,    "Temic 4032FY5" },
-        { TUNER_TEMIC_PAL,     "Temic 4002FH5" },
-        { TUNER_TEMIC_PAL_I,   "Temic 4062FY5" },
-        { TUNER_PHILIPS_PAL,   "Philips FR1216 MK2" },
-        { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
-        { TUNER_PHILIPS_NTSC,  "Philips FR1236 MK2" },
-        { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
-        { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
-        { TUNER_PHILIPS_PAL,   "Philips FM1216" },
-        { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
-        { TUNER_PHILIPS_NTSC,  "Philips FM1236" },
-        { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
-        { TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
-        { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
-        { TUNER_ABSENT,        "Samsung TCPN9082D" },
-        { TUNER_ABSENT,        "Samsung TCPM9092P" },
-        { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
-        { TUNER_ABSENT,        "Samsung TCPN9085D" },
-        { TUNER_ABSENT,        "Samsung TCPB9085P" },
-        { TUNER_ABSENT,        "Samsung TCPL9091P" },
-        { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
-        { TUNER_PHILIPS_FQ1216ME,   "Philips FQ1216 ME" },
-        { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
-        { TUNER_PHILIPS_NTSC,        "Philips TD1536" },
-        { TUNER_PHILIPS_NTSC,        "Philips TD1536D" },
-       { TUNER_PHILIPS_NTSC,  "Philips FMR1236" }, /* mono radio */
-        { TUNER_ABSENT,        "Philips FI1256MP" },
-        { TUNER_ABSENT,        "Samsung TCPQ9091P" },
-        { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
-        { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
-        { TUNER_TEMIC_4046FM5,     "Temic 4046FM5" },
-       { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
-       { TUNER_ABSENT,        "Philips TD1536D_FH_44"},
-       { 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"}
-};
 
 static void modtec_eeprom(struct bttv *btv)
 {
@@ -2832,30 +2818,11 @@ static void modtec_eeprom(struct bttv *btv)
 
 static void __devinit hauppauge_eeprom(struct bttv *btv)
 {
-       unsigned int blk2,tuner,radio,model;
-
-       if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
-               printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
-                      btv->c.nr);
+       struct tveeprom tv;
 
-       /* Block 2 starts after len+3 bytes header */
-       blk2 = eeprom_data[1] + 3;
-
-       /* decode + use some config infos */
-       model = eeprom_data[12] << 8 | eeprom_data[11];
-       tuner = eeprom_data[9];
-       radio = eeprom_data[blk2-1] & 0x01;
-       
-        if (tuner < ARRAY_SIZE(hauppauge_tuner))
-                btv->tuner_type = hauppauge_tuner[tuner].id;
-       if (radio)
-               btv->has_radio = 1;
-       
-       if (bttv_verbose)
-               printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, "
-                      "tuner=%s (%d), radio=%s\n",
-                      btv->c.nr, model, hauppauge_tuner[tuner].name,
-                      btv->tuner_type, radio ? "yes" : "no");
+       tveeprom_hauppauge_analog(&tv, eeprom_data);
+       btv->tuner_type = tv.tuner_type;
+       btv->has_radio  = tv.has_radio;
 }
 
 static int terratec_active_radio_upgrade(struct bttv *btv)
@@ -2886,7 +2853,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
                btv->has_matchbox = 0;
        }
        return 0;
-}      
+}
 
 
 /* ----------------------------------------------------------------------- */
@@ -2913,7 +2880,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
        gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG);
        gpio_write(0);
        udelay(PVR_GPIO_DELAY);
-       
+
        gpio_write(BTTV_ALT_NCONFIG);
        udelay(PVR_GPIO_DELAY);
 
@@ -2923,7 +2890,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
                        gpio_bits(BTTV_ALT_DCLK,0);
                        if (bits & 0x01)
                                gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
-                       else 
+                       else
                                gpio_bits(BTTV_ALT_DATA,0);
                        gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
                        bits >>= 1;
@@ -2931,7 +2898,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
        }
        gpio_bits(BTTV_ALT_DCLK,0);
        udelay(PVR_GPIO_DELAY);
-       
+
        /* begin Altera init loop (Not necessary,but doesn't hurt) */
        for (i = 0 ; i < 30 ; i++) {
                gpio_bits(BTTV_ALT_DCLK,0);
@@ -2941,41 +2908,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
        return 0;
 }
 
-#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
-/* 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;
-       u8 *micro;
-       int result;
-
-       microlen = mod_firmware_load(firm_altera, (char**) &micro);
-       if (!microlen) {
-               printk(KERN_WARNING "bttv%d: altera firmware not found [%s]\n",
-                      btv->c.nr, firm_altera);
-               return -1;
-       }
-       
-       printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n",
-              btv->c.nr, firm_altera);
-       result = pvr_altera_load(btv, micro, microlen);
-       printk(KERN_INFO "bttv%d: ... upload %s\n",
-              btv->c.nr, (result < 0) ? "failed" : "ok");
-       vfree(micro);
-       return result;
-}
-#else
-/* new 2.5.x way -- via hotplug firmware loader */
-
-int __devinit pvr_boot(struct bttv *btv)
+static int __devinit pvr_boot(struct bttv *btv)
 {
         const struct firmware *fw_entry;
        int rc;
@@ -2991,8 +2924,7 @@ int __devinit pvr_boot(struct bttv *btv)
               btv->c.nr, (rc < 0) ? "failed" : "ok");
         release_firmware(fw_entry);
        return rc;
-}      
-#endif
+}
 
 /* ----------------------------------------------------------------------- */
 /* some osprey specific stuff                                              */
@@ -3002,7 +2934,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
        int i = 0;
        unsigned char *ee = eeprom_data;
        unsigned long serial = 0;
-    
+
        if (btv->c.type == 0) {
                /* this might be an antique... check for MMAC label in eeprom */
                if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) {
@@ -3018,7 +2950,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
        } else {
               unsigned short type;
                int offset = 4*16;
-        
+
                for(; offset < 8*16; offset += 16) {
                        unsigned short checksum = 0;
                        /* verify the checksum */
@@ -3029,13 +2961,13 @@ static void __devinit osprey_eeprom(struct bttv *btv)
                                break;
                        }
                }
-        
+
                if (offset >= 8*16)
                       return;
 
               /* found a valid descriptor */
               type = (ee[offset+4]<<8) | (ee[offset+5]);
-              
+
               switch(type) {
 
               /* 848 based */
@@ -3045,7 +2977,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
               case 0x0005:
                       btv->c.type = BTTV_OSPREY101_848;
                       break;
-                      
+
                /* 878 based */
               case 0x0012:
               case 0x0013:
@@ -3093,20 +3025,21 @@ static void __devinit osprey_eeprom(struct bttv *btv)
                       | (ee[offset+8] <<  8)
                       | (ee[offset+9]);
        }
-       
+
        printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n",
              btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial);
-}      
+}
 
 /* ----------------------------------------------------------------------- */
 /* AVermedia specific stuff, from  bktr_card.c                             */
 
-int tuner_0_table[] = {
+static int tuner_0_table[] = {
         TUNER_PHILIPS_NTSC,  TUNER_PHILIPS_PAL /* PAL-BG*/,
         TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL /* PAL-I*/,
         TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
         TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
-        TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL};
+        TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL,
+       TUNER_PHILIPS_FM1216ME_MK3 };
 #if 0
 int tuner_0_fm_table[] = {
         PHILIPS_FR1236_NTSC,  PHILIPS_FR1216_PAL,
@@ -3116,7 +3049,7 @@ int tuner_0_fm_table[] = {
         PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL};
 #endif
 
-int tuner_1_table[] = {
+static int tuner_1_table[] = {
         TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
        TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
        TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
@@ -3133,12 +3066,16 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
        btv->has_remote = (eeprom_data[0x42] & 0x01);
 
        if (tuner_make == 0 || tuner_make == 2)
-               if(tuner_format <=9)
+               if(tuner_format <=0x0a)
                        tuner = tuner_0_table[tuner_format];
        if (tuner_make == 1)
                if(tuner_format <=9)
                        tuner = tuner_1_table[tuner_format];
-       
+
+       if (tuner_make == 4)
+               if(tuner_format == 0x09)
+                       tuner = TUNER_LG_NTSC_NEW_TAPC; // TAPC-G702P
+
        printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
                btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
        if(tuner) {
@@ -3196,6 +3133,7 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
 
 static void __devinit boot_bt832(struct bttv *btv)
 {
+#if 0 /* not working yet */
        int resetbit=0;
 
        switch (btv->c.type) {
@@ -3224,12 +3162,13 @@ static void __devinit boot_bt832(struct bttv *btv)
        // bt832 on pixelview changes from i2c 0x8a to 0x88 after
        // being reset as above. So we must follow by this:
        bttv_call_i2c_clients(btv, BT832_REATTACH, NULL);
+#endif
 }
 
 /* ----------------------------------------------------------------------- */
 /*  Imagenation L-Model PXC200 Framegrabber */
-/*  This is basically the same procedure as 
- *  used by Alessandro Rubini in his pxc200 
+/*  This is basically the same procedure as
+ *  used by Alessandro Rubini in his pxc200
  *  driver, but using BTTV functions */
 
 static void __devinit init_PXC200(struct bttv *btv)
@@ -3240,13 +3179,13 @@ static void __devinit init_PXC200(struct bttv *btv)
        unsigned int i;
        int tmp;
        u32 val;
-       
+
        /* Initialise GPIO-connevted stuff */
        gpio_inout(0xffffff, (1<<13));
        gpio_write(0);
        udelay(3);
        gpio_write(1<<13);
-       /* GPIO inputs are pulled up, so no need to drive 
+       /* GPIO inputs are pulled up, so no need to drive
         * reset pin any longer */
        gpio_bits(0xffffff, 0);
        if (bttv_gpio)
@@ -3261,16 +3200,16 @@ static void __devinit init_PXC200(struct bttv *btv)
        */
 
        btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
-       
+
        /*      Initialise MAX517 DAC */
        printk(KERN_INFO "Setting DAC reference voltage level ...\n");
        bttv_I2CWrite(btv,0x5E,0,0x80,1);
-       
+
        /*      Initialise 12C508 PIC */
-       /*      The I2CWrite and I2CRead commmands are actually to the 
+       /*      The I2CWrite and I2CRead commmands are actually to the
         *      same chips - but the R/W bit is included in the address
         *      argument so the numbers are different */
-       
+
 
        printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
 
@@ -3278,7 +3217,7 @@ static void __devinit init_PXC200(struct bttv *btv)
        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
@@ -3310,7 +3249,7 @@ static void __devinit init_PXC200(struct bttv *btv)
  * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
  */
 
-void bus_low(struct bttv *btv, int bit)
+static void bus_low(struct bttv *btv, int bit)
 {
        if (btv->mbox_ior) {
                gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
@@ -3327,7 +3266,7 @@ void bus_low(struct bttv *btv, int bit)
        }
 }
 
-void bus_high(struct bttv *btv, int bit)
+static void bus_high(struct bttv *btv, int bit)
 {
        if (btv->mbox_ior) {
                gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
@@ -3344,7 +3283,7 @@ void bus_high(struct bttv *btv, int bit)
        }
 }
 
-int bus_in(struct bttv *btv, int bit)
+static int bus_in(struct bttv *btv, int bit)
 {
        if (btv->mbox_ior) {
                gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
@@ -3390,7 +3329,7 @@ static int tea5757_read(struct bttv *btv)
        unsigned long timeout;
        int value = 0;
        int i;
-       
+
        /* better safe than sorry */
        gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
 
@@ -3402,10 +3341,10 @@ static int tea5757_read(struct bttv *btv)
 
        if (bttv_gpio)
                bttv_gpio_tracking(btv,"tea5757 read");
-       
+
        bus_low(btv,btv->mbox_we);
        bus_low(btv,btv->mbox_clk);
-       
+
        udelay(10);
        timeout= jiffies + HZ;
 
@@ -3437,7 +3376,7 @@ static int tea5757_write(struct bttv *btv, int value)
 {
        int i;
        int reg = value;
-       
+
        gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
 
        if (btv->mbox_ior) {
@@ -3492,7 +3431,7 @@ void winview_audio(struct bttv *btv, struct video_audio *v, int set)
                v->flags |= VIDEO_AUDIO_VOLUME;
                return;
        }
-       
+
        /* 32 levels logarithmic */
        vol = 32 - ((v->volume>>11));
        /* units */
@@ -3519,7 +3458,7 @@ void winview_audio(struct bttv *btv, struct video_audio *v, int set)
        data |=  WINVIEW_PT2254_STROBE;
        data &= ~WINVIEW_PT2254_DATA;
        gpio_write(data);
-       udelay(10);                     
+       udelay(10);
        data &= ~WINVIEW_PT2254_STROBE;
        gpio_write(data);
 }
@@ -3644,7 +3583,7 @@ static void
 avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set)
 {
        int val = 0;
-       
+
        if (set) {
                if (v->mode & VIDEO_SOUND_LANG2)   /* SAP */
                        val = 0x01;
@@ -3779,7 +3718,7 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
 
 /*
  * Dariusz Kowalewski <darekk@automex.pl>
- * sound control for FlyVideo 2000S (with tda9874 decoder) 
+ * sound control for FlyVideo 2000S (with tda9874 decoder)
  * based on pvbt878p9b_audio() - this is not tested, please fix!!!
  */
 static void
@@ -3914,6 +3853,47 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input)
        mdelay(1);
 }
 
+/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning]
+ *
+ * The CS16 (available on eBay cheap) is a PCI board with four Fusion
+ * 878A chips, a PCI bridge, an Atmel microcontroller, four sync seperator
+ * chips, ten eight input analog multiplexors, a not chip and a few
+ * other components.
+ *
+ * 16 inputs on a secondary bracket are provided and can be selected
+ * from each of the four capture chips.  Two of the eight input
+ * multiplexors are used to select from any of the 16 input signals.
+ *
+ * Unsupported hardware capabilities:
+ *  . A video output monitor on the secondary bracket can be selected from
+ *    one of the 878A chips.
+ *  . Another passthrough but I haven't spent any time investigating it.
+ *  . Digital I/O (logic level connected to GPIO) is available from an
+ *    onboard header.
+ *
+ * The on chip input mux should always be set to 2.
+ * GPIO[16:19] - Video input selection
+ * GPIO[0:3]   - Video output monitor select (only available from one 878A)
+ * GPIO[?:?]   - Digital I/O.
+ *
+ * There is an ATMEL microcontroller with an 8031 core on board.  I have not
+ * determined what function (if any) it provides.  With the microcontroller
+ * and sync seperator chips a guess is that it might have to do with video
+ * switching and maybe some digital I/O.
+ */
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input)
+{
+       /* video mux */
+       gpio_bits(0x0f0000, input << 16);
+}
+
+static void tibetCS16_init(struct bttv *btv)
+{
+       /* enable gpio bits, mask obtained via btSpy */
+       gpio_inout(0xffffff, 0x0f7fff);
+       gpio_write(0x0f7fff);
+}
+
 // The 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
@@ -3962,13 +3942,13 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
  * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
  *
  * The IVC120G security card has 4 i2c controlled TDA8540 matrix
- * swichers to provide 16 channels to MUX0. The TDA8540's have 
- * 4 indepedant outputs and as such the IVC120G also has the 
- * optional "Monitor Out" bus. This allows the card to be looking 
+ * swichers to provide 16 channels to MUX0. The TDA8540's have
+ * 4 indepedant outputs and as such the IVC120G also has the
+ * optional "Monitor Out" bus. This allows the card to be looking
  * at one input while the monitor is looking at another.
  *
  * Since I've couldn't be bothered figuring out how to add an
- * independant muxsel for the monitor bus, I've just set it to 
+ * independant muxsel for the monitor bus, I've just set it to
  * whatever the card is looking at.
  *
  *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
@@ -3993,12 +3973,12 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
 static void ivc120_muxsel(struct bttv *btv, unsigned int input)
 {
        // Simple maths
-       int key = input % 4;    
+       int key = input % 4;
        int matrix = input / 4;
-       
+
        dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
                btv->c.nr, input, matrix, key);
-       
+
        // Handles the input selection on the TDA8540's
        bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
                      ((matrix == 3) ? (key | key << 2) : 0x00), 1);
@@ -4008,22 +3988,102 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
                      ((matrix == 1) ? (key | key << 2) : 0x00), 1);
        bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
                      ((matrix == 2) ? (key | key << 2) : 0x00), 1);
-       
+
        // Handles the output enables on the TDA8540's
        bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
                      ((matrix == 3) ? 0x03 : 0x00), 1);  // 13 - 16
        bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
                      ((matrix == 0) ? 0x03 : 0x00), 1);  // 1-4
        bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
-                     ((matrix == 1) ? 0x03 : 0x00), 1);  // 5-8 
+                     ((matrix == 1) ? 0x03 : 0x00), 1);  // 5-8
        bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
                      ((matrix == 2) ? 0x03 : 0x00), 1);  // 9-12
-       
+
        // Selects MUX0 for input on the 878
        btaor((0)<<5, ~(3<<5), BT848_IFORM);
 }
 
 
+/* PXC200 muxsel helper
+ * luke@syseng.anu.edu.au
+ * another transplant
+ * from Alessandro Rubini (rubini@linux.it)
+ *
+ * There are 4 kinds of cards:
+ * PXC200L which is bt848
+ * PXC200F which is bt848 with PIC controlling mux
+ * PXC200AL which is bt878
+ * PXC200AF which is bt878 with PIC controlling mux
+ */
+#define PX_CFG_PXC200F 0x01
+#define PX_FLAG_PXC200A  0x00001000 /* a pxc200A is bt-878 based */
+#define PX_I2C_PIC       0x0f
+#define PX_PXC200A_CARDID 0x200a1295
+#define PX_I2C_CMD_CFG   0x00
+
+static void PXC200_muxsel(struct bttv *btv, unsigned int input)
+{
+        int rc;
+       long mux;
+       int bitmask;
+        unsigned char buf[2];
+
+       /* Read PIC config to determine if this is a PXC200F */
+       /* PX_I2C_CMD_CFG*/
+       buf[0]=0;
+       buf[1]=0;
+       rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
+       if (rc) {
+         printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
+         /* not PXC ? do nothing */
+         return;
+       }
+
+       rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
+       if (!(rc & PX_CFG_PXC200F)) {
+         printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
+         return;
+       }
+
+
+       /* The multiplexer in the 200F is handled by the GPIO port */
+       /* get correct mapping between inputs  */
+       /*  mux = bttv_tvcards[btv->type].muxsel[input] & 3; */
+       /* ** not needed!?   */
+       mux = input;
+
+       /* make sure output pins are enabled */
+       /* bitmask=0x30f; */
+       bitmask=0x302;
+       /* check whether we have a PXC200A */
+       if (btv->cardid == PX_PXC200A_CARDID)  {
+          bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */
+          bitmask |= 7<<4; /* the DAC */
+       }
+       btwrite(bitmask, BT848_GPIO_OUT_EN);
+
+       bitmask = btread(BT848_GPIO_DATA);
+       if (btv->cardid == PX_PXC200A_CARDID)
+         bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7);
+       else /* older device */
+         bitmask = (bitmask & ~0x300) | ((mux & 3) << 8);
+       btwrite(bitmask,BT848_GPIO_DATA);
+
+       /*
+        * Was "to be safe, set the bt848 to input 0"
+        * Actually, since it's ok at load time, better not messing
+        * with these bits (on PXC200AF you need to set mux 2 here)
+        *
+        * needed because bttv-driver sets mux before calling this function
+        */
+       if (btv->cardid == PX_PXC200A_CARDID)
+         btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM);
+       else /* older device */
+         btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
+
+       printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
+}
+
 /* ----------------------------------------------------------------------- */
 /* motherboard chipset specific stuff                                      */
 
@@ -4110,86 +4170,6 @@ int __devinit bttv_handle_chipset(struct bttv *btv)
 }
 
 
-/* PXC200 muxsel helper
- * luke@syseng.anu.edu.au
- * another transplant
- * from Alessandro Rubini (rubini@linux.it)
- *
- * There are 4 kinds of cards:
- * PXC200L which is bt848
- * PXC200F which is bt848 with PIC controlling mux
- * PXC200AL which is bt878
- * PXC200AF which is bt878 with PIC controlling mux
- */
-#define PX_CFG_PXC200F 0x01
-#define PX_FLAG_PXC200A  0x00001000 /* a pxc200A is bt-878 based */
-#define PX_I2C_PIC       0x0f
-#define PX_PXC200A_CARDID 0x200a1295
-#define PX_I2C_CMD_CFG   0x00
-
-static void PXC200_muxsel(struct bttv *btv, unsigned int input)
-{
-        int rc;
-       long mux;
-       int bitmask;
-        unsigned char buf[2];
-
-       /* Read PIC config to determine if this is a PXC200F */
-       /* PX_I2C_CMD_CFG*/
-       buf[0]=0;
-       buf[1]=0;
-       rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
-       if (rc) {
-         printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc);
-         /* not PXC ? do nothing */
-         return;
-       }
-
-       rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),0);
-       if (!(rc & PX_CFG_PXC200F)) {
-         printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
-         return;
-       }
-
-
-       /* The multiplexer in the 200F is handled by the GPIO port */
-       /* get correct mapping between inputs  */
-       /*  mux = bttv_tvcards[btv->type].muxsel[input] & 3; */
-       /* ** not needed!?   */
-       mux = input;
-
-       /* make sure output pins are enabled */
-       /* bitmask=0x30f; */
-       bitmask=0x302;
-       /* check whether we have a PXC200A */
-       if (btv->cardid == PX_PXC200A_CARDID)  {
-          bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */
-          bitmask |= 7<<4; /* the DAC */
-       }
-       btwrite(bitmask, BT848_GPIO_OUT_EN);
-
-       bitmask = btread(BT848_GPIO_DATA);
-       if (btv->cardid == PX_PXC200A_CARDID)
-         bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7);
-       else /* older device */
-         bitmask = (bitmask & ~0x300) | ((mux & 3) << 8);
-       btwrite(bitmask,BT848_GPIO_DATA);
-
-       /*
-        * Was "to be safe, set the bt848 to input 0"
-        * Actually, since it's ok at load time, better not messing
-        * with these bits (on PXC200AF you need to set mux 2 here)
-        *
-        * needed because bttv-driver sets mux before calling this function
-        */
-       if (btv->cardid == PX_PXC200A_CARDID)
-         btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM);
-       else /* older device */
-         btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
-
-       printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
-}
-
 /*
  * Local variables:
  * c-basic-offset: 8