fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / dvb / ttpci / av7110.c
index 7c6ccb9..366c137 100644 (file)
@@ -30,7 +30,6 @@
  */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
@@ -54,7 +53,6 @@
 #include <linux/i2c.h>
 
 #include <asm/system.h>
-#include <asm/semaphore.h>
 
 #include <linux/dvb/frontend.h>
 
 #include "av7110_ca.h"
 #include "av7110_ipack.h"
 
+#include "bsbe1.h"
+#include "lnbp21.h"
+#include "bsru6.h"
+
 #define TS_WIDTH  376
 #define TS_HEIGHT 512
 #define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
@@ -82,6 +84,9 @@ static int hw_sections;
 static int rgb_on;
 static int volume = 255;
 static int budgetpatch;
+static int wss_cfg_4_3 = 0x4008;
+static int wss_cfg_16_9 = 0x0007;
+static int tv_standard;
 
 module_param_named(debug, av7110_debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -100,6 +105,12 @@ module_param(volume, int, 0444);
 MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
 module_param(budgetpatch, int, 0444);
 MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
+module_param(wss_cfg_4_3, int, 0444);
+MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(wss_cfg_16_9, int, 0444);
+MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(tv_standard, int, 0444);
+MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
 
 static void restart_feeds(struct av7110 *av7110);
 
@@ -125,6 +136,13 @@ static void init_av7110_av(struct av7110 *av7110)
        if (ret < 0)
                printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
 
+       ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
+       if (ret < 0)
+               printk("dvb-ttpci: unable to configure 4:3 wss\n");
+       ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
+       if (ret < 0)
+               printk("dvb-ttpci: unable to configure 16:9 wss\n");
+
        ret = av7710_set_video_mode(av7110, vidmode);
        if (ret < 0)
                printk("dvb-ttpci:cannot set video mode:%d\n",ret);
@@ -133,13 +151,9 @@ static void init_av7110_av(struct av7110 *av7110)
        /* remaining inits according to card and frontend type */
        av7110->analog_tuner_flags = 0;
        av7110->current_input = 0;
-       if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
-               printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
-                       av7110->dvb_adapter.num);
-               av7110->adac_type = DVB_ADAC_MSP34x5;
+       if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
                av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
-       }
-       else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+       if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
                printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
                        av7110->dvb_adapter.num);
                av7110->adac_type = DVB_ADAC_CRYSTAL;
@@ -242,10 +256,10 @@ static int arm_thread(void *data)
                if (!av7110->arm_ready)
                        continue;
 
-               if (down_interruptible(&av7110->dcomlock))
+               if (mutex_lock_interruptible(&av7110->dcomlock))
                        break;
                newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
-               up(&av7110->dcomlock);
+               mutex_unlock(&av7110->dcomlock);
 
                if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
                        printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
@@ -253,10 +267,10 @@ static int arm_thread(void *data)
 
                        recover_arm(av7110);
 
-                       if (down_interruptible(&av7110->dcomlock))
+                       if (mutex_lock_interruptible(&av7110->dcomlock))
                                break;
                        newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
-                       up(&av7110->dcomlock);
+                       mutex_unlock(&av7110->dcomlock);
                }
                av7110->arm_loops = newloops;
                av7110->arm_errors = 0;
@@ -741,7 +755,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
        int ret = 0;
        dprintk(4, "%p\n", av7110);
 
-       if (down_interruptible(&av7110->pid_mutex))
+       if (mutex_lock_interruptible(&av7110->pid_mutex))
                return -ERESTARTSYS;
 
        if (!(vpid & 0x8000))
@@ -760,7 +774,7 @@ int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
                ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
        }
 
-       up(&av7110->pid_mutex);
+       mutex_unlock(&av7110->pid_mutex);
        return ret;
 }
 
@@ -1088,11 +1102,9 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
        struct av7110 *av7110;
 
        /* pointer casting paranoia... */
-       if (!demux)
-               BUG();
+       BUG_ON(!demux);
        dvbdemux = (struct dvb_demux *) demux->priv;
-       if (!dvbdemux)
-               BUG();
+       BUG_ON(!dvbdemux);
        av7110 = (struct av7110 *) dvbdemux->priv;
 
        dprintk(4, "%p\n", av7110);
@@ -1371,8 +1383,10 @@ static void dvb_unregister(struct av7110 *av7110)
        dvb_dmxdev_release(&av7110->dmxdev);
        dvb_dmx_release(&av7110->demux);
 
-       if (av7110->fe != NULL)
+       if (av7110->fe != NULL) {
                dvb_unregister_frontend(av7110->fe);
+               dvb_frontend_detach(av7110->fe);
+       }
        dvb_unregister_device(av7110->osd_dev);
        av7110_av_unregister(av7110);
        av7110_ca_unregister(av7110);
@@ -1535,7 +1549,7 @@ static int get_firmware(struct av7110* av7110)
 #endif
 
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        u8 pwr = 0;
@@ -1558,6 +1572,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        // NOTE: since we're using a prescaler of 2, we set the
        // divisor frequency to 62.5kHz and divide by 125 above
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1567,212 +1583,9 @@ static struct ves1x93_config alps_bsrv2_config = {
        .demod_address = 0x08,
        .xin = 90100000UL,
        .invert_pwm = 0,
-       .pll_set = alps_bsrv2_pll_set,
-};
-
-
-static u8 alps_bsru6_inittab[] = {
-       0x01, 0x15,
-       0x02, 0x30,
-       0x03, 0x00,
-       0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-       0x06, 0x40,   /* DAC not used, set to high impendance mode */
-       0x07, 0x00,   /* DAC LSB */
-       0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
-       0x09, 0x00,   /* FIFO */
-       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-       0x10, 0x3f,   // AGC2  0x3d
-       0x11, 0x84,
-       0x12, 0xb9,
-       0x15, 0xc9,   // lock detector threshold
-       0x16, 0x00,
-       0x17, 0x00,
-       0x18, 0x00,
-       0x19, 0x00,
-       0x1a, 0x00,
-       0x1f, 0x50,
-       0x20, 0x00,
-       0x21, 0x00,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
-       0x29, 0x1e,  // 1/2 threshold
-       0x2a, 0x14,  // 2/3 threshold
-       0x2b, 0x0f,  // 3/4 threshold
-       0x2c, 0x09,  // 5/6 threshold
-       0x2d, 0x05,  // 7/8 threshold
-       0x2e, 0x01,
-       0x31, 0x1f,  // test all FECs
-       0x32, 0x19,  // viterbi and synchro search
-       0x33, 0xfc,  // rs control
-       0x34, 0x93,  // error control
-       0x0f, 0x52,
-       0xff, 0xff
-};
-
-static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
-{
-       u8 aclk = 0;
-       u8 bclk = 0;
-
-       if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
-       else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
-       else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
-       else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
-       else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
-       else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
-
-       stv0299_writereg(fe, 0x13, aclk);
-       stv0299_writereg(fe, 0x14, bclk);
-       stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-       stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
-       stv0299_writereg(fe, 0x21, (ratio      ) & 0xf0);
-
-       return 0;
-}
-
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
-{
-       int ret;
-       u8 data[4];
-       u32 div;
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
-               return -EINVAL;
-
-       div = (params->frequency + (125 - 1)) / 125; // round correctly
-       data[0] = (div >> 8) & 0x7f;
-       data[1] = div & 0xff;
-       data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-       data[3] = 0xC4;
-
-       if (params->frequency > 1530000) data[3] = 0xc0;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-       if (ret != 1)
-               return -EIO;
-       return 0;
-}
-
-static struct stv0299_config alps_bsru6_config = {
-
-       .demod_address = 0x68,
-       .inittab = alps_bsru6_inittab,
-       .mclk = 88000000UL,
-       .invert = 1,
-       .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_1,
-       .volt13_op0_op1 = STV0299_VOLT13_OP1,
-       .min_delay_ms = 100,
-       .set_symbol_rate = alps_bsru6_set_symbol_rate,
-       .pll_set = alps_bsru6_pll_set,
-};
-
-
-static u8 alps_bsbe1_inittab[] = {
-       0x01, 0x15,
-       0x02, 0x30,
-       0x03, 0x00,
-       0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-       0x06, 0x40,   /* DAC not used, set to high impendance mode */
-       0x07, 0x00,   /* DAC LSB */
-       0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
-       0x09, 0x00,   /* FIFO */
-       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-       0x10, 0x3f,   // AGC2  0x3d
-       0x11, 0x84,
-       0x12, 0xb9,
-       0x15, 0xc9,   // lock detector threshold
-       0x16, 0x00,
-       0x17, 0x00,
-       0x18, 0x00,
-       0x19, 0x00,
-       0x1a, 0x00,
-       0x1f, 0x50,
-       0x20, 0x00,
-       0x21, 0x00,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
-       0x29, 0x1e,  // 1/2 threshold
-       0x2a, 0x14,  // 2/3 threshold
-       0x2b, 0x0f,  // 3/4 threshold
-       0x2c, 0x09,  // 5/6 threshold
-       0x2d, 0x05,  // 7/8 threshold
-       0x2e, 0x01,
-       0x31, 0x1f,  // test all FECs
-       0x32, 0x19,  // viterbi and synchro search
-       0x33, 0xfc,  // rs control
-       0x34, 0x93,  // error control
-       0x0f, 0x92,
-       0xff, 0xff
-};
-
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
-{
-       int ret;
-       u8 data[4];
-       u32 div;
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-       if ((params->frequency < 950000) || (params->frequency > 2150000))
-               return -EINVAL;
-
-       div = (params->frequency + (125 - 1)) / 125; // round correctly
-       data[0] = (div >> 8) & 0x7f;
-       data[1] = div & 0xff;
-       data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-       data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-       return (ret != 1) ? -EIO : 0;
-}
-
-static struct stv0299_config alps_bsbe1_config = {
-       .demod_address = 0x68,
-       .inittab = alps_bsbe1_inittab,
-       .mclk = 88000000UL,
-       .invert = 1,
-       .skip_reinit = 0,
-       .min_delay_ms = 100,
-       .set_symbol_rate = alps_bsru6_set_symbol_rate,
-       .pll_set = alps_bsbe1_pll_set,
 };
 
-static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
-       int ret;
-       u8 data[1];
-       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
-
-       switch(voltage) {
-       case SEC_VOLTAGE_OFF:
-               data[0] = 0x00;
-               break;
-       case SEC_VOLTAGE_13:
-               data[0] = 0x44;
-               break;
-       case SEC_VOLTAGE_18:
-               data[0] = 0x4c;
-               break;
-       default:
-               return -EINVAL;
-       };
-
-       ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
-       return (ret != 1) ? -EIO : 0;
-}
-
-
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1786,6 +1599,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85 | ((div >> 10) & 0x60);
        data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1796,14 +1611,12 @@ static struct ves1820_config alps_tdbe2_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = alps_tdbe2_pll_set,
 };
 
 
 
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
-                                    struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1816,6 +1629,8 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
        data[2] = 0x8e;
        data[3] = 0x00;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1823,13 +1638,11 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
 
 static struct tda8083_config grundig_29504_451_config = {
        .demod_address = 0x68,
-       .pll_set = grundig_29504_451_pll_set,
 };
 
 
 
-static int philips_cd1516_pll_set(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters* params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1844,6 +1657,8 @@ static int philips_cd1516_pll_set(struct dvb_frontend* fe,
        data[2] = 0x8e;
        data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1854,12 +1669,11 @@ static struct ves1820_config philips_cd1516_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = philips_cd1516_pll_set,
 };
 
 
 
-static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div, pwr;
@@ -1878,6 +1692,8 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85;
        data[3] = pwr << 6;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1885,15 +1701,18 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
 
 static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
+#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
 
        return request_firmware(fw, name, &av7110->dev->pci->dev);
+#else
+       return -EINVAL;
+#endif
 }
 
 static struct sp8870_config alps_tdlb7_config = {
 
        .demod_address = 0x71,
-       .pll_set = alps_tdlb7_pll_set,
        .request_firmware = alps_tdlb7_request_firmware,
 };
 
@@ -1991,7 +1810,7 @@ static u8 nexusca_stv0297_inittab[] = {
        0xff, 0xff,
 };
 
-static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -2017,7 +1836,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
        else
                return -EINVAL;
 
-       stv0297_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
                printk("nexusca: pll transfer failed!\n");
                return -EIO;
@@ -2025,8 +1845,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
 
        // wait for PLL lock
        for(i = 0; i < 20; i++) {
-
-               stv0297_enable_plli2c(fe);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
                if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
                        if (data[0] & 0x40) break;
                msleep(10);
@@ -2040,12 +1860,12 @@ static struct stv0297_config nexusca_stv0297_config = {
        .demod_address = 0x1C,
        .inittab = nexusca_stv0297_inittab,
        .invert = 1,
-       .pll_set = nexusca_stv0297_pll_set,
+       .stop_during_read = 1,
 };
 
 
 
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        u32 div;
@@ -2072,13 +1892,14 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        data[2] = ((div >> 10) & 0x60) | cfg;
        data[3] = (cpump << 6) | band_select;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
 static struct l64781_config grundig_29504_401_config = {
        .demod_address = 0x55,
-       .pll_set = grundig_29504_401_pll_set,
 };
 
 
@@ -2096,7 +1917,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
        if (av7110->playing)
                return 0;
 
-       if (down_interruptible(&av7110->pid_mutex))
+       if (mutex_lock_interruptible(&av7110->pid_mutex))
                return -ERESTARTSYS;
 
        if (synced) {
@@ -2118,7 +1939,7 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
        if (!ret)
                av7110->fe_synced = synced;
 
-       up(&av7110->pid_mutex);
+       mutex_unlock(&av7110->pid_mutex);
        return ret;
 }
 
@@ -2262,8 +2083,11 @@ static int frontend_init(struct av7110 *av7110)
        if (av7110->dev->pci->subsystem_vendor == 0x110a) {
                switch(av7110->dev->pci->subsystem_device) {
                case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
-                       av7110->fe = ves1820_attach(&philips_cd1516_config,
+                       av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
                                                    &av7110->i2c_adap, read_pwm(av7110));
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+                       }
                        break;
                }
 
@@ -2274,31 +2098,36 @@ static int frontend_init(struct av7110 *av7110)
                case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
 
                        // try the ALPS BSRV2 first of all
-                       av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
 
                        // try the ALPS BSRU6 now
-                       av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                               av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
 
                        // Try the grundig 29504-451
-                       av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
@@ -2307,62 +2136,80 @@ static int frontend_init(struct av7110 *av7110)
                        switch(av7110->dev->pci->subsystem_device) {
                        case 0x0000:
                                /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
-                               av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
+                               av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
+                               if (av7110->fe) {
+                                       av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+                               }
                                break;
                        case 0x0003:
-                               /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */
-                               av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
+                               /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
+                               av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
+                               if (av7110->fe) {
+                                       av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                               }
                                break;
                        }
                        break;
 
                case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
+                       // try ALPS TDLB7 first, then Grundig 29504-401
+                       av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+                               break;
+                       }
+                       /* fall-thru */
 
-                       // ALPS TDLB7
-                       av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+               case 0x0008: // Hauppauge/TT DVB-T
+                       // Grundig 29504-401
+                       av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
+                       if (av7110->fe)
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
                        break;
 
                case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
 
-                       av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+                       av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                       }
                        break;
 
                case 0x0004: // Galaxis DVB-S rev1.3
                        /* ALPS BSRV2 */
-                       av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                        }
                        break;
 
                case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
                        /* Grundig 29504-451 */
-                       av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                        }
                        break;
 
-               case 0x0008: // Hauppauge/TT DVB-T
-
-                       av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
-                       break;
-
                case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
 
-                       av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
                        if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
+
                                /* set TDA9819 into DVB mode */
-                               saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
-                               saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+                               saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+                               saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
 
                                /* tuner on this needs a slower i2c bus speed */
                                av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
@@ -2372,11 +2219,20 @@ static int frontend_init(struct av7110 *av7110)
 
                case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
                        /* ALPS BSBE1 */
-                       av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->set_voltage = lnbp21_set_voltage;
-                               av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
-                               av7110->recover = dvb_s_recover;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+                               av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+                               if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
+                                       printk("dvb-ttpci: LNBP21 not found!\n");
+                                       if (av7110->fe->ops.release)
+                                               av7110->fe->ops.release(av7110->fe);
+                                       av7110->fe = NULL;
+                               } else {
+                                       av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
+                                       av7110->recover = dvb_s_recover;
+                               }
                        }
                        break;
                }
@@ -2391,21 +2247,20 @@ static int frontend_init(struct av7110 *av7110)
                       av7110->dev->pci->subsystem_vendor,
                       av7110->dev->pci->subsystem_device);
        } else {
-               FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
-               FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
+               FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
 
                ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
                if (ret < 0) {
                        printk("av7110: Frontend registration failed!\n");
-                       if (av7110->fe->ops->release)
-                               av7110->fe->ops->release(av7110->fe);
+                       dvb_frontend_detach(av7110->fe);
                        av7110->fe = NULL;
                }
        }
@@ -2592,7 +2447,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                goto err_kfree_0;
 
        ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-                                  THIS_MODULE);
+                                  THIS_MODULE, &dev->pci->dev);
        if (ret < 0)
                goto err_put_firmware_1;
 
@@ -2714,16 +2569,19 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
        tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
        tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
 
-       sema_init(&av7110->pid_mutex, 1);
+       mutex_init(&av7110->pid_mutex);
 
        /* locks for data transfers from/to AV7110 */
        spin_lock_init(&av7110->debilock);
-       sema_init(&av7110->dcomlock, 1);
+       mutex_init(&av7110->dcomlock);
        av7110->debitype = -1;
 
        /* default OSD window */
        av7110->osdwin = 1;
-       sema_init(&av7110->osd_sema, 1);
+       mutex_init(&av7110->osd_mutex);
+
+       /* TV standard */
+       av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
 
        /* ARM "watchdog" */
        init_waitqueue_head(&av7110->arm_wait);
@@ -2969,8 +2827,8 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 
 static struct saa7146_extension av7110_extension = {
-       .name           = "dvb\0",
-       .flags          = SAA7146_I2C_SHORT_DELAY,
+       .name           = "dvb",
+       .flags          = SAA7146_USE_I2C_IRQ,
 
        .module         = THIS_MODULE,
        .pci_tbl        = &pci_tbl[0],