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