📄 tda1004x.c
字号:
case 0x14: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; case 0xdb: fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; break; case 0x4f: fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; break; } // FEC fe_params->u.ofdm.code_rate_HP = tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7); fe_params->u.ofdm.code_rate_LP = tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7); // constellation switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) { case 0: fe_params->u.ofdm.constellation = QPSK; break; case 1: fe_params->u.ofdm.constellation = QAM_16; break; case 2: fe_params->u.ofdm.constellation = QAM_64; break; } // transmission mode fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) { fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; } // guard interval switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { case 0: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; case 1: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; case 2: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; case 3: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; } // hierarchy switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { case 0: fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; break; case 1: fe_params->u.ofdm.hierarchy_information = HIERARCHY_1; break; case 2: fe_params->u.ofdm.hierarchy_information = HIERARCHY_2; break; case 3: fe_params->u.ofdm.hierarchy_information = HIERARCHY_4; break; } // done return 0;}static int tda1004x_read_status(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status){ int status; int cber; int vber; dprintk("%s\n", __FUNCTION__); // read status status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD); if (status == -1) { return -EIO; } // decode *fe_status = 0; if (status & 4) *fe_status |= FE_HAS_SIGNAL; if (status & 2) *fe_status |= FE_HAS_CARRIER; if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi // is getting anything valid if (!(*fe_status & FE_HAS_VITERBI)) { // read the CBER cber = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); if (cber == -1) return -EIO; status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); if (status == -1) return -EIO; cber |= (status << 8); tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); if (cber != 65535) { *fe_status |= FE_HAS_VITERBI; } } // if we DO have some valid VITERBI output, but don't already have SYNC // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { // read the VBER vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB); if (vber == -1) return -EIO; status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID); if (status == -1) return -EIO; vber |= (status << 8); status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB); if (status == -1) return -EIO; vber |= ((status << 16) & 0x0f); tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT); // if RS has passed some valid TS packets, then we must be // getting some SYNC bytes if (vber < 16632) { *fe_status |= FE_HAS_SYNC; } } // success dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status); return 0;}static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal){ int tmp; dprintk("%s\n", __FUNCTION__); // read it tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SIGNAL_STRENGTH); if (tmp < 0) return -EIO; // done *signal = (tmp << 8) | tmp; dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal); return 0;}static int tda1004x_read_snr(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * snr){ int tmp; dprintk("%s\n", __FUNCTION__); // read it tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR); if (tmp < 0) return -EIO; if (tmp) { tmp = 255 - tmp; } // done *snr = ((tmp << 8) | tmp); dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr); return 0;}static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ucblocks){ int tmp; int tmp2; int counter; dprintk("%s\n", __FUNCTION__); // read the UCBLOCKS and reset counter = 0; tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); if (tmp < 0) return -EIO; tmp &= 0x7f; while (counter++ < 5) { tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); if (tmp2 < 0) return -EIO; tmp2 &= 0x7f; if ((tmp2 < tmp) || (tmp2 == 0)) break; } // done if (tmp != 0x7f) { *ucblocks = tmp; } else { *ucblocks = 0xffffffff; } dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks); return 0;}static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ber){ int tmp; dprintk("%s\n", __FUNCTION__); // read it in tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); if (tmp < 0) return -EIO; *ber = tmp << 1; tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); if (tmp < 0) return -EIO; *ber |= (tmp << 9); tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); // done dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); return 0;}static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg){ int status = 0; struct dvb_i2c_bus *i2c = fe->i2c; struct tda1004x_state *tda_state = (struct tda1004x_state *) &(fe->data); dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd); switch (cmd) { case FE_GET_INFO: switch(tda_state->tda1004x_address) { case TDA10045H_ADDRESS: memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); break; } break; case FE_READ_STATUS: return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg); case FE_READ_BER: return tda1004x_read_ber(i2c, tda_state, (u32 *) arg); case FE_READ_SIGNAL_STRENGTH: return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg); case FE_READ_SNR: return tda1004x_read_snr(i2c, tda_state, (u16 *) arg); case FE_READ_UNCORRECTED_BLOCKS: return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg); case FE_SET_FRONTEND: return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); case FE_GET_FRONTEND: return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); case FE_INIT: // don't bother reinitialising if (tda_state->initialised) return 0; // OK, perform initialisation status = tda1004x_init(i2c, tda_state); if (status == 0) tda_state->initialised = 1; return status; default: return -EOPNOTSUPP; } return 0;}static int tda1004x_attach(struct dvb_i2c_bus *i2c){ int tda1004x_address = -1; int tuner_address = -1; struct tda1004x_state tda_state; struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 }; static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; static u8 tdm1316l_init[] = { 0x0b, 0xf5, 0x85, 0xab }; dprintk("%s\n", __FUNCTION__); // probe for frontend tda_state.tda1004x_address = TDA10045H_ADDRESS; if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) { tda1004x_address = TDA10045H_ADDRESS; printk("tda1004x: Detected Philips TDA10045H.\n"); } // did we find a frontend? if (tda1004x_address == -1) { return -ENODEV; } // supported tuner? tda1004x_enable_tuner_i2c(i2c, &tda_state); tuner_msg.addr = TD1344_ADDRESS; tuner_msg.buf = td1344_init; tuner_msg.len = sizeof(td1344_init); if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { dvb_delay(1); tuner_address = TD1344_ADDRESS; printk("tda1004x: Detected Philips TD1344 tuner. PLEASE CHECK THIS AND REPORT BACK!.\n"); } else { tuner_msg.addr = TDM1316L_ADDRESS; tuner_msg.buf = tdm1316l_init; tuner_msg.len = sizeof(tdm1316l_init); if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { dvb_delay(1); tuner_address = TDM1316L_ADDRESS; printk("tda1004x: Detected Philips TDM1316L tuner.\n"); } } tda1004x_disable_tuner_i2c(i2c, &tda_state); // did we find a tuner? if (tuner_address == -1) { printk("tda1004x: Detected, but with unknown tuner.\n"); return -ENODEV; } // create state tda_state.tda1004x_address = tda1004x_address; tda_state.tuner_address = tuner_address; tda_state.initialised = 0; // register switch(tda_state.tda1004x_address) { case TDA10045H_ADDRESS: dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); break; } // success return 0;}staticvoid tda1004x_detach(struct dvb_i2c_bus *i2c){ dprintk("%s\n", __FUNCTION__); dvb_unregister_frontend(tda1004x_ioctl, i2c);}staticint __init init_tda1004x(void){ return dvb_register_i2c_device(THIS_MODULE, tda1004x_attach, tda1004x_detach);}staticvoid __exit exit_tda1004x(void){ dvb_unregister_i2c_device(tda1004x_attach);}module_init(init_tda1004x);module_exit(exit_tda1004x);MODULE_DESCRIPTION("Philips TDA10045H DVB-T Frontend");MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");MODULE_LICENSE("GPL");MODULE_PARM(tda1004x_debug, "i");MODULE_PARM_DESC(tda1004x_debug, "enable verbose debug messages");MODULE_PARM(tda1004x_firmware, "s");MODULE_PARM_DESC(tda1004x_firmware, "Where to find the firmware file");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -