linux/drivers/media/dvb-frontends/dib0090.c
<<
>>
Prefs
   1/*
   2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
   3 *
   4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of the
   9 * License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *
  15 * GNU General Public License for more details.
  16 *
  17 *
  18 * This code is more or less generated from another driver, please
  19 * excuse some codingstyle oddities.
  20 *
  21 */
  22
  23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  24
  25#include <linux/kernel.h>
  26#include <linux/slab.h>
  27#include <linux/i2c.h>
  28#include <linux/mutex.h>
  29
  30#include <media/dvb_frontend.h>
  31
  32#include "dib0090.h"
  33#include "dibx000_common.h"
  34
  35static int debug;
  36module_param(debug, int, 0644);
  37MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
  38
  39#define dprintk(fmt, arg...) do {                                       \
  40        if (debug)                                                      \
  41                printk(KERN_DEBUG pr_fmt("%s: " fmt),                   \
  42                       __func__, ##arg);                                \
  43} while (0)
  44
  45#define CONFIG_SYS_DVBT
  46#define CONFIG_SYS_ISDBT
  47#define CONFIG_BAND_CBAND
  48#define CONFIG_BAND_VHF
  49#define CONFIG_BAND_UHF
  50#define CONFIG_DIB0090_USE_PWM_AGC
  51
  52#define EN_LNA0      0x8000
  53#define EN_LNA1      0x4000
  54#define EN_LNA2      0x2000
  55#define EN_LNA3      0x1000
  56#define EN_MIX0      0x0800
  57#define EN_MIX1      0x0400
  58#define EN_MIX2      0x0200
  59#define EN_MIX3      0x0100
  60#define EN_IQADC     0x0040
  61#define EN_PLL       0x0020
  62#define EN_TX        0x0010
  63#define EN_BB        0x0008
  64#define EN_LO        0x0004
  65#define EN_BIAS      0x0001
  66
  67#define EN_IQANA     0x0002
  68#define EN_DIGCLK    0x0080     /* not in the 0x24 reg, only in 0x1b */
  69#define EN_CRYSTAL   0x0002
  70
  71#define EN_UHF           0x22E9
  72#define EN_VHF           0x44E9
  73#define EN_LBD           0x11E9
  74#define EN_SBD           0x44E9
  75#define EN_CAB           0x88E9
  76
  77/* Calibration defines */
  78#define      DC_CAL 0x1
  79#define     WBD_CAL 0x2
  80#define    TEMP_CAL 0x4
  81#define CAPTRIM_CAL 0x8
  82
  83#define KROSUS_PLL_LOCKED   0x800
  84#define KROSUS              0x2
  85
  86/* Use those defines to identify SOC version */
  87#define SOC               0x02
  88#define SOC_7090_P1G_11R1 0x82
  89#define SOC_7090_P1G_21R1 0x8a
  90#define SOC_8090_P1G_11R1 0x86
  91#define SOC_8090_P1G_21R1 0x8e
  92
  93/* else use thos ones to check */
  94#define P1A_B      0x0
  95#define P1C        0x1
  96#define P1D_E_F    0x3
  97#define P1G        0x7
  98#define P1G_21R2   0xf
  99
 100#define MP001 0x1               /* Single 9090/8096 */
 101#define MP005 0x4               /* Single Sband */
 102#define MP008 0x6               /* Dual diversity VHF-UHF-LBAND */
 103#define MP009 0x7               /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
 104
 105#define pgm_read_word(w) (*w)
 106
 107struct dc_calibration;
 108
 109struct dib0090_tuning {
 110        u32 max_freq;           /* for every frequency less than or equal to that field: this information is correct */
 111        u8 switch_trim;
 112        u8 lna_tune;
 113        u16 lna_bias;
 114        u16 v2i;
 115        u16 mix;
 116        u16 load;
 117        u16 tuner_enable;
 118};
 119
 120struct dib0090_pll {
 121        u32 max_freq;           /* for every frequency less than or equal to that field: this information is correct */
 122        u8 vco_band;
 123        u8 hfdiv_code;
 124        u8 hfdiv;
 125        u8 topresc;
 126};
 127
 128struct dib0090_identity {
 129        u8 version;
 130        u8 product;
 131        u8 p1g;
 132        u8 in_soc;
 133};
 134
 135struct dib0090_state {
 136        struct i2c_adapter *i2c;
 137        struct dvb_frontend *fe;
 138        const struct dib0090_config *config;
 139
 140        u8 current_band;
 141        enum frontend_tune_state tune_state;
 142        u32 current_rf;
 143
 144        u16 wbd_offset;
 145        s16 wbd_target;         /* in dB */
 146
 147        s16 rf_gain_limit;      /* take-over-point: where to split between bb and rf gain */
 148        s16 current_gain;       /* keeps the currently programmed gain */
 149        u8 agc_step;            /* new binary search */
 150
 151        u16 gain[2];            /* for channel monitoring */
 152
 153        const u16 *rf_ramp;
 154        const u16 *bb_ramp;
 155
 156        /* for the software AGC ramps */
 157        u16 bb_1_def;
 158        u16 rf_lt_def;
 159        u16 gain_reg[4];
 160
 161        /* for the captrim/dc-offset search */
 162        s8 step;
 163        s16 adc_diff;
 164        s16 min_adc_diff;
 165
 166        s8 captrim;
 167        s8 fcaptrim;
 168
 169        const struct dc_calibration *dc;
 170        u16 bb6, bb7;
 171
 172        const struct dib0090_tuning *current_tune_table_index;
 173        const struct dib0090_pll *current_pll_table_index;
 174
 175        u8 tuner_is_tuned;
 176        u8 agc_freeze;
 177
 178        struct dib0090_identity identity;
 179
 180        u32 rf_request;
 181        u8 current_standard;
 182
 183        u8 calibrate;
 184        u32 rest;
 185        u16 bias;
 186        s16 temperature;
 187
 188        u8 wbd_calibration_gain;
 189        const struct dib0090_wbd_slope *current_wbd_table;
 190        u16 wbdmux;
 191
 192        /* for the I2C transfer */
 193        struct i2c_msg msg[2];
 194        u8 i2c_write_buffer[3];
 195        u8 i2c_read_buffer[2];
 196        struct mutex i2c_buffer_lock;
 197};
 198
 199struct dib0090_fw_state {
 200        struct i2c_adapter *i2c;
 201        struct dvb_frontend *fe;
 202        struct dib0090_identity identity;
 203        const struct dib0090_config *config;
 204
 205        /* for the I2C transfer */
 206        struct i2c_msg msg;
 207        u8 i2c_write_buffer[2];
 208        u8 i2c_read_buffer[2];
 209        struct mutex i2c_buffer_lock;
 210};
 211
 212static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
 213{
 214        u16 ret;
 215
 216        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
 217                dprintk("could not acquire lock\n");
 218                return 0;
 219        }
 220
 221        state->i2c_write_buffer[0] = reg;
 222
 223        memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
 224        state->msg[0].addr = state->config->i2c_address;
 225        state->msg[0].flags = 0;
 226        state->msg[0].buf = state->i2c_write_buffer;
 227        state->msg[0].len = 1;
 228        state->msg[1].addr = state->config->i2c_address;
 229        state->msg[1].flags = I2C_M_RD;
 230        state->msg[1].buf = state->i2c_read_buffer;
 231        state->msg[1].len = 2;
 232
 233        if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 234                pr_warn("DiB0090 I2C read failed\n");
 235                ret = 0;
 236        } else
 237                ret = (state->i2c_read_buffer[0] << 8)
 238                        | state->i2c_read_buffer[1];
 239
 240        mutex_unlock(&state->i2c_buffer_lock);
 241        return ret;
 242}
 243
 244static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
 245{
 246        int ret;
 247
 248        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
 249                dprintk("could not acquire lock\n");
 250                return -EINVAL;
 251        }
 252
 253        state->i2c_write_buffer[0] = reg & 0xff;
 254        state->i2c_write_buffer[1] = val >> 8;
 255        state->i2c_write_buffer[2] = val & 0xff;
 256
 257        memset(state->msg, 0, sizeof(struct i2c_msg));
 258        state->msg[0].addr = state->config->i2c_address;
 259        state->msg[0].flags = 0;
 260        state->msg[0].buf = state->i2c_write_buffer;
 261        state->msg[0].len = 3;
 262
 263        if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 264                pr_warn("DiB0090 I2C write failed\n");
 265                ret = -EREMOTEIO;
 266        } else
 267                ret = 0;
 268
 269        mutex_unlock(&state->i2c_buffer_lock);
 270        return ret;
 271}
 272
 273static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
 274{
 275        u16 ret;
 276
 277        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
 278                dprintk("could not acquire lock\n");
 279                return 0;
 280        }
 281
 282        state->i2c_write_buffer[0] = reg;
 283
 284        memset(&state->msg, 0, sizeof(struct i2c_msg));
 285        state->msg.addr = reg;
 286        state->msg.flags = I2C_M_RD;
 287        state->msg.buf = state->i2c_read_buffer;
 288        state->msg.len = 2;
 289        if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 290                pr_warn("DiB0090 I2C read failed\n");
 291                ret = 0;
 292        } else
 293                ret = (state->i2c_read_buffer[0] << 8)
 294                        | state->i2c_read_buffer[1];
 295
 296        mutex_unlock(&state->i2c_buffer_lock);
 297        return ret;
 298}
 299
 300static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
 301{
 302        int ret;
 303
 304        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
 305                dprintk("could not acquire lock\n");
 306                return -EINVAL;
 307        }
 308
 309        state->i2c_write_buffer[0] = val >> 8;
 310        state->i2c_write_buffer[1] = val & 0xff;
 311
 312        memset(&state->msg, 0, sizeof(struct i2c_msg));
 313        state->msg.addr = reg;
 314        state->msg.flags = 0;
 315        state->msg.buf = state->i2c_write_buffer;
 316        state->msg.len = 2;
 317        if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 318                pr_warn("DiB0090 I2C write failed\n");
 319                ret = -EREMOTEIO;
 320        } else
 321                ret = 0;
 322
 323        mutex_unlock(&state->i2c_buffer_lock);
 324        return ret;
 325}
 326
 327#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)
 328#define ADC_TARGET -220
 329#define GAIN_ALPHA 5
 330#define WBD_ALPHA 6
 331#define LPF     100
 332static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
 333{
 334        do {
 335                dib0090_write_reg(state, r++, *b++);
 336        } while (--c);
 337}
 338
 339static int dib0090_identify(struct dvb_frontend *fe)
 340{
 341        struct dib0090_state *state = fe->tuner_priv;
 342        u16 v;
 343        struct dib0090_identity *identity = &state->identity;
 344
 345        v = dib0090_read_reg(state, 0x1a);
 346
 347        identity->p1g = 0;
 348        identity->in_soc = 0;
 349
 350        dprintk("Tuner identification (Version = 0x%04x)\n", v);
 351
 352        /* without PLL lock info */
 353        v &= ~KROSUS_PLL_LOCKED;
 354
 355        identity->version = v & 0xff;
 356        identity->product = (v >> 8) & 0xf;
 357
 358        if (identity->product != KROSUS)
 359                goto identification_error;
 360
 361        if ((identity->version & 0x3) == SOC) {
 362                identity->in_soc = 1;
 363                switch (identity->version) {
 364                case SOC_8090_P1G_11R1:
 365                        dprintk("SOC 8090 P1-G11R1 Has been detected\n");
 366                        identity->p1g = 1;
 367                        break;
 368                case SOC_8090_P1G_21R1:
 369                        dprintk("SOC 8090 P1-G21R1 Has been detected\n");
 370                        identity->p1g = 1;
 371                        break;
 372                case SOC_7090_P1G_11R1:
 373                        dprintk("SOC 7090 P1-G11R1 Has been detected\n");
 374                        identity->p1g = 1;
 375                        break;
 376                case SOC_7090_P1G_21R1:
 377                        dprintk("SOC 7090 P1-G21R1 Has been detected\n");
 378                        identity->p1g = 1;
 379                        break;
 380                default:
 381                        goto identification_error;
 382                }
 383        } else {
 384                switch ((identity->version >> 5) & 0x7) {
 385                case MP001:
 386                        dprintk("MP001 : 9090/8096\n");
 387                        break;
 388                case MP005:
 389                        dprintk("MP005 : Single Sband\n");
 390                        break;
 391                case MP008:
 392                        dprintk("MP008 : diversity VHF-UHF-LBAND\n");
 393                        break;
 394                case MP009:
 395                        dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
 396                        break;
 397                default:
 398                        goto identification_error;
 399                }
 400
 401                switch (identity->version & 0x1f) {
 402                case P1G_21R2:
 403                        dprintk("P1G_21R2 detected\n");
 404                        identity->p1g = 1;
 405                        break;
 406                case P1G:
 407                        dprintk("P1G detected\n");
 408                        identity->p1g = 1;
 409                        break;
 410                case P1D_E_F:
 411                        dprintk("P1D/E/F detected\n");
 412                        break;
 413                case P1C:
 414                        dprintk("P1C detected\n");
 415                        break;
 416                case P1A_B:
 417                        dprintk("P1-A/B detected: driver is deactivated - not available\n");
 418                        goto identification_error;
 419                        break;
 420                default:
 421                        goto identification_error;
 422                }
 423        }
 424
 425        return 0;
 426
 427identification_error:
 428        return -EIO;
 429}
 430
 431static int dib0090_fw_identify(struct dvb_frontend *fe)
 432{
 433        struct dib0090_fw_state *state = fe->tuner_priv;
 434        struct dib0090_identity *identity = &state->identity;
 435
 436        u16 v = dib0090_fw_read_reg(state, 0x1a);
 437        identity->p1g = 0;
 438        identity->in_soc = 0;
 439
 440        dprintk("FE: Tuner identification (Version = 0x%04x)\n", v);
 441
 442        /* without PLL lock info */
 443        v &= ~KROSUS_PLL_LOCKED;
 444
 445        identity->version = v & 0xff;
 446        identity->product = (v >> 8) & 0xf;
 447
 448        if (identity->product != KROSUS)
 449                goto identification_error;
 450
 451        if ((identity->version & 0x3) == SOC) {
 452                identity->in_soc = 1;
 453                switch (identity->version) {
 454                case SOC_8090_P1G_11R1:
 455                        dprintk("SOC 8090 P1-G11R1 Has been detected\n");
 456                        identity->p1g = 1;
 457                        break;
 458                case SOC_8090_P1G_21R1:
 459                        dprintk("SOC 8090 P1-G21R1 Has been detected\n");
 460                        identity->p1g = 1;
 461                        break;
 462                case SOC_7090_P1G_11R1:
 463                        dprintk("SOC 7090 P1-G11R1 Has been detected\n");
 464                        identity->p1g = 1;
 465                        break;
 466                case SOC_7090_P1G_21R1:
 467                        dprintk("SOC 7090 P1-G21R1 Has been detected\n");
 468                        identity->p1g = 1;
 469                        break;
 470                default:
 471                        goto identification_error;
 472                }
 473        } else {
 474                switch ((identity->version >> 5) & 0x7) {
 475                case MP001:
 476                        dprintk("MP001 : 9090/8096\n");
 477                        break;
 478                case MP005:
 479                        dprintk("MP005 : Single Sband\n");
 480                        break;
 481                case MP008:
 482                        dprintk("MP008 : diversity VHF-UHF-LBAND\n");
 483                        break;
 484                case MP009:
 485                        dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
 486                        break;
 487                default:
 488                        goto identification_error;
 489                }
 490
 491                switch (identity->version & 0x1f) {
 492                case P1G_21R2:
 493                        dprintk("P1G_21R2 detected\n");
 494                        identity->p1g = 1;
 495                        break;
 496                case P1G:
 497                        dprintk("P1G detected\n");
 498                        identity->p1g = 1;
 499                        break;
 500                case P1D_E_F:
 501                        dprintk("P1D/E/F detected\n");
 502                        break;
 503                case P1C:
 504                        dprintk("P1C detected\n");
 505                        break;
 506                case P1A_B:
 507                        dprintk("P1-A/B detected: driver is deactivated - not available\n");
 508                        goto identification_error;
 509                        break;
 510                default:
 511                        goto identification_error;
 512                }
 513        }
 514
 515        return 0;
 516
 517identification_error:
 518        return -EIO;
 519}
 520
 521static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
 522{
 523        struct dib0090_state *state = fe->tuner_priv;
 524        u16 PllCfg, i, v;
 525
 526        HARD_RESET(state);
 527        dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
 528        if (cfg->in_soc)
 529                return;
 530
 531        dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);        /* PLL, DIG_CLK and CRYSTAL remain */
 532        /* adcClkOutRatio=8->7, release reset */
 533        dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
 534        if (cfg->clkoutdrive != 0)
 535                dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
 536                                | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
 537        else
 538                dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
 539                                | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
 540
 541        /* Read Pll current config * */
 542        PllCfg = dib0090_read_reg(state, 0x21);
 543
 544        /** Reconfigure PLL if current setting is different from default setting **/
 545        if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
 546                        && !cfg->io.pll_bypass) {
 547
 548                /* Set Bypass mode */
 549                PllCfg |= (1 << 15);
 550                dib0090_write_reg(state, 0x21, PllCfg);
 551
 552                /* Set Reset Pll */
 553                PllCfg &= ~(1 << 13);
 554                dib0090_write_reg(state, 0x21, PllCfg);
 555
 556        /*** Set new Pll configuration in bypass and reset state ***/
 557                PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
 558                dib0090_write_reg(state, 0x21, PllCfg);
 559
 560                /* Remove Reset Pll */
 561                PllCfg |= (1 << 13);
 562                dib0090_write_reg(state, 0x21, PllCfg);
 563
 564        /*** Wait for PLL lock ***/
 565                i = 100;
 566                do {
 567                        v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
 568                        if (v)
 569                                break;
 570                } while (--i);
 571
 572                if (i == 0) {
 573                        dprintk("Pll: Unable to lock Pll\n");
 574                        return;
 575                }
 576
 577                /* Finally Remove Bypass mode */
 578                PllCfg &= ~(1 << 15);
 579                dib0090_write_reg(state, 0x21, PllCfg);
 580        }
 581
 582        if (cfg->io.pll_bypass) {
 583                PllCfg |= (cfg->io.pll_bypass << 15);
 584                dib0090_write_reg(state, 0x21, PllCfg);
 585        }
 586}
 587
 588static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
 589{
 590        struct dib0090_fw_state *state = fe->tuner_priv;
 591        u16 PllCfg;
 592        u16 v;
 593        int i;
 594
 595        dprintk("fw reset digital\n");
 596        HARD_RESET(state);
 597
 598        dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
 599        dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);     /* PLL, DIG_CLK and CRYSTAL remain */
 600
 601        dib0090_fw_write_reg(state, 0x20,
 602                        ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
 603
 604        v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
 605        if (cfg->clkoutdrive != 0)
 606                v |= cfg->clkoutdrive << 5;
 607        else
 608                v |= 7 << 5;
 609
 610        v |= 2 << 10;
 611        dib0090_fw_write_reg(state, 0x23, v);
 612
 613        /* Read Pll current config * */
 614        PllCfg = dib0090_fw_read_reg(state, 0x21);
 615
 616        /** Reconfigure PLL if current setting is different from default setting **/
 617        if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
 618
 619                /* Set Bypass mode */
 620                PllCfg |= (1 << 15);
 621                dib0090_fw_write_reg(state, 0x21, PllCfg);
 622
 623                /* Set Reset Pll */
 624                PllCfg &= ~(1 << 13);
 625                dib0090_fw_write_reg(state, 0x21, PllCfg);
 626
 627        /*** Set new Pll configuration in bypass and reset state ***/
 628                PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
 629                dib0090_fw_write_reg(state, 0x21, PllCfg);
 630
 631                /* Remove Reset Pll */
 632                PllCfg |= (1 << 13);
 633                dib0090_fw_write_reg(state, 0x21, PllCfg);
 634
 635        /*** Wait for PLL lock ***/
 636                i = 100;
 637                do {
 638                        v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
 639                        if (v)
 640                                break;
 641                } while (--i);
 642
 643                if (i == 0) {
 644                        dprintk("Pll: Unable to lock Pll\n");
 645                        return -EIO;
 646                }
 647
 648                /* Finally Remove Bypass mode */
 649                PllCfg &= ~(1 << 15);
 650                dib0090_fw_write_reg(state, 0x21, PllCfg);
 651        }
 652
 653        if (cfg->io.pll_bypass) {
 654                PllCfg |= (cfg->io.pll_bypass << 15);
 655                dib0090_fw_write_reg(state, 0x21, PllCfg);
 656        }
 657
 658        return dib0090_fw_identify(fe);
 659}
 660
 661static int dib0090_wakeup(struct dvb_frontend *fe)
 662{
 663        struct dib0090_state *state = fe->tuner_priv;
 664        if (state->config->sleep)
 665                state->config->sleep(fe, 0);
 666
 667        /* enable dataTX in case we have been restarted in the wrong moment */
 668        dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
 669        return 0;
 670}
 671
 672static int dib0090_sleep(struct dvb_frontend *fe)
 673{
 674        struct dib0090_state *state = fe->tuner_priv;
 675        if (state->config->sleep)
 676                state->config->sleep(fe, 1);
 677        return 0;
 678}
 679
 680void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
 681{
 682        struct dib0090_state *state = fe->tuner_priv;
 683        if (fast)
 684                dib0090_write_reg(state, 0x04, 0);
 685        else
 686                dib0090_write_reg(state, 0x04, 1);
 687}
 688
 689EXPORT_SYMBOL(dib0090_dcc_freq);
 690
 691static const u16 bb_ramp_pwm_normal_socs[] = {
 692        550, /* max BB gain in 10th of dB */
 693        (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
 694        440,
 695        (4  << 9) | 0, /* BB_RAMP3 = 26dB */
 696        (0  << 9) | 208, /* BB_RAMP4 */
 697        (4  << 9) | 208, /* BB_RAMP5 = 29dB */
 698        (0  << 9) | 440, /* BB_RAMP6 */
 699};
 700
 701static const u16 rf_ramp_pwm_cband_7090p[] = {
 702        280, /* max RF gain in 10th of dB */
 703        18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 704        504, /* ramp_max = maximum X used on the ramp */
 705        (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
 706        (0  << 10) | 504, /* RF_RAMP6, LNA 1 */
 707        (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
 708        (0  << 10) | 364, /* RF_RAMP8, LNA 2 */
 709        (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
 710        (0  << 10) | 228, /* GAIN_4_2, LNA 3 */
 711        (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
 712        (0  << 10) | 109, /* RF_RAMP4, LNA 4 */
 713};
 714
 715static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
 716        186, /* max RF gain in 10th of dB */
 717        40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 718        746, /* ramp_max = maximum X used on the ramp */
 719        (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
 720        (0  << 10) | 746, /* RF_RAMP6, LNA 1 */
 721        (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
 722        (0  << 10) | 0, /* RF_RAMP8, LNA 2 */
 723        (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
 724        (0  << 10) | 345, /* GAIN_4_2, LNA 3 */
 725        (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
 726        (0  << 10) | 200, /* RF_RAMP4, LNA 4 */
 727};
 728
 729static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
 730        86, /* max RF gain in 10th of dB */
 731        40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 732        345, /* ramp_max = maximum X used on the ramp */
 733        (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
 734        (0 << 10) | 0, /* RF_RAMP6, LNA 1 */
 735        (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
 736        (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
 737        (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
 738        (0  << 10) | 345, /* GAIN_4_2, LNA 3 */
 739        (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
 740        (0  << 10) | 200, /* RF_RAMP4, LNA 4 */
 741};
 742
 743static const u16 rf_ramp_pwm_cband_8090[] = {
 744        345, /* max RF gain in 10th of dB */
 745        29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 746        1000, /* ramp_max = maximum X used on the ramp */
 747        (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
 748        (0  << 10) | 1000, /* RF_RAMP4, LNA 1 */
 749        (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
 750        (0  << 10) | 772, /* RF_RAMP6, LNA 2 */
 751        (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
 752        (0  << 10) | 496, /* RF_RAMP8, LNA 3 */
 753        (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
 754        (0  << 10) | 200, /* GAIN_4_2, LNA 4 */
 755};
 756
 757static const u16 rf_ramp_pwm_uhf_7090[] = {
 758        407, /* max RF gain in 10th of dB */
 759        13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 760        529, /* ramp_max = maximum X used on the ramp */
 761        (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
 762        (0  << 10) | 176, /* RF_RAMP4, LNA 1 */
 763        (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
 764        (0  << 10) | 529, /* RF_RAMP6, LNA 2 */
 765        (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
 766        (0  << 10) | 400, /* RF_RAMP8, LNA 3 */
 767        (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
 768        (0  << 10) | 316, /* GAIN_4_2, LNA 4 */
 769};
 770
 771static const u16 rf_ramp_pwm_uhf_8090[] = {
 772        388, /* max RF gain in 10th of dB */
 773        26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 774        1008, /* ramp_max = maximum X used on the ramp */
 775        (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
 776        (0  << 10) | 369, /* RF_RAMP4, LNA 1 */
 777        (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
 778        (0  << 10) | 1008, /* RF_RAMP6, LNA 2 */
 779        (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
 780        (0  << 10) | 809, /* RF_RAMP8, LNA 3 */
 781        (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
 782        (0  << 10) | 659, /* GAIN_4_2, LNA 4 */
 783};
 784
 785/* GENERAL PWM ramp definition for all other Krosus */
 786static const u16 bb_ramp_pwm_normal[] = {
 787        500, /* max BB gain in 10th of dB */
 788        8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
 789        400,
 790        (2  << 9) | 0, /* BB_RAMP3 = 21dB */
 791        (0  << 9) | 168, /* BB_RAMP4 */
 792        (2  << 9) | 168, /* BB_RAMP5 = 29dB */
 793        (0  << 9) | 400, /* BB_RAMP6 */
 794};
 795
 796#if 0
 797/* Currently unused */
 798static const u16 bb_ramp_pwm_boost[] = {
 799        550, /* max BB gain in 10th of dB */
 800        8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
 801        440,
 802        (2  << 9) | 0, /* BB_RAMP3 = 26dB */
 803        (0  << 9) | 208, /* BB_RAMP4 */
 804        (2  << 9) | 208, /* BB_RAMP5 = 29dB */
 805        (0  << 9) | 440, /* BB_RAMP6 */
 806};
 807#endif
 808
 809static const u16 rf_ramp_pwm_cband[] = {
 810        314, /* max RF gain in 10th of dB */
 811        33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 812        1023, /* ramp_max = maximum X used on the ramp */
 813        (8  << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
 814        (0  << 10) | 1023, /* RF_RAMP4, LNA 1 */
 815        (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
 816        (0  << 10) | 742, /* RF_RAMP6, LNA 2 */
 817        (9  << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
 818        (0  << 10) | 468, /* RF_RAMP8, LNA 3 */
 819        (9  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
 820        (0  << 10) | 233, /* GAIN_4_2, LNA 4 */
 821};
 822
 823static const u16 rf_ramp_pwm_vhf[] = {
 824        398, /* max RF gain in 10th of dB */
 825        24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 826        954, /* ramp_max = maximum X used on the ramp */
 827        (7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
 828        (0  << 10) | 290, /* RF_RAMP4, LNA 1 */
 829        (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
 830        (0  << 10) | 954, /* RF_RAMP6, LNA 2 */
 831        (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
 832        (0  << 10) | 699, /* RF_RAMP8, LNA 3 */
 833        (7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
 834        (0  << 10) | 580, /* GAIN_4_2, LNA 4 */
 835};
 836
 837static const u16 rf_ramp_pwm_uhf[] = {
 838        398, /* max RF gain in 10th of dB */
 839        24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 840        954, /* ramp_max = maximum X used on the ramp */
 841        (7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
 842        (0  << 10) | 290, /* RF_RAMP4, LNA 1 */
 843        (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
 844        (0  << 10) | 954, /* RF_RAMP6, LNA 2 */
 845        (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
 846        (0  << 10) | 699, /* RF_RAMP8, LNA 3 */
 847        (7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
 848        (0  << 10) | 580, /* GAIN_4_2, LNA 4 */
 849};
 850
 851#if 0
 852/* Currently unused */
 853static const u16 rf_ramp_pwm_sband[] = {
 854        253, /* max RF gain in 10th of dB */
 855        38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
 856        961,
 857        (4  << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
 858        (0  << 10) | 508, /* RF_RAMP4, LNA 1 */
 859        (9  << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
 860        (0  << 10) | 961, /* RF_RAMP6, LNA 2 */
 861        (0  << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
 862        (0  << 10) | 0, /* RF_RAMP8, LNA 3 */
 863        (0  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
 864        (0  << 10) | 0, /* GAIN_4_2, LNA 4 */
 865};
 866#endif
 867
 868struct slope {
 869        s16 range;
 870        s16 slope;
 871};
 872static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
 873{
 874        u8 i;
 875        u16 rest;
 876        u16 ret = 0;
 877        for (i = 0; i < num; i++) {
 878                if (val > slopes[i].range)
 879                        rest = slopes[i].range;
 880                else
 881                        rest = val;
 882                ret += (rest * slopes[i].slope) / slopes[i].range;
 883                val -= rest;
 884        }
 885        return ret;
 886}
 887
 888static const struct slope dib0090_wbd_slopes[3] = {
 889        {66, 120},              /* -64,-52: offset -   65 */
 890        {600, 170},             /* -52,-35: 65     -  665 */
 891        {170, 250},             /* -45,-10: 665    - 835 */
 892};
 893
 894static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
 895{
 896        wbd &= 0x3ff;
 897        if (wbd < state->wbd_offset)
 898                wbd = 0;
 899        else
 900                wbd -= state->wbd_offset;
 901        /* -64dB is the floor */
 902        return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
 903}
 904
 905static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
 906{
 907        u16 offset = 250;
 908
 909        /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
 910
 911        if (state->current_band == BAND_VHF)
 912                offset = 650;
 913#ifndef FIRMWARE_FIREFLY
 914        if (state->current_band == BAND_VHF)
 915                offset = state->config->wbd_vhf_offset;
 916        if (state->current_band == BAND_CBAND)
 917                offset = state->config->wbd_cband_offset;
 918#endif
 919
 920        state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
 921        dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
 922}
 923
 924static const int gain_reg_addr[4] = {
 925        0x08, 0x0a, 0x0f, 0x01
 926};
 927
 928static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
 929{
 930        u16 rf, bb, ref;
 931        u16 i, v, gain_reg[4] = { 0 }, gain;
 932        const u16 *g;
 933
 934        if (top_delta < -511)
 935                top_delta = -511;
 936        if (top_delta > 511)
 937                top_delta = 511;
 938
 939        if (force) {
 940                top_delta *= (1 << WBD_ALPHA);
 941                gain_delta *= (1 << GAIN_ALPHA);
 942        }
 943
 944        if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))       /* overflow */
 945                state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
 946        else
 947                state->rf_gain_limit += top_delta;
 948
 949        if (state->rf_gain_limit < 0)   /*underflow */
 950                state->rf_gain_limit = 0;
 951
 952        /* use gain as a temporary variable and correct current_gain */
 953        gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
 954        if (gain_delta >= ((s16) gain - state->current_gain))   /* overflow */
 955                state->current_gain = gain;
 956        else
 957                state->current_gain += gain_delta;
 958        /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
 959        if (state->current_gain < 0)
 960                state->current_gain = 0;
 961
 962        /* now split total gain to rf and bb gain */
 963        gain = state->current_gain >> GAIN_ALPHA;
 964
 965        /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
 966        if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
 967                rf = state->rf_gain_limit >> WBD_ALPHA;
 968                bb = gain - rf;
 969                if (bb > state->bb_ramp[0])
 970                        bb = state->bb_ramp[0];
 971        } else {                /* high signal level -> all gains put on RF */
 972                rf = gain;
 973                bb = 0;
 974        }
 975
 976        state->gain[0] = rf;
 977        state->gain[1] = bb;
 978
 979        /* software ramp */
 980        /* Start with RF gains */
 981        g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
 982        ref = rf;
 983        for (i = 0; i < 7; i++) {       /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
 984                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 */
 985                        v = 0;  /* force the gain to write for the current amp to be null */
 986                else if (ref >= g[1])   /* Gain to set is higher than the high working point of this amp */
 987                        v = g[2];       /* force this amp to be full gain */
 988                else            /* compute the value to set to this amp because we are somewhere in his range */
 989                        v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
 990
 991                if (i == 0)     /* LNA 1 reg mapping */
 992                        gain_reg[0] = v;
 993                else if (i == 1)        /* LNA 2 reg mapping */
 994                        gain_reg[0] |= v << 7;
 995                else if (i == 2)        /* LNA 3 reg mapping */
 996                        gain_reg[1] = v;
 997                else if (i == 3)        /* LNA 4 reg mapping */
 998                        gain_reg[1] |= v << 7;
 999                else if (i == 4)        /* CBAND LNA reg mapping */
1000                        gain_reg[2] = v | state->rf_lt_def;
1001                else if (i == 5)        /* BB gain 1 reg mapping */
1002                        gain_reg[3] = v << 3;
1003                else if (i == 6)        /* BB gain 2 reg mapping */
1004                        gain_reg[3] |= v << 8;
1005
1006                g += 3;         /* go to next gain bloc */
1007
1008                /* When RF is finished, start with BB */
1009                if (i == 4) {
1010                        g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
1011                        ref = bb;
1012                }
1013        }
1014        gain_reg[3] |= state->bb_1_def;
1015        gain_reg[3] |= ((bb % 10) * 100) / 125;
1016
1017#ifdef DEBUG_AGC
1018        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,
1019                gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1020#endif
1021
1022        /* Write the amplifier regs */
1023        for (i = 0; i < 4; i++) {
1024                v = gain_reg[i];
1025                if (force || state->gain_reg[i] != v) {
1026                        state->gain_reg[i] = v;
1027                        dib0090_write_reg(state, gain_reg_addr[i], v);
1028                }
1029        }
1030}
1031
1032static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1033{
1034        state->bb_1_def &= 0xdfff;
1035        state->bb_1_def |= onoff << 13;
1036}
1037
1038static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1039{
1040        state->rf_ramp = cfg;
1041}
1042
1043static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1044{
1045        state->rf_ramp = cfg;
1046
1047        dib0090_write_reg(state, 0x2a, 0xffff);
1048
1049        dprintk("total RF gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1050
1051        dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1052        dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1053}
1054
1055static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1056{
1057        state->bb_ramp = cfg;
1058        dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1059}
1060
1061static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1062{
1063        state->bb_ramp = cfg;
1064
1065        dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1066
1067        dib0090_write_reg(state, 0x33, 0xffff);
1068        dprintk("total BB gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1069        dib0090_write_regs(state, 0x35, cfg + 3, 4);
1070}
1071
1072void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1073{
1074        struct dib0090_state *state = fe->tuner_priv;
1075        u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
1076        u16 *rf_ramp = NULL;
1077        u8 en_pwm_rf_mux = 1;
1078
1079        /* reset the AGC */
1080        if (state->config->use_pwm_agc) {
1081                if (state->current_band == BAND_CBAND) {
1082                        if (state->identity.in_soc) {
1083                                bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1084                                if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1085                                        rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
1086                                else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1087                                        if (state->config->is_dib7090e) {
1088                                                if (state->rf_ramp == NULL)
1089                                                        rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1090                                                else
1091                                                        rf_ramp = (u16 *)state->rf_ramp;
1092                                        } else
1093                                                rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
1094                                }
1095                        } else
1096                                rf_ramp = (u16 *)&rf_ramp_pwm_cband;
1097                } else
1098
1099                        if (state->current_band == BAND_VHF) {
1100                                if (state->identity.in_soc) {
1101                                        bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1102                                        /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
1103                                } else
1104                                        rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
1105                        } else if (state->current_band == BAND_UHF) {
1106                                if (state->identity.in_soc) {
1107                                        bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1108                                        if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1109                                                rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
1110                                        else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1111                                                rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
1112                                } else
1113                                        rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
1114                        }
1115                if (rf_ramp)
1116                        dib0090_set_rframp_pwm(state, rf_ramp);
1117                dib0090_set_bbramp_pwm(state, bb_ramp);
1118
1119                /* activate the ramp generator using PWM control */
1120                if (state->rf_ramp)
1121                        dprintk("ramp RF gain = %d BAND = %s version = %d\n",
1122                                state->rf_ramp[0],
1123                                (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND",
1124                                state->identity.version & 0x1f);
1125
1126                if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) ||
1127                    (state->current_band == BAND_CBAND &&
1128                    (state->identity.version & 0x1f) <= P1D_E_F))) {
1129                        dprintk("DE-Engage mux for direct gain reg control\n");
1130                        en_pwm_rf_mux = 0;
1131                } else
1132                        dprintk("Engage mux for PWM control\n");
1133
1134                dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1135
1136                /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
1137                if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1138                        dib0090_write_reg(state, 0x04, 3);
1139                else
1140                        dib0090_write_reg(state, 0x04, 1);
1141                dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
1142        }
1143}
1144EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1145
1146void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1147{
1148        struct dib0090_state *state = fe->tuner_priv;
1149        if (DC_servo_cutoff < 4)
1150                dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1151}
1152EXPORT_SYMBOL(dib0090_set_dc_servo);
1153
1154static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1155{
1156        u16 adc_val = dib0090_read_reg(state, 0x1d);
1157        if (state->identity.in_soc)
1158                adc_val >>= 2;
1159        return adc_val;
1160}
1161
1162int dib0090_gain_control(struct dvb_frontend *fe)
1163{
1164        struct dib0090_state *state = fe->tuner_priv;
1165        enum frontend_tune_state *tune_state = &state->tune_state;
1166        int ret = 10;
1167
1168        u16 wbd_val = 0;
1169        u8 apply_gain_immediatly = 1;
1170        s16 wbd_error = 0, adc_error = 0;
1171
1172        if (*tune_state == CT_AGC_START) {
1173                state->agc_freeze = 0;
1174                dib0090_write_reg(state, 0x04, 0x0);
1175
1176#ifdef CONFIG_BAND_SBAND
1177                if (state->current_band == BAND_SBAND) {
1178                        dib0090_set_rframp(state, rf_ramp_sband);
1179                        dib0090_set_bbramp(state, bb_ramp_boost);
1180                } else
1181#endif
1182#ifdef CONFIG_BAND_VHF
1183                if (state->current_band == BAND_VHF && !state->identity.p1g) {
1184                        dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1185                        dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1186                } else
1187#endif
1188#ifdef CONFIG_BAND_CBAND
1189                if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1190                        dib0090_set_rframp(state, rf_ramp_pwm_cband);
1191                        dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1192                } else
1193#endif
1194                if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1195                        dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1196                        dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1197                } else {
1198                        dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1199                        dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1200                }
1201
1202                dib0090_write_reg(state, 0x32, 0);
1203                dib0090_write_reg(state, 0x39, 0);
1204
1205                dib0090_wbd_target(state, state->current_rf);
1206
1207                state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1208                state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1209
1210                *tune_state = CT_AGC_STEP_0;
1211        } else if (!state->agc_freeze) {
1212                s16 wbd = 0, i, cnt;
1213
1214                int adc;
1215                wbd_val = dib0090_get_slow_adc_val(state);
1216
1217                if (*tune_state == CT_AGC_STEP_0)
1218                        cnt = 5;
1219                else
1220                        cnt = 1;
1221
1222                for (i = 0; i < cnt; i++) {
1223                        wbd_val = dib0090_get_slow_adc_val(state);
1224                        wbd += dib0090_wbd_to_db(state, wbd_val);
1225                }
1226                wbd /= cnt;
1227                wbd_error = state->wbd_target - wbd;
1228
1229                if (*tune_state == CT_AGC_STEP_0) {
1230                        if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1231#ifdef CONFIG_BAND_CBAND
1232                                /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1233                                u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1234                                if (state->current_band == BAND_CBAND && ltg2) {
1235                                        ltg2 >>= 1;
1236                                        state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1237                                }
1238#endif
1239                        } else {
1240                                state->agc_step = 0;
1241                                *tune_state = CT_AGC_STEP_1;
1242                        }
1243                } else {
1244                        /* calc the adc power */
1245                        adc = state->config->get_adc_power(fe);
1246                        adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1247
1248                        adc_error = (s16) (((s32) ADC_TARGET) - adc);
1249#ifdef CONFIG_STANDARD_DAB
1250                        if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1251                                adc_error -= 10;
1252#endif
1253#ifdef CONFIG_STANDARD_DVBT
1254                        if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1255                                        (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1256                                adc_error += 60;
1257#endif
1258#ifdef CONFIG_SYS_ISDBT
1259                        if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1260                                                                0)
1261                                                        &&
1262                                                        ((state->fe->dtv_property_cache.layer[0].modulation ==
1263                                                          QAM_64)
1264                                                         || (state->fe->dtv_property_cache.
1265                                                                 layer[0].modulation == QAM_16)))
1266                                                ||
1267                                                ((state->fe->dtv_property_cache.layer[1].segment_count >
1268                                                  0)
1269                                                 &&
1270                                                 ((state->fe->dtv_property_cache.layer[1].modulation ==
1271                                                   QAM_64)
1272                                                  || (state->fe->dtv_property_cache.
1273                                                          layer[1].modulation == QAM_16)))
1274                                                ||
1275                                                ((state->fe->dtv_property_cache.layer[2].segment_count >
1276                                                  0)
1277                                                 &&
1278                                                 ((state->fe->dtv_property_cache.layer[2].modulation ==
1279                                                   QAM_64)
1280                                                  || (state->fe->dtv_property_cache.
1281                                                          layer[2].modulation == QAM_16)))
1282                                                )
1283                                )
1284                                adc_error += 60;
1285#endif
1286
1287                        if (*tune_state == CT_AGC_STEP_1) {     /* quickly go to the correct range of the ADC power */
1288                                if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1289
1290#ifdef CONFIG_STANDARD_DAB
1291                                        if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1292                                                dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));      /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1293                                                dib0090_write_reg(state, 0x04, 0x0);
1294                                        } else
1295#endif
1296                                        {
1297                                                dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1298                                                dib0090_write_reg(state, 0x04, 0x01);   /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1299                                        }
1300
1301                                        *tune_state = CT_AGC_STOP;
1302                                }
1303                        } else {
1304                                /* everything higher than or equal to CT_AGC_STOP means tracking */
1305                                ret = 100;      /* 10ms interval */
1306                                apply_gain_immediatly = 0;
1307                        }
1308                }
1309#ifdef DEBUG_AGC
1310                dprintk
1311                        ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1312                         (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1313                         (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1314#endif
1315        }
1316
1317        /* apply gain */
1318        if (!state->agc_freeze)
1319                dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1320        return ret;
1321}
1322
1323EXPORT_SYMBOL(dib0090_gain_control);
1324
1325void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1326{
1327        struct dib0090_state *state = fe->tuner_priv;
1328        if (rf)
1329                *rf = state->gain[0];
1330        if (bb)
1331                *bb = state->gain[1];
1332        if (rf_gain_limit)
1333                *rf_gain_limit = state->rf_gain_limit;
1334        if (rflt)
1335                *rflt = (state->rf_lt_def >> 10) & 0x7;
1336}
1337
1338EXPORT_SYMBOL(dib0090_get_current_gain);
1339
1340u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1341{
1342        struct dib0090_state *state = fe->tuner_priv;
1343        u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1344        s32 current_temp = state->temperature;
1345        s32 wbd_thot, wbd_tcold;
1346        const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1347
1348        while (f_MHz > wbd->max_freq)
1349                wbd++;
1350
1351        dprintk("using wbd-table-entry with max freq %d\n", wbd->max_freq);
1352
1353        if (current_temp < 0)
1354                current_temp = 0;
1355        if (current_temp > 128)
1356                current_temp = 128;
1357
1358        state->wbdmux &= ~(7 << 13);
1359        if (wbd->wbd_gain != 0)
1360                state->wbdmux |= (wbd->wbd_gain << 13);
1361        else
1362                state->wbdmux |= (4 << 13);
1363
1364        dib0090_write_reg(state, 0x10, state->wbdmux);
1365
1366        wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1367        wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1368
1369        wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1370
1371        state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1372        dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
1373        dprintk("wbd offset applied is %d\n", wbd_tcold);
1374
1375        return state->wbd_offset + wbd_tcold;
1376}
1377EXPORT_SYMBOL(dib0090_get_wbd_target);
1378
1379u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1380{
1381        struct dib0090_state *state = fe->tuner_priv;
1382        return state->wbd_offset;
1383}
1384EXPORT_SYMBOL(dib0090_get_wbd_offset);
1385
1386int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1387{
1388        struct dib0090_state *state = fe->tuner_priv;
1389
1390        dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1391                        | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1392
1393        return 0;
1394}
1395EXPORT_SYMBOL(dib0090_set_switch);
1396
1397int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1398{
1399        struct dib0090_state *state = fe->tuner_priv;
1400
1401        dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1402                        | ((onoff & 1) << 15));
1403        return 0;
1404}
1405EXPORT_SYMBOL(dib0090_set_vga);
1406
1407int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1408{
1409        struct dib0090_state *state = fe->tuner_priv;
1410
1411        if ((!state->identity.p1g) || (!state->identity.in_soc)
1412                        || ((state->identity.version != SOC_7090_P1G_21R1)
1413                                && (state->identity.version != SOC_7090_P1G_11R1))) {
1414                dprintk("%s() function can only be used for dib7090P\n", __func__);
1415                return -ENODEV;
1416        }
1417
1418        if (cfg_sensitivity)
1419                state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1420        else
1421                state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
1422        dib0090_pwm_gain_reset(fe);
1423
1424        return 0;
1425}
1426EXPORT_SYMBOL(dib0090_update_rframp_7090);
1427
1428static const u16 dib0090_defaults[] = {
1429
1430        25, 0x01,
1431        0x0000,
1432        0x99a0,
1433        0x6008,
1434        0x0000,
1435        0x8bcb,
1436        0x0000,
1437        0x0405,
1438        0x0000,
1439        0x0000,
1440        0x0000,
1441        0xb802,
1442        0x0300,
1443        0x2d12,
1444        0xbac0,
1445        0x7c00,
1446        0xdbb9,
1447        0x0954,
1448        0x0743,
1449        0x8000,
1450        0x0001,
1451        0x0040,
1452        0x0100,
1453        0x0000,
1454        0xe910,
1455        0x149e,
1456
1457        1, 0x1c,
1458        0xff2d,
1459
1460        1, 0x39,
1461        0x0000,
1462
1463        2, 0x1e,
1464        0x07FF,
1465        0x0007,
1466
1467        1, 0x24,
1468        EN_UHF | EN_CRYSTAL,
1469
1470        2, 0x3c,
1471        0x3ff,
1472        0x111,
1473        0
1474};
1475
1476static const u16 dib0090_p1g_additionnal_defaults[] = {
1477        1, 0x05,
1478        0xabcd,
1479
1480        1, 0x11,
1481        0x00b4,
1482
1483        1, 0x1c,
1484        0xfffd,
1485
1486        1, 0x40,
1487        0x108,
1488        0
1489};
1490
1491static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1492{
1493        u16 l, r;
1494
1495        l = pgm_read_word(n++);
1496        while (l) {
1497                r = pgm_read_word(n++);
1498                do {
1499                        dib0090_write_reg(state, r, pgm_read_word(n++));
1500                        r++;
1501                } while (--l);
1502                l = pgm_read_word(n++);
1503        }
1504}
1505
1506#define CAP_VALUE_MIN (u8)  9
1507#define CAP_VALUE_MAX (u8) 40
1508#define HR_MIN        (u8) 25
1509#define HR_MAX        (u8) 40
1510#define POLY_MIN      (u8)  0
1511#define POLY_MAX      (u8)  8
1512
1513static void dib0090_set_EFUSE(struct dib0090_state *state)
1514{
1515        u8 c, h, n;
1516        u16 e2, e4;
1517        u16 cal;
1518
1519        e2 = dib0090_read_reg(state, 0x26);
1520        e4 = dib0090_read_reg(state, 0x28);
1521
1522        if ((state->identity.version == P1D_E_F) ||
1523                        (state->identity.version == P1G) || (e2 == 0xffff)) {
1524
1525                dib0090_write_reg(state, 0x22, 0x10);
1526                cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1527
1528                if ((cal < 670) || (cal == 1023))
1529                        cal = 850;
1530                n = 165 - ((cal * 10)>>6) ;
1531                e2 = e4 = (3<<12) | (34<<6) | (n);
1532        }
1533
1534        if (e2 != e4)
1535                e2 &= e4; /* Remove the redundancy  */
1536
1537        if (e2 != 0xffff) {
1538                c = e2 & 0x3f;
1539                n = (e2 >> 12) & 0xf;
1540                h = (e2 >> 6) & 0x3f;
1541
1542                if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1543                        c = 32;
1544                else
1545                        c += 14;
1546                if ((h >= HR_MAX) || (h <= HR_MIN))
1547                        h = 34;
1548                if ((n >= POLY_MAX) || (n <= POLY_MIN))
1549                        n = 3;
1550
1551                dib0090_write_reg(state, 0x13, (h << 10));
1552                e2 = (n << 11) | ((h >> 2)<<6) | c;
1553                dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
1554        }
1555}
1556
1557static int dib0090_reset(struct dvb_frontend *fe)
1558{
1559        struct dib0090_state *state = fe->tuner_priv;
1560
1561        dib0090_reset_digital(fe, state->config);
1562        if (dib0090_identify(fe) < 0)
1563                return -EIO;
1564
1565#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1566        if (!(state->identity.version & 0x1))   /* it is P1B - reset is already done */
1567                return 0;
1568#endif
1569
1570        if (!state->identity.in_soc) {
1571                if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1572                        dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1573                else
1574                        dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1575        }
1576
1577        dib0090_set_default_config(state, dib0090_defaults);
1578
1579        if (state->identity.in_soc)
1580                dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
1581
1582        if (state->identity.p1g)
1583                dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1584
1585        /* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
1586        if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1587                dib0090_set_EFUSE(state);
1588
1589        /* Congigure in function of the crystal */
1590        if (state->config->force_crystal_mode != 0)
1591                dib0090_write_reg(state, 0x14,
1592                                state->config->force_crystal_mode & 3);
1593        else if (state->config->io.clock_khz >= 24000)
1594                dib0090_write_reg(state, 0x14, 1);
1595        else
1596                dib0090_write_reg(state, 0x14, 2);
1597        dprintk("Pll lock : %d\n", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1598
1599        state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1600
1601        return 0;
1602}
1603
1604#define steps(u) (((u) > 15) ? ((u)-16) : (u))
1605#define INTERN_WAIT 10
1606static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1607{
1608        int ret = INTERN_WAIT * 10;
1609
1610        switch (*tune_state) {
1611        case CT_TUNER_STEP_2:
1612                /* Turns to positive */
1613                dib0090_write_reg(state, 0x1f, 0x7);
1614                *tune_state = CT_TUNER_STEP_3;
1615                break;
1616
1617        case CT_TUNER_STEP_3:
1618                state->adc_diff = dib0090_read_reg(state, 0x1d);
1619
1620                /* Turns to negative */
1621                dib0090_write_reg(state, 0x1f, 0x4);
1622                *tune_state = CT_TUNER_STEP_4;
1623                break;
1624
1625        case CT_TUNER_STEP_4:
1626                state->adc_diff -= dib0090_read_reg(state, 0x1d);
1627                *tune_state = CT_TUNER_STEP_5;
1628                ret = 0;
1629                break;
1630
1631        default:
1632                break;
1633        }
1634
1635        return ret;
1636}
1637
1638struct dc_calibration {
1639        u8 addr;
1640        u8 offset;
1641        u8 pga:1;
1642        u16 bb1;
1643        u8 i:1;
1644};
1645
1646static const struct dc_calibration dc_table[] = {
1647        /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1648        {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1649        {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1650        /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1651        {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1652        {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1653        {0},
1654};
1655
1656static const struct dc_calibration dc_p1g_table[] = {
1657        /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1658        /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1659        {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1660        {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1661        /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1662        {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1663        {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1664        {0},
1665};
1666
1667static void dib0090_set_trim(struct dib0090_state *state)
1668{
1669        u16 *val;
1670
1671        if (state->dc->addr == 0x07)
1672                val = &state->bb7;
1673        else
1674                val = &state->bb6;
1675
1676        *val &= ~(0x1f << state->dc->offset);
1677        *val |= state->step << state->dc->offset;
1678
1679        dib0090_write_reg(state, state->dc->addr, *val);
1680}
1681
1682static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1683{
1684        int ret = 0;
1685        u16 reg;
1686
1687        switch (*tune_state) {
1688        case CT_TUNER_START:
1689                dprintk("Start DC offset calibration");
1690
1691                /* force vcm2 = 0.8V */
1692                state->bb6 = 0;
1693                state->bb7 = 0x040d;
1694
1695                /* the LNA AND LO are off */
1696                reg = dib0090_read_reg(state, 0x24) & 0x0ffb;   /* shutdown lna and lo */
1697                dib0090_write_reg(state, 0x24, reg);
1698
1699                state->wbdmux = dib0090_read_reg(state, 0x10);
1700                dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1701                dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1702
1703                state->dc = dc_table;
1704
1705                if (state->identity.p1g)
1706                        state->dc = dc_p1g_table;
1707
1708                /* fall through */
1709        case CT_TUNER_STEP_0:
1710                dprintk("Start/continue DC calibration for %s path\n",
1711                        (state->dc->i == 1) ? "I" : "Q");
1712                dib0090_write_reg(state, 0x01, state->dc->bb1);
1713                dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1714
1715                state->step = 0;
1716                state->min_adc_diff = 1023;
1717                *tune_state = CT_TUNER_STEP_1;
1718                ret = 50;
1719                break;
1720
1721        case CT_TUNER_STEP_1:
1722                dib0090_set_trim(state);
1723                *tune_state = CT_TUNER_STEP_2;
1724                break;
1725
1726        case CT_TUNER_STEP_2:
1727        case CT_TUNER_STEP_3:
1728        case CT_TUNER_STEP_4:
1729                ret = dib0090_get_offset(state, tune_state);
1730                break;
1731
1732        case CT_TUNER_STEP_5:   /* found an offset */
1733                dprintk("adc_diff = %d, current step= %d\n", (u32) state->adc_diff, state->step);
1734                if (state->step == 0 && state->adc_diff < 0) {
1735                        state->min_adc_diff = -1023;
1736                        dprintk("Change of sign of the minimum adc diff\n");
1737                }
1738
1739                dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d\n", state->adc_diff, state->min_adc_diff, state->step);
1740
1741                /* first turn for this frequency */
1742                if (state->step == 0) {
1743                        if (state->dc->pga && state->adc_diff < 0)
1744                                state->step = 0x10;
1745                        if (state->dc->pga == 0 && state->adc_diff > 0)
1746                                state->step = 0x10;
1747                }
1748
1749                /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1750                if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1751                        /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1752                        state->step++;
1753                        state->min_adc_diff = state->adc_diff;
1754                        *tune_state = CT_TUNER_STEP_1;
1755                } else {
1756                        /* the minimum was what we have seen in the step before */
1757                        if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1758                                dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff);
1759                                state->step--;
1760                        }
1761
1762                        dib0090_set_trim(state);
1763                        dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd\n", state->dc->addr, state->adc_diff, state->step);
1764
1765                        state->dc++;
1766                        if (state->dc->addr == 0)       /* done */
1767                                *tune_state = CT_TUNER_STEP_6;
1768                        else
1769                                *tune_state = CT_TUNER_STEP_0;
1770
1771                }
1772                break;
1773
1774        case CT_TUNER_STEP_6:
1775                dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1776                dib0090_write_reg(state, 0x1f, 0x7);
1777                *tune_state = CT_TUNER_START;   /* reset done -> real tuning can now begin */
1778                state->calibrate &= ~DC_CAL;
1779        default:
1780                break;
1781        }
1782        return ret;
1783}
1784
1785static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1786{
1787        u8 wbd_gain;
1788        const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1789
1790        switch (*tune_state) {
1791        case CT_TUNER_START:
1792                while (state->current_rf / 1000 > wbd->max_freq)
1793                        wbd++;
1794                if (wbd->wbd_gain != 0)
1795                        wbd_gain = wbd->wbd_gain;
1796                else {
1797                        wbd_gain = 4;
1798#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1799                        if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1800                                wbd_gain = 2;
1801#endif
1802                }
1803
1804                if (wbd_gain == state->wbd_calibration_gain) {  /* the WBD calibration has already been done */
1805                        *tune_state = CT_TUNER_START;
1806                        state->calibrate &= ~WBD_CAL;
1807                        return 0;
1808                }
1809
1810                dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1811
1812                dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1813                *tune_state = CT_TUNER_STEP_0;
1814                state->wbd_calibration_gain = wbd_gain;
1815                return 90;      /* wait for the WBDMUX to switch and for the ADC to sample */
1816
1817        case CT_TUNER_STEP_0:
1818                state->wbd_offset = dib0090_get_slow_adc_val(state);
1819                dprintk("WBD calibration offset = %d\n", state->wbd_offset);
1820                *tune_state = CT_TUNER_START;   /* reset done -> real tuning can now begin */
1821                state->calibrate &= ~WBD_CAL;
1822                break;
1823
1824        default:
1825                break;
1826        }
1827        return 0;
1828}
1829
1830static void dib0090_set_bandwidth(struct dib0090_state *state)
1831{
1832        u16 tmp;
1833
1834        if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1835                tmp = (3 << 14);
1836        else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1837                tmp = (2 << 14);
1838        else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1839                tmp = (1 << 14);
1840        else
1841                tmp = (0 << 14);
1842
1843        state->bb_1_def &= 0x3fff;
1844        state->bb_1_def |= tmp;
1845
1846        dib0090_write_reg(state, 0x01, state->bb_1_def);        /* be sure that we have the right bb-filter */
1847
1848        dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1849        dib0090_write_reg(state, 0x04, 0x1);    /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1850        if (state->identity.in_soc) {
1851                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 */
1852        } else {
1853                dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));     /* 22 = cap_value */
1854                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 */
1855        }
1856}
1857
1858static const struct dib0090_pll dib0090_pll_table[] = {
1859#ifdef CONFIG_BAND_CBAND
1860        {56000, 0, 9, 48, 6},
1861        {70000, 1, 9, 48, 6},
1862        {87000, 0, 8, 32, 4},
1863        {105000, 1, 8, 32, 4},
1864        {115000, 0, 7, 24, 6},
1865        {140000, 1, 7, 24, 6},
1866        {170000, 0, 6, 16, 4},
1867#endif
1868#ifdef CONFIG_BAND_VHF
1869        {200000, 1, 6, 16, 4},
1870        {230000, 0, 5, 12, 6},
1871        {280000, 1, 5, 12, 6},
1872        {340000, 0, 4, 8, 4},
1873        {380000, 1, 4, 8, 4},
1874        {450000, 0, 3, 6, 6},
1875#endif
1876#ifdef CONFIG_BAND_UHF
1877        {580000, 1, 3, 6, 6},
1878        {700000, 0, 2, 4, 4},
1879        {860000, 1, 2, 4, 4},
1880#endif
1881#ifdef CONFIG_BAND_LBAND
1882        {1800000, 1, 0, 2, 4},
1883#endif
1884#ifdef CONFIG_BAND_SBAND
1885        {2900000, 0, 14, 1, 4},
1886#endif
1887};
1888
1889static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1890
1891#ifdef CONFIG_BAND_CBAND
1892        {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1893        {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1894        {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1895#endif
1896#ifdef CONFIG_BAND_UHF
1897        {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1898        {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1899        {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1900        {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1901        {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1902        {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1903#endif
1904#ifdef CONFIG_BAND_LBAND
1905        {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1906        {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1907        {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1908#endif
1909#ifdef CONFIG_BAND_SBAND
1910        {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1911        {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1912#endif
1913};
1914
1915static const struct dib0090_tuning dib0090_tuning_table[] = {
1916
1917#ifdef CONFIG_BAND_CBAND
1918        {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1919#endif
1920#ifdef CONFIG_BAND_VHF
1921        {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1922        {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1923        {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1924#endif
1925#ifdef CONFIG_BAND_UHF
1926        {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1927        {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1928        {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1929        {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1930        {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1931        {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1932#endif
1933#ifdef CONFIG_BAND_LBAND
1934        {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1935        {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1936        {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1937#endif
1938#ifdef CONFIG_BAND_SBAND
1939        {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1940        {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1941#endif
1942};
1943
1944static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1945#ifdef CONFIG_BAND_CBAND
1946        {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1947#endif
1948#ifdef CONFIG_BAND_VHF
1949        {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1950        {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1951        {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1952#endif
1953#ifdef CONFIG_BAND_UHF
1954        {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1955        {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1956        {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1957        {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1958        {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1959        {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1960        {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1961#endif
1962#ifdef CONFIG_BAND_LBAND
1963        {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1964        {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1965        {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1966#endif
1967#ifdef CONFIG_BAND_SBAND
1968        {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1969        {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1970#endif
1971};
1972
1973static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1974#ifdef CONFIG_BAND_CBAND
1975        {57000, 0, 11, 48, 6},
1976        {70000, 1, 11, 48, 6},
1977        {86000, 0, 10, 32, 4},
1978        {105000, 1, 10, 32, 4},
1979        {115000, 0, 9, 24, 6},
1980        {140000, 1, 9, 24, 6},
1981        {170000, 0, 8, 16, 4},
1982#endif
1983#ifdef CONFIG_BAND_VHF
1984        {200000, 1, 8, 16, 4},
1985        {230000, 0, 7, 12, 6},
1986        {280000, 1, 7, 12, 6},
1987        {340000, 0, 6, 8, 4},
1988        {380000, 1, 6, 8, 4},
1989        {455000, 0, 5, 6, 6},
1990#endif
1991#ifdef CONFIG_BAND_UHF
1992        {580000, 1, 5, 6, 6},
1993        {680000, 0, 4, 4, 4},
1994        {860000, 1, 4, 4, 4},
1995#endif
1996#ifdef CONFIG_BAND_LBAND
1997        {1800000, 1, 2, 2, 4},
1998#endif
1999#ifdef CONFIG_BAND_SBAND
2000        {2900000, 0, 1, 1, 6},
2001#endif
2002};
2003
2004static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
2005#ifdef CONFIG_BAND_CBAND
2006        {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2007        {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2008        {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2009#endif
2010#ifdef CONFIG_BAND_UHF
2011        {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2012        {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2013        {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2014        {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2015        {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2016        {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2017#endif
2018#ifdef CONFIG_BAND_LBAND
2019        {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2020        {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2021        {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2022#endif
2023#ifdef CONFIG_BAND_SBAND
2024        {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2025        {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2026#endif
2027};
2028
2029static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2030#ifdef CONFIG_BAND_CBAND
2031        {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2032        {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2033        {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2034        {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2035#endif
2036};
2037
2038static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2039#ifdef CONFIG_BAND_CBAND
2040        { 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2041        { 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2042        { 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2043        { 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2044        { 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2045        { 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2046#endif
2047};
2048
2049int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2050                u8 cfg_sensitivity)
2051{
2052        struct dib0090_state *state = fe->tuner_priv;
2053        const struct dib0090_tuning *tune =
2054                dib0090_tuning_table_cband_7090e_sensitivity;
2055        static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2056                { 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2057                { 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2058                { 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2059        };
2060
2061        if ((!state->identity.p1g) || (!state->identity.in_soc)
2062                        || ((state->identity.version != SOC_7090_P1G_21R1)
2063                                && (state->identity.version != SOC_7090_P1G_11R1))) {
2064                dprintk("%s() function can only be used for dib7090\n", __func__);
2065                return -ENODEV;
2066        }
2067
2068        if (cfg_sensitivity)
2069                tune = dib0090_tuning_table_cband_7090e_sensitivity;
2070        else
2071                tune = dib0090_tuning_table_cband_7090e_aci;
2072
2073        while (state->rf_request > tune->max_freq)
2074                tune++;
2075
2076        dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2077                        | (tune->lna_bias & 0x7fff));
2078        dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2079                        | ((tune->lna_tune << 6) & 0x07c0));
2080        return 0;
2081}
2082EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2083
2084static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2085{
2086        int ret = 0;
2087        u16 lo4 = 0xe900;
2088
2089        s16 adc_target;
2090        u16 adc;
2091        s8 step_sign;
2092        u8 force_soft_search = 0;
2093
2094        if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2095                force_soft_search = 1;
2096
2097        if (*tune_state == CT_TUNER_START) {
2098                dprintk("Start Captrim search : %s\n",
2099                        (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2100                dib0090_write_reg(state, 0x10, 0x2B1);
2101                dib0090_write_reg(state, 0x1e, 0x0032);
2102
2103                if (!state->tuner_is_tuned) {
2104                        /* prepare a complete captrim */
2105                        if (!state->identity.p1g || force_soft_search)
2106                                state->step = state->captrim = state->fcaptrim = 64;
2107
2108                        state->current_rf = state->rf_request;
2109                } else {        /* we are already tuned to this frequency - the configuration is correct  */
2110                        if (!state->identity.p1g || force_soft_search) {
2111                                /* do a minimal captrim even if the frequency has not changed */
2112                                state->step = 4;
2113                                state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2114                        }
2115                }
2116                state->adc_diff = 3000;
2117                *tune_state = CT_TUNER_STEP_0;
2118
2119        } else if (*tune_state == CT_TUNER_STEP_0) {
2120                if (state->identity.p1g && !force_soft_search) {
2121                        u8 ratio = 31;
2122
2123                        dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2124                        dib0090_read_reg(state, 0x40);
2125                        ret = 50;
2126                } else {
2127                        state->step /= 2;
2128                        dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2129
2130                        if (state->identity.in_soc)
2131                                ret = 25;
2132                }
2133                *tune_state = CT_TUNER_STEP_1;
2134
2135        } else if (*tune_state == CT_TUNER_STEP_1) {
2136                if (state->identity.p1g && !force_soft_search) {
2137                        dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2138                        dib0090_read_reg(state, 0x40);
2139
2140                        state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2141                        dprintk("***Final Captrim= 0x%x\n", state->fcaptrim);
2142                        *tune_state = CT_TUNER_STEP_3;
2143
2144                } else {
2145                        /* MERGE for all krosus before P1G */
2146                        adc = dib0090_get_slow_adc_val(state);
2147                        dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2148
2149                        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 !!! */
2150                                adc_target = 200;
2151                        } else
2152                                adc_target = 400;
2153
2154                        if (adc >= adc_target) {
2155                                adc -= adc_target;
2156                                step_sign = -1;
2157                        } else {
2158                                adc = adc_target - adc;
2159                                step_sign = 1;
2160                        }
2161
2162                        if (adc < state->adc_diff) {
2163                                dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2164                                state->adc_diff = adc;
2165                                state->fcaptrim = state->captrim;
2166                        }
2167
2168                        state->captrim += step_sign * state->step;
2169                        if (state->step >= 1)
2170                                *tune_state = CT_TUNER_STEP_0;
2171                        else
2172                                *tune_state = CT_TUNER_STEP_2;
2173
2174                        ret = 25;
2175                }
2176        } else if (*tune_state == CT_TUNER_STEP_2) {    /* this step is only used by krosus < P1G */
2177                /*write the final cptrim config */
2178                dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2179
2180                *tune_state = CT_TUNER_STEP_3;
2181
2182        } else if (*tune_state == CT_TUNER_STEP_3) {
2183                state->calibrate &= ~CAPTRIM_CAL;
2184                *tune_state = CT_TUNER_STEP_0;
2185        }
2186
2187        return ret;
2188}
2189
2190static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2191{
2192        int ret = 15;
2193        s16 val;
2194
2195        switch (*tune_state) {
2196        case CT_TUNER_START:
2197                state->wbdmux = dib0090_read_reg(state, 0x10);
2198                dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2199
2200                state->bias = dib0090_read_reg(state, 0x13);
2201                dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2202
2203                *tune_state = CT_TUNER_STEP_0;
2204                /* wait for the WBDMUX to switch and for the ADC to sample */
2205                break;
2206
2207        case CT_TUNER_STEP_0:
2208                state->adc_diff = dib0090_get_slow_adc_val(state);
2209                dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2210                *tune_state = CT_TUNER_STEP_1;
2211                break;
2212
2213        case CT_TUNER_STEP_1:
2214                val = dib0090_get_slow_adc_val(state);
2215                state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2216
2217                dprintk("temperature: %d C\n", state->temperature - 30);
2218
2219                *tune_state = CT_TUNER_STEP_2;
2220                break;
2221
2222        case CT_TUNER_STEP_2:
2223                dib0090_write_reg(state, 0x13, state->bias);
2224                dib0090_write_reg(state, 0x10, state->wbdmux);  /* write back original WBDMUX */
2225
2226                *tune_state = CT_TUNER_START;
2227                state->calibrate &= ~TEMP_CAL;
2228                if (state->config->analog_output == 0)
2229                        dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2230
2231                break;
2232
2233        default:
2234                ret = 0;
2235                break;
2236        }
2237        return ret;
2238}
2239
2240#define WBD     0x781           /* 1 1 1 1 0000 0 0 1 */
2241static int dib0090_tune(struct dvb_frontend *fe)
2242{
2243        struct dib0090_state *state = fe->tuner_priv;
2244        const struct dib0090_tuning *tune = state->current_tune_table_index;
2245        const struct dib0090_pll *pll = state->current_pll_table_index;
2246        enum frontend_tune_state *tune_state = &state->tune_state;
2247
2248        u16 lo5, lo6, Den, tmp;
2249        u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2250        int ret = 10;           /* 1ms is the default delay most of the time */
2251        u8 c, i;
2252
2253        /************************* VCO ***************************/
2254        /* Default values for FG                                 */
2255        /* from these are needed :                               */
2256        /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
2257
2258        /* in any case we first need to do a calibration if needed */
2259        if (*tune_state == CT_TUNER_START) {
2260                /* deactivate DataTX before some calibrations */
2261                if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2262                        dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2263                else
2264                        /* Activate DataTX in case a calibration has been done before */
2265                        if (state->config->analog_output == 0)
2266                                dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2267        }
2268
2269        if (state->calibrate & DC_CAL)
2270                return dib0090_dc_offset_calibration(state, tune_state);
2271        else if (state->calibrate & WBD_CAL) {
2272                if (state->current_rf == 0)
2273                        state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2274                return dib0090_wbd_calibration(state, tune_state);
2275        } else if (state->calibrate & TEMP_CAL)
2276                return dib0090_get_temperature(state, tune_state);
2277        else if (state->calibrate & CAPTRIM_CAL)
2278                return dib0090_captrim_search(state, tune_state);
2279
2280        if (*tune_state == CT_TUNER_START) {
2281                /* 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 */
2282                if (state->config->use_pwm_agc && state->identity.in_soc) {
2283                        tmp = dib0090_read_reg(state, 0x39);
2284                        if ((tmp >> 10) & 0x1)
2285                                dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2286                }
2287
2288                state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2289                state->rf_request =
2290                        state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2291                                        BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2292                                        freq_offset_khz_vhf);
2293
2294                /* in ISDB-T 1seg we shift tuning frequency */
2295                if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2296                                        && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2297                        const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2298                        u8 found_offset = 0;
2299                        u32 margin_khz = 100;
2300
2301                        if (LUT_offset != NULL) {
2302                                while (LUT_offset->RF_freq != 0xffff) {
2303                                        if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2304                                                                && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2305                                                        && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2306                                                state->rf_request += LUT_offset->offset_khz;
2307                                                found_offset = 1;
2308                                                break;
2309                                        }
2310                                        LUT_offset++;
2311                                }
2312                        }
2313
2314                        if (found_offset == 0)
2315                                state->rf_request += 400;
2316                }
2317                if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2318                        state->tuner_is_tuned = 0;
2319                        state->current_rf = 0;
2320                        state->current_standard = 0;
2321
2322                        tune = dib0090_tuning_table;
2323                        if (state->identity.p1g)
2324                                tune = dib0090_p1g_tuning_table;
2325
2326                        tmp = (state->identity.version >> 5) & 0x7;
2327
2328                        if (state->identity.in_soc) {
2329                                if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2330                                        if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2331                                                        || state->current_band & BAND_UHF) {
2332                                                state->current_band = BAND_CBAND;
2333                                                if (state->config->is_dib7090e)
2334                                                        tune = dib0090_tuning_table_cband_7090e_sensitivity;
2335                                                else
2336                                                        tune = dib0090_tuning_table_cband_7090;
2337                                        }
2338                                } else {        /* Use the CBAND input for all band under UHF */
2339                                        if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2340                                                state->current_band = BAND_CBAND;
2341                                                if (state->config->is_dib7090e)
2342                                                        tune = dib0090_tuning_table_cband_7090e_sensitivity;
2343                                                else
2344                                                        tune = dib0090_tuning_table_cband_7090;
2345                                        }
2346                                }
2347                        } else
2348                         if (tmp == 0x4 || tmp == 0x7) {
2349                                /* CBAND tuner version for VHF */
2350                                if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2351                                        state->current_band = BAND_CBAND;       /* Force CBAND */
2352
2353                                        tune = dib0090_tuning_table_fm_vhf_on_cband;
2354                                        if (state->identity.p1g)
2355                                                tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2356                                }
2357                        }
2358
2359                        pll = dib0090_pll_table;
2360                        if (state->identity.p1g)
2361                                pll = dib0090_p1g_pll_table;
2362
2363                        /* Look for the interval */
2364                        while (state->rf_request > tune->max_freq)
2365                                tune++;
2366                        while (state->rf_request > pll->max_freq)
2367                                pll++;
2368
2369                        state->current_tune_table_index = tune;
2370                        state->current_pll_table_index = pll;
2371
2372                        dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2373
2374                        VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2375
2376                        FREF = state->config->io.clock_khz;
2377                        if (state->config->fref_clock_ratio != 0)
2378                                FREF /= state->config->fref_clock_ratio;
2379
2380                        FBDiv = (VCOF_kHz / pll->topresc / FREF);
2381                        Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2382
2383                        if (Rest < LPF)
2384                                Rest = 0;
2385                        else if (Rest < 2 * LPF)
2386                                Rest = 2 * LPF;
2387                        else if (Rest > (FREF - LPF)) {
2388                                Rest = 0;
2389                                FBDiv += 1;
2390                        } else if (Rest > (FREF - 2 * LPF))
2391                                Rest = FREF - 2 * LPF;
2392                        Rest = (Rest * 6528) / (FREF / 10);
2393                        state->rest = Rest;
2394
2395                        /* external loop filter, otherwise:
2396                         * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2397                         * lo6 = 0x0e34 */
2398
2399                        if (Rest == 0) {
2400                                if (pll->vco_band)
2401                                        lo5 = 0x049f;
2402                                else
2403                                        lo5 = 0x041f;
2404                        } else {
2405                                if (pll->vco_band)
2406                                        lo5 = 0x049e;
2407                                else if (state->config->analog_output)
2408                                        lo5 = 0x041d;
2409                                else
2410                                        lo5 = 0x041c;
2411                        }
2412
2413                        if (state->identity.p1g) {      /* Bias is done automatically in P1G */
2414                                if (state->identity.in_soc) {
2415                                        if (state->identity.version == SOC_8090_P1G_11R1)
2416                                                lo5 = 0x46f;
2417                                        else
2418                                                lo5 = 0x42f;
2419                                } else
2420                                        lo5 = 0x42c;
2421                        }
2422
2423                        lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);  /* bit 15 is the split to the slave, we do not do it here */
2424
2425                        if (!state->config->io.pll_int_loop_filt) {
2426                                if (state->identity.in_soc)
2427                                        lo6 = 0xff98;
2428                                else if (state->identity.p1g || (Rest == 0))
2429                                        lo6 = 0xfff8;
2430                                else
2431                                        lo6 = 0xff28;
2432                        } else
2433                                lo6 = (state->config->io.pll_int_loop_filt << 3);
2434
2435                        Den = 1;
2436
2437                        if (Rest > 0) {
2438                                lo6 |= (1 << 2) | 2;
2439                                Den = 255;
2440                        }
2441                        dib0090_write_reg(state, 0x15, (u16) FBDiv);
2442                        if (state->config->fref_clock_ratio != 0)
2443                                dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2444                        else
2445                                dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2446                        dib0090_write_reg(state, 0x17, (u16) Rest);
2447                        dib0090_write_reg(state, 0x19, lo5);
2448                        dib0090_write_reg(state, 0x1c, lo6);
2449
2450                        lo6 = tune->tuner_enable;
2451                        if (state->config->analog_output)
2452                                lo6 = (lo6 & 0xff9f) | 0x2;
2453
2454                        dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2455
2456                }
2457
2458                state->current_rf = state->rf_request;
2459                state->current_standard = state->fe->dtv_property_cache.delivery_system;
2460
2461                ret = 20;
2462                state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2463        }
2464
2465        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 */
2466                const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2467
2468                while (state->current_rf / 1000 > wbd->max_freq)
2469                        wbd++;
2470
2471                dib0090_write_reg(state, 0x1e, 0x07ff);
2472                dprintk("Final Captrim: %d\n", (u32) state->fcaptrim);
2473                dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code);
2474                dprintk("VCO = %d\n", (u32) pll->vco_band);
2475                dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2476                dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz);
2477                dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2478                dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2479                        (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2480
2481#define WBD     0x781           /* 1 1 1 1 0000 0 0 1 */
2482                c = 4;
2483                i = 3;
2484
2485                if (wbd->wbd_gain != 0)
2486                        c = wbd->wbd_gain;
2487
2488                state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2489                dib0090_write_reg(state, 0x10, state->wbdmux);
2490
2491                if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2492                        dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune);
2493                        dib0090_write_reg(state, 0x09, tune->lna_bias);
2494                        dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2495                } else
2496                        dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2497
2498                dib0090_write_reg(state, 0x0c, tune->v2i);
2499                dib0090_write_reg(state, 0x0d, tune->mix);
2500                dib0090_write_reg(state, 0x0e, tune->load);
2501                *tune_state = CT_TUNER_STEP_1;
2502
2503        } else if (*tune_state == CT_TUNER_STEP_1) {
2504                /* initialize the lt gain register */
2505                state->rf_lt_def = 0x7c00;
2506
2507                dib0090_set_bandwidth(state);
2508                state->tuner_is_tuned = 1;
2509
2510                state->calibrate |= WBD_CAL;
2511                state->calibrate |= TEMP_CAL;
2512                *tune_state = CT_TUNER_STOP;
2513        } else
2514                ret = FE_CALLBACK_TIME_NEVER;
2515        return ret;
2516}
2517
2518static void dib0090_release(struct dvb_frontend *fe)
2519{
2520        kfree(fe->tuner_priv);
2521        fe->tuner_priv = NULL;
2522}
2523
2524enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2525{
2526        struct dib0090_state *state = fe->tuner_priv;
2527
2528        return state->tune_state;
2529}
2530
2531EXPORT_SYMBOL(dib0090_get_tune_state);
2532
2533int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2534{
2535        struct dib0090_state *state = fe->tuner_priv;
2536
2537        state->tune_state = tune_state;
2538        return 0;
2539}
2540
2541EXPORT_SYMBOL(dib0090_set_tune_state);
2542
2543static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2544{
2545        struct dib0090_state *state = fe->tuner_priv;
2546
2547        *frequency = 1000 * state->current_rf;
2548        return 0;
2549}
2550
2551static int dib0090_set_params(struct dvb_frontend *fe)
2552{
2553        struct dib0090_state *state = fe->tuner_priv;
2554        u32 ret;
2555
2556        state->tune_state = CT_TUNER_START;
2557
2558        do {
2559                ret = dib0090_tune(fe);
2560                if (ret == FE_CALLBACK_TIME_NEVER)
2561                        break;
2562
2563                /*
2564                 * Despite dib0090_tune returns time at a 0.1 ms range,
2565                 * the actual sleep time depends on CONFIG_HZ. The worse case
2566                 * is when CONFIG_HZ=100. In such case, the minimum granularity
2567                 * is 10ms. On some real field tests, the tuner sometimes don't
2568                 * lock when this timer is lower than 10ms. So, enforce a 10ms
2569                 * granularity and use usleep_range() instead of msleep().
2570                 */
2571                ret = 10 * (ret + 99)/100;
2572                usleep_range(ret * 1000, (ret + 1) * 1000);
2573        } while (state->tune_state != CT_TUNER_STOP);
2574
2575        return 0;
2576}
2577
2578static const struct dvb_tuner_ops dib0090_ops = {
2579        .info = {
2580                 .name = "DiBcom DiB0090",
2581                 .frequency_min = 45000000,
2582                 .frequency_max = 860000000,
2583                 .frequency_step = 1000,
2584                 },
2585        .release = dib0090_release,
2586
2587        .init = dib0090_wakeup,
2588        .sleep = dib0090_sleep,
2589        .set_params = dib0090_set_params,
2590        .get_frequency = dib0090_get_frequency,
2591};
2592
2593static const struct dvb_tuner_ops dib0090_fw_ops = {
2594        .info = {
2595                 .name = "DiBcom DiB0090",
2596                 .frequency_min = 45000000,
2597                 .frequency_max = 860000000,
2598                 .frequency_step = 1000,
2599                 },
2600        .release = dib0090_release,
2601
2602        .init = NULL,
2603        .sleep = NULL,
2604        .set_params = NULL,
2605        .get_frequency = NULL,
2606};
2607
2608static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2609        {470, 0, 250, 0, 100, 4},
2610        {860, 51, 866, 21, 375, 4},
2611        {1700, 0, 800, 0, 850, 4},
2612        {2900, 0, 250, 0, 100, 6},
2613        {0xFFFF, 0, 0, 0, 0, 0},
2614};
2615
2616struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2617{
2618        struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2619        if (st == NULL)
2620                return NULL;
2621
2622        st->config = config;
2623        st->i2c = i2c;
2624        st->fe = fe;
2625        mutex_init(&st->i2c_buffer_lock);
2626        fe->tuner_priv = st;
2627
2628        if (config->wbd == NULL)
2629                st->current_wbd_table = dib0090_wbd_table_default;
2630        else
2631                st->current_wbd_table = config->wbd;
2632
2633        if (dib0090_reset(fe) != 0)
2634                goto free_mem;
2635
2636        pr_info("DiB0090: successfully identified\n");
2637        memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2638
2639        return fe;
2640 free_mem:
2641        kfree(st);
2642        fe->tuner_priv = NULL;
2643        return NULL;
2644}
2645
2646EXPORT_SYMBOL(dib0090_register);
2647
2648struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2649{
2650        struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2651        if (st == NULL)
2652                return NULL;
2653
2654        st->config = config;
2655        st->i2c = i2c;
2656        st->fe = fe;
2657        mutex_init(&st->i2c_buffer_lock);
2658        fe->tuner_priv = st;
2659
2660        if (dib0090_fw_reset_digital(fe, st->config) != 0)
2661                goto free_mem;
2662
2663        dprintk("DiB0090 FW: successfully identified\n");
2664        memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2665
2666        return fe;
2667free_mem:
2668        kfree(st);
2669        fe->tuner_priv = NULL;
2670        return NULL;
2671}
2672EXPORT_SYMBOL(dib0090_fw_register);
2673
2674MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
2675MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
2676MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2677MODULE_LICENSE("GPL");
2678