Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
0004  *
0005  * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
0006  *
0007  * This code is more or less generated from another driver, please
0008  * excuse some codingstyle oddities.
0009  */
0010 
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/i2c.h>
0016 #include <linux/mutex.h>
0017 
0018 #include <media/dvb_frontend.h>
0019 
0020 #include "dib0090.h"
0021 #include "dibx000_common.h"
0022 
0023 static int debug;
0024 module_param(debug, int, 0644);
0025 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
0026 
0027 #define dprintk(fmt, arg...) do {                   \
0028     if (debug)                          \
0029         printk(KERN_DEBUG pr_fmt("%s: " fmt),           \
0030                __func__, ##arg);                \
0031 } while (0)
0032 
0033 #define CONFIG_SYS_DVBT
0034 #define CONFIG_SYS_ISDBT
0035 #define CONFIG_BAND_CBAND
0036 #define CONFIG_BAND_VHF
0037 #define CONFIG_BAND_UHF
0038 #define CONFIG_DIB0090_USE_PWM_AGC
0039 
0040 #define EN_LNA0      0x8000
0041 #define EN_LNA1      0x4000
0042 #define EN_LNA2      0x2000
0043 #define EN_LNA3      0x1000
0044 #define EN_MIX0      0x0800
0045 #define EN_MIX1      0x0400
0046 #define EN_MIX2      0x0200
0047 #define EN_MIX3      0x0100
0048 #define EN_IQADC     0x0040
0049 #define EN_PLL       0x0020
0050 #define EN_TX        0x0010
0051 #define EN_BB        0x0008
0052 #define EN_LO        0x0004
0053 #define EN_BIAS      0x0001
0054 
0055 #define EN_IQANA     0x0002
0056 #define EN_DIGCLK    0x0080 /* not in the 0x24 reg, only in 0x1b */
0057 #define EN_CRYSTAL   0x0002
0058 
0059 #define EN_UHF       0x22E9
0060 #define EN_VHF       0x44E9
0061 #define EN_LBD       0x11E9
0062 #define EN_SBD       0x44E9
0063 #define EN_CAB       0x88E9
0064 
0065 /* Calibration defines */
0066 #define      DC_CAL 0x1
0067 #define     WBD_CAL 0x2
0068 #define    TEMP_CAL 0x4
0069 #define CAPTRIM_CAL 0x8
0070 
0071 #define KROSUS_PLL_LOCKED   0x800
0072 #define KROSUS              0x2
0073 
0074 /* Use those defines to identify SOC version */
0075 #define SOC               0x02
0076 #define SOC_7090_P1G_11R1 0x82
0077 #define SOC_7090_P1G_21R1 0x8a
0078 #define SOC_8090_P1G_11R1 0x86
0079 #define SOC_8090_P1G_21R1 0x8e
0080 
0081 /* else use thos ones to check */
0082 #define P1A_B      0x0
0083 #define P1C    0x1
0084 #define P1D_E_F    0x3
0085 #define P1G    0x7
0086 #define P1G_21R2   0xf
0087 
0088 #define MP001 0x1       /* Single 9090/8096 */
0089 #define MP005 0x4       /* Single Sband */
0090 #define MP008 0x6       /* Dual diversity VHF-UHF-LBAND */
0091 #define MP009 0x7       /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
0092 
0093 #define pgm_read_word(w) (*w)
0094 
0095 struct dc_calibration;
0096 
0097 struct dib0090_tuning {
0098     u32 max_freq;       /* for every frequency less than or equal to that field: this information is correct */
0099     u8 switch_trim;
0100     u8 lna_tune;
0101     u16 lna_bias;
0102     u16 v2i;
0103     u16 mix;
0104     u16 load;
0105     u16 tuner_enable;
0106 };
0107 
0108 struct dib0090_pll {
0109     u32 max_freq;       /* for every frequency less than or equal to that field: this information is correct */
0110     u8 vco_band;
0111     u8 hfdiv_code;
0112     u8 hfdiv;
0113     u8 topresc;
0114 };
0115 
0116 struct dib0090_identity {
0117     u8 version;
0118     u8 product;
0119     u8 p1g;
0120     u8 in_soc;
0121 };
0122 
0123 struct dib0090_state {
0124     struct i2c_adapter *i2c;
0125     struct dvb_frontend *fe;
0126     const struct dib0090_config *config;
0127 
0128     u8 current_band;
0129     enum frontend_tune_state tune_state;
0130     u32 current_rf;
0131 
0132     u16 wbd_offset;
0133     s16 wbd_target;     /* in dB */
0134 
0135     s16 rf_gain_limit;  /* take-over-point: where to split between bb and rf gain */
0136     s16 current_gain;   /* keeps the currently programmed gain */
0137     u8 agc_step;        /* new binary search */
0138 
0139     u16 gain[2];        /* for channel monitoring */
0140 
0141     const u16 *rf_ramp;
0142     const u16 *bb_ramp;
0143 
0144     /* for the software AGC ramps */
0145     u16 bb_1_def;
0146     u16 rf_lt_def;
0147     u16 gain_reg[4];
0148 
0149     /* for the captrim/dc-offset search */
0150     s8 step;
0151     s16 adc_diff;
0152     s16 min_adc_diff;
0153 
0154     s8 captrim;
0155     s8 fcaptrim;
0156 
0157     const struct dc_calibration *dc;
0158     u16 bb6, bb7;
0159 
0160     const struct dib0090_tuning *current_tune_table_index;
0161     const struct dib0090_pll *current_pll_table_index;
0162 
0163     u8 tuner_is_tuned;
0164     u8 agc_freeze;
0165 
0166     struct dib0090_identity identity;
0167 
0168     u32 rf_request;
0169     u8 current_standard;
0170 
0171     u8 calibrate;
0172     u32 rest;
0173     u16 bias;
0174     s16 temperature;
0175 
0176     u8 wbd_calibration_gain;
0177     const struct dib0090_wbd_slope *current_wbd_table;
0178     u16 wbdmux;
0179 
0180     /* for the I2C transfer */
0181     struct i2c_msg msg[2];
0182     u8 i2c_write_buffer[3];
0183     u8 i2c_read_buffer[2];
0184     struct mutex i2c_buffer_lock;
0185 };
0186 
0187 struct dib0090_fw_state {
0188     struct i2c_adapter *i2c;
0189     struct dvb_frontend *fe;
0190     struct dib0090_identity identity;
0191     const struct dib0090_config *config;
0192 
0193     /* for the I2C transfer */
0194     struct i2c_msg msg;
0195     u8 i2c_write_buffer[2];
0196     u8 i2c_read_buffer[2];
0197     struct mutex i2c_buffer_lock;
0198 };
0199 
0200 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
0201 {
0202     u16 ret;
0203 
0204     if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0205         dprintk("could not acquire lock\n");
0206         return 0;
0207     }
0208 
0209     state->i2c_write_buffer[0] = reg;
0210 
0211     memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
0212     state->msg[0].addr = state->config->i2c_address;
0213     state->msg[0].flags = 0;
0214     state->msg[0].buf = state->i2c_write_buffer;
0215     state->msg[0].len = 1;
0216     state->msg[1].addr = state->config->i2c_address;
0217     state->msg[1].flags = I2C_M_RD;
0218     state->msg[1].buf = state->i2c_read_buffer;
0219     state->msg[1].len = 2;
0220 
0221     if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
0222         pr_warn("DiB0090 I2C read failed\n");
0223         ret = 0;
0224     } else
0225         ret = (state->i2c_read_buffer[0] << 8)
0226             | state->i2c_read_buffer[1];
0227 
0228     mutex_unlock(&state->i2c_buffer_lock);
0229     return ret;
0230 }
0231 
0232 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
0233 {
0234     int ret;
0235 
0236     if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0237         dprintk("could not acquire lock\n");
0238         return -EINVAL;
0239     }
0240 
0241     state->i2c_write_buffer[0] = reg & 0xff;
0242     state->i2c_write_buffer[1] = val >> 8;
0243     state->i2c_write_buffer[2] = val & 0xff;
0244 
0245     memset(state->msg, 0, sizeof(struct i2c_msg));
0246     state->msg[0].addr = state->config->i2c_address;
0247     state->msg[0].flags = 0;
0248     state->msg[0].buf = state->i2c_write_buffer;
0249     state->msg[0].len = 3;
0250 
0251     if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
0252         pr_warn("DiB0090 I2C write failed\n");
0253         ret = -EREMOTEIO;
0254     } else
0255         ret = 0;
0256 
0257     mutex_unlock(&state->i2c_buffer_lock);
0258     return ret;
0259 }
0260 
0261 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
0262 {
0263     u16 ret;
0264 
0265     if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0266         dprintk("could not acquire lock\n");
0267         return 0;
0268     }
0269 
0270     state->i2c_write_buffer[0] = reg;
0271 
0272     memset(&state->msg, 0, sizeof(struct i2c_msg));
0273     state->msg.addr = reg;
0274     state->msg.flags = I2C_M_RD;
0275     state->msg.buf = state->i2c_read_buffer;
0276     state->msg.len = 2;
0277     if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
0278         pr_warn("DiB0090 I2C read failed\n");
0279         ret = 0;
0280     } else
0281         ret = (state->i2c_read_buffer[0] << 8)
0282             | state->i2c_read_buffer[1];
0283 
0284     mutex_unlock(&state->i2c_buffer_lock);
0285     return ret;
0286 }
0287 
0288 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
0289 {
0290     int ret;
0291 
0292     if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0293         dprintk("could not acquire lock\n");
0294         return -EINVAL;
0295     }
0296 
0297     state->i2c_write_buffer[0] = val >> 8;
0298     state->i2c_write_buffer[1] = val & 0xff;
0299 
0300     memset(&state->msg, 0, sizeof(struct i2c_msg));
0301     state->msg.addr = reg;
0302     state->msg.flags = 0;
0303     state->msg.buf = state->i2c_write_buffer;
0304     state->msg.len = 2;
0305     if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
0306         pr_warn("DiB0090 I2C write failed\n");
0307         ret = -EREMOTEIO;
0308     } else
0309         ret = 0;
0310 
0311     mutex_unlock(&state->i2c_buffer_lock);
0312     return ret;
0313 }
0314 
0315 #define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
0316 #define ADC_TARGET -220
0317 #define GAIN_ALPHA 5
0318 #define WBD_ALPHA 6
0319 #define LPF 100
0320 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
0321 {
0322     do {
0323         dib0090_write_reg(state, r++, *b++);
0324     } while (--c);
0325 }
0326 
0327 static int dib0090_identify(struct dvb_frontend *fe)
0328 {
0329     struct dib0090_state *state = fe->tuner_priv;
0330     u16 v;
0331     struct dib0090_identity *identity = &state->identity;
0332 
0333     v = dib0090_read_reg(state, 0x1a);
0334 
0335     identity->p1g = 0;
0336     identity->in_soc = 0;
0337 
0338     dprintk("Tuner identification (Version = 0x%04x)\n", v);
0339 
0340     /* without PLL lock info */
0341     v &= ~KROSUS_PLL_LOCKED;
0342 
0343     identity->version = v & 0xff;
0344     identity->product = (v >> 8) & 0xf;
0345 
0346     if (identity->product != KROSUS)
0347         goto identification_error;
0348 
0349     if ((identity->version & 0x3) == SOC) {
0350         identity->in_soc = 1;
0351         switch (identity->version) {
0352         case SOC_8090_P1G_11R1:
0353             dprintk("SOC 8090 P1-G11R1 Has been detected\n");
0354             identity->p1g = 1;
0355             break;
0356         case SOC_8090_P1G_21R1:
0357             dprintk("SOC 8090 P1-G21R1 Has been detected\n");
0358             identity->p1g = 1;
0359             break;
0360         case SOC_7090_P1G_11R1:
0361             dprintk("SOC 7090 P1-G11R1 Has been detected\n");
0362             identity->p1g = 1;
0363             break;
0364         case SOC_7090_P1G_21R1:
0365             dprintk("SOC 7090 P1-G21R1 Has been detected\n");
0366             identity->p1g = 1;
0367             break;
0368         default:
0369             goto identification_error;
0370         }
0371     } else {
0372         switch ((identity->version >> 5) & 0x7) {
0373         case MP001:
0374             dprintk("MP001 : 9090/8096\n");
0375             break;
0376         case MP005:
0377             dprintk("MP005 : Single Sband\n");
0378             break;
0379         case MP008:
0380             dprintk("MP008 : diversity VHF-UHF-LBAND\n");
0381             break;
0382         case MP009:
0383             dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
0384             break;
0385         default:
0386             goto identification_error;
0387         }
0388 
0389         switch (identity->version & 0x1f) {
0390         case P1G_21R2:
0391             dprintk("P1G_21R2 detected\n");
0392             identity->p1g = 1;
0393             break;
0394         case P1G:
0395             dprintk("P1G detected\n");
0396             identity->p1g = 1;
0397             break;
0398         case P1D_E_F:
0399             dprintk("P1D/E/F detected\n");
0400             break;
0401         case P1C:
0402             dprintk("P1C detected\n");
0403             break;
0404         case P1A_B:
0405             dprintk("P1-A/B detected: driver is deactivated - not available\n");
0406             goto identification_error;
0407             break;
0408         default:
0409             goto identification_error;
0410         }
0411     }
0412 
0413     return 0;
0414 
0415 identification_error:
0416     return -EIO;
0417 }
0418 
0419 static int dib0090_fw_identify(struct dvb_frontend *fe)
0420 {
0421     struct dib0090_fw_state *state = fe->tuner_priv;
0422     struct dib0090_identity *identity = &state->identity;
0423 
0424     u16 v = dib0090_fw_read_reg(state, 0x1a);
0425     identity->p1g = 0;
0426     identity->in_soc = 0;
0427 
0428     dprintk("FE: Tuner identification (Version = 0x%04x)\n", v);
0429 
0430     /* without PLL lock info */
0431     v &= ~KROSUS_PLL_LOCKED;
0432 
0433     identity->version = v & 0xff;
0434     identity->product = (v >> 8) & 0xf;
0435 
0436     if (identity->product != KROSUS)
0437         goto identification_error;
0438 
0439     if ((identity->version & 0x3) == SOC) {
0440         identity->in_soc = 1;
0441         switch (identity->version) {
0442         case SOC_8090_P1G_11R1:
0443             dprintk("SOC 8090 P1-G11R1 Has been detected\n");
0444             identity->p1g = 1;
0445             break;
0446         case SOC_8090_P1G_21R1:
0447             dprintk("SOC 8090 P1-G21R1 Has been detected\n");
0448             identity->p1g = 1;
0449             break;
0450         case SOC_7090_P1G_11R1:
0451             dprintk("SOC 7090 P1-G11R1 Has been detected\n");
0452             identity->p1g = 1;
0453             break;
0454         case SOC_7090_P1G_21R1:
0455             dprintk("SOC 7090 P1-G21R1 Has been detected\n");
0456             identity->p1g = 1;
0457             break;
0458         default:
0459             goto identification_error;
0460         }
0461     } else {
0462         switch ((identity->version >> 5) & 0x7) {
0463         case MP001:
0464             dprintk("MP001 : 9090/8096\n");
0465             break;
0466         case MP005:
0467             dprintk("MP005 : Single Sband\n");
0468             break;
0469         case MP008:
0470             dprintk("MP008 : diversity VHF-UHF-LBAND\n");
0471             break;
0472         case MP009:
0473             dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
0474             break;
0475         default:
0476             goto identification_error;
0477         }
0478 
0479         switch (identity->version & 0x1f) {
0480         case P1G_21R2:
0481             dprintk("P1G_21R2 detected\n");
0482             identity->p1g = 1;
0483             break;
0484         case P1G:
0485             dprintk("P1G detected\n");
0486             identity->p1g = 1;
0487             break;
0488         case P1D_E_F:
0489             dprintk("P1D/E/F detected\n");
0490             break;
0491         case P1C:
0492             dprintk("P1C detected\n");
0493             break;
0494         case P1A_B:
0495             dprintk("P1-A/B detected: driver is deactivated - not available\n");
0496             goto identification_error;
0497             break;
0498         default:
0499             goto identification_error;
0500         }
0501     }
0502 
0503     return 0;
0504 
0505 identification_error:
0506     return -EIO;
0507 }
0508 
0509 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
0510 {
0511     struct dib0090_state *state = fe->tuner_priv;
0512     u16 PllCfg, i, v;
0513 
0514     HARD_RESET(state);
0515     dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
0516     if (cfg->in_soc)
0517         return;
0518 
0519     dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);    /* PLL, DIG_CLK and CRYSTAL remain */
0520     /* adcClkOutRatio=8->7, release reset */
0521     dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
0522     if (cfg->clkoutdrive != 0)
0523         dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
0524                 | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
0525     else
0526         dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
0527                 | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
0528 
0529     /* Read Pll current config * */
0530     PllCfg = dib0090_read_reg(state, 0x21);
0531 
0532     /** Reconfigure PLL if current setting is different from default setting **/
0533     if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
0534             && !cfg->io.pll_bypass) {
0535 
0536         /* Set Bypass mode */
0537         PllCfg |= (1 << 15);
0538         dib0090_write_reg(state, 0x21, PllCfg);
0539 
0540         /* Set Reset Pll */
0541         PllCfg &= ~(1 << 13);
0542         dib0090_write_reg(state, 0x21, PllCfg);
0543 
0544     /*** Set new Pll configuration in bypass and reset state ***/
0545         PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
0546         dib0090_write_reg(state, 0x21, PllCfg);
0547 
0548         /* Remove Reset Pll */
0549         PllCfg |= (1 << 13);
0550         dib0090_write_reg(state, 0x21, PllCfg);
0551 
0552     /*** Wait for PLL lock ***/
0553         i = 100;
0554         do {
0555             v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
0556             if (v)
0557                 break;
0558         } while (--i);
0559 
0560         if (i == 0) {
0561             dprintk("Pll: Unable to lock Pll\n");
0562             return;
0563         }
0564 
0565         /* Finally Remove Bypass mode */
0566         PllCfg &= ~(1 << 15);
0567         dib0090_write_reg(state, 0x21, PllCfg);
0568     }
0569 
0570     if (cfg->io.pll_bypass) {
0571         PllCfg |= (cfg->io.pll_bypass << 15);
0572         dib0090_write_reg(state, 0x21, PllCfg);
0573     }
0574 }
0575 
0576 static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
0577 {
0578     struct dib0090_fw_state *state = fe->tuner_priv;
0579     u16 PllCfg;
0580     u16 v;
0581     int i;
0582 
0583     dprintk("fw reset digital\n");
0584     HARD_RESET(state);
0585 
0586     dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
0587     dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
0588 
0589     dib0090_fw_write_reg(state, 0x20,
0590             ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
0591 
0592     v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
0593     if (cfg->clkoutdrive != 0)
0594         v |= cfg->clkoutdrive << 5;
0595     else
0596         v |= 7 << 5;
0597 
0598     v |= 2 << 10;
0599     dib0090_fw_write_reg(state, 0x23, v);
0600 
0601     /* Read Pll current config * */
0602     PllCfg = dib0090_fw_read_reg(state, 0x21);
0603 
0604     /** Reconfigure PLL if current setting is different from default setting **/
0605     if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
0606 
0607         /* Set Bypass mode */
0608         PllCfg |= (1 << 15);
0609         dib0090_fw_write_reg(state, 0x21, PllCfg);
0610 
0611         /* Set Reset Pll */
0612         PllCfg &= ~(1 << 13);
0613         dib0090_fw_write_reg(state, 0x21, PllCfg);
0614 
0615     /*** Set new Pll configuration in bypass and reset state ***/
0616         PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
0617         dib0090_fw_write_reg(state, 0x21, PllCfg);
0618 
0619         /* Remove Reset Pll */
0620         PllCfg |= (1 << 13);
0621         dib0090_fw_write_reg(state, 0x21, PllCfg);
0622 
0623     /*** Wait for PLL lock ***/
0624         i = 100;
0625         do {
0626             v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
0627             if (v)
0628                 break;
0629         } while (--i);
0630 
0631         if (i == 0) {
0632             dprintk("Pll: Unable to lock Pll\n");
0633             return -EIO;
0634         }
0635 
0636         /* Finally Remove Bypass mode */
0637         PllCfg &= ~(1 << 15);
0638         dib0090_fw_write_reg(state, 0x21, PllCfg);
0639     }
0640 
0641     if (cfg->io.pll_bypass) {
0642         PllCfg |= (cfg->io.pll_bypass << 15);
0643         dib0090_fw_write_reg(state, 0x21, PllCfg);
0644     }
0645 
0646     return dib0090_fw_identify(fe);
0647 }
0648 
0649 static int dib0090_wakeup(struct dvb_frontend *fe)
0650 {
0651     struct dib0090_state *state = fe->tuner_priv;
0652     if (state->config->sleep)
0653         state->config->sleep(fe, 0);
0654 
0655     /* enable dataTX in case we have been restarted in the wrong moment */
0656     dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
0657     return 0;
0658 }
0659 
0660 static int dib0090_sleep(struct dvb_frontend *fe)
0661 {
0662     struct dib0090_state *state = fe->tuner_priv;
0663     if (state->config->sleep)
0664         state->config->sleep(fe, 1);
0665     return 0;
0666 }
0667 
0668 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
0669 {
0670     struct dib0090_state *state = fe->tuner_priv;
0671     if (fast)
0672         dib0090_write_reg(state, 0x04, 0);
0673     else
0674         dib0090_write_reg(state, 0x04, 1);
0675 }
0676 
0677 EXPORT_SYMBOL(dib0090_dcc_freq);
0678 
0679 static const u16 bb_ramp_pwm_normal_socs[] = {
0680     550, /* max BB gain in 10th of dB */
0681     (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
0682     440,
0683     (4  << 9) | 0, /* BB_RAMP3 = 26dB */
0684     (0  << 9) | 208, /* BB_RAMP4 */
0685     (4  << 9) | 208, /* BB_RAMP5 = 29dB */
0686     (0  << 9) | 440, /* BB_RAMP6 */
0687 };
0688 
0689 static const u16 rf_ramp_pwm_cband_7090p[] = {
0690     280, /* max RF gain in 10th of dB */
0691     18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0692     504, /* ramp_max = maximum X used on the ramp */
0693     (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
0694     (0  << 10) | 504, /* RF_RAMP6, LNA 1 */
0695     (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
0696     (0  << 10) | 364, /* RF_RAMP8, LNA 2 */
0697     (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
0698     (0  << 10) | 228, /* GAIN_4_2, LNA 3 */
0699     (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
0700     (0  << 10) | 109, /* RF_RAMP4, LNA 4 */
0701 };
0702 
0703 static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
0704     186, /* max RF gain in 10th of dB */
0705     40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0706     746, /* ramp_max = maximum X used on the ramp */
0707     (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
0708     (0  << 10) | 746, /* RF_RAMP6, LNA 1 */
0709     (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
0710     (0  << 10) | 0, /* RF_RAMP8, LNA 2 */
0711     (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
0712     (0  << 10) | 345, /* GAIN_4_2, LNA 3 */
0713     (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
0714     (0  << 10) | 200, /* RF_RAMP4, LNA 4 */
0715 };
0716 
0717 static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
0718     86, /* max RF gain in 10th of dB */
0719     40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0720     345, /* ramp_max = maximum X used on the ramp */
0721     (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
0722     (0 << 10) | 0, /* RF_RAMP6, LNA 1 */
0723     (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
0724     (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
0725     (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
0726     (0  << 10) | 345, /* GAIN_4_2, LNA 3 */
0727     (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
0728     (0  << 10) | 200, /* RF_RAMP4, LNA 4 */
0729 };
0730 
0731 static const u16 rf_ramp_pwm_cband_8090[] = {
0732     345, /* max RF gain in 10th of dB */
0733     29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0734     1000, /* ramp_max = maximum X used on the ramp */
0735     (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
0736     (0  << 10) | 1000, /* RF_RAMP4, LNA 1 */
0737     (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
0738     (0  << 10) | 772, /* RF_RAMP6, LNA 2 */
0739     (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
0740     (0  << 10) | 496, /* RF_RAMP8, LNA 3 */
0741     (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
0742     (0  << 10) | 200, /* GAIN_4_2, LNA 4 */
0743 };
0744 
0745 static const u16 rf_ramp_pwm_uhf_7090[] = {
0746     407, /* max RF gain in 10th of dB */
0747     13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0748     529, /* ramp_max = maximum X used on the ramp */
0749     (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
0750     (0  << 10) | 176, /* RF_RAMP4, LNA 1 */
0751     (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
0752     (0  << 10) | 529, /* RF_RAMP6, LNA 2 */
0753     (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
0754     (0  << 10) | 400, /* RF_RAMP8, LNA 3 */
0755     (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
0756     (0  << 10) | 316, /* GAIN_4_2, LNA 4 */
0757 };
0758 
0759 static const u16 rf_ramp_pwm_uhf_8090[] = {
0760     388, /* max RF gain in 10th of dB */
0761     26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0762     1008, /* ramp_max = maximum X used on the ramp */
0763     (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
0764     (0  << 10) | 369, /* RF_RAMP4, LNA 1 */
0765     (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
0766     (0  << 10) | 1008, /* RF_RAMP6, LNA 2 */
0767     (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
0768     (0  << 10) | 809, /* RF_RAMP8, LNA 3 */
0769     (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
0770     (0  << 10) | 659, /* GAIN_4_2, LNA 4 */
0771 };
0772 
0773 /* GENERAL PWM ramp definition for all other Krosus */
0774 static const u16 bb_ramp_pwm_normal[] = {
0775     500, /* max BB gain in 10th of dB */
0776     8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
0777     400,
0778     (2  << 9) | 0, /* BB_RAMP3 = 21dB */
0779     (0  << 9) | 168, /* BB_RAMP4 */
0780     (2  << 9) | 168, /* BB_RAMP5 = 29dB */
0781     (0  << 9) | 400, /* BB_RAMP6 */
0782 };
0783 
0784 #if 0
0785 /* Currently unused */
0786 static const u16 bb_ramp_pwm_boost[] = {
0787     550, /* max BB gain in 10th of dB */
0788     8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
0789     440,
0790     (2  << 9) | 0, /* BB_RAMP3 = 26dB */
0791     (0  << 9) | 208, /* BB_RAMP4 */
0792     (2  << 9) | 208, /* BB_RAMP5 = 29dB */
0793     (0  << 9) | 440, /* BB_RAMP6 */
0794 };
0795 #endif
0796 
0797 static const u16 rf_ramp_pwm_cband[] = {
0798     314, /* max RF gain in 10th of dB */
0799     33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0800     1023, /* ramp_max = maximum X used on the ramp */
0801     (8  << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
0802     (0  << 10) | 1023, /* RF_RAMP4, LNA 1 */
0803     (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
0804     (0  << 10) | 742, /* RF_RAMP6, LNA 2 */
0805     (9  << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
0806     (0  << 10) | 468, /* RF_RAMP8, LNA 3 */
0807     (9  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
0808     (0  << 10) | 233, /* GAIN_4_2, LNA 4 */
0809 };
0810 
0811 static const u16 rf_ramp_pwm_vhf[] = {
0812     398, /* max RF gain in 10th of dB */
0813     24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0814     954, /* ramp_max = maximum X used on the ramp */
0815     (7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
0816     (0  << 10) | 290, /* RF_RAMP4, LNA 1 */
0817     (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
0818     (0  << 10) | 954, /* RF_RAMP6, LNA 2 */
0819     (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
0820     (0  << 10) | 699, /* RF_RAMP8, LNA 3 */
0821     (7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
0822     (0  << 10) | 580, /* GAIN_4_2, LNA 4 */
0823 };
0824 
0825 static const u16 rf_ramp_pwm_uhf[] = {
0826     398, /* max RF gain in 10th of dB */
0827     24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0828     954, /* ramp_max = maximum X used on the ramp */
0829     (7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
0830     (0  << 10) | 290, /* RF_RAMP4, LNA 1 */
0831     (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
0832     (0  << 10) | 954, /* RF_RAMP6, LNA 2 */
0833     (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
0834     (0  << 10) | 699, /* RF_RAMP8, LNA 3 */
0835     (7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
0836     (0  << 10) | 580, /* GAIN_4_2, LNA 4 */
0837 };
0838 
0839 #if 0
0840 /* Currently unused */
0841 static const u16 rf_ramp_pwm_sband[] = {
0842     253, /* max RF gain in 10th of dB */
0843     38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
0844     961,
0845     (4  << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
0846     (0  << 10) | 508, /* RF_RAMP4, LNA 1 */
0847     (9  << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
0848     (0  << 10) | 961, /* RF_RAMP6, LNA 2 */
0849     (0  << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
0850     (0  << 10) | 0, /* RF_RAMP8, LNA 3 */
0851     (0  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
0852     (0  << 10) | 0, /* GAIN_4_2, LNA 4 */
0853 };
0854 #endif
0855 
0856 struct slope {
0857     s16 range;
0858     s16 slope;
0859 };
0860 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
0861 {
0862     u8 i;
0863     u16 rest;
0864     u16 ret = 0;
0865     for (i = 0; i < num; i++) {
0866         if (val > slopes[i].range)
0867             rest = slopes[i].range;
0868         else
0869             rest = val;
0870         ret += (rest * slopes[i].slope) / slopes[i].range;
0871         val -= rest;
0872     }
0873     return ret;
0874 }
0875 
0876 static const struct slope dib0090_wbd_slopes[3] = {
0877     {66, 120},      /* -64,-52: offset -   65 */
0878     {600, 170},     /* -52,-35: 65     -  665 */
0879     {170, 250},     /* -45,-10: 665    - 835 */
0880 };
0881 
0882 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
0883 {
0884     wbd &= 0x3ff;
0885     if (wbd < state->wbd_offset)
0886         wbd = 0;
0887     else
0888         wbd -= state->wbd_offset;
0889     /* -64dB is the floor */
0890     return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
0891 }
0892 
0893 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
0894 {
0895     u16 offset = 250;
0896 
0897     /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
0898 
0899     if (state->current_band == BAND_VHF)
0900         offset = 650;
0901 #ifndef FIRMWARE_FIREFLY
0902     if (state->current_band == BAND_VHF)
0903         offset = state->config->wbd_vhf_offset;
0904     if (state->current_band == BAND_CBAND)
0905         offset = state->config->wbd_cband_offset;
0906 #endif
0907 
0908     state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
0909     dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
0910 }
0911 
0912 static const int gain_reg_addr[4] = {
0913     0x08, 0x0a, 0x0f, 0x01
0914 };
0915 
0916 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
0917 {
0918     u16 rf, bb, ref;
0919     u16 i, v, gain_reg[4] = { 0 }, gain;
0920     const u16 *g;
0921 
0922     if (top_delta < -511)
0923         top_delta = -511;
0924     if (top_delta > 511)
0925         top_delta = 511;
0926 
0927     if (force) {
0928         top_delta *= (1 << WBD_ALPHA);
0929         gain_delta *= (1 << GAIN_ALPHA);
0930     }
0931 
0932     if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))   /* overflow */
0933         state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
0934     else
0935         state->rf_gain_limit += top_delta;
0936 
0937     if (state->rf_gain_limit < 0)   /*underflow */
0938         state->rf_gain_limit = 0;
0939 
0940     /* use gain as a temporary variable and correct current_gain */
0941     gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
0942     if (gain_delta >= ((s16) gain - state->current_gain))   /* overflow */
0943         state->current_gain = gain;
0944     else
0945         state->current_gain += gain_delta;
0946     /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
0947     if (state->current_gain < 0)
0948         state->current_gain = 0;
0949 
0950     /* now split total gain to rf and bb gain */
0951     gain = state->current_gain >> GAIN_ALPHA;
0952 
0953     /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
0954     if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
0955         rf = state->rf_gain_limit >> WBD_ALPHA;
0956         bb = gain - rf;
0957         if (bb > state->bb_ramp[0])
0958             bb = state->bb_ramp[0];
0959     } else {        /* high signal level -> all gains put on RF */
0960         rf = gain;
0961         bb = 0;
0962     }
0963 
0964     state->gain[0] = rf;
0965     state->gain[1] = bb;
0966 
0967     /* software ramp */
0968     /* Start with RF gains */
0969     g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
0970     ref = rf;
0971     for (i = 0; i < 7; i++) {   /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
0972         if (g[0] == 0 || ref < (g[1] - g[0]))   /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
0973             v = 0;  /* force the gain to write for the current amp to be null */
0974         else if (ref >= g[1])   /* Gain to set is higher than the high working point of this amp */
0975             v = g[2];   /* force this amp to be full gain */
0976         else        /* compute the value to set to this amp because we are somewhere in his range */
0977             v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
0978 
0979         if (i == 0) /* LNA 1 reg mapping */
0980             gain_reg[0] = v;
0981         else if (i == 1)    /* LNA 2 reg mapping */
0982             gain_reg[0] |= v << 7;
0983         else if (i == 2)    /* LNA 3 reg mapping */
0984             gain_reg[1] = v;
0985         else if (i == 3)    /* LNA 4 reg mapping */
0986             gain_reg[1] |= v << 7;
0987         else if (i == 4)    /* CBAND LNA reg mapping */
0988             gain_reg[2] = v | state->rf_lt_def;
0989         else if (i == 5)    /* BB gain 1 reg mapping */
0990             gain_reg[3] = v << 3;
0991         else if (i == 6)    /* BB gain 2 reg mapping */
0992             gain_reg[3] |= v << 8;
0993 
0994         g += 3;     /* go to next gain bloc */
0995 
0996         /* When RF is finished, start with BB */
0997         if (i == 4) {
0998             g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
0999             ref = bb;
1000         }
1001     }
1002     gain_reg[3] |= state->bb_1_def;
1003     gain_reg[3] |= ((bb % 10) * 100) / 125;
1004 
1005 #ifdef DEBUG_AGC
1006     dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x\n", rf, bb, rf + bb,
1007         gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1008 #endif
1009 
1010     /* Write the amplifier regs */
1011     for (i = 0; i < 4; i++) {
1012         v = gain_reg[i];
1013         if (force || state->gain_reg[i] != v) {
1014             state->gain_reg[i] = v;
1015             dib0090_write_reg(state, gain_reg_addr[i], v);
1016         }
1017     }
1018 }
1019 
1020 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1021 {
1022     state->bb_1_def &= 0xdfff;
1023     state->bb_1_def |= onoff << 13;
1024 }
1025 
1026 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1027 {
1028     state->rf_ramp = cfg;
1029 }
1030 
1031 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1032 {
1033     state->rf_ramp = cfg;
1034 
1035     dib0090_write_reg(state, 0x2a, 0xffff);
1036 
1037     dprintk("total RF gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1038 
1039     dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1040     dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1041 }
1042 
1043 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1044 {
1045     state->bb_ramp = cfg;
1046     dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1047 }
1048 
1049 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1050 {
1051     state->bb_ramp = cfg;
1052 
1053     dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1054 
1055     dib0090_write_reg(state, 0x33, 0xffff);
1056     dprintk("total BB gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1057     dib0090_write_regs(state, 0x35, cfg + 3, 4);
1058 }
1059 
1060 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1061 {
1062     struct dib0090_state *state = fe->tuner_priv;
1063     const u16 *bb_ramp = bb_ramp_pwm_normal; /* default baseband config */
1064     const u16 *rf_ramp = NULL;
1065     u8 en_pwm_rf_mux = 1;
1066 
1067     /* reset the AGC */
1068     if (state->config->use_pwm_agc) {
1069         if (state->current_band == BAND_CBAND) {
1070             if (state->identity.in_soc) {
1071                 bb_ramp = bb_ramp_pwm_normal_socs;
1072                 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1073                     rf_ramp = rf_ramp_pwm_cband_8090;
1074                 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1075                     if (state->config->is_dib7090e) {
1076                         if (state->rf_ramp == NULL)
1077                             rf_ramp = rf_ramp_pwm_cband_7090e_sensitivity;
1078                         else
1079                             rf_ramp = state->rf_ramp;
1080                     } else
1081                         rf_ramp = rf_ramp_pwm_cband_7090p;
1082                 }
1083             } else
1084                 rf_ramp = rf_ramp_pwm_cband;
1085         } else
1086 
1087             if (state->current_band == BAND_VHF) {
1088                 if (state->identity.in_soc) {
1089                     bb_ramp = bb_ramp_pwm_normal_socs;
1090                     /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
1091                 } else
1092                     rf_ramp = rf_ramp_pwm_vhf;
1093             } else if (state->current_band == BAND_UHF) {
1094                 if (state->identity.in_soc) {
1095                     bb_ramp = bb_ramp_pwm_normal_socs;
1096                     if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1097                         rf_ramp = rf_ramp_pwm_uhf_8090;
1098                     else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1099                         rf_ramp = rf_ramp_pwm_uhf_7090;
1100                 } else
1101                     rf_ramp = rf_ramp_pwm_uhf;
1102             }
1103         if (rf_ramp)
1104             dib0090_set_rframp_pwm(state, rf_ramp);
1105         dib0090_set_bbramp_pwm(state, bb_ramp);
1106 
1107         /* activate the ramp generator using PWM control */
1108         if (state->rf_ramp)
1109             dprintk("ramp RF gain = %d BAND = %s version = %d\n",
1110                 state->rf_ramp[0],
1111                 (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND",
1112                 state->identity.version & 0x1f);
1113 
1114         if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) ||
1115             (state->current_band == BAND_CBAND &&
1116             (state->identity.version & 0x1f) <= P1D_E_F))) {
1117             dprintk("DE-Engage mux for direct gain reg control\n");
1118             en_pwm_rf_mux = 0;
1119         } else
1120             dprintk("Engage mux for PWM control\n");
1121 
1122         dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1123 
1124         /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
1125         if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1126             dib0090_write_reg(state, 0x04, 3);
1127         else
1128             dib0090_write_reg(state, 0x04, 1);
1129         dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
1130     }
1131 }
1132 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1133 
1134 void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1135 {
1136     struct dib0090_state *state = fe->tuner_priv;
1137     if (DC_servo_cutoff < 4)
1138         dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1139 }
1140 EXPORT_SYMBOL(dib0090_set_dc_servo);
1141 
1142 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1143 {
1144     u16 adc_val = dib0090_read_reg(state, 0x1d);
1145     if (state->identity.in_soc)
1146         adc_val >>= 2;
1147     return adc_val;
1148 }
1149 
1150 int dib0090_gain_control(struct dvb_frontend *fe)
1151 {
1152     struct dib0090_state *state = fe->tuner_priv;
1153     enum frontend_tune_state *tune_state = &state->tune_state;
1154     int ret = 10;
1155 
1156     u16 wbd_val = 0;
1157     u8 apply_gain_immediatly = 1;
1158     s16 wbd_error = 0, adc_error = 0;
1159 
1160     if (*tune_state == CT_AGC_START) {
1161         state->agc_freeze = 0;
1162         dib0090_write_reg(state, 0x04, 0x0);
1163 
1164 #ifdef CONFIG_BAND_SBAND
1165         if (state->current_band == BAND_SBAND) {
1166             dib0090_set_rframp(state, rf_ramp_sband);
1167             dib0090_set_bbramp(state, bb_ramp_boost);
1168         } else
1169 #endif
1170 #ifdef CONFIG_BAND_VHF
1171         if (state->current_band == BAND_VHF && !state->identity.p1g) {
1172             dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1173             dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1174         } else
1175 #endif
1176 #ifdef CONFIG_BAND_CBAND
1177         if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1178             dib0090_set_rframp(state, rf_ramp_pwm_cband);
1179             dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1180         } else
1181 #endif
1182         if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1183             dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1184             dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1185         } else {
1186             dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1187             dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1188         }
1189 
1190         dib0090_write_reg(state, 0x32, 0);
1191         dib0090_write_reg(state, 0x39, 0);
1192 
1193         dib0090_wbd_target(state, state->current_rf);
1194 
1195         state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1196         state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1197 
1198         *tune_state = CT_AGC_STEP_0;
1199     } else if (!state->agc_freeze) {
1200         s16 wbd = 0, i, cnt;
1201 
1202         int adc;
1203         wbd_val = dib0090_get_slow_adc_val(state);
1204 
1205         if (*tune_state == CT_AGC_STEP_0)
1206             cnt = 5;
1207         else
1208             cnt = 1;
1209 
1210         for (i = 0; i < cnt; i++) {
1211             wbd_val = dib0090_get_slow_adc_val(state);
1212             wbd += dib0090_wbd_to_db(state, wbd_val);
1213         }
1214         wbd /= cnt;
1215         wbd_error = state->wbd_target - wbd;
1216 
1217         if (*tune_state == CT_AGC_STEP_0) {
1218             if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1219 #ifdef CONFIG_BAND_CBAND
1220                 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1221                 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1222                 if (state->current_band == BAND_CBAND && ltg2) {
1223                     ltg2 >>= 1;
1224                     state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1225                 }
1226 #endif
1227             } else {
1228                 state->agc_step = 0;
1229                 *tune_state = CT_AGC_STEP_1;
1230             }
1231         } else {
1232             /* calc the adc power */
1233             adc = state->config->get_adc_power(fe);
1234             adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1235 
1236             adc_error = (s16) (((s32) ADC_TARGET) - adc);
1237 #ifdef CONFIG_STANDARD_DAB
1238             if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1239                 adc_error -= 10;
1240 #endif
1241 #ifdef CONFIG_STANDARD_DVBT
1242             if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1243                     (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1244                 adc_error += 60;
1245 #endif
1246 #ifdef CONFIG_SYS_ISDBT
1247             if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1248                                 0)
1249                             &&
1250                             ((state->fe->dtv_property_cache.layer[0].modulation ==
1251                               QAM_64)
1252                              || (state->fe->dtv_property_cache.
1253                                  layer[0].modulation == QAM_16)))
1254                         ||
1255                         ((state->fe->dtv_property_cache.layer[1].segment_count >
1256                           0)
1257                          &&
1258                          ((state->fe->dtv_property_cache.layer[1].modulation ==
1259                            QAM_64)
1260                           || (state->fe->dtv_property_cache.
1261                               layer[1].modulation == QAM_16)))
1262                         ||
1263                         ((state->fe->dtv_property_cache.layer[2].segment_count >
1264                           0)
1265                          &&
1266                          ((state->fe->dtv_property_cache.layer[2].modulation ==
1267                            QAM_64)
1268                           || (state->fe->dtv_property_cache.
1269                               layer[2].modulation == QAM_16)))
1270                         )
1271                 )
1272                 adc_error += 60;
1273 #endif
1274 
1275             if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1276                 if (abs(adc_error) < 50 || state->agc_step++ > 5) {
1277 
1278 #ifdef CONFIG_STANDARD_DAB
1279                     if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1280                         dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));  /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1281                         dib0090_write_reg(state, 0x04, 0x0);
1282                     } else
1283 #endif
1284                     {
1285                         dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1286                         dib0090_write_reg(state, 0x04, 0x01);   /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1287                     }
1288 
1289                     *tune_state = CT_AGC_STOP;
1290                 }
1291             } else {
1292                 /* everything higher than or equal to CT_AGC_STOP means tracking */
1293                 ret = 100;  /* 10ms interval */
1294                 apply_gain_immediatly = 0;
1295             }
1296         }
1297 #ifdef DEBUG_AGC
1298         dprintk
1299             ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1300              (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1301              (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1302 #endif
1303     }
1304 
1305     /* apply gain */
1306     if (!state->agc_freeze)
1307         dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1308     return ret;
1309 }
1310 
1311 EXPORT_SYMBOL(dib0090_gain_control);
1312 
1313 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1314 {
1315     struct dib0090_state *state = fe->tuner_priv;
1316     if (rf)
1317         *rf = state->gain[0];
1318     if (bb)
1319         *bb = state->gain[1];
1320     if (rf_gain_limit)
1321         *rf_gain_limit = state->rf_gain_limit;
1322     if (rflt)
1323         *rflt = (state->rf_lt_def >> 10) & 0x7;
1324 }
1325 
1326 EXPORT_SYMBOL(dib0090_get_current_gain);
1327 
1328 u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1329 {
1330     struct dib0090_state *state = fe->tuner_priv;
1331     u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1332     s32 current_temp = state->temperature;
1333     s32 wbd_thot, wbd_tcold;
1334     const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1335 
1336     while (f_MHz > wbd->max_freq)
1337         wbd++;
1338 
1339     dprintk("using wbd-table-entry with max freq %d\n", wbd->max_freq);
1340 
1341     if (current_temp < 0)
1342         current_temp = 0;
1343     if (current_temp > 128)
1344         current_temp = 128;
1345 
1346     state->wbdmux &= ~(7 << 13);
1347     if (wbd->wbd_gain != 0)
1348         state->wbdmux |= (wbd->wbd_gain << 13);
1349     else
1350         state->wbdmux |= (4 << 13);
1351 
1352     dib0090_write_reg(state, 0x10, state->wbdmux);
1353 
1354     wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1355     wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1356 
1357     wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1358 
1359     state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1360     dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
1361     dprintk("wbd offset applied is %d\n", wbd_tcold);
1362 
1363     return state->wbd_offset + wbd_tcold;
1364 }
1365 EXPORT_SYMBOL(dib0090_get_wbd_target);
1366 
1367 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1368 {
1369     struct dib0090_state *state = fe->tuner_priv;
1370     return state->wbd_offset;
1371 }
1372 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1373 
1374 int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1375 {
1376     struct dib0090_state *state = fe->tuner_priv;
1377 
1378     dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1379             | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1380 
1381     return 0;
1382 }
1383 EXPORT_SYMBOL(dib0090_set_switch);
1384 
1385 int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1386 {
1387     struct dib0090_state *state = fe->tuner_priv;
1388 
1389     dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1390             | ((onoff & 1) << 15));
1391     return 0;
1392 }
1393 EXPORT_SYMBOL(dib0090_set_vga);
1394 
1395 int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1396 {
1397     struct dib0090_state *state = fe->tuner_priv;
1398 
1399     if ((!state->identity.p1g) || (!state->identity.in_soc)
1400             || ((state->identity.version != SOC_7090_P1G_21R1)
1401                 && (state->identity.version != SOC_7090_P1G_11R1))) {
1402         dprintk("%s() function can only be used for dib7090P\n", __func__);
1403         return -ENODEV;
1404     }
1405 
1406     if (cfg_sensitivity)
1407         state->rf_ramp = rf_ramp_pwm_cband_7090e_sensitivity;
1408     else
1409         state->rf_ramp = rf_ramp_pwm_cband_7090e_aci;
1410     dib0090_pwm_gain_reset(fe);
1411 
1412     return 0;
1413 }
1414 EXPORT_SYMBOL(dib0090_update_rframp_7090);
1415 
1416 static const u16 dib0090_defaults[] = {
1417 
1418     25, 0x01,
1419     0x0000,
1420     0x99a0,
1421     0x6008,
1422     0x0000,
1423     0x8bcb,
1424     0x0000,
1425     0x0405,
1426     0x0000,
1427     0x0000,
1428     0x0000,
1429     0xb802,
1430     0x0300,
1431     0x2d12,
1432     0xbac0,
1433     0x7c00,
1434     0xdbb9,
1435     0x0954,
1436     0x0743,
1437     0x8000,
1438     0x0001,
1439     0x0040,
1440     0x0100,
1441     0x0000,
1442     0xe910,
1443     0x149e,
1444 
1445     1, 0x1c,
1446     0xff2d,
1447 
1448     1, 0x39,
1449     0x0000,
1450 
1451     2, 0x1e,
1452     0x07FF,
1453     0x0007,
1454 
1455     1, 0x24,
1456     EN_UHF | EN_CRYSTAL,
1457 
1458     2, 0x3c,
1459     0x3ff,
1460     0x111,
1461     0
1462 };
1463 
1464 static const u16 dib0090_p1g_additionnal_defaults[] = {
1465     1, 0x05,
1466     0xabcd,
1467 
1468     1, 0x11,
1469     0x00b4,
1470 
1471     1, 0x1c,
1472     0xfffd,
1473 
1474     1, 0x40,
1475     0x108,
1476     0
1477 };
1478 
1479 static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1480 {
1481     u16 l, r;
1482 
1483     l = pgm_read_word(n++);
1484     while (l) {
1485         r = pgm_read_word(n++);
1486         do {
1487             dib0090_write_reg(state, r, pgm_read_word(n++));
1488             r++;
1489         } while (--l);
1490         l = pgm_read_word(n++);
1491     }
1492 }
1493 
1494 #define CAP_VALUE_MIN (u8)  9
1495 #define CAP_VALUE_MAX (u8) 40
1496 #define HR_MIN        (u8) 25
1497 #define HR_MAX        (u8) 40
1498 #define POLY_MIN      (u8)  0
1499 #define POLY_MAX      (u8)  8
1500 
1501 static void dib0090_set_EFUSE(struct dib0090_state *state)
1502 {
1503     u8 c, h, n;
1504     u16 e2, e4;
1505     u16 cal;
1506 
1507     e2 = dib0090_read_reg(state, 0x26);
1508     e4 = dib0090_read_reg(state, 0x28);
1509 
1510     if ((state->identity.version == P1D_E_F) ||
1511             (state->identity.version == P1G) || (e2 == 0xffff)) {
1512 
1513         dib0090_write_reg(state, 0x22, 0x10);
1514         cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1515 
1516         if ((cal < 670) || (cal == 1023))
1517             cal = 850;
1518         n = 165 - ((cal * 10)>>6) ;
1519         e2 = e4 = (3<<12) | (34<<6) | (n);
1520     }
1521 
1522     if (e2 != e4)
1523         e2 &= e4; /* Remove the redundancy  */
1524 
1525     if (e2 != 0xffff) {
1526         c = e2 & 0x3f;
1527         n = (e2 >> 12) & 0xf;
1528         h = (e2 >> 6) & 0x3f;
1529 
1530         if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1531             c = 32;
1532         else
1533             c += 14;
1534         if ((h >= HR_MAX) || (h <= HR_MIN))
1535             h = 34;
1536         if ((n >= POLY_MAX) || (n <= POLY_MIN))
1537             n = 3;
1538 
1539         dib0090_write_reg(state, 0x13, (h << 10));
1540         e2 = (n << 11) | ((h >> 2)<<6) | c;
1541         dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
1542     }
1543 }
1544 
1545 static int dib0090_reset(struct dvb_frontend *fe)
1546 {
1547     struct dib0090_state *state = fe->tuner_priv;
1548 
1549     dib0090_reset_digital(fe, state->config);
1550     if (dib0090_identify(fe) < 0)
1551         return -EIO;
1552 
1553 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1554     if (!(state->identity.version & 0x1))   /* it is P1B - reset is already done */
1555         return 0;
1556 #endif
1557 
1558     if (!state->identity.in_soc) {
1559         if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1560             dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1561         else
1562             dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1563     }
1564 
1565     dib0090_set_default_config(state, dib0090_defaults);
1566 
1567     if (state->identity.in_soc)
1568         dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
1569 
1570     if (state->identity.p1g)
1571         dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1572 
1573     /* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
1574     if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1575         dib0090_set_EFUSE(state);
1576 
1577     /* Congigure in function of the crystal */
1578     if (state->config->force_crystal_mode != 0)
1579         dib0090_write_reg(state, 0x14,
1580                 state->config->force_crystal_mode & 3);
1581     else if (state->config->io.clock_khz >= 24000)
1582         dib0090_write_reg(state, 0x14, 1);
1583     else
1584         dib0090_write_reg(state, 0x14, 2);
1585     dprintk("Pll lock : %d\n", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1586 
1587     state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1588 
1589     return 0;
1590 }
1591 
1592 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
1593 #define INTERN_WAIT 10
1594 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1595 {
1596     int ret = INTERN_WAIT * 10;
1597 
1598     switch (*tune_state) {
1599     case CT_TUNER_STEP_2:
1600         /* Turns to positive */
1601         dib0090_write_reg(state, 0x1f, 0x7);
1602         *tune_state = CT_TUNER_STEP_3;
1603         break;
1604 
1605     case CT_TUNER_STEP_3:
1606         state->adc_diff = dib0090_read_reg(state, 0x1d);
1607 
1608         /* Turns to negative */
1609         dib0090_write_reg(state, 0x1f, 0x4);
1610         *tune_state = CT_TUNER_STEP_4;
1611         break;
1612 
1613     case CT_TUNER_STEP_4:
1614         state->adc_diff -= dib0090_read_reg(state, 0x1d);
1615         *tune_state = CT_TUNER_STEP_5;
1616         ret = 0;
1617         break;
1618 
1619     default:
1620         break;
1621     }
1622 
1623     return ret;
1624 }
1625 
1626 struct dc_calibration {
1627     u8 addr;
1628     u8 offset;
1629     u8 pga:1;
1630     u16 bb1;
1631     u8 i:1;
1632 };
1633 
1634 static const struct dc_calibration dc_table[] = {
1635     /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1636     {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1637     {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1638     /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1639     {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1640     {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1641     {0},
1642 };
1643 
1644 static const struct dc_calibration dc_p1g_table[] = {
1645     /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1646     /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1647     {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1648     {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1649     /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1650     {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1651     {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1652     {0},
1653 };
1654 
1655 static void dib0090_set_trim(struct dib0090_state *state)
1656 {
1657     u16 *val;
1658 
1659     if (state->dc->addr == 0x07)
1660         val = &state->bb7;
1661     else
1662         val = &state->bb6;
1663 
1664     *val &= ~(0x1f << state->dc->offset);
1665     *val |= state->step << state->dc->offset;
1666 
1667     dib0090_write_reg(state, state->dc->addr, *val);
1668 }
1669 
1670 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1671 {
1672     int ret = 0;
1673     u16 reg;
1674 
1675     switch (*tune_state) {
1676     case CT_TUNER_START:
1677         dprintk("Start DC offset calibration");
1678 
1679         /* force vcm2 = 0.8V */
1680         state->bb6 = 0;
1681         state->bb7 = 0x040d;
1682 
1683         /* the LNA AND LO are off */
1684         reg = dib0090_read_reg(state, 0x24) & 0x0ffb;   /* shutdown lna and lo */
1685         dib0090_write_reg(state, 0x24, reg);
1686 
1687         state->wbdmux = dib0090_read_reg(state, 0x10);
1688         dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1689         dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1690 
1691         state->dc = dc_table;
1692 
1693         if (state->identity.p1g)
1694             state->dc = dc_p1g_table;
1695 
1696         fallthrough;
1697     case CT_TUNER_STEP_0:
1698         dprintk("Start/continue DC calibration for %s path\n",
1699             (state->dc->i == 1) ? "I" : "Q");
1700         dib0090_write_reg(state, 0x01, state->dc->bb1);
1701         dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1702 
1703         state->step = 0;
1704         state->min_adc_diff = 1023;
1705         *tune_state = CT_TUNER_STEP_1;
1706         ret = 50;
1707         break;
1708 
1709     case CT_TUNER_STEP_1:
1710         dib0090_set_trim(state);
1711         *tune_state = CT_TUNER_STEP_2;
1712         break;
1713 
1714     case CT_TUNER_STEP_2:
1715     case CT_TUNER_STEP_3:
1716     case CT_TUNER_STEP_4:
1717         ret = dib0090_get_offset(state, tune_state);
1718         break;
1719 
1720     case CT_TUNER_STEP_5:   /* found an offset */
1721         dprintk("adc_diff = %d, current step= %d\n", (u32) state->adc_diff, state->step);
1722         if (state->step == 0 && state->adc_diff < 0) {
1723             state->min_adc_diff = -1023;
1724             dprintk("Change of sign of the minimum adc diff\n");
1725         }
1726 
1727         dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d\n", state->adc_diff, state->min_adc_diff, state->step);
1728 
1729         /* first turn for this frequency */
1730         if (state->step == 0) {
1731             if (state->dc->pga && state->adc_diff < 0)
1732                 state->step = 0x10;
1733             if (state->dc->pga == 0 && state->adc_diff > 0)
1734                 state->step = 0x10;
1735         }
1736 
1737         /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1738         if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1739             /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1740             state->step++;
1741             state->min_adc_diff = state->adc_diff;
1742             *tune_state = CT_TUNER_STEP_1;
1743         } else {
1744             /* the minimum was what we have seen in the step before */
1745             if (abs(state->adc_diff) > abs(state->min_adc_diff)) {
1746                 dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff);
1747                 state->step--;
1748             }
1749 
1750             dib0090_set_trim(state);
1751             dprintk("BB Offset Cal, BBreg=%u,Offset=%d,Value Set=%d\n",
1752                 state->dc->addr, state->adc_diff, state->step);
1753 
1754             state->dc++;
1755             if (state->dc->addr == 0)   /* done */
1756                 *tune_state = CT_TUNER_STEP_6;
1757             else
1758                 *tune_state = CT_TUNER_STEP_0;
1759 
1760         }
1761         break;
1762 
1763     case CT_TUNER_STEP_6:
1764         dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1765         dib0090_write_reg(state, 0x1f, 0x7);
1766         *tune_state = CT_TUNER_START;   /* reset done -> real tuning can now begin */
1767         state->calibrate &= ~DC_CAL;
1768         break;
1769 
1770     default:
1771         break;
1772     }
1773     return ret;
1774 }
1775 
1776 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1777 {
1778     u8 wbd_gain;
1779     const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1780 
1781     switch (*tune_state) {
1782     case CT_TUNER_START:
1783         while (state->current_rf / 1000 > wbd->max_freq)
1784             wbd++;
1785         if (wbd->wbd_gain != 0)
1786             wbd_gain = wbd->wbd_gain;
1787         else {
1788             wbd_gain = 4;
1789 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1790             if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1791                 wbd_gain = 2;
1792 #endif
1793         }
1794 
1795         if (wbd_gain == state->wbd_calibration_gain) {  /* the WBD calibration has already been done */
1796             *tune_state = CT_TUNER_START;
1797             state->calibrate &= ~WBD_CAL;
1798             return 0;
1799         }
1800 
1801         dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1802 
1803         dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1804         *tune_state = CT_TUNER_STEP_0;
1805         state->wbd_calibration_gain = wbd_gain;
1806         return 90;  /* wait for the WBDMUX to switch and for the ADC to sample */
1807 
1808     case CT_TUNER_STEP_0:
1809         state->wbd_offset = dib0090_get_slow_adc_val(state);
1810         dprintk("WBD calibration offset = %d\n", state->wbd_offset);
1811         *tune_state = CT_TUNER_START;   /* reset done -> real tuning can now begin */
1812         state->calibrate &= ~WBD_CAL;
1813         break;
1814 
1815     default:
1816         break;
1817     }
1818     return 0;
1819 }
1820 
1821 static void dib0090_set_bandwidth(struct dib0090_state *state)
1822 {
1823     u16 tmp;
1824 
1825     if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1826         tmp = (3 << 14);
1827     else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1828         tmp = (2 << 14);
1829     else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1830         tmp = (1 << 14);
1831     else
1832         tmp = (0 << 14);
1833 
1834     state->bb_1_def &= 0x3fff;
1835     state->bb_1_def |= tmp;
1836 
1837     dib0090_write_reg(state, 0x01, state->bb_1_def);    /* be sure that we have the right bb-filter */
1838 
1839     dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1840     dib0090_write_reg(state, 0x04, 0x1);    /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1841     if (state->identity.in_soc) {
1842         dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
1843     } else {
1844         dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1845         dib0090_write_reg(state, 0x05, 0xabcd); /* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
1846     }
1847 }
1848 
1849 static const struct dib0090_pll dib0090_pll_table[] = {
1850 #ifdef CONFIG_BAND_CBAND
1851     {56000, 0, 9, 48, 6},
1852     {70000, 1, 9, 48, 6},
1853     {87000, 0, 8, 32, 4},
1854     {105000, 1, 8, 32, 4},
1855     {115000, 0, 7, 24, 6},
1856     {140000, 1, 7, 24, 6},
1857     {170000, 0, 6, 16, 4},
1858 #endif
1859 #ifdef CONFIG_BAND_VHF
1860     {200000, 1, 6, 16, 4},
1861     {230000, 0, 5, 12, 6},
1862     {280000, 1, 5, 12, 6},
1863     {340000, 0, 4, 8, 4},
1864     {380000, 1, 4, 8, 4},
1865     {450000, 0, 3, 6, 6},
1866 #endif
1867 #ifdef CONFIG_BAND_UHF
1868     {580000, 1, 3, 6, 6},
1869     {700000, 0, 2, 4, 4},
1870     {860000, 1, 2, 4, 4},
1871 #endif
1872 #ifdef CONFIG_BAND_LBAND
1873     {1800000, 1, 0, 2, 4},
1874 #endif
1875 #ifdef CONFIG_BAND_SBAND
1876     {2900000, 0, 14, 1, 4},
1877 #endif
1878 };
1879 
1880 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1881 
1882 #ifdef CONFIG_BAND_CBAND
1883     {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1884     {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1885     {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1886 #endif
1887 #ifdef CONFIG_BAND_UHF
1888     {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1889     {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1890     {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1891     {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1892     {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1893     {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1894 #endif
1895 #ifdef CONFIG_BAND_LBAND
1896     {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1897     {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1898     {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1899 #endif
1900 #ifdef CONFIG_BAND_SBAND
1901     {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1902     {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1903 #endif
1904 };
1905 
1906 static const struct dib0090_tuning dib0090_tuning_table[] = {
1907 
1908 #ifdef CONFIG_BAND_CBAND
1909     {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1910 #endif
1911 #ifdef CONFIG_BAND_VHF
1912     {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1913     {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1914     {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1915 #endif
1916 #ifdef CONFIG_BAND_UHF
1917     {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1918     {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1919     {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1920     {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1921     {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1922     {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1923 #endif
1924 #ifdef CONFIG_BAND_LBAND
1925     {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1926     {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1927     {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1928 #endif
1929 #ifdef CONFIG_BAND_SBAND
1930     {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1931     {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1932 #endif
1933 };
1934 
1935 static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1936 #ifdef CONFIG_BAND_CBAND
1937     {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1938 #endif
1939 #ifdef CONFIG_BAND_VHF
1940     {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1941     {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1942     {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1943 #endif
1944 #ifdef CONFIG_BAND_UHF
1945     {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1946     {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1947     {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1948     {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1949     {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1950     {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1951     {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1952 #endif
1953 #ifdef CONFIG_BAND_LBAND
1954     {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1955     {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1956     {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1957 #endif
1958 #ifdef CONFIG_BAND_SBAND
1959     {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1960     {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1961 #endif
1962 };
1963 
1964 static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1965 #ifdef CONFIG_BAND_CBAND
1966     {57000, 0, 11, 48, 6},
1967     {70000, 1, 11, 48, 6},
1968     {86000, 0, 10, 32, 4},
1969     {105000, 1, 10, 32, 4},
1970     {115000, 0, 9, 24, 6},
1971     {140000, 1, 9, 24, 6},
1972     {170000, 0, 8, 16, 4},
1973 #endif
1974 #ifdef CONFIG_BAND_VHF
1975     {200000, 1, 8, 16, 4},
1976     {230000, 0, 7, 12, 6},
1977     {280000, 1, 7, 12, 6},
1978     {340000, 0, 6, 8, 4},
1979     {380000, 1, 6, 8, 4},
1980     {455000, 0, 5, 6, 6},
1981 #endif
1982 #ifdef CONFIG_BAND_UHF
1983     {580000, 1, 5, 6, 6},
1984     {680000, 0, 4, 4, 4},
1985     {860000, 1, 4, 4, 4},
1986 #endif
1987 #ifdef CONFIG_BAND_LBAND
1988     {1800000, 1, 2, 2, 4},
1989 #endif
1990 #ifdef CONFIG_BAND_SBAND
1991     {2900000, 0, 1, 1, 6},
1992 #endif
1993 };
1994 
1995 static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1996 #ifdef CONFIG_BAND_CBAND
1997     {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1998     {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1999     {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2000 #endif
2001 #ifdef CONFIG_BAND_UHF
2002     {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2003     {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2004     {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2005     {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2006     {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2007     {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2008 #endif
2009 #ifdef CONFIG_BAND_LBAND
2010     {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2011     {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2012     {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2013 #endif
2014 #ifdef CONFIG_BAND_SBAND
2015     {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2016     {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2017 #endif
2018 };
2019 
2020 static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2021 #ifdef CONFIG_BAND_CBAND
2022     {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2023     {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2024     {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2025     {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2026 #endif
2027 };
2028 
2029 static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2030 #ifdef CONFIG_BAND_CBAND
2031     { 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2032     { 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2033     { 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2034     { 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2035     { 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2036     { 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2037 #endif
2038 };
2039 
2040 int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2041         u8 cfg_sensitivity)
2042 {
2043     struct dib0090_state *state = fe->tuner_priv;
2044     const struct dib0090_tuning *tune =
2045         dib0090_tuning_table_cband_7090e_sensitivity;
2046     static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2047         { 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2048         { 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2049         { 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2050     };
2051 
2052     if ((!state->identity.p1g) || (!state->identity.in_soc)
2053             || ((state->identity.version != SOC_7090_P1G_21R1)
2054                 && (state->identity.version != SOC_7090_P1G_11R1))) {
2055         dprintk("%s() function can only be used for dib7090\n", __func__);
2056         return -ENODEV;
2057     }
2058 
2059     if (cfg_sensitivity)
2060         tune = dib0090_tuning_table_cband_7090e_sensitivity;
2061     else
2062         tune = dib0090_tuning_table_cband_7090e_aci;
2063 
2064     while (state->rf_request > tune->max_freq)
2065         tune++;
2066 
2067     dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2068             | (tune->lna_bias & 0x7fff));
2069     dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2070             | ((tune->lna_tune << 6) & 0x07c0));
2071     return 0;
2072 }
2073 EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2074 
2075 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2076 {
2077     int ret = 0;
2078     u16 lo4 = 0xe900;
2079 
2080     s16 adc_target;
2081     u16 adc;
2082     s8 step_sign;
2083     u8 force_soft_search = 0;
2084 
2085     if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2086         force_soft_search = 1;
2087 
2088     if (*tune_state == CT_TUNER_START) {
2089         dprintk("Start Captrim search : %s\n",
2090             (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2091         dib0090_write_reg(state, 0x10, 0x2B1);
2092         dib0090_write_reg(state, 0x1e, 0x0032);
2093 
2094         if (!state->tuner_is_tuned) {
2095             /* prepare a complete captrim */
2096             if (!state->identity.p1g || force_soft_search)
2097                 state->step = state->captrim = state->fcaptrim = 64;
2098 
2099             state->current_rf = state->rf_request;
2100         } else {    /* we are already tuned to this frequency - the configuration is correct  */
2101             if (!state->identity.p1g || force_soft_search) {
2102                 /* do a minimal captrim even if the frequency has not changed */
2103                 state->step = 4;
2104                 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2105             }
2106         }
2107         state->adc_diff = 3000;
2108         *tune_state = CT_TUNER_STEP_0;
2109 
2110     } else if (*tune_state == CT_TUNER_STEP_0) {
2111         if (state->identity.p1g && !force_soft_search) {
2112             u8 ratio = 31;
2113 
2114             dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2115             dib0090_read_reg(state, 0x40);
2116             ret = 50;
2117         } else {
2118             state->step /= 2;
2119             dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2120 
2121             if (state->identity.in_soc)
2122                 ret = 25;
2123         }
2124         *tune_state = CT_TUNER_STEP_1;
2125 
2126     } else if (*tune_state == CT_TUNER_STEP_1) {
2127         if (state->identity.p1g && !force_soft_search) {
2128             dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2129             dib0090_read_reg(state, 0x40);
2130 
2131             state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2132             dprintk("***Final Captrim= 0x%x\n", state->fcaptrim);
2133             *tune_state = CT_TUNER_STEP_3;
2134 
2135         } else {
2136             /* MERGE for all krosus before P1G */
2137             adc = dib0090_get_slow_adc_val(state);
2138             dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2139 
2140             if (state->rest == 0 || state->identity.in_soc) {   /* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
2141                 adc_target = 200;
2142             } else
2143                 adc_target = 400;
2144 
2145             if (adc >= adc_target) {
2146                 adc -= adc_target;
2147                 step_sign = -1;
2148             } else {
2149                 adc = adc_target - adc;
2150                 step_sign = 1;
2151             }
2152 
2153             if (adc < state->adc_diff) {
2154                 dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2155                 state->adc_diff = adc;
2156                 state->fcaptrim = state->captrim;
2157             }
2158 
2159             state->captrim += step_sign * state->step;
2160             if (state->step >= 1)
2161                 *tune_state = CT_TUNER_STEP_0;
2162             else
2163                 *tune_state = CT_TUNER_STEP_2;
2164 
2165             ret = 25;
2166         }
2167     } else if (*tune_state == CT_TUNER_STEP_2) {    /* this step is only used by krosus < P1G */
2168         /*write the final cptrim config */
2169         dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2170 
2171         *tune_state = CT_TUNER_STEP_3;
2172 
2173     } else if (*tune_state == CT_TUNER_STEP_3) {
2174         state->calibrate &= ~CAPTRIM_CAL;
2175         *tune_state = CT_TUNER_STEP_0;
2176     }
2177 
2178     return ret;
2179 }
2180 
2181 static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2182 {
2183     int ret = 15;
2184     s16 val;
2185 
2186     switch (*tune_state) {
2187     case CT_TUNER_START:
2188         state->wbdmux = dib0090_read_reg(state, 0x10);
2189         dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2190 
2191         state->bias = dib0090_read_reg(state, 0x13);
2192         dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2193 
2194         *tune_state = CT_TUNER_STEP_0;
2195         /* wait for the WBDMUX to switch and for the ADC to sample */
2196         break;
2197 
2198     case CT_TUNER_STEP_0:
2199         state->adc_diff = dib0090_get_slow_adc_val(state);
2200         dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2201         *tune_state = CT_TUNER_STEP_1;
2202         break;
2203 
2204     case CT_TUNER_STEP_1:
2205         val = dib0090_get_slow_adc_val(state);
2206         state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2207 
2208         dprintk("temperature: %d C\n", state->temperature - 30);
2209 
2210         *tune_state = CT_TUNER_STEP_2;
2211         break;
2212 
2213     case CT_TUNER_STEP_2:
2214         dib0090_write_reg(state, 0x13, state->bias);
2215         dib0090_write_reg(state, 0x10, state->wbdmux);  /* write back original WBDMUX */
2216 
2217         *tune_state = CT_TUNER_START;
2218         state->calibrate &= ~TEMP_CAL;
2219         if (state->config->analog_output == 0)
2220             dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2221 
2222         break;
2223 
2224     default:
2225         ret = 0;
2226         break;
2227     }
2228     return ret;
2229 }
2230 
2231 #define WBD     0x781       /* 1 1 1 1 0000 0 0 1 */
2232 static int dib0090_tune(struct dvb_frontend *fe)
2233 {
2234     struct dib0090_state *state = fe->tuner_priv;
2235     const struct dib0090_tuning *tune = state->current_tune_table_index;
2236     const struct dib0090_pll *pll = state->current_pll_table_index;
2237     enum frontend_tune_state *tune_state = &state->tune_state;
2238 
2239     u16 lo5, lo6, Den, tmp;
2240     u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2241     int ret = 10;       /* 1ms is the default delay most of the time */
2242     u8 c, i;
2243 
2244     /************************* VCO ***************************/
2245     /* Default values for FG                                 */
2246     /* from these are needed :                               */
2247     /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
2248 
2249     /* in any case we first need to do a calibration if needed */
2250     if (*tune_state == CT_TUNER_START) {
2251         /* deactivate DataTX before some calibrations */
2252         if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2253             dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2254         else
2255             /* Activate DataTX in case a calibration has been done before */
2256             if (state->config->analog_output == 0)
2257                 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2258     }
2259 
2260     if (state->calibrate & DC_CAL)
2261         return dib0090_dc_offset_calibration(state, tune_state);
2262     else if (state->calibrate & WBD_CAL) {
2263         if (state->current_rf == 0)
2264             state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2265         return dib0090_wbd_calibration(state, tune_state);
2266     } else if (state->calibrate & TEMP_CAL)
2267         return dib0090_get_temperature(state, tune_state);
2268     else if (state->calibrate & CAPTRIM_CAL)
2269         return dib0090_captrim_search(state, tune_state);
2270 
2271     if (*tune_state == CT_TUNER_START) {
2272         /* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
2273         if (state->config->use_pwm_agc && state->identity.in_soc) {
2274             tmp = dib0090_read_reg(state, 0x39);
2275             if ((tmp >> 10) & 0x1)
2276                 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2277         }
2278 
2279         state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2280         state->rf_request =
2281             state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2282                     BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2283                     freq_offset_khz_vhf);
2284 
2285         /* in ISDB-T 1seg we shift tuning frequency */
2286         if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2287                     && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2288             const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2289             u8 found_offset = 0;
2290             u32 margin_khz = 100;
2291 
2292             if (LUT_offset != NULL) {
2293                 while (LUT_offset->RF_freq != 0xffff) {
2294                     if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2295                                 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2296                             && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2297                         state->rf_request += LUT_offset->offset_khz;
2298                         found_offset = 1;
2299                         break;
2300                     }
2301                     LUT_offset++;
2302                 }
2303             }
2304 
2305             if (found_offset == 0)
2306                 state->rf_request += 400;
2307         }
2308         if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2309             state->tuner_is_tuned = 0;
2310             state->current_rf = 0;
2311             state->current_standard = 0;
2312 
2313             tune = dib0090_tuning_table;
2314             if (state->identity.p1g)
2315                 tune = dib0090_p1g_tuning_table;
2316 
2317             tmp = (state->identity.version >> 5) & 0x7;
2318 
2319             if (state->identity.in_soc) {
2320                 if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2321                     if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2322                             || state->current_band & BAND_UHF) {
2323                         state->current_band = BAND_CBAND;
2324                         if (state->config->is_dib7090e)
2325                             tune = dib0090_tuning_table_cband_7090e_sensitivity;
2326                         else
2327                             tune = dib0090_tuning_table_cband_7090;
2328                     }
2329                 } else {    /* Use the CBAND input for all band under UHF */
2330                     if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2331                         state->current_band = BAND_CBAND;
2332                         if (state->config->is_dib7090e)
2333                             tune = dib0090_tuning_table_cband_7090e_sensitivity;
2334                         else
2335                             tune = dib0090_tuning_table_cband_7090;
2336                     }
2337                 }
2338             } else
2339              if (tmp == 0x4 || tmp == 0x7) {
2340                 /* CBAND tuner version for VHF */
2341                 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2342                     state->current_band = BAND_CBAND;   /* Force CBAND */
2343 
2344                     tune = dib0090_tuning_table_fm_vhf_on_cband;
2345                     if (state->identity.p1g)
2346                         tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2347                 }
2348             }
2349 
2350             pll = dib0090_pll_table;
2351             if (state->identity.p1g)
2352                 pll = dib0090_p1g_pll_table;
2353 
2354             /* Look for the interval */
2355             while (state->rf_request > tune->max_freq)
2356                 tune++;
2357             while (state->rf_request > pll->max_freq)
2358                 pll++;
2359 
2360             state->current_tune_table_index = tune;
2361             state->current_pll_table_index = pll;
2362 
2363             dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2364 
2365             VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2366 
2367             FREF = state->config->io.clock_khz;
2368             if (state->config->fref_clock_ratio != 0)
2369                 FREF /= state->config->fref_clock_ratio;
2370 
2371             FBDiv = (VCOF_kHz / pll->topresc / FREF);
2372             Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2373 
2374             if (Rest < LPF)
2375                 Rest = 0;
2376             else if (Rest < 2 * LPF)
2377                 Rest = 2 * LPF;
2378             else if (Rest > (FREF - LPF)) {
2379                 Rest = 0;
2380                 FBDiv += 1;
2381             } else if (Rest > (FREF - 2 * LPF))
2382                 Rest = FREF - 2 * LPF;
2383             Rest = (Rest * 6528) / (FREF / 10);
2384             state->rest = Rest;
2385 
2386             /* external loop filter, otherwise:
2387              * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2388              * lo6 = 0x0e34 */
2389 
2390             if (Rest == 0) {
2391                 if (pll->vco_band)
2392                     lo5 = 0x049f;
2393                 else
2394                     lo5 = 0x041f;
2395             } else {
2396                 if (pll->vco_band)
2397                     lo5 = 0x049e;
2398                 else if (state->config->analog_output)
2399                     lo5 = 0x041d;
2400                 else
2401                     lo5 = 0x041c;
2402             }
2403 
2404             if (state->identity.p1g) {  /* Bias is done automatically in P1G */
2405                 if (state->identity.in_soc) {
2406                     if (state->identity.version == SOC_8090_P1G_11R1)
2407                         lo5 = 0x46f;
2408                     else
2409                         lo5 = 0x42f;
2410                 } else
2411                     lo5 = 0x42c;
2412             }
2413 
2414             lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);  /* bit 15 is the split to the slave, we do not do it here */
2415 
2416             if (!state->config->io.pll_int_loop_filt) {
2417                 if (state->identity.in_soc)
2418                     lo6 = 0xff98;
2419                 else if (state->identity.p1g || (Rest == 0))
2420                     lo6 = 0xfff8;
2421                 else
2422                     lo6 = 0xff28;
2423             } else
2424                 lo6 = (state->config->io.pll_int_loop_filt << 3);
2425 
2426             Den = 1;
2427 
2428             if (Rest > 0) {
2429                 lo6 |= (1 << 2) | 2;
2430                 Den = 255;
2431             }
2432             dib0090_write_reg(state, 0x15, (u16) FBDiv);
2433             if (state->config->fref_clock_ratio != 0)
2434                 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2435             else
2436                 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2437             dib0090_write_reg(state, 0x17, (u16) Rest);
2438             dib0090_write_reg(state, 0x19, lo5);
2439             dib0090_write_reg(state, 0x1c, lo6);
2440 
2441             lo6 = tune->tuner_enable;
2442             if (state->config->analog_output)
2443                 lo6 = (lo6 & 0xff9f) | 0x2;
2444 
2445             dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2446 
2447         }
2448 
2449         state->current_rf = state->rf_request;
2450         state->current_standard = state->fe->dtv_property_cache.delivery_system;
2451 
2452         ret = 20;
2453         state->calibrate = CAPTRIM_CAL; /* captrim search now */
2454     }
2455 
2456     else if (*tune_state == CT_TUNER_STEP_0) {  /* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
2457         const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2458 
2459         while (state->current_rf / 1000 > wbd->max_freq)
2460             wbd++;
2461 
2462         dib0090_write_reg(state, 0x1e, 0x07ff);
2463         dprintk("Final Captrim: %d\n", (u32) state->fcaptrim);
2464         dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code);
2465         dprintk("VCO = %d\n", (u32) pll->vco_band);
2466         dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2467         dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz);
2468         dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2469         dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2470             (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2471 
2472 #define WBD     0x781       /* 1 1 1 1 0000 0 0 1 */
2473         c = 4;
2474         i = 3;
2475 
2476         if (wbd->wbd_gain != 0)
2477             c = wbd->wbd_gain;
2478 
2479         state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2480         dib0090_write_reg(state, 0x10, state->wbdmux);
2481 
2482         if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2483             dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune);
2484             dib0090_write_reg(state, 0x09, tune->lna_bias);
2485             dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2486         } else
2487             dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2488 
2489         dib0090_write_reg(state, 0x0c, tune->v2i);
2490         dib0090_write_reg(state, 0x0d, tune->mix);
2491         dib0090_write_reg(state, 0x0e, tune->load);
2492         *tune_state = CT_TUNER_STEP_1;
2493 
2494     } else if (*tune_state == CT_TUNER_STEP_1) {
2495         /* initialize the lt gain register */
2496         state->rf_lt_def = 0x7c00;
2497 
2498         dib0090_set_bandwidth(state);
2499         state->tuner_is_tuned = 1;
2500 
2501         state->calibrate |= WBD_CAL;
2502         state->calibrate |= TEMP_CAL;
2503         *tune_state = CT_TUNER_STOP;
2504     } else
2505         ret = FE_CALLBACK_TIME_NEVER;
2506     return ret;
2507 }
2508 
2509 static void dib0090_release(struct dvb_frontend *fe)
2510 {
2511     kfree(fe->tuner_priv);
2512     fe->tuner_priv = NULL;
2513 }
2514 
2515 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2516 {
2517     struct dib0090_state *state = fe->tuner_priv;
2518 
2519     return state->tune_state;
2520 }
2521 
2522 EXPORT_SYMBOL(dib0090_get_tune_state);
2523 
2524 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2525 {
2526     struct dib0090_state *state = fe->tuner_priv;
2527 
2528     state->tune_state = tune_state;
2529     return 0;
2530 }
2531 
2532 EXPORT_SYMBOL(dib0090_set_tune_state);
2533 
2534 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2535 {
2536     struct dib0090_state *state = fe->tuner_priv;
2537 
2538     *frequency = 1000 * state->current_rf;
2539     return 0;
2540 }
2541 
2542 static int dib0090_set_params(struct dvb_frontend *fe)
2543 {
2544     struct dib0090_state *state = fe->tuner_priv;
2545     u32 ret;
2546 
2547     state->tune_state = CT_TUNER_START;
2548 
2549     do {
2550         ret = dib0090_tune(fe);
2551         if (ret == FE_CALLBACK_TIME_NEVER)
2552             break;
2553 
2554         /*
2555          * Despite dib0090_tune returns time at a 0.1 ms range,
2556          * the actual sleep time depends on CONFIG_HZ. The worse case
2557          * is when CONFIG_HZ=100. In such case, the minimum granularity
2558          * is 10ms. On some real field tests, the tuner sometimes don't
2559          * lock when this timer is lower than 10ms. So, enforce a 10ms
2560          * granularity and use usleep_range() instead of msleep().
2561          */
2562         ret = 10 * (ret + 99)/100;
2563         usleep_range(ret * 1000, (ret + 1) * 1000);
2564     } while (state->tune_state != CT_TUNER_STOP);
2565 
2566     return 0;
2567 }
2568 
2569 static const struct dvb_tuner_ops dib0090_ops = {
2570     .info = {
2571          .name = "DiBcom DiB0090",
2572          .frequency_min_hz  =  45 * MHz,
2573          .frequency_max_hz  = 860 * MHz,
2574          .frequency_step_hz =   1 * kHz,
2575          },
2576     .release = dib0090_release,
2577 
2578     .init = dib0090_wakeup,
2579     .sleep = dib0090_sleep,
2580     .set_params = dib0090_set_params,
2581     .get_frequency = dib0090_get_frequency,
2582 };
2583 
2584 static const struct dvb_tuner_ops dib0090_fw_ops = {
2585     .info = {
2586          .name = "DiBcom DiB0090",
2587          .frequency_min_hz  =  45 * MHz,
2588          .frequency_max_hz  = 860 * MHz,
2589          .frequency_step_hz =   1 * kHz,
2590          },
2591     .release = dib0090_release,
2592 
2593     .init = NULL,
2594     .sleep = NULL,
2595     .set_params = NULL,
2596     .get_frequency = NULL,
2597 };
2598 
2599 static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2600     {470, 0, 250, 0, 100, 4},
2601     {860, 51, 866, 21, 375, 4},
2602     {1700, 0, 800, 0, 850, 4},
2603     {2900, 0, 250, 0, 100, 6},
2604     {0xFFFF, 0, 0, 0, 0, 0},
2605 };
2606 
2607 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2608 {
2609     struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2610     if (st == NULL)
2611         return NULL;
2612 
2613     st->config = config;
2614     st->i2c = i2c;
2615     st->fe = fe;
2616     mutex_init(&st->i2c_buffer_lock);
2617     fe->tuner_priv = st;
2618 
2619     if (config->wbd == NULL)
2620         st->current_wbd_table = dib0090_wbd_table_default;
2621     else
2622         st->current_wbd_table = config->wbd;
2623 
2624     if (dib0090_reset(fe) != 0)
2625         goto free_mem;
2626 
2627     pr_info("DiB0090: successfully identified\n");
2628     memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2629 
2630     return fe;
2631  free_mem:
2632     kfree(st);
2633     fe->tuner_priv = NULL;
2634     return NULL;
2635 }
2636 
2637 EXPORT_SYMBOL(dib0090_register);
2638 
2639 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2640 {
2641     struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2642     if (st == NULL)
2643         return NULL;
2644 
2645     st->config = config;
2646     st->i2c = i2c;
2647     st->fe = fe;
2648     mutex_init(&st->i2c_buffer_lock);
2649     fe->tuner_priv = st;
2650 
2651     if (dib0090_fw_reset_digital(fe, st->config) != 0)
2652         goto free_mem;
2653 
2654     dprintk("DiB0090 FW: successfully identified\n");
2655     memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2656 
2657     return fe;
2658 free_mem:
2659     kfree(st);
2660     fe->tuner_priv = NULL;
2661     return NULL;
2662 }
2663 EXPORT_SYMBOL(dib0090_fw_register);
2664 
2665 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
2666 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
2667 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2668 MODULE_LICENSE("GPL");