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