📄 tda1004x.c
字号:
// Initialise the DSP and check upload was OK tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67); if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) || (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != 0x2c)) { printk("%s: firmware upload failed!\n", __FUNCTION__); return -EIO; } // tda setup tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1E, 0); tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1F, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // done return 0;}static int tda1004x_encode_fec(int fec){ // convert known FEC values switch (fec) { case FEC_1_2: return 0; case FEC_2_3: return 1; case FEC_3_4: return 2; case FEC_5_6: return 3; case FEC_7_8: return 4; } // unsupported return -EINVAL;}static int tda1004x_decode_fec(int tdafec){ // convert known FEC values switch (tdafec) { case 0: return FEC_1_2; case 1: return FEC_2_3; case 2: return FEC_3_4; case 3: return FEC_5_6; case 4: return FEC_7_8; } // unsupported return -1;}static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, struct dvb_frontend_parameters *fe_params){ u8 tuner_buf[4]; struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; int tuner_frequency; u8 band, cp, filter; int counter, counter2; dprintk("%s\n", __FUNCTION__); // setup the frequency buffer switch (tda_state->tuner_address) { case TD1344_ADDRESS: // setup tuner buffer tuner_frequency = (((fe_params->frequency / 1000) * 6) + 217502) / 1000; tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0x88; if (fe_params->frequency < 550000000) { tuner_buf[3] = 0xab; } else { tuner_buf[3] = 0xeb; } // tune it tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = tda_state->tuner_address; tuner_msg.len = 4; i2c->xfer(i2c, &tuner_msg, 1); // wait for it to finish tuner_msg.len = 1; tuner_msg.flags = I2C_M_RD; counter = 0; counter2 = 0; while (counter++ < 100) { if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { if (tuner_buf[0] & 0x40) { counter2++; } else { counter2 = 0; } } if (counter2 > 10) { break; } } tda1004x_disable_tuner_i2c(i2c, tda_state); break; case TDM1316L_ADDRESS: // determine charge pump tuner_frequency = fe_params->frequency + 36130000; if (tuner_frequency < 87000000) { return -EINVAL; } else if (tuner_frequency < 130000000) { cp = 3; } else if (tuner_frequency < 160000000) { cp = 5; } else if (tuner_frequency < 200000000) { cp = 6; } else if (tuner_frequency < 290000000) { cp = 3; } else if (tuner_frequency < 420000000) { cp = 5; } else if (tuner_frequency < 480000000) { cp = 6; } else if (tuner_frequency < 620000000) { cp = 3; } else if (tuner_frequency < 830000000) { cp = 5; } else if (tuner_frequency < 895000000) { cp = 7; } else { return -EINVAL; } // determine band if (fe_params->frequency < 49000000) { return -EINVAL; } else if (fe_params->frequency < 159000000) { band = 1; } else if (fe_params->frequency < 444000000) { band = 2; } else if (fe_params->frequency < 861000000) { band = 4; } else { return -EINVAL; } // work out filter switch (fe_params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: // 6 MHz isn't supported directly, but set this to // the 8 MHz setting in case we can fiddle it later filter = 1; break; case BANDWIDTH_7_MHZ: filter = 0; break; case BANDWIDTH_8_MHZ: filter = 1; break; default: return -EINVAL; } // calculate tuner parameters tuner_frequency = (((fe_params->frequency / 1000) * 6) + 217280) / 1000; tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; // tune it tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = tda_state->tuner_address; tuner_msg.len = 4; if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { return -EIO; } dvb_delay(1); tda1004x_disable_tuner_i2c(i2c, tda_state); break; default: return -EINVAL; } dprintk("%s: success\n", __FUNCTION__); // done return 0;}static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, struct dvb_frontend_parameters *fe_params){ int tmp; dprintk("%s\n", __FUNCTION__); // set frequency tmp = tda1004x_set_frequency(i2c, tda_state, fe_params); if (tmp < 0) return tmp; // hardcoded to use auto as much as possible fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || (fe_params->u.ofdm.constellation == QAM_AUTO) || (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1); // enable auto tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits } else { tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0); // disable auto // set HP FEC tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP); if (tmp < 0) return tmp; tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp); // set LP FEC if (fe_params->u.ofdm.code_rate_LP != FEC_NONE) { tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); if (tmp < 0) return tmp; tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3); } // set constellation switch (fe_params->u.ofdm.constellation) { case QPSK: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0); break; case QAM_16: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1); break; case QAM_64: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2); break; default: return -EINVAL; } // set hierarchy switch (fe_params->u.ofdm.hierarchy_information) { case HIERARCHY_NONE: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5); break; case HIERARCHY_1: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5); break; case HIERARCHY_2: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5); break; case HIERARCHY_4: tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5); break; default: return -EINVAL; } } // set bandwidth switch(tda_state->tda1004x_address) { case TDA10045H_ADDRESS: tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); break; } // set inversion switch (fe_params->inversion) { case INVERSION_OFF: tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); break; case INVERSION_ON: tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20); break; default: return -EINVAL; } // set guard interval switch (fe_params->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_32: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; case GUARD_INTERVAL_1_16: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); break; case GUARD_INTERVAL_1_8: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); break; case GUARD_INTERVAL_1_4: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); break; case GUARD_INTERVAL_AUTO: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; default: return -EINVAL; } // set transmission mode switch (fe_params->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4); break; case TRANSMISSION_MODE_8K: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4); break; case TRANSMISSION_MODE_AUTO: tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4); tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0); break; default: return -EINVAL; } // reset DSP tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); dvb_delay(10); // done return 0;}static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params){ dprintk("%s\n", __FUNCTION__); // inversion status fe_params->inversion = INVERSION_OFF; if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) { fe_params->inversion = INVERSION_ON; } // bandwidth switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_WREF_LSB)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -