include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / media / video / saa7134 / saa7134-dvb.c
index a51264f..4ab4a98 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/suspend.h>
 #include "saa7134.h"
 #include <media/v4l2-common.h>
 #include "dvb-pll.h"
+#include <dvb_frontend.h>
 
 #include "mt352.h"
 #include "mt352_priv.h" /* FIXME */
 #include "tda1004x.h"
 #include "nxt200x.h"
+#include "tuner-xc2028.h"
+#include "xc5000.h"
 
 #include "tda10086.h"
 #include "tda826x.h"
+#include "tda827x.h"
 #include "isl6421.h"
+#include "isl6405.h"
+#include "lnbp21.h"
+#include "tuner-simple.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "lgdt3305.h"
+#include "tda8290.h"
+
+#include "zl10353.h"
+
+#include "zl10036.h"
+#include "zl10039.h"
+#include "mt312.h"
+
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
-static unsigned int antenna_pwr = 0;
+static unsigned int antenna_pwr;
 
 module_param(antenna_pwr, int, 0444);
 MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
 
-/* ------------------------------------------------------------------ */
+static int use_frontend;
+module_param(use_frontend, int, 0644);
+MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(fmt, arg...)   do { if (debug) \
+       printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
+
+/* Print a warning */
+#define wprintk(fmt, arg...) \
+       printk(KERN_WARNING "%s/dvb: " fmt, dev->name, ## arg)
+
+/* ------------------------------------------------------------------
+ * mt352 based DVB-T cards
+ */
+
 static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
 {
        u32 ok;
@@ -71,8 +108,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
        saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
        udelay(10);
        ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
-       printk("%s: %s %s\n", dev->name, __FUNCTION__,
-              ok ? "on" : "off");
+       dprintk("%s %s\n", __func__, ok ? "on" : "off");
 
        if (!ok)
                saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
@@ -92,7 +128,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
        static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
        struct saa7134_dev *dev= fe->dvb->priv;
 
-       printk("%s: %s called\n",dev->name,__FUNCTION__);
+       dprintk("%s called\n", __func__);
 
        mt352_write(fe, clock_config,   sizeof(clock_config));
        udelay(200);
@@ -127,6 +163,23 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
        return 0;
 }
 
+static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL, 0x38, 0x2d };
+       static u8 reset []         = { RESET, 0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0xe };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+       return 0;
+}
+
 static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
                                           struct dvb_frontend_parameters* params)
 {
@@ -144,7 +197,7 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
-       saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
+       saa_call_all(dev, tuner, s_frequency, &f);
        msg.buf = on;
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
@@ -156,18 +209,6 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
        return mt352_pinnacle_init(fe);
 }
 
-static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
-{
-       if (buf_len < 5)
-               return -EINVAL;
-
-       pllbuf[0] = 0x61;
-       dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1,
-                         params->frequency,
-                         params->u.ofdm.bandwidth);
-       return 5;
-}
-
 static struct mt352_config pinnacle_300i = {
        .demod_address = 0x3c >> 1,
        .adc_clock     = 20333,
@@ -181,10 +222,32 @@ static struct mt352_config avermedia_777 = {
        .demod_init    = mt352_aver777_init,
 };
 
-/* ------------------------------------------------------------------ */
-static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static struct mt352_config avermedia_xc3028_mt352_dev = {
+       .demod_address   = (0x1e >> 1),
+       .no_tuner        = 1,
+       .demod_init      = mt352_avermedia_xc3028_init,
+};
+
+/* ==================================================================
+ * tda1004x based DVB-T cards, helper functions
+ */
+
+static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
+                                          const struct firmware **fw, char *name)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       return request_firmware(fw, name, &dev->pci->dev);
+}
+
+/* ------------------------------------------------------------------
+ * these tuners are tu1216, td1316(a)
+ */
+
+static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
        u8 tuner_buf[4];
        struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len =
                        sizeof(tuner_buf) };
@@ -259,15 +322,20 @@ static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
+       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) {
+               wprintk("could not write to tuner at addr: 0x%02x\n",
+                       addr << 1);
                return -EIO;
+       }
        msleep(1);
        return 0;
 }
 
-static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe)
+static int philips_tu1216_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
        static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
        struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
 
@@ -283,46 +351,17 @@ static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe)
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tu1216_tuner_60_init(struct dvb_frontend *fe)
-{
-       return philips_tda6651_pll_init(0x60, fe);
-}
-
-static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       return philips_tda6651_pll_set(0x60, fe, params);
-}
-
-static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
-                                          const struct firmware **fw, char *name)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       return request_firmware(fw, name, &dev->pci->dev);
-}
-
 static struct tda1004x_config philips_tu1216_60_config = {
-
        .demod_address = 0x8,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .request_firmware = philips_tda1004x_request_firmware,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
-static int philips_tu1216_tuner_61_init(struct dvb_frontend *fe)
-{
-       return philips_tda6651_pll_init(0x61, fe);
-}
-
-static int philips_tu1216_tuner_61_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       return philips_tda6651_pll_set(0x61, fe, params);
-}
-
 static struct tda1004x_config philips_tu1216_61_config = {
 
        .demod_address = 0x8,
@@ -331,7 +370,8 @@ static struct tda1004x_config philips_tu1216_61_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .request_firmware = philips_tda1004x_request_firmware,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
 /* ------------------------------------------------------------------ */
@@ -339,24 +379,42 @@ static struct tda1004x_config philips_tu1216_61_config = {
 static int philips_td1316_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
        static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
-       struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
+       struct i2c_msg init_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
 
        /* setup PLL configuration */
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
                return -EIO;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
        return 0;
 }
 
 static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
-       return philips_tda6651_pll_set(0x61, fe, params);
+       return philips_tda6651_pll_set(fe, params);
+}
+
+static int philips_td1316_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
+       static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 };
+       struct i2c_msg analog_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+       /* switch the tuner to analog mode */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
+               return -EIO;
+       return 0;
 }
 
+/* ------------------------------------------------------------------ */
+
 static int philips_europa_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -376,18 +434,14 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe)
 static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
-       /* this message actually turns the tuner back to analog mode */
-       static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 };
-       struct i2c_msg analog_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
 
-       i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
-       msleep(1);
+       static u8 msg[] = { 0x00, 0x14 };
+       struct i2c_msg analog_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+       if (philips_td1316_tuner_sleep(fe))
+               return -EIO;
 
        /* switch the board to analog mode */
-       analog_msg.addr = 0x43;
-       analog_msg.len  = 0x02;
-       msg[0] = 0x00;
-       msg[1] = 0x14;
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
@@ -412,583 +466,374 @@ static struct tda1004x_config philips_europa_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_IFO_AUTO_POS,
        .if_freq       = TDA10046_FREQ_052,
-       .request_firmware = NULL,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
+static struct tda1004x_config medion_cardbus = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
+       .if_freq       = TDA10046_FREQ_3613,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+/* ------------------------------------------------------------------
+ * tda 1004x based cards with philips silicon tuner
+ */
 
-static int philips_fmd1216_tuner_init(struct dvb_frontend *fe)
+static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
 {
-       struct saa7134_dev *dev = fe->dvb->priv;
-       /* this message is to set up ATC and ALC */
-       static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
-       struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
+       struct tda1004x_state *state = fe->demodulator_priv;
 
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
+       u8 addr = state->config->i2c_gate;
+       static u8 tda8290_close[] = { 0x21, 0xc0};
+       static u8 tda8290_open[]  = { 0x21, 0x80};
+       struct i2c_msg tda8290_msg = {.addr = addr,.flags = 0, .len = 2};
+       if (enable) {
+               tda8290_msg.buf = tda8290_close;
+       } else {
+               tda8290_msg.buf = tda8290_open;
+       }
+       if (i2c_transfer(state->i2c, &tda8290_msg, 1) != 1) {
+               struct saa7134_dev *dev = fe->dvb->priv;
+               wprintk("could not access tda8290 I2C gate\n");
                return -EIO;
-       msleep(1);
-
+       }
+       msleep(20);
        return 0;
 }
 
-static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe)
+static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
-       /* this message actually turns the tuner back to analog mode */
-       static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 };
-       struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
+       struct tda1004x_state *state = fe->demodulator_priv;
 
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-       msleep(1);
-       fmd1216_init[2] = 0x86;
-       fmd1216_init[3] = 0x54;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-       msleep(1);
+       switch (state->config->antenna_switch) {
+       case 0: break;
+       case 1: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+               saa7134_set_gpio(dev, 21, 0);
+               break;
+       case 2: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+               saa7134_set_gpio(dev, 21, 1);
+               break;
+       }
        return 0;
 }
 
-static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
-       u8 tuner_buf[4];
-       struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = tuner_buf,.len =
-                       sizeof(tuner_buf) };
-       int tuner_frequency = 0;
-       int divider = 0;
-       u8 band, mode, cp;
-
-       /* determine charge pump */
-       tuner_frequency = params->frequency + 36130000;
-       if (tuner_frequency < 87000000)
-               return -EINVAL;
-       /* low band */
-       else if (tuner_frequency < 180000000) {
-               band = 1;
-               mode = 7;
-               cp   = 0;
-       } else if (tuner_frequency < 195000000) {
-               band = 1;
-               mode = 6;
-               cp   = 1;
-       /* mid band     */
-       } else if (tuner_frequency < 366000000) {
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
-                       band = 10;
-               } else {
-                       band = 2;
-               }
-               mode = 7;
-               cp   = 0;
-       } else if (tuner_frequency < 478000000) {
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
-                       band = 10;
-               } else {
-                       band = 2;
-               }
-               mode = 6;
-               cp   = 1;
-       /* high band */
-       } else if (tuner_frequency < 662000000) {
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
-                       band = 12;
-               } else {
-                       band = 4;
-               }
-               mode = 7;
-               cp   = 0;
-       } else if (tuner_frequency < 840000000) {
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
-                       band = 12;
-               } else {
-                       band = 4;
-               }
-               mode = 6;
-               cp   = 1;
-       } else {
-               if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
-                       band = 12;
-               } else {
-                       band = 4;
-               }
-               mode = 7;
-               cp   = 1;
+       struct tda1004x_state *state = fe->demodulator_priv;
 
+       switch (state->config->antenna_switch) {
+       case 0: break;
+       case 1: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+               saa7134_set_gpio(dev, 21, 1);
+               break;
+       case 2: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+               saa7134_set_gpio(dev, 21, 0);
+               break;
        }
-       /* calculate divisor */
-       /* ((36166000 + Finput) / 166666) rounded! */
-       divider = (tuner_frequency + 83333) / 166667;
-
-       /* setup tuner buffer */
-       tuner_buf[0] = (divider >> 8) & 0x7f;
-       tuner_buf[1] = divider & 0xff;
-       tuner_buf[2] = 0x80 | (cp << 6) | (mode  << 3) | 4;
-       tuner_buf[3] = 0x40 | band;
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
-               return -EIO;
        return 0;
 }
 
-static struct tda1004x_config medion_cardbus = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
-       .if_freq       = TDA10046_FREQ_3613,
-       .request_firmware = NULL,
-};
+static int configure_tda827x_fe(struct saa7134_dev *dev,
+                               struct tda1004x_config *cdec_conf,
+                               struct tda827x_config *tuner_conf)
+{
+       struct videobuf_dvb_frontend *fe0;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+
+       fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+       if (fe0->dvb.frontend) {
+               if (cdec_conf->i2c_gate)
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+               if (dvb_attach(tda827x_attach, fe0->dvb.frontend,
+                              cdec_conf->tuner_address,
+                              &dev->i2c_adap, tuner_conf))
+                       return 0;
+
+               wprintk("no tda827x tuner found at addr: %02x\n",
+                               cdec_conf->tuner_address);
+       }
+       return -EINVAL;
+}
 
 /* ------------------------------------------------------------------ */
 
-struct tda827x_data {
-       u32 lomax;
-       u8  spd;
-       u8  bs;
-       u8  bp;
-       u8  cp;
-       u8  gc3;
-       u8 div1p5;
+static struct tda827x_config tda827x_cfg_0 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 0,
+       .switch_addr = 0
 };
 
-static struct tda827x_data tda827x_dvbt[] = {
-       { .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
-       { .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
-       { .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
-       { .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
-       { .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
-       { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
-       { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-       { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-       { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-       { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
-       { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-       { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
-       { .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
+static struct tda827x_config tda827x_cfg_1 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 1,
+       .switch_addr = 0x4b
 };
 
-static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
-{
-       return 0;
-}
-
-static int philips_tda827x_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       u8 tuner_buf[14];
+static struct tda827x_config tda827x_cfg_2 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x4b
+};
 
-       struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,
-                                       .len = sizeof(tuner_buf) };
-       int i, tuner_freq, if_freq;
-       u32 N;
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
-               if_freq = 4000000;
-               break;
-       case BANDWIDTH_7_MHZ:
-               if_freq = 4500000;
-               break;
-       default:                   /* 8 MHz or Auto */
-               if_freq = 5000000;
-               break;
-       }
-       tuner_freq = params->frequency + if_freq;
+static struct tda827x_config tda827x_cfg_2_sw42 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x42
+};
 
-       i = 0;
-       while (tda827x_dvbt[i].lomax < tuner_freq) {
-               if(tda827x_dvbt[i + 1].lomax == 0)
-                       break;
-               i++;
-       }
+/* ------------------------------------------------------------------ */
 
-       N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2);
-       tuner_buf[0] = 0;
-       tuner_buf[1] = (N>>8) | 0x40;
-       tuner_buf[2] = N & 0xff;
-       tuner_buf[3] = 0;
-       tuner_buf[4] = 0x52;
-       tuner_buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) +
-                                  (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp;
-       tuner_buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f;
-       tuner_buf[7] = 0xbf;
-       tuner_buf[8] = 0x2a;
-       tuner_buf[9] = 0x05;
-       tuner_buf[10] = 0xff;
-       tuner_buf[11] = 0x00;
-       tuner_buf[12] = 0x00;
-       tuner_buf[13] = 0x40;
-
-       tuner_msg.len = 14;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
-               return -EIO;
+static struct tda1004x_config tda827x_lifeview_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-       msleep(500);
-       /* correct CP value */
-       tuner_buf[0] = 0x30;
-       tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp;
-       tuner_msg.len = 2;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+static struct tda1004x_config philips_tiger_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-       return 0;
-}
+static struct tda1004x_config cinergy_ht_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 tda827x_sleep[] = { 0x30, 0xd0};
-       struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep,
-                                   .len = sizeof(tda827x_sleep) };
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-       return 0;
-}
+static struct tda1004x_config cinergy_ht_pci_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-static struct tda1004x_config tda827x_lifeview_config = {
+static struct tda1004x_config philips_tiger_s_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
+static struct tda1004x_config pinnacle_pctv_310i_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-struct tda827xa_data {
-       u32 lomax;
-       u8  svco;
-       u8  spd;
-       u8  scr;
-       u8  sbs;
-       u8  gc3;
+static struct tda1004x_config hauppauge_hvr_1110_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-static struct tda827xa_data tda827xa_dvbt[] = {
-       { .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
-       { .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
-       { .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
-       { .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
-       { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
-       { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-       { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-       { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-       { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-       { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
-       { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
-       { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
-       { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
-       { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-       { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-       { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-       { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-       { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
-       { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-       { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-       { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-       { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-       { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-       { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-       { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-       { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
-       { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}};
-
-
-static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       u8 tuner_buf[14];
-       unsigned char reg2[2];
+static struct tda1004x_config asus_p7131_dual_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-       struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = tuner_buf};
-       int i, tuner_freq, if_freq;
-       u32 N;
+static struct tda1004x_config lifeview_trio_config = {
+       .demod_address = 0x09,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP00_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_6_MHZ:
-               if_freq = 4000000;
-               break;
-       case BANDWIDTH_7_MHZ:
-               if_freq = 4500000;
-               break;
-       default:                   /* 8 MHz or Auto */
-               if_freq = 5000000;
-               break;
-       }
-       tuner_freq = params->frequency + if_freq;
-
-       i = 0;
-       while (tda827xa_dvbt[i].lomax < tuner_freq) {
-               if(tda827xa_dvbt[i + 1].lomax == 0)
-                       break;
-               i++;
-       }
-
-       N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
-       tuner_buf[0] = 0;            // subaddress
-       tuner_buf[1] = N >> 8;
-       tuner_buf[2] = N & 0xff;
-       tuner_buf[3] = 0;
-       tuner_buf[4] = 0x16;
-       tuner_buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
-                       tda827xa_dvbt[i].sbs;
-       tuner_buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
-       tuner_buf[7] = 0x0c;
-       tuner_buf[8] = 0x06;
-       tuner_buf[9] = 0x24;
-       tuner_buf[10] = 0xff;
-       tuner_buf[11] = 0x60;
-       tuner_buf[12] = 0x00;
-       tuner_buf[13] = 0x39;  // lpsel
-       msg.len = 14;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-
-       msg.buf= reg2;
-       msg.len = 2;
-       reg2[0] = 0x60;
-       reg2[1] = 0x3c;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-       reg2[0] = 0xa0;
-       reg2[1] = 0x40;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-       msleep(2);
-       /* correct CP value */
-       reg2[0] = 0x30;
-       reg2[1] = 0x10 + tda827xa_dvbt[i].scr;
-       msg.len = 2;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-       msleep(550);
-       reg2[0] = 0x50;
-       reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-       return 0;
-
-}
-
-static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 tda827xa_sleep[] = { 0x30, 0x90};
-       struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep,
-                                   .len = sizeof(tda827xa_sleep) };
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 tda8290_close[] = { 0x21, 0xc0};
-       static u8 tda8290_open[]  = { 0x21, 0x80};
-       struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
-       if (enable) {
-               tda8290_msg.buf = tda8290_close;
-       } else {
-               tda8290_msg.buf = tda8290_open;
-       }
-       if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1)
-               return -EIO;
-       msleep(20);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       int ret;
-
-       ret = philips_tda827xa_pll_set(0x61, fe, params);
-       if (ret != 0)
-               return ret;
-       return 0;
-}
-
-static int philips_tiger_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 data[] = { 0x3c, 0x33, 0x6a};
-       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-
-       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-       return 0;
-}
-
-static int philips_tiger_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 data[] = { 0x3c, 0x33, 0x68};
-       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-       philips_tda827xa_tuner_sleep( 0x61, fe);
-       return 0;
-}
-
-static struct tda1004x_config philips_tiger_config = {
+static struct tda1004x_config tevion_dvbt220rf_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
-static struct tda1004x_config pinnacle_pctv_310i_config = {
+static struct tda1004x_config md8800_dvbt_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = philips_tda1004x_request_firmware,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
-static struct tda1004x_config hauppauge_hvr_1110_config = {
+static struct tda1004x_config asus_p7131_4871_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = philips_tda1004x_request_firmware,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
-
-static struct tda1004x_config asus_p7131_dual_config = {
+static struct tda1004x_config asus_p7131_hybrid_lna_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = philips_tda1004x_request_firmware,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 data[] = { 0x3c, 0x33, 0x6a};
-       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-
-       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-       /* make sure the DVB-T antenna input is set */
-       saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0200000);
-       return 0;
-}
-
-static int asus_p7131_dual_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 data[] = { 0x3c, 0x33, 0x68};
-       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-       philips_tda827xa_tuner_sleep( 0x61, fe);
-       /* reset antenna inputs for analog usage */
-       saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0200000);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int lifeview_trio_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       int ret;
-
-       ret = philips_tda827xa_pll_set(0x60, fe, params);
-       return ret;
-}
-
-static int lifeview_trio_tuner_sleep(struct dvb_frontend *fe)
-{
-       philips_tda827xa_tuner_sleep(0x60, fe);
-       return 0;
-}
+static struct tda1004x_config kworld_dvb_t_210_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-static struct tda1004x_config lifeview_trio_config = {
-       .demod_address = 0x09,
+static struct tda1004x_config avermedia_super_007_config = {
+       .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X_GPL,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
+static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x42,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-static int ads_duo_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       int ret;
+static struct tda1004x_config asus_tiger_3in1_config = {
+       .demod_address = 0x0b,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
 
-       ret = philips_tda827xa_pll_set(0x61, fe, params);
-       return ret;
-}
+/* ------------------------------------------------------------------
+ * special case: this card uses saa713x GPIO22 for the mode switch
+ */
 
 static int ads_duo_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
+       philips_tda827x_tuner_init(fe);
        /* route TDA8275a AGC input to the channel decoder */
-       saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x60);
+       saa7134_set_gpio(dev, 22, 1);
        return 0;
 }
 
@@ -996,126 +841,262 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* route TDA8275a AGC input to the analog IF chip*/
-       saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20);
-       philips_tda827xa_tuner_sleep( 0x61, fe);
+       saa7134_set_gpio(dev, 22, 0);
+       philips_tda827x_tuner_sleep(fe);
        return 0;
 }
 
+static struct tda827x_config ads_duo_cfg = {
+       .init = ads_duo_tuner_init,
+       .sleep = ads_duo_tuner_sleep,
+       .config = 0
+};
+
 static struct tda1004x_config ads_tech_duo_config = {
        .demod_address = 0x08,
        .invert        = 1,
        .invert_oclk   = 0,
        .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X_GPL,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP00_I,
        .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
 };
 
-/* ------------------------------------------------------------------ */
+static struct zl10353_config behold_h6_config = {
+       .demod_address = 0x1e>>1,
+       .no_tuner      = 1,
+       .parallel_ts   = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
 
-static int tevion_dvb220rf_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
-       int ret;
-       ret = philips_tda827xa_pll_set(0x60, fe, params);
-       return ret;
-}
+static struct xc5000_config behold_x7_tunerconfig = {
+       .i2c_address      = 0xc2>>1,
+       .if_khz           = 4560,
+       .radio_input      = XC5000_RADIO_FM1,
+};
 
-static int tevion_dvb220rf_tuner_sleep(struct dvb_frontend *fe)
-{
-       philips_tda827xa_tuner_sleep( 0x61, fe);
-       return 0;
-}
+static struct zl10353_config behold_x7_config = {
+       .demod_address = 0x1e>>1,
+       .if2           = 45600,
+       .no_tuner      = 1,
+       .parallel_ts   = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
 
-static struct tda1004x_config tevion_dvbt220rf_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+/* ==================================================================
+ * tda10086 based DVB-S cards, helper functions
+ */
+
+static struct tda10086_config flydvbs = {
+       .demod_address = 0x0e,
+       .invert = 0,
+       .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_16M,
 };
 
-/* ------------------------------------------------------------------ */
+static struct tda10086_config sd1878_4m = {
+       .demod_address = 0x0e,
+       .invert = 0,
+       .diseqc_tone = 0,
+       .xtal_freq = TDA10086_XTAL_4M,
+};
 
-static int md8800_dvbt_analog_mode(struct dvb_frontend *fe)
+/* ------------------------------------------------------------------
+ * special case: lnb supply is connected to the gated i2c
+ */
+
+static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
+       int res = -EIO;
        struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 data[] = { 0x3c, 0x33, 0x68};
-       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_voltage)
+                       res = dev->original_set_voltage(fe, voltage);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
 
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-       philips_tda827xa_tuner_sleep( 0x61, fe);
+static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
+{
+       int res = -EIO;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       if (fe->ops.i2c_gate_ctrl) {
+               fe->ops.i2c_gate_ctrl(fe, 1);
+               if (dev->original_set_high_voltage)
+                       res = dev->original_set_high_voltage(fe, arg);
+               fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       return res;
+};
+
+static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       u8 wbuf[2] = { 0x1f, 00 };
+       u8 rbuf;
+       struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 },
+                                { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } };
+
+       if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2)
+               return -EIO;
+       /* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */
+       if (voltage == SEC_VOLTAGE_18)
+               wbuf[1] = rbuf | 0x10;
+       else
+               wbuf[1] = rbuf & 0xef;
+       msg[0].len = 2;
+       i2c_transfer(&dev->i2c_adap, msg, 1);
        return 0;
 }
 
-static int md8800_dvbt_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
 {
-       int ret;
        struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 tda8290_close[] = { 0x21, 0xc0};
-       static u8 tda8290_open[]  = { 0x21, 0x80};
-       struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
-       /* close tda8290 i2c bridge */
-       tda8290_msg.buf = tda8290_close;
-       ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
-       if (ret != 1)
-               return -EIO;
-       msleep(20);
-       ret = philips_tda827xa_pll_set(0x60, fe, params);
-       if (ret != 0)
-               return ret;
-       /* open tda8290 i2c bridge */
-       tda8290_msg.buf = tda8290_open;
-       i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
-       return ret;
+       wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
+       return -EIO;
 }
 
-static struct tda1004x_config md8800_dvbt_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .if_freq       = TDA10046_FREQ_045,
-       .request_firmware = NULL,
+/* ==================================================================
+ * nxt200x based ATSC cards, helper functions
+ */
+
+static struct nxt200x_config avertvhda180 = {
+       .demod_address    = 0x0a,
 };
 
-static struct tda10086_config flydvbs = {
-       .demod_address = 0x0e,
-       .invert = 0,
+static struct nxt200x_config kworldatsc110 = {
+       .demod_address    = 0x0a,
 };
 
 /* ------------------------------------------------------------------ */
 
-static struct nxt200x_config avertvhda180 = {
-       .demod_address    = 0x0a,
+static struct mt312_config avertv_a700_mt312 = {
+       .demod_address = 0x0e,
+       .voltage_inverted = 1,
 };
 
-static int nxt200x_set_pll_input(u8 *buf, int input)
-{
-       if (input)
-               buf[3] |= 0x08;
-       else
-               buf[3] &= ~0x08;
-       return 0;
-}
+static struct zl10036_config avertv_a700_tuner = {
+       .tuner_address = 0x60,
+};
 
-static struct nxt200x_config kworldatsc110 = {
-       .demod_address    = 0x0a,
-       .set_pll_input    = nxt200x_set_pll_input,
+static struct mt312_config zl10313_compro_s350_config = {
+       .demod_address = 0x0e,
 };
 
-/* ------------------------------------------------------------------ */
+static struct lgdt3305_config hcw_lgdt3305_config = {
+       .i2c_addr           = 0x0e,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .qam_if_khz         = 4000,
+       .vsb_if_khz         = 3250,
+};
+
+static struct tda10048_config hcw_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+};
+
+static struct tda18271_config hcw_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .config  = 3,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda10048_config zolid_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_config zolid_tda18271_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static struct tda10048_config dtv1000s_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3800,
+       .dtv8_if_freq_khz = TDA10048_IF_4300,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_std_map dtv1000s_tda18271_std_map = {
+       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config dtv1000s_tda18271_config = {
+       .std_map = &dtv1000s_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+/* ==================================================================
+ * Core code
+ */
 
 static int dvb_init(struct saa7134_dev *dev)
 {
+       int ret;
+       int attach_xc3028 = 0;
+       struct videobuf_dvb_frontend *fe0;
+
+       /* FIXME: add support for multi-frontend */
+       mutex_init(&dev->frontends.lock);
+       INIT_LIST_HEAD(&dev->frontends.felist);
+
+       printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
+       fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
+       if (!fe0) {
+               printk(KERN_ERR "%s() failed to alloc\n", __func__);
+               return -ENOMEM;
+       }
+
        /* init struct videobuf_dvb */
        dev->ts.nr_bufs    = 32;
        dev->ts.nr_packets = 32*4;
-       dev->dvb.name = dev->name;
-       videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops,
-                           dev->pci, &dev->slock,
+       fe0->dvb.name = dev->name;
+       videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_ALTERNATE,
                            sizeof(struct saa7134_buf),
@@ -1123,270 +1104,572 @@ static int dvb_init(struct saa7134_dev *dev)
 
        switch (dev->board) {
        case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
-               printk("%s: pinnacle 300i dvb setup\n",dev->name);
-               dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
+               dprintk("pinnacle 300i dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
                }
                break;
        case SAA7134_BOARD_AVERMEDIA_777:
        case SAA7134_BOARD_AVERMEDIA_A16AR:
-               printk("%s: avertv 777 dvb setup\n",dev->name);
-               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+               dprintk("avertv 777 dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TD1316);
                }
                break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               dprintk("AverMedia A16D dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
        case SAA7134_BOARD_MD7134:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                               &medion_cardbus,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                               &philips_tu1216_60_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params;
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
                }
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &tda827x_lifeview_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
-               }
-               break;
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &tda827x_lifeview_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
-               }
+               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_europa_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
-                       dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
-               }
-               break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+       case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                               &philips_europa_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
-                       dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               if (fe0->dvb.frontend) {
+                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+                       fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                               &philips_tu1216_61_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params;
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
                }
                break;
-       case SAA7134_BOARD_PHILIPS_TIGER:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_tiger_config,
+       case SAA7134_BOARD_KWORLD_DVBT_210:
+               if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &hcw_tda10048_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hcw_tda18271_config);
                }
                break;
+       case SAA7134_BOARD_PHILIPS_TIGER:
+               if (configure_tda827x_fe(dev, &philips_tiger_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &pinnacle_pctv_310i_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
-               }
+               if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config,
+                                        &tda827x_cfg_1) < 0)
+                       goto dettach_frontend;
                break;
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &hauppauge_hvr_1110_config,
+               if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config,
+                                        &tda827x_cfg_1) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+               fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+                                              &hcw_lgdt3305_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               if (fe0->dvb.frontend) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hcw_tda18271_config);
                }
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &asus_p7131_dual_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-                       dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
-               }
+               if (configure_tda827x_fe(dev, &asus_p7131_dual_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &tda827x_lifeview_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
-               }
+               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &lifeview_trio_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
+               if (!use_frontend) {    /* terrestrial */
+                       if (configure_tda827x_fe(dev, &lifeview_trio_config,
+                                                &tda827x_cfg_0) < 0)
+                               goto dettach_frontend;
+               } else {                /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
+                                                                       &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                               if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
+                                                                               0x08, 0, 0) == NULL) {
+                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                       }
                }
                break;
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                               &ads_tech_duo_config,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
-               }
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
+                                  ads_tech_duo_config.tuner_address, &dev->i2c_adap,
+                                                               &ads_duo_cfg) == NULL) {
+                               wprintk("no tda827x tuner found at addr: %02x\n",
+                                       ads_tech_duo_config.tuner_address);
+                               goto dettach_frontend;
+                       }
+               } else
+                       wprintk("failed to attach tda10046\n");
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &tevion_dvbt220rf_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params;
-               }
-               break;
-       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &ads_tech_duo_config,
-                                              &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
-               }
+               if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
                break;
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
-               dev->dvb.frontend = tda10046_attach(&md8800_dvbt_config,
-                                                   &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = md8800_dvbt_analog_mode;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = md8800_dvbt_pll_set;
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+                                                &tda827x_cfg_0) < 0)
+                               goto dettach_frontend;
+               } else {        /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                                       &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               struct dvb_frontend *fe = fe0->dvb.frontend;
+                               u8 dev_id = dev->eedata[2];
+                               u8 data = 0xc4;
+                               struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
+
+                               if (dvb_attach(tda826x_attach, fe0->dvb.frontend,
+                                               0x60, &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Medion Quadro, no tda826x "
+                                               "found !\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                               if (dev_id != 0x08) {
+                                       /* we need to open the i2c gate (we know it exists) */
+                                       fe->ops.i2c_gate_ctrl(fe, 1);
+                                       if (dvb_attach(isl6405_attach, fe,
+                                                       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+                                               wprintk("%s: Medion Quadro, no ISL6405 "
+                                                       "found !\n", __func__);
+                                               goto dettach_frontend;
+                                       }
+                                       if (dev_id == 0x07) {
+                                               /* fire up the 2nd section of the LNB supply since
+                                                  we can't do this from the other section */
+                                               msg.buf = &data;
+                                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                                       }
+                                       fe->ops.i2c_gate_ctrl(fe, 0);
+                                       dev->original_set_voltage = fe->ops.set_voltage;
+                                       fe->ops.set_voltage = md8800_set_voltage;
+                                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+                               } else {
+                                       fe->ops.set_voltage = md8800_set_voltage2;
+                                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2;
+                               }
+                       }
                }
                break;
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
-               dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, &dvb_pll_tdhu2);
-               }
+               if (fe0->dvb.frontend)
+                       dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61,
+                                  NULL, DVB_PLL_TDHU2);
                break;
+       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
        case SAA7134_BOARD_KWORLD_ATSC110:
-               dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
-                                  NULL, &dvb_pll_tuv1236d);
-               }
+               if (fe0->dvb.frontend)
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
-               dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
                                               &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
                                       &dev->i2c_adap, 0) == NULL) {
-                               printk("%s: No tda826x found!\n", __FUNCTION__);
+                               wprintk("%s: No tda826x found!\n", __func__);
+                               goto dettach_frontend;
                        }
-                       if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+                       if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
                                       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
-                               printk("%s: No ISL6421 found!\n", __FUNCTION__);
+                               wprintk("%s: No ISL6421 found!\n", __func__);
+                               goto dettach_frontend;
                        }
                }
                break;
        case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
-               dev->dvb.frontend = tda10046_attach(&medion_cardbus,
-                                                   &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
-                       dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &medion_cardbus,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-               dev->dvb.frontend = dvb_attach(tda10046_attach,
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
                                &philips_europa_config,
                                &dev->i2c_adap);
-               if (dev->dvb.frontend) {
-                       dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
-                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+               if (configure_tda827x_fe(dev, &cinergy_ht_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_CINERGY_HT_PCI:
+               if (configure_tda827x_fe(dev, &cinergy_ht_pci_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_PHILIPS_TIGER_S:
+               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_ASUS_P7131_4871:
+               if (configure_tda827x_fe(dev, &asus_p7131_4871_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+               if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+               if (configure_tda827x_fe(dev, &avermedia_super_007_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+               if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config,
+                                        &tda827x_cfg_2_sw42) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_PHILIPS_SNAKE:
+               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
+                                       &dev->i2c_adap, 0) == NULL) {
+                               wprintk("%s: No tda826x found!\n", __func__);
+                               goto dettach_frontend;
+                       }
+                       if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+                                       &dev->i2c_adap, 0, 0) == NULL) {
+                               wprintk("%s: No lnbp21 found!\n", __func__);
+                               goto dettach_frontend;
+                       }
+               }
+               break;
+       case SAA7134_BOARD_CREATIX_CTX953:
+               if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
+               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               dprintk("AverMedia E506R dvb setup\n");
+               saa7134_set_gpio(dev, 25, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 25, 1);
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_MD7134_BRIDGE_2:
+               fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &sd1878_4m, &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       struct dvb_frontend *fe;
+                       if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
+                                 &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
+                               wprintk("%s: MD7134 DVB-S, no SD1878 "
+                                       "found !\n", __func__);
+                               goto dettach_frontend;
+                       }
+                       /* we need to open the i2c gate (we know it exists) */
+                       fe = fe0->dvb.frontend;
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+                       if (dvb_attach(isl6405_attach, fe,
+                                       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+                               wprintk("%s: MD7134 DVB-S, no ISL6405 "
+                                       "found !\n", __func__);
+                               goto dettach_frontend;
+                       }
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+                       dev->original_set_voltage = fe->ops.set_voltage;
+                       fe->ops.set_voltage = md8800_set_voltage;
+                       dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
+                       fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
+               }
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M103:
+               saa7134_set_gpio(dev, 25, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 25, 1);
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &asus_tiger_3in1_config,
+                                                       &tda827x_cfg_2) < 0)
+                               goto dettach_frontend;
+               } else {                /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach,
+                                               fe0->dvb.frontend, 0x60,
+                                               &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no "
+                                               "tda826x found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                               if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+                                               &dev->i2c_adap, 0, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no lnbp21"
+                                               " found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                       }
+               }
+               break;
+       case SAA7134_BOARD_ASUSTeK_TIGER:
+               if (configure_tda827x_fe(dev, &philips_tiger_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
+       case SAA7134_BOARD_BEHOLD_H6:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_h6_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216MEX_MK3);
+               }
+               break;
+       case SAA7134_BOARD_BEHOLD_X7:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_x7_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, &behold_x7_tunerconfig);
+               }
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+               /* Zarlink ZL10313 */
+               fe0->dvb.frontend = dvb_attach(mt312_attach,
+                       &avertv_a700_mt312, &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(zl10036_attach, fe0->dvb.frontend,
+                                       &avertv_a700_tuner, &dev->i2c_adap) == NULL) {
+                               wprintk("%s: No zl10036 found!\n",
+                                       __func__);
+                       }
+               }
+               break;
+       case SAA7134_BOARD_VIDEOMATE_S350:
+               fe0->dvb.frontend = dvb_attach(mt312_attach,
+                               &zl10313_compro_s350_config, &dev->i2c_adap);
+               if (fe0->dvb.frontend)
+                       if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
+                                       0x60, &dev->i2c_adap) == NULL)
+                               wprintk("%s: No zl10039 found!\n",
+                                       __func__);
+
+               break;
+       case SAA7134_BOARD_ZOLID_HYBRID_PCI:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &zolid_tda10048_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &zolid_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &dtv1000s_tda10048_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &dtv1000s_tda18271_config);
                }
                break;
        default:
-               printk("%s: Huh? unknown DVB card?\n",dev->name);
+               wprintk("Huh? unknown DVB card?\n");
                break;
        }
 
-       if (NULL == dev->dvb.frontend) {
-               printk("%s: frontend initialization failed\n",dev->name);
-               return -1;
+       if (attach_xc3028) {
+               struct dvb_frontend *fe;
+               struct xc2028_config cfg = {
+                       .i2c_adap  = &dev->i2c_adap,
+                       .i2c_addr  = 0x61,
+               };
+
+               if (!fe0->dvb.frontend)
+                       goto dettach_frontend;
+
+               fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
+               if (!fe) {
+                       printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                              dev->name);
+                       goto dettach_frontend;
+               }
+       }
+
+       if (NULL == fe0->dvb.frontend) {
+               printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
+               goto dettach_frontend;
        }
+       /* define general-purpose callback pointer */
+       fe0->dvb.frontend->callback = saa7134_tuner_callback;
 
        /* register everything else */
-       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+       ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+                                       &dev->pci->dev, adapter_nr, 0, NULL);
+
+       /* this sequence is necessary to make the tda1004x load its firmware
+        * and to enter analog mode of hybrid boards
+        */
+       if (!ret) {
+               if (fe0->dvb.frontend->ops.init)
+                       fe0->dvb.frontend->ops.init(fe0->dvb.frontend);
+               if (fe0->dvb.frontend->ops.sleep)
+                       fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend);
+               if (fe0->dvb.frontend->ops.tuner_ops.sleep)
+                       fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
+       }
+       return ret;
+
+dettach_frontend:
+       videobuf_dvb_dealloc_frontends(&dev->frontends);
+       return -EINVAL;
 }
 
 static int dvb_fini(struct saa7134_dev *dev)
 {
-       static int on  = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
+       struct videobuf_dvb_frontend *fe0;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       /* FIXME: I suspect that this code is bogus, since the entry for
+          Pinnacle 300I DVB-T PAL already defines the proper init to allow
+          the detection of mt2032 (TDA9887_PORT2_INACTIVE)
+        */
+       if (dev->board == SAA7134_BOARD_PINNACLE_300I_DVBT_PAL) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+               static int on  = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv  = &on;
 
-       switch (dev->board) {
-       case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
                /* otherwise we don't detect the tuner on next insmod */
-               saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on);
-               break;
-       };
-       videobuf_dvb_unregister(&dev->dvb);
+               saa_call_all(dev, tuner, s_config, &tda9887_cfg);
+       } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
+               if ((dev->eedata[2] == 0x07) && use_frontend) {
+                       /* turn off the 2nd lnb supply */
+                       u8 data = 0x80;
+                       struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
+                       struct dvb_frontend *fe;
+                       fe = fe0->dvb.frontend;
+                       if (fe->ops.i2c_gate_ctrl) {
+                               fe->ops.i2c_gate_ctrl(fe, 1);
+                               i2c_transfer(&dev->i2c_adap, &msg, 1);
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+                       }
+               }
+       }
+       videobuf_dvb_unregister_bus(&dev->frontends);
        return 0;
 }