Commit 0e8a0d01 authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] dvb: frontend update

- dib3000: support for dynamically i2c addresses of the demod

- tda1004x: fixed firmware upload problems, forgot to include tune_settings
  for tda1004x, added setting to allow inversion of OCLK, set
  fesettings->min_delay_ms = 800 as suggested by Peter Siering

- stv0297: code cleanup

- mt312: added vp310 support

- mt352: decrease verbosity
Signed-off-by: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7b05de7e
...@@ -393,7 +393,7 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s) ...@@ -393,7 +393,7 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
{ {
struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
int ret; int ret;
u8 status[3], vit_mode; u8 status[3];
*s = 0; *s = 0;
...@@ -413,17 +413,6 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s) ...@@ -413,17 +413,6 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
if (status[0] & 0x01) if (status[0] & 0x01)
*s |= FE_HAS_LOCK; /* qpsk lock */ *s |= FE_HAS_LOCK; /* qpsk lock */
// VP310 doesn't have AUTO, so we "implement it here" ACCJr
if ((state->id == ID_VP310) && !(status[0] & 0x01)) {
if ((ret = mt312_readreg(state, VIT_MODE, &vit_mode)) < 0)
return ret;
vit_mode ^= 0x40;
if ((ret = mt312_writereg(state, VIT_MODE, vit_mode)) < 0)
return ret;
if ((ret = mt312_writereg(state, GO, 0x01)) < 0)
return ret;
}
return 0; return 0;
} }
...@@ -638,61 +627,88 @@ static void mt312_release(struct dvb_frontend* fe) ...@@ -638,61 +627,88 @@ static void mt312_release(struct dvb_frontend* fe)
kfree(state); kfree(state);
} }
static struct dvb_frontend_ops mt312_ops; static struct dvb_frontend_ops vp310_mt312_ops;
struct dvb_frontend* mt312_attach(const struct mt312_config* config, struct dvb_frontend* vp310_attach(const struct mt312_config* config,
struct i2c_adapter* i2c) struct i2c_adapter* i2c)
{ {
struct mt312_state* state = NULL; struct mt312_state* state = NULL;
/* allocate memory for the internal state */ /* allocate memory for the internal state */
state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL); state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
if (state == NULL) goto error; if (state == NULL)
goto error;
/* setup the state */ /* setup the state */
state->config = config; state->config = config;
state->i2c = i2c; state->i2c = i2c;
memcpy(&state->ops, &mt312_ops, sizeof(struct dvb_frontend_ops)); memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
/* check if the demod is there */ /* check if the demod is there */
if (mt312_readreg(state, ID, &state->id) < 0) goto error; if (mt312_readreg(state, ID, &state->id) < 0)
switch(state->id) { goto error;
case ID_VP310: if (state->id != ID_VP310) {
goto error;
}
/* create dvb_frontend */
state->frequency = 90; state->frequency = 90;
printk("mt312: Detected Zarlink VP310\n"); state->frontend.ops = &state->ops;
break; state->frontend.demodulator_priv = state;
return &state->frontend;
case ID_MT312: error:
state->frequency = 60; if (state)
printk("mt312: Detected Zarlink MT312\n"); kfree(state);
break; return NULL;
}
default: struct dvb_frontend* mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c)
{
struct mt312_state* state = NULL;
/* allocate memory for the internal state */
state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
if (state == NULL)
goto error;
/* setup the state */
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
/* check if the demod is there */
if (mt312_readreg(state, ID, &state->id) < 0)
goto error;
if (state->id != ID_MT312) {
goto error; goto error;
} }
/* create dvb_frontend */ /* create dvb_frontend */
state->frequency = 60;
state->frontend.ops = &state->ops; state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state; state->frontend.demodulator_priv = state;
return &state->frontend; return &state->frontend;
error: error:
if (state) kfree(state); if (state)
kfree(state);
return NULL; return NULL;
} }
static struct dvb_frontend_ops mt312_ops = { static struct dvb_frontend_ops vp310_mt312_ops = {
.info = { .info = {
.name = "Zarlink VP310/MT312 DVB-S", .name = "Zarlink ???? DVB-S",
.type = FE_QPSK, .type = FE_QPSK,
.frequency_min = 950000, .frequency_min = 950000,
.frequency_max = 2150000, .frequency_max = 2150000,
.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
/*.frequency_tolerance = 29500, FIXME: binary compatibility waste? */
.symbol_rate_min = MT312_SYS_CLK / 128, .symbol_rate_min = MT312_SYS_CLK / 128,
.symbol_rate_max = MT312_SYS_CLK / 2, .symbol_rate_max = MT312_SYS_CLK / 2,
/*.symbol_rate_tolerance = 500, FIXME: binary compatibility waste? 2% */
.caps = .caps =
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 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 |
...@@ -729,3 +745,4 @@ MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); ...@@ -729,3 +745,4 @@ MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mt312_attach); EXPORT_SYMBOL(mt312_attach);
EXPORT_SYMBOL(vp310_attach);
...@@ -41,4 +41,7 @@ struct mt312_config ...@@ -41,4 +41,7 @@ struct mt312_config
extern struct dvb_frontend* mt312_attach(const struct mt312_config* config, extern struct dvb_frontend* mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c); struct i2c_adapter* i2c);
extern struct dvb_frontend* vp310_attach(const struct mt312_config* config,
struct i2c_adapter* i2c);
#endif // MT312_H #endif // MT312_H
...@@ -65,8 +65,7 @@ int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) ...@@ -65,8 +65,7 @@ int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
.buf = ibuf, .len = ilen }; .buf = ibuf, .len = ilen };
int err = i2c_transfer(state->i2c, &msg, 1); int err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1) { if (err != 1) {
printk(KERN_WARNING dprintk("mt352_write() failed (err = %d)!\n", err);
"mt352_write() failed (err = %d)!\n", err);
return err; return err;
} }
...@@ -88,8 +87,7 @@ static u8 mt352_read_register(struct mt352_state* state, u8 reg) ...@@ -88,8 +87,7 @@ static u8 mt352_read_register(struct mt352_state* state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2); ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) if (ret != 2)
printk(KERN_WARNING dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
"%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
return b1[0]; return b1[0];
} }
......
...@@ -51,7 +51,7 @@ struct stv0297_state { ...@@ -51,7 +51,7 @@ struct stv0297_state {
#define dprintk(x...) #define dprintk(x...)
#endif #endif
#define STV0297_CLOCK 28900 #define STV0297_CLOCK_KHZ 28900
static u8 init_tab [] = { static u8 init_tab [] = {
0x00, 0x09, 0x00, 0x09,
...@@ -78,7 +78,7 @@ static u8 init_tab [] = { ...@@ -78,7 +78,7 @@ static u8 init_tab [] = {
0x40, 0x1c, 0x40, 0x1c,
0x41, 0xff, 0x41, 0xff,
0x42, 0x29, 0x42, 0x29,
0x43, 0x00,// check 0x43, 0x00,
0x44, 0xff, 0x44, 0xff,
0x45, 0x00, 0x45, 0x00,
0x46, 0x00, 0x46, 0x00,
...@@ -167,13 +167,11 @@ static int stv0297_readreg (struct stv0297_state* state, u8 reg) ...@@ -167,13 +167,11 @@ static int stv0297_readreg (struct stv0297_state* state, u8 reg)
// this device needs a STOP between the register and data // this device needs a STOP between the register and data
if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
__FUNCTION__, reg, ret);
return -1; return -1;
} }
if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
__FUNCTION__, reg, ret);
return -1; return -1;
} }
...@@ -200,59 +198,38 @@ static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len ...@@ -200,59 +198,38 @@ static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len
// this device needs a STOP between the register and data // this device needs a STOP between the register and data
if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
__FUNCTION__, reg1, ret);
return -1; return -1;
} }
if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
__FUNCTION__, reg1, ret);
return -1; return -1;
} }
return 0; return 0;
} }
static int stv0297_set_symbolrate (struct stv0297_state* state, u32 srate) static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate)
{ {
u64 tmp; long tmp;
tmp = srate; tmp = 131072L * srate; /* 131072 = 2^17 */
tmp <<= 32; tmp = tmp / (STV0297_CLOCK_KHZ / 4); /* 1/4 = 2^-2 */
do_div(tmp, STV0297_CLOCK); tmp = tmp * 8192L; /* 8192 = 2^13 */
stv0297_writereg (state, 0x55,(unsigned char)(tmp & 0xFF)); stv0297_writereg (state, 0x55,(unsigned char)(tmp & 0xFF));
stv0297_writereg (state, 0x56,(unsigned char)(tmp>> 8)); stv0297_writereg (state, 0x56,(unsigned char)(tmp>> 8));
stv0297_writereg (state, 0x57,(unsigned char)(tmp>>16)); stv0297_writereg (state, 0x57,(unsigned char)(tmp>>16));
stv0297_writereg (state, 0x58,(unsigned char)(tmp>>24)); stv0297_writereg (state, 0x58,(unsigned char)(tmp>>24));
return 0;
}
static u32 stv0297_get_symbolrate (struct stv0297_state* state)
{
u64 tmp;
tmp = stv0297_readreg(state, 0x55);
tmp |= (stv0297_readreg(state, 0x56) << 8);
tmp |= (stv0297_readreg(state, 0x57) << 16);
tmp |= (stv0297_readreg(state, 0x57) << 24);
tmp *= STV0297_CLOCK;
tmp >>= 32;
return tmp;
} }
static void stv0297_set_sweeprate(struct stv0297_state* state, short fshift) static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate)
{ {
s64 tmp; long tmp;
u32 symrate;
symrate = stv0297_get_symbolrate(state); tmp = (long) fshift *262144L; /* 262144 = 2*18 */
tmp /= symrate;
// cannot use shifts - it is signed tmp *= 1024; /* 1024 = 2*10 */
tmp = fshift * (1<<28);
do_div(tmp, symrate);
// adjust // adjust
if (tmp >= 0) { if (tmp >= 0) {
...@@ -260,68 +237,61 @@ static void stv0297_set_sweeprate(struct stv0297_state* state, short fshift) ...@@ -260,68 +237,61 @@ static void stv0297_set_sweeprate(struct stv0297_state* state, short fshift)
} else { } else {
tmp -= 500000; tmp -= 500000;
} }
do_div(tmp, 1000000); tmp /= 1000000;
stv0297_writereg(state, 0x60, tmp & 0xFF); stv0297_writereg(state, 0x60, tmp & 0xFF);
stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0); stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);
return;
} }
static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset) static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset)
{ {
long long_tmp; long tmp;
// symrate is hardcoded to 10000 here - don't ask me why /* symrate is hardcoded to 10000 */
long_tmp = offset * 26844L ; /* (2**28)/10000 */ tmp = offset * 26844L; /* (2**28)/10000 */
if(long_tmp < 0) long_tmp += 0x10000000 ; if (tmp < 0)
long_tmp &= 0x0FFFFFFF ; tmp += 0x10000000;
tmp &= 0x0FFFFFFF;
stv0297_writereg (state,0x66,(unsigned char)(long_tmp & 0xFF)); // iphase0
stv0297_writereg (state,0x67,(unsigned char)(long_tmp>>8)); // iphase1 stv0297_writereg(state, 0x66, (unsigned char) (tmp & 0xFF));
stv0297_writereg (state,0x68,(unsigned char)(long_tmp>>16)); // iphase2 stv0297_writereg(state, 0x67, (unsigned char) (tmp >> 8));
stv0297_writereg_mask(state, 0x69, 0x0F, (long_tmp >> 24) & 0x0f); stv0297_writereg(state, 0x68, (unsigned char) (tmp >> 16));
stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f);
return;
} }
static long stv0297_get_carrieroffset(struct stv0297_state* state) static long stv0297_get_carrieroffset(struct stv0297_state* state)
{ {
s32 raw; s32 raw;
s64 tmp; long tmp;
u32 symbol_rate;
stv0297_writereg(state,0x6B, 0x00); stv0297_writereg(state,0x6B, 0x00);
symbol_rate = stv0297_get_symbolrate(state);
raw = stv0297_readreg(state,0x66); raw = stv0297_readreg(state,0x66);
raw |= (stv0297_readreg(state,0x67) << 8); raw |= (stv0297_readreg(state,0x67) << 8);
raw |= (stv0297_readreg(state,0x68) << 16); raw |= (stv0297_readreg(state,0x68) << 16);
raw |= (stv0297_readreg(state,0x69) & 0x0F) << 24; raw |= (stv0297_readreg(state,0x69) & 0x0F) << 24;
// cannot just use a shift here 'cos it is signed
tmp = raw; tmp = raw;
tmp *= symbol_rate; tmp /= 26844L;
do_div(tmp, 1<<28);
return (s32) tmp; return tmp;
} }
static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq) static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq)
{ {
u64 tmp; /*
s64 tmp;
if (freq > 10000) freq -= STV0297_CLOCK; if (freq > 10000) freq -= STV0297_CLOCK_KHZ;
if (freq < 0) freq = 0;
tmp = freq << 16; tmp = freq << 16;
do_div(tmp, STV0297_CLOCK); do_div(tmp, STV0297_CLOCK_KHZ);
if (tmp > 0xffff) tmp = 0xffff; if (tmp > 0xffff) tmp = 0xffff; // check this calculation
stv0297_writereg_mask(state, 0x25, 0x80, 0x80); stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
stv0297_writereg(state, 0x21, tmp >> 8); stv0297_writereg(state, 0x21, tmp >> 8);
stv0297_writereg(state, 0x20, tmp); stv0297_writereg(state, 0x20, tmp);
*/
} }
static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation) static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation)
...@@ -407,26 +377,38 @@ static int stv0297_init (struct dvb_frontend* fe) ...@@ -407,26 +377,38 @@ static int stv0297_init (struct dvb_frontend* fe)
struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
int i; int i;
/* soft reset */
stv0297_writereg_mask(state, 0x80, 1, 1); stv0297_writereg_mask(state, 0x80, 1, 1);
stv0297_writereg_mask(state, 0x80, 1, 0); stv0297_writereg_mask(state, 0x80, 1, 0);
/* reset deinterleaver */
stv0297_writereg_mask(state, 0x81, 1, 1); stv0297_writereg_mask(state, 0x81, 1, 1);
stv0297_writereg_mask(state, 0x81, 1, 0); stv0297_writereg_mask(state, 0x81, 1, 0);
/* load init table */
for (i=0; i<sizeof(init_tab); i+=2) { for (i=0; i<sizeof(init_tab); i+=2) {
stv0297_writereg (state, init_tab[i], init_tab[i+1]); stv0297_writereg (state, init_tab[i], init_tab[i+1]);
} }
/* set a dummy symbol rate */
stv0297_set_symbolrate(state, 6900); stv0297_set_symbolrate(state, 6900);
/* invert AGC1 polarity */
stv0297_writereg_mask(state, 0x88, 0x10, 0x10); stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
/* setup bit error counting */
stv0297_writereg_mask(state, 0xA0, 0x80, 0x00); stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
stv0297_writereg_mask(state, 0xA0, 0x10, 0x00); stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
stv0297_writereg_mask(state, 0xA0, 0x08, 0x00); stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
stv0297_writereg_mask(state, 0xA0, 0x07, 0x04); stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
/* min + max PWM */
stv0297_writereg(state, 0x4a, 0x00); stv0297_writereg(state, 0x4a, 0x00);
stv0297_writereg(state, 0x4b, state->pwm); stv0297_writereg(state, 0x4b, state->pwm);
msleep(200); msleep(200);
if (state->config->pll_init) state->config->pll_init(fe); if (state->config->pll_init)
state->config->pll_init(fe);
return 0; return 0;
} }
...@@ -439,7 +421,8 @@ static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status) ...@@ -439,7 +421,8 @@ static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status)
*status = 0; *status = 0;
if (sync & 0x80) if (sync & 0x80)
*status |= FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; *status |=
FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
return 0; return 0;
} }
...@@ -497,7 +480,6 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -497,7 +480,6 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
int initial_u; int initial_u;
int blind_u; int blind_u;
int delay; int delay;
int locked;
int sweeprate; int sweeprate;
int carrieroffset; int carrieroffset;
unsigned long starttime; unsigned long starttime;
...@@ -542,9 +524,13 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -542,9 +524,13 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
state->config->pll_set(fe, p); state->config->pll_set(fe, p);
// reset everything /* clear software interrupts */
stv0297_writereg_mask(state, 0x82, 0x4, 0x4); stv0297_writereg(state, 0x82, 0x0);
/* set initial demodulation frequency */
stv0297_set_initialdemodfreq(state, state->freq_off + 7250); stv0297_set_initialdemodfreq(state, state->freq_off + 7250);
/* setup AGC */
stv0297_writereg_mask(state, 0x43, 0x10, 0x00); stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
stv0297_writereg(state, 0x41, 0x00); stv0297_writereg(state, 0x41, 0x00);
stv0297_writereg_mask(state, 0x42, 0x03, 0x01); stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
...@@ -556,16 +542,26 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -556,16 +542,26 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_writereg_mask(state, 0x74, 0x0F, 0x00); stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
stv0297_writereg_mask(state, 0x43, 0x08, 0x00); stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
stv0297_writereg_mask(state, 0x71, 0x80, 0x00); stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
/* setup STL */
stv0297_writereg_mask(state, 0x5a, 0x20, 0x20); stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
stv0297_writereg_mask(state, 0x5b, 0x02, 0x02); stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
stv0297_writereg_mask(state, 0x5b, 0x02, 0x00); stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
stv0297_writereg_mask(state, 0x5b, 0x01, 0x00); stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
stv0297_writereg_mask(state, 0x5a, 0x40, 0x40); stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
/* disable frequency sweep */
stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
/* reset deinterleaver */
stv0297_writereg_mask(state, 0x81, 0x01, 0x01); stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
stv0297_writereg_mask(state, 0x81, 0x01, 0x00); stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
/* ??? */
stv0297_writereg_mask(state, 0x83, 0x20, 0x20); stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
stv0297_writereg_mask(state, 0x83, 0x20, 0x00); stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
/* reset equaliser */
u_threshold = stv0297_readreg(state, 0x00) & 0xf; u_threshold = stv0297_readreg(state, 0x00) & 0xf;
initial_u = stv0297_readreg(state, 0x01) >> 4; initial_u = stv0297_readreg(state, 0x01) >> 4;
blind_u = stv0297_readreg(state, 0x01) & 0xf; blind_u = stv0297_readreg(state, 0x01) & 0xf;
...@@ -574,7 +570,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -574,7 +570,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold); stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4); stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
stv0297_writereg_mask(state, 0x01, 0x0f, blind_u); stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
/* data comes from internal A/D */
stv0297_writereg_mask(state, 0x87, 0x80, 0x00); stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
/* clear phase registers */
stv0297_writereg(state, 0x63, 0x00); stv0297_writereg(state, 0x63, 0x00);
stv0297_writereg(state, 0x64, 0x00); stv0297_writereg(state, 0x64, 0x00);
stv0297_writereg(state, 0x65, 0x00); stv0297_writereg(state, 0x65, 0x00);
...@@ -583,14 +583,14 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -583,14 +583,14 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_writereg(state, 0x68, 0x00); stv0297_writereg(state, 0x68, 0x00);
stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
// set parameters /* set parameters */
stv0297_set_qam(state, p->u.qam.modulation); stv0297_set_qam(state, p->u.qam.modulation);
stv0297_set_symbolrate(state, p->u.qam.symbol_rate/1000); stv0297_set_symbolrate(state, p->u.qam.symbol_rate/1000);
stv0297_set_sweeprate(state, sweeprate); stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
stv0297_set_carrieroffset(state, carrieroffset); stv0297_set_carrieroffset(state, carrieroffset);
stv0297_set_inversion(state, p->inversion); stv0297_set_inversion(state, p->inversion);
// kick off lock /* kick off lock */
stv0297_writereg_mask(state, 0x88, 0x08, 0x08); stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
stv0297_writereg_mask(state, 0x5a, 0x20, 0x00); stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
stv0297_writereg_mask(state, 0x6a, 0x01, 0x01); stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
...@@ -600,33 +600,33 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -600,33 +600,33 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_writereg_mask(state, 0x03, 0x03, 0x03); stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
stv0297_writereg_mask(state, 0x43, 0x10, 0x10); stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
// wait for WGAGC lock /* wait for WGAGC lock */
starttime = jiffies; starttime = jiffies;
timeout = jiffies + (200*HZ)/1000; timeout = jiffies + (200*HZ)/1000;
while(time_before(jiffies, timeout)) { while(time_before(jiffies, timeout)) {
msleep(10); msleep(10);
if (stv0297_readreg(state, 0x43) & 0x08) break; if (stv0297_readreg(state, 0x43) & 0x08)
break;
} }
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
goto timeout; goto timeout;
} }
msleep(20); msleep(20);
// wait for equaliser partial convergence /* wait for equaliser partial convergence */
locked = 0;
timeout = jiffies + (50*HZ)/1000; timeout = jiffies + (50*HZ)/1000;
while(time_before(jiffies, timeout)) { while(time_before(jiffies, timeout)) {
msleep(10); msleep(10);
if (stv0297_readreg(state, 0x82) & 0x04) { if (stv0297_readreg(state, 0x82) & 0x04) {
locked = 1; break;
} }
} }
if (time_after(jiffies, timeout) && (!locked)) { if (time_after(jiffies, timeout)) {
goto timeout; goto timeout;
} }
// wait for equaliser full convergence /* wait for equaliser full convergence */
timeout = jiffies + (delay*HZ)/1000; timeout = jiffies + (delay*HZ)/1000;
while(time_before(jiffies, timeout)) { while(time_before(jiffies, timeout)) {
msleep(10); msleep(10);
...@@ -639,11 +639,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -639,11 +639,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
goto timeout; goto timeout;
} }
// disable sweep /* disable sweep */
stv0297_writereg_mask(state, 0x6a, 1, 0); stv0297_writereg_mask(state, 0x6a, 1, 0);
stv0297_writereg_mask(state, 0x88, 8, 0); stv0297_writereg_mask(state, 0x88, 8, 0);
// wait for main lock /* wait for main lock */
timeout = jiffies + (20*HZ)/1000; timeout = jiffies + (20*HZ)/1000;
while(time_before(jiffies, timeout)) { while(time_before(jiffies, timeout)) {
msleep(10); msleep(10);
...@@ -657,12 +657,12 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -657,12 +657,12 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
} }
msleep(100); msleep(100);
// is it still locked after that delay? /* is it still locked after that delay? */
if (!(stv0297_readreg(state, 0xDF) & 0x80)) { if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
goto timeout; goto timeout;
} }
// success!! /* success!! */
stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
state->freq_off = stv0297_get_carrieroffset(state); state->freq_off = stv0297_get_carrieroffset(state);
state->base_freq = p->frequency; state->base_freq = p->frequency;
...@@ -683,15 +683,25 @@ static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -683,15 +683,25 @@ static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
p->frequency = state->base_freq + state->freq_off; p->frequency = state->base_freq + state->freq_off;
p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF; p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
p->u.qam.symbol_rate = stv0297_get_symbolrate(state); p->u.qam.symbol_rate = 0;
p->u.qam.fec_inner = 0; p->u.qam.fec_inner = 0;
switch((reg_00 >> 4) & 0x7) { switch((reg_00 >> 4) & 0x7) {
case 0: p->u.qam.modulation = QAM_16; break; case 0:
case 1: p->u.qam.modulation = QAM_32; break; p->u.qam.modulation = QAM_16;
case 2: p->u.qam.modulation = QAM_128; break; break;
case 3: p->u.qam.modulation = QAM_256; break; case 1:
case 4: p->u.qam.modulation = QAM_64; break; p->u.qam.modulation = QAM_32;
break;
case 2:
p->u.qam.modulation = QAM_128;
break;
case 3:
p->u.qam.modulation = QAM_256;
break;
case 4:
p->u.qam.modulation = QAM_64;
break;
} }
return 0; return 0;
...@@ -706,14 +716,14 @@ static void stv0297_release(struct dvb_frontend* fe) ...@@ -706,14 +716,14 @@ static void stv0297_release(struct dvb_frontend* fe)
static struct dvb_frontend_ops stv0297_ops; static struct dvb_frontend_ops stv0297_ops;
struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
struct i2c_adapter* i2c, struct i2c_adapter *i2c, int pwm)
int pwm)
{ {
struct stv0297_state* state = NULL; struct stv0297_state* state = NULL;
/* allocate memory for the internal state */ /* allocate memory for the internal state */
state = (struct stv0297_state*) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL); state = (struct stv0297_state*) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
if (state == NULL) goto error; if (state == NULL)
goto error;
/* setup the state */ /* setup the state */
state->config = config; state->config = config;
...@@ -724,7 +734,8 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, ...@@ -724,7 +734,8 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
state->pwm = pwm; state->pwm = pwm;
/* check if the demod is there */ /* check if the demod is there */
if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20) goto error; if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
goto error;
/* create dvb_frontend */ /* create dvb_frontend */
state->frontend.ops = &state->ops; state->frontend.ops = &state->ops;
...@@ -732,7 +743,8 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, ...@@ -732,7 +743,8 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
return &state->frontend; return &state->frontend;
error: error:
if (state) kfree(state); if (state)
kfree(state);
return NULL; return NULL;
} }
...@@ -747,10 +759,7 @@ static struct dvb_frontend_ops stv0297_ops = { ...@@ -747,10 +759,7 @@ static struct dvb_frontend_ops stv0297_ops = {
.symbol_rate_min = 870000, .symbol_rate_min = 870000,
.symbol_rate_max = 11700000, .symbol_rate_max = 11700000,
.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_FEC_AUTO | FE_CAN_INVERSION_AUTO |
FE_CAN_RECOVER
},
.release = stv0297_release, .release = stv0297_release,
......
...@@ -393,6 +393,11 @@ static int tda10046_fwupload(struct dvb_frontend* fe) ...@@ -393,6 +393,11 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
int ret; int ret;
const struct firmware *fw; const struct firmware *fw;
/* reset + wake up chip */
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0);
tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
msleep(100);
/* don't re-upload unless necessary */ /* don't re-upload unless necessary */
if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0; if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0;
...@@ -404,11 +409,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe) ...@@ -404,11 +409,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret; return ret;
} }
/* reset chip */
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0);
tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
msleep(10);
/* set parameters */ /* set parameters */
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0);
...@@ -533,6 +533,8 @@ static int tda10045_init(struct dvb_frontend* fe) ...@@ -533,6 +533,8 @@ static int tda10045_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity
tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e); tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e);
tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
state->initialised = 1; state->initialised = 1;
return 0; return 0;
} }
...@@ -585,6 +587,8 @@ static int tda10046_init(struct dvb_frontend* fe) ...@@ -585,6 +587,8 @@ static int tda10046_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
state->initialised = 1; state->initialised = 1;
return 0; return 0;
} }
...@@ -616,12 +620,13 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, ...@@ -616,12 +620,13 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
if (state->demod_type == TDA1004X_DEMOD_TDA10046) if (state->demod_type == TDA1004X_DEMOD_TDA10046)
tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4); tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4);
// Hardcoded to use auto as much as possible // Hardcoded to use auto as much as possible on the TDA10045 as it
// The TDA10045 is very unreliable if AUTO mode is _not_ used. I have not // is very unreliable if AUTO mode is _not_ used.
// yet tested the TDA10046 to see if this issue has been fixed if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
}
// Set standard params.. or put them to auto // Set standard params.. or put them to auto
if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
...@@ -1170,6 +1175,7 @@ static struct dvb_frontend_ops tda10045_ops = { ...@@ -1170,6 +1175,7 @@ static struct dvb_frontend_ops tda10045_ops = {
.set_frontend = tda1004x_set_fe, .set_frontend = tda1004x_set_fe,
.get_frontend = tda1004x_get_fe, .get_frontend = tda1004x_get_fe,
.get_tune_settings = tda1004x_get_tune_settings,
.read_status = tda1004x_read_status, .read_status = tda1004x_read_status,
.read_ber = tda1004x_read_ber, .read_ber = tda1004x_read_ber,
......
...@@ -34,6 +34,9 @@ struct tda1004x_config ...@@ -34,6 +34,9 @@ struct tda1004x_config
/* does the "inversion" need inverted? */ /* does the "inversion" need inverted? */
u8 invert:1; u8 invert:1;
/* Does the OCLK signal need inverted? */
u8 invert_oclk:1;
/* PLL maintenance */ /* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe); int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
......
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