⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tda1004x.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -