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