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