From: Michael Hunold - 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: Michael Hunold Signed-off-by: Andrew Morton --- 25-akpm/drivers/media/dvb/frontends/mt312.c | 79 +++++---- 25-akpm/drivers/media/dvb/frontends/mt312.h | 3 25-akpm/drivers/media/dvb/frontends/mt352.c | 6 25-akpm/drivers/media/dvb/frontends/stv0297.c | 211 +++++++++++++------------ 25-akpm/drivers/media/dvb/frontends/tda1004x.c | 22 +- 25-akpm/drivers/media/dvb/frontends/tda1004x.h | 3 6 files changed, 180 insertions(+), 144 deletions(-) diff -puN drivers/media/dvb/frontends/mt312.c~dvb-frontend-update drivers/media/dvb/frontends/mt312.c --- 25/drivers/media/dvb/frontends/mt312.c~dvb-frontend-update Fri Dec 10 15:14:18 2004 +++ 25-akpm/drivers/media/dvb/frontends/mt312.c Fri Dec 10 15:14:18 2004 @@ -393,7 +393,7 @@ static int mt312_read_status(struct dvb_ { struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; - u8 status[3], vit_mode; + u8 status[3]; *s = 0; @@ -413,17 +413,6 @@ static int mt312_read_status(struct dvb_ if (status[0] & 0x01) *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; } @@ -638,61 +627,88 @@ static void mt312_release(struct dvb_fro 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 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; + if (state == NULL) + goto error; /* setup the state */ state->config = config; 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 */ - if (mt312_readreg(state, ID, &state->id) < 0) goto error; - switch(state->id) { - case ID_VP310: + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + if (state->id != ID_VP310) { + goto error; + } + + /* create dvb_frontend */ state->frequency = 90; - printk("mt312: Detected Zarlink VP310\n"); - break; + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - case ID_MT312: - state->frequency = 60; - printk("mt312: Detected Zarlink MT312\n"); - break; +error: + if (state) + kfree(state); + 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; } /* create dvb_frontend */ + state->frequency = 60; state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; return &state->frontend; error: - if (state) kfree(state); + if (state) + kfree(state); return NULL; } -static struct dvb_frontend_ops mt312_ops = { +static struct dvb_frontend_ops vp310_mt312_ops = { .info = { - .name = "Zarlink VP310/MT312 DVB-S", + .name = "Zarlink ???? DVB-S", .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, - /*.frequency_tolerance = 29500, FIXME: binary compatibility waste? */ .symbol_rate_min = MT312_SYS_CLK / 128, .symbol_rate_max = MT312_SYS_CLK / 2, - /*.symbol_rate_tolerance = 500, FIXME: binary compatibility waste? 2% */ .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 | @@ -729,3 +745,4 @@ MODULE_AUTHOR("Andreas Oberritter i2c, &msg, 1); if (err != 1) { - printk(KERN_WARNING - "mt352_write() failed (err = %d)!\n", err); + dprintk("mt352_write() failed (err = %d)!\n", err); return err; } @@ -88,8 +87,7 @@ static u8 mt352_read_register(struct mt3 ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk(KERN_WARNING - "%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); return b1[0]; } diff -puN drivers/media/dvb/frontends/stv0297.c~dvb-frontend-update drivers/media/dvb/frontends/stv0297.c --- 25/drivers/media/dvb/frontends/stv0297.c~dvb-frontend-update Fri Dec 10 15:14:18 2004 +++ 25-akpm/drivers/media/dvb/frontends/stv0297.c Fri Dec 10 15:14:18 2004 @@ -51,7 +51,7 @@ struct stv0297_state { #define dprintk(x...) #endif -#define STV0297_CLOCK 28900 +#define STV0297_CLOCK_KHZ 28900 static u8 init_tab [] = { 0x00, 0x09, @@ -78,7 +78,7 @@ static u8 init_tab [] = { 0x40, 0x1c, 0x41, 0xff, 0x42, 0x29, - 0x43, 0x00,// check + 0x43, 0x00, 0x44, 0xff, 0x45, 0x00, 0x46, 0x00, @@ -167,13 +167,11 @@ static int stv0297_readreg (struct stv02 // this device needs a STOP between the register and data if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); return -1; } if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); return -1; } @@ -200,59 +198,38 @@ static int stv0297_readregs (struct stv0 // this device needs a STOP between the register and data if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", - __FUNCTION__, reg1, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); return -1; } if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", - __FUNCTION__, reg1, ret); + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); return -1; } 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 <<= 32; - do_div(tmp, STV0297_CLOCK); + tmp = 131072L * srate; /* 131072 = 2^17 */ + tmp = tmp / (STV0297_CLOCK_KHZ / 4); /* 1/4 = 2^-2 */ + tmp = tmp * 8192L; /* 8192 = 2^13 */ stv0297_writereg (state, 0x55,(unsigned char)(tmp & 0xFF)); stv0297_writereg (state, 0x56,(unsigned char)(tmp>> 8)); stv0297_writereg (state, 0x57,(unsigned char)(tmp>>16)); 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; - u32 symrate; - - symrate = stv0297_get_symbolrate(state); + long tmp; - // cannot use shifts - it is signed - tmp = fshift * (1<<28); - do_div(tmp, symrate); + tmp = (long) fshift *262144L; /* 262144 = 2*18 */ + tmp /= symrate; + tmp *= 1024; /* 1024 = 2*10 */ // adjust if (tmp >= 0) { @@ -260,68 +237,61 @@ static void stv0297_set_sweeprate(struct } else { tmp -= 500000; } - do_div(tmp, 1000000); + tmp /= 1000000; stv0297_writereg(state, 0x60, tmp & 0xFF); stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0); - - return; } static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset) { - long long_tmp; - - // symrate is hardcoded to 10000 here - don't ask me why - long_tmp = offset * 26844L ; /* (2**28)/10000 */ - if(long_tmp < 0) long_tmp += 0x10000000 ; - long_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,0x68,(unsigned char)(long_tmp>>16)); // iphase2 - stv0297_writereg_mask(state, 0x69, 0x0F, (long_tmp >> 24) & 0x0f); + long tmp; - return; + /* symrate is hardcoded to 10000 */ + tmp = offset * 26844L; /* (2**28)/10000 */ + if (tmp < 0) + tmp += 0x10000000; + tmp &= 0x0FFFFFFF; + + stv0297_writereg(state, 0x66, (unsigned char) (tmp & 0xFF)); + stv0297_writereg(state, 0x67, (unsigned char) (tmp >> 8)); + stv0297_writereg(state, 0x68, (unsigned char) (tmp >> 16)); + stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f); } static long stv0297_get_carrieroffset(struct stv0297_state* state) { s32 raw; - s64 tmp; - u32 symbol_rate; + long tmp; stv0297_writereg(state,0x6B, 0x00); - symbol_rate = stv0297_get_symbolrate(state); - raw = stv0297_readreg(state,0x66); raw |= (stv0297_readreg(state,0x67) << 8); raw |= (stv0297_readreg(state,0x68) << 16); raw |= (stv0297_readreg(state,0x69) & 0x0F) << 24; - // cannot just use a shift here 'cos it is signed tmp = raw; - tmp *= symbol_rate; - do_div(tmp, 1<<28); + tmp /= 26844L; - return (s32) tmp; + return tmp; } static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq) { - u64 tmp; +/* + s64 tmp; - if (freq > 10000) freq -= STV0297_CLOCK; - if (freq < 0) freq = 0; + if (freq > 10000) freq -= STV0297_CLOCK_KHZ; tmp = freq << 16; - do_div(tmp, STV0297_CLOCK); - if (tmp > 0xffff) tmp = 0xffff; + do_div(tmp, STV0297_CLOCK_KHZ); + if (tmp > 0xffff) tmp = 0xffff; // check this calculation stv0297_writereg_mask(state, 0x25, 0x80, 0x80); stv0297_writereg(state, 0x21, tmp >> 8); stv0297_writereg(state, 0x20, tmp); +*/ } static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation) @@ -407,26 +377,38 @@ static int stv0297_init (struct dvb_fron struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; int i; + /* soft reset */ stv0297_writereg_mask(state, 0x80, 1, 1); stv0297_writereg_mask(state, 0x80, 1, 0); + + /* reset deinterleaver */ stv0297_writereg_mask(state, 0x81, 1, 1); stv0297_writereg_mask(state, 0x81, 1, 0); + /* load init table */ for (i=0; ipwm); msleep(200); - if (state->config->pll_init) state->config->pll_init(fe); + if (state->config->pll_init) + state->config->pll_init(fe); return 0; } @@ -439,7 +421,8 @@ static int stv0297_read_status(struct dv *status = 0; 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; } @@ -497,7 +480,6 @@ static int stv0297_set_frontend(struct d int initial_u; int blind_u; int delay; - int locked; int sweeprate; int carrieroffset; unsigned long starttime; @@ -542,9 +524,13 @@ static int stv0297_set_frontend(struct d state->config->pll_set(fe, p); - // reset everything - stv0297_writereg_mask(state, 0x82, 0x4, 0x4); + /* clear software interrupts */ + stv0297_writereg(state, 0x82, 0x0); + + /* set initial demodulation frequency */ stv0297_set_initialdemodfreq(state, state->freq_off + 7250); + + /* setup AGC */ stv0297_writereg_mask(state, 0x43, 0x10, 0x00); stv0297_writereg(state, 0x41, 0x00); stv0297_writereg_mask(state, 0x42, 0x03, 0x01); @@ -556,16 +542,26 @@ static int stv0297_set_frontend(struct d stv0297_writereg_mask(state, 0x74, 0x0F, 0x00); stv0297_writereg_mask(state, 0x43, 0x08, 0x00); stv0297_writereg_mask(state, 0x71, 0x80, 0x00); + + /* setup STL */ stv0297_writereg_mask(state, 0x5a, 0x20, 0x20); stv0297_writereg_mask(state, 0x5b, 0x02, 0x02); stv0297_writereg_mask(state, 0x5b, 0x02, 0x00); stv0297_writereg_mask(state, 0x5b, 0x01, 0x00); stv0297_writereg_mask(state, 0x5a, 0x40, 0x40); + + /* disable frequency sweep */ stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); + + /* reset deinterleaver */ stv0297_writereg_mask(state, 0x81, 0x01, 0x01); stv0297_writereg_mask(state, 0x81, 0x01, 0x00); + + /* ??? */ stv0297_writereg_mask(state, 0x83, 0x20, 0x20); stv0297_writereg_mask(state, 0x83, 0x20, 0x00); + + /* reset equaliser */ u_threshold = stv0297_readreg(state, 0x00) & 0xf; initial_u = stv0297_readreg(state, 0x01) >> 4; blind_u = stv0297_readreg(state, 0x01) & 0xf; @@ -574,7 +570,11 @@ static int stv0297_set_frontend(struct d stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold); stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4); stv0297_writereg_mask(state, 0x01, 0x0f, blind_u); + + /* data comes from internal A/D */ stv0297_writereg_mask(state, 0x87, 0x80, 0x00); + + /* clear phase registers */ stv0297_writereg(state, 0x63, 0x00); stv0297_writereg(state, 0x64, 0x00); stv0297_writereg(state, 0x65, 0x00); @@ -583,14 +583,14 @@ static int stv0297_set_frontend(struct d stv0297_writereg(state, 0x68, 0x00); stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); - // set parameters + /* set parameters */ stv0297_set_qam(state, p->u.qam.modulation); 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_inversion(state, p->inversion); - // kick off lock + /* kick off lock */ stv0297_writereg_mask(state, 0x88, 0x08, 0x08); stv0297_writereg_mask(state, 0x5a, 0x20, 0x00); stv0297_writereg_mask(state, 0x6a, 0x01, 0x01); @@ -600,33 +600,33 @@ static int stv0297_set_frontend(struct d stv0297_writereg_mask(state, 0x03, 0x03, 0x03); stv0297_writereg_mask(state, 0x43, 0x10, 0x10); - // wait for WGAGC lock + /* wait for WGAGC lock */ starttime = jiffies; timeout = jiffies + (200*HZ)/1000; while(time_before(jiffies, timeout)) { msleep(10); - if (stv0297_readreg(state, 0x43) & 0x08) break; + if (stv0297_readreg(state, 0x43) & 0x08) + break; } if (time_after(jiffies, timeout)) { goto timeout; } msleep(20); - // wait for equaliser partial convergence - locked = 0; + /* wait for equaliser partial convergence */ timeout = jiffies + (50*HZ)/1000; while(time_before(jiffies, timeout)) { msleep(10); if (stv0297_readreg(state, 0x82) & 0x04) { - locked = 1; + break; } } - if (time_after(jiffies, timeout) && (!locked)) { + if (time_after(jiffies, timeout)) { goto timeout; } - // wait for equaliser full convergence + /* wait for equaliser full convergence */ timeout = jiffies + (delay*HZ)/1000; while(time_before(jiffies, timeout)) { msleep(10); @@ -639,11 +639,11 @@ static int stv0297_set_frontend(struct d goto timeout; } - // disable sweep + /* disable sweep */ stv0297_writereg_mask(state, 0x6a, 1, 0); stv0297_writereg_mask(state, 0x88, 8, 0); - // wait for main lock + /* wait for main lock */ timeout = jiffies + (20*HZ)/1000; while(time_before(jiffies, timeout)) { msleep(10); @@ -657,12 +657,12 @@ static int stv0297_set_frontend(struct d } msleep(100); - // is it still locked after that delay? + /* is it still locked after that delay? */ if (!(stv0297_readreg(state, 0xDF) & 0x80)) { goto timeout; } - // success!! + /* success!! */ stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); state->freq_off = stv0297_get_carrieroffset(state); state->base_freq = p->frequency; @@ -683,15 +683,25 @@ static int stv0297_get_frontend(struct d p->frequency = state->base_freq + state->freq_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; switch((reg_00 >> 4) & 0x7) { - case 0: p->u.qam.modulation = QAM_16; break; - case 1: 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; + case 0: + p->u.qam.modulation = QAM_16; + break; + case 1: + 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; @@ -706,14 +716,14 @@ static void stv0297_release(struct dvb_f static struct dvb_frontend_ops stv0297_ops; struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, - struct i2c_adapter* i2c, - int pwm) + struct i2c_adapter *i2c, int pwm) { struct stv0297_state* state = NULL; /* allocate memory for the internal state */ state = (struct stv0297_state*) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL); - if (state == NULL) goto error; + if (state == NULL) + goto error; /* setup the state */ state->config = config; @@ -724,7 +734,8 @@ struct dvb_frontend* stv0297_attach(cons state->pwm = pwm; /* 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 */ state->frontend.ops = &state->ops; @@ -732,7 +743,8 @@ struct dvb_frontend* stv0297_attach(cons return &state->frontend; error: - if (state) kfree(state); + if (state) + kfree(state); return NULL; } @@ -747,10 +759,7 @@ static struct dvb_frontend_ops stv0297_o .symbol_rate_min = 870000, .symbol_rate_max = 11700000, .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO | - FE_CAN_RECOVER - }, + FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO}, .release = stv0297_release, diff -puN drivers/media/dvb/frontends/tda1004x.c~dvb-frontend-update drivers/media/dvb/frontends/tda1004x.c --- 25/drivers/media/dvb/frontends/tda1004x.c~dvb-frontend-update Fri Dec 10 15:14:18 2004 +++ 25-akpm/drivers/media/dvb/frontends/tda1004x.c Fri Dec 10 15:14:18 2004 @@ -393,6 +393,11 @@ static int tda10046_fwupload(struct dvb_ int ret; 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 */ if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0; @@ -404,11 +409,6 @@ static int tda10046_fwupload(struct dvb_ 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 */ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); @@ -533,6 +533,8 @@ static int tda10045_init(struct dvb_fron tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e); + tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk); + state->initialised = 1; return 0; } @@ -585,6 +587,8 @@ static int tda10046_init(struct dvb_fron tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select 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; return 0; } @@ -616,12 +620,13 @@ static int tda1004x_set_fe(struct dvb_fr if (state->demod_type == TDA1004X_DEMOD_TDA10046) tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4); - // Hardcoded to use auto as much as possible - // The TDA10045 is very unreliable if AUTO mode is _not_ used. I have not - // yet tested the TDA10046 to see if this issue has been fixed + // Hardcoded to use auto as much as possible on the TDA10045 as it + // is very unreliable if AUTO mode is _not_ used. + if (state->demod_type == TDA1004X_DEMOD_TDA10045) { fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + } // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || @@ -1170,6 +1175,7 @@ static struct dvb_frontend_ops tda10045_ .set_frontend = tda1004x_set_fe, .get_frontend = tda1004x_get_fe, + .get_tune_settings = tda1004x_get_tune_settings, .read_status = tda1004x_read_status, .read_ber = tda1004x_read_ber, diff -puN drivers/media/dvb/frontends/tda1004x.h~dvb-frontend-update drivers/media/dvb/frontends/tda1004x.h --- 25/drivers/media/dvb/frontends/tda1004x.h~dvb-frontend-update Fri Dec 10 15:14:18 2004 +++ 25-akpm/drivers/media/dvb/frontends/tda1004x.h Fri Dec 10 15:14:18 2004 @@ -34,6 +34,9 @@ struct tda1004x_config /* does the "inversion" need inverted? */ u8 invert:1; + /* Does the OCLK signal need inverted? */ + u8 invert_oclk:1; + /* PLL maintenance */ int (*pll_init)(struct dvb_frontend* fe); int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); _