]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
[media] m88rs2000: make use ts2020
authorIgor M. Liplianin <liplianin@me.by>
Fri, 28 Dec 2012 22:40:33 +0000 (19:40 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 28 Dec 2012 23:37:36 +0000 (21:37 -0200)
Tuner part of Montage rs2000 chip is similar to ts2020 tuner.
Patch to use ts2020 code.

[mchehab@redhat.com: a few CodingStyle fixes]
Signed-off-by: Igor M. Liplianin <liplianin@me.by>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb-frontends/m88rs2000.c
drivers/media/dvb-frontends/m88rs2000.h
drivers/media/dvb-frontends/ts2020.c
drivers/media/dvb-frontends/ts2020.h
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/cx88/cx88-dvb.c
drivers/media/pci/dm1105/dm1105.c
drivers/media/usb/dvb-usb-v2/Kconfig
drivers/media/usb/dvb-usb-v2/lmedm04.c
drivers/media/usb/dvb-usb/dw2102.c

index df9e7dd6fe74010469f258bdc0474df4a7c5145e..283c90fee374658be4159b81f7d2e908e342603e 100644 (file)
@@ -60,15 +60,13 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
 #define info(format, arg...) \
        printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg)
 
-static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner,
+static int m88rs2000_writereg(struct m88rs2000_state *state,
        u8 reg, u8 data)
 {
        int ret;
-       u8 addr = (tuner == 0) ? state->config->tuner_addr :
-               state->config->demod_addr;
        u8 buf[] = { reg, data };
        struct i2c_msg msg = {
-               .addr = addr,
+               .addr = state->config->demod_addr,
                .flags = 0,
                .buf = buf,
                .len = 2
@@ -83,44 +81,20 @@ static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner,
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
-       return m88rs2000_writereg(state, 1, reg, data);
-}
-
-static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
-       m88rs2000_demod_write(state, 0x81, 0x84);
-       udelay(10);
-       return m88rs2000_writereg(state, 0, reg, data);
-
-}
-
-static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-       struct m88rs2000_state *state = fe->demodulator_priv;
-
-       if (len != 2)
-               return -EINVAL;
-
-       return m88rs2000_writereg(state, 1, buf[0], buf[1]);
-}
-
-static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg)
+static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg)
 {
        int ret;
        u8 b0[] = { reg };
        u8 b1[] = { 0 };
-       u8 addr = (tuner == 0) ? state->config->tuner_addr :
-               state->config->demod_addr;
+
        struct i2c_msg msg[] = {
                {
-                       .addr = addr,
+                       .addr = state->config->demod_addr,
                        .flags = 0,
                        .buf = b0,
                        .len = 1
                }, {
-                       .addr = addr,
+                       .addr = state->config->demod_addr,
                        .flags = I2C_M_RD,
                        .buf = b1,
                        .len = 1
@@ -136,18 +110,6 @@ static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg)
        return b1[0];
 }
 
-static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)
-{
-       return m88rs2000_readreg(state, 1, reg);
-}
-
-static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg)
-{
-       m88rs2000_demod_write(state, 0x81, 0x85);
-       udelay(10);
-       return m88rs2000_readreg(state, 0, reg);
-}
-
 static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
 {
        struct m88rs2000_state *state = fe->demodulator_priv;
@@ -166,9 +128,9 @@ static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
        b[0] = (u8) (temp >> 16) & 0xff;
        b[1] = (u8) (temp >> 8) & 0xff;
        b[2] = (u8) temp & 0xff;
-       ret = m88rs2000_demod_write(state, 0x93, b[2]);
-       ret |= m88rs2000_demod_write(state, 0x94, b[1]);
-       ret |= m88rs2000_demod_write(state, 0x95, b[0]);
+       ret = m88rs2000_writereg(state, 0x93, b[2]);
+       ret |= m88rs2000_writereg(state, 0x94, b[1]);
+       ret |= m88rs2000_writereg(state, 0x95, b[0]);
 
        deb_info("m88rs2000: m88rs2000_set_symbolrate\n");
        return ret;
@@ -182,37 +144,37 @@ static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
        int i;
        u8 reg;
        deb_info("%s\n", __func__);
-       m88rs2000_demod_write(state, 0x9a, 0x30);
-       reg = m88rs2000_demod_read(state, 0xb2);
+       m88rs2000_writereg(state, 0x9a, 0x30);
+       reg = m88rs2000_readreg(state, 0xb2);
        reg &= 0x3f;
-       m88rs2000_demod_write(state, 0xb2, reg);
+       m88rs2000_writereg(state, 0xb2, reg);
        for (i = 0; i <  m->msg_len; i++)
-               m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]);
+               m88rs2000_writereg(state, 0xb3 + i, m->msg[i]);
 
-       reg = m88rs2000_demod_read(state, 0xb1);
+       reg = m88rs2000_readreg(state, 0xb1);
        reg &= 0x87;
        reg |= ((m->msg_len - 1) << 3) | 0x07;
        reg &= 0x7f;
-       m88rs2000_demod_write(state, 0xb1, reg);
+       m88rs2000_writereg(state, 0xb1, reg);
 
        for (i = 0; i < 15; i++) {
-               if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0)
+               if ((m88rs2000_readreg(state, 0xb1) & 0x40) == 0x0)
                        break;
                msleep(20);
        }
 
-       reg = m88rs2000_demod_read(state, 0xb1);
+       reg = m88rs2000_readreg(state, 0xb1);
        if ((reg & 0x40) > 0x0) {
                reg &= 0x7f;
                reg |= 0x40;
-               m88rs2000_demod_write(state, 0xb1, reg);
+               m88rs2000_writereg(state, 0xb1, reg);
        }
 
-       reg = m88rs2000_demod_read(state, 0xb2);
+       reg = m88rs2000_readreg(state, 0xb2);
        reg &= 0x3f;
        reg |= 0x80;
-       m88rs2000_demod_write(state, 0xb2, reg);
-       m88rs2000_demod_write(state, 0x9a, 0xb0);
+       m88rs2000_writereg(state, 0xb2, reg);
+       m88rs2000_writereg(state, 0x9a, 0xb0);
 
 
        return 0;
@@ -224,14 +186,14 @@ static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
        struct m88rs2000_state *state = fe->demodulator_priv;
        u8 reg0, reg1;
        deb_info("%s\n", __func__);
-       m88rs2000_demod_write(state, 0x9a, 0x30);
+       m88rs2000_writereg(state, 0x9a, 0x30);
        msleep(50);
-       reg0 = m88rs2000_demod_read(state, 0xb1);
-       reg1 = m88rs2000_demod_read(state, 0xb2);
+       reg0 = m88rs2000_readreg(state, 0xb1);
+       reg1 = m88rs2000_readreg(state, 0xb2);
        /* TODO complete this section */
-       m88rs2000_demod_write(state, 0xb2, reg1);
-       m88rs2000_demod_write(state, 0xb1, reg0);
-       m88rs2000_demod_write(state, 0x9a, 0xb0);
+       m88rs2000_writereg(state, 0xb2, reg1);
+       m88rs2000_writereg(state, 0xb1, reg0);
+       m88rs2000_writereg(state, 0x9a, 0xb0);
 
        return 0;
 }
@@ -240,9 +202,9 @@ static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
        struct m88rs2000_state *state = fe->demodulator_priv;
        u8 reg0, reg1;
-       m88rs2000_demod_write(state, 0x9a, 0x30);
-       reg0 = m88rs2000_demod_read(state, 0xb1);
-       reg1 = m88rs2000_demod_read(state, 0xb2);
+       m88rs2000_writereg(state, 0x9a, 0x30);
+       reg0 = m88rs2000_readreg(state, 0xb1);
+       reg1 = m88rs2000_readreg(state, 0xb2);
 
        reg1 &= 0x3f;
 
@@ -257,9 +219,9 @@ static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
        default:
                break;
        }
-       m88rs2000_demod_write(state, 0xb2, reg1);
-       m88rs2000_demod_write(state, 0xb1, reg0);
-       m88rs2000_demod_write(state, 0x9a, 0xb0);
+       m88rs2000_writereg(state, 0xb2, reg1);
+       m88rs2000_writereg(state, 0xb1, reg0);
+       m88rs2000_writereg(state, 0x9a, 0xb0);
        return 0;
 }
 
@@ -276,14 +238,6 @@ struct inittab m88rs2000_setup[] = {
        {DEMOD_WRITE, 0x00, 0x00},
        {DEMOD_WRITE, 0x9a, 0xb0},
        {DEMOD_WRITE, 0x81, 0xc1},
-       {TUNER_WRITE, 0x42, 0x73},
-       {TUNER_WRITE, 0x05, 0x07},
-       {TUNER_WRITE, 0x20, 0x27},
-       {TUNER_WRITE, 0x07, 0x02},
-       {TUNER_WRITE, 0x11, 0xff},
-       {TUNER_WRITE, 0x60, 0xf9},
-       {TUNER_WRITE, 0x08, 0x01},
-       {TUNER_WRITE, 0x00, 0x41},
        {DEMOD_WRITE, 0x81, 0x81},
        {DEMOD_WRITE, 0x86, 0xc6},
        {DEMOD_WRITE, 0x9a, 0x30},
@@ -301,23 +255,10 @@ struct inittab m88rs2000_shutdown[] = {
        {DEMOD_WRITE, 0xf1, 0x89},
        {DEMOD_WRITE, 0x00, 0x01},
        {DEMOD_WRITE, 0x9a, 0xb0},
-       {TUNER_WRITE, 0x00, 0x40},
        {DEMOD_WRITE, 0x81, 0x81},
        {0xff, 0xaa, 0xff}
 };
 
-struct inittab tuner_reset[] = {
-       {TUNER_WRITE, 0x42, 0x73},
-       {TUNER_WRITE, 0x05, 0x07},
-       {TUNER_WRITE, 0x20, 0x27},
-       {TUNER_WRITE, 0x07, 0x02},
-       {TUNER_WRITE, 0x11, 0xff},
-       {TUNER_WRITE, 0x60, 0xf9},
-       {TUNER_WRITE, 0x08, 0x01},
-       {TUNER_WRITE, 0x00, 0x41},
-       {0xff, 0xaa, 0xff}
-};
-
 struct inittab fe_reset[] = {
        {DEMOD_WRITE, 0x00, 0x01},
        {DEMOD_WRITE, 0xf1, 0xbf},
@@ -389,11 +330,7 @@ static int m88rs2000_tab_set(struct m88rs2000_state *state,
        for (i = 0; i < 255; i++) {
                switch (tab[i].cmd) {
                case 0x01:
-                       ret = m88rs2000_demod_write(state, tab[i].reg,
-                               tab[i].val);
-                       break;
-               case 0x02:
-                       ret = m88rs2000_tuner_write(state, tab[i].reg,
+                       ret = m88rs2000_writereg(state, tab[i].reg,
                                tab[i].val);
                        break;
                case 0x10:
@@ -419,7 +356,7 @@ static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
        struct m88rs2000_state *state = fe->demodulator_priv;
        u8 data;
 
-       data = m88rs2000_demod_read(state, 0xb2);
+       data = m88rs2000_readreg(state, 0xb2);
        data |= 0x03; /* bit0 V/H, bit1 off/on */
 
        switch (volt) {
@@ -434,23 +371,11 @@ static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
                break;
        }
 
-       m88rs2000_demod_write(state, 0xb2, data);
+       m88rs2000_writereg(state, 0xb2, data);
 
        return 0;
 }
 
-static int m88rs2000_startup(struct m88rs2000_state *state)
-{
-       int ret = 0;
-       u8 reg;
-
-       reg = m88rs2000_tuner_read(state, 0x00);
-       if ((reg & 0x40) == 0)
-               ret = -ENODEV;
-
-       return ret;
-}
-
 static int m88rs2000_init(struct dvb_frontend *fe)
 {
        struct m88rs2000_state *state = fe->demodulator_priv;
@@ -479,7 +404,7 @@ static int m88rs2000_sleep(struct dvb_frontend *fe)
 static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct m88rs2000_state *state = fe->demodulator_priv;
-       u8 reg = m88rs2000_demod_read(state, 0x8c);
+       u8 reg = m88rs2000_readreg(state, 0x8c);
 
        *status = 0;
 
@@ -497,23 +422,23 @@ static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber)
        struct m88rs2000_state *state = fe->demodulator_priv;
        u8 tmp0, tmp1;
 
-       m88rs2000_demod_write(state, 0x9a, 0x30);
-       tmp0 = m88rs2000_demod_read(state, 0xd8);
+       m88rs2000_writereg(state, 0x9a, 0x30);
+       tmp0 = m88rs2000_readreg(state, 0xd8);
        if ((tmp0 & 0x10) != 0) {
-               m88rs2000_demod_write(state, 0x9a, 0xb0);
+               m88rs2000_writereg(state, 0x9a, 0xb0);
                *ber = 0xffffffff;
                return 0;
        }
 
-       *ber = (m88rs2000_demod_read(state, 0xd7) << 8) |
-               m88rs2000_demod_read(state, 0xd6);
+       *ber = (m88rs2000_readreg(state, 0xd7) << 8) |
+               m88rs2000_readreg(state, 0xd6);
 
-       tmp1 = m88rs2000_demod_read(state, 0xd9);
-       m88rs2000_demod_write(state, 0xd9, (tmp1 & ~7) | 4);
+       tmp1 = m88rs2000_readreg(state, 0xd9);
+       m88rs2000_writereg(state, 0xd9, (tmp1 & ~7) | 4);
        /* needs twice */
-       m88rs2000_demod_write(state, 0xd8, (tmp0 & ~8) | 0x30);
-       m88rs2000_demod_write(state, 0xd8, (tmp0 & ~8) | 0x30);
-       m88rs2000_demod_write(state, 0x9a, 0xb0);
+       m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30);
+       m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30);
+       m88rs2000_writereg(state, 0x9a, 0xb0);
 
        return 0;
 }
@@ -529,7 +454,7 @@ static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct m88rs2000_state *state = fe->demodulator_priv;
 
-       *snr = 512 * m88rs2000_demod_read(state, 0x65);
+       *snr = 512 * m88rs2000_readreg(state, 0x65);
 
        return 0;
 }
@@ -539,166 +464,17 @@ static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
        struct m88rs2000_state *state = fe->demodulator_priv;
        u8 tmp;
 
-       *ucblocks = (m88rs2000_demod_read(state, 0xd5) << 8) |
-                       m88rs2000_demod_read(state, 0xd4);
-       tmp = m88rs2000_demod_read(state, 0xd8);
-       m88rs2000_demod_write(state, 0xd8, tmp & ~0x20);
+       *ucblocks = (m88rs2000_readreg(state, 0xd5) << 8) |
+                       m88rs2000_readreg(state, 0xd4);
+       tmp = m88rs2000_readreg(state, 0xd8);
+       m88rs2000_writereg(state, 0xd8, tmp & ~0x20);
        /* needs two times */
-       m88rs2000_demod_write(state, 0xd8, tmp | 0x20);
-       m88rs2000_demod_write(state, 0xd8, tmp | 0x20);
+       m88rs2000_writereg(state, 0xd8, tmp | 0x20);
+       m88rs2000_writereg(state, 0xd8, tmp | 0x20);
 
        return 0;
 }
 
-static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset)
-{
-       int ret;
-       ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset);
-       ret |= m88rs2000_tuner_write(state, 0x51, 0x1f);
-       ret |= m88rs2000_tuner_write(state, 0x50, offset);
-       ret |= m88rs2000_tuner_write(state, 0x50, 0x00);
-       msleep(20);
-       return ret;
-}
-
-static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe)
-{
-       struct m88rs2000_state *state = fe->demodulator_priv;
-       int reg;
-       reg = m88rs2000_tuner_read(state, 0x3d);
-       reg &= 0x7f;
-       if (reg < 0x16)
-               reg = 0xa1;
-       else if (reg == 0x16)
-               reg = 0x99;
-       else
-               reg = 0xf9;
-
-       m88rs2000_tuner_write(state, 0x60, reg);
-       reg = m88rs2000_tuner_gate_ctrl(state, 0x08);
-
-       if (fe->ops.i2c_gate_ctrl)
-                       fe->ops.i2c_gate_ctrl(fe, 0);
-       return reg;
-}
-
-static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset)
-{
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct m88rs2000_state *state = fe->demodulator_priv;
-       int ret;
-       u32 frequency = c->frequency;
-       s32 offset_khz;
-       s32 tmp;
-       u32 symbol_rate = (c->symbol_rate / 1000);
-       u32 f3db, gdiv28;
-       u16 value, ndiv, lpf_coeff;
-       u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
-       u8 lo = 0x01, div4 = 0x0;
-
-       /* Reset Tuner */
-       ret = m88rs2000_tab_set(state, tuner_reset);
-
-       /* Calculate frequency divider */
-       if (frequency < 1060000) {
-               lo |= 0x10;
-               div4 = 0x1;
-               ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ;
-       } else
-               ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ;
-       ndiv = ndiv + ndiv % 2;
-       ndiv = ndiv - 1024;
-
-       ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo);
-
-       /* Set frequency divider */
-       ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf);
-       ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff);
-
-       ret |= m88rs2000_tuner_write(state, 0x03, 0x06);
-       ret |= m88rs2000_tuner_gate_ctrl(state, 0x10);
-       if (ret < 0)
-               return -ENODEV;
-
-       /* Tuner Frequency Range */
-       ret = m88rs2000_tuner_write(state, 0x10, lo);
-
-       ret |= m88rs2000_tuner_gate_ctrl(state, 0x08);
-
-       /* Tuner RF */
-       ret |= m88rs2000_set_tuner_rf(fe);
-
-       gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000;
-       ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff);
-       ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
-       if (ret < 0)
-               return -ENODEV;
-
-       value = m88rs2000_tuner_read(state, 0x26);
-
-       f3db = (symbol_rate * 135) / 200 + 2000;
-       f3db += FREQ_OFFSET_LOW_SYM_RATE;
-       if (f3db < 7000)
-               f3db = 7000;
-       if (f3db > 40000)
-               f3db = 40000;
-
-       gdiv28 = gdiv28 * 207 / (value * 2 + 151);
-       mlpf_max = gdiv28 * 135 / 100;
-       mlpf_min = gdiv28 * 78 / 100;
-       if (mlpf_max > 63)
-               mlpf_max = 63;
-
-       lpf_coeff = 2766;
-
-       nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
-               (FE_CRYSTAL_KHZ / 1000)  + 1) / 2;
-       if (nlpf > 23)
-               nlpf = 23;
-       if (nlpf < 1)
-               nlpf = 1;
-
-       lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
-               * lpf_coeff * 2  / f3db + 1) / 2;
-
-       if (lpf_mxdiv < mlpf_min) {
-               nlpf++;
-               lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
-                       * lpf_coeff * 2  / f3db + 1) / 2;
-       }
-
-       if (lpf_mxdiv > mlpf_max)
-               lpf_mxdiv = mlpf_max;
-
-       ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv);
-       ret |= m88rs2000_tuner_write(state, 0x06, nlpf);
-
-       ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
-
-       ret |= m88rs2000_tuner_gate_ctrl(state, 0x01);
-
-       msleep(80);
-       /* calculate offset assuming 96000kHz*/
-       offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ
-               / 14 / (div4 + 1) / 2;
-
-       offset_khz -= frequency;
-
-       tmp = offset_khz;
-       tmp *= 65536;
-
-       tmp = (2 * tmp + 96000) / (2 * 96000);
-       if (tmp < 0)
-               tmp += 65536;
-
-       *offset = tmp & 0xffff;
-
-       if (fe->ops.i2c_gate_ctrl)
-                       fe->ops.i2c_gate_ctrl(fe, 0);
-
-       return (ret < 0) ? -EINVAL : 0;
-}
-
 static int m88rs2000_set_fec(struct m88rs2000_state *state,
                fe_code_rate_t fec)
 {
@@ -724,7 +500,7 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state,
        default:
                fec_set = 0x08;
        }
-       m88rs2000_demod_write(state, 0x76, fec_set);
+       m88rs2000_writereg(state, 0x76, fec_set);
 
        return 0;
 }
@@ -733,9 +509,9 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state,
 static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state)
 {
        u8 reg;
-       m88rs2000_demod_write(state, 0x9a, 0x30);
-       reg = m88rs2000_demod_read(state, 0x76);
-       m88rs2000_demod_write(state, 0x9a, 0xb0);
+       m88rs2000_writereg(state, 0x9a, 0x30);
+       reg = m88rs2000_readreg(state, 0x76);
+       m88rs2000_writereg(state, 0x9a, 0xb0);
 
        switch (reg) {
        case 0x88:
@@ -761,7 +537,9 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
        struct m88rs2000_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        fe_status_t status;
-       int i, ret;
+       int i, ret = 0;
+       s32 tmp;
+       u32 tuner_freq;
        u16 offset = 0;
        u8 reg;
 
@@ -775,17 +553,37 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
        }
 
        /* Set Tuner */
-       ret = m88rs2000_set_tuner(fe, &offset);
+       if (fe->ops.tuner_ops.set_params)
+               ret = fe->ops.tuner_ops.set_params(fe);
+
+       if (ret < 0)
+               return -ENODEV;
+
+       if (fe->ops.tuner_ops.get_frequency)
+               ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_freq);
+
        if (ret < 0)
                return -ENODEV;
 
-       ret = m88rs2000_demod_write(state, 0x9a, 0x30);
+       offset = tuner_freq - c->frequency;
+
+       /* calculate offset assuming 96000kHz*/
+       tmp = offset;
+       tmp *= 65536;
+
+       tmp = (2 * tmp + 96000) / (2 * 96000);
+       if (tmp < 0)
+               tmp += 65536;
+
+       offset = tmp & 0xffff;
+
+       ret = m88rs2000_writereg(state, 0x9a, 0x30);
        /* Unknown usually 0xc6 sometimes 0xc1 */
-       reg = m88rs2000_demod_read(state, 0x86);
-       ret |= m88rs2000_demod_write(state, 0x86, reg);
+       reg = m88rs2000_readreg(state, 0x86);
+       ret |= m88rs2000_writereg(state, 0x86, reg);
        /* Offset lower nibble always 0 */
-       ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8));
-       ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0);
+       ret |= m88rs2000_writereg(state, 0x9c, (offset >> 8));
+       ret |= m88rs2000_writereg(state, 0x9d, offset & 0xf0);
 
 
        /* Reset Demod */
@@ -794,16 +592,16 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
                return -ENODEV;
 
        /* Unknown */
-       reg = m88rs2000_demod_read(state, 0x70);
-       ret = m88rs2000_demod_write(state, 0x70, reg);
+       reg = m88rs2000_readreg(state, 0x70);
+       ret = m88rs2000_writereg(state, 0x70, reg);
 
        /* Set FEC */
        ret |= m88rs2000_set_fec(state, c->fec_inner);
-       ret |= m88rs2000_demod_write(state, 0x85, 0x1);
-       ret |= m88rs2000_demod_write(state, 0x8a, 0xbf);
-       ret |= m88rs2000_demod_write(state, 0x8d, 0x1e);
-       ret |= m88rs2000_demod_write(state, 0x90, 0xf1);
-       ret |= m88rs2000_demod_write(state, 0x91, 0x08);
+       ret |= m88rs2000_writereg(state, 0x85, 0x1);
+       ret |= m88rs2000_writereg(state, 0x8a, 0xbf);
+       ret |= m88rs2000_writereg(state, 0x8d, 0x1e);
+       ret |= m88rs2000_writereg(state, 0x90, 0xf1);
+       ret |= m88rs2000_writereg(state, 0x91, 0x08);
 
        if (ret < 0)
                return -ENODEV;
@@ -819,27 +617,25 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
                return -ENODEV;
 
        for (i = 0; i < 25; i++) {
-               reg = m88rs2000_demod_read(state, 0x8c);
+               reg = m88rs2000_readreg(state, 0x8c);
                if ((reg & 0x7) == 0x7) {
                        status = FE_HAS_LOCK;
                        break;
                }
                state->no_lock_count++;
                if (state->no_lock_count == 15) {
-                       reg = m88rs2000_demod_read(state, 0x70);
+                       reg = m88rs2000_readreg(state, 0x70);
                        reg ^= 0x4;
-                       m88rs2000_demod_write(state, 0x70, reg);
+                       m88rs2000_writereg(state, 0x70, reg);
                        state->no_lock_count = 0;
                }
-               if (state->no_lock_count == 20)
-                       m88rs2000_set_tuner_rf(fe);
                msleep(20);
        }
 
        if (status & FE_HAS_LOCK) {
                state->fec_inner = m88rs2000_get_fec(state);
                /* Uknown suspect SNR level */
-               reg = m88rs2000_demod_read(state, 0x65);
+               reg = m88rs2000_readreg(state, 0x65);
        }
 
        state->tuner_frequency = c->frequency;
@@ -862,9 +658,9 @@ static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        struct m88rs2000_state *state = fe->demodulator_priv;
 
        if (enable)
-               m88rs2000_demod_write(state, 0x81, 0x84);
+               m88rs2000_writereg(state, 0x81, 0x84);
        else
-               m88rs2000_demod_write(state, 0x81, 0x81);
+               m88rs2000_writereg(state, 0x81, 0x81);
        udelay(10);
        return 0;
 }
@@ -895,7 +691,6 @@ static struct dvb_frontend_ops m88rs2000_ops = {
        .release = m88rs2000_release,
        .init = m88rs2000_init,
        .sleep = m88rs2000_sleep,
-       .write = m88rs2000_write,
        .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl,
        .read_status = m88rs2000_read_status,
        .read_ber = m88rs2000_read_ber,
@@ -928,9 +723,6 @@ struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config,
        state->symbol_rate = 0;
        state->fec_inner = 0;
 
-       if (m88rs2000_startup(state) < 0)
-               goto error;
-
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &m88rs2000_ops,
                        sizeof(struct dvb_frontend_ops));
index 59acdb69687335f92726ec0636d580d036ccd5d6..5a8023e5a4b8b2f728f7439f02a773a9f12edaf4 100644 (file)
@@ -26,8 +26,6 @@
 struct m88rs2000_config {
        /* Demodulator i2c address */
        u8 demod_addr;
-       /* Tuner address */
-       u8 tuner_addr;
 
        u8 *inittab;
 
@@ -55,12 +53,8 @@ static inline struct dvb_frontend *m88rs2000_attach(
 }
 #endif /* CONFIG_DVB_M88RS2000 */
 
-#define FE_CRYSTAL_KHZ 27000
-#define FREQ_OFFSET_LOW_SYM_RATE 3000
-
 enum {
        DEMOD_WRITE = 0x1,
-       TUNER_WRITE,
        WRITE_DELAY = 0x10,
 };
 #endif /* M88RS2000_H */
index 73010ecb9866052d9cfc4af6d8bc6181281456ad..94e3fe21eefbf0be4f2ed69dc976399a7d5c150f 100644 (file)
 #include "ts2020.h"
 
 #define TS2020_XTAL_FREQ   27000 /* in kHz */
+#define FREQ_OFFSET_LOW_SYM_RATE 3000
 
-struct ts2020_state {
-       u8 tuner_address;
+struct ts2020_priv {
+       /* i2c details */
+       int i2c_address;
        struct i2c_adapter *i2c;
+       u8 clk_out_div;
+       u32 frequency;
 };
 
-static int ts2020_readreg(struct dvb_frontend *fe, u8 reg)
+static int ts2020_release(struct dvb_frontend *fe)
 {
-       struct ts2020_state *state = fe->tuner_priv;
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int ts2020_writereg(struct dvb_frontend *fe, int reg, int data)
+{
+       struct ts2020_priv *priv = fe->tuner_priv;
+       u8 buf[] = { reg, data };
+       struct i2c_msg msg[] = {
+               {
+                       .addr = priv->i2c_address,
+                       .flags = 0,
+                       .buf = buf,
+                       .len = 2
+               }
+       };
+       int err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       err = i2c_transfer(priv->i2c, msg, 1);
+       if (err != 1) {
+               printk(KERN_ERR
+                      "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
+                      __func__, err, reg, data);
+               return -EREMOTEIO;
+       }
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+}
+
+static int ts2020_readreg(struct dvb_frontend *fe, u8 reg)
+{
+       struct ts2020_priv *priv = fe->tuner_priv;
        int ret;
        u8 b0[] = { reg };
        u8 b1[] = { 0 };
        struct i2c_msg msg[] = {
                {
-                       .addr = state->tuner_address,
+                       .addr = priv->i2c_address,
                        .flags = 0,
                        .buf = b0,
                        .len = 1
                }, {
-                       .addr = state->tuner_address,
+                       .addr = priv->i2c_address,
                        .flags = I2C_M_RD,
                        .buf = b1,
                        .len = 1
@@ -53,212 +94,202 @@ static int ts2020_readreg(struct dvb_frontend *fe, u8 reg)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
 
-       ret = i2c_transfer(state->i2c, msg, 2);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
+       ret = i2c_transfer(priv->i2c, msg, 2);
 
        if (ret != 2) {
-               printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
+               printk(KERN_ERR "%s: reg=0x%x(error=%d)\n",
+                      __func__, reg, ret);
                return ret;
        }
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
        return b1[0];
 }
 
-static int ts2020_writereg(struct dvb_frontend *fe, int reg, int data)
+static int ts2020_sleep(struct dvb_frontend *fe)
 {
-       struct ts2020_state *state = fe->tuner_priv;
-
-       u8 buf[] = { reg, data };
-       struct i2c_msg msg = { .addr = state->tuner_address,
-               .flags = 0, .buf = buf, .len = 2 };
-       int err;
-
+       struct ts2020_priv *priv = fe->tuner_priv;
+       int ret;
+       u8 buf[] = { 10, 0 };
+       struct i2c_msg msg = {
+               .addr = priv->i2c_address,
+               .flags = 0,
+               .buf = buf,
+               .len = 2
+       };
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
 
-       err = i2c_transfer(state->i2c, &msg, 1);
+       ret = i2c_transfer(priv->i2c, &msg, 1);
+       if (ret != 1)
+               printk(KERN_ERR "%s: i2c error\n", __func__);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0);
 
-       if (err != 1) {
-               printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
-                        " value == 0x%02x)\n", __func__, err, reg, data);
-               return -EREMOTEIO;
-       }
-
-       return 0;
+       return (ret == 1) ? 0 : ret;
 }
 
 static int ts2020_init(struct dvb_frontend *fe)
 {
+       struct ts2020_priv *priv = fe->tuner_priv;
+
        ts2020_writereg(fe, 0x42, 0x73);
-       ts2020_writereg(fe, 0x05, 0x01);
-       ts2020_writereg(fe, 0x62, 0xf5);
+       ts2020_writereg(fe, 0x05, priv->clk_out_div);
+       ts2020_writereg(fe, 0x20, 0x27);
+       ts2020_writereg(fe, 0x07, 0x02);
+       ts2020_writereg(fe, 0x11, 0xff);
+       ts2020_writereg(fe, 0x60, 0xf9);
+       ts2020_writereg(fe, 0x08, 0x01);
+       ts2020_writereg(fe, 0x00, 0x41);
+
        return 0;
 }
 
-static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+static int ts2020_tuner_gate_ctrl(struct dvb_frontend *fe, u8 offset)
 {
-       u16 ndiv, div4;
+       int ret;
+       ret = ts2020_writereg(fe, 0x51, 0x1f - offset);
+       ret |= ts2020_writereg(fe, 0x51, 0x1f);
+       ret |= ts2020_writereg(fe, 0x50, offset);
+       ret |= ts2020_writereg(fe, 0x50, 0x00);
+       msleep(20);
+       return ret;
+}
 
-       div4 = (ts2020_readreg(fe, 0x10) & 0x10) >> 4;
+static int ts2020_set_tuner_rf(struct dvb_frontend *fe)
+{
+       int reg;
 
-       ndiv = ts2020_readreg(fe, 0x01);
-       ndiv &= 0x0f;
-       ndiv <<= 8;
-       ndiv |= ts2020_readreg(fe, 0x02);
+       reg = ts2020_readreg(fe, 0x3d);
+       reg &= 0x7f;
+       if (reg < 0x16)
+               reg = 0xa1;
+       else if (reg == 0x16)
+               reg = 0x99;
+       else
+               reg = 0xf9;
 
-       /* actual tuned frequency, i.e. including the offset */
-       *frequency = (ndiv - ndiv % 2 + 1024) * TS2020_XTAL_FREQ
-               / (6 + 8) / (div4 + 1) / 2;
+       ts2020_writereg(fe, 0x60, reg);
+       reg = ts2020_tuner_gate_ctrl(fe, 0x08);
 
-       return 0;
+       return reg;
 }
 
 static int ts2020_set_params(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct ts2020_priv *priv = fe->demodulator_priv;
+       int ret;
+       u32 frequency = c->frequency;
+       s32 offset_khz;
+       u32 symbol_rate = (c->symbol_rate / 1000);
+       u32 f3db, gdiv28;
+       u16 value, ndiv, lpf_coeff;
+       u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
+       u8 lo = 0x01, div4 = 0x0;
+
+       /* Calculate frequency divider */
+       if (frequency < 1060000) {
+               lo |= 0x10;
+               div4 = 0x1;
+               ndiv = (frequency * 14 * 4) / TS2020_XTAL_FREQ;
+       } else
+               ndiv = (frequency * 14 * 2) / TS2020_XTAL_FREQ;
+       ndiv = ndiv + ndiv % 2;
+       ndiv = ndiv - 1024;
+
+       ret = ts2020_writereg(fe, 0x10, 0x80 | lo);
+
+       /* Set frequency divider */
+       ret |= ts2020_writereg(fe, 0x01, (ndiv >> 8) & 0xf);
+       ret |= ts2020_writereg(fe, 0x02, ndiv & 0xff);
+
+       ret |= ts2020_writereg(fe, 0x03, 0x06);
+       ret |= ts2020_tuner_gate_ctrl(fe, 0x10);
+       if (ret < 0)
+               return -ENODEV;
+
+       /* Tuner Frequency Range */
+       ret = ts2020_writereg(fe, 0x10, lo);
+
+       ret |= ts2020_tuner_gate_ctrl(fe, 0x08);
+
+       /* Tuner RF */
+       ret |= ts2020_set_tuner_rf(fe);
+
+       gdiv28 = (TS2020_XTAL_FREQ / 1000 * 1694 + 500) / 1000;
+       ret |= ts2020_writereg(fe, 0x04, gdiv28 & 0xff);
+       ret |= ts2020_tuner_gate_ctrl(fe, 0x04);
+       if (ret < 0)
+               return -ENODEV;
 
-       u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf;
-       u16 value, ndiv;
-       u32 srate = 0, f3db;
-
-       ts2020_init(fe);
-
-       /* unknown */
-       ts2020_writereg(fe, 0x07, 0x02);
-       ts2020_writereg(fe, 0x10, 0x00);
-       ts2020_writereg(fe, 0x60, 0x79);
-       ts2020_writereg(fe, 0x08, 0x01);
-       ts2020_writereg(fe, 0x00, 0x01);
-
-       /* calculate and set freq divider */
-       if (c->frequency < 1146000) {
-               ts2020_writereg(fe, 0x10, 0x11);
-               ndiv = ((c->frequency * (6 + 8) * 4) +
-                               (TS2020_XTAL_FREQ / 2)) /
-                               TS2020_XTAL_FREQ - 1024;
-       } else {
-               ts2020_writereg(fe, 0x10, 0x01);
-               ndiv = ((c->frequency * (6 + 8) * 2) +
-                               (TS2020_XTAL_FREQ / 2)) /
-                               TS2020_XTAL_FREQ - 1024;
-       }
-
-       ts2020_writereg(fe, 0x01, (ndiv & 0x0f00) >> 8);
-       ts2020_writereg(fe, 0x02, ndiv & 0x00ff);
-
-       /* set pll */
-       ts2020_writereg(fe, 0x03, 0x06);
-       ts2020_writereg(fe, 0x51, 0x0f);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x10);
-       ts2020_writereg(fe, 0x50, 0x00);
-       msleep(5);
-
-       /* unknown */
-       ts2020_writereg(fe, 0x51, 0x17);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x08);
-       ts2020_writereg(fe, 0x50, 0x00);
-       msleep(5);
-
-       value = ts2020_readreg(fe, 0x3d);
-       value &= 0x0f;
-       if ((value > 4) && (value < 15)) {
-               value -= 3;
-               if (value < 4)
-                       value = 4;
-               value = ((value << 3) | 0x01) & 0x79;
-       }
+       value = ts2020_readreg(fe, 0x26);
 
-       ts2020_writereg(fe, 0x60, value);
-       ts2020_writereg(fe, 0x51, 0x17);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x08);
-       ts2020_writereg(fe, 0x50, 0x00);
-
-       /* set low-pass filter period */
-       ts2020_writereg(fe, 0x04, 0x2e);
-       ts2020_writereg(fe, 0x51, 0x1b);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x04);
-       ts2020_writereg(fe, 0x50, 0x00);
-       msleep(5);
-
-       srate = c->symbol_rate / 1000;
-
-       f3db = (srate << 2) / 5 + 2000;
-       if (srate < 5000)
-               f3db += 3000;
+       f3db = (symbol_rate * 135) / 200 + 2000;
+       f3db += FREQ_OFFSET_LOW_SYM_RATE;
        if (f3db < 7000)
                f3db = 7000;
        if (f3db > 40000)
                f3db = 40000;
 
-       /* set low-pass filter baseband */
-       value = ts2020_readreg(fe, 0x26);
-       mlpf = 0x2e * 207 / ((value << 1) + 151);
-       mlpf_max = mlpf * 135 / 100;
-       mlpf_min = mlpf * 78 / 100;
+       gdiv28 = gdiv28 * 207 / (value * 2 + 151);
+       mlpf_max = gdiv28 * 135 / 100;
+       mlpf_min = gdiv28 * 78 / 100;
        if (mlpf_max > 63)
                mlpf_max = 63;
 
-       /* rounded to the closest integer */
-       nlpf = ((mlpf * f3db * 1000) + (2766 * TS2020_XTAL_FREQ / 2))
-                       / (2766 * TS2020_XTAL_FREQ);
+       lpf_coeff = 2766;
+
+       nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
+               (TS2020_XTAL_FREQ / 1000)  + 1) / 2;
        if (nlpf > 23)
                nlpf = 23;
        if (nlpf < 1)
                nlpf = 1;
 
-       /* rounded to the closest integer */
-       mlpf_new = ((TS2020_XTAL_FREQ * nlpf * 2766) +
-                       (1000 * f3db / 2)) / (1000 * f3db);
+       lpf_mxdiv = (nlpf * (TS2020_XTAL_FREQ / 1000)
+               * lpf_coeff * 2  / f3db + 1) / 2;
 
-       if (mlpf_new < mlpf_min) {
+       if (lpf_mxdiv < mlpf_min) {
                nlpf++;
-               mlpf_new = ((TS2020_XTAL_FREQ * nlpf * 2766) +
-                               (1000 * f3db / 2)) / (1000 * f3db);
+               lpf_mxdiv = (nlpf * (TS2020_XTAL_FREQ / 1000)
+                       * lpf_coeff * 2  / f3db + 1) / 2;
        }
 
-       if (mlpf_new > mlpf_max)
-               mlpf_new = mlpf_max;
+       if (lpf_mxdiv > mlpf_max)
+               lpf_mxdiv = mlpf_max;
 
-       ts2020_writereg(fe, 0x04, mlpf_new);
-       ts2020_writereg(fe, 0x06, nlpf);
-       ts2020_writereg(fe, 0x51, 0x1b);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x04);
-       ts2020_writereg(fe, 0x50, 0x00);
-       msleep(5);
+       ret = ts2020_writereg(fe, 0x04, lpf_mxdiv);
+       ret |= ts2020_writereg(fe, 0x06, nlpf);
 
-       /* unknown */
-       ts2020_writereg(fe, 0x51, 0x1e);
-       ts2020_writereg(fe, 0x51, 0x1f);
-       ts2020_writereg(fe, 0x50, 0x01);
-       ts2020_writereg(fe, 0x50, 0x00);
-       msleep(60);
+       ret |= ts2020_tuner_gate_ctrl(fe, 0x04);
 
-       return 0;
-}
+       ret |= ts2020_tuner_gate_ctrl(fe, 0x01);
 
-static int ts2020_release(struct dvb_frontend *fe)
-{
-       struct ts2020_state *state = fe->tuner_priv;
+       msleep(80);
+       /* calculate offset assuming 96000kHz*/
+       offset_khz = (ndiv - ndiv % 2 + 1024) * TS2020_XTAL_FREQ
+               / (6 + 8) / (div4 + 1) / 2;
 
-       fe->tuner_priv = NULL;
-       kfree(state);
+       priv->frequency = offset_khz;
+
+       return (ret < 0) ? -EINVAL : 0;
+}
 
+static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct ts2020_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
        return 0;
 }
 
-static int ts2020_get_signal_strength(struct dvb_frontend *fe,
-       u16 *signal_strength)
+/* read TS2020 signal strength */
+static int ts2020_read_signal_strength(struct dvb_frontend *fe,
+                                               u16 *signal_strength)
 {
        u16 sig_reading, sig_strength;
        u8 rfgain, bbgain;
@@ -281,35 +312,57 @@ static int ts2020_get_signal_strength(struct dvb_frontend *fe,
        return 0;
 }
 
-static struct dvb_tuner_ops ts2020_ops = {
+static struct dvb_tuner_ops ts2020_tuner_ops = {
        .info = {
-               .name = "Montage Technology TS2020 Silicon Tuner",
+               .name = "TS2020",
                .frequency_min = 950000,
-               .frequency_max = 2150000,
+               .frequency_max = 2150000
        },
-
        .init = ts2020_init,
        .release = ts2020_release,
+       .sleep = ts2020_sleep,
        .set_params = ts2020_set_params,
        .get_frequency = ts2020_get_frequency,
-       .get_rf_strength = ts2020_get_signal_strength
+       .get_rf_strength = ts2020_read_signal_strength,
 };
 
 struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
-       const struct ts2020_config *config, struct i2c_adapter *i2c)
+                                       const struct ts2020_config *config,
+                                       struct i2c_adapter *i2c)
 {
-       struct ts2020_state *state = NULL;
+       struct ts2020_priv *priv = NULL;
+       u8 buf;
+
+       priv = kzalloc(sizeof(struct ts2020_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
 
-       /* allocate memory for the internal state */
-       state = kzalloc(sizeof(struct ts2020_state), GFP_KERNEL);
-       if (!state)
+       priv->i2c_address = config->tuner_address;
+       priv->i2c = i2c;
+       priv->clk_out_div = config->clk_out_div;
+       fe->tuner_priv = priv;
+
+       /* Wake Up the tuner */
+       if ((0x03 & ts2020_readreg(fe, 0x00)) == 0x00) {
+               ts2020_writereg(fe, 0x00, 0x01);
+               msleep(2);
+       }
+
+       ts2020_writereg(fe, 0x00, 0x03);
+       msleep(2);
+
+       /* Check the tuner version */
+       buf = ts2020_readreg(fe, 0x00);
+       if ((buf == 0x01) || (buf == 0x41) || (buf == 0x81))
+               printk(KERN_INFO "%s: Find tuner TS2020!\n", __func__);
+       else {
+               printk(KERN_ERR "%s: Read tuner reg[0] = %d\n", __func__, buf);
+               kfree(priv);
                return NULL;
+       }
 
-       /* setup the state */
-       state->tuner_address = config->tuner_address;
-       state->i2c = i2c;
-       fe->tuner_priv = state;
-       fe->ops.tuner_ops = ts2020_ops;
+       memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops,
+                               sizeof(struct dvb_tuner_ops));
        fe->ops.read_signal_strength = fe->ops.tuner_ops.get_rf_strength;
 
        return fe;
index 13a172dfd58209fbca8c52cf1f0b18c8eaaffafd..c7e64afa614a40f07cefca9bb107a5bb8ee909b9 100644 (file)
@@ -26,6 +26,7 @@
 
 struct ts2020_config {
        u8 tuner_address;
+       u8 clk_out_div;
 };
 
 #if defined(CONFIG_DVB_TS2020) || \
index a2ed0f759b0a1f9a7a4f76d4e2a192261c7a5db3..9c5ed10b2c5eb8e5d1c03897d2bf5813f68a41fa 100644 (file)
@@ -474,6 +474,7 @@ static struct ds3000_config tevii_ds3000_config = {
 
 static struct ts2020_config tevii_ts2020_config  = {
        .tuner_address = 0x60,
+       .clk_out_div = 1,
 };
 
 static struct cx24116_config dvbworld_cx24116_config = {
@@ -500,20 +501,20 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
 };
 
 static struct stv090x_config prof_8000_stv090x_config = {
-        .device                 = STV0903,
-        .demod_mode             = STV090x_SINGLE,
-        .clk_mode               = STV090x_CLK_EXT,
-        .xtal                   = 27000000,
-        .address                = 0x6A,
-        .ts1_mode               = STV090x_TSMODE_PARALLEL_PUNCTURED,
-        .repeater_level         = STV090x_RPTLEVEL_64,
-        .adc1_range             = STV090x_ADC_2Vpp,
-        .diseqc_envelope_mode   = false,
-
-        .tuner_get_frequency    = stb6100_get_frequency,
-        .tuner_set_frequency    = stb6100_set_frequency,
-        .tuner_set_bandwidth    = stb6100_set_bandwidth,
-        .tuner_get_bandwidth    = stb6100_get_bandwidth,
+       .device                 = STV0903,
+       .demod_mode             = STV090x_SINGLE,
+       .clk_mode               = STV090x_CLK_EXT,
+       .xtal                   = 27000000,
+       .address                = 0x6A,
+       .ts1_mode               = STV090x_TSMODE_PARALLEL_PUNCTURED,
+       .repeater_level         = STV090x_RPTLEVEL_64,
+       .adc1_range             = STV090x_ADC_2Vpp,
+       .diseqc_envelope_mode   = false,
+
+       .tuner_get_frequency    = stb6100_get_frequency,
+       .tuner_set_frequency    = stb6100_set_frequency,
+       .tuner_set_bandwidth    = stb6100_set_bandwidth,
+       .tuner_get_bandwidth    = stb6100_get_bandwidth,
 };
 
 static struct stb6100_config prof_8000_stb6100_config = {
index e085851d6872adef06ddecc86b662442f238080f..50b5ac5b3983a0b41d4ca852995268c8f24d7d20 100644 (file)
@@ -703,6 +703,7 @@ static struct ds3000_config tevii_ds3000_config = {
 
 static struct ts2020_config tevii_ts2020_config  = {
        .tuner_address = 0x60,
+       .clk_out_div = 1,
 };
 
 static const struct stv0900_config prof_7301_stv0900_config = {
index 79fe74aae1f9735f5d04bf13157ccf9a57272afd..c789e7c67e4ed3778bd12dc4164f24c11206d856 100644 (file)
@@ -852,6 +852,7 @@ static struct ds3000_config dvbworld_ds3000_config = {
 
 static struct ts2020_config dvbworld_ts2020_config  = {
        .tuner_address = 0x60,
+       .clk_out_div = 1,
 };
 
 static int __devinit frontend_init(struct dm1105_dev *dev)
index 834bfecbed73d59e11d6baf5d7a1c04816f6f7fb..3240d559ef7b4634d3467a7879e9d29e445117e4 100644 (file)
@@ -120,6 +120,7 @@ config DVB_USB_LME2510
        select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
        select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to support the LME DM04/QQBOX DVB-S USB2.0
 
index 6427ac359f21abda6447a38471c1c560d511dec0..b5e1f736eb7e0ae5b35839a23427be07fa2722b5 100644 (file)
@@ -81,6 +81,7 @@
 #include "dvb-pll.h"
 #include "z0194a.h"
 #include "m88rs2000.h"
+#include "ts2020.h"
 
 
 #define LME2510_C_S7395        "dvb-usb-lme2510c-s7395.fw";
@@ -944,10 +945,14 @@ static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe,
 
 static struct m88rs2000_config m88rs2000_config = {
        .demod_addr = 0xd0,
-       .tuner_addr = 0xc0,
        .set_ts_params = dm04_rs2000_set_ts_param,
 };
 
+static struct ts2020_config ts2020_config = {
+       .tuner_address = 0x60,
+       .clk_out_div = 7,
+};
+
 static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
                                        fe_sec_voltage_t voltage)
 {
@@ -1097,6 +1102,8 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
 
                if (adap->fe[0]) {
                        info("FE Found M88RS2000");
+                       dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
+                                       &d->i2c_adap);
                        st->i2c_tuner_gate_w = 5;
                        st->i2c_tuner_gate_r = 5;
                        st->i2c_tuner_addr = 0xc0;
index d8a5ebb436260d845905a69480a0fe2056184f7d..9578a6761f1bc72230eaed6a8b35500898ffb972 100644 (file)
@@ -29,6 +29,7 @@
 #include "stb6100.h"
 #include "stb6100_proc.h"
 #include "m88rs2000.h"
+#include "ts2020.h"
 
 #ifndef USB_PID_DW2102
 #define USB_PID_DW2102 0x2102
@@ -953,10 +954,12 @@ static struct ds3000_config dw2104_ds3000_config = {
 
 static struct ts2020_config dw2104_ts2020_config  = {
        .tuner_address = 0x60,
+       .clk_out_div = 1,
 };
 
 static struct ds3000_config s660_ds3000_config = {
        .demod_address = 0x68,
+       .ci_mode = 1,
        .set_lock_led = dw210x_led_ctrl,
 };
 
@@ -1009,10 +1012,7 @@ static struct stv0900_config prof_7500_stv0900_config = {
 static struct ds3000_config su3000_ds3000_config = {
        .demod_address = 0x68,
        .ci_mode = 1,
-};
-
-static struct ts2020_config su3000_ts2020_config  = {
-       .tuner_address = 0x60,
+       .set_lock_led = dw210x_led_ctrl,
 };
 
 static u8 m88rs2000_inittab[] = {
@@ -1022,14 +1022,6 @@ static u8 m88rs2000_inittab[] = {
        DEMOD_WRITE, 0x00, 0x00,
        DEMOD_WRITE, 0x9a, 0xb0,
        DEMOD_WRITE, 0x81, 0xc1,
-       TUNER_WRITE, 0x42, 0x73,
-       TUNER_WRITE, 0x05, 0x07,
-       TUNER_WRITE, 0x20, 0x27,
-       TUNER_WRITE, 0x07, 0x02,
-       TUNER_WRITE, 0x11, 0xff,
-       TUNER_WRITE, 0x60, 0xf9,
-       TUNER_WRITE, 0x08, 0x01,
-       TUNER_WRITE, 0x00, 0x41,
        DEMOD_WRITE, 0x81, 0x81,
        DEMOD_WRITE, 0x86, 0xc6,
        DEMOD_WRITE, 0x9a, 0x30,
@@ -1043,7 +1035,6 @@ static u8 m88rs2000_inittab[] = {
 
 static struct m88rs2000_config s421_m88rs2000_config = {
        .demod_addr = 0x68,
-       .tuner_addr = 0x60,
        .inittab = m88rs2000_inittab,
 };
 
@@ -1250,6 +1241,14 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
        if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
                err("command 0x0e transfer failed.");
 
+       obuf[0] = 0xe;
+       obuf[1] = 0x02;
+       obuf[2] = 1;
+
+       if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+               err("command 0x0e transfer failed.");
+       msleep(300);
+
        obuf[0] = 0xe;
        obuf[1] = 0x83;
        obuf[2] = 0;
@@ -1274,12 +1273,15 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
        if (d->fe_adap[0].fe == NULL)
                return -EIO;
 
-       dvb_attach(ts2020_attach, d->fe_adap[0].fe, &su3000_ts2020_config,
-               &d->dev->i2c_adap);
-
-       info("Attached DS3000!\n");
+       if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
+                               &dw2104_ts2020_config,
+                               &d->dev->i2c_adap)) {
+               info("Attached DS3000/TS2020!\n");
+               return 0;
+       }
 
-       return 0;
+       info("Failed to attach DS3000/TS2020!\n");
+       return -EIO;
 }
 
 static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
@@ -1292,12 +1294,19 @@ static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
 
        d->fe_adap[0].fe = dvb_attach(m88rs2000_attach, &s421_m88rs2000_config,
                                        &d->dev->i2c_adap);
+
        if (d->fe_adap[0].fe == NULL)
                return -EIO;
 
-       info("Attached m88rs2000!\n");
+       if (dvb_attach(ts2020_attach, d->fe_adap[0].fe,
+                               &dw2104_ts2020_config,
+                               &d->dev->i2c_adap)) {
+               info("Attached RS2000/TS2020!\n");
+               return 0;
+       }
 
-       return 0;
+       info("Failed to attach RS2000/TS2020!\n");
+       return -EIO;
 }
 
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)