--- v4l-dvb/linux/drivers/media/dvb/frontends/l64781.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/l64781.c 2006-07-23 11:38:39.000000000 +0400 @@ -140,9 +140,10 @@ static int apply_frontend_param (struct u8 val0x06; int bw = p->bandwidth - BANDWIDTH_8_MHZ; - if (fe->ops.tuner_ops.set_params) { - fe->ops.tuner_ops.set_params(fe, param); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } if (param->inversion != INVERSION_ON && @@ -234,6 +235,217 @@ static int apply_frontend_param (struct return 0; } +static int l64781_set_params(struct dvb_frontend *fe, + struct dvbfe_params *param) +{ + struct l64781_state *state = fe->demodulator_priv; + /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */ + /* QPSK, QAM_16, QAM_64 */ + static const u8 bw_tab[] = { 8, 7, 6 }; /* 8Mhz, 7MHz, 6MHz */ + /* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */ + static const u32 ppm = 8000; + struct dvbt_params *p = ¶m->delsys.dvbt; + u32 ddfs_offset_fixed; +/* u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */ +/* bw_tab[p->bandWidth]<<10)/15625; */ + u32 init_freq; + u32 spi_bias; + u8 val0x04 = 0; + u8 val0x05 = 0; + u8 val0x06 = 0; + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + ddfs_offset_fixed = 0x4000-(ppm<<16)/bw_tab[p->bandwidth]/1000000; + + /* This works up to 20000 ppm, it overflows if too large ppm! */ + init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) / + bw_tab[p->bandwidth] & 0xFFFFFF); + + /* SPI bias calculation is slightly modified to fit in 32bit */ + /* will work for high ppm only... */ + spi_bias = 378 * (1 << 10); + spi_bias *= 16; + + switch (p->bandwidth) { + case DVBFE_BANDWIDTH_8_MHZ: + spi_bias *= 8; + break; + case DVBFE_BANDWIDTH_7_MHZ: + spi_bias *= 7; + break; + case DVBFE_BANDWIDTH_6_MHZ: + spi_bias *= 6; + break; + default: + return -EINVAL; + } + + switch (p->hierarchy) { + case DVBFE_HIERARCHY_OFF: + val0x06 = 0; + break; + case DVBFE_HIERARCHY_ON: + switch (p->alpha) { + case DVBFE_ALPHA_1: + val0x06 = 1 << 2; + break; + case DVBFE_ALPHA_2: + val0x06 = 2 << 2; + break; + case DVBFE_ALPHA_4: + val0x06 = 4 << 2; + break; + } + break; + case DVBFE_HIERARCHY_AUTO: + default: + break; + } + + switch (p->constellation) { + case DVBFE_MOD_QPSK: + spi_bias *= 2; + val0x06 |= 0; + break; + case DVBFE_MOD_QAM16: + spi_bias *= 4; + val0x06 |= 1; + break; + case DVBFE_MOD_QAM64: + spi_bias *= 6; + val0x06 |= 3; + break; + default: + return -EINVAL; + } + + switch (p->code_rate_HP) { + case DVBFE_FEC_NONE: + spi_bias = 0; + val0x05 = 7; + break; + case DVBFE_FEC_1_2: + spi_bias /= 2; + spi_bias *= 1; + val0x05 = 0; + break; + case DVBFE_FEC_2_3: + spi_bias /= 3; + spi_bias *= 2; + val0x05 = 1; + break; + case DVBFE_FEC_3_4: + spi_bias /= 4; + spi_bias *= 3; + val0x05 = 2; + break; + case DVBFE_FEC_5_6: + spi_bias /= 6; + spi_bias *= 5; + val0x05 = 3; + break; + case DVBFE_FEC_7_8: + spi_bias /= 8; + spi_bias *= 7; + val0x05 = 4; + break; + default: + return -EINVAL; + } + + switch (p->transmission_mode) { + case DVBFE_TRANSMISSION_MODE_2K: + val0x04 = 0; + break; + case DVBFE_TRANSMISSION_MODE_8K: + val0x04 = 1 << 2; + break; + case DVBFE_TRANSMISSION_MODE_AUTO: + val0x04 = 2 << 2; + break; + default: + break; + } + + switch (p->guard_interval) { + case DVBFE_GUARD_INTERVAL_1_32: + spi_bias /= 33; + val0x04 |= 0; + break; + case DVBFE_GUARD_INTERVAL_1_16: + spi_bias /= 34; + val0x04 |= 1; + break; + case DVBFE_GUARD_INTERVAL_1_8: + spi_bias /= 36; + val0x04 |= 2; + break; + case DVBFE_GUARD_INTERVAL_1_4: + spi_bias /= 40; + val0x04 |= 3; + break; + default: + return -EINVAL; + } + spi_bias *= 1000ULL; + spi_bias /= 1000ULL + ppm/1000; + + switch (p->code_rate_LP) { + case DVBFE_FEC_1_2: + val0x05 |= 0; + break; + case DVBFE_FEC_2_3: + val0x05 |= 1 << 3; + break; + case DVBFE_FEC_3_4: + val0x05 |= 2 << 3; + break; + case DVBFE_FEC_5_6: + val0x05 |= 4 << 3; + break; + case DVBFE_FEC_7_8: + val0x05 |= 6 << 3; + break; + default: + return -EINVAL; + } + + l64781_writereg(state, 0x04, val0x04); + l64781_writereg(state, 0x05, val0x05); + l64781_writereg(state, 0x06, val0x06); + + reset_afc(state); + + /* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */ + if (p->transmission_mode & DVBFE_TRANSMISSION_MODE_2K) + l64781_writereg (state, 0x15, 1); + else + l64781_writereg (state, 0x15, 3); + + l64781_writereg(state, 0x16, init_freq & 0xff); + l64781_writereg(state, 0x17, (init_freq >> 8) & 0xff); + l64781_writereg(state, 0x18, (init_freq >> 16) & 0xff); + + l64781_writereg(state, 0x1b, spi_bias & 0xff); + l64781_writereg(state, 0x1c, (spi_bias >> 8) & 0xff); + l64781_writereg(state, 0x1d, ((spi_bias >> 16) & 0x7f) | + (param->inversion == INVERSION_ON ? 0x80 : 0x00)); + + l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff); + l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f); + + l64781_readreg (state, 0x00); /* clear interrupt registers... */ + l64781_readreg (state, 0x01); /* dto. */ + + apply_tps (state); + + return 0; +} + static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* param) { struct l64781_state* state = fe->demodulator_priv; @@ -352,6 +564,125 @@ static int get_frontend(struct dvb_front return 0; } +static int l64781_get_params(struct dvb_frontend *fe, + struct dvbfe_params *param) +{ + struct l64781_state *state = fe->demodulator_priv; + int tmp; + + tmp = l64781_readreg(state, 0x04); + switch (tmp & 3) { + case 0: + param->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_32; + break; + case 1: + param->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_16; + break; + case 2: + param->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_8; + break; + case 3: + param->delsys.dvbt.guard_interval = DVBFE_GUARD_INTERVAL_1_4; + break; + } + switch ((tmp >> 2) & 3) { + case 0: + param->delsys.dvbt.transmission_mode = DVBFE_TRANSMISSION_MODE_2K; + break; + case 1: + param->delsys.dvbt.transmission_mode = DVBFE_TRANSMISSION_MODE_8K; + break; + default: + printk("Unexpected value for transmission_mode\n"); + } + + tmp = l64781_readreg(state, 0x05); + switch (tmp & 7) { + case 0: + param->delsys.dvbt.code_rate_HP = DVBFE_FEC_1_2; + break; + case 1: + param->delsys.dvbt.code_rate_HP = DVBFE_FEC_2_3; + break; + case 2: + param->delsys.dvbt.code_rate_HP = DVBFE_FEC_3_4; + break; + case 3: + param->delsys.dvbt.code_rate_HP = DVBFE_FEC_5_6; + break; + case 4: + param->delsys.dvbt.code_rate_HP = DVBFE_FEC_7_8; + break; + default: + printk("Unexpected value for code_rate_HP\n"); + } + switch ((tmp >> 3) & 7) { + case 0: + param->delsys.dvbt.code_rate_LP = DVBFE_FEC_1_2; + break; + case 1: + param->delsys.dvbt.code_rate_LP = DVBFE_FEC_2_3; + break; + case 2: + param->delsys.dvbt.code_rate_LP = DVBFE_FEC_3_4; + break; + case 3: + param->delsys.dvbt.code_rate_LP = DVBFE_FEC_5_6; + break; + case 4: + param->delsys.dvbt.code_rate_LP = DVBFE_FEC_7_8; + break; + default: + printk("Unexpected value for code_rate_LP\n"); + } + + + tmp = l64781_readreg(state, 0x06); + switch (tmp & 3) { + case 0: + param->delsys.dvbt.constellation = DVBFE_MOD_QPSK; + break; + case 1: + param->delsys.dvbt.constellation = DVBFE_MOD_QAM16; + break; + case 2: + param->delsys.dvbt.constellation = DVBFE_MOD_QAM64; + break; + default: + printk("Unexpected value for constellation\n"); + } + switch ((tmp >> 2) & 7) { + case 0: + param->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_OFF; + break; + case 1: + param->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + param->delsys.dvbt.alpha = DVBFE_ALPHA_1; + break; + case 2: + param->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + param->delsys.dvbt.alpha = DVBFE_ALPHA_2; + break; + case 3: + param->delsys.dvbt.hierarchy = DVBFE_HIERARCHY_ON; + param->delsys.dvbt.alpha = DVBFE_ALPHA_4; + break; + default: + printk("Unexpected value for hierarchy\n"); + } + + + tmp = l64781_readreg (state, 0x1d); + param->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF; + + tmp = (int) (l64781_readreg (state, 0x08) | + (l64781_readreg (state, 0x09) << 8) | + (l64781_readreg (state, 0x0a) << 16)); + param->frequency += tmp; + + return 0; +} + static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct l64781_state* state = fe->demodulator_priv; @@ -564,6 +895,32 @@ error: return NULL; } +static struct dvbfe_info dvbt_info = { + .name = "LSI L64781 DVB-T", + .delivery = DVBFE_DELSYS_DVBT, + .delsys = { + .dvbt.modulation = DVBFE_MOD_OFDM, + .dvbt.stream_priority = DVBFE_STREAM_PRIORITY_HP | + DVBFE_STREAM_PRIORITY_LP, + }, + + .frequency_step = 166666, +}; + +static int l64781_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbt_info, sizeof (dvbt_info)); + + return 0; +} + +static int l64781_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBT; + + return 0; +} + static struct dvb_frontend_ops l64781_ops = { .info = { @@ -594,6 +951,11 @@ static struct dvb_frontend_ops l64781_op .read_signal_strength = l64781_read_signal_strength, .read_snr = l64781_read_snr, .read_ucblocks = l64781_read_ucblocks, + + .set_params = l64781_set_params, + .get_params = l64781_get_params, + .get_info = l64781_get_info, + .get_delsys = l64781_get_delsys, }; MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver");
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb