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