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"); 763