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