This source file includes following definitions.
- dib0070_read_reg
- dib0070_write_reg
- dib0070_set_bandwidth
- dib0070_captrim
- dib0070_set_ctrl_lo5
- dib0070_ctrl_agc_filter
- dib0070_tune_digital
- dib0070_tune
- dib0070_wakeup
- dib0070_sleep
- dib0070_get_rf_output
- dib0070_set_rf_output
- dib0070_read_wbd_offset
- dib0070_wbd_offset_calibration
- dib0070_wbd_offset
- dib0070_reset
- dib0070_get_frequency
- dib0070_release
- dib0070_attach
1
2
3
4
5
6
7
8
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
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
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
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;
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;
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 },
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 },
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 },
274 };
275
276 static const struct dib0070_tuning dib0070_tuning_table[] = {
277 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 },
278 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 },
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 },
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 },
285 };
286
287 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
288 { 180000, 0 },
289 { 188000, 1 },
290 { 196400, 2 },
291 { 250000, 3 },
292 { 550000, 0 },
293 { 590000, 1 },
294 { 666000, 3 },
295 { 864000, 5 },
296 { 1500000, 0 },
297 { 1600000, 1 },
298 { 2000000, 3 },
299 { 0xffffffff, 7 },
300 };
301
302 static const struct dib0070_lna_match dib0070_lna[] = {
303 { 180000, 0 },
304 { 188000, 1 },
305 { 196400, 2 },
306 { 250000, 3 },
307 { 550000, 2 },
308 { 650000, 3 },
309 { 750000, 5 },
310 { 850000, 6 },
311 { 864000, 7 },
312 { 1500000, 0 },
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;
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)
358 tune++;
359 while (freq > lna_match->max_freq)
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 {
454 ret = 50;
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)
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;
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)
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
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
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");