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