Commit 76aec2dc authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] DVB: Misc. DVB frontend driver updates

 - [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
parent a652d124
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
*/ */
#define __KERNEL_SYSCALLS__
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -56,6 +56,8 @@ static int debug = 0; ...@@ -56,6 +56,8 @@ static int debug = 0;
#define SP8870_FIRMWARE_OFFSET 0x0A #define SP8870_FIRMWARE_OFFSET 0x0A
static int errno;
static struct dvb_frontend_info tdlb7_info = { static struct dvb_frontend_info tdlb7_info = {
.name = "Alps TDLB7", .name = "Alps TDLB7",
.type = FE_OFDM, .type = FE_OFDM,
...@@ -74,12 +76,7 @@ static struct dvb_frontend_info tdlb7_info = { ...@@ -74,12 +76,7 @@ static struct dvb_frontend_info tdlb7_info = {
static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
{ {
u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
struct i2c_msg msg = { struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
.addr = 0x71,
.flags = 0,
.buf = buf,
.len = 4
};
int err; int err;
if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
...@@ -96,20 +93,8 @@ static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) ...@@ -96,20 +93,8 @@ static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
int ret; int ret;
u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b0 [] = { reg >> 8 , reg & 0xff };
u8 b1 [] = { 0, 0 }; u8 b1 [] = { 0, 0 };
struct i2c_msg msg [] = { struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
{ { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
.addr = 0x71,
.flags = 0,
.buf = b0,
.len = 2
},
{
.addr = 0x71,
.flags = I2C_M_RD,
.buf = b1,
.len = 2
}
};
ret = i2c->xfer (i2c, msg, 2); ret = i2c->xfer (i2c, msg, 2);
...@@ -125,12 +110,7 @@ static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) ...@@ -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]) static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
{ {
int ret; int ret;
struct i2c_msg msg = { struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 };
.addr = 0x60,
.flags = 0,
.buf = data,
.len =4
};
ret = i2c->xfer (i2c, &msg, 1); ret = i2c->xfer (i2c, &msg, 1);
...@@ -170,13 +150,13 @@ static int sp8870_read_firmware_file (const char *fn, char **fp) ...@@ -170,13 +150,13 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
loff_t filesize; loff_t filesize;
char *dp; char *dp;
fd = sys_open(fn, 0, 0); fd = open(fn, 0, 0);
if (fd == -1) { if (fd == -1) {
printk("%s: unable to open '%s'.\n", __FUNCTION__, fn); printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
return -EIO; return -EIO;
} }
filesize = sys_lseek(fd, 0L, 2); filesize = lseek(fd, 0L, 2);
if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) { if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn); printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
sys_close(fd); sys_close(fd);
...@@ -190,8 +170,8 @@ static int sp8870_read_firmware_file (const char *fn, char **fp) ...@@ -190,8 +170,8 @@ static int sp8870_read_firmware_file (const char *fn, char **fp)
return -EIO; return -EIO;
} }
sys_lseek(fd, SP8870_FIRMWARE_OFFSET, 0); lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
if (sys_read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) { if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
printk("%s: failed to read '%s'.\n",__FUNCTION__, fn); printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
vfree(dp); vfree(dp);
sys_close(fd); sys_close(fd);
...@@ -658,9 +638,6 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -658,9 +638,6 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_SET_FRONTEND: case FE_SET_FRONTEND:
return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg); 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... case FE_GET_FRONTEND: // FIXME: read known values back from Hardware...
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -675,6 +652,15 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -675,6 +652,15 @@ static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
} }
break; 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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
}; };
...@@ -687,21 +673,8 @@ static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -687,21 +673,8 @@ static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
{ {
u8 b0 [] = { 0x02 , 0x00 }; u8 b0 [] = { 0x02 , 0x00 };
u8 b1 [] = { 0, 0 }; u8 b1 [] = { 0, 0 };
struct i2c_msg msg [] = struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
{ { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
{
.addr = 0x71,
.flags = 0,
.buf = b0,
.len = 2
},
{
.addr = 0x71,
.flags = I2C_M_RD,
.buf = b1,
.len = 2
}
};
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
......
...@@ -50,7 +50,7 @@ static struct dvb_frontend_info tdmb7_info = { ...@@ -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 | .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_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_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) ...@@ -390,8 +390,14 @@ static int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_INIT: case FE_INIT:
return cx22700_init (i2c); return cx22700_init (i2c);
case FE_RESET: case FE_GET_TUNE_SETTINGS:
break; {
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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -71,9 +71,7 @@ static struct dvb_frontend_info at76c651_info = { ...@@ -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_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_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_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_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
FE_CAN_RECOVER | FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
}; };
#if ! defined(__powerpc__) #if ! defined(__powerpc__)
...@@ -361,6 +359,7 @@ static int at76c651_set_parameters(struct dvb_i2c_bus *i2c, ...@@ -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_symbolrate(i2c, p->u.qam.symbol_rate);
at76c651_set_inversion(i2c, p->inversion); at76c651_set_inversion(i2c, p->inversion);
at76c651_set_auto_config(i2c); at76c651_set_auto_config(i2c);
at76c651_reset(i2c);
return 0; return 0;
...@@ -462,8 +461,14 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -462,8 +461,14 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_INIT: case FE_INIT:
return at76c651_set_defaults(fe->i2c); return at76c651_set_defaults(fe->i2c);
case FE_RESET: case FE_GET_TUNE_SETTINGS:
return at76c651_reset(fe->i2c); {
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: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -59,8 +59,7 @@ static struct dvb_frontend_info cx24110_info = { ...@@ -59,8 +59,7 @@ static struct dvb_frontend_info cx24110_info = {
.caps = FE_CAN_INVERSION_AUTO | .caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 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_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QPSK | FE_CAN_RECOVER
FE_CAN_CLEAN_SETUP
}; };
/* fixme: are these values correct? especially ..._tolerance and caps */ /* 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) ...@@ -621,11 +620,6 @@ static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_INIT: case FE_INIT:
return cx24110_init (i2c); 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: 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)); 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: case FE_SET_VOLTAGE:
......
...@@ -963,7 +963,6 @@ struct lkup { ...@@ -963,7 +963,6 @@ struct lkup {
{FE_GET_FRONTEND, "FE_GET_FRONTEND:" }, {FE_GET_FRONTEND, "FE_GET_FRONTEND:" },
{FE_SLEEP, "FE_SLEEP:" }, {FE_SLEEP, "FE_SLEEP:" },
{FE_INIT, "FE_INIT:" }, {FE_INIT, "FE_INIT:" },
{FE_RESET, "FE_RESET:" },
{FE_SET_TONE, "FE_SET_TONE:" }, {FE_SET_TONE, "FE_SET_TONE:" },
{FE_SET_VOLTAGE, "FE_SET_VOLTAGE:" }, {FE_SET_VOLTAGE, "FE_SET_VOLTAGE:" },
}; };
...@@ -1091,9 +1090,6 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -1091,9 +1090,6 @@ static int dst_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
dst_init(dst); dst_init(dst);
break; break;
case FE_RESET:
break;
case FE_DISEQC_SEND_MASTER_CMD: case FE_DISEQC_SEND_MASTER_CMD:
{ {
struct dvb_diseqc_master_cmd *cmd = (struct dvb_diseqc_master_cmd *)arg; 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) ...@@ -1149,8 +1145,8 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
} }
dst_init (dst); dst_init (dst);
dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__,
dst, dst->bt, dst->i2c); (u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
info = &dst_info_sat; info = &dst_info_sat;
if (dst->dst_type == DST_TYPE_IS_TERR) if (dst->dst_type == DST_TYPE_IS_TERR)
...@@ -1166,7 +1162,7 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -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) static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
{ {
dvb_unregister_frontend (dst_ioctl, i2c); 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) if (data)
kfree(data); kfree(data);
} }
......
...@@ -62,8 +62,7 @@ static struct dvb_frontend_info dvb_c_dummyfe_info = { ...@@ -62,8 +62,7 @@ static struct dvb_frontend_info dvb_c_dummyfe_info = {
#endif #endif
.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO
FE_CAN_CLEAN_SETUP
}; };
static struct dvb_frontend_info dvb_t_dummyfe_info = { 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 ...@@ -157,9 +156,6 @@ static int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *ar
case FE_INIT: case FE_INIT:
return 0; return 0;
case FE_RESET:
return 0;
case FE_SET_TONE: case FE_SET_TONE:
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -35,6 +35,9 @@ static int debug = 0; ...@@ -35,6 +35,9 @@ static int debug = 0;
#define dprintk if (debug) printk #define dprintk if (debug) printk
struct grundig_state {
int first:1;
};
struct dvb_frontend_info grundig_29504_401_info = { struct dvb_frontend_info grundig_29504_401_info = {
.name = "Grundig 29504-401", .name = "Grundig 29504-401",
...@@ -48,7 +51,7 @@ struct dvb_frontend_info grundig_29504_401_info = { ...@@ -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 | .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_5_6 | FE_CAN_FEC_7_8 |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | 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]) ...@@ -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) static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
{ {
#if 1
u32 div; u32 div;
u8 buf [4]; u8 buf [4];
u8 cfg, cpump, band_select; u8 cfg, cpump, band_select;
...@@ -118,6 +122,20 @@ static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) ...@@ -118,6 +122,20 @@ static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
buf [1] = div & 0xff; buf [1] = div & 0xff;
buf [2] = ((div >> 10) & 0x60) | cfg; buf [2] = ((div >> 10) & 0x60) | cfg;
buf [3] = (cpump << 6) | band_select; 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); return tsa5060_write (i2c, buf);
} }
...@@ -276,6 +294,123 @@ static int reset_and_configure (struct dvb_i2c_bus *i2c) ...@@ -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) static int init (struct dvb_i2c_bus *i2c)
{ {
...@@ -318,6 +453,9 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe, ...@@ -318,6 +453,9 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
unsigned int cmd, void *arg) unsigned int cmd, void *arg)
{ {
struct dvb_i2c_bus *i2c = fe->i2c; struct dvb_i2c_bus *i2c = fe->i2c;
int res;
struct grundig_state* state = (struct grundig_state*) fe->data;
switch (cmd) { switch (cmd) {
case FE_GET_INFO: case FE_GET_INFO:
memcpy (arg, &grundig_29504_401_info, memcpy (arg, &grundig_29504_401_info,
...@@ -393,18 +531,33 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe, ...@@ -393,18 +531,33 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
tsa5060_set_tv_freq (i2c, p->frequency); tsa5060_set_tv_freq (i2c, p->frequency);
return apply_frontend_param (i2c, p); return apply_frontend_param (i2c, p);
} }
case FE_GET_FRONTEND: case FE_GET_FRONTEND:
/* we could correct the frequency here, but... {
* (...do you want to implement this?;) struct dvb_frontend_parameters *p = arg;
*/ return get_frontend(i2c, p);
return 0; }
case FE_SLEEP: case FE_SLEEP:
/* Power down */ /* Power down */
return l64781_writereg (i2c, 0x3e, 0x5a); return l64781_writereg (i2c, 0x3e, 0x5a);
case FE_INIT: 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: default:
dprintk ("%s: unknown command !!!\n", __FUNCTION__); dprintk ("%s: unknown command !!!\n", __FUNCTION__);
...@@ -422,6 +575,7 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -422,6 +575,7 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
u8 b1 [] = { 0x00 }; u8 b1 [] = { 0x00 };
struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 },
{ .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .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() * 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) ...@@ -465,7 +619,12 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data)
goto bailout; 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); &grundig_29504_401_info);
bailout: bailout:
...@@ -477,6 +636,7 @@ static int l64781_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -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) static void l64781_detach (struct dvb_i2c_bus *i2c, void *data)
{ {
kfree(data);
dvb_unregister_frontend (grundig_29504_401_ioctl, i2c); dvb_unregister_frontend (grundig_29504_401_ioctl, i2c);
} }
......
...@@ -52,8 +52,7 @@ static struct dvb_frontend_info grundig_29504_491_info = { ...@@ -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_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_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_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QPSK | FE_CAN_MUTE_TS
FE_CAN_MUTE_TS | FE_CAN_CLEAN_SETUP
}; };
...@@ -398,11 +397,6 @@ static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd, ...@@ -398,11 +397,6 @@ static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd,
tda8083_writereg (i2c, 0x00, 0x04); tda8083_writereg (i2c, 0x00, 0x04);
break; break;
case FE_RESET:
tda8083_writereg (i2c, 0x00, 0x3c);
tda8083_writereg (i2c, 0x00, 0x04);
break;
case FE_DISEQC_SEND_MASTER_CMD: case FE_DISEQC_SEND_MASTER_CMD:
return tda8083_send_diseqc_msg (i2c, arg); return tda8083_send_diseqc_msg (i2c, arg);
......
...@@ -66,8 +66,8 @@ static struct dvb_frontend_info mt312_info = { ...@@ -66,8 +66,8 @@ static struct dvb_frontend_info mt312_info = {
.caps = .caps =
FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 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_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS |
FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS FE_CAN_RECOVER
}; };
static int mt312_read(struct dvb_i2c_bus *i2c, static int mt312_read(struct dvb_i2c_bus *i2c,
...@@ -570,6 +570,8 @@ static int mt312_set_frontend(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) if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0)
return ret; return ret;
mt312_reset(i2c, 0);
return 0; return 0;
} }
...@@ -756,8 +758,14 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -756,8 +758,14 @@ static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
else else
return mt312_init(i2c, (long) fe->data, (u8) 60); return mt312_init(i2c, (long) fe->data, (u8) 60);
case FE_RESET: case FE_GET_TUNE_SETTINGS:
return mt312_reset(i2c, 0); {
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: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -55,7 +55,12 @@ static struct dvb_frontend_info nxt6000_info = { ...@@ -55,7 +55,12 @@ static struct dvb_frontend_info nxt6000_info = {
.symbol_rate_max = 9360000, /* FIXME */ .symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000, .symbol_rate_tolerance = 4000,
.notifier_delay = 0, .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 { struct nxt6000_config {
...@@ -762,9 +767,6 @@ static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -762,9 +767,6 @@ static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
nxt6000_setup(fe); nxt6000_setup(fe);
break; break;
case FE_RESET:
break;
case FE_SET_FRONTEND: case FE_SET_FRONTEND:
{ {
struct nxt6000_config *nxt = FE2NXT(fe); struct nxt6000_config *nxt = FE2NXT(fe);
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
next 0x4000 loaded. This may change in future versions. next 0x4000 loaded. This may change in future versions.
*/ */
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
...@@ -64,19 +64,17 @@ struct dvb_frontend_info sp887x_info = { ...@@ -64,19 +64,17 @@ struct dvb_frontend_info sp887x_info = {
.frequency_stepsize = 166666, .frequency_stepsize = 166666,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | .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_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 static
int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len) int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
{ {
struct dvb_i2c_bus *i2c = fe->i2c; struct dvb_i2c_bus *i2c = fe->i2c;
struct i2c_msg msg = { struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
.addr = addr,
.flags = 0,
.buf = buf,
.len = len
};
int err; int err;
LOG("i2c_writebytes", msg.addr, msg.buf, msg.len); LOG("i2c_writebytes", msg.addr, msg.buf, msg.len);
...@@ -213,13 +211,13 @@ int sp887x_initial_setup (struct dvb_frontend *fe) ...@@ -213,13 +211,13 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
// Load the firmware // Load the firmware
set_fs(get_ds()); set_fs(get_ds());
fd = sys_open(sp887x_firmware, 0, 0); fd = open(sp887x_firmware, 0, 0);
if (fd < 0) { if (fd < 0) {
printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__, printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,
sp887x_firmware); sp887x_firmware);
return -EIO; return -EIO;
} }
filesize = sys_lseek(fd, 0L, 2); filesize = lseek(fd, 0L, 2);
if (filesize <= 0) { if (filesize <= 0) {
printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__, printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,
sp887x_firmware); sp887x_firmware);
...@@ -241,8 +239,8 @@ int sp887x_initial_setup (struct dvb_frontend *fe) ...@@ -241,8 +239,8 @@ int sp887x_initial_setup (struct dvb_frontend *fe)
// read it! // read it!
// read the first 16384 bytes from the file // read the first 16384 bytes from the file
// ignore the first 10 bytes // ignore the first 10 bytes
sys_lseek(fd, 10, 0); lseek(fd, 10, 0);
if (sys_read(fd, firmware, fw_size) != fw_size) { if (read(fd, firmware, fw_size) != fw_size) {
printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__); printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);
vfree(firmware); vfree(firmware);
sys_close(fd); sys_close(fd);
...@@ -635,6 +633,15 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -635,6 +633,15 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
sp887x_writereg(fe, 0xc18, 0x00d); sp887x_writereg(fe, 0xc18, 0x00d);
break; 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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
}; };
...@@ -647,12 +654,7 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -647,12 +654,7 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
static static
int sp887x_attach (struct dvb_i2c_bus *i2c, void **data) int sp887x_attach (struct dvb_i2c_bus *i2c, void **data)
{ {
struct i2c_msg msg = { struct i2c_msg msg = {.addr = 0x70, .flags = 0, .buf = NULL, .len = 0 };
.addr = 0x70,
.flags = 0,
.buf = NULL,
.len = 0
};
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
...@@ -61,6 +62,7 @@ ...@@ -61,6 +62,7 @@
#endif #endif
static int stv0299_status = 0; static int stv0299_status = 0;
static int disable_typhoon = 0;
#define STATUS_BER 0 #define STATUS_BER 0
#define STATUS_UCBLOCKS 1 #define STATUS_UCBLOCKS 1
...@@ -68,12 +70,13 @@ static int stv0299_status = 0; ...@@ -68,12 +70,13 @@ static int stv0299_status = 0;
/* frontend types */ /* frontend types */
#define UNKNOWN_FRONTEND -1 #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 ALPS_BSRU6 1
#define LG_TDQF_S001F 2 #define LG_TDQF_S001F 2
#define PHILIPS_SU1278_TUA 3 // SU1278 with TUA6100 synth #define PHILIPS_SU1278_TUA 3 // SU1278 with TUA6100 synth
#define SAMSUNG_TBMU24112IMB 4 #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 */ /* Master Clock = 88 MHz */
#define M_CLK (88000000UL) #define M_CLK (88000000UL)
...@@ -95,8 +98,16 @@ static struct dvb_frontend_info uni0299_info = { ...@@ -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 | .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_5_6 | FE_CAN_FEC_7_8 |
FE_CAN_QPSK | FE_CAN_QPSK |
FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO
FE_CAN_CLEAN_SETUP };
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 [] = { ...@@ -253,6 +264,9 @@ static u8 init_tab_su1278_tsa_tt [] = {
0x34, 0x13 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) static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{ {
int ret; int ret;
...@@ -305,12 +319,8 @@ static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) ...@@ -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) static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len)
{ {
int ret; int ret;
struct i2c_msg msg = { struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len };
.addr = addr,
.flags = 0,
.buf = data,
.len = len
};
stv0299_writereg(i2c, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ 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 ...@@ -353,17 +363,22 @@ static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, in
u8 addr; u8 addr;
u32 div; u32 div;
u8 buf[4]; u8 buf[4];
int i, divisor, regcode; int divisor, regcode;
dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype); dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype);
if ((freq < 950000) || (freq > 2150000)) return -EINVAL; if ((freq < 950000) || (freq > 2150000)) return -EINVAL;
if (ftype == PHILIPS_SU1278_TSA_TT) {
divisor = 500; divisor = 500;
regcode = 2; regcode = 2;
} else {
divisor = 125;
regcode = 4;
}
// setup frequency divisor // setup frequency divisor
div = freq / divisor; div = (freq + (divisor - 1)) / divisor; // round correctly
buf[0] = (div >> 8) & 0x7f; buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff; buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode; 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 ...@@ -373,20 +388,26 @@ static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, in
switch(ftype) { switch(ftype) {
case PHILIPS_SU1278_TSA: case PHILIPS_SU1278_TSA:
case PHILIPS_SU1278_TSA_TT: case PHILIPS_SU1278_TSA_TT:
case PHILIPS_SU1278_TSA_TY:
if (ftype == PHILIPS_SU1278_TSA_TY)
addr = 0x61;
else
addr = 0x60; addr = 0x60;
buf[3] |= 0x20; buf[3] |= 0x20;
if (srate < 4000000) buf[3] |= 1; if (srate < 4000000) buf[3] |= 1;
if (freq <= 1250000) buf[3] |= 0; if (freq < 1250000) buf[3] |= 0;
else if (freq <= 1550000) buf[3] |= 0x40; else if (freq < 1550000) buf[3] |= 0x40;
else if (freq <= 2050000) buf[3] |= 0x80; else if (freq < 2050000) buf[3] |= 0x80;
else if (freq <= 2150000) buf[3] |= 0xC0; else if (freq < 2150000) buf[3] |= 0xC0;
break; break;
case ALPS_BSRU6: case ALPS_BSRU6:
addr = 0x61; addr = 0x61;
buf[3] |= 0xC0; buf[3] = 0xC4;
if (freq > 1530000) buf[3] = 0xc0;
break; break;
default: default:
...@@ -595,7 +616,7 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) ...@@ -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]); stv0299_writereg (i2c, init_tab[i], init_tab[i+1]);
/* AGC1 reference register setup */ /* 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 */ stv0299_writereg (i2c, 0x0f, 0x92); /* Iagc = Inverse, m1 = 18 */
else if (ftype == PHILIPS_SU1278_TUA) else if (ftype == PHILIPS_SU1278_TUA)
stv0299_writereg (i2c, 0x0f, 0x94); /* Iagc = Inverse, m1 = 20 */ stv0299_writereg (i2c, 0x0f, 0x94); /* Iagc = Inverse, m1 = 20 */
...@@ -618,23 +639,6 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) ...@@ -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) static int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec)
{ {
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
...@@ -824,7 +828,8 @@ static int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) ...@@ -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 reg0x08;
u8 reg0x0c; u8 reg0x0c;
...@@ -842,22 +847,26 @@ static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag ...@@ -842,22 +847,26 @@ static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag
reg0x0c &= 0x0f; reg0x0c &= 0x0f;
if (voltage == SEC_VOLTAGE_OFF) { if (voltage == SEC_VOLTAGE_OFF) {
stv0299_writereg (i2c, 0x08, reg0x08 & ~0x40); stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */
return stv0299_writereg (i2c, 0x0c, reg0x0c & ~0x40); return stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */
} else { }
stv0299_writereg (i2c, 0x08, reg0x08 | 0x40); stv0299_writereg (i2c, 0x08, reg0x08 | 0x40);
reg0x0c |= 0x40; /* LNB power on */
switch (voltage) { switch (voltage) {
case SEC_VOLTAGE_13: case SEC_VOLTAGE_13:
return stv0299_writereg (i2c, 0x0c, reg0x0c); if (tuner_type == PHILIPS_SU1278_TSA_TY)
case SEC_VOLTAGE_18:
return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x10); 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: default:
return -EINVAL; return -EINVAL;
}; };
} }
}
static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type) 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 ...@@ -875,6 +884,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
// calculate value to program // calculate value to program
if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT;
big = big << 20; big = big << 20;
big += (Mclk-1); // round correctly
do_div(big, Mclk); do_div(big, Mclk);
ratio = big << 4; ratio = big << 4;
...@@ -909,6 +919,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner ...@@ -909,6 +919,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0);
break; break;
case PHILIPS_SU1278_TSA_TY:
case PHILIPS_SU1278_TSA: case PHILIPS_SU1278_TSA:
aclk = 0xb5; aclk = 0xb5;
if (srate < 2000000) bclk = 0x86; if (srate < 2000000) bclk = 0x86;
...@@ -929,20 +940,18 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner ...@@ -929,20 +940,18 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
case ALPS_BSRU6: case ALPS_BSRU6:
default: default:
if (srate <= 1500000) { aclk = 0xb7; bclk = 0x87; } if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
else if (srate <= 3000000) { aclk = 0xb7; bclk = 0x8b; } else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
else if (srate <= 7000000) { aclk = 0xb7; bclk = 0x8f; } else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
else if (srate <= 14000000) { aclk = 0xb7; bclk = 0x93; } else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
else if (srate <= 30000000) { aclk = 0xb6; bclk = 0x93; } else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
else if (srate <= 45000000) { aclk = 0xb4; bclk = 0x91; } else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
m1 = 0x12;
stv0299_writereg (i2c, 0x13, aclk); stv0299_writereg (i2c, 0x13, aclk);
stv0299_writereg (i2c, 0x14, bclk); stv0299_writereg (i2c, 0x14, bclk);
stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0);
stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1);
break; break;
} }
...@@ -986,11 +995,10 @@ static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c, int tuner_type) ...@@ -986,11 +995,10 @@ static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c, int tuner_type)
return srate; return srate;
} }
static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) 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 dvb_i2c_bus *i2c = fe->i2c;
struct stv0299_state *state = (struct stv0299_state *) fe->data;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
...@@ -1000,7 +1008,7 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -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; struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) arg;
memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); 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; tmp->frequency_tolerance = M_CLK_SU1278_TSA_TT / 2000;
} }
break; break;
...@@ -1078,23 +1086,67 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -1078,23 +1086,67 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_SET_FRONTEND: case FE_SET_FRONTEND:
{ {
struct dvb_frontend_parameters *p = arg; struct dvb_frontend_parameters *p = arg;
int invval = 0;
dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
pll_set_tv_freq (i2c, p->frequency, tuner_type, // set the inversion
p->u.qpsk.symbol_rate); 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);
}
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_FEC (i2c, p->u.qpsk.fec_inner);
stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, tuner_type); stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type);
stv0299_writereg (i2c, 0x22, 0x00); stv0299_writereg (i2c, 0x22, 0x00);
stv0299_writereg (i2c, 0x23, 0x00); stv0299_writereg (i2c, 0x23, 0x00);
if (tuner_type != PHILIPS_SU1278_TSA_TT) {
stv0299_readreg (i2c, 0x23); stv0299_readreg (i2c, 0x23);
stv0299_writereg (i2c, 0x12, 0xb9); 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; break;
} }
...@@ -1103,8 +1155,9 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -1103,8 +1155,9 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
struct dvb_frontend_parameters *p = arg; struct dvb_frontend_parameters *p = arg;
s32 derot_freq; s32 derot_freq;
int Mclk = M_CLK; 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) derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8)
| stv0299_readreg (i2c, 0x23)); | stv0299_readreg (i2c, 0x23));
...@@ -1114,10 +1167,13 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -1114,10 +1167,13 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
derot_freq /= 1000; derot_freq /= 1000;
p->frequency += derot_freq; 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.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; break;
} }
...@@ -1125,10 +1181,23 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -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, 0x0c, 0x00); /* LNB power off! */
stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */
stv0299_writereg (i2c, 0x02, 0x80); stv0299_writereg (i2c, 0x02, 0x80);
state->initialised = 0;
break; break;
case FE_INIT: 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: case FE_DISEQC_SEND_MASTER_CMD:
return stv0299_send_diseqc_msg (i2c, arg); return stv0299_send_diseqc_msg (i2c, arg);
...@@ -1140,7 +1209,39 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *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); return stv0299_set_tone (i2c, (fe_sec_tone_mode_t) arg);
case FE_SET_VOLTAGE: 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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1158,48 +1259,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c) ...@@ -1158,48 +1259,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
u8 stat [] = { 0 }; u8 stat [] = { 0 };
u8 tda6100_buf [] = { 0, 0 }; u8 tda6100_buf [] = { 0, 0 };
int ret; int ret;
struct i2c_msg msg1 [] = { struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 },
{ { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
.addr = 0x68, struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 },
.flags = 0, { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
.buf = rpt, struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 },
.len = 2 { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .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, 0x01, 0x15);
stv0299_writereg (i2c, 0x02, 0x30); stv0299_writereg (i2c, 0x02, 0x30);
...@@ -1218,18 +1283,28 @@ static long probe_tuner (struct dvb_i2c_bus *i2c) ...@@ -1218,18 +1283,28 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) { if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) {
if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) { if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) {
// technotrend cards require non-datasheet settings // 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; return PHILIPS_SU1278_TSA_TT;
} else { } else {
// fall back to datasheet-recommended settings // 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; return PHILIPS_SU1278_TSA;
} }
} }
if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) { if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) {
//if ((stat[0] & 0x3f) == 0) { if ( strcmp(adapter->name, "KNC1 DVB-S") == 0 &&
if (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__); printk ("%s: setup for tuner TDQF-S001F\n", __FILE__);
return LG_TDQF_S001F; return LG_TDQF_S001F;
} else { } else {
...@@ -1245,7 +1320,8 @@ static long probe_tuner (struct dvb_i2c_bus *i2c) ...@@ -1245,7 +1320,8 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
stv0299_writereg (i2c, 0x02, 0x00); stv0299_writereg (i2c, 0x02, 0x00);
if ((ret = i2c->xfer(i2c, msg3, 2)) == 2) { 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; return PHILIPS_SU1278_TUA;
} }
...@@ -1259,10 +1335,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c) ...@@ -1259,10 +1335,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data) static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
{ {
long tuner_type; struct stv0299_state* state;
int tuner_type;
u8 id; u8 id;
stv0299_writereg (i2c, 0x02, 0x00); /* standby off */ stv0299_writereg (i2c, 0x02, 0x34); /* standby off */
dvb_delay(200);
id = stv0299_readreg (i2c, 0x00); id = stv0299_readreg (i2c, 0x00);
dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id); dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id);
...@@ -1275,7 +1353,15 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -1275,7 +1353,15 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
if ((tuner_type = probe_tuner(i2c)) < 0) if ((tuner_type = probe_tuner(i2c)) < 0)
return -ENODEV; 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); &uni0299_info);
} }
...@@ -1283,6 +1369,7 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -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) static void uni0299_detach (struct dvb_i2c_bus *i2c, void *data)
{ {
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
kfree(data);
dvb_unregister_frontend (uni0299_ioctl, i2c); dvb_unregister_frontend (uni0299_ioctl, i2c);
} }
...@@ -1305,8 +1392,11 @@ module_init (init_uni0299); ...@@ -1305,8 +1392,11 @@ module_init (init_uni0299);
module_exit (exit_uni0299); module_exit (exit_uni0299);
MODULE_DESCRIPTION("Universal STV0299/TSA5059/SL1935 DVB Frontend driver"); 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_LICENSE("GPL");
MODULE_PARM(stv0299_status, "i"); MODULE_PARM(stv0299_status, "i");
MODULE_PARM_DESC(stv0299_status, "Which status value to support (0: BER, 1: UCBLOCKS)"); 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.");
...@@ -32,14 +32,15 @@ ...@@ -32,14 +32,15 @@
*/ */
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/unistd.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/errno.h> #include <linux/errno.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
...@@ -167,7 +168,6 @@ static struct dvb_frontend_info tda10046h_info = { ...@@ -167,7 +168,6 @@ static struct dvb_frontend_info tda10046h_info = {
}; };
#pragma pack(1)
struct tda1004x_state { struct tda1004x_state {
u8 tda1004x_address; u8 tda1004x_address;
u8 tuner_address; u8 tuner_address;
...@@ -175,7 +175,7 @@ struct tda1004x_state { ...@@ -175,7 +175,7 @@ struct tda1004x_state {
u8 tuner_type:2; u8 tuner_type:2;
u8 fe_type:2; u8 fe_type:2;
}; };
#pragma pack()
struct fwinfo { struct fwinfo {
int file_size; int file_size;
...@@ -397,13 +397,13 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda ...@@ -397,13 +397,13 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
// Load the firmware // Load the firmware
set_fs(get_ds()); set_fs(get_ds());
fd = sys_open(tda1004x_firmware, 0, 0); fd = open(tda1004x_firmware, 0, 0);
if (fd < 0) { if (fd < 0) {
printk("%s: Unable to open firmware %s\n", __FUNCTION__, printk("%s: Unable to open firmware %s\n", __FUNCTION__,
tda1004x_firmware); tda1004x_firmware);
return -EIO; return -EIO;
} }
filesize = sys_lseek(fd, 0L, 2); filesize = lseek(fd, 0L, 2);
if (filesize <= 0) { if (filesize <= 0) {
printk("%s: Firmware %s is empty\n", __FUNCTION__, printk("%s: Firmware %s is empty\n", __FUNCTION__,
tda1004x_firmware); tda1004x_firmware);
...@@ -434,8 +434,8 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda ...@@ -434,8 +434,8 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
} }
// read it! // read it!
sys_lseek(fd, fw_offset, 0); lseek(fd, fw_offset, 0);
if (sys_read(fd, firmware, fw_size) != fw_size) { if (read(fd, firmware, fw_size) != fw_size) {
printk("%s: Failed to read firmware\n", __FUNCTION__); printk("%s: Failed to read firmware\n", __FUNCTION__);
vfree(firmware); vfree(firmware);
sys_close(fd); sys_close(fd);
...@@ -448,6 +448,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda ...@@ -448,6 +448,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
switch(tda_state->fe_type) { switch(tda_state->fe_type) {
case FE_TYPE_TDA10045H: case FE_TYPE_TDA10045H:
// reset chip // 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, 8);
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0);
dvb_delay(10); dvb_delay(10);
...@@ -458,6 +459,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda ...@@ -458,6 +459,7 @@ static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda
case FE_TYPE_TDA10046H: case FE_TYPE_TDA10046H:
// reset chip // reset chip
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0);
tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0); tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0);
dvb_delay(10); dvb_delay(10);
...@@ -539,6 +541,8 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st ...@@ -539,6 +541,8 @@ static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
dprintk("%s\n", __FUNCTION__); dprintk("%s\n", __FUNCTION__);
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
// Disable the MC44BC374C // Disable the MC44BC374C
tda1004x_enable_tuner_i2c(i2c, tda_state); tda1004x_enable_tuner_i2c(i2c, tda_state);
tuner_msg.addr = MC44BC374_ADDRESS; tuner_msg.addr = MC44BC374_ADDRESS;
...@@ -575,6 +579,8 @@ static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st ...@@ -575,6 +579,8 @@ static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_st
dprintk("%s\n", __FUNCTION__); dprintk("%s\n", __FUNCTION__);
tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); // wake up the chip
// Disable the MC44BC374C // Disable the MC44BC374C
tda1004x_enable_tuner_i2c(i2c, tda_state); tda1004x_enable_tuner_i2c(i2c, tda_state);
tuner_msg.addr = MC44BC374_ADDRESS; tuner_msg.addr = MC44BC374_ADDRESS;
...@@ -1278,12 +1284,27 @@ static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda ...@@ -1278,12 +1284,27 @@ static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda
return 0; 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) static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
{ {
int status = 0; int status = 0;
struct dvb_i2c_bus *i2c = fe->i2c; 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); 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) ...@@ -1321,7 +1342,12 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_GET_FRONTEND: case FE_GET_FRONTEND:
return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); 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: case FE_INIT:
// don't bother reinitialising // don't bother reinitialising
if (tda_state->initialised) if (tda_state->initialised)
return 0; return 0;
...@@ -1340,6 +1366,15 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -1340,6 +1366,15 @@ static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
tda_state->initialised = 1; tda_state->initialised = 1;
return status; 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: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1355,6 +1390,7 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data) ...@@ -1355,6 +1390,7 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
int fe_type = -1; int fe_type = -1;
int tuner_type = -1; int tuner_type = -1;
struct tda1004x_state tda_state; struct tda1004x_state tda_state;
struct tda1004x_state* ptda_state;
struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 }; struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 };
static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab };
static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
...@@ -1447,13 +1483,20 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data) ...@@ -1447,13 +1483,20 @@ static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data)
// upload firmware // upload firmware
if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status; 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 // register
switch(tda_state.fe_type) { switch(tda_state.fe_type) {
case FE_TYPE_TDA10045H: 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: 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 // should not get here
...@@ -1466,6 +1509,7 @@ void tda1004x_detach(struct dvb_i2c_bus *i2c, void *data) ...@@ -1466,6 +1509,7 @@ void tda1004x_detach(struct dvb_i2c_bus *i2c, void *data)
{ {
dprintk("%s\n", __FUNCTION__); dprintk("%s\n", __FUNCTION__);
kfree(data);
dvb_unregister_frontend(tda1004x_ioctl, i2c); dvb_unregister_frontend(tda1004x_ioctl, i2c);
} }
......
...@@ -111,8 +111,7 @@ static struct dvb_frontend_info ves1820_info = { ...@@ -111,8 +111,7 @@ static struct dvb_frontend_info ves1820_info = {
#endif #endif
.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO,
FE_CAN_CLEAN_SETUP | FE_CAN_RECOVER
}; };
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
#include "dvb_functions.h"
static int debug = 0; static int debug = 0;
#define dprintk if (debug) printk #define dprintk if (debug) printk
...@@ -67,10 +68,10 @@ static struct dvb_frontend_info ves1x93_info = { ...@@ -67,10 +68,10 @@ static struct dvb_frontend_info ves1x93_info = {
*/ */
static u8 init_1893_tab [] = { 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, 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00,
0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x55, 0x00, 0x00, 0x7f, 0x00 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
...@@ -109,6 +110,11 @@ static u8 init_1993_wtab[] = ...@@ -109,6 +110,11 @@ static u8 init_1993_wtab[] =
1,1,1,0,1,1,1,1, 1,1,1,1,1 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) 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) ...@@ -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] & 0xfe);
ves1x93_writereg (i2c, 0, init_1x93_tab[0]); 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); 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 ...@@ -275,10 +289,7 @@ static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion
return -EINVAL; return -EINVAL;
} }
/* needs to be saved for FE_GET_FRONTEND */ return ves1x93_writereg (i2c, 0x0c, (init_1x93_tab[0x0c] & 0x3f) | val);
init_1x93_tab[0x0c] = (init_1x93_tab[0x0c] & 0x3f) | val;
return ves1x93_writereg (i2c, 0x0c, init_1x93_tab[0x0c]);
} }
...@@ -403,6 +414,25 @@ static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) ...@@ -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) static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
{ {
switch (voltage) { switch (voltage) {
...@@ -421,6 +451,7 @@ static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag ...@@ -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) static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{ {
struct dvb_i2c_bus *i2c = fe->i2c; struct dvb_i2c_bus *i2c = fe->i2c;
struct ves1x93_state *state = (struct ves1x93_state*) fe->data;
switch (cmd) { switch (cmd) {
case FE_GET_INFO: case FE_GET_INFO:
...@@ -497,6 +528,8 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -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_inversion (i2c, p->inversion);
ves1x93_set_fec (i2c, p->u.qpsk.fec_inner); ves1x93_set_fec (i2c, p->u.qpsk.fec_inner);
ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate); ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate);
ves1x93_afc (i2c, p->frequency, p->u.qpsk.symbol_rate);
state->inversion = p->inversion;
break; break;
} }
...@@ -514,7 +547,7 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -514,7 +547,7 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
* inversion indicator is only valid * inversion indicator is only valid
* if auto inversion was used * if auto inversion was used
*/ */
if (!(init_1x93_tab[0x0c] & 0x80)) if (state->inversion == INVERSION_AUTO)
p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ?
INVERSION_OFF : INVERSION_ON; INVERSION_OFF : INVERSION_ON;
p->u.qpsk.fec_inner = ves1x93_get_fec (i2c); 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) ...@@ -530,9 +563,6 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_INIT: case FE_INIT:
return ves1x93_init (i2c); return ves1x93_init (i2c);
case FE_RESET:
return ves1x93_clr_bit (i2c);
case FE_SET_TONE: case FE_SET_TONE:
return -EOPNOTSUPP; /* the ves1893 can generate the 22k */ return -EOPNOTSUPP; /* the ves1893 can generate the 22k */
/* let's implement this when we have */ /* let's implement this when we have */
...@@ -552,14 +582,21 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) ...@@ -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) static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data)
{ {
u8 identity = ves1x93_readreg(i2c, 0x1e); u8 identity = ves1x93_readreg(i2c, 0x1e);
struct ves1x93_state* state;
switch (identity) { switch (identity) {
case 0xdc: /* VES1893A rev1 */ case 0xdc: /* VES1893A rev1 */
printk("ves1x93: Detected ves1893a rev1\n");
demod_type = DEMOD_VES1893;
ves1x93_info.name[4] = '8';
break;
case 0xdd: /* VES1893A rev2 */ case 0xdd: /* VES1893A rev2 */
printk("ves1x93: Detected ves1893a rev2\n");
demod_type = DEMOD_VES1893; demod_type = DEMOD_VES1893;
ves1x93_info.name[4] = '8'; ves1x93_info.name[4] = '8';
break; break;
case 0xde: /* VES1993 */ case 0xde: /* VES1993 */
printk("ves1x93: Detected ves1993\n");
demod_type = DEMOD_VES1993; demod_type = DEMOD_VES1993;
ves1x93_info.name[4] = '9'; ves1x93_info.name[4] = '9';
break; break;
...@@ -568,12 +605,19 @@ static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) ...@@ -568,12 +605,19 @@ static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data)
return -ENODEV; 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) static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data)
{ {
kfree(data);
dvb_unregister_frontend (ves1x93_ioctl, i2c); dvb_unregister_frontend (ves1x93_ioctl, i2c);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment