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

📄 tda1004x.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 4 页
字号:
        *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;        int reg = 0;        dprintk("%s\n", __FUNCTION__);        // determine the register to use        switch(tda_state->fe_type) {        case FE_TYPE_TDA10045H:                reg = TDA10045H_S_AGC;                break;        case FE_TYPE_TDA10046H:                reg = TDA10046H_AGC_IF_LEVEL;                break;        }        // read it        tmp = tda1004x_read_byte(i2c, tda_state, reg);        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->fe_type) {                case FE_TYPE_TDA10045H:                        memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info));                        break;                case FE_TYPE_TDA10046H:                        memcpy(arg, &tda10046h_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                switch(tda_state->fe_type) {                case FE_TYPE_TDA10045H:                        status = tda10045h_init(i2c, tda_state);                        break;                case FE_TYPE_TDA10046H:                        status = tda10046h_init(i2c, tda_state);                        break;                }                if (status == 0)                        tda_state->initialised = 1;                return status;        default:                return -EOPNOTSUPP;        }        return 0;}static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data){        int tda1004x_address = -1;        int tuner_address = -1;        int fe_type = -1;        int tuner_type = -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 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };        static u8 td1316_init_tda10046h[] = { 0x0b, 0xf5, 0x80, 0xab };        int status;        dprintk("%s\n", __FUNCTION__);        // probe for tda10045h        if (tda1004x_address == -1) {                tda_state.tda1004x_address = 0x08;                if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) {                        tda1004x_address = 0x08;                        fe_type = FE_TYPE_TDA10045H;                        printk("tda1004x: Detected Philips TDA10045H.\n");                }        }        // probe for tda10046h        if (tda1004x_address == -1) {                tda_state.tda1004x_address = 0x08;                if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x46) {                        tda1004x_address = 0x08;                        fe_type = FE_TYPE_TDA10046H;                        printk("tda1004x: Detected Philips TDA10046H.\n");                }        }        // did we find a frontend?        if (tda1004x_address == -1) {                return -ENODEV;        }        // enable access to the tuner        tda1004x_enable_tuner_i2c(i2c, &tda_state);        // check for a TD1344 first        if (tuner_address == -1) {                tuner_msg.addr = 0x61;                tuner_msg.buf = td1344_init;                tuner_msg.len = sizeof(td1344_init);                if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {                        dvb_delay(1);                        tuner_address = 0x61;                        tuner_type = TUNER_TYPE_TD1344;                        printk("tda1004x: Detected Philips TD1344 tuner.\n");                }        }        // OK, try a TD1316 on address 0x63        if (tuner_address == -1) {                tuner_msg.addr = 0x63;                tuner_msg.buf = td1316_init;                tuner_msg.len = sizeof(td1316_init);                if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {                        dvb_delay(1);                        tuner_address = 0x63;                        tuner_type = TUNER_TYPE_TD1316;                        printk("tda1004x: Detected Philips TD1316 tuner.\n");                }        }        // OK, TD1316 again, on address 0x60 (TDA10046H)        if (tuner_address == -1) {                tuner_msg.addr = 0x60;                tuner_msg.buf = td1316_init_tda10046h;                tuner_msg.len = sizeof(td1316_init_tda10046h);                if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {                        dvb_delay(1);                        tuner_address = 0x60;                        tuner_type = TUNER_TYPE_TD1316;                        printk("tda1004x: Detected Philips TD1316 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.fe_type = fe_type;        tda_state.tuner_address = tuner_address;        tda_state.tuner_type = tuner_type;        tda_state.initialised = 0;        // upload firmware        if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status;        // register        switch(tda_state.fe_type) {        case FE_TYPE_TDA10045H:                return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info);        case FE_TYPE_TDA10046H:                return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10046h_info);        }        // should not get here        return -EINVAL;}staticvoid tda1004x_detach(struct dvb_i2c_bus *i2c, void *data){        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 & TDA10046H 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 + -