]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/media/dvb/frontends/stv090x.c
V4L/DVB (11601): stv090x: update demodulator capabilities
[mirror_ubuntu-artful-kernel.git] / drivers / media / dvb / frontends / stv090x.c
index a65f1b7849a11ecd478742b36d72f7c04cfad07c..fc87dfa96597be97b4d209b42ed607a34e2af5b9 100644 (file)
@@ -176,8 +176,10 @@ static const struct stv090x_tab stv090x_rf_tab[] = {
 static struct stv090x_reg stv0900_initval[] = {
 
        { STV090x_OUTCFG,               0x00 },
+       { STV090x_MODECFG,              0xff },
        { STV090x_AGCRF1CFG,            0x11 },
        { STV090x_AGCRF2CFG,            0x13 },
+       { STV090x_TSGENERAL1X,          0x14 },
        { STV090x_TSTTNR2,              0x21 },
        { STV090x_TSTTNR4,              0x21 },
        { STV090x_P2_DISTXCTL,          0x22 },
@@ -203,8 +205,10 @@ static struct stv090x_reg stv0900_initval[] = {
        { STV090x_P2_ERRCTRL2,          0xc1 },
        { STV090x_P2_CFRICFG,           0xf8 },
        { STV090x_P2_NOSCFG,            0x1c },
+       { STV090x_P2_DMDTOM,            0x20 },
        { STV090x_P2_CORRELMANT,        0x70 },
        { STV090x_P2_CORRELABS,         0x88 },
+       { STV090x_P2_AGC2O,             0x5b },
        { STV090x_P2_AGC2REF,           0x38 },
        { STV090x_P2_CARCFG,            0xe4 },
        { STV090x_P2_ACLC,              0x1A },
@@ -246,6 +250,7 @@ static struct stv090x_reg stv0900_initval[] = {
        { STV090x_P1_DMDCFGMD,          0xf9 },
        { STV090x_P1_DEMOD,             0x08 },
        { STV090x_P1_DMDCFG3,           0xc4 },
+       { STV090x_P1_DMDTOM,            0x20 },
        { STV090x_P1_CARFREQ,           0xed },
        { STV090x_P1_LDT,               0xd0 },
        { STV090x_P1_LDT2,              0xb8 },
@@ -265,6 +270,7 @@ static struct stv090x_reg stv0900_initval[] = {
        { STV090x_P1_NOSCFG,            0x1c },
        { STV090x_P1_CORRELMANT,        0x70 },
        { STV090x_P1_CORRELABS,         0x88 },
+       { STV090x_P1_AGC2O,             0x5b },
        { STV090x_P1_AGC2REF,           0x38 },
        { STV090x_P1_CARCFG,            0xe4 },
        { STV090x_P1_ACLC,              0x1A },
@@ -326,6 +332,7 @@ static struct stv090x_reg stv0900_initval[] = {
        { STV090x_GAINLLR_NF15,         0x1A },
        { STV090x_GAINLLR_NF16,         0x1F },
        { STV090x_GAINLLR_NF17,         0x21 },
+       { STV090x_RCCFGH,               0x20 },
        { STV090x_P1_FECM,              0x01 }, /* disable DSS modes */
        { STV090x_P2_FECM,              0x01 }, /* disable DSS modes */
        { STV090x_P1_PRVIT,             0x2F }, /* disable PR 6/7 */
@@ -364,12 +371,14 @@ static struct stv090x_reg stv0903_initval[] = {
        { STV090x_P1_ERRCTRL2,          0xc1 },
        { STV090x_P1_CFRICFG,           0xf8 },
        { STV090x_P1_NOSCFG,            0x1c },
+       { STV090x_P1_DMDTOM,            0x20 },
        { STV090x_P1_CORRELMANT,        0x70 },
        { STV090x_P1_CORRELABS,         0x88 },
-       { STV090x_P1_AGC2REF,           0x38 } ,
+       { STV090x_P1_AGC2O,             0x5b },
+       { STV090x_P1_AGC2REF,           0x38 },
        { STV090x_P1_CARCFG,            0xe4 },
        { STV090x_P1_ACLC,              0x1A },
-       { STV090x_P1_BCLC,              0x09 } ,
+       { STV090x_P1_BCLC,              0x09 },
        { STV090x_P1_CARHDR,            0x08 },
        { STV090x_P1_KREFTMG,           0xc1 },
        { STV090x_P1_SFRSTEP,           0x58 },
@@ -427,6 +436,7 @@ static struct stv090x_reg stv0903_initval[] = {
        { STV090x_GAINLLR_NF15,         0x1A },
        { STV090x_GAINLLR_NF16,         0x1F },
        { STV090x_GAINLLR_NF17,         0x21 },
+       { STV090x_RCCFGH,               0x20 },
        { STV090x_P1_FECM,              0x01 }, /*disable the DSS mode */
        { STV090x_P1_PRVIT,             0x2f }  /*disable puncture rate 6/7*/
 };
@@ -434,6 +444,7 @@ static struct stv090x_reg stv0903_initval[] = {
 static struct stv090x_reg stv0900_cut20_val[] = {
 
        { STV090x_P2_DMDCFG3,           0xe8 },
+       { STV090x_P2_DMDCFG4,           0x10 },
        { STV090x_P2_CARFREQ,           0x38 },
        { STV090x_P2_CARHDR,            0x20 },
        { STV090x_P2_KREFTMG,           0x5a },
@@ -442,6 +453,7 @@ static struct stv090x_reg stv0900_cut20_val[] = {
        { STV090x_P2_SMAPCOEF5,         0x04 },
        { STV090x_P2_NOSCFG,            0x0c },
        { STV090x_P1_DMDCFG3,           0xe8 },
+       { STV090x_P1_DMDCFG4,           0x10 },
        { STV090x_P1_CARFREQ,           0x38 },
        { STV090x_P1_CARHDR,            0x20 },
        { STV090x_P1_KREFTMG,           0x5a },
@@ -467,6 +479,7 @@ static struct stv090x_reg stv0900_cut20_val[] = {
 
 static struct stv090x_reg stv0903_cut20_val[] = {
        { STV090x_P1_DMDCFG3,           0xe8 },
+       { STV090x_P1_DMDCFG4,           0x10 },
        { STV090x_P1_CARFREQ,           0x38 },
        { STV090x_P1_CARHDR,            0x20 },
        { STV090x_P1_KREFTMG,           0x5a },
@@ -643,13 +656,14 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        u32 reg;
 
        reg = STV090x_READ_DEMOD(state, I2CRPT);
-
        if (enable) {
+               dprintk(FE_DEBUG, 1, "Enable Gate");
                STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
                if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
                        goto err;
 
        } else {
+               dprintk(FE_DEBUG, 1, "Disable Gate");
                STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
                if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
                        goto err;
@@ -711,18 +725,22 @@ static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
 {
        u32 sym;
 
-       if (srate > 6000000) {
-               sym  = (srate / 1000) * 65536;
-               sym /= (state->mclk / 1000);
+       if (srate > 60000000) {
+               sym  = (srate << 4); /* SR * 2^16 / master_clk */
+               sym /= (state->mclk >> 12);
+       } else if (srate > 6000000) {
+               sym  = (srate << 6);
+               sym /= (state->mclk >> 10);
        } else {
-               sym  = (srate / 100) * 65536;
-               sym /= (state->mclk / 100);
+               sym  = (srate << 9);
+               sym /= (state->mclk >> 7);
        }
 
-       if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) /* MSB */
+       if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
                goto err;
        if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
                goto err;
+
        return 0;
 err:
        dprintk(FE_ERROR, 1, "I/O error");
@@ -734,17 +752,29 @@ static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate
        u32 sym;
 
        srate = 105 * (srate / 100);
-       if (srate > 6000000) {
-               sym  = (srate / 1000) * 65536;
-               sym /= (clk / 1000);
+       if (srate > 60000000) {
+               sym  = (srate << 4); /* SR * 2^16 / master_clk */
+               sym /= (state->mclk >> 12);
+       } else if (srate > 6000000) {
+               sym  = (srate << 6);
+               sym /= (state->mclk >> 10);
        } else {
-               sym  = (srate / 100) * 65536;
-               sym /= (clk / 100);
+               sym  = (srate << 9);
+               sym /= (state->mclk >> 7);
        }
-       if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
-               goto err;
-       if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
-               goto err;
+
+       if (sym < 0x7fff) {
+               if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
+                       goto err;
+               if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
+                       goto err;
+       } else {
+               if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
+                       goto err;
+               if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
+                       goto err;
+       }
+
        return 0;
 err:
        dprintk(FE_ERROR, 1, "I/O error");
@@ -756,13 +786,17 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate
        u32 sym;
 
        srate = 95 * (srate / 100);
-       if (srate > 6000000) {
-               sym  = (srate / 1000) * 65536;
-               sym /= (clk / 1000);
+       if (srate > 60000000) {
+               sym  = (srate << 4); /* SR * 2^16 / master_clk */
+               sym /= (state->mclk >> 12);
+       } else if (srate > 6000000) {
+               sym  = (srate << 6);
+               sym /= (state->mclk >> 10);
        } else {
-               sym  = (srate / 100) * 65536;
-               sym /= (clk / 100);
+               sym  = (srate << 9);
+               sym /= (state->mclk >> 7);
        }
+
        if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */
                goto err;
        if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
@@ -773,9 +807,24 @@ err:
        return -1;
 }
 
-static u32 stv090x_car_width(u32 srate, u32 rolloff)
+static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
 {
-       return srate + (srate * rolloff) / 100;
+       u32 ro;
+
+       switch (rolloff) {
+       case STV090x_RO_20:
+               ro = 20;
+               break;
+       case STV090x_RO_25:
+               ro = 25;
+               break;
+       case STV090x_RO_35:
+       default:
+               ro = 35;
+               break;
+       }
+
+       return srate + (srate * ro) / 100;
 }
 
 static int stv090x_set_vit_thacq(struct stv090x_state *state)
@@ -1114,12 +1163,12 @@ static int stv090x_delivery_search(struct stv090x_state *state)
                if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
                        goto err;
 
-               if (stv090x_vitclk_ctl(state, 1) < 0)
+               if (stv090x_vitclk_ctl(state, 0) < 0)
                        goto err;
 
                if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
                        goto err;
-               if (STV090x_WRITE_DEMOD(state, ACLC, 0x09) < 0)
+               if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
                        goto err;
                if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
                        goto err;
@@ -1334,7 +1383,6 @@ static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
 {
        u8 r3, r2, r1, r0;
        s32 srate, int_1, int_2, tmp_1, tmp_2;
-       u32 pow2;
 
        r3 = STV090x_READ_DEMOD(state, SFR3);
        r2 = STV090x_READ_DEMOD(state, SFR2);
@@ -1343,16 +1391,15 @@ static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
 
        srate = ((r3 << 24) | (r2 << 16) | (r1 <<  8) | r0);
 
-       pow2 = 1 << 16;
-       int_1 = clk / pow2;
-       int_2 = srate / pow2;
+       int_1 = clk >> 16;
+       int_2 = srate >> 16;
 
-       tmp_1 = clk % pow2;
-       tmp_2 = srate % pow2;
+       tmp_1 = clk % 0x10000;
+       tmp_2 = srate % 0x10000;
 
        srate = (int_1 * int_2) +
-               ((int_1 * tmp_2) / pow2) +
-               ((int_2 * tmp_1) / pow2);
+               ((int_1 * tmp_2) >> 16) +
+               ((int_2 * tmp_1) >> 16);
 
        return srate;
 }
@@ -1896,6 +1943,7 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s
 
        srate = state->srate;
        car_max = state->search_range / 1000;
+       car_max += car_max / 10;
        car_max  = 65536 * (car_max / 2);
        car_max /= (state->mclk / 1000);
 
@@ -1908,7 +1956,7 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s
        inc *= 256;
        inc /= 1000;
 
-       switch (state->algo) {
+       switch (state->search_mode) {
        case STV090x_SEARCH_DVBS1:
        case STV090x_SEARCH_DSS:
                inc *= 3; /* freq step = 3% of srate */
@@ -1956,6 +2004,7 @@ static int stv090x_chk_signal(struct stv090x_state *state)
 
        offst_car  = STV090x_READ_DEMOD(state, CFR2) << 8;
        offst_car |= STV090x_READ_DEMOD(state, CFR1);
+       offst_car = comp2(offst_car, 16);
 
        agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
        agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
@@ -2018,6 +2067,9 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim
                        STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x1);
                        if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
                                goto err;
+                       STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x0);
+                       if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+                               goto err;
                }
 
                if (zigzag) {
@@ -2029,6 +2081,8 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim
                        offst_freq += 2 * inc;
                }
 
+               cpt_step++;
+
                lock = stv090x_get_dmdlock(state, timeout);
                no_signal = stv090x_chk_signal(state);
 
@@ -2059,7 +2113,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
 
        stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); /* get params */
 
-       switch (state->algo) {
+       switch (state->search_mode) {
        case STV090x_SEARCH_DVBS1:
        case STV090x_SEARCH_DSS:
                /* accelerate the frequency detector */
@@ -2102,7 +2156,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
                        if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0)
                                goto err;
                }
-               if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x69) < 0)
+               if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
                        goto err;
                zigzag = 0;
                break;
@@ -2190,23 +2244,22 @@ static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
 static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
 {
        s32 derot, int_1, int_2, tmp_1, tmp_2;
-       u32 pow2;
 
        derot  = STV090x_READ_DEMOD(state, CFR2) << 16;
        derot |= STV090x_READ_DEMOD(state, CFR1) <<  8;
        derot |= STV090x_READ_DEMOD(state, CFR0);
 
        derot = comp2(derot, 24);
-       pow2 = 1 << 12;
-       int_1 = state->mclk / pow2;
-       int_2 = derot / pow2;
+       int_1 = state->mclk >> 12;
+       int_2 = derot >> 12;
 
-       tmp_1 = state->mclk % pow2;
-       tmp_2 = derot % pow2;
+       /* carrier_frequency = MasterClock * Reg / 2^24 */
+       tmp_1 = state->mclk % 0x1000;
+       tmp_2 = derot % 0x1000;
 
        derot = (int_1 * int_2) +
-               ((int_1 * tmp_2) / pow2) +
-               ((int_1 * tmp_1) / pow2);
+               ((int_1 * tmp_2) >> 12) +
+               ((int_1 * tmp_1) >> 12);
 
        return derot;
 }
@@ -2264,7 +2317,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
        if (state->algo == STV090x_BLIND_SEARCH) {
                tmg = STV090x_READ_DEMOD(state, TMGREG2);
                STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
-               while ((i <= 50) && (!tmg) && (tmg != 0xff)) {
+               while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
                        tmg = STV090x_READ_DEMOD(state, TMGREG2);
                        msleep(5);
                        i += 5;
@@ -2301,7 +2354,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
                stv090x_i2c_gate_ctrl(fe, 0);
 
                if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
-                       return  STV090x_RANGEOK;
+                       return STV090x_RANGEOK;
                else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
                        return STV090x_RANGEOK;
                else
@@ -2319,19 +2372,16 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
 static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
 {
        s32 offst_tmg;
-       s32 pow2;
 
        offst_tmg  = STV090x_READ_DEMOD(state, TMGREG2) << 16;
        offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) <<  8;
        offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
 
-       pow2 = 1 << 24;
-
        offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
        if (!offst_tmg)
                offst_tmg = 1;
 
-       offst_tmg  = ((s32) srate * 10) / (pow2 / offst_tmg);
+       offst_tmg  = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
        offst_tmg /= 320;
 
        return offst_tmg;
@@ -2526,8 +2576,8 @@ static int stv090x_optimize_track(struct stv090x_state *state)
 
        case STV090x_DVBS2:
                reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-               STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-               STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+               STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+               STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
                if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
                        goto err;
                if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
@@ -2876,7 +2926,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
        enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
        u32 reg;
        s32 timeout_dmd = 500, timeout_fec = 50;
-       int lock = 0, low_sr, no_signal = 0;
+       int lock = 0, low_sr = 0, no_signal = 0;
 
        reg = STV090x_READ_DEMOD(state, TSCFGH);
        STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
@@ -2920,7 +2970,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
                        if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
                                goto err;
                        if (state->algo == STV090x_COLD_SEARCH)
-                               state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 1000000)) / 10;
+                               state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
                        else if (state->algo == STV090x_WARM_SEARCH)
                                state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
                } else {
@@ -2935,6 +2985,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
                stv090x_set_min_srate(state, state->mclk, state->srate);
 
                if (state->srate >= 10000000)
+                       low_sr = 0;
+               else
                        low_sr = 1;
        }
 
@@ -2972,7 +3024,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
        if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
                goto err;
        stv090x_delivery_search(state);
-       if (state->algo == STV090x_BLIND_SEARCH)
+       if (state->algo != STV090x_BLIND_SEARCH)
                stv090x_start_search(state);
 
        if (state->dev_ver == 0x12) {
@@ -3070,7 +3122,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
        if ((signal_state == STV090x_NODATA) && (!no_signal)) {
                if (state->dev_ver <= 0x11) {
                        reg = STV090x_READ_DEMOD(state, DMDSTATE);
-                       if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS2) && (state->inversion == INVERSION_AUTO))
+                       if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS1) && (state->inversion == INVERSION_AUTO))
                                signal_state = stv090x_acq_fixs1(state);
                }
        }
@@ -3089,8 +3141,12 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
        state->delsys = props->delivery_system;
        state->frequency = p->frequency;
        state->srate = p->u.qpsk.symbol_rate;
+       state->search_mode = STV090x_SEARCH_AUTO;
+       state->algo = STV090x_COLD_SEARCH;
+       state->fec = STV090x_PRERR;
+       state->search_range = 2000000;
 
-       if (!stv090x_algo(state)) {
+       if (stv090x_algo(state) == STV090x_RANGEOK) {
                dprintk(FE_DEBUG, 1, "Search success!");
                return DVBFE_ALGO_SEARCH_SUCCESS;
        } else {
@@ -3107,7 +3163,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
        struct stv090x_state *state = fe->demodulator_priv;
        u32 reg;
        u8 search_state;
-       int locked = 0;
 
        reg = STV090x_READ_DEMOD(state, DMDSTATE);
        search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
@@ -3117,7 +3172,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
        case 1: /* first PLH detected */
        default:
                dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
-               locked = 0;
+               *status = 0;
                break;
 
        case 2: /* DVB-S2 mode */
@@ -3126,7 +3181,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
                if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
                        reg = STV090x_READ_DEMOD(state, TSSTATUS);
                        if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-                               locked = 1;
                                *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
                        }
                }
@@ -3140,7 +3194,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
                        if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
                                reg = STV090x_READ_DEMOD(state, TSSTATUS);
                                if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
-                                       locked = 1;
                                        *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
                                }
                        }
@@ -3148,7 +3201,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
                break;
        }
 
-       return locked;
+       return 0;
 }
 
 static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
@@ -3159,7 +3212,8 @@ static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
        u32 reg, h, m, l;
        enum fe_status status;
 
-       if (!stv090x_read_status(fe, &status)) {
+       stv090x_read_status(fe, &status);
+       if (!(status & FE_HAS_LOCK)) {
                *per = 1 << 23; /* Max PER */
        } else {
                /* Counter 2 */
@@ -3346,6 +3400,15 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
        int i;
 
        reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+       STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2);
+       STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+       STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+
        STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
        if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
                goto err;
@@ -3359,8 +3422,64 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
 
                if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
                        goto err;
+       }
+       reg = STV090x_READ_DEMOD(state, DISTXCTL);
+       STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+
+       i = 0;
+
+       while ((!idle) && (i < 10)) {
+               reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+               idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+               msleep(10);
                i++;
        }
+
+       return 0;
+err:
+       dprintk(FE_ERROR, 1, "I/O error");
+       return -1;
+}
+
+static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+       struct stv090x_state *state = fe->demodulator_priv;
+       u32 reg, idle = 0, fifo_full = 1;
+       u8 mode, value;
+       int i;
+
+       reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+       if (burst == SEC_MINI_A) {
+               mode = 3;
+               value = 0x00;
+       } else {
+               mode = 2;
+               value = 0xFF;
+       }
+
+       STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
+       STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+       STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+
+       STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+       if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+               goto err;
+
+       while (fifo_full) {
+               reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+               fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+       }
+
+       if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
+               goto err;
+
        reg = STV090x_READ_DEMOD(state, DISTXCTL);
        STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
        if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
@@ -3415,6 +3534,11 @@ static int stv090x_sleep(struct dvb_frontend *fe)
        if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
                goto err;
 
+       reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+       STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
+       if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+               goto err;
+
        return 0;
 err:
        dprintk(FE_ERROR, 1, "I/O error");
@@ -3434,6 +3558,11 @@ static int stv090x_wakeup(struct dvb_frontend *fe)
        if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
                goto err;
 
+       reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+       STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
+       if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+               goto err;
+
        return 0;
 err:
        dprintk(FE_ERROR, 1, "I/O error");
@@ -3534,6 +3663,13 @@ static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
 
        state->mclk = stv090x_get_mclk(state);
 
+       /*Set the DiseqC frequency to 22KHz */
+       div = state->mclk / 704000;
+       if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
+               goto err;
+       if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
+               goto err;
+
        return 0;
 err:
        dprintk(FE_ERROR, 1, "I/O error");
@@ -3602,10 +3738,12 @@ static int stv090x_set_tspath(struct stv090x_state *state)
                        case STV090x_TSMODE_SERIAL_PUNCTURED:
                        case STV090x_TSMODE_SERIAL_CONTINUOUS:
                        default:
+                               stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
                                break;
 
                        case STV090x_TSMODE_PARALLEL_PUNCTURED:
                        case STV090x_TSMODE_DVBCI:
+                               stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
                                reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
                                STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
                                if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
@@ -3629,10 +3767,12 @@ static int stv090x_set_tspath(struct stv090x_state *state)
                        case STV090x_TSMODE_SERIAL_PUNCTURED:
                        case STV090x_TSMODE_SERIAL_CONTINUOUS:
                        default:
+                               stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
                                break;
 
                        case STV090x_TSMODE_PARALLEL_PUNCTURED:
                        case STV090x_TSMODE_DVBCI:
+                               stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
                                break;
                        }
                        break;
@@ -3678,34 +3818,34 @@ static int stv090x_set_tspath(struct stv090x_state *state)
 
        switch (state->config->ts2_mode) {
        case STV090x_TSMODE_PARALLEL_PUNCTURED:
-               reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+               reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
                STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
                STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-               if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+               if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
                        goto err;
                break;
 
        case STV090x_TSMODE_DVBCI:
-               reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+               reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
                STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
                STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-               if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+               if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
                        goto err;
                break;
 
        case STV090x_TSMODE_SERIAL_PUNCTURED:
-               reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+               reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
                STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
                STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-               if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+               if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
                        goto err;
                break;
 
        case STV090x_TSMODE_SERIAL_CONTINUOUS:
-               reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+               reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
                STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
                STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-               if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+               if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
                        goto err;
                break;
 
@@ -3740,6 +3880,11 @@ static int stv090x_init(struct dvb_frontend *fe)
        const struct stv090x_config *config = state->config;
        u32 reg;
 
+       if (stv090x_wakeup(fe) < 0) {
+               dprintk(FE_ERROR, 1, "Error waking device");
+               goto err;
+       }
+
        stv090x_ldpc_mode(state, state->demod_mode);
 
        reg = STV090x_READ_DEMOD(state, TNRCFG2);
@@ -3753,6 +3898,8 @@ static int stv090x_init(struct dvb_frontend *fe)
 
        stv090x_i2c_gate_ctrl(fe, 1);
 
+       if (config->tuner_set_mode)
+               config->tuner_set_mode(fe, TUNER_WAKE);
        if (config->tuner_init)
                config->tuner_init(fe);
 
@@ -3773,6 +3920,7 @@ static int stv090x_setup(struct dvb_frontend *fe)
        const struct stv090x_reg *stv090x_initval = NULL;
        const struct stv090x_reg *stv090x_cut20_val = NULL;
        unsigned long t1_size = 0, t2_size = 0;
+       u32 reg = 0;
 
        int i;
 
@@ -3799,7 +3947,8 @@ static int stv090x_setup(struct dvb_frontend *fe)
        if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */
                goto err;
 
-       if (STV090x_WRITE_DEMOD(state, I2CRPT, 0x00) < 0) /* repeater OFF */
+       STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
+       if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */
                goto err;
 
        if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
@@ -3812,12 +3961,13 @@ static int stv090x_setup(struct dvb_frontend *fe)
        msleep(5);
 
        /* write initval */
+       dprintk(FE_DEBUG, 1, "Setting up initial values");
        for (i = 0; i < t1_size; i++) {
-               dprintk(FE_DEBUG, 1, "Setting up initial values");
                if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
                        goto err;
        }
 
+       state->dev_ver = stv090x_read_reg(state, STV090x_MID);
        if (state->dev_ver >= 0x20) {
                if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
                        goto err;
@@ -3851,6 +4001,17 @@ static struct dvb_frontend_ops stv090x_ops = {
 
        .info = {
                .name                   = "STV090x Multistandard",
+               .type                   = FE_QPSK,
+               .frequency_min          = 950000,
+               .frequency_max          = 2150000,
+               .frequency_stepsize     = 0,
+               .frequency_tolerance    = 0,
+               .symbol_rate_min        = 1000000,
+               .symbol_rate_max        = 45000000,
+               .caps                   = FE_CAN_INVERSION_AUTO |
+                                         FE_CAN_FEC_AUTO       |
+                                         FE_CAN_QPSK           |
+                                         FE_CAN_2G_MODULATION
        },
 
        .release                        = stv090x_release,
@@ -3862,6 +4023,7 @@ static struct dvb_frontend_ops stv090x_ops = {
        .i2c_gate_ctrl                  = stv090x_i2c_gate_ctrl,
 
        .diseqc_send_master_cmd         = stv090x_send_diseqc_msg,
+       .diseqc_send_burst              = stv090x_send_diseqc_burst,
        .diseqc_recv_slave_reply        = stv090x_recv_slave_reply,
        .set_tone                       = stv090x_set_tone,
 
@@ -3888,9 +4050,10 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
        state->i2c                              = i2c;
        state->frontend.ops                     = stv090x_ops;
        state->frontend.demodulator_priv        = state;
+       state->demod                            = demod;
        state->demod_mode                       = config->demod_mode; /* Single or Dual mode */
        state->device                           = config->device;
-       state->rolloff                          = 35; /* default */
+       state->rolloff                          = STV090x_RO_35; /* default */
 
        if (state->demod == STV090x_DEMODULATOR_0)
                mutex_init(&demod_lock);
@@ -3908,7 +4071,6 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
                dprintk(FE_ERROR, 1, "Error waking device");
                goto error;
        }
-       state->dev_ver = stv090x_read_reg(state, STV090x_MID);
 
        dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n",
               state->device == STV0900 ? "STV0900" : "STV0903",