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