linux/drivers/media/dvb-frontends/dib0070.c
<<
>>
Prefs
   1/*
   2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
   3 *
   4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of the
   9 * License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *
  15 * GNU General Public License for more details.
  16 *
  17 *
  18 * This code is more or less generated from another driver, please
  19 * excuse some codingstyle oddities.
  20 *
  21 */
  22
  23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  24
  25#include <linux/kernel.h>
  26#include <linux/slab.h>
  27#include <linux/i2c.h>
  28#include <linux/mutex.h>
  29
  30#include <media/dvb_frontend.h>
  31
  32#include "dib0070.h"
  33#include "dibx000_common.h"
  34
  35static int debug;
  36module_param(debug, int, 0644);
  37MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
  38
  39#define dprintk(fmt, arg...) do {                                       \
  40        if (debug)                                                      \
  41                printk(KERN_DEBUG pr_fmt("%s: " fmt),                   \
  42                       __func__, ##arg);                                \
  43} while (0)
  44
  45#define DIB0070_P1D  0x00
  46#define DIB0070_P1F  0x01
  47#define DIB0070_P1G  0x03
  48#define DIB0070S_P1A 0x02
  49
  50struct dib0070_state {
  51        struct i2c_adapter *i2c;
  52        struct dvb_frontend *fe;
  53        const struct dib0070_config *cfg;
  54        u16 wbd_ff_offset;
  55        u8 revision;
  56
  57        enum frontend_tune_state tune_state;
  58        u32 current_rf;
  59
  60        /* for the captrim binary search */
  61        s8 step;
  62        u16 adc_diff;
  63
  64        s8 captrim;
  65        s8 fcaptrim;
  66        u16 lo4;
  67
  68        const struct dib0070_tuning *current_tune_table_index;
  69        const struct dib0070_lna_match *lna_match;
  70
  71        u8  wbd_gain_current;
  72        u16 wbd_offset_3_3[2];
  73
  74        /* for the I2C transfer */
  75        struct i2c_msg msg[2];
  76        u8 i2c_write_buffer[3];
  77        u8 i2c_read_buffer[2];
  78        struct mutex i2c_buffer_lock;
  79};
  80
  81static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
  82{
  83        u16 ret;
  84
  85        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
  86                dprintk("could not acquire lock\n");
  87                return 0;
  88        }
  89
  90        state->i2c_write_buffer[0] = reg;
  91
  92        memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
  93        state->msg[0].addr = state->cfg->i2c_address;
  94        state->msg[0].flags = 0;
  95        state->msg[0].buf = state->i2c_write_buffer;
  96        state->msg[0].len = 1;
  97        state->msg[1].addr = state->cfg->i2c_address;
  98        state->msg[1].flags = I2C_M_RD;
  99        state->msg[1].buf = state->i2c_read_buffer;
 100        state->msg[1].len = 2;
 101
 102        if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 103                pr_warn("DiB0070 I2C read failed\n");
 104                ret = 0;
 105        } else
 106                ret = (state->i2c_read_buffer[0] << 8)
 107                        | state->i2c_read_buffer[1];
 108
 109        mutex_unlock(&state->i2c_buffer_lock);
 110        return ret;
 111}
 112
 113static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
 114{
 115        int ret;
 116
 117        if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
 118                dprintk("could not acquire lock\n");
 119                return -EINVAL;
 120        }
 121        state->i2c_write_buffer[0] = reg;
 122        state->i2c_write_buffer[1] = val >> 8;
 123        state->i2c_write_buffer[2] = val & 0xff;
 124
 125        memset(state->msg, 0, sizeof(struct i2c_msg));
 126        state->msg[0].addr = state->cfg->i2c_address;
 127        state->msg[0].flags = 0;
 128        state->msg[0].buf = state->i2c_write_buffer;
 129        state->msg[0].len = 3;
 130
 131        if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 132                pr_warn("DiB0070 I2C write failed\n");
 133                ret = -EREMOTEIO;
 134        } else
 135                ret = 0;
 136
 137        mutex_unlock(&state->i2c_buffer_lock);
 138        return ret;
 139}
 140
 141#define HARD_RESET(state) do { \
 142    state->cfg->sleep(state->fe, 0); \
 143    if (state->cfg->reset) { \
 144        state->cfg->reset(state->fe,1); msleep(10); \
 145        state->cfg->reset(state->fe,0); msleep(10); \
 146    } \
 147} while (0)
 148
 149static int dib0070_set_bandwidth(struct dvb_frontend *fe)
 150        {
 151        struct dib0070_state *state = fe->tuner_priv;
 152        u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
 153
 154        if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
 155                tmp |= (0 << 14);
 156        else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
 157                tmp |= (1 << 14);
 158        else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
 159                tmp |= (2 << 14);
 160        else
 161                tmp |= (3 << 14);
 162
 163        dib0070_write_reg(state, 0x02, tmp);
 164
 165        /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
 166        if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
 167                u16 value = dib0070_read_reg(state, 0x17);
 168
 169                dib0070_write_reg(state, 0x17, value & 0xfffc);
 170                tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
 171                dib0070_write_reg(state, 0x01, tmp | (60 << 9));
 172
 173                dib0070_write_reg(state, 0x17, value);
 174        }
 175        return 0;
 176}
 177
 178static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
 179{
 180        int8_t step_sign;
 181        u16 adc;
 182        int ret = 0;
 183
 184        if (*tune_state == CT_TUNER_STEP_0) {
 185                dib0070_write_reg(state, 0x0f, 0xed10);
 186                dib0070_write_reg(state, 0x17,    0x0034);
 187
 188                dib0070_write_reg(state, 0x18, 0x0032);
 189                state->step = state->captrim = state->fcaptrim = 64;
 190                state->adc_diff = 3000;
 191                ret = 20;
 192
 193                *tune_state = CT_TUNER_STEP_1;
 194        } else if (*tune_state == CT_TUNER_STEP_1) {
 195                state->step /= 2;
 196                dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
 197                ret = 15;
 198
 199                *tune_state = CT_TUNER_STEP_2;
 200        } else if (*tune_state == CT_TUNER_STEP_2) {
 201
 202                adc = dib0070_read_reg(state, 0x19);
 203
 204                dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV\n", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
 205
 206                if (adc >= 400) {
 207                        adc -= 400;
 208                        step_sign = -1;
 209                } else {
 210                        adc = 400 - adc;
 211                        step_sign = 1;
 212                }
 213
 214                if (adc < state->adc_diff) {
 215                        dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)\n", state->captrim, adc, state->adc_diff);
 216                        state->adc_diff = adc;
 217                        state->fcaptrim = state->captrim;
 218                }
 219                state->captrim += (step_sign * state->step);
 220
 221                if (state->step >= 1)
 222                        *tune_state = CT_TUNER_STEP_1;
 223                else
 224                        *tune_state = CT_TUNER_STEP_3;
 225
 226        } else if (*tune_state == CT_TUNER_STEP_3) {
 227                dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
 228                dib0070_write_reg(state, 0x18, 0x07ff);
 229                *tune_state = CT_TUNER_STEP_4;
 230        }
 231
 232        return ret;
 233}
 234
 235static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
 236{
 237        struct dib0070_state *state = fe->tuner_priv;
 238        u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
 239
 240        dprintk("CTRL_LO5: 0x%x\n", lo5);
 241        return dib0070_write_reg(state, 0x15, lo5);
 242}
 243
 244void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
 245{
 246        struct dib0070_state *state = fe->tuner_priv;
 247
 248        if (open) {
 249                dib0070_write_reg(state, 0x1b, 0xff00);
 250                dib0070_write_reg(state, 0x1a, 0x0000);
 251        } else {
 252                dib0070_write_reg(state, 0x1b, 0x4112);
 253                if (state->cfg->vga_filter != 0) {
 254                        dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
 255                        dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
 256                } else
 257                        dib0070_write_reg(state, 0x1a, 0x0009);
 258        }
 259}
 260
 261EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
 262struct dib0070_tuning {
 263        u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
 264        u8 switch_trim;
 265        u8 vco_band;
 266        u8 hfdiv;
 267        u8 vco_multi;
 268        u8 presc;
 269        u8 wbdmux;
 270        u16 tuner_enable;
 271};
 272
 273struct dib0070_lna_match {
 274        u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
 275        u8 lna_band;
 276};
 277
 278static const struct dib0070_tuning dib0070s_tuning_table[] = {
 279        {     570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
 280        {     700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
 281        {     863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
 282        {    1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
 283        {    1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
 284        {    2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
 285        { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
 286};
 287
 288static const struct dib0070_tuning dib0070_tuning_table[] = {
 289        {     115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
 290        {     179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
 291        {     189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
 292        {     250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
 293        {     569999, 2, 1, 5,  6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
 294        {     699999, 2, 0, 1,  4, 2, 2, 0x4000 | 0x0800 },
 295        {     863999, 2, 1, 1,  4, 2, 2, 0x4000 | 0x0800 },
 296        { 0xffffffff, 0, 1, 0,  2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
 297};
 298
 299static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
 300        {     180000, 0 }, /* VHF */
 301        {     188000, 1 },
 302        {     196400, 2 },
 303        {     250000, 3 },
 304        {     550000, 0 }, /* UHF */
 305        {     590000, 1 },
 306        {     666000, 3 },
 307        {     864000, 5 },
 308        {    1500000, 0 }, /* LBAND or everything higher than UHF */
 309        {    1600000, 1 },
 310        {    2000000, 3 },
 311        { 0xffffffff, 7 },
 312};
 313
 314static const struct dib0070_lna_match dib0070_lna[] = {
 315        {     180000, 0 }, /* VHF */
 316        {     188000, 1 },
 317        {     196400, 2 },
 318        {     250000, 3 },
 319        {     550000, 2 }, /* UHF */
 320        {     650000, 3 },
 321        {     750000, 5 },
 322        {     850000, 6 },
 323        {     864000, 7 },
 324        {    1500000, 0 }, /* LBAND or everything higher than UHF */
 325        {    1600000, 1 },
 326        {    2000000, 3 },
 327        { 0xffffffff, 7 },
 328};
 329
 330#define LPF     100
 331static int dib0070_tune_digital(struct dvb_frontend *fe)
 332{
 333        struct dib0070_state *state = fe->tuner_priv;
 334
 335        const struct dib0070_tuning *tune;
 336        const struct dib0070_lna_match *lna_match;
 337
 338        enum frontend_tune_state *tune_state = &state->tune_state;
 339        int ret = 10; /* 1ms is the default delay most of the time */
 340
 341        u8  band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
 342        u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
 343
 344#ifdef CONFIG_SYS_ISDBT
 345        if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
 346                        if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
 347                        && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
 348                        || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
 349                                && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
 350                        || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
 351                                && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
 352                                freq += 850;
 353#endif
 354        if (state->current_rf != freq) {
 355
 356                switch (state->revision) {
 357                case DIB0070S_P1A:
 358                tune = dib0070s_tuning_table;
 359                lna_match = dib0070_lna;
 360                break;
 361                default:
 362                tune = dib0070_tuning_table;
 363                if (state->cfg->flip_chip)
 364                        lna_match = dib0070_lna_flip_chip;
 365                else
 366                        lna_match = dib0070_lna;
 367                break;
 368                }
 369                while (freq > tune->max_freq) /* find the right one */
 370                        tune++;
 371                while (freq > lna_match->max_freq) /* find the right one */
 372                        lna_match++;
 373
 374                state->current_tune_table_index = tune;
 375                state->lna_match = lna_match;
 376        }
 377
 378        if (*tune_state == CT_TUNER_START) {
 379                dprintk("Tuning for Band: %hd (%d kHz)\n", band, freq);
 380                if (state->current_rf != freq) {
 381                        u8 REFDIV;
 382                        u32 FBDiv, Rest, FREF, VCOF_kHz;
 383                        u8 Den;
 384
 385                        state->current_rf = freq;
 386                        state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
 387
 388
 389                        dib0070_write_reg(state, 0x17, 0x30);
 390
 391
 392                        VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
 393
 394                        switch (band) {
 395                        case BAND_VHF:
 396                                REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
 397                                break;
 398                        case BAND_FM:
 399                                REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
 400                                break;
 401                        default:
 402                                REFDIV = (u8) (state->cfg->clock_khz  / 10000);
 403                                break;
 404                        }
 405                        FREF = state->cfg->clock_khz / REFDIV;
 406
 407
 408
 409                        switch (state->revision) {
 410                        case DIB0070S_P1A:
 411                                FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
 412                                Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
 413                                break;
 414
 415                        case DIB0070_P1G:
 416                        case DIB0070_P1F:
 417                        default:
 418                                FBDiv = (freq / (FREF / 2));
 419                                Rest  = 2 * freq - FBDiv * FREF;
 420                                break;
 421                        }
 422
 423                        if (Rest < LPF)
 424                                Rest = 0;
 425                        else if (Rest < 2 * LPF)
 426                                Rest = 2 * LPF;
 427                        else if (Rest > (FREF - LPF)) {
 428                                Rest = 0;
 429                                FBDiv += 1;
 430                        } else if (Rest > (FREF - 2 * LPF))
 431                                Rest = FREF - 2 * LPF;
 432                        Rest = (Rest * 6528) / (FREF / 10);
 433
 434                        Den = 1;
 435                        if (Rest > 0) {
 436                                state->lo4 |= (1 << 14) | (1 << 12);
 437                                Den = 255;
 438                        }
 439
 440
 441                        dib0070_write_reg(state, 0x11, (u16)FBDiv);
 442                        dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
 443                        dib0070_write_reg(state, 0x13, (u16) Rest);
 444
 445                        if (state->revision == DIB0070S_P1A) {
 446
 447                                if (band == BAND_SBAND) {
 448                                        dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
 449                                        dib0070_write_reg(state, 0x1d, 0xFFFF);
 450                                } else
 451                                        dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
 452                        }
 453
 454                        dib0070_write_reg(state, 0x20,
 455                                0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
 456
 457                        dprintk("REFDIV: %hd, FREF: %d\n", REFDIV, FREF);
 458                        dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
 459                        dprintk("Num: %hd, Den: %hd, SD: %hd\n", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
 460                        dprintk("HFDIV code: %hd\n", state->current_tune_table_index->hfdiv);
 461                        dprintk("VCO = %hd\n", state->current_tune_table_index->vco_band);
 462                        dprintk("VCOF: ((%hd*%d) << 1))\n", state->current_tune_table_index->vco_multi, freq);
 463
 464                        *tune_state = CT_TUNER_STEP_0;
 465                } else { /* we are already tuned to this frequency - the configuration is correct  */
 466                        ret = 50; /* wakeup time */
 467                        *tune_state = CT_TUNER_STEP_5;
 468                }
 469        } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
 470
 471                ret = dib0070_captrim(state, tune_state);
 472
 473        } else if (*tune_state == CT_TUNER_STEP_4) {
 474                const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
 475                if (tmp != NULL) {
 476                        while (freq/1000 > tmp->freq) /* find the right one */
 477                                tmp++;
 478                        dib0070_write_reg(state, 0x0f,
 479                                (0 << 15) | (1 << 14) | (3 << 12)
 480                                | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
 481                                | (state->current_tune_table_index->wbdmux << 0));
 482                        state->wbd_gain_current = tmp->wbd_gain_val;
 483                } else {
 484                        dib0070_write_reg(state, 0x0f,
 485                                          (0 << 15) | (1 << 14) | (3 << 12)
 486                                          | (6 << 9) | (0 << 8) | (1 << 7)
 487                                          | (state->current_tune_table_index->wbdmux << 0));
 488                        state->wbd_gain_current = 6;
 489                }
 490
 491                dib0070_write_reg(state, 0x06, 0x3fff);
 492                dib0070_write_reg(state, 0x07,
 493                                  (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
 494                dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
 495                dib0070_write_reg(state, 0x0d, 0x0d80);
 496
 497
 498                dib0070_write_reg(state, 0x18,   0x07ff);
 499                dib0070_write_reg(state, 0x17, 0x0033);
 500
 501
 502                *tune_state = CT_TUNER_STEP_5;
 503        } else if (*tune_state == CT_TUNER_STEP_5) {
 504                dib0070_set_bandwidth(fe);
 505                *tune_state = CT_TUNER_STOP;
 506        } else {
 507                ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
 508        }
 509        return ret;
 510}
 511
 512
 513static int dib0070_tune(struct dvb_frontend *fe)
 514{
 515        struct dib0070_state *state = fe->tuner_priv;
 516        uint32_t ret;
 517
 518        state->tune_state = CT_TUNER_START;
 519
 520        do {
 521                ret = dib0070_tune_digital(fe);
 522                if (ret != FE_CALLBACK_TIME_NEVER)
 523                        msleep(ret/10);
 524                else
 525                break;
 526        } while (state->tune_state != CT_TUNER_STOP);
 527
 528        return 0;
 529}
 530
 531static int dib0070_wakeup(struct dvb_frontend *fe)
 532{
 533        struct dib0070_state *state = fe->tuner_priv;
 534        if (state->cfg->sleep)
 535                state->cfg->sleep(fe, 0);
 536        return 0;
 537}
 538
 539static int dib0070_sleep(struct dvb_frontend *fe)
 540{
 541        struct dib0070_state *state = fe->tuner_priv;
 542        if (state->cfg->sleep)
 543                state->cfg->sleep(fe, 1);
 544        return 0;
 545}
 546
 547u8 dib0070_get_rf_output(struct dvb_frontend *fe)
 548{
 549        struct dib0070_state *state = fe->tuner_priv;
 550        return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
 551}
 552EXPORT_SYMBOL(dib0070_get_rf_output);
 553
 554int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
 555{
 556        struct dib0070_state *state = fe->tuner_priv;
 557        u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
 558        if (no > 3)
 559                no = 3;
 560        if (no < 1)
 561                no = 1;
 562        return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
 563}
 564EXPORT_SYMBOL(dib0070_set_rf_output);
 565
 566static const u16 dib0070_p1f_defaults[] =
 567
 568{
 569        7, 0x02,
 570                0x0008,
 571                0x0000,
 572                0x0000,
 573                0x0000,
 574                0x0000,
 575                0x0002,
 576                0x0100,
 577
 578        3, 0x0d,
 579                0x0d80,
 580                0x0001,
 581                0x0000,
 582
 583        4, 0x11,
 584                0x0000,
 585                0x0103,
 586                0x0000,
 587                0x0000,
 588
 589        3, 0x16,
 590                0x0004 | 0x0040,
 591                0x0030,
 592                0x07ff,
 593
 594        6, 0x1b,
 595                0x4112,
 596                0xff00,
 597                0xc07f,
 598                0x0000,
 599                0x0180,
 600                0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
 601
 602        0,
 603};
 604
 605static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
 606{
 607        u16 tuner_en = dib0070_read_reg(state, 0x20);
 608        u16 offset;
 609
 610        dib0070_write_reg(state, 0x18, 0x07ff);
 611        dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
 612        dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
 613        msleep(9);
 614        offset = dib0070_read_reg(state, 0x19);
 615        dib0070_write_reg(state, 0x20, tuner_en);
 616        return offset;
 617}
 618
 619static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
 620{
 621        u8 gain;
 622        for (gain = 6; gain < 8; gain++) {
 623                state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
 624                dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
 625        }
 626}
 627
 628u16 dib0070_wbd_offset(struct dvb_frontend *fe)
 629{
 630        struct dib0070_state *state = fe->tuner_priv;
 631        const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
 632        u32 freq = fe->dtv_property_cache.frequency/1000;
 633
 634        if (tmp != NULL) {
 635                while (freq/1000 > tmp->freq) /* find the right one */
 636                        tmp++;
 637                state->wbd_gain_current = tmp->wbd_gain_val;
 638        } else
 639                state->wbd_gain_current = 6;
 640
 641        return state->wbd_offset_3_3[state->wbd_gain_current - 6];
 642}
 643EXPORT_SYMBOL(dib0070_wbd_offset);
 644
 645#define pgm_read_word(w) (*w)
 646static int dib0070_reset(struct dvb_frontend *fe)
 647{
 648        struct dib0070_state *state = fe->tuner_priv;
 649        u16 l, r, *n;
 650
 651        HARD_RESET(state);
 652
 653
 654#ifndef FORCE_SBAND_TUNER
 655        if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
 656                state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
 657        else
 658#else
 659#warning forcing SBAND
 660#endif
 661        state->revision = DIB0070S_P1A;
 662
 663        /* P1F or not */
 664        dprintk("Revision: %x\n", state->revision);
 665
 666        if (state->revision == DIB0070_P1D) {
 667                dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
 668                return -EINVAL;
 669        }
 670
 671        n = (u16 *) dib0070_p1f_defaults;
 672        l = pgm_read_word(n++);
 673        while (l) {
 674                r = pgm_read_word(n++);
 675                do {
 676                        dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
 677                        r++;
 678                } while (--l);
 679                l = pgm_read_word(n++);
 680        }
 681
 682        if (state->cfg->force_crystal_mode != 0)
 683                r = state->cfg->force_crystal_mode;
 684        else if (state->cfg->clock_khz >= 24000)
 685                r = 1;
 686        else
 687                r = 2;
 688
 689
 690        r |= state->cfg->osc_buffer_state << 3;
 691
 692        dib0070_write_reg(state, 0x10, r);
 693        dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
 694
 695        if (state->cfg->invert_iq) {
 696                r = dib0070_read_reg(state, 0x02) & 0xffdf;
 697                dib0070_write_reg(state, 0x02, r | (1 << 5));
 698        }
 699
 700        if (state->revision == DIB0070S_P1A)
 701                dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
 702        else
 703                dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
 704                                     state->cfg->enable_third_order_filter);
 705
 706        dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
 707
 708        dib0070_wbd_offset_calibration(state);
 709
 710        return 0;
 711}
 712
 713static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 714{
 715        struct dib0070_state *state = fe->tuner_priv;
 716
 717        *frequency = 1000 * state->current_rf;
 718        return 0;
 719}
 720
 721static void dib0070_release(struct dvb_frontend *fe)
 722{
 723        kfree(fe->tuner_priv);
 724        fe->tuner_priv = NULL;
 725}
 726
 727static const struct dvb_tuner_ops dib0070_ops = {
 728        .info = {
 729                .name           = "DiBcom DiB0070",
 730                .frequency_min  =  45000000,
 731                .frequency_max  = 860000000,
 732                .frequency_step =      1000,
 733        },
 734        .release       = dib0070_release,
 735
 736        .init          = dib0070_wakeup,
 737        .sleep         = dib0070_sleep,
 738        .set_params    = dib0070_tune,
 739
 740        .get_frequency = dib0070_get_frequency,
 741//      .get_bandwidth = dib0070_get_bandwidth
 742};
 743
 744struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
 745{
 746        struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
 747        if (state == NULL)
 748                return NULL;
 749
 750        state->cfg = cfg;
 751        state->i2c = i2c;
 752        state->fe  = fe;
 753        mutex_init(&state->i2c_buffer_lock);
 754        fe->tuner_priv = state;
 755
 756        if (dib0070_reset(fe) != 0)
 757                goto free_mem;
 758
 759        pr_info("DiB0070: successfully identified\n");
 760        memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
 761
 762        fe->tuner_priv = state;
 763        return fe;
 764
 765free_mem:
 766        kfree(state);
 767        fe->tuner_priv = NULL;
 768        return NULL;
 769}
 770EXPORT_SYMBOL(dib0070_attach);
 771
 772MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
 773MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
 774MODULE_LICENSE("GPL");
 775