include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / media / dvb / frontends / mb86a16.c
index 47c0d57..599d1aa 100644 (file)
@@ -1,7 +1,7 @@
 /*
        Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
 
-       Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com)
+       Copyright (C) Manu Abraham (abraham.manu@gmail.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
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "mb86a16.h"
@@ -36,13 +37,12 @@ struct mb86a16_state {
        struct i2c_adapter              *i2c_adap;
        const struct mb86a16_config     *config;
        struct dvb_frontend             frontend;
-       u8                              signal;
 
-       // tuning parameters
+       /* tuning parameters */
        int                             frequency;
        int                             srate;
 
-       // Internal stuff
+       /* Internal stuff */
        int                             master_clk;
        int                             deci;
        int                             csel;
@@ -106,7 +106,7 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val)
                        .flags = 0,
                        .buf = b0,
                        .len = 1
-               },{
+               }, {
                        .addr = state->config->demod_address,
                        .flags = I2C_M_RD,
                        .buf = b1,
@@ -417,7 +417,8 @@ static int signal_det(struct mb86a16_state *state,
        int ret ;
        int smrtd ;
        int wait_sym ;
-       int wait_t ;
+
+       u32 wait_t;
        unsigned char S[3] ;
        int i ;
 
@@ -435,7 +436,7 @@ static int signal_det(struct mb86a16_state *state,
                wait_sym = 80000;
        }
        for (i = 0; i < 3; i++) {
-               if (i == 0 )
+               if (i == 0)
                        smrtd = smrt * 98 / 100;
                else if (i == 1)
                        smrtd = smrt;
@@ -480,11 +481,11 @@ static int rf_val_set(struct mb86a16_state *state,
        unsigned char rf_val[5];
        int ack = -1;
 
-       if (smrt > 37750 )
+       if (smrt > 37750)
                C = 1;
        else if (smrt > 18875)
                C = 2;
-       else if (smrt > 5500 )
+       else if (smrt > 5500)
                C = 3;
        else
                C = 4;
@@ -526,7 +527,7 @@ static int rf_val_set(struct mb86a16_state *state,
        rf_val[2] = (M & 0x00ff0) >> 4;
        rf_val[3] = ((M & 0x0000f) << 4) | B;
 
-       // Frequency Set
+       /* Frequency Set */
        if (mb86a16_write(state, 0x21, rf_val[0]) < 0)
                ack = 0;
        if (mb86a16_write(state, 0x22, rf_val[1]) < 0)
@@ -592,16 +593,39 @@ err:
 
 static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
+       u8 stat, stat2;
        struct mb86a16_state *state = fe->demodulator_priv;
 
-       if (state->signal & 0x02)
-               *status |= FE_HAS_VITERBI;
-       if (state->signal & 0x01)
+       *status = 0;
+
+       if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2)
+               goto err;
+       if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2)
+               goto err;
+       if ((stat > 25) && (stat2 > 25))
+               *status |= FE_HAS_SIGNAL;
+       if ((stat > 45) && (stat2 > 45))
+               *status |= FE_HAS_CARRIER;
+
+       if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2)
+               goto err;
+
+       if (stat & 0x01)
                *status |= FE_HAS_SYNC;
-       if (state->signal & 0x03)
+       if (stat & 0x01)
+               *status |= FE_HAS_VITERBI;
+
+       if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2)
+               goto err;
+
+       if ((stat & 0x0f) && (*status & FE_HAS_VITERBI))
                *status |= FE_HAS_LOCK;
 
        return 0;
+
+err:
+       dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+       return -EREMOTEIO;
 }
 
 static int sync_chk(struct mb86a16_state *state,
@@ -632,8 +656,8 @@ static int freqerr_chk(struct mb86a16_state *state,
        unsigned char CRM, AFCML, AFCMH;
        unsigned char temp1, temp2, temp3;
        int crm, afcm, AFCM;
-       int crrerr, afcerr;             // [kHz]
-       int frqerr;                     // [MHz]
+       int crrerr, afcerr;             /* kHz */
+       int frqerr;                     /* MHz */
        int afcen, afcexen = 0;
        int R, M, fOSC, fOSC_OFS;
 
@@ -695,12 +719,12 @@ static int freqerr_chk(struct mb86a16_state *state,
 
        fOSC_OFS = fOSC - fTP;
 
-       if (unit == 0) {        //[MHz]
+       if (unit == 0) {        /* MHz */
                if (crrerr + afcerr + fOSC_OFS * 1000 >= 0)
                        frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000;
                else
                        frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000;
-       } else {        //[kHz]
+       } else {        /* kHz */
                frqerr = crrerr + afcerr + fOSC_OFS * 1000;
        }
 
@@ -737,13 +761,13 @@ static void swp_info_get(struct mb86a16_state *state,
 
        crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs;
 
-       if (R == 0 )
+       if (R == 0)
                *fOSC = (crnt_swp_freq + 1000) / 2000 * 2;
        else
                *fOSC = (crnt_swp_freq + 500) / 1000;
 
        if (*fOSC >= crnt_swp_freq)
-               *afcex_freq = *fOSC *1000 - crnt_swp_freq;
+               *afcex_freq = *fOSC * 1000 - crnt_swp_freq;
        else
                *afcex_freq = crnt_swp_freq - *fOSC * 1000;
 
@@ -759,7 +783,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
        int swp_freq ;
 
        if ((i % 2 == 1) && (v <= vmax)) {
-               // positive v (case 1)
+               /* positive v (case 1) */
                if ((v - 1 == vmin)                             &&
                    (*(V + 30 + v) >= 0)                        &&
                    (*(V + 30 + v - 1) >= 0)                    &&
@@ -773,7 +797,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v - 1) >= 0)             &&
                           (*(V + 30 + v) > *(V + 30 + v - 1))  &&
                           (*(V + 30 + v) > SIGMIN)) {
-                       // (case 2)
+                       /* (case 2) */
                        swp_freq = fOSC * 1000 + afcex_freq;
                        *SIG1 = *(V + 30 + v);
                } else if ((*(V + 30 + v) > 0)                  &&
@@ -784,7 +808,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v - 2) > *(V + 30 + v - 3)) &&
                           ((*(V + 30 + v - 1) > SIGMIN)        ||
                           (*(V + 30 + v - 2) > SIGMIN))) {
-                       // (case 3)
+                       /* (case 3) */
                        if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) {
                                swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
                                *SIG1 = *(V + 30 + v - 1);
@@ -800,7 +824,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v - 1) > *(V + 30 + v - 2)) &&
                           ((*(V + 30 + v) > SIGMIN)            ||
                           (*(V + 30 + v - 1) > SIGMIN))) {
-                       // (case 4)
+                       /* (case 4) */
                        if (*(V + 30 + v) >= *(V + 30 + v - 1)) {
                                swp_freq = fOSC * 1000 + afcex_freq;
                                *SIG1 = *(V + 30 + v);
@@ -812,7 +836,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                        swp_freq = -1 ;
                }
        } else if ((i % 2 == 0) && (v >= vmin)) {
-               // Negative v (case 1)
+               /* Negative v (case 1) */
                if ((*(V + 30 + v) > 0)                         &&
                    (*(V + 30 + v + 1) > 0)                     &&
                    (*(V + 30 + v + 2) > 0)                     &&
@@ -827,7 +851,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v + 1) >= 0)             &&
                           (*(V + 30 + v + 1) > *(V + 30 + v))  &&
                           (*(V + 30 + v + 1) > SIGMIN)) {
-                       // (case 2)
+                       /* (case 2) */
                        swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
                        *SIG1 = *(V + 30 + v);
                } else if ((v == vmin)                          &&
@@ -837,18 +861,18 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v) > *(V + 30 + v + 1))  &&
                           (*(V + 30 + v) > *(V + 30 + v + 2))  &&
                           (*(V + 30 + v) > SIGMIN)) {
-                       // (case 3)
+                       /* (case 3) */
                        swp_freq = fOSC * 1000 + afcex_freq;
                        *SIG1 = *(V + 30 + v);
                } else if ((*(V + 30 + v) >= 0)                 &&
                           (*(V + 30 + v + 1) >= 0)             &&
                           (*(V + 30 + v + 2) >= 0)             &&
-                          (*(V +30 + v + 3) >= 0)              &&
+                          (*(V + 30 + v + 3) >= 0)             &&
                           (*(V + 30 + v + 1) > *(V + 30 + v))  &&
                           (*(V + 30 + v + 2) > *(V + 30 + v + 3)) &&
                           ((*(V + 30 + v + 1) > SIGMIN)        ||
                            (*(V + 30 + v + 2) > SIGMIN))) {
-                       // (case 4)
+                       /* (case 4) */
                        if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
                                swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
                                *SIG1 = *(V + 30 + v + 1);
@@ -866,7 +890,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v + 1) > *(V + 30 + v + 3)) &&
                           ((*(V + 30 + v) > SIGMIN)            ||
                            (*(V + 30 + v + 1) > SIGMIN))) {
-                       // (case 5)
+                       /* (case 5) */
                        if (*(V + 30 + v) >= *(V + 30 + v + 1)) {
                                swp_freq = fOSC * 1000 + afcex_freq;
                                *SIG1 = *(V + 30 + v);
@@ -882,7 +906,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                           (*(V + 30 + v + 2) > *(V + 30 + v))  &&
                           ((*(V + 30 + v + 1) > SIGMIN)        ||
                            (*(V + 30 + v + 2) > SIGMIN))) {
-                       // (case 6)
+                       /* (case 6) */
                        if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
                                swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
                                *SIG1 = *(V + 30 + v + 1);
@@ -893,8 +917,10 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V
                } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) {
                        swp_freq = fOSC * 1000;
                        *SIG1 = *(V + 30 + v);
-               } else swp_freq = -1;
-       } else swp_freq = -1;
+               } else
+                       swp_freq = -1;
+       } else
+               swp_freq = -1;
 
        return swp_freq;
 }
@@ -939,7 +965,7 @@ static void afcex_info_get(struct mb86a16_state *state,
 
 static int SEQ_set(struct mb86a16_state *state, unsigned char loop)
 {
-       // SLOCK0 = 0
+       /* SLOCK0 = 0 */
        if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) {
                dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
                return -EREMOTEIO;
@@ -950,7 +976,7 @@ static int SEQ_set(struct mb86a16_state *state, unsigned char loop)
 
 static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV)
 {
-       // Viterbi Rate, IQ Settings
+       /* Viterbi Rate, IQ Settings */
        if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) {
                dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
                return -EREMOTEIO;
@@ -1008,7 +1034,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
        unsigned char TIMINT1, TIMINT2, TIMEXT;
        unsigned char S0T, S1T;
        unsigned char S2T;
-//     unsigned char S2T, S3T;
+/*     unsigned char S2T, S3T; */
        unsigned char S4T, S5T;
        unsigned char AFCEX_L, AFCEX_H;
        unsigned char R;
@@ -1029,7 +1055,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
        int temp_freq, delta_freq;
        int dagcm[4];
        int smrt_d;
-//     int freq_err;
+/*     int freq_err; */
        int n;
        int ret = -1;
        int sync;
@@ -1070,19 +1096,19 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                }
                if (EN_set(state, CREN, AFCEN) < 0) {
                        dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
-                       return -1; // (0, 0)
+                       return -1; /* (0, 0) */
                }
                if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
                        dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
-                       return -1; // (1, smrt) = (1, symbolrate)
+                       return -1; /* (1, smrt) = (1, symbolrate) */
                }
                if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) {
                        dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error");
-                       return -1; // (0, 1, 2)
+                       return -1; /* (0, 1, 2) */
                }
                if (S01T_set(state, S1T, S0T) < 0) {
                        dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
-                       return -1; // (0, 0)
+                       return -1; /* (0, 0) */
                }
                smrt_info_get(state, state->srate);
                if (smrt_set(state, state->srate) < 0) {
@@ -1110,13 +1136,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                        ftemp = ftemp + swp_ofs;
                        vmax++;
 
-                       // Upper bound
+                       /* Upper bound */
                        if (ftemp > 2150000) {
                                loop = 0;
                                vmax--;
+                       } else {
+                               if ((ftemp == 2150000) ||
+                                   (ftemp - state->frequency * 1000 >= fcp + state->srate / 4))
+                                       loop = 0;
                        }
-                       else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4))
-                               loop = 0;
                }
 
                loop = 1;
@@ -1126,13 +1154,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                        ftemp = ftemp - swp_ofs;
                        vmin--;
 
-                       // Lower bound
+                       /* Lower bound */
                        if (ftemp < 950000) {
                                loop = 0;
                                vmin++;
+                       } else {
+                               if ((ftemp == 950000) ||
+                                   (state->frequency * 1000 - ftemp >= fcp + state->srate / 4))
+                                       loop = 0;
                        }
-                       else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4))
-                               loop = 0;
                }
 
                wait_t = (8000 + state->srate / 2) / state->srate;
@@ -1176,7 +1206,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                        V[30 + v] = SIG1 ;
                        swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin,
                                                      SIG1MIN, fOSC, afcex_freq,
-                                                     swp_ofs, &SIG1);  //changed
+                                                     swp_ofs, &SIG1);  /* changed */
 
                        signal_dupl = 0;
                        for (j = 0; j < prev_freq_num; j++) {
@@ -1268,7 +1298,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                                dprintk(verbose, MB86A16_ERROR, 1, "srst error");
                                return -1;
                        }
-                       // delay 4~200
+                       /* delay 4~200 */
                        wait_t = 200000 / state->master_clk + 200000 / state->srate;
                        msleep(wait_t);
                        afcerr = afcerr_chk(state);
@@ -1429,6 +1459,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                                        S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
                                        wait_t = 7 + (2097152 + state->srate / 2) / state->srate;
                                }
+                               wait_t *= 2; /* FOS */
                                S2T_set(state, S2T);
                                S45T_set(state, S4T, S5T);
                                Vi_set(state, ETH, VIA);
@@ -1436,18 +1467,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                                msleep_interruptible(wait_t);
                                sync = sync_chk(state, &VIRM);
                                dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync);
-                               if (mb86a16_read(state, 0x0d, &state->signal) != 2) {
-                                       dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-                                       return -EREMOTEIO;
-                               }
                                if (VIRM) {
-                                       if (VIRM == 4) { // 5/6
+                                       if (VIRM == 4) {
+                                               /* 5/6 */
                                                if (SIG1 > 110)
-                                                       wait_t = ( 786432 + state->srate / 2) / state->srate;
+                                                       wait_t = (786432 + state->srate / 2) / state->srate;
                                                else
                                                        wait_t = (1572864 + state->srate / 2) / state->srate;
                                                if (state->srate < 5000)
-                                                       // FIXME ! , should be a long wait !
+                                                       /* FIXME ! , should be a long wait ! */
                                                        msleep_interruptible(wait_t);
                                                else
                                                        msleep_interruptible(wait_t);
@@ -1456,35 +1484,31 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
                                                        iq_vt_set(state, 1);
                                                        FEC_srst(state);
                                                }
-                                               if (SIG1 > 110)
-                                                       wait_t = ( 786432 + state->srate / 2) / state->srate;
-                                               else
-                                                       wait_t = (1572864 + state->srate / 2) / state->srate;
-
-                                               msleep_interruptible(wait_t);
-                                               SEQ_set(state, 1);
-                                       } else { // 1/2, 2/3, 3/4, 7/8
-                                               if (SIG1 > 110)
-                                                       wait_t = ( 786432 + state->srate / 2) / state->srate;
-                                               else
-                                                       wait_t = (1572864 + state->srate / 2) / state->srate;
-
-                                               msleep_interruptible(wait_t);
-                                               SEQ_set(state, 1);
                                        }
+                                       /* 1/2, 2/3, 3/4, 7/8 */
+                                       if (SIG1 > 110)
+                                               wait_t = (786432 + state->srate / 2) / state->srate;
+                                       else
+                                               wait_t = (1572864 + state->srate / 2) / state->srate;
+                                       msleep_interruptible(wait_t);
+                                       SEQ_set(state, 1);
                                } else {
-                                       dprintk(verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
+                                       dprintk(verbose, MB86A16_INFO, 1, "NO  -- SYNC");
                                        SEQ_set(state, 1);
+                                       ret = -1;
                                }
                        }
                } else {
-                       dprintk (verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
+                       dprintk(verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
+                       ret = -1;
                }
 
                sync = sync_chk(state, &junk);
                if (sync) {
                        dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******");
                        freqerr_chk(state, state->frequency, state->srate, 1);
+                       ret = 0;
+                       break;
                }
        }
 
@@ -1597,33 +1621,21 @@ err:
        return -EREMOTEIO;
 }
 
-#define MB86A16_FE_ALGO                1
-
-static int mb86a16_frontend_algo(struct dvb_frontend *fe)
+static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe,
+                                       struct dvb_frontend_parameters *p)
 {
-       return MB86A16_FE_ALGO;
-}
-
-static int mb86a16_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p,
-                               unsigned int mode_flags,
-                               int *delay,
-                               fe_status_t *status)
-{
-       int ret = 0;
        struct mb86a16_state *state = fe->demodulator_priv;
 
-       if (p != NULL) {
-               state->frequency = p->frequency / 1000;
-               state->srate = p->u.qpsk.symbol_rate / 1000;
-               ret = mb86a16_set_fe(state);
-       }
-       if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
-               mb86a16_read_status(fe, status);
+       state->frequency = p->frequency / 1000;
+       state->srate = p->u.qpsk.symbol_rate / 1000;
 
-       *delay = HZ/3000;
+       if (!mb86a16_set_fe(state)) {
+               dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK");
+               return DVBFE_ALGO_SEARCH_SUCCESS;
+       }
 
-       return ret;
+       dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!");
+       return DVBFE_ALGO_SEARCH_FAILED;
 }
 
 static void mb86a16_release(struct dvb_frontend *fe)
@@ -1644,12 +1656,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe)
 
 static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
+       u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst;
+       u32 timer;
+
+       struct mb86a16_state *state = fe->demodulator_priv;
+
+       *ber = 0;
+       if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2)
+               goto err;
+       if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2)
+               goto err;
+       if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2)
+               goto err;
+       if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2)
+               goto err;
+       if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2)
+               goto err;
+       /* BER monitor invalid when BER_EN = 0  */
+       if (ber_mon & 0x04) {
+               /* coarse, fast calculation     */
+               *ber = ber_tab & 0x1f;
+               dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber);
+               if (ber_mon & 0x01) {
+                       /*
+                        * BER_SEL = 1, The monitored BER is the estimated
+                        * value with a Reed-Solomon decoder error amount at
+                        * the deinterleaver output.
+                        * monitored BER is expressed as a 20 bit output in total
+                        */
+                       ber_rst = ber_mon >> 3;
+                       *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+                       if (ber_rst == 0)
+                               timer =  12500000;
+                       if (ber_rst == 1)
+                               timer =  25000000;
+                       if (ber_rst == 2)
+                               timer =  50000000;
+                       if (ber_rst == 3)
+                               timer = 100000000;
+
+                       *ber /= timer;
+                       dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+               } else {
+                       /*
+                        * BER_SEL = 0, The monitored BER is the estimated
+                        * value with a Viterbi decoder error amount at the
+                        * QPSK demodulator output.
+                        * monitored BER is expressed as a 24 bit output in total
+                        */
+                       ber_tim = ber_mon >> 1;
+                       *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+                       if (ber_tim == 0)
+                               timer = 16;
+                       if (ber_tim == 1)
+                               timer = 24;
+
+                       *ber /= 2 ^ timer;
+                       dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+               }
+       }
        return 0;
+err:
+       dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+       return -EREMOTEIO;
 }
 
 static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
+       u8 agcm = 0;
+       struct mb86a16_state *state = fe->demodulator_priv;
+
        *strength = 0;
+       if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) {
+               dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+               return -EREMOTEIO;
+       }
+
+       *strength = ((0xff - agcm) * 100) / 256;
+       dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength);
+       *strength = (0xffff - 0xff) + agcm;
 
        return 0;
 }
@@ -1690,6 +1775,7 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
        int low_tide = 2, high_tide = 30, q_level;
        u8  cn;
 
+       *snr = 0;
        if (mb86a16_read(state, 0x26, &cn) != 2) {
                dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
                return -EREMOTEIO;
@@ -1703,22 +1789,37 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
        }
        q_level = (*snr * 100) / (high_tide - low_tide);
        dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level);
+       *snr = (0xffff - 0xff) + *snr;
 
        return 0;
 }
 
 static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
+       u8 dist;
+       struct mb86a16_state *state = fe->demodulator_priv;
+
+       if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) {
+               dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+               return -EREMOTEIO;
+       }
+       *ucblocks = dist;
+
        return 0;
 }
 
+static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
+{
+       return DVBFE_ALGO_CUSTOM;
+}
+
 static struct dvb_frontend_ops mb86a16_ops = {
        .info = {
                .name                   = "Fujitsu MB86A16 DVB-S",
                .type                   = FE_QPSK,
                .frequency_min          = 950000,
                .frequency_max          = 2150000,
-               .frequency_stepsize     = 125,
+               .frequency_stepsize     = 3000,
                .frequency_tolerance    = 0,
                .symbol_rate_min        = 1000000,
                .symbol_rate_max        = 45000000,
@@ -1729,9 +1830,10 @@ static struct dvb_frontend_ops mb86a16_ops = {
                                          FE_CAN_FEC_AUTO
        },
        .release                        = mb86a16_release,
-       .tune                           = mb86a16_set_frontend,
-       .read_status                    = mb86a16_read_status,
+
        .get_frontend_algo              = mb86a16_frontend_algo,
+       .search                         = mb86a16_search,
+       .read_status                    = mb86a16_read_status,
        .init                           = mb86a16_init,
        .sleep                          = mb86a16_sleep,
        .read_status                    = mb86a16_read_status,
@@ -1752,7 +1854,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
        u8 dev_id = 0;
        struct mb86a16_state *state = NULL;
 
-       state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL);
+       state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
@@ -1763,7 +1865,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
        if (dev_id != 0xfe)
                goto error;
 
-       memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops));
+       memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        state->frontend.ops.set_voltage = state->config->set_voltage;