V4L/DVB (13583): DiB8090: Add the DiB0090 tuner driver and STK8096GP-board
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / dvb / frontends / dib0070.c
blob81860b2cfe98aef04ca69f59c1f0d7865884d780
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 // 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)
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) | (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;
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;
516 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) no = 3;
522 if (no < 1) no = 1;
523 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
526 EXPORT_SYMBOL(dib0070_set_rf_output);
527 static const u16 dib0070_p1f_defaults[] =
530 7, 0x02,
531 0x0008,
532 0x0000,
533 0x0000,
534 0x0000,
535 0x0000,
536 0x0002,
537 0x0100,
539 3, 0x0d,
540 0x0d80,
541 0x0001,
542 0x0000,
544 4, 0x11,
545 0x0000,
546 0x0103,
547 0x0000,
548 0x0000,
550 3, 0x16,
551 0x0004 | 0x0040,
552 0x0030,
553 0x07ff,
555 6, 0x1b,
556 0x4112,
557 0xff00,
558 0xc07f,
559 0x0000,
560 0x0180,
561 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
566 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
568 u16 tuner_en = dib0070_read_reg(state, 0x20);
569 u16 offset;
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;
580 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
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]);
589 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
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;
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;
602 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
604 EXPORT_SYMBOL(dib0070_wbd_offset);
606 #define pgm_read_word(w) (*w)
607 static int dib0070_reset(struct dvb_frontend *fe)
609 struct dib0070_state *state = fe->tuner_priv;
610 u16 l, r, *n;
612 HARD_RESET(state);
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;
624 /* P1F or not */
625 dprintk( "Revision: %x", state->revision);
627 if (state->revision == DIB0070_P1D) {
628 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
629 return -EINVAL;
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++);
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;
651 r |= state->cfg->osc_buffer_state << 3;
653 dib0070_write_reg(state, 0x10, r);
654 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
656 if (state->cfg->invert_iq) {
657 r = dib0070_read_reg(state, 0x02) & 0xffdf;
658 dib0070_write_reg(state, 0x02, r | (1 << 5));
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);
666 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
668 dib0070_wbd_offset_calibration(state);
670 return 0;
673 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
675 struct dib0070_state *state = fe->tuner_priv;
677 *frequency = 1000 * state->current_rf;
678 return 0;
681 static int dib0070_release(struct dvb_frontend *fe)
683 kfree(fe->tuner_priv);
684 fe->tuner_priv = NULL;
685 return 0;
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,
695 .release = dib0070_release,
697 .init = dib0070_wakeup,
698 .sleep = dib0070_sleep,
699 .set_params = dib0070_tune,
701 .get_frequency = dib0070_get_frequency,
702 // .get_bandwidth = dib0070_get_bandwidth
705 struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
707 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
708 if (state == NULL)
709 return NULL;
711 state->cfg = cfg;
712 state->i2c = i2c;
713 state->fe = fe;
714 fe->tuner_priv = state;
716 if (dib0070_reset(fe) != 0)
717 goto free_mem;
719 printk(KERN_INFO "DiB0070: successfully identified\n");
720 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
722 fe->tuner_priv = state;
723 return fe;
725 free_mem:
726 kfree(state);
727 fe->tuner_priv = NULL;
728 return NULL;
730 EXPORT_SYMBOL(dib0070_attach);
732 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
733 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
734 MODULE_LICENSE("GPL");