root/drivers/media/dvb-frontends/dib0070.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dib0070_read_reg
  2. dib0070_write_reg
  3. dib0070_set_bandwidth
  4. dib0070_captrim
  5. dib0070_set_ctrl_lo5
  6. dib0070_ctrl_agc_filter
  7. dib0070_tune_digital
  8. dib0070_tune
  9. dib0070_wakeup
  10. dib0070_sleep
  11. dib0070_get_rf_output
  12. dib0070_set_rf_output
  13. dib0070_read_wbd_offset
  14. dib0070_wbd_offset_calibration
  15. dib0070_wbd_offset
  16. dib0070_reset
  17. dib0070_get_frequency
  18. dib0070_release
  19. dib0070_attach

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

/* [<][>][^][v][top][bottom][index][help] */