Linux 2.6.34-rc3
[pohmelfs.git] / drivers / media / dvb / frontends / dib0070.c
blob0d12763603b47d7bdcb2f4f008fb1eff875f97ae
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.
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.
22 * This code is more or less generated from another driver, please
23 * excuse some codingstyle oddities.
27 #include <linux/kernel.h>
28 #include <linux/i2c.h>
30 #include "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(args...) do { \
40 if (debug) { \
41 printk(KERN_DEBUG "DiB0070: "); \
42 printk(args); \
43 printk("\n"); \
44 } \
45 } while (0)
47 #define DIB0070_P1D 0x00
48 #define DIB0070_P1F 0x01
49 #define DIB0070_P1G 0x03
50 #define DIB0070S_P1A 0x02
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;
59 enum frontend_tune_state tune_state;
60 u32 current_rf;
62 /* for the captrim binary search */
63 s8 step;
64 u16 adc_diff;
66 s8 captrim;
67 s8 fcaptrim;
68 u16 lo4;
70 const struct dib0070_tuning *current_tune_table_index;
71 const struct dib0070_lna_match *lna_match;
73 u8 wbd_gain_current;
74 u16 wbd_offset_3_3[2];
77 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
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 },
84 if (i2c_transfer(state->i2c, msg, 2) != 2) {
85 printk(KERN_WARNING "DiB0070 I2C read failed\n");
86 return 0;
88 return (b[0] << 8) | b[1];
91 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
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;
99 return 0;
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); \
108 } while (0)
110 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
112 struct dib0070_state *state = fe->tuner_priv;
113 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
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);
124 dib0070_write_reg(state, 0x02, tmp);
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);
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));
134 dib0070_write_reg(state, 0x17, value);
136 return 0;
139 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
141 int8_t step_sign;
142 u16 adc;
143 int ret = 0;
145 if (*tune_state == CT_TUNER_STEP_0) {
147 dib0070_write_reg(state, 0x0f, 0xed10);
148 dib0070_write_reg(state, 0x17, 0x0034);
150 dib0070_write_reg(state, 0x18, 0x0032);
151 state->step = state->captrim = state->fcaptrim = 64;
152 state->adc_diff = 3000;
153 ret = 20;
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;
161 *tune_state = CT_TUNER_STEP_2;
162 } else if (*tune_state == CT_TUNER_STEP_2) {
164 adc = dib0070_read_reg(state, 0x19);
166 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
168 if (adc >= 400) {
169 adc -= 400;
170 step_sign = -1;
171 } else {
172 adc = 400 - adc;
173 step_sign = 1;
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;
184 state->captrim += (step_sign * state->step);
186 if (state->step >= 1)
187 *tune_state = CT_TUNER_STEP_1;
188 else
189 *tune_state = CT_TUNER_STEP_3;
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;
197 return ret;
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)
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);
208 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
210 struct dib0070_state *state = fe->tuner_priv;
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);
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;
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;
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 */
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 */
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 },
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 },
294 #define LPF 100
295 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
297 struct dib0070_state *state = fe->tuner_priv;
299 const struct dib0070_tuning *tune;
300 const struct dib0070_lna_match *lna_match;
302 enum frontend_tune_state *tune_state = &state->tune_state;
303 int ret = 10; /* 1ms is the default delay most of the time */
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);
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) {
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;
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++;
338 state->current_tune_table_index = tune;
339 state->lna_match = lna_match;
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;
349 state->current_rf = freq;
350 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
353 dib0070_write_reg(state, 0x17, 0x30);
356 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
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;
369 FREF = state->cfg->clock_khz / REFDIV;
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;
379 case DIB0070_P1G:
380 case DIB0070_P1F:
381 default:
382 FBDiv = (freq / (FREF / 2));
383 Rest = 2 * freq - FBDiv * FREF;
384 break;
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);
398 Den = 1;
399 if (Rest > 0) {
400 state->lo4 |= (1 << 14) | (1 << 12);
401 Den = 255;
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);
409 if (state->revision == DIB0070S_P1A) {
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);
418 dib0070_write_reg(state, 0x20,
419 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
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);
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;
433 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
435 ret = dib0070_captrim(state, tune_state);
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)
444 | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
445 | (state->current_tune_table_index->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;
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);
461 dib0070_write_reg(state, 0x18, 0x07ff);
462 dib0070_write_reg(state, 0x17, 0x0033);
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 */
472 return ret;
476 static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
478 struct dib0070_state *state = fe->tuner_priv;
479 uint32_t ret;
481 state->tune_state = CT_TUNER_START;
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);
491 return 0;
494 static int dib0070_wakeup(struct dvb_frontend *fe)
496 struct dib0070_state *state = fe->tuner_priv;
497 if (state->cfg->sleep)
498 state->cfg->sleep(fe, 0);
499 return 0;
502 static int dib0070_sleep(struct dvb_frontend *fe)
504 struct dib0070_state *state = fe->tuner_priv;
505 if (state->cfg->sleep)
506 state->cfg->sleep(fe, 1);
507 return 0;
510 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
512 struct dib0070_state *state = fe->tuner_priv;
513 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
515 EXPORT_SYMBOL(dib0070_get_rf_output);
517 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
519 struct dib0070_state *state = fe->tuner_priv;
520 u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
521 if (no > 3)
522 no = 3;
523 if (no < 1)
524 no = 1;
525 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
527 EXPORT_SYMBOL(dib0070_set_rf_output);
529 static const u16 dib0070_p1f_defaults[] =
532 7, 0x02,
533 0x0008,
534 0x0000,
535 0x0000,
536 0x0000,
537 0x0000,
538 0x0002,
539 0x0100,
541 3, 0x0d,
542 0x0d80,
543 0x0001,
544 0x0000,
546 4, 0x11,
547 0x0000,
548 0x0103,
549 0x0000,
550 0x0000,
552 3, 0x16,
553 0x0004 | 0x0040,
554 0x0030,
555 0x07ff,
557 6, 0x1b,
558 0x4112,
559 0xff00,
560 0xc07f,
561 0x0000,
562 0x0180,
563 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
568 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
570 u16 tuner_en = dib0070_read_reg(state, 0x20);
571 u16 offset;
573 dib0070_write_reg(state, 0x18, 0x07ff);
574 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
575 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
576 msleep(9);
577 offset = dib0070_read_reg(state, 0x19);
578 dib0070_write_reg(state, 0x20, tuner_en);
579 return offset;
582 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
584 u8 gain;
585 for (gain = 6; gain < 8; gain++) {
586 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
587 dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
591 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
593 struct dib0070_state *state = fe->tuner_priv;
594 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
595 u32 freq = fe->dtv_property_cache.frequency/1000;
597 if (tmp != NULL) {
598 while (freq/1000 > tmp->freq) /* find the right one */
599 tmp++;
600 state->wbd_gain_current = tmp->wbd_gain_val;
601 } else
602 state->wbd_gain_current = 6;
604 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
606 EXPORT_SYMBOL(dib0070_wbd_offset);
608 #define pgm_read_word(w) (*w)
609 static int dib0070_reset(struct dvb_frontend *fe)
611 struct dib0070_state *state = fe->tuner_priv;
612 u16 l, r, *n;
614 HARD_RESET(state);
617 #ifndef FORCE_SBAND_TUNER
618 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
619 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
620 else
621 #else
622 #warning forcing SBAND
623 #endif
624 state->revision = DIB0070S_P1A;
626 /* P1F or not */
627 dprintk("Revision: %x", state->revision);
629 if (state->revision == DIB0070_P1D) {
630 dprintk("Error: this driver is not to be used meant for P1D or earlier");
631 return -EINVAL;
634 n = (u16 *) dib0070_p1f_defaults;
635 l = pgm_read_word(n++);
636 while (l) {
637 r = pgm_read_word(n++);
638 do {
639 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
640 r++;
641 } while (--l);
642 l = pgm_read_word(n++);
645 if (state->cfg->force_crystal_mode != 0)
646 r = state->cfg->force_crystal_mode;
647 else if (state->cfg->clock_khz >= 24000)
648 r = 1;
649 else
650 r = 2;
653 r |= state->cfg->osc_buffer_state << 3;
655 dib0070_write_reg(state, 0x10, r);
656 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
658 if (state->cfg->invert_iq) {
659 r = dib0070_read_reg(state, 0x02) & 0xffdf;
660 dib0070_write_reg(state, 0x02, r | (1 << 5));
663 if (state->revision == DIB0070S_P1A)
664 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
665 else
666 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
668 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
670 dib0070_wbd_offset_calibration(state);
672 return 0;
675 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
677 struct dib0070_state *state = fe->tuner_priv;
679 *frequency = 1000 * state->current_rf;
680 return 0;
683 static int dib0070_release(struct dvb_frontend *fe)
685 kfree(fe->tuner_priv);
686 fe->tuner_priv = NULL;
687 return 0;
690 static const struct dvb_tuner_ops dib0070_ops = {
691 .info = {
692 .name = "DiBcom DiB0070",
693 .frequency_min = 45000000,
694 .frequency_max = 860000000,
695 .frequency_step = 1000,
697 .release = dib0070_release,
699 .init = dib0070_wakeup,
700 .sleep = dib0070_sleep,
701 .set_params = dib0070_tune,
703 .get_frequency = dib0070_get_frequency,
704 // .get_bandwidth = dib0070_get_bandwidth
707 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
709 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
710 if (state == NULL)
711 return NULL;
713 state->cfg = cfg;
714 state->i2c = i2c;
715 state->fe = fe;
716 fe->tuner_priv = state;
718 if (dib0070_reset(fe) != 0)
719 goto free_mem;
721 printk(KERN_INFO "DiB0070: successfully identified\n");
722 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
724 fe->tuner_priv = state;
725 return fe;
727 free_mem:
728 kfree(state);
729 fe->tuner_priv = NULL;
730 return NULL;
732 EXPORT_SYMBOL(dib0070_attach);
734 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
735 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
736 MODULE_LICENSE("GPL");