summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.c74
1 files changed, 31 insertions, 43 deletions
diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c
index 35d9211ad..8c9154948 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.c
+++ b/linux/drivers/media/dvb/frontends/stv0299.c
@@ -103,6 +103,7 @@ static struct dvb_frontend_info uni0299_info = {
struct stv0299_state {
u8 tuner_type;
+ u8 initialised:1;
u32 tuner_frequency;
u32 symbol_rate;
fe_code_rate_t fec_inner;
@@ -371,7 +372,7 @@ static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, in
regcode = 2;
// setup frequency divisor
- div = freq / divisor;
+ div = (freq + (divisor - 1)) / divisor; // round correctly
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode;
@@ -592,15 +593,6 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype)
for (i=0; i<sizeof(init_tab_su1278_tsa_tt); i+=2) {
stv0299_writereg (i2c, init_tab_su1278_tsa_tt[i], init_tab_su1278_tsa_tt[i+1]);
}
-
- // seems to be much more reliable if a proper tune is kicked off during init
- stv0299_writereg(i2c, 0x0c, stv0299_readreg(i2c, 0x0c) & 0xfe);
- stv0299_set_FEC(i2c, FEC_AUTO);
- stv0299_set_symbolrate(i2c, 27500000, ftype);
- pll_set_tv_freq (i2c, 12200000, ftype, 27500000);
- stv0299_writereg (i2c, 0x22, 0x00);
- stv0299_writereg (i2c, 0x23, 0x00);
- dvb_delay(200); // long delay is needed to recover from sleeping
break;
default:
@@ -635,23 +627,6 @@ static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype)
}
-static int stv0299_check_inversion (struct dvb_i2c_bus *i2c)
-{
- dprintk ("%s\n", __FUNCTION__);
-
- if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
- dvb_delay(30);
- if ((stv0299_readreg (i2c, 0x1b) & 0x98) != 0x98) {
- u8 val = stv0299_readreg (i2c, 0x0c);
- dprintk ("%s : changing inversion\n", __FUNCTION__);
- return stv0299_writereg (i2c, 0x0c, val ^ 0x01);
- }
- }
-
- return 0;
-}
-
-
static int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -892,6 +867,7 @@ static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner
// calculate value to program
if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT;
big = big << 20;
+ big += (Mclk-1); // round correctly
do_div(big, Mclk);
ratio = big << 4;
@@ -1112,10 +1088,16 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
int frequency_delta = p->frequency - state->tuner_frequency;
int minmax = p->u.qpsk.symbol_rate / 1000;
- if ((frequency_delta > -minmax) && (frequency_delta < minmax) &&
+ 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);
+ 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);
break;
@@ -1123,18 +1105,18 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
}
/* A "normal" tune is requested */
- stv0299_set_FEC (i2c, p->u.qpsk.fec_inner);
- stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type);
- pll_set_tv_freq (i2c, p->frequency, state->tuner_type,
- p->u.qpsk.symbol_rate);
- stv0299_writereg (i2c, 0x22, 0x00);
- stv0299_writereg (i2c, 0x23, 0x00);
- if (state->tuner_type != PHILIPS_SU1278_TSA_TT) {
- stv0299_readreg (i2c, 0x23);
- stv0299_writereg (i2c, 0x12, 0xb9);
- }
- dvb_delay(10);
-
+ 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);
+ pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate);
+ dvb_delay(50);
+ stv0299_writereg (i2c, 0x22, 0x00);
+ stv0299_writereg (i2c, 0x23, 0x00);
+ pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate);
+
state->tuner_frequency = p->frequency;
state->fec_inner = p->u.qpsk.fec_inner;
state->symbol_rate = p->u.qpsk.symbol_rate;
@@ -1168,11 +1150,16 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */
stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */
stv0299_writereg (i2c, 0x02, 0x80);
+ state->initialised = 0;
break;
case FE_INIT:
state->tuner_frequency = 0;
- return stv0299_init (i2c, state->tuner_type);
+ if (!state->initialised) {
+ state->initialised = 1;
+ return stv0299_init (i2c, state->tuner_type);
+ }
+ break;
case FE_DISEQC_SEND_MASTER_CMD:
return stv0299_send_diseqc_msg (i2c, arg);
@@ -1186,7 +1173,7 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case FE_SET_VOLTAGE:
return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg);
- default:
+ default:
return -EOPNOTSUPP;
};
@@ -1291,6 +1278,7 @@ static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data)
*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);
}