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