From 0eb3de20a1cec67547951cebc4fcddc701e7428b Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 7 Feb 2006 06:49:10 -0200 Subject: 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda1004x.c | 25 +++++++++++++++++++++---- drivers/media/dvb/frontends/tda1004x.h | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index c63e9a5084e..8e8df7b4ca0 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) dprintk("%s\n", __FUNCTION__); result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); - msleep(1); + msleep(20); return result; } @@ -502,7 +502,12 @@ static int tda10046_fwupload(struct dvb_frontend* fe) const struct firmware *fw; /* reset + wake up chip */ - tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); + if (state->config->xtal_freq == TDA10046_XTAL_4M) { + tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); + } else { + dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__); + tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); + } tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); /* let the clocks recover from sleep */ msleep(5); @@ -651,7 +656,7 @@ static int tda10046_init(struct dvb_frontend* fe) // tda setup tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream - tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer + tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88); // enable pulse killer switch (state->config->agc_config) { case TDA10046_AGC_DEFAULT: @@ -672,6 +677,12 @@ static int tda10046_init(struct dvb_frontend* fe) tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities break; + case TDA10046_AGC_TDA827X_GPL: + tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup + tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold + tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize + tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities + break; } tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38); 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) tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config + // tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); state->initialised = 1; @@ -1027,6 +1039,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status if (status == -1) return -EIO; cber |= (status << 8); + // The address 0x20 should be read to cope with a TDA10046 bug tda1004x_read_byte(state, TDA1004X_CBER_RESET); if (cber != 65535) @@ -1047,7 +1060,8 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); if (status == -1) return -EIO; - vber |= ((status << 16) & 0x0f); + vber |= (status & 0x0f) << 16; + // The CVBER_LUT should be read to cope with TDA10046 hardware bug tda1004x_read_byte(state, TDA1004X_CVBER_LUT); // 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) if (tmp < 0) return -EIO; *ber |= (tmp << 9); + // The address 0x20 should be read to cope with a TDA10046 bug tda1004x_read_byte(state, TDA1004X_CBER_RESET); dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); @@ -1187,6 +1202,8 @@ static int tda1004x_sleep(struct dvb_frontend* fe) tda1004x_disable_tuner_i2c(state); } } + /* set outputs to tristate */ + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index 8659c52647a..cc0c4af6406 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -35,7 +35,8 @@ enum tda10046_agc { TDA10046_AGC_DEFAULT, /* original configuration */ TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */ TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */ - TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */ + TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */ }; enum tda10046_if { -- cgit v1.2.3