📄 tda1004x.c
字号:
struct fwinfo* fwInfo = NULL; unsigned long timeout; // DSP parameters switch(tda_state->fe_type) { case FE_TYPE_TDA10045H: dspCodeCounterReg = TDA10045H_FWPAGE; dspCodeInReg = TDA10045H_CODE_IN; dspVersion = 0x2c; fwInfoCount = tda10045h_fwinfo_count; fwInfo = tda10045h_fwinfo; break; case FE_TYPE_TDA10046H: dspCodeCounterReg = TDA10046H_CODE_CPT; dspCodeInReg = TDA10046H_CODE_IN; dspVersion = 0x20; fwInfoCount = tda10046h_fwinfo_count; fwInfo = tda10046h_fwinfo; break; } // Load the firmware set_fs(get_ds()); fd = open(tda1004x_firmware, 0, 0); if (fd < 0) { printk("%s: Unable to open firmware %s\n", __FUNCTION__, tda1004x_firmware); return -EIO; } filesize = lseek(fd, 0L, 2); if (filesize <= 0) { printk("%s: Firmware %s is empty\n", __FUNCTION__, tda1004x_firmware); sys_close(fd); return -EIO; } // find extraction parameters for firmware for (fwinfo_idx = 0; fwinfo_idx < fwInfoCount; fwinfo_idx++) { if (fwInfo[fwinfo_idx].file_size == filesize) break; } if (fwinfo_idx >= fwInfoCount) { printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware); sys_close(fd); return -EIO; } fw_size = fwInfo[fwinfo_idx].fw_size; fw_offset = fwInfo[fwinfo_idx].fw_offset; // allocate buffer for it firmware = vmalloc(fw_size); if (firmware == NULL) { printk("%s: Out of memory loading firmware\n", __FUNCTION__); sys_close(fd); return -EIO; } // read it! lseek(fd, fw_offset, 0); if (read(fd, firmware, fw_size) != fw_size) { printk("%s: Failed to read firmware\n", __FUNCTION__); vfree(firmware); sys_close(fd); return -EIO; } sys_close(fd); set_fs(fs); // set some valid bandwith parameters before uploading switch(tda_state->fe_type) { case FE_TYPE_TDA10045H: // reset chip tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); dvb_delay(10); // set parameters tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); break; case FE_TYPE_TDA10046H: // reset chip tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0); dvb_delay(10); // set parameters tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST break; } // do the firmware upload tda1004x_write_byte(i2c, tda_state, dspCodeCounterReg, 0); // clear code counter fw_msg.addr = tda_state->tda1004x_address; fw_pos = 0; while (fw_pos != fw_size) { // work out how much to send this time tx_size = fw_size - fw_pos; if (tx_size > 0x10) { tx_size = 0x10; } // send the chunk fw_buf[0] = dspCodeInReg; memcpy(fw_buf + 1, firmware + fw_pos, tx_size); fw_msg.len = tx_size + 1; if (i2c->xfer(i2c, &fw_msg, 1) != 1) { printk("tda1004x: Error during firmware upload\n"); vfree(firmware); return -EIO; } fw_pos += tx_size; dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos); } vfree(firmware); // wait for DSP to initialise switch(tda_state->fe_type) { case FE_TYPE_TDA10045H: // DSPREADY doesn't seem to work on the TDA10045H dvb_delay(100); break; case FE_TYPE_TDA10046H: timeout = jiffies + HZ; while(!(tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD) & 0x20)) { if (time_after(jiffies, timeout)) { printk("tda1004x: DSP failed to initialised.\n"); return -EIO; } dvb_delay(1); } break; } // check upload was OK tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP 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) != dspVersion)) { printk("%s: firmware upload failed!\n", __FUNCTION__); return -EIO; } // success return 0;}static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state){ struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; dprintk("%s\n", __FUNCTION__); // Disable the MC44BC374C tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = MC44BC374_ADDRESS; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { i2c->xfer(i2c, &tuner_msg, 1); } tda1004x_disable_tuner_i2c(i2c, tda_state); // tda setup tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); // no frequency inversion tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); // done return 0;}static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state){ struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; dprintk("%s\n", __FUNCTION__); // Disable the MC44BC374C tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = MC44BC374_ADDRESS; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { i2c->xfer(i2c, &tuner_msg, 1); } tda1004x_disable_tuner_i2c(i2c, tda_state); // tda setup tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0x40); // TT TDA10046H needs inversion ON tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); // PLL M = 10 tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_CONF, 0); // AGC setup tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MIN, 0); // } tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MIN, 0); // } tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MAX, 0xff); // } tda1004x_write_mask(i2c, tda_state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config tda1004x_write_mask(i2c, tda_state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN tda1004x_write_byte(i2c, tda_state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup tda1004x_write_byte(i2c, tda_state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config tda1004x_write_mask(i2c, tda_state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select tda10046h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz // 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 = 0; u8 band, cp, filter; int counter, counter2; dprintk("%s\n", __FUNCTION__); // setup the frequency buffer switch (tda_state->tuner_type) { case TUNER_TYPE_TD1344: // setup tuner buffer // ((Fif+((1000000/6)/2)) + Finput)/(1000000/6) 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 TUNER_TYPE_TD1316: // 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -