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