📄 tda10086.c
字号:
case FEC_6_7: fecval = 0x05; break; case FEC_7_8: fecval = 0x06; break; case FEC_8_9: fecval = 0x07; break; case FEC_AUTO: fecval = 0x08; break; default: return -1; } tda10086_write_byte(state, 0x0d, fecval); return 0;}static int tda10086_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params){ struct tda10086_state *state = fe->demodulator_priv; int ret; u32 freq = 0; int freqoff; dprintk ("%s\n", __FUNCTION__); // modify parameters for tuning tda10086_write_byte(state, 0x02, 0x35); state->has_lock = false; // set params if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, fe_params); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); if (fe->ops.tuner_ops.get_frequency) fe->ops.tuner_ops.get_frequency(fe, &freq); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } // calcluate the frequency offset (in *Hz* not kHz) freqoff = fe_params->frequency - freq; freqoff = ((1<<16) * freqoff) / (SACLK/1000); tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f)); tda10086_write_byte(state, 0x3e, freqoff); if ((ret = tda10086_set_inversion(state, fe_params)) < 0) return ret; if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0) return ret; if ((ret = tda10086_set_fec(state, fe_params)) < 0) return ret; // soft reset + disable TS output until lock tda10086_write_mask(state, 0x10, 0x40, 0x40); tda10086_write_mask(state, 0x00, 0x01, 0x00); state->symbol_rate = fe_params->u.qpsk.symbol_rate; state->frequency = fe_params->frequency; return 0;}static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params){ struct tda10086_state* state = fe->demodulator_priv; u8 val; int tmp; u64 tmp64; dprintk ("%s\n", __FUNCTION__); // check for invalid symbol rate if (fe_params->u.qpsk.symbol_rate < 500000) return -EINVAL; // calculate the updated frequency (note: we convert from Hz->kHz) tmp64 = tda10086_read_byte(state, 0x52); tmp64 |= (tda10086_read_byte(state, 0x51) << 8); if (tmp64 & 0x8000) tmp64 |= 0xffffffffffff0000ULL; tmp64 = (tmp64 * (SACLK/1000ULL)); do_div(tmp64, (1ULL<<15) * (1ULL<<1)); fe_params->frequency = (int) state->frequency + (int) tmp64; // the inversion val = tda10086_read_byte(state, 0x0c); if (val & 0x80) { switch(val & 0x40) { case 0x00: fe_params->inversion = INVERSION_OFF; if (state->config->invert) fe_params->inversion = INVERSION_ON; break; default: fe_params->inversion = INVERSION_ON; if (state->config->invert) fe_params->inversion = INVERSION_OFF; break; } } else { tda10086_read_byte(state, 0x0f); switch(val & 0x02) { case 0x00: fe_params->inversion = INVERSION_OFF; if (state->config->invert) fe_params->inversion = INVERSION_ON; break; default: fe_params->inversion = INVERSION_ON; if (state->config->invert) fe_params->inversion = INVERSION_OFF; break; } } // calculate the updated symbol rate tmp = tda10086_read_byte(state, 0x1d); if (tmp & 0x80) tmp |= 0xffffff00; tmp = (tmp * 480 * (1<<1)) / 128; tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000); fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp; // the FEC val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4; switch(val) { case 0x00: fe_params->u.qpsk.fec_inner = FEC_1_2; break; case 0x01: fe_params->u.qpsk.fec_inner = FEC_2_3; break; case 0x02: fe_params->u.qpsk.fec_inner = FEC_3_4; break; case 0x03: fe_params->u.qpsk.fec_inner = FEC_4_5; break; case 0x04: fe_params->u.qpsk.fec_inner = FEC_5_6; break; case 0x05: fe_params->u.qpsk.fec_inner = FEC_6_7; break; case 0x06: fe_params->u.qpsk.fec_inner = FEC_7_8; break; case 0x07: fe_params->u.qpsk.fec_inner = FEC_8_9; break; } return 0;}static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status){ struct tda10086_state* state = fe->demodulator_priv; u8 val; dprintk ("%s\n", __FUNCTION__); val = tda10086_read_byte(state, 0x0e); *fe_status = 0; if (val & 0x01) *fe_status |= FE_HAS_SIGNAL; if (val & 0x02) *fe_status |= FE_HAS_CARRIER; if (val & 0x04) *fe_status |= FE_HAS_VITERBI; if (val & 0x08) *fe_status |= FE_HAS_SYNC; if (val & 0x10) { *fe_status |= FE_HAS_LOCK; if (!state->has_lock) { state->has_lock = true; // modify parameters for stable reception tda10086_write_byte(state, 0x02, 0x00); } } return 0;}static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal){ struct tda10086_state* state = fe->demodulator_priv; u8 _str; dprintk ("%s\n", __FUNCTION__); _str = 0xff - tda10086_read_byte(state, 0x43); *signal = (_str << 8) | _str; return 0;}static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr){ struct tda10086_state* state = fe->demodulator_priv; u8 _snr; dprintk ("%s\n", __FUNCTION__); _snr = 0xff - tda10086_read_byte(state, 0x1c); *snr = (_snr << 8) | _snr; return 0;}static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){ struct tda10086_state* state = fe->demodulator_priv; dprintk ("%s\n", __FUNCTION__); // read it *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f; // reset counter tda10086_write_byte(state, 0x18, 0x00); tda10086_write_byte(state, 0x18, 0x80); return 0;}static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber){ struct tda10086_state* state = fe->demodulator_priv; dprintk ("%s\n", __FUNCTION__); // read it *ber = 0; *ber |= tda10086_read_byte(state, 0x15); *ber |= tda10086_read_byte(state, 0x16) << 8; *ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16; return 0;}static int tda10086_sleep(struct dvb_frontend* fe){ struct tda10086_state* state = fe->demodulator_priv; dprintk ("%s\n", __FUNCTION__); tda10086_write_mask(state, 0x00, 0x08, 0x08); return 0;}static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable){ struct tda10086_state* state = fe->demodulator_priv; dprintk ("%s\n", __FUNCTION__); if (enable) { tda10086_write_mask(state, 0x00, 0x10, 0x10); } else { tda10086_write_mask(state, 0x00, 0x10, 0x00); } return 0;}static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings){ if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { fesettings->min_delay_ms = 50; fesettings->step_size = 2000; fesettings->max_drift = 8000; } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) { fesettings->min_delay_ms = 100; fesettings->step_size = 1500; fesettings->max_drift = 9000; } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) { fesettings->min_delay_ms = 100; fesettings->step_size = 1000; fesettings->max_drift = 8000; } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) { fesettings->min_delay_ms = 100; fesettings->step_size = 500; fesettings->max_drift = 7000; } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) { fesettings->min_delay_ms = 200; fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); fesettings->max_drift = 14 * fesettings->step_size; } else { fesettings->min_delay_ms = 200; fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); fesettings->max_drift = 18 * fesettings->step_size; } return 0;}static void tda10086_release(struct dvb_frontend* fe){ struct tda10086_state *state = fe->demodulator_priv; tda10086_sleep(fe); kfree(state);}static struct dvb_frontend_ops tda10086_ops = { .info = { .name = "Philips TDA10086 DVB-S", .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 125, /* kHz for QPSK frontends */ .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK }, .release = tda10086_release, .init = tda10086_init, .sleep = tda10086_sleep, .i2c_gate_ctrl = tda10086_i2c_gate_ctrl, .set_frontend = tda10086_set_frontend, .get_frontend = tda10086_get_frontend, .get_tune_settings = tda10086_get_tune_settings, .read_status = tda10086_read_status, .read_ber = tda10086_read_ber, .read_signal_strength = tda10086_read_signal_strength, .read_snr = tda10086_read_snr, .read_ucblocks = tda10086_read_ucblocks, .diseqc_send_master_cmd = tda10086_send_master_cmd, .diseqc_send_burst = tda10086_send_burst, .set_tone = tda10086_set_tone,};struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, struct i2c_adapter* i2c){ struct tda10086_state *state; dprintk ("%s\n", __FUNCTION__); /* allocate memory for the internal state */ state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL); if (!state) return NULL; /* setup the state */ state->config = config; state->i2c = i2c; /* check if the demod is there */ if (tda10086_read_byte(state, 0x1e) != 0xe1) { kfree(state); return NULL; } /* create dvb_frontend */ memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend;}module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");MODULE_AUTHOR("Andrew de Quincey");MODULE_LICENSE("GPL");EXPORT_SYMBOL(tda10086_attach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -