--- v4l-dvb/linux/drivers/media/dvb/frontends/tda80xx.c 2006-06-30 19:59:10.000000000 +0400 +++ mp-bc1/linux/drivers/media/dvb/frontends/tda80xx.c 2006-07-23 11:41:07.000000000 +0400 @@ -157,10 +157,10 @@ static __inline__ int tda80xx_writereg(s return tda80xx_write(state, reg, &data, 1); } -static int tda80xx_set_parameters(struct tda80xx_state* state, - fe_spectral_inversion_t inversion, - u32 symbol_rate, - fe_code_rate_t fec_inner) +static int tda80xx_set_parameters_compat(struct tda80xx_state* state, + fe_spectral_inversion_t inversion, + u32 symbol_rate, + fe_code_rate_t fec_inner) { u8 buf[15]; u64 ratio; @@ -287,6 +287,166 @@ static int tda80xx_set_parameters(struct return tda80xx_write(state, 0x01, buf, sizeof(buf)); } +static int tda80xx_set_parameters(struct tda80xx_state* state, + fe_spectral_inversion_t inversion, + u32 symbol_rate, + enum dvbfe_fec fec) +{ + u8 buf[15]; + u64 ratio; + u32 clk; + u32 k; + u32 sr = symbol_rate; + u32 gcd; + u8 scd; + + if (symbol_rate > (state->clk * 3) / 16) + scd = 0; + else if (symbol_rate > (state->clk * 3) / 32) + scd = 1; + else if (symbol_rate > (state->clk * 3) / 64) + scd = 2; + else + scd = 3; + + clk = scd ? (state->clk / (scd * 2)) : state->clk; + + /* + * Viterbi decoder: + * Differential decoding off + * Spectral inversion unknown + * QPSK modulation + */ + if (inversion == INVERSION_ON) + buf[0] = 0x60; + else if (inversion == INVERSION_OFF) + buf[0] = 0x20; + else + buf[0] = 0x00; + + /* + * CLK ratio: + * system clock frequency is up to 64 or 96 MHz + * + * formula: + * r = k * clk / symbol_rate + * + * k: 2^21 for caa 0..3, + * 2^20 for caa 4..5, + * 2^19 for caa 6..7 + */ + if (symbol_rate <= (clk * 3) / 32) + k = (1 << 19); + else if (symbol_rate <= (clk * 3) / 16) + k = (1 << 20); + else + k = (1 << 21); + + gcd = tda80xx_gcd(clk, sr); + clk /= gcd; + sr /= gcd; + + gcd = tda80xx_gcd(k, sr); + k /= gcd; + sr /= gcd; + + ratio = (u64)k * (u64)clk; + do_div(ratio, sr); + + buf[1] = ratio >> 16; + buf[2] = ratio >> 8; + buf[3] = ratio; + + /* nyquist filter roll-off factor 35% */ + buf[4] = 0x20; + + clk = scd ? (state->clk / (scd * 2)) : state->clk; + + /* Anti Alias Filter */ + if (symbol_rate < (clk * 3) / 64) + printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate); + else if (symbol_rate <= clk / 16) + buf[4] |= 0x07; + else if (symbol_rate <= (clk * 3) / 32) + buf[4] |= 0x06; + else if (symbol_rate <= clk / 8) + buf[4] |= 0x05; + else if (symbol_rate <= (clk * 3) / 16) + buf[4] |= 0x04; + else if (symbol_rate <= clk / 4) + buf[4] |= 0x03; + else if (symbol_rate <= (clk * 3) / 8) + buf[4] |= 0x02; + else if (symbol_rate <= clk / 2) + buf[4] |= 0x01; + else + buf[4] |= 0x00; + + /* Sigma Delta converter */ + buf[5] = 0x00; + + /* FEC: Possible puncturing rates */ + if (fec == DVBFE_FEC_NONE) + buf[6] = 0x00; + else if ((fec >= DVBFE_FEC_1_2) && (fec_inner <= FEC_8_9)) + buf[6] = (1 << (8 - fec_inner)); + else if (fec_inner == FEC_AUTO) + buf[6] = 0xff; + else + return -EINVAL; + + switch (fec) { + case DVBFE_FEC_NONE: + buf[6] = 0x00; + break; + case DVBFE_FEC_1_2: + buf[6] = 1 << 7; + break; + case DVBFE_FEC_2_3: + buf[6] = 1 << 6; + break; + case DVBFE_FEC_3_4: + buf[6] = 1 << 5; + break; + case DVBFE_FEC_4_5: + buf[6] = 1 << 4; + break; + case DVBFE_FEC_5_6: + buf[6] = 1 << 3; + break; + case DVBFE_FEC_6_7: + buf[6] = 1 << 2; + break; + case DVBFE_FEC_7_8: + buf[6] = 1 << 1; + break; + case DVBFE_FEC_8_9: + buf[6] = 1 << 0; + break; + } + + /* carrier lock detector threshold value */ + buf[7] = 0x30; + /* AFC1: proportional part settings */ + buf[8] = 0x42; + /* AFC1: integral part settings */ + buf[9] = 0x98; + /* PD: Leaky integrator SCPC mode */ + buf[10] = 0x28; + /* AFC2, AFC1 controls */ + buf[11] = 0x30; + /* PD: proportional part settings */ + buf[12] = 0x42; + /* PD: integral part settings */ + buf[13] = 0x99; + /* AGC */ + buf[14] = 0x50 | scd; + + printk("symbol_rate=%u clk=%u\n", symbol_rate, clk); + + return tda80xx_write(state, 0x01, buf, sizeof (buf)); +} + static int tda80xx_set_clk(struct tda80xx_state* state) { u8 buf[2]; @@ -521,12 +681,32 @@ static int tda80xx_set_frontend(struct d { struct tda80xx_state* state = fe->demodulator_priv; + if (fe->ops.tuner_ops.set_params_compat) { + fe->ops.tuner_ops.set_params_compat(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + tda80xx_set_parameters_compat(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); + tda80xx_set_clk(state); + //tda80xx_set_scpc_freq_offset(state); + state->afc_loop = 1; + + return 0; +} + +static int tda80xx_set_params(struct dvb_frontend* fe, + struct dvbfe_params *p) +{ + struct tda80xx_state* state = fe->demodulator_priv; + if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); } - tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); + tda80xx_set_parameters(state, p->inversion, p->delsys.dvbs.symbol_rate, p->delsys.dvbs.fec); tda80xx_set_clk(state); //tda80xx_set_scpc_freq_offset(state); state->afc_loop = 1; @@ -696,6 +876,37 @@ error: return NULL; } +static struct dvbfe_info dvbs_info = { + .name = "Philips TDA80xx DVB-S", + .delivery = DVBFE_DELSYS_DVBS, + .delsys = { + .dvbs.modulation = DVBFE_MOD_QPSK, + .dvbs.fec = DVBFE_FEC_1_2 | DVBFE_FEC_2_3 | + DVBFE_FEC_3_4 | DVBFE_FEC_5_6 | + DVBFE_FEC_7_8 | DVBFE_FEC_AUTO + }, + + .frequency_min = 950000, + .frequency_max = 2700000, + .frequency_step = 125, + .symbol_rate_min = 4500000, + .symbol_rate_max = 45000000, +}; + +static int tda80xx_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info) +{ + memcpy(fe_info, &dvbs_info, sizeof (dvbs_info)); + + return 0; +} + +static int tda80xx_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys) +{ + *fe_delsys = DVBFE_DELSYS_DVBS; + + return 0; +} + static struct dvb_frontend_ops tda80xx_ops = { .info = { @@ -733,6 +944,11 @@ static struct dvb_frontend_ops tda80xx_o .diseqc_send_burst = tda80xx_send_diseqc_burst, .set_tone = tda80xx_set_tone, .set_voltage = tda80xx_set_voltage, + + .set_params = tda80xx_set_params, + .get_params = tda80xx_get_params, + .get_info = tda80xx_get_info, + .get_delsys = tda80xx_get_delsys, }; module_param(debug, int, 0644);
_______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb