diff options
Diffstat (limited to 'linux/drivers/media/dvb/frontends/stv0297.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/stv0297.c | 1185 |
1 files changed, 598 insertions, 587 deletions
diff --git a/linux/drivers/media/dvb/frontends/stv0297.c b/linux/drivers/media/dvb/frontends/stv0297.c index 4a2ed985c..eb0cd6254 100644 --- a/linux/drivers/media/dvb/frontends/stv0297.c +++ b/linux/drivers/media/dvb/frontends/stv0297.c @@ -30,18 +30,16 @@ struct stv0297_state { - struct i2c_adapter* i2c; + struct i2c_adapter *i2c; - struct dvb_frontend_ops ops; + struct dvb_frontend_ops ops; - const struct stv0297_config* config; + const struct stv0297_config *config; - struct dvb_frontend frontend; - - int freq_off; + struct dvb_frontend frontend; + int freq_off; unsigned long base_freq; - u8 pwm; }; @@ -51,333 +49,307 @@ struct stv0297_state { #define dprintk(x...) #endif -#define STV0297_CLOCK 28900 - -static u8 init_tab [] = { - 0x00, 0x09, - 0x01, 0x69, - 0x03, 0x00, - 0x04, 0x00, - 0x07, 0x00, - 0x08, 0x00, - 0x20, 0x00, - 0x21, 0x40, - 0x22, 0x00, - 0x23, 0x00, - 0x24, 0x40, - 0x25, 0x88, - 0x30, 0xff, - 0x31, 0x00, - 0x32, 0xff, - 0x33, 0x00, - 0x34, 0x50, - 0x35, 0x7f, - 0x36, 0x00, - 0x37, 0x20, - 0x38, 0x00, - 0x40, 0x1c, - 0x41, 0xff, - 0x42, 0x29, - 0x43, 0x00,// check - 0x44, 0xff, - 0x45, 0x00, - 0x46, 0x00, - 0x49, 0x04, - 0x4a, 0xff, - 0x4b, 0x7f, - 0x52, 0x30, - 0x55, 0xae, - 0x56, 0x47, - 0x57, 0xe1, - 0x58, 0x3a, - 0x5a, 0x1e, - 0x5b, 0x34, - 0x60, 0x00, - 0x63, 0x00, - 0x64, 0x00, - 0x65, 0x00, - 0x66, 0x00, - 0x67, 0x00, - 0x68, 0x00, - 0x69, 0x00, - 0x6a, 0x02, - 0x6b, 0x00, - 0x70, 0xff, - 0x71, 0x00, - 0x72, 0x00, - 0x73, 0x00, - 0x74, 0x0c, - 0x80, 0x00, - 0x81, 0x00, - 0x82, 0x00, - 0x83, 0x00, - 0x84, 0x04, - 0x85, 0x80, - 0x86, 0x24, - 0x87, 0x78, - 0x88, 0x00, - 0x89, 0x00, - 0x90, 0x01, - 0x91, 0x01, - 0xa0, 0x00, - 0xa1, 0x00, - 0xa2, 0x00, - 0xb0, 0x91, - 0xb1, 0x0b, - 0xc0, 0x53, - 0xc1, 0x70, - 0xc2, 0x12, - 0xd0, 0x00, - 0xd1, 0x00, - 0xd2, 0x00, - 0xd3, 0x00, - 0xd4, 0x00, - 0xd5, 0x00, - 0xde, 0x00, - 0xdf, 0x00, - 0x61, 0x49, - 0x62, 0x0b, - 0x53, 0x08, - 0x59, 0x08, +#define STV0297_CLOCK_KHZ 28900 + +static u8 init_tab[] = { + 0x00, 0x09, + 0x01, 0x69, + 0x03, 0x00, + 0x04, 0x00, + 0x07, 0x00, + 0x08, 0x00, + 0x20, 0x00, + 0x21, 0x40, + 0x22, 0x00, + 0x23, 0x00, + 0x24, 0x40, + 0x25, 0x88, + 0x30, 0xff, + 0x31, 0x00, + 0x32, 0xff, + 0x33, 0x00, + 0x34, 0x50, + 0x35, 0x7f, + 0x36, 0x00, + 0x37, 0x20, + 0x38, 0x00, + 0x40, 0x1c, + 0x41, 0xff, + 0x42, 0x29, + 0x43, 0x00, + 0x44, 0xff, + 0x45, 0x00, + 0x46, 0x00, + 0x49, 0x04, + 0x4a, 0xff, + 0x4b, 0x7f, + 0x52, 0x30, + 0x55, 0xae, + 0x56, 0x47, + 0x57, 0xe1, + 0x58, 0x3a, + 0x5a, 0x1e, + 0x5b, 0x34, + 0x60, 0x00, + 0x63, 0x00, + 0x64, 0x00, + 0x65, 0x00, + 0x66, 0x00, + 0x67, 0x00, + 0x68, 0x00, + 0x69, 0x00, + 0x6a, 0x02, + 0x6b, 0x00, + 0x70, 0xff, + 0x71, 0x00, + 0x72, 0x00, + 0x73, 0x00, + 0x74, 0x0c, + 0x80, 0x00, + 0x81, 0x00, + 0x82, 0x00, + 0x83, 0x00, + 0x84, 0x04, + 0x85, 0x80, + 0x86, 0x24, + 0x87, 0x78, + 0x88, 0x00, + 0x89, 0x00, + 0x90, 0x01, + 0x91, 0x01, + 0xa0, 0x00, + 0xa1, 0x00, + 0xa2, 0x00, + 0xb0, 0x91, + 0xb1, 0x0b, + 0xc0, 0x53, + 0xc1, 0x70, + 0xc2, 0x12, + 0xd0, 0x00, + 0xd1, 0x00, + 0xd2, 0x00, + 0xd3, 0x00, + 0xd4, 0x00, + 0xd5, 0x00, + 0xde, 0x00, + 0xdf, 0x00, + 0x61, 0x49, + 0x62, 0x0b, + 0x53, 0x08, + 0x59, 0x08, }; -static int stv0297_writereg (struct stv0297_state* state, u8 reg, u8 data) +static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data) { - int ret; - u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 }; - ret = i2c_transfer (state->i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); - if (ret != 1) - dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " - "ret == %i)\n", __FUNCTION__, reg, data, ret); + if (ret != 1) + dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " + "ret == %i)\n", __FUNCTION__, reg, data, ret); - return (ret != 1) ? -1 : 0; + return (ret != 1) ? -1 : 0; } -static int stv0297_readreg (struct stv0297_state* state, u8 reg) +static int stv0297_readreg(struct stv0297_state *state, u8 reg) { - int ret; - u8 b0[] = { reg }; - u8 b1[] = { 0 }; - struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - - // 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); - 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); - return -1; - } - - return b1[0]; + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = + 1}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} + }; + + // 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); + 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); + return -1; + } + + return b1[0]; } -static int stv0297_writereg_mask (struct stv0297_state* state, u8 reg, u8 mask, u8 data) +static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data) { - int val; + int val; - val = stv0297_readreg(state, reg); - val &= ~mask; - val |= (data & mask); - stv0297_writereg(state, reg, val); + val = stv0297_readreg(state, reg); + val &= ~mask; + val |= (data & mask); + stv0297_writereg(state, reg, val); - return 0; + return 0; } -static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len) +static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len) { - int ret; - struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®1, .len = 1 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } }; - - // 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); - 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); - return -1; - } - - return 0; + int ret; + struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = + ®1,.len = 1}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len} + }; + + // 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); + 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); + 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; - - tmp = srate; - tmp <<= 32; - do_div(tmp, STV0297_CLOCK); + long tmp; - 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)); + tmp = 131072L * srate; /* 131072 = 2^17 */ + tmp = tmp / (STV0297_CLOCK_KHZ / 4); /* 1/4 = 2^-2 */ + tmp = tmp * 8192L; /* 8192 = 2^13 */ - return 0; + 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)); } -static u32 stv0297_get_symbolrate (struct stv0297_state* state) +static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate) { - 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) -{ - s64 tmp; - u32 symrate; - - symrate = stv0297_get_symbolrate(state); - - // cannot use shifts - it is signed - tmp = fshift * (1<<28); - do_div(tmp, symrate); - - // adjust - if (tmp >= 0) { - tmp += 500000; - } else { - tmp -= 500000; - } - do_div(tmp, 1000000); - - stv0297_writereg(state, 0x60, tmp & 0xFF); - stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0); - - return; + long tmp; + + tmp = (long) fshift *262144L; /* 262144 = 2*18 */ + tmp /= symrate; + tmp *= 1024; /* 1024 = 2*10 */ + + // adjust + if (tmp >= 0) { + tmp += 500000; + } else { + tmp -= 500000; + } + tmp /= 1000000; + + stv0297_writereg(state, 0x60, tmp & 0xFF); + stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0); } -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; - - // 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); - - return; + long tmp; + + /* 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) +static long stv0297_get_carrieroffset(struct stv0297_state *state) { - s32 raw; - s64 tmp; - u32 symbol_rate; + s32 raw; + long tmp; - 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, 0x67) << 8); + raw |= (stv0297_readreg(state, 0x68) << 16); + raw |= (stv0297_readreg(state, 0x69) & 0x0F) << 24; - raw = stv0297_readreg(state,0x66); - raw |= (stv0297_readreg(state,0x67) << 8); - raw |= (stv0297_readreg(state,0x68) << 16); - raw |= (stv0297_readreg(state,0x69) & 0x0F) << 24; + tmp = raw; + tmp /= 26844L; - // cannot just use a shift here 'cos it is signed - tmp = raw; - tmp *= symbol_rate; - 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 < 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) +static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation) { - int val = 0; + int val = 0; - switch(modulation) { - case QAM_16: - val = 0; - break; + switch (modulation) { + case QAM_16: + val = 0; + break; - case QAM_32: - val = 1; - break; + case QAM_32: + val = 1; + break; - case QAM_64: - val = 4; - break; + case QAM_64: + val = 4; + break; - case QAM_128: - val = 2; - break; + case QAM_128: + val = 2; + break; - case QAM_256: - val = 3; - break; + case QAM_256: + val = 3; + break; - default: - return -EINVAL; - } + default: + return -EINVAL; + } - stv0297_writereg_mask(state, 0x00, 0x70, val << 4); + stv0297_writereg_mask(state, 0x00, 0x70, val << 4); - return 0; + return 0; } -static int stv0297_set_inversion(struct stv0297_state* state, fe_spectral_inversion_t inversion) +static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion) { - int val = 0; + int val = 0; - switch(inversion) { - case INVERSION_OFF: - val = 0; - break; + switch (inversion) { + case INVERSION_OFF: + val = 0; + break; - case INVERSION_ON: - val = 1; - break; + case INVERSION_ON: + val = 1; + break; - default: - return -EINVAL; - } + default: + return -EINVAL; + } - stv0297_writereg_mask(state, 0x83, 0x08, val << 3); + stv0297_writereg_mask(state, 0x83, 0x08, val << 3); - return 0; + return 0; } @@ -392,378 +364,417 @@ static int stv0297_set_inversion(struct stv0297_state* state, fe_spectral_invers -int stv0297_enable_plli2c(struct dvb_frontend* fe) +int stv0297_enable_plli2c(struct dvb_frontend *fe) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; - stv0297_writereg(state, 0x87, 0x78); - stv0297_writereg(state, 0x86, 0xc8); + stv0297_writereg(state, 0x87, 0x78); + stv0297_writereg(state, 0x86, 0xc8); - return 0; + return 0; } -static int stv0297_init (struct dvb_frontend* fe) +static int stv0297_init(struct dvb_frontend *fe) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - int i; - - stv0297_writereg_mask(state, 0x80, 1, 1); - stv0297_writereg_mask(state, 0x80, 1, 0); - stv0297_writereg_mask(state, 0x81, 1, 1); - stv0297_writereg_mask(state, 0x81, 1, 0); - - for (i=0; i<sizeof(init_tab); i+=2) { - stv0297_writereg (state, init_tab[i], init_tab[i+1]); - } - - stv0297_set_symbolrate(state, 6900); - stv0297_writereg_mask(state, 0x88, 0x10, 0x10); - stv0297_writereg_mask(state, 0xA0, 0x80, 0x00); - stv0297_writereg_mask(state, 0xA0, 0x10, 0x00); - stv0297_writereg_mask(state, 0xA0, 0x08, 0x00); - stv0297_writereg_mask(state, 0xA0, 0x07, 0x04); - stv0297_writereg(state, 0x4a, 0x00); - stv0297_writereg(state, 0x4b, state->pwm); - msleep(200); - - if (state->config->pll_init) state->config->pll_init(fe); - - return 0; + 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; i < sizeof(init_tab); i += 2) { + stv0297_writereg(state, init_tab[i], init_tab[i + 1]); + } + + /* set a dummy symbol rate */ + stv0297_set_symbolrate(state, 6900); + + /* invert AGC1 polarity */ + stv0297_writereg_mask(state, 0x88, 0x10, 0x10); + + /* setup bit error counting */ + stv0297_writereg_mask(state, 0xA0, 0x80, 0x00); + stv0297_writereg_mask(state, 0xA0, 0x10, 0x00); + stv0297_writereg_mask(state, 0xA0, 0x08, 0x00); + stv0297_writereg_mask(state, 0xA0, 0x07, 0x04); + + /* min + max PWM */ + stv0297_writereg(state, 0x4a, 0x00); + stv0297_writereg(state, 0x4b, state->pwm); + msleep(200); + + if (state->config->pll_init) + state->config->pll_init(fe); + + return 0; } -static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; - u8 sync = stv0297_readreg (state, 0xDF); + u8 sync = stv0297_readreg(state, 0xDF); - *status = 0; - if (sync & 0x80) - *status |= FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; - return 0; + *status = 0; + if (sync & 0x80) + *status |= + FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; + return 0; } -static int stv0297_read_ber(struct dvb_frontend* fe, u32* ber) +static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - u8 BER[3]; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + u8 BER[3]; - stv0297_writereg (state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes - mdelay(25); // Hopefully got 4096 Bytes - stv0297_readregs (state, 0xA0, BER, 3); - mdelay(25); - *ber = (BER[2] << 8 | BER[1]) / ( 8 * 4096); + stv0297_writereg(state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes + mdelay(25); // Hopefully got 4096 Bytes + stv0297_readregs(state, 0xA0, BER, 3); + mdelay(25); + *ber = (BER[2] << 8 | BER[1]) / (8 * 4096); - return 0; + return 0; } -static int stv0297_read_signal_strength(struct dvb_frontend* fe, u16* strength) +static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - u8 STRENGTH[2]; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + u8 STRENGTH[2]; - stv0297_readregs (state, 0x41, STRENGTH, 2); - *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0]; + stv0297_readregs(state, 0x41, STRENGTH, 2); + *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0]; - return 0; + return 0; } -static int stv0297_read_snr(struct dvb_frontend* fe, u16* snr) +static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - u8 SNR[2]; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + u8 SNR[2]; - stv0297_readregs (state, 0x07, SNR, 2); - *snr = SNR[1] << 8 | SNR[0]; + stv0297_readregs(state, 0x07, SNR, 2); + *snr = SNR[1] << 8 | SNR[0]; - return 0; + return 0; } -static int stv0297_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; - *ucblocks = (stv0297_readreg (state, 0xD5) << 8) - | stv0297_readreg (state, 0xD4); + *ucblocks = (stv0297_readreg(state, 0xD5) << 8) + | stv0297_readreg(state, 0xD4); - return 0; + return 0; } -static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) +static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - int u_threshold; - int initial_u; - int blind_u; - int delay; - int locked; - int sweeprate; - int carrieroffset; - unsigned long starttime; - unsigned long timeout; - - switch(p->u.qam.modulation) { - case QAM_16: - case QAM_32: - case QAM_64: - delay = 100; - sweeprate = 1500; - break; - - case QAM_128: - delay = 150; - sweeprate = 1000; - break; - - case QAM_256: - delay = 200; - sweeprate = 500; - break; - - default: - return -EINVAL; - } - - // determine inversion dependant parameters - carrieroffset = -330; - switch(p->inversion) { - case INVERSION_OFF: - break; - - case INVERSION_ON: - sweeprate = -sweeprate; - carrieroffset = -carrieroffset; - break; - - default: - return -EINVAL; - } - - state->config->pll_set(fe, p); - - // reset everything - stv0297_writereg_mask(state, 0x82, 0x4, 0x4); - stv0297_set_initialdemodfreq(state, state->freq_off + 7250); - stv0297_writereg_mask(state, 0x43, 0x10, 0x00); - stv0297_writereg(state, 0x41, 0x00); - stv0297_writereg_mask(state, 0x42, 0x03, 0x01); - stv0297_writereg_mask(state, 0x36, 0x60, 0x00); - stv0297_writereg_mask(state, 0x36, 0x18, 0x00); - stv0297_writereg_mask(state, 0x71, 0x80, 0x80); - stv0297_writereg(state, 0x72, 0x00); - stv0297_writereg(state, 0x73, 0x00); - stv0297_writereg_mask(state, 0x74, 0x0F, 0x00); - stv0297_writereg_mask(state, 0x43, 0x08, 0x00); - stv0297_writereg_mask(state, 0x71, 0x80, 0x00); - 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); - stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); - 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); - u_threshold = stv0297_readreg(state, 0x00) & 0xf; - initial_u = stv0297_readreg(state, 0x01) >> 4; - blind_u = stv0297_readreg(state, 0x01) & 0xf; - stv0297_writereg_mask(state, 0x84, 0x01, 0x01); - stv0297_writereg_mask(state, 0x84, 0x01, 0x00); - 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); - stv0297_writereg_mask(state, 0x87, 0x80, 0x00); - stv0297_writereg(state, 0x63, 0x00); - stv0297_writereg(state, 0x64, 0x00); - stv0297_writereg(state, 0x65, 0x00); - stv0297_writereg(state, 0x66, 0x00); - stv0297_writereg(state, 0x67, 0x00); - stv0297_writereg(state, 0x68, 0x00); - stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); - - // 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_carrieroffset(state, carrieroffset); - stv0297_set_inversion(state, p->inversion); - - // kick off lock - stv0297_writereg_mask(state, 0x88, 0x08, 0x08); - stv0297_writereg_mask(state, 0x5a, 0x20, 0x00); - stv0297_writereg_mask(state, 0x6a, 0x01, 0x01); - stv0297_writereg_mask(state, 0x43, 0x40, 0x40); - stv0297_writereg_mask(state, 0x5b, 0x30, 0x00); - stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c); - stv0297_writereg_mask(state, 0x03, 0x03, 0x03); - stv0297_writereg_mask(state, 0x43, 0x10, 0x10); - - // 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 (time_after(jiffies, timeout)) { - goto timeout; - } - msleep(20); - - // wait for equaliser partial convergence - locked = 0; - timeout = jiffies + (50*HZ)/1000; - while(time_before(jiffies, timeout)) { - msleep(10); - - if (stv0297_readreg(state, 0x82) & 0x04) { - locked = 1; - } - } - if (time_after(jiffies, timeout) && (!locked)) { - goto timeout; - } - - // wait for equaliser full convergence - timeout = jiffies + (delay*HZ)/1000; - while(time_before(jiffies, timeout)) { - msleep(10); - - if (stv0297_readreg(state, 0x82) & 0x08) { - break; - } - } - if (time_after(jiffies, timeout)) { - goto timeout; - } - - // disable sweep - stv0297_writereg_mask(state, 0x6a, 1, 0); - stv0297_writereg_mask(state, 0x88, 8, 0); - - // wait for main lock - timeout = jiffies + (20*HZ)/1000; - while(time_before(jiffies, timeout)) { - msleep(10); - - if (stv0297_readreg(state, 0xDF) & 0x80) { - break; - } - } - if (time_after(jiffies, timeout)) { - goto timeout; - } - msleep(100); - - // is it still locked after that delay? - if (!(stv0297_readreg(state, 0xDF) & 0x80)) { - goto timeout; - } - - // success!! - stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); - state->freq_off = stv0297_get_carrieroffset(state); - state->base_freq = p->frequency; - return 0; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + int u_threshold; + int initial_u; + int blind_u; + int delay; + int sweeprate; + int carrieroffset; + unsigned long starttime; + unsigned long timeout; + + switch (p->u.qam.modulation) { + case QAM_16: + case QAM_32: + case QAM_64: + delay = 100; + sweeprate = 1500; + break; + + case QAM_128: + delay = 150; + sweeprate = 1000; + break; + + case QAM_256: + delay = 200; + sweeprate = 500; + break; + + default: + return -EINVAL; + } + + // determine inversion dependant parameters + carrieroffset = -330; + switch (p->inversion) { + case INVERSION_OFF: + break; + + case INVERSION_ON: + sweeprate = -sweeprate; + carrieroffset = -carrieroffset; + break; + + default: + return -EINVAL; + } + + state->config->pll_set(fe, p); + + /* 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); + stv0297_writereg_mask(state, 0x36, 0x60, 0x00); + stv0297_writereg_mask(state, 0x36, 0x18, 0x00); + stv0297_writereg_mask(state, 0x71, 0x80, 0x80); + stv0297_writereg(state, 0x72, 0x00); + stv0297_writereg(state, 0x73, 0x00); + 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; + stv0297_writereg_mask(state, 0x84, 0x01, 0x01); + stv0297_writereg_mask(state, 0x84, 0x01, 0x00); + 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); + stv0297_writereg(state, 0x66, 0x00); + stv0297_writereg(state, 0x67, 0x00); + stv0297_writereg(state, 0x68, 0x00); + stv0297_writereg_mask(state, 0x69, 0x0f, 0x00); + + /* 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, p->u.qam.symbol_rate / 1000); + stv0297_set_carrieroffset(state, carrieroffset); + stv0297_set_inversion(state, p->inversion); + + /* kick off lock */ + stv0297_writereg_mask(state, 0x88, 0x08, 0x08); + stv0297_writereg_mask(state, 0x5a, 0x20, 0x00); + stv0297_writereg_mask(state, 0x6a, 0x01, 0x01); + stv0297_writereg_mask(state, 0x43, 0x40, 0x40); + stv0297_writereg_mask(state, 0x5b, 0x30, 0x00); + stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c); + stv0297_writereg_mask(state, 0x03, 0x03, 0x03); + stv0297_writereg_mask(state, 0x43, 0x10, 0x10); + + /* 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 (time_after(jiffies, timeout)) { + goto timeout; + } + msleep(20); + + /* wait for equaliser partial convergence */ + timeout = jiffies + (50 * HZ) / 1000; + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0x82) & 0x04) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + + /* wait for equaliser full convergence */ + timeout = jiffies + (delay * HZ) / 1000; + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0x82) & 0x08) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + + /* disable sweep */ + stv0297_writereg_mask(state, 0x6a, 1, 0); + stv0297_writereg_mask(state, 0x88, 8, 0); + + /* wait for main lock */ + timeout = jiffies + (20 * HZ) / 1000; + while (time_before(jiffies, timeout)) { + msleep(10); + + if (stv0297_readreg(state, 0xDF) & 0x80) { + break; + } + } + if (time_after(jiffies, timeout)) { + goto timeout; + } + msleep(100); + + /* is it still locked after that delay? */ + if (!(stv0297_readreg(state, 0xDF) & 0x80)) { + goto timeout; + } + + /* success!! */ + stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); + state->freq_off = stv0297_get_carrieroffset(state); + state->base_freq = p->frequency; + return 0; timeout: - stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); - return 0; + stv0297_writereg_mask(state, 0x6a, 0x01, 0x00); + return 0; } -static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) +static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - int reg_00, reg_83; - - reg_00 = stv0297_readreg(state, 0x00); - reg_83 = stv0297_readreg(state, 0x83); - - 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.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; - } - - return 0; + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + int reg_00, reg_83; + + reg_00 = stv0297_readreg(state, 0x00); + reg_83 = stv0297_readreg(state, 0x83); + + p->frequency = state->base_freq + state->freq_off; + p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF; + 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; + } + + return 0; } -static void stv0297_release(struct dvb_frontend* fe) +static void stv0297_release(struct dvb_frontend *fe) { - struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; - kfree(state); + struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv; + kfree(state); } static struct dvb_frontend_ops stv0297_ops; -struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, - struct i2c_adapter* i2c, - int pwm) +struct dvb_frontend *stv0297_attach(const struct stv0297_config *config, + 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; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); - state->freq_off = 0; - state->base_freq = 0; - state->pwm = pwm; - - /* check if the demod is there */ - if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20) goto error; - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; + 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; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); + state->freq_off = 0; + state->base_freq = 0; + state->pwm = pwm; + + /* check if the demod is there */ + if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20) + goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; error: - if (state) kfree(state); - return NULL; + if (state) + kfree(state); + return NULL; } static struct dvb_frontend_ops stv0297_ops = { - .info = { - .name = "ST STV0297 DVB-C", - .type = FE_QAM, - .frequency_min = 64000000, - .frequency_max = 1300000000, - .frequency_stepsize = 62500, - .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 - }, - - .release = stv0297_release, - - .init = stv0297_init, - - .set_frontend = stv0297_set_frontend, - .get_frontend = stv0297_get_frontend, - - .read_status = stv0297_read_status, - .read_ber = stv0297_read_ber, - .read_signal_strength = stv0297_read_signal_strength, - .read_snr = stv0297_read_snr, - .read_ucblocks = stv0297_read_ucblocks, + .info = { + .name = "ST STV0297 DVB-C", + .type = FE_QAM, + .frequency_min = 64000000, + .frequency_max = 1300000000, + .frequency_stepsize = 62500, + .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}, + + .release = stv0297_release, + + .init = stv0297_init, + + .set_frontend = stv0297_set_frontend, + .get_frontend = stv0297_get_frontend, + + .read_status = stv0297_read_status, + .read_ber = stv0297_read_ber, + .read_signal_strength = stv0297_read_signal_strength, + .read_snr = stv0297_read_snr, + .read_ucblocks = stv0297_read_ucblocks, }; MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver"); |