| /* |
| M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage |
| |
| Copyright (C) 2012 Max nibble<nibble.max@gmail.com> |
| Copyright (C) 2011 Montage Technology<www.montage-tech.com> |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| #include <linux/delay.h> |
| #include <linux/errno.h> |
| #include <linux/init.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/string.h> |
| #include <linux/slab.h> |
| #include <asm/div64.h> |
| #include "dvb_frontend.h" |
| #include "m88dc2800.h" |
| |
| struct m88dc2800_state { |
| struct i2c_adapter* i2c; |
| const struct m88dc2800_config *config; |
| struct dvb_frontend frontend; |
| u32 freq; |
| u32 ber; |
| u32 sym; |
| u16 qam; |
| u8 inverted; |
| u32 xtal; |
| /*tuner state*/ |
| u8 tuner_init_OK; /* Tuner initialize status */
|
| u8 tuner_dev_addr; /* Tuner device address */
|
| u32 tuner_freq; /* RF frequency to be set, unit: KHz */
|
| u16 tuner_qam; /* Reserved */ |
| u16 tuner_mode;
|
| u8 tuner_bandwidth; /* Bandwidth of the channel, unit: MHz, 6/7/8 */
|
| u8 tuner_loopthrough; /* Tuner loop through switch, 0/1 */
|
| u32 tuner_crystal; /* Tuner crystal frequency, unit: KHz */
|
| u32 tuner_dac; /* Tuner DAC frequency, unit: KHz */
|
| u16 tuner_mtt; /* Tuner chip version, D1: 0x0d, E0: 0x0e, E1: 0x8e */ |
| u16 tuner_custom_cfg;
|
| u32 tuner_version; /* Tuner driver version number */ |
| u32 tuner_time; |
| }; |
| |
| static int debug; |
| module_param(debug, int, 0644); |
| MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); |
| |
| #define dprintk(args...) \ |
| do { \ |
| if (debug) \ |
| printk(KERN_INFO "m88dc2800: " args); \ |
| } while (0) |
| |
| |
| static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr, u8 *p_data, u8 len) |
| { |
| struct i2c_msg msg = { .flags = 0 }; |
| |
| msg.addr = addr; |
| msg.buf = p_data; |
| msg.len = len; |
| |
| return i2c_transfer(state->i2c, &msg, 1); |
| } |
| |
| static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr, u8 *p_data, u8 len) |
| { |
| struct i2c_msg msg = { .flags = I2C_M_RD }; |
| |
| msg.addr = addr; |
| msg.buf = p_data; |
| msg.len = len; |
| |
| return i2c_transfer(state->i2c, &msg, 1); |
| } |
| |
| /*demod register operations.*/ |
| static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data) |
| { |
| u8 buf[] = { reg, data }; |
| u8 addr = state->config->demod_address; |
| int err; |
| |
| if (debug > 1) |
| printk("m88dc2800: %s: write reg 0x%02x, value 0x%02x\n", |
| __func__, reg, data); |
| |
| err = m88dc2800_i2c_write(state, addr, buf, 2); |
| |
| if (err != 1) { |
| printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," |
| " value == 0x%02x)\n", __func__, err, reg, data); |
| return -EIO; |
| } |
| return 0; |
| } |
| |
| static int ReadReg(struct m88dc2800_state *state, u8 reg) |
| { |
| int ret; |
| u8 b0[] = { reg }; |
| u8 b1[] = { 0 }; |
| u8 addr = state->config->demod_address; |
| |
| ret = m88dc2800_i2c_write(state, addr, b0, 1); |
| |
| if (ret != 1) { |
| printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", |
| __func__, reg, ret); |
| return -EIO; |
| } |
| |
| ret = m88dc2800_i2c_read(state, addr, b1, 1); |
| |
| if (debug > 1) |
| printk(KERN_INFO "m88dc2800: read reg 0x%02x, value 0x%02x\n", |
| reg, b1[0]); |
| return b1[0]; |
| } |
| |
| static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg, u8 data) |
| { |
| int ret; |
| u8 buf[2];
|
| u8 addr = state->tuner_dev_addr; |
| |
| buf[1] = ReadReg(state, 0x86); |
| buf[1] |= 0x80; |
| ret = WriteReg(state, 0x86, buf[1]); |
| |
| buf[0] = reg; |
| buf[1] = data; |
| |
| ret = m88dc2800_i2c_write(state, addr, buf, 2); |
| if(ret != 1) |
| return -EIO; |
| return 0; |
| } |
| |
| static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg, u8 *p_data) |
| { |
| int ret; |
| u8 buf[2];
|
| u8 addr = state->tuner_dev_addr; |
| |
| buf[1] = ReadReg(state, 0x86); |
| buf[1] |= 0x80; |
| ret = WriteReg(state, 0x86, buf[1]); |
| |
| buf[0] = reg; |
| ret = m88dc2800_i2c_write(state, addr, buf, 1); |
| |
| msleep(1); |
| |
| buf[1] = ReadReg(state, 0x86); |
| buf[1] |= 0x80; |
| ret = WriteReg(state, 0x86, buf[1]); |
| |
| return m88dc2800_i2c_read(state, addr, p_data, 1); |
| } |
| |
| /* Tuner operation functions.*/ |
| static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state)
|
| {
|
| u32 freq_KHz = state->tuner_freq;
|
|
|
| if (state->tuner_mtt == 0xD1) { /* D1 */
|
| if (freq_KHz <= 123000) {
|
| if (freq_KHz <= 56000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x00);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x00);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x00);
|
| }else if (freq_KHz <= 64000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x10);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x01);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x08);
|
| }else if (freq_KHz <= 72000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x20);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x02);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x10);
|
| }else if (freq_KHz <= 80000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x30);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x03);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x18);
|
| }else if (freq_KHz <= 88000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x40);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x04);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x20);
|
| }else if (freq_KHz <= 96000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x50);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x05);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x28);
|
| }else if (freq_KHz <= 104000) {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x60);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x06);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x30);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x58, 0x9b);
|
| _mt_fe_tn_set_reg(state, 0x59, 0x70);
|
| _mt_fe_tn_set_reg(state, 0x5d, 0x07);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x38);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x5a, 0x75);
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0c);
|
| } else { /* if (freq_KHz > 112000) */
|
| _mt_fe_tn_set_reg(state, 0x58, 0x7b);
|
| if (freq_KHz <= 304000) {
|
| if (freq_KHz <= 136000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x40);
|
| }else if (freq_KHz <= 160000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x48);
|
| }else if (freq_KHz <= 184000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x50);
|
| }else if (freq_KHz <= 208000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x58);
|
| }else if (freq_KHz <= 232000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x60);
|
| }else if (freq_KHz <= 256000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x68);
|
| }else if (freq_KHz <= 280000) {
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x70);
|
| }else { /*if (freq_KHz <= 304000)*/
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x78);
|
| }
|
| if (freq_KHz <= 171000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x08);
|
| }else if (freq_KHz <= 211000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0a);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0e);
|
| }
|
| }else { /* if (freq_KHz > 304000) */
|
| _mt_fe_tn_set_reg(state, 0x5e, 0x88);
|
| if (freq_KHz <= 400000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0c);
|
| }else if (freq_KHz <= 450000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x09);
|
| }else if (freq_KHz <= 550000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0e);
|
| }else if (freq_KHz <= 650000) {
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0d);
|
| }else { /*if (freq_KHz > 650000) */
|
| _mt_fe_tn_set_reg(state, 0x73, 0x0e);
|
| }
|
| }
|
| }
|
|
|
| if (freq_KHz > 800000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x24);
|
| else if (freq_KHz > 700000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x34);
|
| else if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x44);
|
| else if (freq_KHz > 300000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x43);
|
| else if (freq_KHz > 220000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
| else if (freq_KHz > 110000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x14);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
|
|
| if (freq_KHz > 600000)
|
| _mt_fe_tn_set_reg(state, 0x6a, 0x53);
|
| else if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x6a, 0x57);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x6a, 0x59);
|
|
|
| if (freq_KHz < 200000) {
|
| _mt_fe_tn_set_reg(state, 0x20, 0x5d);
|
| }else if (freq_KHz < 500000) {
|
| _mt_fe_tn_set_reg(state, 0x20, 0x7d);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x20, 0xfd);
|
| }/* end of 0xD1 */
|
| }else if (state->tuner_mtt == 0xE1) { /* E1 */
|
| if (freq_KHz <= 112000) { /* 123MHz */
|
| if (freq_KHz <= 56000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x01);
|
| }else if (freq_KHz <= 64000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x09);
|
| }else if (freq_KHz <= 72000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x11);
|
| }else if (freq_KHz <= 80000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x19);
|
| }else if (freq_KHz <= 88000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x21);
|
| }else if (freq_KHz <= 96000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x29);
|
| }else if (freq_KHz <= 104000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x31);
|
| }else {/* if (freq_KHz <= 112000) */
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x39);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x5b, 0x30);
|
| }else { /* if (freq_KHz > 112000) */
|
| if (freq_KHz <= 304000) {
|
| if (freq_KHz <= 136000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x41);
|
| }else if (freq_KHz <= 160000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x49);
|
| }else if (freq_KHz <= 184000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x51);
|
| }else if (freq_KHz <= 208000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x59);
|
| }else if (freq_KHz <= 232000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x61);
|
| }else if (freq_KHz <= 256000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x69);
|
| }else if (freq_KHz <= 280000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x71);
|
| }else { /*if (freq_KHz <= 304000)*/
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x79);
|
| }
|
|
|
| if (freq_KHz <= 150000) {
|
| _mt_fe_tn_set_reg(state, 0x5b, 0x28);
|
| }else if (freq_KHz <= 256000) {
|
| _mt_fe_tn_set_reg(state, 0x5b, 0x29);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x5b, 0x2a);
|
| }
|
| }else { /* if (freq_KHz > 304000) */
|
| if (freq_KHz <= 400000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x89);
|
| }else if (freq_KHz <= 450000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x91);
|
| }else if (freq_KHz <= 650000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0x98);
|
| }else if (freq_KHz <= 850000) {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0xa0);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x5c, 0xa8);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x5b, 0x08);
|
| }
|
| }
|
| } /* end of 0xE1 */
|
| return 0;
|
| } |
| |
| static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state, u32 freq_KHz, u32 cali_freq_thres_div2, u32 cali_freq_thres_div3r, u32 cali_freq_thres_div3)
|
| {
|
| s32 N, F, MUL;
|
| u8 buf, tmp, tmp2;
|
| s32 M;
|
| const s32 crystal_KHz = state->tuner_crystal;
|
|
|
| if (state->tuner_mtt == 0xD1) {
|
| M = state->tuner_crystal / 4000;
|
| if (freq_KHz > cali_freq_thres_div2) {
|
| MUL = 4;
|
| tmp = 2;
|
| }else if (freq_KHz > 300000) {
|
| MUL = 8;
|
| tmp = 3;
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
|
| MUL = 8;
|
| tmp = 4;
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
|
| MUL = 16;
|
| tmp = 5;
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
|
| MUL = 32;
|
| tmp = 6;
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 16)){
|
| MUL = 64;
|
| tmp = 7;
|
| }else { /* invalid */
|
| MUL = 0;
|
| tmp = 0;
|
| return 1;
|
| }
|
| }else if (state->tuner_mtt == 0xE1) {
|
| M = state->tuner_crystal / 1000;
|
|
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_set_reg(state, 0x32, 0xe0); |
| _mt_fe_tn_set_reg(state, 0x33, 0x86);
|
| _mt_fe_tn_set_reg(state, 0x37, 0x70);
|
| _mt_fe_tn_set_reg(state, 0x38, 0x20);
|
| _mt_fe_tn_set_reg(state, 0x39, 0x18);
|
| _mt_fe_tn_set_reg(state, 0x89, 0x83);
|
|
|
| if (freq_KHz > cali_freq_thres_div2) {
|
| M = M / 4;
|
| MUL = 4;
|
| tmp = 2;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > cali_freq_thres_div3r) {
|
| M = M / 3;
|
| MUL = 6;
|
| tmp = 2;
|
| tmp2 = M + 32; /*32*/
|
| }else if (freq_KHz > cali_freq_thres_div3) {
|
| M = M / 3;
|
| MUL = 6;
|
| tmp = 2;
|
| tmp2 = M; /*16*/
|
| }else if (freq_KHz > 304000) {
|
| M = M / 4;
|
| MUL = 8;
|
| tmp = 3;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
|
| M = M / 4;
|
| MUL = 8;
|
| tmp = 4;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > (cali_freq_thres_div3r / 2)) {
|
| M = M / 3;
|
| MUL = 12;
|
| tmp = 4;
|
| tmp2 = M + 32; /*32*/
|
| }else if (freq_KHz > (cali_freq_thres_div3 / 2)) {
|
| M = M / 3;
|
| MUL = 12;
|
| tmp = 4;
|
| tmp2 = M; /*16*/
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
|
| M = M / 4;
|
| MUL = 16;
|
| tmp = 5;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > (cali_freq_thres_div3r / 4)) {
|
| M = M / 3;
|
| MUL = 24;
|
| tmp = 5;
|
| tmp2 = M + 32; /*32*/
|
| }else if (freq_KHz > (cali_freq_thres_div3 / 4)) {
|
| M = M / 3;
|
| MUL = 24;
|
| tmp = 5;
|
| tmp2 = M; /*16*/
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
|
| M = M / 4;
|
| MUL = 32;
|
| tmp = 6;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > (cali_freq_thres_div3r / 8)) {
|
| M = M / 3;
|
| MUL = 48;
|
| tmp = 6;
|
| tmp2 = M + 32; /*32*/
|
| }else if (freq_KHz > (cali_freq_thres_div3 / 8)) {
|
| M = M / 3;
|
| MUL = 48;
|
| tmp = 6;
|
| tmp2 = M; /*16*/
|
| }else if (freq_KHz > (cali_freq_thres_div2 / 16)) {
|
| M = M / 4;
|
| MUL = 64;
|
| tmp = 7;
|
| tmp2 = M + 16; /*48*/
|
| }else if (freq_KHz > (cali_freq_thres_div3r / 16)) {
|
| M = M / 3;
|
| MUL = 96;
|
| tmp = 7;
|
| tmp2 = M + 32; /*32*/
|
| }else if (freq_KHz > (cali_freq_thres_div3 / 16)) {
|
| M = M / 3;
|
| MUL = 96;
|
| tmp = 7;
|
| tmp2 = M; /*16*/
|
| }else { /* invalid */
|
| M = M / 4;
|
| MUL = 0;
|
| tmp = 0;
|
| tmp2 = 48;
|
| return 1;
|
| }
|
|
|
| if (freq_KHz == 291000) {
|
| M = state->tuner_crystal / 1000 / 3;
|
| MUL = 12;
|
| tmp = 4;
|
| tmp2 = M + 32; /*32*/
|
| } |
| /* |
| if (freq_KHz == 578000) {
|
| M = state->tuner_crystal / 1000 / 4;
|
| MUL = 4;
|
| tmp = 2;
|
| tmp2 = M + 16; //48
|
| } |
| */
|
| if (freq_KHz == 690000) {
|
| M = state->tuner_crystal / 1000 / 3;
|
| MUL = 4;
|
| tmp = 2;
|
| tmp2 = M + 16; /*48*/
|
| }
|
| _mt_fe_tn_get_reg(state, 0x33, &buf);
|
| buf &= 0xc0;
|
| buf += tmp2;
|
| _mt_fe_tn_set_reg(state, 0x33, buf);
|
| }else {
|
| return 1;
|
| }
|
|
|
| _mt_fe_tn_get_reg(state, 0x39, &buf);
|
| buf &= 0xf8;
|
| buf += tmp;
|
| _mt_fe_tn_set_reg(state, 0x39, buf);
|
|
|
| N = (freq_KHz * MUL * M / crystal_KHz) / 2 * 2 - 256;
|
|
|
| buf = (N >> 8) & 0xcf;
|
| if (state->tuner_mtt == 0xE1) {
|
| buf |= 0x30;
|
| }
|
| _mt_fe_tn_set_reg(state, 0x34, buf);
|
|
|
| buf = N & 0xff;
|
| _mt_fe_tn_set_reg(state, 0x35, buf);
|
|
|
| F = ((freq_KHz * MUL * M / (crystal_KHz / 1000) / 2) - (freq_KHz * MUL * M / crystal_KHz / 2 * 1000)) * 64 / 1000;
|
|
|
| buf = F & 0xff;
|
| _mt_fe_tn_set_reg(state, 0x36, buf);
|
|
|
| if (F == 0) {
|
| if (state->tuner_mtt == 0xD1) {
|
| _mt_fe_tn_set_reg(state, 0x3d, 0xca);
|
| }else if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_set_reg(state, 0x3d, 0xfe);
|
| } else {
|
| return 1;
|
| }
|
| _mt_fe_tn_set_reg(state, 0x3e, 0x9c);
|
| _mt_fe_tn_set_reg(state, 0x3f, 0x34);
|
| }
|
|
|
| if (F > 0) {
|
| if (state->tuner_mtt == 0xD1) {
|
| if ((F == 32) || (F == 16) || (F == 48)) {
|
| _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
|
| _mt_fe_tn_set_reg(state, 0x3d, 0x4a);
|
| _mt_fe_tn_set_reg(state, 0x3f, 0x36);
|
| }else {
|
| _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
|
| _mt_fe_tn_set_reg(state, 0x3d, 0x4a);
|
| _mt_fe_tn_set_reg(state, 0x3f, 0x36);
|
| }
|
| }else if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
|
| _mt_fe_tn_set_reg(state, 0x3d, 0x7e);
|
| _mt_fe_tn_set_reg(state, 0x3f, 0x36);
|
| _mt_fe_tn_set_reg(state, 0x89, 0x84);
|
| _mt_fe_tn_get_reg(state, 0x39, &buf);
|
| buf = buf & 0x1f;
|
| _mt_fe_tn_set_reg(state, 0x39, buf);
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf | 0x02;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
| }else {
|
| return 1;
|
| }
|
| }
|
|
|
| _mt_fe_tn_set_reg(state, 0x41, 0x00);
|
| if (state->tuner_mtt == 0xD1) {
|
| msleep(5);
|
| }else if (state->tuner_mtt == 0xE1) {
|
| msleep(2);
|
| }else {
|
| return 1;
|
| }
|
| _mt_fe_tn_set_reg(state, 0x41, 0x02);
|
| _mt_fe_tn_set_reg(state, 0x30, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x80);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x00); |
| |
| return 0;
|
| } |
|
|
| static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state)
|
| {
|
| u8 buf, buf1;
|
| u32 freq_thres_div2_KHz, freq_thres_div3r_KHz, freq_thres_div3_KHz;
|
|
|
| const u32 freq_KHz = state->tuner_freq;
|
|
|
| if (state->tuner_mtt == 0xD1) {
|
| _mt_fe_tn_set_reg(state, 0x32, 0xe1);
|
| _mt_fe_tn_set_reg(state, 0x33, 0xa6);
|
| _mt_fe_tn_set_reg(state, 0x37, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x38, 0x20); |
| _mt_fe_tn_set_reg(state, 0x39, 0x18);
|
| _mt_fe_tn_set_reg(state, 0x40, 0x40);
|
|
|
| freq_thres_div2_KHz = 520000;
|
| _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, freq_thres_div2_KHz, 0, 0);
|
|
|
| msleep(5);
|
| _mt_fe_tn_get_reg(state, 0x3a, &buf);
|
| buf1 = buf;
|
| buf = buf & 0x03;
|
| buf1 = buf1 & 0x01;
|
| if ((buf1 == 0) || (buf == 3)) {
|
| freq_thres_div2_KHz = 420000;
|
| _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, freq_thres_div2_KHz, 0, 0);
|
| msleep(5);
|
|
|
| _mt_fe_tn_get_reg(state, 0x3a, &buf);
|
| buf = buf & 0x07;
|
| if (buf == 5) {
|
| freq_thres_div2_KHz = 520000;
|
| _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, freq_thres_div2_KHz, 0, 0);
|
| msleep(5);
|
| }
|
| }
|
|
|
| _mt_fe_tn_get_reg(state, 0x38, &buf);
|
| _mt_fe_tn_set_reg(state, 0x38, buf);
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf | 0x10;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| _mt_fe_tn_set_reg(state, 0x30, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf & 0xdf;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
| _mt_fe_tn_set_reg(state, 0x40, 0x0);
|
|
|
| _mt_fe_tn_set_reg(state, 0x30, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x80);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x00);
|
| msleep(5);
|
|
|
| _mt_fe_tn_get_reg(state, 0x39, &buf);
|
| buf = buf >> 5;
|
| if (buf < 5) {
|
| _mt_fe_tn_get_reg(state, 0x39, &buf);
|
| buf = buf | 0xa0;
|
| buf = buf & 0xbf;
|
| _mt_fe_tn_set_reg(state, 0x39, buf);
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf | 0x02;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
| }
|
|
|
| _mt_fe_tn_get_reg(state, 0x37, &buf);
|
| if (buf > 0x70) {
|
| buf = 0x7f;
|
| _mt_fe_tn_set_reg(state, 0x40, 0x40);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x37, buf);
|
|
|
|
|
| _mt_fe_tn_get_reg(state, 0x38, &buf);
|
| if (buf < 0x0f) {
|
| buf = (buf & 0x0f) << 2;
|
| buf = buf + 0x0f;
|
| _mt_fe_tn_set_reg(state, 0x37, buf);
|
| }else if (buf < 0x1f) {
|
| buf= buf + 0x0f;
|
| _mt_fe_tn_set_reg(state, 0x37, buf);
|
| }
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = (buf | 0x20) & 0xef;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| _mt_fe_tn_set_reg(state, 0x41, 0x00);
|
| msleep(5);
|
| _mt_fe_tn_set_reg(state, 0x41, 0x02); |
|
|
| }else if (state->tuner_mtt == 0xE1){
|
| freq_thres_div2_KHz = 580000;
|
| freq_thres_div3r_KHz = 500000;
|
| freq_thres_div3_KHz = 440000;
|
| _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, freq_thres_div2_KHz, freq_thres_div3r_KHz, freq_thres_div3_KHz);
|
|
|
| msleep(3);
|
|
|
| _mt_fe_tn_get_reg(state, 0x38, &buf);
|
| _mt_fe_tn_set_reg(state, 0x38, buf);
|
| |
| _mt_fe_tn_set_reg(state, 0x30, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x80);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x00);
|
| msleep(3);
|
| _mt_fe_tn_get_reg(state, 0x38, &buf);
|
| _mt_fe_tn_set_reg(state, 0x38, buf); |
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf | 0x10;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| _mt_fe_tn_set_reg(state, 0x30, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = buf & 0xdf;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x80);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x00);
|
| msleep(3);
|
|
|
| _mt_fe_tn_get_reg(state, 0x37, &buf);
|
| _mt_fe_tn_set_reg(state, 0x37, buf); |
| /*
|
| if ((freq_KHz == 802000) || (freq_KHz == 826000)) {
|
| _mt_fe_tn_set_reg(state, 0x37, 0x5e);
|
| } |
| */
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = (buf & 0xef) | 0x30;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| _mt_fe_tn_set_reg(state, 0x41, 0x00);
|
| msleep(2);
|
| _mt_fe_tn_set_reg(state, 0x41, 0x02);
|
| } else {
|
| return 1;
|
| }
|
|
|
| return 0;
|
| } |
| |
| static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state)
|
| { |
| return 0;
|
| }
|
|
|
| static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state)
|
| {
|
| u8 buf;
|
| const u32 freq_KHz = state->tuner_freq;
|
|
|
| if (state->tuner_mtt == 0xD1) {
|
| if ((freq_KHz == 123000) || (freq_KHz == 147000) || (freq_KHz == 171000)
|
| || (freq_KHz == 195000))
|
| _mt_fe_tn_set_reg(state, 0x20, 0x1b);
|
|
|
| if ((freq_KHz == 371000) || (freq_KHz == 419000) || (freq_KHz == 610000)
|
| || (freq_KHz == 730000) || (freq_KHz == 754000) || (freq_KHz == 826000)) {
|
| _mt_fe_tn_get_reg(state, 0x0d, &buf);
|
| _mt_fe_tn_set_reg(state, 0x0d, (u8)(buf + 1));
|
| }
|
|
|
| if ((freq_KHz == 522000) || (freq_KHz == 578000) || (freq_KHz == 634000)
|
| || (freq_KHz == 690000) || (freq_KHz == 834000)) {
|
| _mt_fe_tn_get_reg(state, 0x0d, &buf);
|
| _mt_fe_tn_set_reg(state, 0x0d, (u8)(buf - 1));
|
| }
|
| } else if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_set_reg(state, 0x20, 0xfc);
|
| |
| if ((freq_KHz == 123000) || (freq_KHz == 147000) || (freq_KHz == 171000)
|
| || (freq_KHz == 195000) || (freq_KHz == 219000) || (freq_KHz == 267000)
|
| || (freq_KHz == 291000) || (freq_KHz == 339000) || (freq_KHz == 387000)
|
| || (freq_KHz == 435000) || (freq_KHz == 482000) || (freq_KHz == 530000)
|
| || (freq_KHz == 722000)
|
| || ((state->tuner_custom_cfg == 1) && (freq_KHz == 315000))) {
|
| _mt_fe_tn_set_reg(state, 0x20, 0x5c);
|
| }
|
| }
|
| return 0;
|
| }
|
|
|
| static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state)
|
| {
|
| u8 buf, tempnumber;
|
| s32 N;
|
| s32 f1f2number, f1, f2, delta1, Totalnum1;
|
| s32 cntT, cntin, NCOI, z0, z1, z2, tmp;
|
| u32 fc, fadc, fsd, f2d;
|
| u32 FreqTrue108_Hz;
|
|
|
| s32 M = state->tuner_crystal / 4000;
|
|
|
| /* const u8 bandwidth = state->tuner_bandwidth; */
|
| const u16 DAC_fre = 108;
|
| const u32 crystal_KHz = state->tuner_crystal;
|
| const u32 DACFreq_KHz = state->tuner_dac;
|
|
|
| const u32 freq_KHz = state->tuner_freq;
|
|
|
| if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_get_reg(state, 0x33, &buf);
|
| M = buf & 0x0f;
|
| if (M == 0)
|
| M = 6;
|
| }
|
|
|
| _mt_fe_tn_get_reg(state, 0x34, &buf);
|
| N = buf & 0x07;
|
|
|
| _mt_fe_tn_get_reg(state, 0x35, &buf);
|
| N = (N << 8) + buf;
|
|
|
|
|
| buf = ((N + 256) * crystal_KHz / M / DAC_fre + 500) / 1000;
|
|
|
| if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_set_appendix_tc2800(state);
|
| |
| if ((freq_KHz == 187000) || (freq_KHz == 195000) || (freq_KHz == 131000)
|
| || (freq_KHz == 211000) || (freq_KHz == 219000) || (freq_KHz == 227000)
|
| || (freq_KHz == 267000) || (freq_KHz == 299000) || (freq_KHz == 347000)
|
| || (freq_KHz == 363000) || (freq_KHz == 395000) || (freq_KHz == 403000)
|
| || (freq_KHz == 435000) || (freq_KHz == 482000) || (freq_KHz == 474000)
|
| || (freq_KHz == 490000) || (freq_KHz == 610000) || (freq_KHz == 642000)
|
| || (freq_KHz == 666000) || (freq_KHz == 722000) || (freq_KHz == 754000)
|
| || (((freq_KHz == 379000) || (freq_KHz == 467000) || (freq_KHz == 762000))
|
| && (state->tuner_custom_cfg != 1))) { |
| buf = buf + 1;
|
| }
|
| |
| if ((freq_KHz == 123000) || (freq_KHz == 139000) || (freq_KHz == 147000)
|
| || (freq_KHz == 171000) || (freq_KHz == 179000) || (freq_KHz == 203000)
|
| || (freq_KHz == 235000) || (freq_KHz == 251000) || (freq_KHz == 259000)
|
| || (freq_KHz == 283000) || (freq_KHz == 331000) || (freq_KHz == 363000)
|
| || (freq_KHz == 371000) || (freq_KHz == 387000) || (freq_KHz == 411000)
|
| || (freq_KHz == 427000) || (freq_KHz == 443000) || (freq_KHz == 451000)
|
| || (freq_KHz == 459000) || (freq_KHz == 506000) || (freq_KHz == 514000)
|
| || (freq_KHz == 538000) || (freq_KHz == 546000) || (freq_KHz == 554000)
|
| || (freq_KHz == 562000) || (freq_KHz == 570000) || (freq_KHz == 578000)
|
| || (freq_KHz == 602000) || (freq_KHz == 626000) || (freq_KHz == 658000)
|
| || (freq_KHz == 690000) || (freq_KHz == 714000) || (freq_KHz == 746000)
|
| || (freq_KHz == 522000) || (freq_KHz == 826000) || (freq_KHz == 155000)
|
| || (freq_KHz == 530000)
|
| || (((freq_KHz == 275000) || (freq_KHz == 355000)) && (state->tuner_custom_cfg != 1))
|
| || (((freq_KHz == 467000) || (freq_KHz == 762000) || (freq_KHz == 778000)
|
| || (freq_KHz == 818000)) && (state->tuner_custom_cfg == 1))) {
|
| buf = buf - 1;
|
| }
|
| }
|
|
|
| _mt_fe_tn_set_reg(state, 0x0e, buf);
|
| _mt_fe_tn_set_reg(state, 0x0d, buf);
|
|
|
| f1f2number = (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256)
|
| + (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) * crystal_KHz);
|
|
|
|
|
| _mt_fe_tn_set_reg(state, 0xf1, (u8)((f1f2number & 0xff00) >> 8));
|
| _mt_fe_tn_set_reg(state, 0xf2, (u8)(f1f2number & 0x00ff));
|
|
|
| FreqTrue108_Hz = (N + 256) * crystal_KHz / (M * buf) * 1000 + (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf);
|
|
|
| f1 = 4096;
|
| fc = FreqTrue108_Hz;
|
| fadc = fc / 4;
|
| fsd = 27000000;
|
| f2d = state->tuner_bandwidth * 1000 / 2 -150;
|
| f2 = (fsd / 250) * f2d / ((fc + 500) / 1000);
|
| delta1 = ((f1 - f2) << 15) / f2;
|
|
|
| Totalnum1 = ((f1 - f2) << 15) - delta1 * f2;
|
|
|
| cntT = f2;
|
| cntin = Totalnum1;
|
| NCOI = delta1;
|
|
|
| z0 = cntin;
|
| z1 = cntT;
|
| z2 = NCOI;
|
|
|
| tempnumber = (z0 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xc9, (u8)(tempnumber & 0x0f));
|
| tempnumber = (z0 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xca, tempnumber);
|
|
|
| tempnumber = (z1 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xcb, tempnumber);
|
| tempnumber = (z1 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xcc, tempnumber);
|
|
|
| tempnumber = (z2 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xcd, tempnumber);
|
| tempnumber = (z2 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xce, tempnumber);
|
|
|
| tmp = f1;
|
| f1 = f2;
|
| f2 = tmp / 2;
|
| delta1 = ((f1 - f2) << 15) / f2;
|
| Totalnum1 = ((f1 - f2) << 15) - delta1 * f2;
|
| NCOI = (f1 << 15) / f2 - (1 << 15);
|
| cntT = f2;
|
| cntin = Totalnum1;
|
| z0 = cntin;
|
| z1 = cntT;
|
| z2 = NCOI;
|
|
|
| tempnumber = (z0 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xd9, (u8)(tempnumber & 0x0f));
|
| tempnumber = (z0 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xda, tempnumber);
|
|
|
| tempnumber = (z1 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xdb, tempnumber);
|
| tempnumber = (z1 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xdc, tempnumber);
|
|
|
| tempnumber = (z2 & 0xff00) >> 8;
|
| _mt_fe_tn_set_reg(state, 0xdd, tempnumber);
|
| tempnumber = (z2 & 0xff);
|
| _mt_fe_tn_set_reg(state, 0xde, tempnumber); |
| |
| return 0;
|
| } |
| |
| static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state)
|
| {
|
| if (state->tuner_mtt == 0xD1) {
|
| _mt_fe_tn_set_reg(state, 0x19, 0x4a);
|
| _mt_fe_tn_set_reg(state, 0x1b, 0x4b);
|
|
|
| _mt_fe_tn_set_reg(state, 0x04, 0x04);
|
| _mt_fe_tn_set_reg(state, 0x17, 0x0d);
|
| _mt_fe_tn_set_reg(state, 0x62, 0x6c);
|
| _mt_fe_tn_set_reg(state, 0x63, 0xf4);
|
| _mt_fe_tn_set_reg(state, 0x1f, 0x0e);
|
| _mt_fe_tn_set_reg(state, 0x6b, 0xf4);
|
| _mt_fe_tn_set_reg(state, 0x14, 0x01);
|
| _mt_fe_tn_set_reg(state, 0x5a, 0x75);
|
| _mt_fe_tn_set_reg(state, 0x66, 0x74);
|
| _mt_fe_tn_set_reg(state, 0x72, 0xe0);
|
| _mt_fe_tn_set_reg(state, 0x70, 0x07);
|
| _mt_fe_tn_set_reg(state, 0x15, 0x7b);
|
| _mt_fe_tn_set_reg(state, 0x55, 0x71);
|
|
|
| _mt_fe_tn_set_reg(state, 0x75, 0x55);
|
| _mt_fe_tn_set_reg(state, 0x76, 0xac);
|
| _mt_fe_tn_set_reg(state, 0x77, 0x6c);
|
| _mt_fe_tn_set_reg(state, 0x78, 0x8b);
|
| _mt_fe_tn_set_reg(state, 0x79, 0x42);
|
| _mt_fe_tn_set_reg(state, 0x7a, 0xd2);
|
|
|
| _mt_fe_tn_set_reg(state, 0x81, 0x01);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x00);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x02);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x04);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x06);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x08);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x09);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x29);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x49);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x58);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x59);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x98);
|
| _mt_fe_tn_set_reg(state, 0x82, 0x99);
|
|
|
|
|
| _mt_fe_tn_set_reg(state, 0x10, 0x05);
|
| _mt_fe_tn_set_reg(state, 0x10, 0x0d);
|
| _mt_fe_tn_set_reg(state, 0x11, 0x95);
|
| _mt_fe_tn_set_reg(state, 0x11, 0x9d);
|
|
|
|
|
| if (state->tuner_loopthrough != 0) {
|
| _mt_fe_tn_set_reg(state, 0x67, 0x25);
|
| } else {
|
| _mt_fe_tn_set_reg(state, 0x67, 0x05);
|
| }
|
| } else if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_set_reg(state, 0x1b, 0x47);
|
| if(state->tuner_mode == 0) // DVB-C
|
| {
|
| _mt_fe_tn_set_reg(state, 0x66, 0x74);
|
| _mt_fe_tn_set_reg(state, 0x62, 0x2c);
|
| _mt_fe_tn_set_reg(state, 0x63, 0x54);
|
| _mt_fe_tn_set_reg(state, 0x68, 0x0b);
|
| _mt_fe_tn_set_reg(state, 0x14, 0x00);
|
| }
|
| else // CTTB
|
| {
|
| _mt_fe_tn_set_reg(state, 0x66, 0x74);
|
| _mt_fe_tn_set_reg(state, 0x62, 0x0c);
|
| _mt_fe_tn_set_reg(state, 0x63, 0x54);
|
| _mt_fe_tn_set_reg(state, 0x68, 0x0b);
|
| _mt_fe_tn_set_reg(state, 0x14, 0x05);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x6f, 0x00);
|
| _mt_fe_tn_set_reg(state, 0x84, 0x04);
|
| _mt_fe_tn_set_reg(state, 0x5e, 0xbe);
|
| _mt_fe_tn_set_reg(state, 0x87, 0x07);
|
| _mt_fe_tn_set_reg(state, 0x8a, 0x1f);
|
| _mt_fe_tn_set_reg(state, 0x8b, 0x1f);
|
| _mt_fe_tn_set_reg(state, 0x88, 0x30);
|
| _mt_fe_tn_set_reg(state, 0x58, 0x34);
|
| _mt_fe_tn_set_reg(state, 0x61, 0x8c);
|
| _mt_fe_tn_set_reg(state, 0x6a, 0x42);
|
| }
|
| return 0;
|
| } |
| |
| static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state)
|
| {
|
| _mt_fe_tn_set_reg(state, 0x16, 0xb1);
|
| _mt_fe_tn_set_reg(state, 0x09, 0x7d); |
| return 0;
|
| }
|
|
|
|
|
| static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state)
|
| {
|
| _mt_fe_tn_set_reg(state, 0x16, 0xb0);
|
| _mt_fe_tn_set_reg(state, 0x09, 0x6d); |
| return 0;
|
| }
|
|
|
| static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state)
|
| {
|
| if (state->tuner_init_OK != 1) {
|
| state->tuner_dev_addr = 0x61; /* TUNER_I2C_ADDR_TC2800 */
|
| state->tuner_freq = 650000; |
| state->tuner_qam = 0;
|
| state->tuner_mode = 0; // 0: DVB-C, 1: CTTB
|
|
|
| state->tuner_bandwidth = 8;
|
| state->tuner_loopthrough = 0;
|
| state->tuner_crystal = 24000;
|
| state->tuner_dac = 7200;
|
| state->tuner_mtt = 0x00; |
| state->tuner_custom_cfg = 0;
|
| state->tuner_version = 30022; /* Driver version number */ |
| state->tuner_time = 12092611;
|
| state->tuner_init_OK = 1;
|
| }
|
| |
| _mt_fe_tn_set_reg(state, 0x2b, 0x46);
|
| _mt_fe_tn_set_reg(state, 0x2c, 0x75); |
|
|
| if (state->tuner_mtt == 0x00) {
|
| u8 tmp = 0;
|
| _mt_fe_tn_get_reg(state, 0x01, &tmp); |
| printk("m88dc2800: tuner id = 0x%02x ", tmp);
|
| switch(tmp) {
|
| case 0x0d:
|
| state->tuner_mtt = 0xD1;
|
| break;
|
| case 0x8e:
|
| default:
|
| state->tuner_mtt = 0xE1;
|
| break;
|
| }
|
| }
|
| return 0;
|
| }
|
|
|
| static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state, u32 freq_KHz)
|
| {
|
| u8 buf; |
| u8 buf1;
|
|
|
| mt_fe_tn_init_tc2800(state);
|
|
|
| state->tuner_freq = freq_KHz;
|
| |
| if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x21, 0xb9);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x21, 0x99); |
|
|
| mt_fe_tn_wakeup_tc2800(state);
|
|
|
| _mt_fe_tn_set_reg(state, 0x05, 0x7f);
|
| _mt_fe_tn_set_reg(state, 0x06, 0xf8);
|
|
|
| _mt_fe_tn_set_RF_front_tc2800(state);
|
| _mt_fe_tn_set_PLL_freq_tc2800(state);
|
| _mt_fe_tn_set_DAC_tc2800(state);
|
| _mt_fe_tn_set_BB_tc2800(state);
|
| _mt_fe_tn_preset_tc2800(state);
|
|
|
| _mt_fe_tn_set_reg(state, 0x05, 0x00);
|
| _mt_fe_tn_set_reg(state, 0x06, 0x00);
|
|
|
| if (state->tuner_mtt == 0xD1) {
|
| _mt_fe_tn_set_reg(state, 0x00, 0x01);
|
| _mt_fe_tn_set_reg(state, 0x00, 0x00);
|
|
|
| msleep(5);
|
| _mt_fe_tn_set_reg(state, 0x41, 0x00);
|
| msleep(5);
|
| _mt_fe_tn_set_reg(state, 0x41, 0x02); |
| |
| _mt_fe_tn_get_reg(state, 0x69, &buf1);
|
| buf1 = buf1 & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x61, &buf);
|
| buf = buf & 0x0f;
|
| if (buf == 0x0c)
|
| {
|
| _mt_fe_tn_set_reg(state, 0x6a, 0x59);
|
| }
|
|
|
| if(buf1 > 0x02)
|
| {
|
| if (freq_KHz > 600000)
|
| _mt_fe_tn_set_reg(state, 0x66, 0x44);
|
| else if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x66, 0x64);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x66, 0x74);
|
| }
|
|
|
| if (buf1 < 0x03)
|
| {
|
| if (freq_KHz > 800000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x64);
|
| else if (freq_KHz > 600000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
| else if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
| else if (freq_KHz > 300000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x43);
|
| else if (freq_KHz > 220000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
| else if (freq_KHz > 110000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x14);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
|
|
| msleep(5);
|
| }
|
| else if (buf < 0x0c)
|
| {
|
| if (freq_KHz > 800000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x14);
|
| else if (freq_KHz >600000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x14);
|
| else if (freq_KHz > 500000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x34);
|
| else if (freq_KHz > 300000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x43);
|
| else if (freq_KHz > 220000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
| else if (freq_KHz > 110000)
|
| _mt_fe_tn_set_reg(state, 0x87, 0x14);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x87, 0x54);
|
|
|
| msleep(5);
|
| }
|
| } else if ((state->tuner_mtt == 0xE1)) {
|
| _mt_fe_tn_set_reg(state, 0x00, 0x01);
|
| _mt_fe_tn_set_reg(state, 0x00, 0x00);
|
|
|
| msleep(20);
|
|
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = (buf & 0xef) | 0x28;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| msleep(50);
|
| _mt_fe_tn_get_reg(state, 0x38, &buf);
|
| _mt_fe_tn_set_reg(state, 0x38, buf);
|
| _mt_fe_tn_get_reg(state, 0x32, &buf);
|
| buf = (buf & 0xf7)| 0x10 ;
|
| _mt_fe_tn_set_reg(state, 0x32, buf);
|
|
|
| msleep(10);
|
|
|
| _mt_fe_tn_get_reg(state, 0x69, &buf);
|
| buf = buf & 0x03;
|
| _mt_fe_tn_set_reg(state, 0x2a, buf);
|
|
|
| if(buf > 0)
|
| {
|
| msleep(20);
|
| _mt_fe_tn_get_reg(state, 0x84, &buf);
|
| buf = buf & 0x1f;
|
| _mt_fe_tn_set_reg(state, 0x68, 0x0a);
|
| _mt_fe_tn_get_reg(state, 0x88, &buf1);
|
| buf1 = buf1 & 0x1f;
|
| if(buf <= buf1)
|
| _mt_fe_tn_set_reg(state, 0x66, 0x44);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x66, 0x74);
|
| }
|
| else
|
| {
|
| if (freq_KHz <= 600000)
|
| {
|
| _mt_fe_tn_set_reg(state, 0x68, 0x0c);
|
| }
|
| else
|
| {
|
| _mt_fe_tn_set_reg(state, 0x68, 0x0e);
|
| }
|
| _mt_fe_tn_set_reg(state, 0x30, 0xfb);
|
| _mt_fe_tn_set_reg(state, 0x30, 0xff);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x04);
|
| _mt_fe_tn_set_reg(state, 0x31, 0x00);
|
| }
|
| if(state->tuner_loopthrough != 0) {
|
| _mt_fe_tn_get_reg(state, 0x28, &buf);
|
| if (buf == 0) {
|
| _mt_fe_tn_set_reg(state, 0x28, 0xff);
|
| _mt_fe_tn_get_reg(state, 0x61, &buf);
|
| buf = buf & 0x0f;
|
| if(buf > 9)
|
| _mt_fe_tn_set_reg(state, 0x67, 0x74);
|
| else if (buf >6)
|
| _mt_fe_tn_set_reg(state, 0x67, 0x64);
|
| else if (buf >3)
|
| _mt_fe_tn_set_reg(state, 0x67, 0x54);
|
| else
|
| _mt_fe_tn_set_reg(state, 0x67, 0x44);
|
| }
|
| } else {
|
| _mt_fe_tn_set_reg(state, 0x67, 0x34);
|
| }
|
| } else {
|
| return 1;
|
| }
|
| return 0;
|
| }
|
|
|
| /*
|
| static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state, u8 bandwidth)
|
| {
|
| u8 buf, tmp;
|
|
|
| _mt_fe_tn_get_reg(state, 0x53, &tmp);
|
|
|
| if (bandwidth == 6) |
| buf = 0x01 << 1;
|
| else if (bandwidth == 7) |
| buf = 0x02 << 1;
|
| else if (bandwidth == 8) |
| buf = 0x04 << 1;
|
| else |
| buf = 0x04 << 1;
|
|
|
| tmp &= 0xf1;
|
| tmp |= buf;
|
| _mt_fe_tn_set_reg(state, 0x53, tmp);
|
| state->tuner_bandwidth = bandwidth; |
| return 0;
|
| }
|
| */
|
|
|
| /*static s64 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state *state)*/
|
| static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state *state)
|
| {
|
| /*s64 level = -107;*/
|
| s32 level = -107;
|
| s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
| s32 val1, val2, val;
|
| s32 result2, result3, result4, result5, result6;
|
| s32 append;
|
| u8 tmp;
|
| s32 freq_KHz = (s32)state->tuner_freq;
|
|
|
| if (state->tuner_mtt == 0xD1) {
|
| _mt_fe_tn_get_reg(state, 0x61, &tmp);
|
| tmp1 = tmp & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x69, &tmp);
|
| tmp2 = tmp & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x73, &tmp);
|
| tmp3 = tmp & 0x07;
|
|
|
| _mt_fe_tn_get_reg(state, 0x7c, &tmp);
|
| tmp4 = (tmp >> 4) & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x7b, &tmp);
|
| tmp5 = tmp & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x7f, &tmp);
|
| tmp6 = (tmp >> 5) & 0x01;
|
|
|
| if (tmp1 > 6) {
|
| val1 = 0;
|
| if (freq_KHz <= 200000) {
|
| val2 = (tmp1 - 6) * 267;
|
| } else if (freq_KHz <= 600000) {
|
| val2 = (tmp1 - 6) * 280;
|
| } else {
|
| val2 = (tmp1 - 6) * 290;
|
| }
|
| val = val1 + val2;
|
| } else {
|
| if (tmp1 == 0) {
|
| val1 = -550;
|
| } else {
|
| val1 = 0;
|
| }
|
| if ((tmp1 < 4) && (freq_KHz >= 506000)) {
|
| val1 = -850;
|
| }
|
| val2 = 0;
|
| val = val1 + val2;
|
| }
|
|
|
| if (freq_KHz <= 95000) {
|
| result2 = tmp2 * 289;
|
| } else if (freq_KHz <= 155000) {
|
| result2 = tmp2 * 278;
|
| } else if (freq_KHz <= 245000) {
|
| result2 = tmp2 * 267;
|
| } else if (freq_KHz <= 305000) {
|
| result2 = tmp2 * 256;
|
| } else if (freq_KHz <= 335000) {
|
| result2 = tmp2 * 244;
|
| } else if (freq_KHz <= 425000) {
|
| result2 = tmp2 * 233;
|
| } else if (freq_KHz <= 575000) {
|
| result2 = tmp2 * 222;
|
| } else if (freq_KHz <= 665000) {
|
| result2 = tmp2 * 211;
|
| } else {
|
| result2 = tmp2 * 200;
|
| }
|
| result3 = (6 - tmp3) * 100;
|
| result4 = 300 * tmp4;
|
| result5 = 50 * tmp5;
|
| result6 = 300 * tmp6;
|
| if (freq_KHz < 105000) {
|
| append = -450;
|
| } else if (freq_KHz <= 227000) {
|
| append = -4 * (freq_KHz / 1000 - 100) + 150;
|
| } else if (freq_KHz <= 305000) {
|
| append = -4 * (freq_KHz / 1000 - 100);
|
| } else if (freq_KHz <= 419000) {
|
| append = 500 - 40 * (freq_KHz / 1000 - 300) / 17 + 130;
|
| } else if (freq_KHz <= 640000) {
|
| append = 500 - 40 * (freq_KHz / 1000 - 300) / 17;
|
| } else {
|
| append = -500;
|
| }
|
| level = append - (val + result2 + result3 + result4 + result5 + result6);
|
| level /= 100;
|
| } else if (state->tuner_mtt == 0xE1) {
|
| _mt_fe_tn_get_reg(state, 0x61, &tmp);
|
| tmp1 = tmp & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x84, &tmp);
|
| tmp2 = tmp & 0x1f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x69, &tmp);
|
| tmp3 = tmp & 0x03;
|
|
|
| _mt_fe_tn_get_reg(state, 0x73, &tmp);
|
| tmp4 = tmp & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x7c, &tmp);
|
| tmp5 = (tmp >> 4) & 0x0f;
|
|
|
| _mt_fe_tn_get_reg(state, 0x7b, &tmp);
|
| tmp6 = tmp & 0x0f;
|
|
|
| if (freq_KHz < 151000) {
|
| result2 = (1150 - freq_KHz / 100) * 163 / 33 + 4230;
|
| result3 = (1150 - freq_KHz / 100) * 115 / 33 + 1850;
|
| result4 = -3676 * (freq_KHz / 1000) / 100 + 6115;
|
| } else if (freq_KHz < 257000) {
|
| result2 = (1540 - freq_KHz / 100) * 11 / 4 + 3870;
|
| result3 = (1540 - freq_KHz / 100) * 205 / 96 + 2100;
|
| result4 = -21 * freq_KHz / 1000 + 5084;
|
| } else if (freq_KHz < 305000) {
|
| result2 = (2620 - freq_KHz / 100) * 5 / 3 + 2770;
|
| result3 = (2620 - freq_KHz / 100) * 10 / 7 + 1700;
|
| result4 = 650;
|
| } else if (freq_KHz < 449000) {
|
| result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270;
|
| result3 = (3100 - freq_KHz / 100) * 5 / 3 + 10000;
|
| result4 = 134 * freq_KHz / 10000 + 11875;
|
| } else {
|
| result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270;
|
| result3 = 8400;
|
| result4 = 5300;
|
| }
|
|
|
| if (tmp1 > 6) {
|
| val1 = result2;
|
| val2 = 2900;
|
| val = 500;
|
| } else if (tmp1 > 0) {
|
| val1 = result3;
|
| val2 = 2700;
|
| val = 500;
|
| } else {
|
| val1 = result4;
|
| val2 = 2700;
|
| val = 400;
|
| }
|
| level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 - 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000;
|
| level /= 1000;
|
| }
|
| return level;
|
| }
|
| |
| /* m88dc2800 operation functions */ |
| u8 M88DC2000GetLock(struct m88dc2800_state *state)
|
| {
|
| u8 u8ret = 0;
|
|
|
| if (ReadReg(state, 0x80) < 0x06) {
|
| if ((ReadReg(state, 0xdf)&0x80)==0x80
|
| && (ReadReg(state, 0x91)&0x23)==0x03
|
| && (ReadReg(state, 0x43)&0x08)==0x08)
|
| u8ret = 1;
|
| else
|
| u8ret = 0;
|
| } else {
|
| if ((ReadReg(state, 0x85)&0x08)==0x08)
|
| u8ret = 1;
|
| else
|
| u8ret = 0;
|
| }
|
| printk("%s, lock=%d\n", __func__,u8ret);
|
| return u8ret;
|
| } |
| |
| static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type)
|
| {
|
| u8 regC2H;
|
|
|
| if (type == 3) {
|
| WriteReg(state, 0x84, 0x6A);
|
| WriteReg(state, 0xC0, 0x43);
|
| WriteReg(state, 0xE2, 0x06);
|
| regC2H = ReadReg(state, 0xC2);
|
| regC2H &= 0xC0;
|
| regC2H |= 0x1B;
|
| WriteReg(state, 0xC2, regC2H);
|
| WriteReg(state, 0xC1, 0x60); /* common interface */
|
| } else if (type == 1) {
|
| WriteReg(state, 0x84, 0x6A);
|
| WriteReg(state, 0xC0, 0x47); /* serial format */
|
| WriteReg(state, 0xE2, 0x02);
|
| regC2H = ReadReg(state, 0xC2);
|
| regC2H &= 0xC7;
|
| WriteReg(state, 0xC2, regC2H);
|
| WriteReg(state, 0xC1, 0x00);
|
| } else {
|
| WriteReg(state, 0x84, 0x6C);
|
| WriteReg(state, 0xC0, 0x43); /* parallel format */
|
| WriteReg(state, 0xE2, 0x06);
|
| regC2H = ReadReg(state, 0xC2);
|
| regC2H &= 0xC7;
|
| WriteReg(state, 0xC2, regC2H);
|
| WriteReg(state, 0xC1, 0x00);
|
| } |
| return 0;
|
| } |
| |
| static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state)
|
| {
|
| u8 RegE3H, RegE4H;
|
|
|
| WriteReg(state, 0x00, 0x48);
|
| WriteReg(state, 0x01, 0x09);
|
| WriteReg(state, 0xFB, 0x0A);
|
| WriteReg(state, 0xFC, 0x0B);
|
| WriteReg(state, 0x02, 0x0B);
|
| WriteReg(state, 0x03, 0x18);
|
| WriteReg(state, 0x05, 0x0D);
|
| WriteReg(state, 0x36, 0x80);
|
| WriteReg(state, 0x43, 0x40);
|
| WriteReg(state, 0x55, 0x7A);
|
| WriteReg(state, 0x56, 0xD9);
|
| WriteReg(state, 0x57, 0xDF);
|
| WriteReg(state, 0x58, 0x39);
|
| WriteReg(state, 0x5A, 0x00);
|
| WriteReg(state, 0x5C, 0x71);
|
| WriteReg(state, 0x5D, 0x23);
|
| WriteReg(state, 0x86, 0x40);
|
| WriteReg(state, 0xF9, 0x08);
|
| WriteReg(state, 0x61, 0x40);
|
| WriteReg(state, 0x62, 0x0A);
|
| WriteReg(state, 0x90, 0x06);
|
| WriteReg(state, 0xDE, 0x00);
|
| WriteReg(state, 0xA0, 0x03);
|
| WriteReg(state, 0xDF, 0x81);
|
| WriteReg(state, 0xFA, 0x40);
|
| WriteReg(state, 0x37, 0x10);
|
| WriteReg(state, 0xF0, 0x40);
|
| WriteReg(state, 0xF2, 0x9C);
|
| WriteReg(state, 0xF3, 0x40);
|
|
|
| RegE3H = ReadReg(state, 0xE3);
|
| RegE4H = ReadReg(state, 0xE4);
|
| if (((RegE3H & 0xC0) == 0x00) && ((RegE4H & 0xC0) == 0x00)) {
|
| WriteReg(state, 0x30, 0xFF);
|
| WriteReg(state, 0x31, 0x00);
|
| WriteReg(state, 0x32, 0x00);
|
| WriteReg(state, 0x33, 0x00);
|
| WriteReg(state, 0x35, 0x32);
|
| WriteReg(state, 0x40, 0x00);
|
| WriteReg(state, 0x41, 0x10);
|
| WriteReg(state, 0xF1, 0x02);
|
| WriteReg(state, 0xF4, 0x04);
|
| WriteReg(state, 0xF5, 0x00);
|
| WriteReg(state, 0x42, 0x14);
|
| WriteReg(state, 0xE1, 0x25);
|
| } else if (((RegE3H & 0xC0) == 0x80) && ((RegE4H & 0xC0) == 0x40)) {
|
| WriteReg(state, 0x30, 0xFF);
|
| WriteReg(state, 0x31, 0x00);
|
| WriteReg(state, 0x32, 0x00);
|
| WriteReg(state, 0x33, 0x00);
|
| WriteReg(state, 0x35, 0x32);
|
| WriteReg(state, 0x39, 0x00);
|
| WriteReg(state, 0x3A, 0x00);
|
| WriteReg(state, 0x40, 0x00);
|
| WriteReg(state, 0x41, 0x10);
|
| WriteReg(state, 0xF1, 0x00);
|
| WriteReg(state, 0xF4, 0x00);
|
| WriteReg(state, 0xF5, 0x40);
|
| WriteReg(state, 0x42, 0x14);
|
| WriteReg(state, 0xE1, 0x25);
|
| } else if ((RegE3H == 0x80 || RegE3H == 0x81) && (RegE4H == 0x80 || RegE4H == 0x81)) {
|
| WriteReg(state, 0x30, 0xFF);
|
| WriteReg(state, 0x31, 0x00);
|
| WriteReg(state, 0x32, 0x00);
|
| WriteReg(state, 0x33, 0x00);
|
| WriteReg(state, 0x35, 0x32);
|
| WriteReg(state, 0x39, 0x00);
|
| WriteReg(state, 0x3A, 0x00);
|
| WriteReg(state, 0xF1, 0x00);
|
| WriteReg(state, 0xF4, 0x00);
|
| WriteReg(state, 0xF5, 0x40);
|
| WriteReg(state, 0x42, 0x24);
|
| WriteReg(state, 0xE1, 0x25);
|
|
|
| WriteReg(state, 0x92, 0x7F);
|
| WriteReg(state, 0x93, 0x91);
|
| WriteReg(state, 0x95, 0x00);
|
| WriteReg(state, 0x2B, 0x33);
|
| WriteReg(state, 0x2A, 0x2A);
|
| WriteReg(state, 0x2E, 0x80);
|
| WriteReg(state, 0x25, 0x25);
|
| WriteReg(state, 0x2D, 0xFF);
|
| WriteReg(state, 0x26, 0xFF);
|
| WriteReg(state, 0x27, 0x00);
|
| WriteReg(state, 0x24, 0x25);
|
| WriteReg(state, 0xA4, 0xFF);
|
| WriteReg(state, 0xA3, 0x0D);
|
| } else {
|
| WriteReg(state, 0x30, 0xFF);
|
| WriteReg(state, 0x31, 0x00);
|
| WriteReg(state, 0x32, 0x00);
|
| WriteReg(state, 0x33, 0x00);
|
| WriteReg(state, 0x35, 0x32);
|
| WriteReg(state, 0x39, 0x00);
|
| WriteReg(state, 0x3A, 0x00);
|
| WriteReg(state, 0xF1, 0x00);
|
| WriteReg(state, 0xF4, 0x00);
|
| WriteReg(state, 0xF5, 0x40);
|
| WriteReg(state, 0x42, 0x24);
|
| WriteReg(state, 0xE1, 0x27);
|
|
|
| WriteReg(state, 0x92, 0x7F);
|
| WriteReg(state, 0x93, 0x91);
|
| WriteReg(state, 0x95, 0x00);
|
| WriteReg(state, 0x2B, 0x33);
|
| WriteReg(state, 0x2A, 0x2A);
|
| WriteReg(state, 0x2E, 0x80);
|
| WriteReg(state, 0x25, 0x25);
|
| WriteReg(state, 0x2D, 0xFF);
|
| WriteReg(state, 0x26, 0xFF);
|
| WriteReg(state, 0x27, 0x00);
|
| WriteReg(state, 0x24, 0x25);
|
| WriteReg(state, 0xA4, 0xFF);
|
| WriteReg(state, 0xA3, 0x10);
|
| }
|
|
|
| WriteReg(state, 0xF6, 0x4E);
|
| WriteReg(state, 0xF7, 0x20);
|
| WriteReg(state, 0x89, 0x02);
|
| WriteReg(state, 0x14, 0x08);
|
| WriteReg(state, 0x6F, 0x0D);
|
| WriteReg(state, 0x10, 0xFF);
|
| WriteReg(state, 0x11, 0x00);
|
| WriteReg(state, 0x12, 0x30);
|
| WriteReg(state, 0x13, 0x23);
|
| WriteReg(state, 0x60, 0x00);
|
| WriteReg(state, 0x69, 0x00);
|
| WriteReg(state, 0x6A, 0x03);
|
| WriteReg(state, 0xE0, 0x75);
|
| WriteReg(state, 0x8D, 0x29);
|
| WriteReg(state, 0x4E, 0xD8);
|
| WriteReg(state, 0x88, 0x80);
|
| WriteReg(state, 0x52, 0x79);
|
| WriteReg(state, 0x53, 0x03);
|
| WriteReg(state, 0x59, 0x30);
|
| WriteReg(state, 0x5E, 0x02);
|
| WriteReg(state, 0x5F, 0x0F);
|
| WriteReg(state, 0x71, 0x03);
|
| WriteReg(state, 0x72, 0x12);
|
| WriteReg(state, 0x73, 0x12); |
| |
| return 0;
|
| } |
| |
| static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym, u16 qam)
|
| {
|
| u32 dataRate;
|
| u8 clk_div, value; |
| printk("m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n",sym,qam);
|
| switch(qam)
|
| {
|
| case 16:
|
| dataRate = 4;
|
| break;
|
| case 32:
|
| dataRate = 5;
|
| break;
|
| case 128:
|
| dataRate = 7;
|
| break;
|
| case 256:
|
| dataRate = 8;
|
| break;
|
| case 64:
|
| default:
|
| dataRate = 6;
|
| break;
|
| }
|
| dataRate *= sym * 105;
|
| dataRate /= 800;
|
|
|
| if(dataRate <= 4115)
|
| clk_div = 0x05;
|
| else if(dataRate <= 4800)
|
| clk_div = 0x04;
|
| else if(dataRate <= 5760)
|
| clk_div = 0x03;
|
| else if(dataRate <= 7200)
|
| clk_div = 0x02;
|
| else if(dataRate <= 9600)
|
| clk_div = 0x01;
|
| else
|
| clk_div = 0x00;
|
|
|
| value = ReadReg(state, 0xC2);
|
| value &= 0xc0;
|
| value |= clk_div;
|
| WriteReg(state, 0xC2, value); |
| return 0;
|
| } |
| |
| static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym, u16 qam)
|
| {
|
| u32 dataRate;
|
| u8 clk_div, value; |
| printk("m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n",sym,qam);
|
| switch(qam)
|
| {
|
| case 16:
|
| dataRate = 4;
|
| break;
|
| case 32:
|
| dataRate = 5;
|
| break;
|
| case 128:
|
| dataRate = 7;
|
| break;
|
| case 256:
|
| dataRate = 8;
|
| break;
|
| case 64:
|
| default:
|
| dataRate = 6;
|
| break;
|
| }
|
| dataRate *= sym * 105;
|
| dataRate /= 800;
|
|
|
| if(dataRate <= 4115)
|
| clk_div = 0x3F;
|
| else if(dataRate <= 4800)
|
| clk_div = 0x36;
|
| else if(dataRate <= 5760)
|
| clk_div = 0x2D;
|
| else if(dataRate <= 7200)
|
| clk_div = 0x24;
|
| else if(dataRate <= 9600)
|
| clk_div = 0x1B;
|
| else
|
| clk_div = 0x12;
|
|
|
| value = ReadReg(state, 0xC2);
|
| value &= 0xc0;
|
| value |= clk_div;
|
| WriteReg(state, 0xC2, value); |
| return 0;
|
| } |
| |
| static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted, u8 j83)
|
| {
|
| u8 value = 0;
|
| if (inverted) |
| value |= 0x08; /* spectrum inverted */
|
| if (j83) |
| value |= 0x01; /* J83C */
|
| WriteReg(state, 0x83, value); |
| return 0;
|
| } |
| |
| static int M88DC2000SoftReset(struct m88dc2800_state *state)
|
| {
|
| WriteReg(state, 0x80, 0x01);
|
| WriteReg(state, 0x82, 0x00);
|
| msleep(1);
|
| WriteReg(state, 0x80, 0x00); |
| return 0;
|
| } |
| |
| static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal)
|
| {
|
| u8 value;
|
| u8 reg6FH, reg12H;
|
| u64 fValue;
|
| u32 dwValue;
|
| printk("%s, sym=%d, xtal=%d\n", __func__, sym, xtal);
|
|
|
| fValue = 4294967296 * (sym + 10);
|
| do_div(fValue, xtal);
|
| /* fValue = 4294967296 * (sym + 10) / xtal; */
|
|
|
| dwValue = (u32)fValue;
|
| printk("%s, fvalue1=%x\n", __func__, dwValue);
|
|
|
| WriteReg(state, 0x58, (u8)((dwValue >> 24) & 0xff));
|
| WriteReg(state, 0x57, (u8)((dwValue >> 16) & 0xff));
|
| WriteReg(state, 0x56, (u8)((dwValue >> 8) & 0xff));
|
| WriteReg(state, 0x55, (u8)((dwValue >> 0) & 0xff));
|
| |
| /* fValue = 2048 * xtal / sym; */
|
| fValue = 2048 * xtal;
|
| do_div(fValue, sym);
|
|
|
| dwValue = (u32)fValue;
|
| printk("%s, fvalue2=%x\n", __func__, dwValue);
|
| WriteReg(state, 0x5D, (u8)((dwValue >> 8) & 0xff));
|
| WriteReg(state, 0x5C, (u8)((dwValue >> 0) & 0xff));
|
|
|
| value = ReadReg(state, 0x5A);
|
| if (((dwValue >> 16) & 0x0001) == 0)
|
| value &= 0x7F;
|
| else
|
| value |= 0x80;
|
| WriteReg(state, 0x5A, value);
|
|
|
| value = ReadReg(state, 0x89);
|
| if (sym <= 1800)
|
| value |= 0x01;
|
| else
|
| value &= 0xFE;
|
| WriteReg(state, 0x89, value);
|
|
|
| if (sym >= 6700){
|
| reg6FH = 0x0D;
|
| reg12H = 0x30;
|
| } else if (sym >= 4000) {
|
| fValue = 22 * 4096 / sym;
|
| reg6FH = (u8)fValue;
|
| reg12H = 0x30;
|
| } else if (sym >= 2000) {
|
| fValue = 14 * 4096 / sym;
|
| reg6FH = (u8)fValue;
|
| reg12H = 0x20;
|
| } else {
|
| fValue = 7 * 4096 / sym;
|
| reg6FH = (u8)fValue;
|
| reg12H = 0x10;
|
| }
|
| WriteReg(state, 0x6F, reg6FH);
|
| WriteReg(state, 0x12, reg12H);
|
|
|
| if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| if(sym < 3000) {
|
| WriteReg(state, 0x6C, 0x16);
|
| WriteReg(state, 0x6D, 0x10);
|
| WriteReg(state, 0x6E, 0x18);
|
| } else {
|
| WriteReg(state, 0x6C, 0x14);
|
| WriteReg(state, 0x6D, 0x0E);
|
| WriteReg(state, 0x6E, 0x36);
|
| }
|
| } else {
|
| WriteReg(state, 0x6C, 0x16);
|
| WriteReg(state, 0x6D, 0x10);
|
| WriteReg(state, 0x6E, 0x18);
|
| } |
| return 0;
|
| } |
| |
| static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam)
|
| {
|
| u8 reg00H, reg4AH, regC2H, reg44H, reg4CH, reg4DH, reg74H, value;
|
| u8 reg8BH, reg8EH;
|
| printk("%s, qam=%d\n", __func__, qam);
|
| regC2H = ReadReg(state, 0xC2);
|
| regC2H &= 0xF8;
|
| switch(qam){
|
| case 16: /* 16 QAM */
|
| reg00H = 0x08;
|
| reg4AH = 0x0F;
|
| regC2H |= 0x02;
|
| reg44H = 0xAA;
|
| reg4CH = 0x0C;
|
| reg4DH = 0xF7;
|
| reg74H = 0x0E;
|
| if(((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| reg8BH = 0x5A;
|
| reg8EH = 0xBD;
|
| } else {
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| }
|
| WriteReg(state, 0x6E, 0x18);
|
| break;
|
| case 32: /* 32 QAM */
|
| reg00H = 0x18;
|
| reg4AH = 0xFB;
|
| regC2H |= 0x02;
|
| reg44H = 0xAA;
|
| reg4CH = 0x0C;
|
| reg4DH = 0xF7;
|
| reg74H = 0x0E;
|
| if(((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| reg8BH = 0x5A;
|
| reg8EH = 0xBD;
|
| } else {
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| }
|
| WriteReg(state, 0x6E, 0x18);
|
| break;
|
| case 64: /* 64 QAM */
|
| reg00H = 0x48;
|
| reg4AH = 0xCD;
|
| regC2H |= 0x02;
|
| reg44H = 0xAA;
|
| reg4CH = 0x0C;
|
| reg4DH = 0xF7;
|
| reg74H = 0x0E;
|
| if(((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| reg8BH = 0x5A;
|
| reg8EH = 0xBD;
|
| } else {
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| }
|
| break;
|
| case 128: /* 128 QAM */
|
| reg00H = 0x28;
|
| reg4AH = 0xFF;
|
| regC2H |= 0x02;
|
| reg44H = 0xA9;
|
| reg4CH = 0x08;
|
| reg4DH = 0xF5;
|
| reg74H = 0x0E;
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| break;
|
| case 256: /* 256 QAM */
|
| reg00H = 0x38;
|
| reg4AH = 0xCD;
|
| if(((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| regC2H |= 0x02;
|
| } else {
|
| regC2H |= 0x01;
|
| }
|
| reg44H = 0xA9;
|
| reg4CH = 0x08;
|
| reg4DH = 0xF5;
|
| reg74H = 0x0E;
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| break;
|
| default: /* 64 QAM */
|
| reg00H = 0x48;
|
| reg4AH = 0xCD;
|
| regC2H |= 0x02;
|
| reg44H = 0xAA;
|
| reg4CH = 0x0C;
|
| reg4DH = 0xF7;
|
| reg74H = 0x0E;
|
| if(((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
|
| reg8BH = 0x5A;
|
| reg8EH = 0xBD;
|
| } else {
|
| reg8BH = 0x5B;
|
| reg8EH = 0x9D;
|
| }
|
| break;
|
| }
|
| WriteReg(state, 0x00, reg00H);
|
|
|
| value = ReadReg(state, 0x88);
|
| value |= 0x08;
|
| WriteReg(state, 0x88, value);
|
| WriteReg(state, 0x4B, 0xFF);
|
| WriteReg(state, 0x4A, reg4AH);
|
| value &= 0xF7;
|
| WriteReg(state, 0x88, value);
|
|
|
| WriteReg(state, 0xC2, regC2H);
|
| WriteReg(state, 0x44, reg44H);
|
| WriteReg(state, 0x4C, reg4CH);
|
| WriteReg(state, 0x4D, reg4DH);
|
| WriteReg(state, 0x74, reg74H);
|
| WriteReg(state, 0x8B, reg8BH);
|
| WriteReg(state, 0x8E, reg8EH); |
| return 0;
|
| } |
| |
| static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state, u32 freq_KHz)
|
| {
|
| printk("%s, freq=%d KHz\n", __func__, freq_KHz);
|
| return mt_fe_tn_set_freq_tc2800(state, freq_KHz);
|
| } |
| |
| static int m88dc2800_init(struct dvb_frontend *fe) |
| { |
| dprintk("%s()\n", __func__); |
| return 0; |
| } |
| |
| static int m88dc2800_set_parameters(struct dvb_frontend *fe) |
| { |
| struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| u8 is_annex_c, is_update; |
| u16 temp_qam; |
| s32 waiting_time; |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| |
| if(c->delivery_system == SYS_DVBC_ANNEX_C) |
| is_annex_c = 1; |
| else |
| is_annex_c = 0; |
| |
| switch (c->modulation) { |
| case QAM_16: |
| temp_qam = 16; |
| break; |
| case QAM_32: |
| temp_qam = 32; |
| break; |
| case QAM_128: |
| temp_qam = 128; |
| break; |
| case QAM_256: |
| temp_qam = 256; |
| break; |
| default: /* QAM_64 */ |
| temp_qam = 64; |
| break; |
| } |
| |
| if(c->inversion == INVERSION_ON) |
| state->inverted = 1; |
| else |
| state->inverted = 0; |
| |
| printk("m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n", state->freq,state->qam,state->sym,state->inverted,state->xtal); |
| printk("m88dc2800: set frequency to %d qam=%d symrate=%d annex-c=%d\n", c->frequency,temp_qam,c->symbol_rate,is_annex_c); |
| |
| is_update = 0; |
| WriteReg(state, 0x80, 0x01); |
| if(c->frequency != state->freq){ |
| M88DC2000WriteTuner_TC2800(state, c->frequency/1000); |
| state->freq = c->frequency; |
| } |
| if(c->symbol_rate != state->sym){
|
| M88DC2000SetSym(state, c->symbol_rate/1000, state->xtal);
|
| state->sym = c->symbol_rate; |
| is_update = 1; |
| } |
| if(temp_qam != state->qam){
|
| M88DC2000SetQAM(state, temp_qam);
|
| state->qam = temp_qam; |
| is_update = 1;
|
| } |
| |
| if(is_update != 0){ |
| if(state->config->ts_mode == 3) |
| M88DC2000AutoTSClock_C(state, state->sym/1000, temp_qam); |
| else |
| M88DC2000AutoTSClock_P(state, state->sym/1000, temp_qam); |
| } |
| |
| M88DC2000SetTxMode(state, state->inverted, is_annex_c); |
| M88DC2000SoftReset(state); |
| if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80))
|
| waiting_time = 800;
|
| else
|
| waiting_time = 500;
|
| while (waiting_time > 0) {
|
| msleep(50);
|
| waiting_time -= 50;
|
| if (M88DC2000GetLock(state))
|
| return 0;
|
| } |
| |
| if (state->inverted != 0)
|
| state->inverted = 0;
|
| else
|
| state->inverted = 1; |
| M88DC2000SetTxMode(state, state->inverted, is_annex_c);
|
| M88DC2000SoftReset(state);
|
| if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && ((ReadReg(state, 0xE4) & 0x80) == 0x80))
|
| waiting_time = 800;
|
| else
|
| waiting_time = 500;
|
| while (waiting_time > 0) {
|
| msleep(50);
|
| waiting_time -= 50;
|
| if (M88DC2000GetLock(state))
|
| return 0;
|
| } |
| return 0; |
| } |
| |
| static int m88dc2800_read_status(struct dvb_frontend* fe, fe_status_t* status) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| *status = 0; |
| |
| if (M88DC2000GetLock(state)) { |
| *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
|
| | FE_HAS_SYNC|FE_HAS_VITERBI | FE_HAS_LOCK; |
| } |
| return 0; |
| } |
| |
| static int m88dc2800_read_ber(struct dvb_frontend* fe, u32* ber) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| u16 tmp; |
| |
| if (M88DC2000GetLock(state) == 0) {
|
| state->ber = 0; |
| } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) {
|
| tmp = ReadReg(state, 0xA2) << 8;
|
| tmp += ReadReg(state, 0xA1);
|
| state->ber = tmp;
|
| WriteReg(state, 0xA0, 0x05);
|
| WriteReg(state, 0xA0, 0x85);
|
| } |
| *ber = state->ber; |
| return 0; |
| } |
| |
| static int m88dc2800_read_signal_strength(struct dvb_frontend* fe, u16* strength) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| |
| s16 tuner_strength; |
| tuner_strength = (s16)mt_fe_tn_get_signal_strength_tc2800(state);
|
|
|
| if(tuner_strength < -107)
|
| *strength = 0;
|
| else
|
| *strength = tuner_strength + 107; |
| |
| return 0; |
| } |
| |
| static int m88dc2800_read_snr(struct dvb_frontend* fe, u16* snr) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| |
| const u32 mes_log[] = {
|
| 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000,
|
| 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, 13010,
|
| 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, 14624, 14771,
|
| 14914, 15052, 15185, 15315, 15441, 15563, 15682, 15798, 15911, 16021,
|
| 16128, 16232, 16335, 16435, 16532, 16628, 16721, 16812, 16902, 16990,
|
| 17076, 17160, 17243, 17324, 17404, 17482, 17559, 17634, 17709, 17782,
|
| 17853, 17924, 17993, 18062, 18129, 18195, 18261, 18325, 18388, 18451,
|
| 18513, 18573, 18633, 18692, 18751, 18808, 18865, 18921, 18976, 19031
|
| };
|
| u8 i;
|
| u32 _snr, mse;
|
|
|
| if ((ReadReg(state, 0x91)&0x23)!=0x03) { |
| *snr = 0;
|
| return 0; |
| }
|
|
|
| mse = 0;
|
| for (i=0; i<30; i++) {
|
| mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07);
|
| }
|
| mse /= 30;
|
| if (mse > 80)
|
| mse = 80;
|
|
|
| switch (state->qam) {
|
| case 16: _snr = 34080; break; /* 16QAM */
|
| case 32: _snr = 37600; break; /* 32QAM */
|
| case 64: _snr = 40310; break; /* 64QAM */
|
| case 128: _snr = 43720; break; /* 128QAM */
|
| case 256: _snr = 46390; break; /* 256QAM */
|
| default: _snr = 40310; break;
|
| }
|
| _snr -= mes_log[mse-1]; /* C - 10*log10(MSE) */
|
| _snr /= 1000;
|
| if (_snr > 0xff)
|
| _snr = 0xff;
|
|
|
| *snr = _snr; |
| return 0; |
| } |
| |
| static int m88dc2800_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| u8 u8Value; |
| |
| u8Value = ReadReg(state, 0xdf); |
| u8Value |= 0x02; /* Hold */ |
| WriteReg(state, 0xdf, u8Value); |
| |
| *ucblocks = ReadReg(state, 0xd5); |
| *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4); |
| |
| u8Value &= 0xfe; /* Clear */ |
| WriteReg(state, 0xdf, u8Value); |
| u8Value &= 0xfc; /* Update */ |
| u8Value |= 0x01; |
| WriteReg(state, 0xdf, u8Value); |
| |
| return 0; |
| } |
| |
| static int m88dc2800_sleep(struct dvb_frontend* fe) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| |
| mt_fe_tn_sleep_tc2800(state); |
| state->freq = 0; |
| |
| return 0; |
| } |
| |
| static void m88dc2800_release(struct dvb_frontend* fe) |
| { |
| struct m88dc2800_state* state = fe->demodulator_priv; |
| kfree(state); |
| } |
| |
| static struct dvb_frontend_ops m88dc2800_ops; |
| |
| struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, |
| struct i2c_adapter* i2c) |
| { |
| struct m88dc2800_state* state = NULL; |
| |
| /* allocate memory for the internal state */ |
| state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL); |
| if (state == NULL) goto error; |
| |
| /* setup the state */ |
| state->config = config; |
| state->i2c = i2c; |
| state->xtal = 28800; |
| |
| WriteReg(state, 0x80, 0x01); |
| M88DC2000RegInitial_TC2800(state);
|
| M88DC2000SetTsType(state, state->config->ts_mode); |
| mt_fe_tn_init_tc2800(state); |
| |
| /* create dvb_frontend */ |
| memcpy(&state->frontend.ops, &m88dc2800_ops, sizeof(struct dvb_frontend_ops)); |
| state->frontend.demodulator_priv = state; |
| return &state->frontend; |
| |
| error: |
| kfree(state); |
| return NULL; |
| } |
| EXPORT_SYMBOL(m88dc2800_attach); |
| |
| static struct dvb_frontend_ops m88dc2800_ops = { |
| .info = { |
| .name = "Montage M88DC2800 DVB-C", |
| .frequency_stepsize = 62500, |
| .frequency_min = 48000000, |
| .frequency_max = 870000000, |
| .symbol_rate_min = 870000, |
| .symbol_rate_max = 9000000, |
| .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | |
| FE_CAN_QAM_128 | FE_CAN_QAM_256 | |
| FE_CAN_FEC_AUTO |
| }, |
| |
| .release = m88dc2800_release, |
| .init = m88dc2800_init, |
| .sleep = m88dc2800_sleep, |
| .set_frontend = m88dc2800_set_parameters, |
| .read_status = m88dc2800_read_status, |
| .read_ber = m88dc2800_read_ber, |
| .read_signal_strength = m88dc2800_read_signal_strength, |
| .read_snr = m88dc2800_read_snr, |
| .read_ucblocks = m88dc2800_read_ucblocks, |
| }; |
| |
| MODULE_DESCRIPTION("Montage DVB-C demodulator driver"); |
| MODULE_AUTHOR("Max nibble"); |
| MODULE_LICENSE("GPL"); |