]> git.hungrycats.org Git - linux/commitdiff
[PATCH] DVB: Misc. DVB frontend driver updates
authorMichael Hunold <hunold@linuxtv.org>
Mon, 26 Apr 2004 01:53:29 +0000 (18:53 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 26 Apr 2004 01:53:29 +0000 (18:53 -0700)
 - [DVB] follow changes in dvb-core for frontend drivers (ves1x93,
   ves1820, nxt6000, sp887x, tda1004x, stv0299, mt312, alps_tdlb7,
   alps_tdmb7, at76c651, cx24110, dst, dvb_dummy_fe, grundig_29504-401,
   grundig_29504-491)
 - [DVB] tda1004x: updated timeout to 800ms, implemented FE_SLEEP
 - [DVB] cx24110: add FE_CAN_RECOVER to reduce kdvb-fe CPU load
 - [DVB] grundig_29504-401: added 200ms delay after first FE_INIT,
   Implemented FE_GET_FRONTEND
 - [DVB] alps_tdlb7, alps_tdmb7: upped tuning delays to fix tuning

15 files changed:
drivers/media/dvb/frontends/alps_tdlb7.c
drivers/media/dvb/frontends/alps_tdmb7.c
drivers/media/dvb/frontends/at76c651.c
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/dst.c
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/grundig_29504-401.c
drivers/media/dvb/frontends/grundig_29504-491.c
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1x93.c

index 249140a4a6837daaf6b085079fafcb6176ad2170..7c9f853272599bdfefb6d88800daba6000bff448 100644 (file)
 */  
 
 
+#define __KERNEL_SYSCALLS__
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
-#include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/delay.h>
 
@@ -56,6 +56,8 @@ static int debug = 0;
 #define SP8870_FIRMWARE_OFFSET 0x0A
 
 
+static int errno;
+
 static struct dvb_frontend_info tdlb7_info = {
        .name                   = "Alps TDLB7",
        .type                   = FE_OFDM,
@@ -74,12 +76,7 @@ static struct dvb_frontend_info tdlb7_info = {
 static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
 {
         u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
-       struct i2c_msg msg = {
-               .addr = 0x71,
-               .flags = 0,
-               .buf = buf,
-               .len =  4
-       };
+       struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
        int err;
 
         if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
@@ -96,20 +93,8 @@ static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
        int ret;
        u8 b0 [] = { reg >> 8 , reg & 0xff };
        u8 b1 [] = { 0, 0 };
-       struct i2c_msg msg [] = {
-               {
-                       .addr   = 0x71,
-                       .flags  = 0,
-                       .buf    = b0,
-                       .len    = 2
-               },
-               {
-                       .addr   = 0x71,
-                       .flags  = I2C_M_RD,
-                       .buf    = b1,
-                       .len    = 2
-               }
-       };
+       struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
+                          { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
 
        ret = i2c->xfer (i2c, msg, 2);
 
@@ -125,12 +110,7 @@ static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
 static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
 {
         int ret;
-        struct i2c_msg msg = {
-               .addr   = 0x60,
-               .flags  = 0,
-               .buf    = data,
-               .len    =4
-       };
+        struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 };
 
         ret = i2c->xfer (i2c, &msg, 1);
 
@@ -170,13 +150,13 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
        loff_t filesize;
        char *dp;
 
-       fd = sys_open(fn, 0, 0);
+       fd = open(fn, 0, 0);
        if (fd == -1) {
                 printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
                return -EIO;
        }
 
-       filesize = sys_lseek(fd, 0L, 2);
+       filesize = lseek(fd, 0L, 2);
        if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
                printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
                sys_close(fd);
@@ -190,8 +170,8 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
                return -EIO;
        }
 
-       sys_lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
-       if (sys_read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
+       lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
+       if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
                printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
                vfree(dp);
                sys_close(fd);
@@ -658,9 +638,6 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
         case FE_SET_FRONTEND:
                return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg);
 
-       case FE_RESET:
-               return -EOPNOTSUPP;
-
        case FE_GET_FRONTEND:                    // FIXME: read known values back from Hardware...
                return -EOPNOTSUPP;
 
@@ -675,6 +652,15 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                }
                break;
 
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 150;
+               fesettings->step_size = 166667;
+               fesettings->max_drift = 166667*2;
+               return 0;
+       }           
+           
        default:
                return -EOPNOTSUPP;
         };
@@ -687,21 +673,8 @@ static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
 {
         u8 b0 [] = { 0x02 , 0x00 };
         u8 b1 [] = { 0, 0 };
-        struct i2c_msg msg [] =
-                       {
-                               {
-                                       .addr = 0x71,
-                                       .flags = 0,
-                                       .buf = b0,
-                                       .len = 2
-                               },
-                               {
-                                       .addr = 0x71,
-                                       .flags = I2C_M_RD,
-                                       .buf = b1,
-                                       .len = 2
-                               }
-                       };
+        struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
+                                  { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
 
        dprintk ("%s\n", __FUNCTION__);
 
index 6107c2b5e80f708fc7d24249fd7e7dd9afdc9f39..55e4004c8a1518c27cc0ecf28b459198727f3ef8 100644 (file)
@@ -50,7 +50,7 @@ static struct dvb_frontend_info tdmb7_info = {
        .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
              FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
              FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | 
-             FE_CAN_CLEAN_SETUP | FE_CAN_RECOVER
+              FE_CAN_RECOVER
 };
 
 
@@ -390,8 +390,14 @@ static int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
         case FE_INIT:
                return cx22700_init (i2c);
 
-        case FE_RESET:
-                break;
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 150;
+               fesettings->step_size = 166667;
+               fesettings->max_drift = 166667*2;
+               return 0;
+       }           
 
        default:
                return -EOPNOTSUPP;
index 16629ef8bb2c7dc16ccc291c61cadf1b7aaeb8ee..01d438a4fa29afef9a39477f5616528037864f9b 100644 (file)
@@ -71,9 +71,7 @@ static struct dvb_frontend_info at76c651_info = {
            FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
            FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
            FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
-           FE_CAN_QAM_256 /* | FE_CAN_QAM_512 | FE_CAN_QAM_1024 */ |
-           FE_CAN_RECOVER | FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
-
+           FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
 };
 
 #if ! defined(__powerpc__)
@@ -361,6 +359,7 @@ static int at76c651_set_parameters(struct dvb_i2c_bus *i2c,
        at76c651_set_symbolrate(i2c, p->u.qam.symbol_rate);
        at76c651_set_inversion(i2c, p->inversion);
        at76c651_set_auto_config(i2c);
+        at76c651_reset(i2c);
 
        return 0;
 
@@ -462,8 +461,14 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
        case FE_INIT:
                return at76c651_set_defaults(fe->i2c);
 
-       case FE_RESET:
-               return at76c651_reset(fe->i2c);
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 50;
+               fesettings->step_size = 0;
+               fesettings->max_drift = 0;
+               return 0;
+       }           
 
        default:
                return -ENOIOCTLCMD;
index d429bd3741de959f89ef2cda4939305cbfb393f2..ee4d9a868ece1751ceac654ef9f88886c97b015f 100644 (file)
@@ -59,8 +59,7 @@ static struct dvb_frontend_info cx24110_info = {
        .caps = FE_CAN_INVERSION_AUTO |
                FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-               FE_CAN_QPSK |
-               FE_CAN_CLEAN_SETUP
+               FE_CAN_QPSK | FE_CAN_RECOVER
 };
 /* fixme: are these values correct? especially ..._tolerance and caps */
 
@@ -621,11 +620,6 @@ static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
         case FE_INIT:
                return cx24110_init (i2c);
 
-       case FE_RESET:
-/* no idea what to do for this call */
-/* fixme (medium): fill me in */
-               break;
-
        case FE_SET_TONE:
                return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&~0x10)|((((fe_sec_tone_mode_t) arg)==SEC_TONE_ON)?0x10:0));
        case FE_SET_VOLTAGE:
index 859a203481214cb3fbedaf3ac1b4b48e521c3c5f..431ea9253255bb2eaab6c320f921385120b7fe33 100644 (file)
@@ -963,7 +963,6 @@ struct lkup {
        {FE_GET_FRONTEND,            "FE_GET_FRONTEND:" },
        {FE_SLEEP,                   "FE_SLEEP:" },
        {FE_INIT,                    "FE_INIT:" },
-       {FE_RESET,                   "FE_RESET:" },
        {FE_SET_TONE,                "FE_SET_TONE:" },
        {FE_SET_VOLTAGE,             "FE_SET_VOLTAGE:" },
        };
@@ -1091,9 +1090,6 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                dst_init(dst);
                break;
 
-       case FE_RESET:
-               break;
-
        case FE_DISEQC_SEND_MASTER_CMD:
        {
                struct dvb_diseqc_master_cmd *cmd = (struct dvb_diseqc_master_cmd *)arg;
@@ -1149,8 +1145,8 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
        }
 
        dst_init (dst);
-       dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, 
-               dst, dst->bt, dst->i2c);
+       dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
+                       (u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
 
        info = &dst_info_sat;
        if (dst->dst_type == DST_TYPE_IS_TERR)
@@ -1166,7 +1162,7 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
 static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
 {
        dvb_unregister_frontend (dst_ioctl, i2c);
-       dprintk("%s: unregister dst %p\n", __FUNCTION__, data);
+       dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
        if (data)
                kfree(data);
 }
index ab019e8169ea3362b5c4e708316c0c79d1278adc..6d9e6108e489d58e1f5196d363ee6ed2b8cad0bd 100644 (file)
@@ -62,8 +62,7 @@ static struct dvb_frontend_info dvb_c_dummyfe_info = {
 #endif
        .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
                FE_CAN_QAM_128 | FE_CAN_QAM_256 | 
-               FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |
-               FE_CAN_CLEAN_SETUP
+               FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO
 };
 
 static struct dvb_frontend_info dvb_t_dummyfe_info = {
@@ -157,9 +156,6 @@ static int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *ar
         case FE_INIT:
                return 0;
 
-       case FE_RESET:
-               return 0;
-
        case FE_SET_TONE:
                return -EOPNOTSUPP;
 
index f4215ff7f0fb4bc57270f34c2ee4de384c82f38f..d866dd5cc24d9841cfec63597cd8bb5c29d37bed 100644 (file)
@@ -35,6 +35,9 @@ static int debug = 0;
 
 #define dprintk        if (debug) printk
 
+struct grundig_state {
+       int first:1;
+};
 
 struct dvb_frontend_info grundig_29504_401_info = {
        .name = "Grundig 29504-401",
@@ -48,7 +51,7 @@ struct dvb_frontend_info grundig_29504_401_info = {
        .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
              FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
              FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-             FE_CAN_MUTE_TS /*| FE_CAN_CLEAN_SETUP*/
+              FE_CAN_MUTE_TS
 };
 
 
@@ -102,6 +105,7 @@ static int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4])
  */
 static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
 {
+#if 1
        u32 div;
        u8 buf [4];
        u8 cfg, cpump, band_select;
@@ -118,6 +122,20 @@ static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
        buf [1] = div & 0xff;
        buf [2] = ((div >> 10) & 0x60) | cfg;
        buf [3] = (cpump << 6) | band_select;
+#else
+       /* old code which seems to work better for at least one person */
+        u32 div;
+        u8 buf [4];
+        u8 cfg;
+
+        div = (36000000 + freq) / 166666;
+        cfg = 0x88;
+
+        buf [0] = (div >> 8) & 0x7f;
+        buf [1] = div & 0xff;
+        buf [2] = ((div >> 10) & 0x60) | cfg;
+        buf [3] = 0xc0;
+#endif
 
        return tsa5060_write (i2c, buf);
 }
@@ -276,6 +294,123 @@ static int reset_and_configure (struct dvb_i2c_bus *i2c)
 }
 
 
+static int get_frontend(struct dvb_i2c_bus* i2c, struct dvb_frontend_parameters* param)
+{
+       int tmp;
+
+
+       tmp = l64781_readreg(i2c, 0x04);
+       switch(tmp & 3) {
+       case 0: 
+               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; 
+               break;
+       case 1:
+               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               break;
+       case 2:
+               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; 
+               break;
+       case 3:
+               param->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; 
+               break;
+       }
+       switch((tmp >> 2) & 3) {
+       case 0: 
+               param->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               break;
+       case 1:
+               param->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+               break;
+       default:
+               printk("Unexpected value for transmission_mode\n");
+       }
+       
+       
+       
+       tmp = l64781_readreg(i2c, 0x05);
+       switch(tmp & 7) {
+       case 0: 
+               param->u.ofdm.code_rate_HP = FEC_1_2;
+               break;
+       case 1:
+               param->u.ofdm.code_rate_HP = FEC_2_3;
+               break;
+       case 2:
+               param->u.ofdm.code_rate_HP = FEC_3_4;
+               break;
+       case 3:
+               param->u.ofdm.code_rate_HP = FEC_5_6;
+               break;
+       case 4:
+               param->u.ofdm.code_rate_HP = FEC_7_8;
+               break;
+       default:
+               printk("Unexpected value for code_rate_HP\n");
+       }
+       switch((tmp >> 3) & 7) {
+       case 0: 
+               param->u.ofdm.code_rate_LP = FEC_1_2;
+               break;
+       case 1:
+               param->u.ofdm.code_rate_LP = FEC_2_3;
+               break;
+       case 2:
+               param->u.ofdm.code_rate_LP = FEC_3_4;
+               break;
+       case 3:
+               param->u.ofdm.code_rate_LP = FEC_5_6;
+               break;
+       case 4:
+               param->u.ofdm.code_rate_LP = FEC_7_8;
+               break;
+       default:
+               printk("Unexpected value for code_rate_LP\n");
+       }
+       
+       
+       tmp = l64781_readreg(i2c, 0x06);
+       switch(tmp & 3) {
+       case 0: 
+               param->u.ofdm.constellation = QPSK;
+               break;
+       case 1:
+               param->u.ofdm.constellation = QAM_16;
+               break;
+       case 2:
+               param->u.ofdm.constellation = QAM_64;
+               break;
+       default:
+               printk("Unexpected value for constellation\n");
+       }
+       switch((tmp >> 2) & 7) {
+       case 0: 
+               param->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               break;
+       case 1:
+               param->u.ofdm.hierarchy_information = HIERARCHY_1;
+               break;
+       case 2:
+               param->u.ofdm.hierarchy_information = HIERARCHY_2;
+               break;
+       case 3:
+               param->u.ofdm.hierarchy_information = HIERARCHY_4;
+               break;
+       default:
+               printk("Unexpected value for hierarchy\n");
+       }
+
+
+       tmp = l64781_readreg (i2c, 0x1d);
+       param->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
+
+       tmp = (int) (l64781_readreg (i2c, 0x08) | 
+                    (l64781_readreg (i2c, 0x09) << 8) |
+                    (l64781_readreg (i2c, 0x0a) << 16));
+       param->frequency += tmp;
+
+       return 0;
+}
+
 
 static int init (struct dvb_i2c_bus *i2c)
 {
@@ -318,6 +453,9 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
                             unsigned int cmd, void *arg)
 {
        struct dvb_i2c_bus *i2c = fe->i2c;
+       int res;
+       struct grundig_state* state = (struct grundig_state*) fe->data;
+
         switch (cmd) {
         case FE_GET_INFO:
                memcpy (arg, &grundig_29504_401_info,
@@ -393,18 +531,33 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
                tsa5060_set_tv_freq (i2c, p->frequency);
                return apply_frontend_param (i2c, p);
        }
+
         case FE_GET_FRONTEND:
-               /*  we could correct the frequency here, but...
-                *  (...do you want to implement this?;)
-                */
-               return 0;
+       {
+               struct dvb_frontend_parameters *p = arg;
+               return get_frontend(i2c, p);
+       }
 
        case FE_SLEEP:
                /* Power down */
                return l64781_writereg (i2c, 0x3e, 0x5a);
 
        case FE_INIT:
-               return init (i2c);
+               res = init (i2c);
+               if ((res == 0) && (state->first)) {
+                       state->first = 0;
+                       dvb_delay(200);
+               }
+               return res;
+
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 200;
+               fesettings->step_size = 166667;
+               fesettings->max_drift = 166667*2;
+               return 0;
+       }
 
         default:
                dprintk ("%s: unknown command !!!\n", __FUNCTION__);
@@ -422,6 +575,7 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
        u8 b1 [] = { 0x00 };
        struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 },
                           { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+       struct grundig_state* state;
 
        /**
         *  the L64781 won't show up before we send the reset_and_configure()
@@ -465,7 +619,12 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
                goto bailout;
        }
 
-       return dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL,
+       state = kmalloc(sizeof(struct grundig_state), GFP_KERNEL);
+       if (state == NULL) goto bailout;
+       *data = state;
+       state->first = 1;
+
+       return dvb_register_frontend (grundig_29504_401_ioctl, i2c, state,
                               &grundig_29504_401_info);
 
  bailout:
@@ -477,6 +636,7 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
 
 static void l64781_detach (struct dvb_i2c_bus *i2c, void *data)
 {
+       kfree(data);
        dvb_unregister_frontend (grundig_29504_401_ioctl, i2c);
 }
 
index a70c769bfbff4d19ba217718b6cef8fc4737b2a5..68408c7b4401d1080747350f2920b0c804695fa6 100644 (file)
@@ -52,8 +52,7 @@ static struct dvb_frontend_info grundig_29504_491_info = {
                FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
                FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-               FE_CAN_QPSK |
-               FE_CAN_MUTE_TS | FE_CAN_CLEAN_SETUP
+               FE_CAN_QPSK | FE_CAN_MUTE_TS
 };
 
 
@@ -398,11 +397,6 @@ static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd,
                tda8083_writereg (i2c, 0x00, 0x04);
                break;
 
-       case FE_RESET:
-               tda8083_writereg (i2c, 0x00, 0x3c);
-               tda8083_writereg (i2c, 0x00, 0x04);
-               break;
-
        case FE_DISEQC_SEND_MASTER_CMD:
                return tda8083_send_diseqc_msg (i2c, arg);
 
index 404378485c0e2b5c15437bf8597db1df6297a82f..b3d5ddf80c710307ae8fcf18f6b3daa38c039715 100644 (file)
@@ -66,8 +66,8 @@ static struct dvb_frontend_info mt312_info = {
        .caps =
            FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
            FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
-           FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER |
-           FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
+           FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS | 
+            FE_CAN_RECOVER
 };
 
 static int mt312_read(struct dvb_i2c_bus *i2c,
@@ -570,6 +570,8 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
        if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0)
                return ret;
 
+        mt312_reset(i2c, 0);
+
        return 0;
 }
 
@@ -756,8 +758,14 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
                else
                        return mt312_init(i2c, (long) fe->data, (u8) 60);
 
-       case FE_RESET:
-               return mt312_reset(i2c, 0);
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 50;
+               fesettings->step_size = 0;
+               fesettings->max_drift = 0;
+               return 0;
+       }           
 
        default:
                return -ENOIOCTLCMD;
index 14e9cfe2f1d6dfc16be57b763269e6646ee3646c..7116b0ba5df0d0e9e9b871411070bc08098eedef 100644 (file)
@@ -55,7 +55,12 @@ static struct dvb_frontend_info nxt6000_info = {
        .symbol_rate_max = 9360000,     /* FIXME */
        .symbol_rate_tolerance = 4000,
        .notifier_delay = 0,
-       .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+       .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 
+                FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | 
+                FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | 
+                FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 
+                FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 
+                FE_CAN_HIERARCHY_AUTO,
 };
 
 struct nxt6000_config {
@@ -762,9 +767,6 @@ static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
                        nxt6000_setup(fe);
                break;
 
-       case FE_RESET:
-                       break;
-               
                case FE_SET_FRONTEND:
                {
                        struct nxt6000_config *nxt = FE2NXT(fe);
index 81743c11b2b6354e382fdba09363ba8ca7fcc569..6cc71cbb2329d915e5f882156b7df11c5f1acc75 100644 (file)
    next 0x4000 loaded. This may change in future versions.
  */
 
+#define __KERNEL_SYSCALLS__
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/syscalls.h>
 #include <linux/fs.h>
 #include <linux/unistd.h>
 #include <linux/fcntl.h>
@@ -64,19 +64,17 @@ struct dvb_frontend_info sp887x_info = {
        .frequency_stepsize = 166666,
        .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_RECOVER
+               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+                FE_CAN_RECOVER
 };
 
+static int errno;
+
 static
 int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
 {
        struct dvb_i2c_bus *i2c = fe->i2c;
-       struct i2c_msg msg = {
-               .addr   = addr,
-               .flags  = 0,
-               .buf    = buf,
-               .len    = len
-       };
+       struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
        int err;
 
        LOG("i2c_writebytes", msg.addr, msg.buf, msg.len);
@@ -213,13 +211,13 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
 
        // Load the firmware
        set_fs(get_ds());
-       fd = sys_open(sp887x_firmware, 0, 0);
+       fd = open(sp887x_firmware, 0, 0);
        if (fd < 0) {
                printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,
                       sp887x_firmware);
                return -EIO;
        }
-       filesize = sys_lseek(fd, 0L, 2);
+       filesize = lseek(fd, 0L, 2);
        if (filesize <= 0) {
                printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,
                       sp887x_firmware);
@@ -241,8 +239,8 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
        // read it!
        // read the first 16384 bytes from the file
        // ignore the first 10 bytes
-       sys_lseek(fd, 10, 0);
-       if (sys_read(fd, firmware, fw_size) != fw_size) {
+       lseek(fd, 10, 0);
+       if (read(fd, firmware, fw_size) != fw_size) {
                printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);
                vfree(firmware);
                sys_close(fd);
@@ -635,6 +633,15 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                sp887x_writereg(fe, 0xc18, 0x00d);
                break;
 
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 50;
+               fesettings->step_size = 0;
+               fesettings->max_drift = 0;
+               return 0;
+       }           
+
        default:
                return -EOPNOTSUPP;
         };
@@ -647,12 +654,7 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
 static
 int sp887x_attach (struct dvb_i2c_bus *i2c, void **data)
 {
-       struct i2c_msg msg = {
-               .addr   = 0x70,
-               .flags  = 0,
-               .buf    = NULL,
-               .len    = 0
-       };
+       struct i2c_msg msg = {.addr = 0x70, .flags = 0, .buf = NULL, .len = 0 };
 
        dprintk ("%s\n", __FUNCTION__);
 
index 07cf80625e441838b1509ad9ec2fbff5dc5422e6..be9d86a1b0519db41ffab671ac9b8c085a5cdf25 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
@@ -61,6 +62,7 @@
 #endif
 
 static int stv0299_status = 0;
+static int disable_typhoon = 0;
 
 #define STATUS_BER 0
 #define STATUS_UCBLOCKS 1
@@ -68,12 +70,13 @@ static int stv0299_status = 0;
 
 /* frontend types */
 #define UNKNOWN_FRONTEND  -1
-#define PHILIPS_SU1278_TSA      0 // SU1278 with TSA5959 synth and datasheet recommended settings
+#define PHILIPS_SU1278_TSA     0 // SU1278 with TSA5059 synth and datasheet recommended settings
 #define ALPS_BSRU6         1
 #define LG_TDQF_S001F      2
 #define PHILIPS_SU1278_TUA      3 // SU1278 with TUA6100 synth
 #define SAMSUNG_TBMU24112IMB    4
-#define PHILIPS_SU1278_TSA_TT   5 // SU1278 with TSA5959 synth and TechnoTrend settings
+#define PHILIPS_SU1278_TSA_TT  5 // SU1278 with TSA5059 synth and TechnoTrend settings
+#define PHILIPS_SU1278_TSA_TY  6 // SU1278 with TUA5059 synth and Typhoon wiring
 
 /* Master Clock = 88 MHz */
 #define M_CLK (88000000UL) 
@@ -95,8 +98,16 @@ static struct dvb_frontend_info uni0299_info = {
        .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
              FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
              FE_CAN_QPSK |
-             FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |
-             FE_CAN_CLEAN_SETUP
+             FE_CAN_FEC_AUTO
+};
+
+
+struct stv0299_state {
+       u8 tuner_type;
+       u8 initialised:1;
+       u32 tuner_frequency;
+       u32 symbol_rate;
+       fe_code_rate_t fec_inner;
 };
 
 
@@ -253,6 +264,9 @@ static u8 init_tab_su1278_tsa_tt [] = {
         0x34, 0x13
 };
 
+static int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec);
+static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type);
+
 static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
 {
        int ret;
@@ -305,12 +319,8 @@ static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len)
 static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len)
 {
        int ret;
-       struct i2c_msg msg = {
-               .addr = addr,
-               .flags = 0,
-               .buf = data,
-               .len = len
-       };
+       struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len };
+
 
        stv0299_writereg(i2c, 0x05, 0xb5);      /*  enable i2c repeater on stv0299  */
 
@@ -353,17 +363,22 @@ static int tsa5059_set_tv_freq    (struct dvb_i2c_bus *i2c, u32 freq, int ftype, in
        u8 addr;
        u32 div;
        u8 buf[4];
-        int i, divisor, regcode;
+       int divisor, regcode;
 
        dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype);
 
        if ((freq < 950000) || (freq > 2150000)) return -EINVAL;
 
+       if (ftype == PHILIPS_SU1278_TSA_TT) {
         divisor = 500;
         regcode = 2;
+       } else {
+               divisor = 125;
+               regcode = 4;
+       }
 
        // setup frequency divisor
-       div = freq / divisor;
+       div = (freq + (divisor - 1)) / divisor; // round correctly
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
        buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode;
@@ -373,20 +388,26 @@ static int tsa5059_set_tv_freq    (struct dvb_i2c_bus *i2c, u32 freq, int ftype, in
        switch(ftype) {
        case PHILIPS_SU1278_TSA:
        case PHILIPS_SU1278_TSA_TT:
+       case PHILIPS_SU1278_TSA_TY:
+               if (ftype == PHILIPS_SU1278_TSA_TY)
+                       addr = 0x61;
+               else
                addr = 0x60;
+
                buf[3] |= 0x20;
 
                if (srate < 4000000) buf[3] |= 1;
           
-               if (freq <= 1250000) buf[3] |= 0;
-               else if (freq <= 1550000) buf[3] |= 0x40;
-               else if (freq <= 2050000) buf[3] |= 0x80;
-               else if (freq <= 2150000) buf[3] |= 0xC0;
+               if (freq < 1250000) buf[3] |= 0;
+               else if (freq < 1550000) buf[3] |= 0x40;
+               else if (freq < 2050000) buf[3] |= 0x80;
+               else if (freq < 2150000) buf[3] |= 0xC0;
                break;
 
        case ALPS_BSRU6:
                addr = 0x61;
-               buf[3] |= 0xC0;
+               buf[3] = 0xC4;
+               if (freq > 1530000) buf[3] = 0xc0;
                break;
 
        default:
@@ -595,7 +616,7 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype)
                stv0299_writereg (i2c, init_tab[i], init_tab[i+1]);
 
         /* AGC1 reference register setup */
-               if (ftype == PHILIPS_SU1278_TSA)
+               if (ftype == PHILIPS_SU1278_TSA || ftype == PHILIPS_SU1278_TSA_TY)
                  stv0299_writereg (i2c, 0x0f, 0x92);  /* Iagc = Inverse, m1 = 18 */
                else if (ftype == PHILIPS_SU1278_TUA)
                  stv0299_writereg (i2c, 0x0f, 0x94);  /* Iagc = Inverse, m1 = 20 */
@@ -618,23 +639,6 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype)
 }
 
 
-static int stv0299_check_inversion (struct dvb_i2c_bus *i2c)
-{
-       dprintk ("%s\n", __FUNCTION__);
-
-       if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
-               dvb_delay(30);
-               if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
-               u8 val = stv0299_readreg (i2c, 0x0c);
-                       dprintk ("%s : changing inversion\n", __FUNCTION__);
-               return stv0299_writereg (i2c, 0x0c, val ^ 0x01);
-       }
-       }
-
-       return 0;
-}
-
-
 static int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec)
 {
        dprintk ("%s\n", __FUNCTION__);
@@ -824,7 +828,8 @@ static int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone)
 }
 
 
-static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
+static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage,
+                               int tuner_type)
 {
        u8 reg0x08;
        u8 reg0x0c;
@@ -842,22 +847,26 @@ static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag
        reg0x0c &= 0x0f;
 
        if (voltage == SEC_VOLTAGE_OFF) {
-               stv0299_writereg (i2c, 0x08, reg0x08 & ~0x40);
-               return stv0299_writereg (i2c, 0x0c, reg0x0c & ~0x40);
-       } else {
+               stv0299_writereg (i2c, 0x0c, 0x00); /*  LNB power off! */
+               return stv0299_writereg (i2c, 0x08, 0x00); /*   LNB power off! */
+       }
+       
                stv0299_writereg (i2c, 0x08, reg0x08 | 0x40);
-               reg0x0c |= 0x40;   /* LNB power on */
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
-                       return stv0299_writereg (i2c, 0x0c, reg0x0c);
-       case SEC_VOLTAGE_18:
+               if (tuner_type == PHILIPS_SU1278_TSA_TY)
                        return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x10);
+               else
+                       return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x40);
+
+       case SEC_VOLTAGE_18:
+               return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x50);
+
        default:
                return -EINVAL;
        };
 }
-}
 
 
 static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type)
@@ -875,6 +884,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
         // calculate value to program
        if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT;
         big = big << 20;
+       big += (Mclk-1); // round correctly
         do_div(big, Mclk);
         ratio = big << 4;
 
@@ -909,6 +919,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
                stv0299_writereg (i2c, 0x21, (ratio      ) & 0xf0);
                break;
 
+       case PHILIPS_SU1278_TSA_TY:
        case PHILIPS_SU1278_TSA:
                aclk = 0xb5;
                if (srate < 2000000) bclk = 0x86;
@@ -929,20 +940,18 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
 
        case ALPS_BSRU6:
        default:
-               if (srate <= 1500000) { aclk = 0xb7; bclk = 0x87; }
-               else if (srate <= 3000000) { aclk = 0xb7; bclk = 0x8b; }
-               else if (srate <= 7000000) { aclk = 0xb7; bclk = 0x8f; }
-               else if (srate <= 14000000) { aclk = 0xb7; bclk = 0x93; }
-               else if (srate <= 30000000) { aclk = 0xb6; bclk = 0x93; }
-               else if (srate <= 45000000) { aclk = 0xb4; bclk = 0x91; }
-               m1 = 0x12;
+               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 (i2c, 0x13, aclk);
        stv0299_writereg (i2c, 0x14, bclk);
        stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff);
        stv0299_writereg (i2c, 0x20, (ratio >>  8) & 0xff);
        stv0299_writereg (i2c, 0x21, (ratio      ) & 0xf0);
-       stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1);
                break;
        }
 
@@ -986,11 +995,10 @@ static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c, int tuner_type)
        return srate;
 }
 
-
 static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
 {
-        int tuner_type = (long) fe->data;
        struct dvb_i2c_bus *i2c = fe->i2c;
+       struct stv0299_state *state = (struct stv0299_state *) fe->data;
 
        dprintk ("%s\n", __FUNCTION__);
 
@@ -1000,7 +1008,7 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) arg;
                memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info));
 
-               if (tuner_type == PHILIPS_SU1278_TSA_TT) {
+               if (state->tuner_type == PHILIPS_SU1278_TSA_TT) {
                        tmp->frequency_tolerance = M_CLK_SU1278_TSA_TT / 2000;
                }
                break;
@@ -1078,23 +1086,67 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
         case FE_SET_FRONTEND:
         {
                struct dvb_frontend_parameters *p = arg;
+               int invval = 0;
 
                dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
 
-               pll_set_tv_freq (i2c, p->frequency, tuner_type,
-                                p->u.qpsk.symbol_rate);
+               // set the inversion
+               if (p->inversion == INVERSION_OFF) invval = 0;
+               else if (p->inversion == INVERSION_ON) invval = 1;
+               else {
+                       printk("stv0299 does not support auto-inversion\n");
+                       return -EINVAL;
+               }
+               if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1;
+               stv0299_writereg(i2c, 0x0c, (stv0299_readreg(i2c, 0x0c) & 0xfe) | invval);
 
+               switch(state->tuner_type) {
+               case PHILIPS_SU1278_TSA_TT: 
+               {
+                       /* check if we should do a finetune */
+                       int frequency_delta = p->frequency - state->tuner_frequency;
+                       int minmax = p->u.qpsk.symbol_rate / 2000;
+                       if (minmax < 5000) minmax = 5000;
+                  
+                       if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) &&
+                           (state->fec_inner == p->u.qpsk.fec_inner) && 
+                           (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+                               int Drot_freq = (frequency_delta << 16) / (M_CLK_SU1278_TSA_TT / 1000);
+
+                               // zap the derotator registers first
+                               stv0299_writereg (i2c, 0x22, 0x00); 
+                               stv0299_writereg (i2c, 0x23, 0x00);
+
+                               // now set them as we want
+                               stv0299_writereg (i2c, 0x22, Drot_freq >> 8);
+                               stv0299_writereg (i2c, 0x23, Drot_freq);
+                       } else {
+                               /* A "normal" tune is requested */
+                               pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate);
+                               stv0299_writereg (i2c, 0x32, 0x80);
+                               stv0299_writereg (i2c, 0x22, 0x00);
+                               stv0299_writereg (i2c, 0x23, 0x00);
+                               stv0299_writereg (i2c, 0x32, 0x19);
+                               stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type);
                 stv0299_set_FEC (i2c, p->u.qpsk.fec_inner);
-                stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, tuner_type);
+                       }
+                       break;
+               }
+                   
+               default:
+                       pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate);
+                       stv0299_set_FEC (i2c, p->u.qpsk.fec_inner);
+                       stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type);
                stv0299_writereg (i2c, 0x22, 0x00);
                stv0299_writereg (i2c, 0x23, 0x00);
-               if (tuner_type != PHILIPS_SU1278_TSA_TT) {
                stv0299_readreg (i2c, 0x23);
                stv0299_writereg (i2c, 0x12, 0xb9);
+                       break;
                }
-               stv0299_check_inversion (i2c);
 
-               /* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */
+               state->tuner_frequency = p->frequency;
+               state->fec_inner = p->u.qpsk.fec_inner;
+               state->symbol_rate = p->u.qpsk.symbol_rate;
                 break;
         }
 
@@ -1103,8 +1155,9 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                struct dvb_frontend_parameters *p = arg;
                s32 derot_freq;
                int Mclk = M_CLK;
+               int invval;
 
-               if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT;
+               if (state->tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT;
 
                derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8)
                                        | stv0299_readreg (i2c, 0x23));
@@ -1114,10 +1167,13 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                derot_freq /= 1000;
 
                p->frequency += derot_freq;
-               p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ?
-                                               INVERSION_OFF : INVERSION_ON;
+
+               invval = stv0299_readreg (i2c, 0x0c) & 1;
+               if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1;
+               p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
+
                p->u.qpsk.fec_inner = stv0299_get_fec (i2c);
-               p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c, tuner_type);
+               p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c, state->tuner_type);
                 break;
         }
 
@@ -1125,10 +1181,23 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                stv0299_writereg (i2c, 0x0c, 0x00);  /*  LNB power off! */
                stv0299_writereg (i2c, 0x08, 0x00); /*  LNB power off! */
                stv0299_writereg (i2c, 0x02, 0x80);
+               state->initialised = 0;
                break;
 
         case FE_INIT:
-               return stv0299_init (i2c, tuner_type);
+               switch(state->tuner_type) {
+               case PHILIPS_SU1278_TSA_TT:
+                       state->tuner_frequency = 0;
+                       if (!state->initialised) {
+                               state->initialised = 1;
+                               return stv0299_init (i2c, state->tuner_type);
+                       }
+                       break;
+
+               default:
+                       return stv0299_init (i2c, state->tuner_type);
+               }
+               break;
 
        case FE_DISEQC_SEND_MASTER_CMD:
                return stv0299_send_diseqc_msg (i2c, arg);
@@ -1140,7 +1209,39 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                return stv0299_set_tone (i2c, (fe_sec_tone_mode_t) arg);
 
        case FE_SET_VOLTAGE:
-               return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg);
+               return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg,
+                                           state->tuner_type);
+
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+           
+               switch(state->tuner_type) {
+               case PHILIPS_SU1278_TSA_TT:
+                       fesettings->min_delay_ms = 50;
+                       if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
+                               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
+                               fesettings->max_drift = 5000;
+                       } else {
+                               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
+                               fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
+                       }
+                       break;
+
+               default:
+                       fesettings->min_delay_ms = 100;
+                       if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
+                               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
+                               fesettings->max_drift = 5000;
+                       } else {
+                               fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
+                               fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
+                       }
+                       break;              
+               }
+
+               return 0;
+       }
 
        default:
                return -EOPNOTSUPP;
@@ -1158,48 +1259,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
         u8 stat [] = { 0 };
        u8 tda6100_buf [] = { 0, 0 };
        int ret;
-       struct i2c_msg msg1 [] = {
-               {
-                       .addr   = 0x68,
-                       .flags  = 0,
-                       .buf    = rpt,
-                       .len    = 2
-               },
-               {
-                       .addr   = 0x60,
-                       .flags  = I2C_M_RD,
-                       .buf    = stat,
-                       .len    = 1
-               }
-       };
-       struct i2c_msg msg2 [] = {
-               {
-                       .addr   = 0x68,
-                       .flags  = 0,
-                       .buf    = rpt,
-                       .len    = 2
-               },
-               {
-                       .addr   = 0x61,
-                       .flags  = I2C_M_RD,
-                       .buf    = stat,
-                       .len    = 1
-               }
-       };
-       struct i2c_msg msg3 [] = {
-               {
-                       .addr   = 0x68,
-                       .flags  = 0,
-                       .buf    = rpt,
-                       .len    = 2
-               },
-               {
-                       .addr   = 0x60,
-                       .flags  = 0,
-                       .buf    = tda6100_buf,
-                       .len    = 2
-               }
-       };
+       struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+                          { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
+       struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+                          { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
+       struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+                          { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }};
 
        stv0299_writereg (i2c, 0x01, 0x15);
        stv0299_writereg (i2c, 0x02, 0x30);
@@ -1218,18 +1283,28 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
        if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) {
                if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) {
                        // technotrend cards require non-datasheet settings
-                       printk ("%s: setup for tuner SU1278 (TSA5959 synth) on TechnoTrend hardware\n", __FILE__);
+                       printk ("%s: setup for tuner SU1278 (TSA5059 synth) on"
+                               " TechnoTrend hardware\n", __FILE__);
                        return PHILIPS_SU1278_TSA_TT;
                }  else {
                        // fall back to datasheet-recommended settings
-                       printk ("%s: setup for tuner SU1278 (TSA5959 synth)\n", __FILE__);
+                       printk ("%s: setup for tuner SU1278 (TSA5059 synth)\n",
+                               __FILE__);
                        return PHILIPS_SU1278_TSA;
                }
                }
 
        if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) {
-               //if ((stat[0] & 0x3f) == 0) {
-               if (0) {        
+               if ( strcmp(adapter->name, "KNC1 DVB-S") == 0 &&
+                    !disable_typhoon )
+               {
+                       // Typhoon cards have unusual wiring.
+                       printk ("%s: setup for tuner SU1278 (TSA5059 synth) on"
+                               " Typhoon hardware\n", __FILE__);
+                       return PHILIPS_SU1278_TSA_TY;
+               }
+               //else if ((stat[0] & 0x3f) == 0) {
+               else if (0) {
                        printk ("%s: setup for tuner TDQF-S001F\n", __FILE__);
                        return LG_TDQF_S001F;
        } else {
@@ -1245,7 +1320,8 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
        stv0299_writereg (i2c, 0x02, 0x00);
 
        if ((ret = i2c->xfer(i2c, msg3, 2)) == 2) {
-               printk ("%s: setup for tuner Philips SU1278 (TUA6100 synth)\n", __FILE__);
+               printk ("%s: setup for tuner Philips SU1278 (TUA6100 synth)\n",
+                       __FILE__);
                return PHILIPS_SU1278_TUA;
        }
 
@@ -1259,10 +1335,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
 
 static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
 {
-        long tuner_type;
+       struct stv0299_state* state;
+       int tuner_type;
        u8 id;
  
-       stv0299_writereg (i2c, 0x02, 0x00); /* standby off */
+       stv0299_writereg (i2c, 0x02, 0x34); /* standby off */
+       dvb_delay(200);
        id = stv0299_readreg (i2c, 0x00);
 
        dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id);
@@ -1275,7 +1353,15 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
        if ((tuner_type = probe_tuner(i2c)) < 0)
                return -ENODEV;
 
-       return dvb_register_frontend (uni0299_ioctl, i2c, (void*) tuner_type, 
+       if ((state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL)) == NULL) {
+               return -ENOMEM;
+       }
+
+       *data = state;
+       state->tuner_type = tuner_type;
+       state->tuner_frequency = 0;
+       state->initialised = 0;
+       return dvb_register_frontend (uni0299_ioctl, i2c, (void *) state,
                               &uni0299_info);
 }
 
@@ -1283,6 +1369,7 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
 static void uni0299_detach (struct dvb_i2c_bus *i2c, void *data)
 {
        dprintk ("%s\n", __FUNCTION__);
+       kfree(data);
        dvb_unregister_frontend (uni0299_ioctl, i2c);
 }
 
@@ -1305,8 +1392,11 @@ module_init (init_uni0299);
 module_exit (exit_uni0299);
 
 MODULE_DESCRIPTION("Universal STV0299/TSA5059/SL1935 DVB Frontend driver");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter, Andrew de Quincey");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(stv0299_status, "i");
 MODULE_PARM_DESC(stv0299_status, "Which status value to support (0: BER, 1: UCBLOCKS)");
+
+MODULE_PARM(disable_typhoon, "i");
+MODULE_PARM_DESC(disable_typhoon, "Disable support for Philips SU1278 on Typhoon hardware.");
index e0abae796752c90156a200901af60add406d9848..d481c1901b3a24239796482ce71858b7ad178205 100644 (file)
  */
 
 
+#define __KERNEL_SYSCALLS__
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/syscalls.h>
 #include <linux/fs.h>
+#include <linux/unistd.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 #include "dvb_frontend.h"
@@ -167,7 +168,6 @@ static struct dvb_frontend_info tda10046h_info = {
 };
 
 
-#pragma pack(1)
 struct tda1004x_state {
        u8 tda1004x_address;
        u8 tuner_address;
@@ -175,7 +175,7 @@ struct tda1004x_state {
         u8 tuner_type:2;
         u8 fe_type:2;
 };
-#pragma pack()
+
 
 struct fwinfo {
        int file_size;
@@ -397,13 +397,13 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
 
        // Load the firmware
        set_fs(get_ds());
-       fd = sys_open(tda1004x_firmware, 0, 0);
+       fd = open(tda1004x_firmware, 0, 0);
        if (fd < 0) {
                printk("%s: Unable to open firmware %s\n", __FUNCTION__,
                       tda1004x_firmware);
                return -EIO;
        }
-       filesize = sys_lseek(fd, 0L, 2);
+       filesize = lseek(fd, 0L, 2);
        if (filesize <= 0) {
                printk("%s: Firmware %s is empty\n", __FUNCTION__,
                       tda1004x_firmware);
@@ -434,8 +434,8 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
        }
 
        // read it!
-        sys_lseek(fd, fw_offset, 0);
-       if (sys_read(fd, firmware, fw_size) != fw_size) {
+       lseek(fd, fw_offset, 0);
+       if (read(fd, firmware, fw_size) != fw_size) {
                printk("%s: Failed to read firmware\n", __FUNCTION__);
                vfree(firmware);
                sys_close(fd);
@@ -448,6 +448,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
         switch(tda_state->fe_type) {
         case FE_TYPE_TDA10045H:
                 // reset chip
+               tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0);
                 tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8);
                 tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0);
                 dvb_delay(10);
@@ -458,6 +459,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
 
         case FE_TYPE_TDA10046H:
                 // reset chip
+               tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0);
                 tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0);
                 dvb_delay(10);
 
@@ -539,6 +541,8 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
 
         dprintk("%s\n", __FUNCTION__);
 
+       tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
+
         // Disable the MC44BC374C
         tda1004x_enable_tuner_i2c(i2c, tda_state);
         tuner_msg.addr = MC44BC374_ADDRESS;
@@ -575,6 +579,8 @@ static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
 
         dprintk("%s\n", __FUNCTION__);
 
+       tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); // wake up the chip
+
         // Disable the MC44BC374C
         tda1004x_enable_tuner_i2c(i2c, tda_state);
         tuner_msg.addr = MC44BC374_ADDRESS;
@@ -1278,12 +1284,27 @@ static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda
        return 0;
 }
 
+static int tda1004x_sleep(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state)
+{
+       switch(tda_state->fe_type) {
+       case FE_TYPE_TDA10045H:
+               tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0x10);
+               break;
+
+       case FE_TYPE_TDA10046H:
+               tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 1);
+               break;
+       }
+
+       return 0;
+}
+
 
 static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
 {
        int status = 0;
        struct dvb_i2c_bus *i2c = fe->i2c;
-       struct tda1004x_state *tda_state = (struct tda1004x_state *) &(fe->data);
+       struct tda1004x_state *tda_state = (struct tda1004x_state *) fe->data;
 
        dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd);
 
@@ -1321,7 +1342,12 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
        case FE_GET_FRONTEND:
                return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg);
 
+       case FE_SLEEP:
+               tda_state->initialised = 0;
+               return tda1004x_sleep(i2c, tda_state);
+
        case FE_INIT:
+
                // don't bother reinitialising
                if (tda_state->initialised)
                        return 0;
@@ -1340,6 +1366,15 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
                        tda_state->initialised = 1;
                return status;
 
+       case FE_GET_TUNE_SETTINGS:
+       {
+               struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
+               fesettings->min_delay_ms = 800;
+               fesettings->step_size = 166667;
+               fesettings->max_drift = 166667*2;
+               return 0;
+       }
+           
        default:
                return -EOPNOTSUPP;
        }
@@ -1355,6 +1390,7 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
         int fe_type = -1;
         int tuner_type = -1;
        struct tda1004x_state tda_state;
+       struct tda1004x_state* ptda_state;
        struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 };
         static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab };
         static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -1447,13 +1483,20 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
         // upload firmware
         if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status;
 
+       // create the real state we'll be passing about
+       if ((ptda_state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL)) == NULL) {
+               return -ENOMEM;
+       }
+       memcpy(ptda_state, &tda_state, sizeof(struct tda1004x_state));
+       *data = ptda_state;
+
        // register
         switch(tda_state.fe_type) {
         case FE_TYPE_TDA10045H:
-               return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info);
+               return dvb_register_frontend(tda1004x_ioctl, i2c, ptda_state, &tda10045h_info);
 
         case FE_TYPE_TDA10046H:
-                return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10046h_info);
+               return dvb_register_frontend(tda1004x_ioctl, i2c, ptda_state, &tda10046h_info);
         }
 
         // should not get here
@@ -1466,6 +1509,7 @@ void tda1004x_detach(struct dvb_i2c_bus *i2c, void *data)
 {
        dprintk("%s\n", __FUNCTION__);
 
+       kfree(data);
        dvb_unregister_frontend(tda1004x_ioctl, i2c);
 }
 
index 1652be9d316779a7dfa4cc2c9362fa9c7c485077..d01d28361c45ed463db99617e9ebf30bed9f796a 100644 (file)
@@ -111,8 +111,7 @@ static struct dvb_frontend_info ves1820_info = {
 #endif
        .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
                FE_CAN_QAM_128 | FE_CAN_QAM_256 | 
-               FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |
-               FE_CAN_CLEAN_SETUP | FE_CAN_RECOVER
+               FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO,
 };
 
 
index e6e6ba3fb458bfeb815109d1ec28e1648aa90ff3..876246d2485f09c5d2d81ea88c634dc0c0413ff7 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 
 #include "dvb_frontend.h"
+#include "dvb_functions.h"
 
 static int debug = 0;
 #define dprintk        if (debug) printk
@@ -67,10 +68,10 @@ static struct dvb_frontend_info ves1x93_info = {
  */
 
 static u8 init_1893_tab [] = {
-       0x01, 0xa4, 0x35, 0x81, 0x2a, 0x0d, 0x55, 0xc4,
+       0x01, 0xa4, 0x35, 0x80, 0x2a, 0x0b, 0x55, 0xc4,
        0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00,
        0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xdc, 0x00,
+       0x80, 0x00, 0x21, 0xb0, 0x14, 0x00, 0xdc, 0x00,
        0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
@@ -109,6 +110,11 @@ static u8 init_1993_wtab[] =
        1,1,1,0,1,1,1,1, 1,1,1,1,1
 };
 
+struct ves1x93_state {
+       fe_spectral_inversion_t inversion;
+};
+
+
 
 static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
 {
@@ -247,8 +253,16 @@ static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c)
 {
         ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe);
         ves1x93_writereg (i2c, 0, init_1x93_tab[0]);
+       dvb_delay(5);
+       return 0;
+}
+
+static int ves1x93_init_aquire (struct dvb_i2c_bus *i2c)
+{
         ves1x93_writereg (i2c, 3, 0x00);
-        return ves1x93_writereg (i2c, 3, init_1x93_tab[3]);
+       ves1x93_writereg (i2c, 3, init_1x93_tab[3]);
+       dvb_delay(5);
+       return 0;
 }
 
 
@@ -275,10 +289,7 @@ static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion
                return -EINVAL;
        }
 
-       /* needs to be saved for FE_GET_FRONTEND */
-       init_1x93_tab[0x0c] = (init_1x93_tab[0x0c] & 0x3f) | val;
-
-       return ves1x93_writereg (i2c, 0x0c, init_1x93_tab[0x0c]);
+       return ves1x93_writereg (i2c, 0x0c, (init_1x93_tab[0x0c] & 0x3f) | val);
 }
 
 
@@ -403,6 +414,25 @@ static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate)
 }
 
 
+static int ves1x93_afc (struct dvb_i2c_bus *i2c, u32 freq, u32 srate)
+{
+       int afc;
+
+       afc = ((int)((ves1x93_readreg (i2c, 0x0a) << 1) & 0xff))/2;
+       afc = (afc * (int)(srate/1000/8))/16;
+    
+       if (afc) {
+       
+               freq -= afc;
+
+               tuner_set_tv_freq (i2c, freq, 0);
+
+               ves1x93_init_aquire (i2c);
+       }
+       
+       return 0;
+}
+
 static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
 {
        switch (voltage) {
@@ -421,6 +451,7 @@ static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag
 static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
 {
        struct dvb_i2c_bus *i2c = fe->i2c;
+       struct ves1x93_state *state = (struct ves1x93_state*) fe->data;
 
         switch (cmd) {
         case FE_GET_INFO:
@@ -497,6 +528,8 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                ves1x93_set_inversion (i2c, p->inversion);
                ves1x93_set_fec (i2c, p->u.qpsk.fec_inner);
                ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate);
+               ves1x93_afc (i2c, p->frequency, p->u.qpsk.symbol_rate);     
+               state->inversion = p->inversion;
                 break;
         }
 
@@ -514,7 +547,7 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
                 * inversion indicator is only valid
                 * if auto inversion was used
                 */
-               if (!(init_1x93_tab[0x0c] & 0x80))
+               if (state->inversion == INVERSION_AUTO)
                        p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? 
                                        INVERSION_OFF : INVERSION_ON;
                p->u.qpsk.fec_inner = ves1x93_get_fec (i2c);
@@ -530,9 +563,6 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
         case FE_INIT:
                return ves1x93_init (i2c);
 
-       case FE_RESET:
-               return ves1x93_clr_bit (i2c);
-
        case FE_SET_TONE:
                return -EOPNOTSUPP;  /* the ves1893 can generate the 22k */
                                     /* let's implement this when we have */
@@ -552,14 +582,21 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
 static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data)
 {
        u8 identity = ves1x93_readreg(i2c, 0x1e);
+       struct ves1x93_state* state;
 
        switch (identity) {
        case 0xdc: /* VES1893A rev1 */
+               printk("ves1x93: Detected ves1893a rev1\n");
+               demod_type = DEMOD_VES1893;
+               ves1x93_info.name[4] = '8';
+               break;
        case 0xdd: /* VES1893A rev2 */
+               printk("ves1x93: Detected ves1893a rev2\n");
                demod_type = DEMOD_VES1893;
                ves1x93_info.name[4] = '8';
                break;
        case 0xde: /* VES1993 */
+               printk("ves1x93: Detected ves1993\n");
                demod_type = DEMOD_VES1993;
                ves1x93_info.name[4] = '9';
                break;
@@ -568,12 +605,19 @@ static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data)
                return -ENODEV;
        }
 
-       return dvb_register_frontend (ves1x93_ioctl, i2c, NULL, &ves1x93_info);
+       if ((state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL)) == NULL) {
+               return -ENOMEM;
+       }
+       state->inversion = INVERSION_OFF;
+       *data = state;
+
+       return dvb_register_frontend (ves1x93_ioctl, i2c, (void*) state, &ves1x93_info);
 }
 
 
 static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data)
 {
+       kfree(data);
        dvb_unregister_frontend (ves1x93_ioctl, i2c);
 }