Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / media / dvb-frontends / dib0070.c
blob932d235118e2c575010017a151a8235694c5a3c3
1 /*
2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
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.
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
15 * GNU General Public License for more details.
18 * This code is more or less generated from another driver, please
19 * excuse some codingstyle oddities.
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include <linux/mutex.h>
30 #include <media/dvb_frontend.h>
32 #include "dib0070.h"
33 #include "dibx000_common.h"
35 static int debug;
36 module_param(debug, int, 0644);
37 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
39 #define dprintk(fmt, arg...) do { \
40 if (debug) \
41 printk(KERN_DEBUG pr_fmt("%s: " fmt), \
42 __func__, ##arg); \
43 } while (0)
45 #define DIB0070_P1D 0x00
46 #define DIB0070_P1F 0x01
47 #define DIB0070_P1G 0x03
48 #define DIB0070S_P1A 0x02
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;
57 enum frontend_tune_state tune_state;
58 u32 current_rf;
60 /* for the captrim binary search */
61 s8 step;
62 u16 adc_diff;
64 s8 captrim;
65 s8 fcaptrim;
66 u16 lo4;
68 const struct dib0070_tuning *current_tune_table_index;
69 const struct dib0070_lna_match *lna_match;
71 u8 wbd_gain_current;
72 u16 wbd_offset_3_3[2];
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;
81 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
83 u16 ret;
85 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
86 dprintk("could not acquire lock\n");
87 return 0;
90 state->i2c_write_buffer[0] = reg;
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;
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];
109 mutex_unlock(&state->i2c_buffer_lock);
110 return ret;
113 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
115 int ret;
117 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
118 dprintk("could not acquire lock\n");
119 return -EINVAL;
121 state->i2c_write_buffer[0] = reg;
122 state->i2c_write_buffer[1] = val >> 8;
123 state->i2c_write_buffer[2] = val & 0xff;
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;
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;
137 mutex_unlock(&state->i2c_buffer_lock);
138 return ret;
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); \
147 } while (0)
149 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
151 struct dib0070_state *state = fe->tuner_priv;
152 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
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);
163 dib0070_write_reg(state, 0x02, tmp);
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);
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));
173 dib0070_write_reg(state, 0x17, value);
175 return 0;
178 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
180 int8_t step_sign;
181 u16 adc;
182 int ret = 0;
184 if (*tune_state == CT_TUNER_STEP_0) {
185 dib0070_write_reg(state, 0x0f, 0xed10);
186 dib0070_write_reg(state, 0x17, 0x0034);
188 dib0070_write_reg(state, 0x18, 0x0032);
189 state->step = state->captrim = state->fcaptrim = 64;
190 state->adc_diff = 3000;
191 ret = 20;
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;
199 *tune_state = CT_TUNER_STEP_2;
200 } else if (*tune_state == CT_TUNER_STEP_2) {
202 adc = dib0070_read_reg(state, 0x19);
204 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV\n", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
206 if (adc >= 400) {
207 adc -= 400;
208 step_sign = -1;
209 } else {
210 adc = 400 - adc;
211 step_sign = 1;
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;
219 state->captrim += (step_sign * state->step);
221 if (state->step >= 1)
222 *tune_state = CT_TUNER_STEP_1;
223 else
224 *tune_state = CT_TUNER_STEP_3;
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;
232 return ret;
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)
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);
240 dprintk("CTRL_LO5: 0x%x\n", lo5);
241 return dib0070_write_reg(state, 0x15, lo5);
244 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
246 struct dib0070_state *state = fe->tuner_priv;
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);
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;
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;
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 */
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 */
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 },
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 },
330 #define LPF 100
331 static int dib0070_tune_digital(struct dvb_frontend *fe)
333 struct dib0070_state *state = fe->tuner_priv;
335 const struct dib0070_tuning *tune;
336 const struct dib0070_lna_match *lna_match;
338 enum frontend_tune_state *tune_state = &state->tune_state;
339 int ret = 10; /* 1ms is the default delay most of the time */
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);
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) {
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;
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++;
374 state->current_tune_table_index = tune;
375 state->lna_match = lna_match;
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;
385 state->current_rf = freq;
386 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
389 dib0070_write_reg(state, 0x17, 0x30);
392 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
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;
405 FREF = state->cfg->clock_khz / REFDIV;
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;
415 case DIB0070_P1G:
416 case DIB0070_P1F:
417 default:
418 FBDiv = (freq / (FREF / 2));
419 Rest = 2 * freq - FBDiv * FREF;
420 break;
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);
434 Den = 1;
435 if (Rest > 0) {
436 state->lo4 |= (1 << 14) | (1 << 12);
437 Den = 255;
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);
445 if (state->revision == DIB0070S_P1A) {
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);
454 dib0070_write_reg(state, 0x20,
455 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
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);
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;
469 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
471 ret = dib0070_captrim(state, tune_state);
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;
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);
498 dib0070_write_reg(state, 0x18, 0x07ff);
499 dib0070_write_reg(state, 0x17, 0x0033);
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 */
509 return ret;
513 static int dib0070_tune(struct dvb_frontend *fe)
515 struct dib0070_state *state = fe->tuner_priv;
516 uint32_t ret;
518 state->tune_state = CT_TUNER_START;
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);
528 return 0;
531 static int dib0070_wakeup(struct dvb_frontend *fe)
533 struct dib0070_state *state = fe->tuner_priv;
534 if (state->cfg->sleep)
535 state->cfg->sleep(fe, 0);
536 return 0;
539 static int dib0070_sleep(struct dvb_frontend *fe)
541 struct dib0070_state *state = fe->tuner_priv;
542 if (state->cfg->sleep)
543 state->cfg->sleep(fe, 1);
544 return 0;
547 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
549 struct dib0070_state *state = fe->tuner_priv;
550 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
552 EXPORT_SYMBOL(dib0070_get_rf_output);
554 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
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));
564 EXPORT_SYMBOL(dib0070_set_rf_output);
566 static const u16 dib0070_p1f_defaults[] =
569 7, 0x02,
570 0x0008,
571 0x0000,
572 0x0000,
573 0x0000,
574 0x0000,
575 0x0002,
576 0x0100,
578 3, 0x0d,
579 0x0d80,
580 0x0001,
581 0x0000,
583 4, 0x11,
584 0x0000,
585 0x0103,
586 0x0000,
587 0x0000,
589 3, 0x16,
590 0x0004 | 0x0040,
591 0x0030,
592 0x07ff,
594 6, 0x1b,
595 0x4112,
596 0xff00,
597 0xc07f,
598 0x0000,
599 0x0180,
600 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
605 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
607 u16 tuner_en = dib0070_read_reg(state, 0x20);
608 u16 offset;
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;
619 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
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]);
628 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
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;
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;
641 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
643 EXPORT_SYMBOL(dib0070_wbd_offset);
645 #define pgm_read_word(w) (*w)
646 static int dib0070_reset(struct dvb_frontend *fe)
648 struct dib0070_state *state = fe->tuner_priv;
649 u16 l, r, *n;
651 HARD_RESET(state);
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;
663 /* P1F or not */
664 dprintk("Revision: %x\n", state->revision);
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;
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++);
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;
690 r |= state->cfg->osc_buffer_state << 3;
692 dib0070_write_reg(state, 0x10, r);
693 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
695 if (state->cfg->invert_iq) {
696 r = dib0070_read_reg(state, 0x02) & 0xffdf;
697 dib0070_write_reg(state, 0x02, r | (1 << 5));
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);
706 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
708 dib0070_wbd_offset_calibration(state);
710 return 0;
713 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
715 struct dib0070_state *state = fe->tuner_priv;
717 *frequency = 1000 * state->current_rf;
718 return 0;
721 static void dib0070_release(struct dvb_frontend *fe)
723 kfree(fe->tuner_priv);
724 fe->tuner_priv = NULL;
727 static const struct dvb_tuner_ops dib0070_ops = {
728 .info = {
729 .name = "DiBcom DiB0070",
730 .frequency_min = 45000000,
731 .frequency_max = 860000000,
732 .frequency_step = 1000,
734 .release = dib0070_release,
736 .init = dib0070_wakeup,
737 .sleep = dib0070_sleep,
738 .set_params = dib0070_tune,
740 .get_frequency = dib0070_get_frequency,
741 // .get_bandwidth = dib0070_get_bandwidth
744 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
746 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
747 if (state == NULL)
748 return NULL;
750 state->cfg = cfg;
751 state->i2c = i2c;
752 state->fe = fe;
753 mutex_init(&state->i2c_buffer_lock);
754 fe->tuner_priv = state;
756 if (dib0070_reset(fe) != 0)
757 goto free_mem;
759 pr_info("DiB0070: successfully identified\n");
760 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
762 fe->tuner_priv = state;
763 return fe;
765 free_mem:
766 kfree(state);
767 fe->tuner_priv = NULL;
768 return NULL;
770 EXPORT_SYMBOL(dib0070_attach);
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");