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>
30 #include <linux/mutex.h>
32 #include "dvb_frontend.h"
35 #include "dibx000_common.h"
38 module_param(debug
, int, 0644);
39 MODULE_PARM_DESC(debug
, "turn on debugging (default: 0)");
41 #define dprintk(args...) do { \
43 printk(KERN_DEBUG "DiB0070: "); \
49 #define DIB0070_P1D 0x00
50 #define DIB0070_P1F 0x01
51 #define DIB0070_P1G 0x03
52 #define DIB0070S_P1A 0x02
54 struct dib0070_state
{
55 struct i2c_adapter
*i2c
;
56 struct dvb_frontend
*fe
;
57 const struct dib0070_config
*cfg
;
61 enum frontend_tune_state tune_state
;
64 /* for the captrim binary search */
72 const struct dib0070_tuning
*current_tune_table_index
;
73 const struct dib0070_lna_match
*lna_match
;
76 u16 wbd_offset_3_3
[2];
78 /* for the I2C transfer */
79 struct i2c_msg msg
[2];
80 u8 i2c_write_buffer
[3];
81 u8 i2c_read_buffer
[2];
82 struct mutex i2c_buffer_lock
;
85 static u16
dib0070_read_reg(struct dib0070_state
*state
, u8 reg
)
89 if (mutex_lock_interruptible(&state
->i2c_buffer_lock
) < 0) {
90 dprintk("could not acquire lock");
94 state
->i2c_write_buffer
[0] = reg
;
96 memset(state
->msg
, 0, 2 * sizeof(struct i2c_msg
));
97 state
->msg
[0].addr
= state
->cfg
->i2c_address
;
98 state
->msg
[0].flags
= 0;
99 state
->msg
[0].buf
= state
->i2c_write_buffer
;
100 state
->msg
[0].len
= 1;
101 state
->msg
[1].addr
= state
->cfg
->i2c_address
;
102 state
->msg
[1].flags
= I2C_M_RD
;
103 state
->msg
[1].buf
= state
->i2c_read_buffer
;
104 state
->msg
[1].len
= 2;
106 if (i2c_transfer(state
->i2c
, state
->msg
, 2) != 2) {
107 printk(KERN_WARNING
"DiB0070 I2C read failed\n");
110 ret
= (state
->i2c_read_buffer
[0] << 8)
111 | state
->i2c_read_buffer
[1];
113 mutex_unlock(&state
->i2c_buffer_lock
);
117 static int dib0070_write_reg(struct dib0070_state
*state
, u8 reg
, u16 val
)
121 if (mutex_lock_interruptible(&state
->i2c_buffer_lock
) < 0) {
122 dprintk("could not acquire lock");
125 state
->i2c_write_buffer
[0] = reg
;
126 state
->i2c_write_buffer
[1] = val
>> 8;
127 state
->i2c_write_buffer
[2] = val
& 0xff;
129 memset(state
->msg
, 0, sizeof(struct i2c_msg
));
130 state
->msg
[0].addr
= state
->cfg
->i2c_address
;
131 state
->msg
[0].flags
= 0;
132 state
->msg
[0].buf
= state
->i2c_write_buffer
;
133 state
->msg
[0].len
= 3;
135 if (i2c_transfer(state
->i2c
, state
->msg
, 1) != 1) {
136 printk(KERN_WARNING
"DiB0070 I2C write failed\n");
141 mutex_unlock(&state
->i2c_buffer_lock
);
145 #define HARD_RESET(state) do { \
146 state->cfg->sleep(state->fe, 0); \
147 if (state->cfg->reset) { \
148 state->cfg->reset(state->fe,1); msleep(10); \
149 state->cfg->reset(state->fe,0); msleep(10); \
153 static int dib0070_set_bandwidth(struct dvb_frontend
*fe
)
155 struct dib0070_state
*state
= fe
->tuner_priv
;
156 u16 tmp
= dib0070_read_reg(state
, 0x02) & 0x3fff;
158 if (state
->fe
->dtv_property_cache
.bandwidth_hz
/1000 > 7000)
160 else if (state
->fe
->dtv_property_cache
.bandwidth_hz
/1000 > 6000)
162 else if (state
->fe
->dtv_property_cache
.bandwidth_hz
/1000 > 5000)
167 dib0070_write_reg(state
, 0x02, tmp
);
169 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
170 if (state
->fe
->dtv_property_cache
.delivery_system
== SYS_ISDBT
) {
171 u16 value
= dib0070_read_reg(state
, 0x17);
173 dib0070_write_reg(state
, 0x17, value
& 0xfffc);
174 tmp
= dib0070_read_reg(state
, 0x01) & 0x01ff;
175 dib0070_write_reg(state
, 0x01, tmp
| (60 << 9));
177 dib0070_write_reg(state
, 0x17, value
);
182 static int dib0070_captrim(struct dib0070_state
*state
, enum frontend_tune_state
*tune_state
)
188 if (*tune_state
== CT_TUNER_STEP_0
) {
189 dib0070_write_reg(state
, 0x0f, 0xed10);
190 dib0070_write_reg(state
, 0x17, 0x0034);
192 dib0070_write_reg(state
, 0x18, 0x0032);
193 state
->step
= state
->captrim
= state
->fcaptrim
= 64;
194 state
->adc_diff
= 3000;
197 *tune_state
= CT_TUNER_STEP_1
;
198 } else if (*tune_state
== CT_TUNER_STEP_1
) {
200 dib0070_write_reg(state
, 0x14, state
->lo4
| state
->captrim
);
203 *tune_state
= CT_TUNER_STEP_2
;
204 } else if (*tune_state
== CT_TUNER_STEP_2
) {
206 adc
= dib0070_read_reg(state
, 0x19);
208 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state
->captrim
, adc
, (u32
) adc
*(u32
)1800/(u32
)1024);
218 if (adc
< state
->adc_diff
) {
219 dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state
->captrim
, adc
, state
->adc_diff
);
220 state
->adc_diff
= adc
;
221 state
->fcaptrim
= state
->captrim
;
223 state
->captrim
+= (step_sign
* state
->step
);
225 if (state
->step
>= 1)
226 *tune_state
= CT_TUNER_STEP_1
;
228 *tune_state
= CT_TUNER_STEP_3
;
230 } else if (*tune_state
== CT_TUNER_STEP_3
) {
231 dib0070_write_reg(state
, 0x14, state
->lo4
| state
->fcaptrim
);
232 dib0070_write_reg(state
, 0x18, 0x07ff);
233 *tune_state
= CT_TUNER_STEP_4
;
239 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
)
241 struct dib0070_state
*state
= fe
->tuner_priv
;
242 u16 lo5
= (third_order_filt
<< 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current
<< 6) | (hf_div_trim
<< 3) | (vco_bias_trim
<< 0);
244 dprintk("CTRL_LO5: 0x%x", lo5
);
245 return dib0070_write_reg(state
, 0x15, lo5
);
248 void dib0070_ctrl_agc_filter(struct dvb_frontend
*fe
, u8 open
)
250 struct dib0070_state
*state
= fe
->tuner_priv
;
253 dib0070_write_reg(state
, 0x1b, 0xff00);
254 dib0070_write_reg(state
, 0x1a, 0x0000);
256 dib0070_write_reg(state
, 0x1b, 0x4112);
257 if (state
->cfg
->vga_filter
!= 0) {
258 dib0070_write_reg(state
, 0x1a, state
->cfg
->vga_filter
);
259 dprintk("vga filter register is set to %x", state
->cfg
->vga_filter
);
261 dib0070_write_reg(state
, 0x1a, 0x0009);
265 EXPORT_SYMBOL(dib0070_ctrl_agc_filter
);
266 struct dib0070_tuning
{
267 u32 max_freq
; /* for every frequency less than or equal to that field: this information is correct */
277 struct dib0070_lna_match
{
278 u32 max_freq
; /* for every frequency less than or equal to that field: this information is correct */
282 static const struct dib0070_tuning dib0070s_tuning_table
[] = {
283 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
284 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
285 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
286 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
287 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
288 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
289 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
292 static const struct dib0070_tuning dib0070_tuning_table
[] = {
293 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
294 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
295 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
296 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
297 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
298 { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
299 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
300 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
303 static const struct dib0070_lna_match dib0070_lna_flip_chip
[] = {
304 { 180000, 0 }, /* VHF */
308 { 550000, 0 }, /* UHF */
312 { 1500000, 0 }, /* LBAND or everything higher than UHF */
318 static const struct dib0070_lna_match dib0070_lna
[] = {
319 { 180000, 0 }, /* VHF */
323 { 550000, 2 }, /* UHF */
328 { 1500000, 0 }, /* LBAND or everything higher than UHF */
335 static int dib0070_tune_digital(struct dvb_frontend
*fe
)
337 struct dib0070_state
*state
= fe
->tuner_priv
;
339 const struct dib0070_tuning
*tune
;
340 const struct dib0070_lna_match
*lna_match
;
342 enum frontend_tune_state
*tune_state
= &state
->tune_state
;
343 int ret
= 10; /* 1ms is the default delay most of the time */
345 u8 band
= (u8
)BAND_OF_FREQUENCY(fe
->dtv_property_cache
.frequency
/1000);
346 u32 freq
= fe
->dtv_property_cache
.frequency
/1000 + (band
== BAND_VHF
? state
->cfg
->freq_offset_khz_vhf
: state
->cfg
->freq_offset_khz_uhf
);
348 #ifdef CONFIG_SYS_ISDBT
349 if (state
->fe
->dtv_property_cache
.delivery_system
== SYS_ISDBT
&& state
->fe
->dtv_property_cache
.isdbt_sb_mode
== 1)
350 if (((state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
% 2)
351 && (state
->fe
->dtv_property_cache
.isdbt_sb_segment_idx
== ((state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
/ 2) + 1)))
352 || (((state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
% 2) == 0)
353 && (state
->fe
->dtv_property_cache
.isdbt_sb_segment_idx
== (state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
/ 2)))
354 || (((state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
% 2) == 0)
355 && (state
->fe
->dtv_property_cache
.isdbt_sb_segment_idx
== ((state
->fe
->dtv_property_cache
.isdbt_sb_segment_count
/ 2) + 1))))
358 if (state
->current_rf
!= freq
) {
360 switch (state
->revision
) {
362 tune
= dib0070s_tuning_table
;
363 lna_match
= dib0070_lna
;
366 tune
= dib0070_tuning_table
;
367 if (state
->cfg
->flip_chip
)
368 lna_match
= dib0070_lna_flip_chip
;
370 lna_match
= dib0070_lna
;
373 while (freq
> tune
->max_freq
) /* find the right one */
375 while (freq
> lna_match
->max_freq
) /* find the right one */
378 state
->current_tune_table_index
= tune
;
379 state
->lna_match
= lna_match
;
382 if (*tune_state
== CT_TUNER_START
) {
383 dprintk("Tuning for Band: %hd (%d kHz)", band
, freq
);
384 if (state
->current_rf
!= freq
) {
386 u32 FBDiv
, Rest
, FREF
, VCOF_kHz
;
389 state
->current_rf
= freq
;
390 state
->lo4
= (state
->current_tune_table_index
->vco_band
<< 11) | (state
->current_tune_table_index
->hfdiv
<< 7);
393 dib0070_write_reg(state
, 0x17, 0x30);
396 VCOF_kHz
= state
->current_tune_table_index
->vco_multi
* freq
* 2;
400 REFDIV
= (u8
) ((state
->cfg
->clock_khz
+ 9999) / 10000);
403 REFDIV
= (u8
) ((state
->cfg
->clock_khz
) / 1000);
406 REFDIV
= (u8
) (state
->cfg
->clock_khz
/ 10000);
409 FREF
= state
->cfg
->clock_khz
/ REFDIV
;
413 switch (state
->revision
) {
415 FBDiv
= (VCOF_kHz
/ state
->current_tune_table_index
->presc
/ FREF
);
416 Rest
= (VCOF_kHz
/ state
->current_tune_table_index
->presc
) - FBDiv
* FREF
;
422 FBDiv
= (freq
/ (FREF
/ 2));
423 Rest
= 2 * freq
- FBDiv
* FREF
;
429 else if (Rest
< 2 * LPF
)
431 else if (Rest
> (FREF
- LPF
)) {
434 } else if (Rest
> (FREF
- 2 * LPF
))
435 Rest
= FREF
- 2 * LPF
;
436 Rest
= (Rest
* 6528) / (FREF
/ 10);
440 state
->lo4
|= (1 << 14) | (1 << 12);
445 dib0070_write_reg(state
, 0x11, (u16
)FBDiv
);
446 dib0070_write_reg(state
, 0x12, (Den
<< 8) | REFDIV
);
447 dib0070_write_reg(state
, 0x13, (u16
) Rest
);
449 if (state
->revision
== DIB0070S_P1A
) {
451 if (band
== BAND_SBAND
) {
452 dib0070_set_ctrl_lo5(fe
, 2, 4, 3, 0);
453 dib0070_write_reg(state
, 0x1d, 0xFFFF);
455 dib0070_set_ctrl_lo5(fe
, 5, 4, 3, 1);
458 dib0070_write_reg(state
, 0x20,
459 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state
->current_tune_table_index
->tuner_enable
);
461 dprintk("REFDIV: %hd, FREF: %d", REFDIV
, FREF
);
462 dprintk("FBDIV: %d, Rest: %d", FBDiv
, Rest
);
463 dprintk("Num: %hd, Den: %hd, SD: %hd", (u16
) Rest
, Den
, (state
->lo4
>> 12) & 0x1);
464 dprintk("HFDIV code: %hd", state
->current_tune_table_index
->hfdiv
);
465 dprintk("VCO = %hd", state
->current_tune_table_index
->vco_band
);
466 dprintk("VCOF: ((%hd*%d) << 1))", state
->current_tune_table_index
->vco_multi
, freq
);
468 *tune_state
= CT_TUNER_STEP_0
;
469 } else { /* we are already tuned to this frequency - the configuration is correct */
470 ret
= 50; /* wakeup time */
471 *tune_state
= CT_TUNER_STEP_5
;
473 } else if ((*tune_state
> CT_TUNER_START
) && (*tune_state
< CT_TUNER_STEP_4
)) {
475 ret
= dib0070_captrim(state
, tune_state
);
477 } else if (*tune_state
== CT_TUNER_STEP_4
) {
478 const struct dib0070_wbd_gain_cfg
*tmp
= state
->cfg
->wbd_gain
;
480 while (freq
/1000 > tmp
->freq
) /* find the right one */
482 dib0070_write_reg(state
, 0x0f,
483 (0 << 15) | (1 << 14) | (3 << 12)
484 | (tmp
->wbd_gain_val
<< 9) | (0 << 8) | (1 << 7)
485 | (state
->current_tune_table_index
->wbdmux
<< 0));
486 state
->wbd_gain_current
= tmp
->wbd_gain_val
;
488 dib0070_write_reg(state
, 0x0f,
489 (0 << 15) | (1 << 14) | (3 << 12)
490 | (6 << 9) | (0 << 8) | (1 << 7)
491 | (state
->current_tune_table_index
->wbdmux
<< 0));
492 state
->wbd_gain_current
= 6;
495 dib0070_write_reg(state
, 0x06, 0x3fff);
496 dib0070_write_reg(state
, 0x07,
497 (state
->current_tune_table_index
->switch_trim
<< 11) | (7 << 8) | (state
->lna_match
->lna_band
<< 3) | (3 << 0));
498 dib0070_write_reg(state
, 0x08, (state
->lna_match
->lna_band
<< 10) | (3 << 7) | (127));
499 dib0070_write_reg(state
, 0x0d, 0x0d80);
502 dib0070_write_reg(state
, 0x18, 0x07ff);
503 dib0070_write_reg(state
, 0x17, 0x0033);
506 *tune_state
= CT_TUNER_STEP_5
;
507 } else if (*tune_state
== CT_TUNER_STEP_5
) {
508 dib0070_set_bandwidth(fe
);
509 *tune_state
= CT_TUNER_STOP
;
511 ret
= FE_CALLBACK_TIME_NEVER
; /* tuner finished, time to call again infinite */
517 static int dib0070_tune(struct dvb_frontend
*fe
)
519 struct dib0070_state
*state
= fe
->tuner_priv
;
522 state
->tune_state
= CT_TUNER_START
;
525 ret
= dib0070_tune_digital(fe
);
526 if (ret
!= FE_CALLBACK_TIME_NEVER
)
530 } while (state
->tune_state
!= CT_TUNER_STOP
);
535 static int dib0070_wakeup(struct dvb_frontend
*fe
)
537 struct dib0070_state
*state
= fe
->tuner_priv
;
538 if (state
->cfg
->sleep
)
539 state
->cfg
->sleep(fe
, 0);
543 static int dib0070_sleep(struct dvb_frontend
*fe
)
545 struct dib0070_state
*state
= fe
->tuner_priv
;
546 if (state
->cfg
->sleep
)
547 state
->cfg
->sleep(fe
, 1);
551 u8
dib0070_get_rf_output(struct dvb_frontend
*fe
)
553 struct dib0070_state
*state
= fe
->tuner_priv
;
554 return (dib0070_read_reg(state
, 0x07) >> 11) & 0x3;
556 EXPORT_SYMBOL(dib0070_get_rf_output
);
558 int dib0070_set_rf_output(struct dvb_frontend
*fe
, u8 no
)
560 struct dib0070_state
*state
= fe
->tuner_priv
;
561 u16 rxrf2
= dib0070_read_reg(state
, 0x07) & 0xfe7ff;
566 return dib0070_write_reg(state
, 0x07, rxrf2
| (no
<< 11));
568 EXPORT_SYMBOL(dib0070_set_rf_output
);
570 static const u16 dib0070_p1f_defaults
[] =
604 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
609 static u16
dib0070_read_wbd_offset(struct dib0070_state
*state
, u8 gain
)
611 u16 tuner_en
= dib0070_read_reg(state
, 0x20);
614 dib0070_write_reg(state
, 0x18, 0x07ff);
615 dib0070_write_reg(state
, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
616 dib0070_write_reg(state
, 0x0f, (1 << 14) | (2 << 12) | (gain
<< 9) | (1 << 8) | (1 << 7) | (0 << 0));
618 offset
= dib0070_read_reg(state
, 0x19);
619 dib0070_write_reg(state
, 0x20, tuner_en
);
623 static void dib0070_wbd_offset_calibration(struct dib0070_state
*state
)
626 for (gain
= 6; gain
< 8; gain
++) {
627 state
->wbd_offset_3_3
[gain
- 6] = ((dib0070_read_wbd_offset(state
, gain
) * 8 * 18 / 33 + 1) / 2);
628 dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain
, state
->wbd_offset_3_3
[gain
-6]);
632 u16
dib0070_wbd_offset(struct dvb_frontend
*fe
)
634 struct dib0070_state
*state
= fe
->tuner_priv
;
635 const struct dib0070_wbd_gain_cfg
*tmp
= state
->cfg
->wbd_gain
;
636 u32 freq
= fe
->dtv_property_cache
.frequency
/1000;
639 while (freq
/1000 > tmp
->freq
) /* find the right one */
641 state
->wbd_gain_current
= tmp
->wbd_gain_val
;
643 state
->wbd_gain_current
= 6;
645 return state
->wbd_offset_3_3
[state
->wbd_gain_current
- 6];
647 EXPORT_SYMBOL(dib0070_wbd_offset
);
649 #define pgm_read_word(w) (*w)
650 static int dib0070_reset(struct dvb_frontend
*fe
)
652 struct dib0070_state
*state
= fe
->tuner_priv
;
658 #ifndef FORCE_SBAND_TUNER
659 if ((dib0070_read_reg(state
, 0x22) >> 9) & 0x1)
660 state
->revision
= (dib0070_read_reg(state
, 0x1f) >> 8) & 0xff;
663 #warning forcing SBAND
665 state
->revision
= DIB0070S_P1A
;
668 dprintk("Revision: %x", state
->revision
);
670 if (state
->revision
== DIB0070_P1D
) {
671 dprintk("Error: this driver is not to be used meant for P1D or earlier");
675 n
= (u16
*) dib0070_p1f_defaults
;
676 l
= pgm_read_word(n
++);
678 r
= pgm_read_word(n
++);
680 dib0070_write_reg(state
, (u8
)r
, pgm_read_word(n
++));
683 l
= pgm_read_word(n
++);
686 if (state
->cfg
->force_crystal_mode
!= 0)
687 r
= state
->cfg
->force_crystal_mode
;
688 else if (state
->cfg
->clock_khz
>= 24000)
694 r
|= state
->cfg
->osc_buffer_state
<< 3;
696 dib0070_write_reg(state
, 0x10, r
);
697 dib0070_write_reg(state
, 0x1f, (1 << 8) | ((state
->cfg
->clock_pad_drive
& 0xf) << 5));
699 if (state
->cfg
->invert_iq
) {
700 r
= dib0070_read_reg(state
, 0x02) & 0xffdf;
701 dib0070_write_reg(state
, 0x02, r
| (1 << 5));
704 if (state
->revision
== DIB0070S_P1A
)
705 dib0070_set_ctrl_lo5(fe
, 2, 4, 3, 0);
707 dib0070_set_ctrl_lo5(fe
, 5, 4, state
->cfg
->charge_pump
,
708 state
->cfg
->enable_third_order_filter
);
710 dib0070_write_reg(state
, 0x01, (54 << 9) | 0xc8);
712 dib0070_wbd_offset_calibration(state
);
717 static int dib0070_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
719 struct dib0070_state
*state
= fe
->tuner_priv
;
721 *frequency
= 1000 * state
->current_rf
;
725 static int dib0070_release(struct dvb_frontend
*fe
)
727 kfree(fe
->tuner_priv
);
728 fe
->tuner_priv
= NULL
;
732 static const struct dvb_tuner_ops dib0070_ops
= {
734 .name
= "DiBcom DiB0070",
735 .frequency_min
= 45000000,
736 .frequency_max
= 860000000,
737 .frequency_step
= 1000,
739 .release
= dib0070_release
,
741 .init
= dib0070_wakeup
,
742 .sleep
= dib0070_sleep
,
743 .set_params
= dib0070_tune
,
745 .get_frequency
= dib0070_get_frequency
,
746 // .get_bandwidth = dib0070_get_bandwidth
749 struct dvb_frontend
*dib0070_attach(struct dvb_frontend
*fe
, struct i2c_adapter
*i2c
, struct dib0070_config
*cfg
)
751 struct dib0070_state
*state
= kzalloc(sizeof(struct dib0070_state
), GFP_KERNEL
);
758 mutex_init(&state
->i2c_buffer_lock
);
759 fe
->tuner_priv
= state
;
761 if (dib0070_reset(fe
) != 0)
764 printk(KERN_INFO
"DiB0070: successfully identified\n");
765 memcpy(&fe
->ops
.tuner_ops
, &dib0070_ops
, sizeof(struct dvb_tuner_ops
));
767 fe
->tuner_priv
= state
;
772 fe
->tuner_priv
= NULL
;
775 EXPORT_SYMBOL(dib0070_attach
);
777 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
778 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
779 MODULE_LICENSE("GPL");