diff options
author | Hartmut Hackmann <hartmut.hackmann@t\-online.de> | 2006-02-07 03:49:10 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-02-07 03:49:10 -0500 |
commit | 0eb3de20a1cec67547951cebc4fcddc701e7428b (patch) | |
tree | 056fbb4adedc7b2462efa4146b8bd8ad35c3cb16 | |
parent | 0157a9cc727dec90a7d60ad254eb899a775685a9 (diff) |
V4L/DVB (3304): TDA10046 Driver update
- Set outputs to tristate in sleep mode
- Reduce dangerously high firmware download speed with 16MHz xtal
- added tda827x configuration with GPIOs low
- added comments to stupid looking IIC reads that work around bugs in
the tda10046.
- some minor updates
Signed-off-by: Hartmut Hackmann <hartmut.hackmann@t-online.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/frontends/tda1004x.c | 25 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda1004x.h | 3 |
2 files changed, 23 insertions, 5 deletions
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index c63e9a5084eb..8e8df7b4ca0e 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
@@ -229,7 +229,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) | |||
229 | dprintk("%s\n", __FUNCTION__); | 229 | dprintk("%s\n", __FUNCTION__); |
230 | 230 | ||
231 | result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); | 231 | result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); |
232 | msleep(1); | 232 | msleep(20); |
233 | return result; | 233 | return result; |
234 | } | 234 | } |
235 | 235 | ||
@@ -502,7 +502,12 @@ static int tda10046_fwupload(struct dvb_frontend* fe) | |||
502 | const struct firmware *fw; | 502 | const struct firmware *fw; |
503 | 503 | ||
504 | /* reset + wake up chip */ | 504 | /* reset + wake up chip */ |
505 | tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); | 505 | if (state->config->xtal_freq == TDA10046_XTAL_4M) { |
506 | tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); | ||
507 | } else { | ||
508 | dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__); | ||
509 | tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); | ||
510 | } | ||
506 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); | 511 | tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); |
507 | /* let the clocks recover from sleep */ | 512 | /* let the clocks recover from sleep */ |
508 | msleep(5); | 513 | msleep(5); |
@@ -651,7 +656,7 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
651 | // tda setup | 656 | // tda setup |
652 | tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer | 657 | tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer |
653 | tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream | 658 | tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream |
654 | tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer | 659 | tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88); // enable pulse killer |
655 | 660 | ||
656 | switch (state->config->agc_config) { | 661 | switch (state->config->agc_config) { |
657 | case TDA10046_AGC_DEFAULT: | 662 | case TDA10046_AGC_DEFAULT: |
@@ -672,6 +677,12 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
672 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | 677 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize |
673 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities | 678 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities |
674 | break; | 679 | break; |
680 | case TDA10046_AGC_TDA827X_GPL: | ||
681 | tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup | ||
682 | tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold | ||
683 | tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize | ||
684 | tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities | ||
685 | break; | ||
675 | } | 686 | } |
676 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); | 687 | tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); |
677 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on | 688 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on |
@@ -683,6 +694,7 @@ static int tda10046_init(struct dvb_frontend* fe) | |||
683 | tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits | 694 | tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits |
684 | tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config | 695 | tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config |
685 | tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config | 696 | tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config |
697 | // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes | ||
686 | tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); | 698 | tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); |
687 | 699 | ||
688 | state->initialised = 1; | 700 | state->initialised = 1; |
@@ -1027,6 +1039,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status | |||
1027 | if (status == -1) | 1039 | if (status == -1) |
1028 | return -EIO; | 1040 | return -EIO; |
1029 | cber |= (status << 8); | 1041 | cber |= (status << 8); |
1042 | // The address 0x20 should be read to cope with a TDA10046 bug | ||
1030 | tda1004x_read_byte(state, TDA1004X_CBER_RESET); | 1043 | tda1004x_read_byte(state, TDA1004X_CBER_RESET); |
1031 | 1044 | ||
1032 | if (cber != 65535) | 1045 | if (cber != 65535) |
@@ -1047,7 +1060,8 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status | |||
1047 | status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); | 1060 | status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); |
1048 | if (status == -1) | 1061 | if (status == -1) |
1049 | return -EIO; | 1062 | return -EIO; |
1050 | vber |= ((status << 16) & 0x0f); | 1063 | vber |= (status & 0x0f) << 16; |
1064 | // The CVBER_LUT should be read to cope with TDA10046 hardware bug | ||
1051 | tda1004x_read_byte(state, TDA1004X_CVBER_LUT); | 1065 | tda1004x_read_byte(state, TDA1004X_CVBER_LUT); |
1052 | 1066 | ||
1053 | // if RS has passed some valid TS packets, then we must be | 1067 | // if RS has passed some valid TS packets, then we must be |
@@ -1161,6 +1175,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) | |||
1161 | if (tmp < 0) | 1175 | if (tmp < 0) |
1162 | return -EIO; | 1176 | return -EIO; |
1163 | *ber |= (tmp << 9); | 1177 | *ber |= (tmp << 9); |
1178 | // The address 0x20 should be read to cope with a TDA10046 bug | ||
1164 | tda1004x_read_byte(state, TDA1004X_CBER_RESET); | 1179 | tda1004x_read_byte(state, TDA1004X_CBER_RESET); |
1165 | 1180 | ||
1166 | dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); | 1181 | dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); |
@@ -1187,6 +1202,8 @@ static int tda1004x_sleep(struct dvb_frontend* fe) | |||
1187 | tda1004x_disable_tuner_i2c(state); | 1202 | tda1004x_disable_tuner_i2c(state); |
1188 | } | 1203 | } |
1189 | } | 1204 | } |
1205 | /* set outputs to tristate */ | ||
1206 | tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); | ||
1190 | tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); | 1207 | tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); |
1191 | break; | 1208 | break; |
1192 | } | 1209 | } |
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 8659c52647ad..cc0c4af64067 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h | |||
@@ -35,7 +35,8 @@ enum tda10046_agc { | |||
35 | TDA10046_AGC_DEFAULT, /* original configuration */ | 35 | TDA10046_AGC_DEFAULT, /* original configuration */ |
36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ | 36 | TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ |
37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ | 37 | TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ |
38 | TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ | 38 | TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ |
39 | TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | enum tda10046_if { | 42 | enum tda10046_if { |