FRV: Use generic show_interrupts()
[cris-mirror.git] / drivers / media / dvb / frontends / dib0070.c
blobd4e466a90e43d08d0e3fb6c3a24589ccd8f91857
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/slab.h>
29 #include <linux/i2c.h>
31 #include "dvb_frontend.h"
33 #include "dib0070.h"
34 #include "dibx000_common.h"
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40 #define dprintk(args...) do { \
41 if (debug) { \
42 printk(KERN_DEBUG "DiB0070: "); \
43 printk(args); \
44 printk("\n"); \
45 } \
46 } while (0)
48 #define DIB0070_P1D 0x00
49 #define DIB0070_P1F 0x01
50 #define DIB0070_P1G 0x03
51 #define DIB0070S_P1A 0x02
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;
60 enum frontend_tune_state tune_state;
61 u32 current_rf;
63 /* for the captrim binary search */
64 s8 step;
65 u16 adc_diff;
67 s8 captrim;
68 s8 fcaptrim;
69 u16 lo4;
71 const struct dib0070_tuning *current_tune_table_index;
72 const struct dib0070_lna_match *lna_match;
74 u8 wbd_gain_current;
75 u16 wbd_offset_3_3[2];
78 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
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 },
85 if (i2c_transfer(state->i2c, msg, 2) != 2) {
86 printk(KERN_WARNING "DiB0070 I2C read failed\n");
87 return 0;
89 return (b[0] << 8) | b[1];
92 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
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;
100 return 0;
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); \
109 } while (0)
111 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
113 struct dib0070_state *state = fe->tuner_priv;
114 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
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);
125 dib0070_write_reg(state, 0x02, tmp);
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);
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));
135 dib0070_write_reg(state, 0x17, value);
137 return 0;
140 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
142 int8_t step_sign;
143 u16 adc;
144 int ret = 0;
146 if (*tune_state == CT_TUNER_STEP_0) {
148 dib0070_write_reg(state, 0x0f, 0xed10);
149 dib0070_write_reg(state, 0x17, 0x0034);
151 dib0070_write_reg(state, 0x18, 0x0032);
152 state->step = state->captrim = state->fcaptrim = 64;
153 state->adc_diff = 3000;
154 ret = 20;
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;
162 *tune_state = CT_TUNER_STEP_2;
163 } else if (*tune_state == CT_TUNER_STEP_2) {
165 adc = dib0070_read_reg(state, 0x19);
167 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
169 if (adc >= 400) {
170 adc -= 400;
171 step_sign = -1;
172 } else {
173 adc = 400 - adc;
174 step_sign = 1;
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;
185 state->captrim += (step_sign * state->step);
187 if (state->step >= 1)
188 *tune_state = CT_TUNER_STEP_1;
189 else
190 *tune_state = CT_TUNER_STEP_3;
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;
198 return ret;
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)
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);
209 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
211 struct dib0070_state *state = fe->tuner_priv;
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);
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;
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;
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 */
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 */
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 },
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 },
295 #define LPF 100
296 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
298 struct dib0070_state *state = fe->tuner_priv;
300 const struct dib0070_tuning *tune;
301 const struct dib0070_lna_match *lna_match;
303 enum frontend_tune_state *tune_state = &state->tune_state;
304 int ret = 10; /* 1ms is the default delay most of the time */
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);
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) {
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;
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++;
339 state->current_tune_table_index = tune;
340 state->lna_match = lna_match;
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;
350 state->current_rf = freq;
351 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
354 dib0070_write_reg(state, 0x17, 0x30);
357 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
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;
370 FREF = state->cfg->clock_khz / REFDIV;
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;
380 case DIB0070_P1G:
381 case DIB0070_P1F:
382 default:
383 FBDiv = (freq / (FREF / 2));
384 Rest = 2 * freq - FBDiv * FREF;
385 break;
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);
399 Den = 1;
400 if (Rest > 0) {
401 state->lo4 |= (1 << 14) | (1 << 12);
402 Den = 255;
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);
410 if (state->revision == DIB0070S_P1A) {
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);
419 dib0070_write_reg(state, 0x20,
420 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
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);
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;
434 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
436 ret = dib0070_captrim(state, tune_state);
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;
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);
462 dib0070_write_reg(state, 0x18, 0x07ff);
463 dib0070_write_reg(state, 0x17, 0x0033);
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 */
473 return ret;
477 static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
479 struct dib0070_state *state = fe->tuner_priv;
480 uint32_t ret;
482 state->tune_state = CT_TUNER_START;
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);
492 return 0;
495 static int dib0070_wakeup(struct dvb_frontend *fe)
497 struct dib0070_state *state = fe->tuner_priv;
498 if (state->cfg->sleep)
499 state->cfg->sleep(fe, 0);
500 return 0;
503 static int dib0070_sleep(struct dvb_frontend *fe)
505 struct dib0070_state *state = fe->tuner_priv;
506 if (state->cfg->sleep)
507 state->cfg->sleep(fe, 1);
508 return 0;
511 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
513 struct dib0070_state *state = fe->tuner_priv;
514 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
516 EXPORT_SYMBOL(dib0070_get_rf_output);
518 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
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));
528 EXPORT_SYMBOL(dib0070_set_rf_output);
530 static const u16 dib0070_p1f_defaults[] =
533 7, 0x02,
534 0x0008,
535 0x0000,
536 0x0000,
537 0x0000,
538 0x0000,
539 0x0002,
540 0x0100,
542 3, 0x0d,
543 0x0d80,
544 0x0001,
545 0x0000,
547 4, 0x11,
548 0x0000,
549 0x0103,
550 0x0000,
551 0x0000,
553 3, 0x16,
554 0x0004 | 0x0040,
555 0x0030,
556 0x07ff,
558 6, 0x1b,
559 0x4112,
560 0xff00,
561 0xc07f,
562 0x0000,
563 0x0180,
564 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
569 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
571 u16 tuner_en = dib0070_read_reg(state, 0x20);
572 u16 offset;
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;
583 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
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]);
592 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
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;
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;
605 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
607 EXPORT_SYMBOL(dib0070_wbd_offset);
609 #define pgm_read_word(w) (*w)
610 static int dib0070_reset(struct dvb_frontend *fe)
612 struct dib0070_state *state = fe->tuner_priv;
613 u16 l, r, *n;
615 HARD_RESET(state);
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;
627 /* P1F or not */
628 dprintk("Revision: %x", state->revision);
630 if (state->revision == DIB0070_P1D) {
631 dprintk("Error: this driver is not to be used meant for P1D or earlier");
632 return -EINVAL;
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++);
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;
654 r |= state->cfg->osc_buffer_state << 3;
656 dib0070_write_reg(state, 0x10, r);
657 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
659 if (state->cfg->invert_iq) {
660 r = dib0070_read_reg(state, 0x02) & 0xffdf;
661 dib0070_write_reg(state, 0x02, r | (1 << 5));
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);
669 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
671 dib0070_wbd_offset_calibration(state);
673 return 0;
676 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
678 struct dib0070_state *state = fe->tuner_priv;
680 *frequency = 1000 * state->current_rf;
681 return 0;
684 static int dib0070_release(struct dvb_frontend *fe)
686 kfree(fe->tuner_priv);
687 fe->tuner_priv = NULL;
688 return 0;
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,
698 .release = dib0070_release,
700 .init = dib0070_wakeup,
701 .sleep = dib0070_sleep,
702 .set_params = dib0070_tune,
704 .get_frequency = dib0070_get_frequency,
705 // .get_bandwidth = dib0070_get_bandwidth
708 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
710 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
711 if (state == NULL)
712 return NULL;
714 state->cfg = cfg;
715 state->i2c = i2c;
716 state->fe = fe;
717 fe->tuner_priv = state;
719 if (dib0070_reset(fe) != 0)
720 goto free_mem;
722 printk(KERN_INFO "DiB0070: successfully identified\n");
723 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
725 fe->tuner_priv = state;
726 return fe;
728 free_mem:
729 kfree(state);
730 fe->tuner_priv = NULL;
731 return NULL;
733 EXPORT_SYMBOL(dib0070_attach);
735 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
736 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
737 MODULE_LICENSE("GPL");