Merge branch 'for-linus-1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[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/i2c.h>
29
30 #include "dvb_frontend.h"
31
32 #include "dib0070.h"
33 #include "dibx000_common.h"
34
35 static int debug;
36 module_param(debug, int, 0644);
37 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
38
39 #define dprintk(args...) do { \
40         if (debug) { \
41                 printk(KERN_DEBUG "DiB0070: "); \
42                 printk(args); \
43                 printk("\n"); \
44         } \
45 } while (0)
46
47 #define DIB0070_P1D  0x00
48 #define DIB0070_P1F  0x01
49 #define DIB0070_P1G  0x03
50 #define DIB0070S_P1A 0x02
51
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;
58
59     enum frontend_tune_state tune_state;
60     u32 current_rf;
61
62     /* for the captrim binary search */
63         s8 step;
64         u16 adc_diff;
65
66         s8 captrim;
67         s8 fcaptrim;
68         u16 lo4;
69
70         const struct dib0070_tuning *current_tune_table_index;
71         const struct dib0070_lna_match *lna_match;
72
73     u8  wbd_gain_current;
74         u16 wbd_offset_3_3[2];
75 };
76
77 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
78 {
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 },
83         };
84         if (i2c_transfer(state->i2c, msg, 2) != 2) {
85                 printk(KERN_WARNING "DiB0070 I2C read failed\n");
86                 return 0;
87         }
88         return (b[0] << 8) | b[1];
89 }
90
91 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
92 {
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;
98         }
99         return 0;
100 }
101
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); \
107     } \
108 } while (0)
109
110 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
111 {
112     struct dib0070_state *state = fe->tuner_priv;
113     u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
114
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);
123
124     dib0070_write_reg(state, 0x02, tmp);
125
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);
129
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));
133
134         dib0070_write_reg(state, 0x17, value);
135     }
136         return 0;
137 }
138
139 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
140 {
141         int8_t step_sign;
142         u16 adc;
143         int ret = 0;
144
145         if (*tune_state == CT_TUNER_STEP_0) {
146
147                 dib0070_write_reg(state, 0x0f, 0xed10);
148                 dib0070_write_reg(state, 0x17,    0x0034);
149
150                 dib0070_write_reg(state, 0x18, 0x0032);
151                 state->step = state->captrim = state->fcaptrim = 64;
152                 state->adc_diff = 3000;
153                 ret = 20;
154
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;
160
161                 *tune_state = CT_TUNER_STEP_2;
162         } else if (*tune_state == CT_TUNER_STEP_2) {
163
164                 adc = dib0070_read_reg(state, 0x19);
165
166                 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
167
168                 if (adc >= 400) {
169                         adc -= 400;
170                         step_sign = -1;
171                 } else {
172                         adc = 400 - adc;
173                         step_sign = 1;
174                 }
175
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;
180
181
182
183                 }
184                 state->captrim += (step_sign * state->step);
185
186                 if (state->step >= 1)
187                         *tune_state = CT_TUNER_STEP_1;
188                 else
189                         *tune_state = CT_TUNER_STEP_3;
190
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;
195         }
196
197         return ret;
198 }
199
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)
201 {
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);
206 }
207
208 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
209 {
210         struct dib0070_state *state = fe->tuner_priv;
211
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);
222         }
223 }
224
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;
235 };
236
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;
240 };
241
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 */
250 };
251
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 */
261 };
262
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 },
276 };
277
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 },
292 };
293
294 #define LPF     100
295 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
296 {
297     struct dib0070_state *state = fe->tuner_priv;
298
299     const struct dib0070_tuning *tune;
300     const struct dib0070_lna_match *lna_match;
301
302     enum frontend_tune_state *tune_state = &state->tune_state;
303     int ret = 10; /* 1ms is the default delay most of the time */
304
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);
307
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) {
319
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;
332         }
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++;
337
338         state->current_tune_table_index = tune;
339         state->lna_match = lna_match;
340     }
341
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;
348
349                 state->current_rf = freq;
350                 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
351
352
353                 dib0070_write_reg(state, 0x17, 0x30);
354
355
356                 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
357
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;
368                 }
369                 FREF = state->cfg->clock_khz / REFDIV;
370
371
372
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;
378
379                 case DIB0070_P1G:
380                 case DIB0070_P1F:
381                 default:
382                         FBDiv = (freq / (FREF / 2));
383                         Rest  = 2 * freq - FBDiv * FREF;
384                         break;
385                 }
386
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);
397
398                 Den = 1;
399                 if (Rest > 0) {
400                         state->lo4 |= (1 << 14) | (1 << 12);
401                         Den = 255;
402                 }
403
404
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);
408
409                 if (state->revision == DIB0070S_P1A) {
410
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);
416                 }
417
418                 dib0070_write_reg(state, 0x20,
419                         0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
420
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);
427
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;
432         }
433     } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
434
435         ret = dib0070_captrim(state, tune_state);
436
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;
452         }
453
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);
459
460
461         dib0070_write_reg(state, 0x18,   0x07ff);
462         dib0070_write_reg(state, 0x17, 0x0033);
463
464
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 */
471     }
472     return ret;
473 }
474
475
476 static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
477 {
478     struct dib0070_state *state = fe->tuner_priv;
479     uint32_t ret;
480
481     state->tune_state = CT_TUNER_START;
482
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);
490
491     return 0;
492 }
493
494 static int dib0070_wakeup(struct dvb_frontend *fe)
495 {
496         struct dib0070_state *state = fe->tuner_priv;
497         if (state->cfg->sleep)
498                 state->cfg->sleep(fe, 0);
499         return 0;
500 }
501
502 static int dib0070_sleep(struct dvb_frontend *fe)
503 {
504         struct dib0070_state *state = fe->tuner_priv;
505         if (state->cfg->sleep)
506                 state->cfg->sleep(fe, 1);
507         return 0;
508 }
509
510 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
511 {
512         struct dib0070_state *state = fe->tuner_priv;
513         return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
514 }
515 EXPORT_SYMBOL(dib0070_get_rf_output);
516
517 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
518 {
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));
526 }
527 EXPORT_SYMBOL(dib0070_set_rf_output);
528
529 static const u16 dib0070_p1f_defaults[] =
530
531 {
532         7, 0x02,
533                 0x0008,
534                 0x0000,
535                 0x0000,
536                 0x0000,
537                 0x0000,
538                 0x0002,
539                 0x0100,
540
541         3, 0x0d,
542                 0x0d80,
543                 0x0001,
544                 0x0000,
545
546         4, 0x11,
547                 0x0000,
548                 0x0103,
549                 0x0000,
550                 0x0000,
551
552         3, 0x16,
553                 0x0004 | 0x0040,
554                 0x0030,
555                 0x07ff,
556
557         6, 0x1b,
558                 0x4112,
559                 0xff00,
560                 0xc07f,
561                 0x0000,
562                 0x0180,
563                 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
564
565         0,
566 };
567
568 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
569 {
570     u16 tuner_en = dib0070_read_reg(state, 0x20);
571     u16 offset;
572
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;
580 }
581
582 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
583 {
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]);
588     }
589 }
590
591 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
592 {
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;
596
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;
603
604     return state->wbd_offset_3_3[state->wbd_gain_current - 6];
605 }
606 EXPORT_SYMBOL(dib0070_wbd_offset);
607
608 #define pgm_read_word(w) (*w)
609 static int dib0070_reset(struct dvb_frontend *fe)
610 {
611     struct dib0070_state *state = fe->tuner_priv;
612         u16 l, r, *n;
613
614         HARD_RESET(state);
615
616
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;
625
626         /* P1F or not */
627         dprintk("Revision: %x", state->revision);
628
629         if (state->revision == DIB0070_P1D) {
630                 dprintk("Error: this driver is not to be used meant for P1D or earlier");
631                 return -EINVAL;
632         }
633
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++);
643         }
644
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;
651
652
653         r |= state->cfg->osc_buffer_state << 3;
654
655         dib0070_write_reg(state, 0x10, r);
656         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
657
658         if (state->cfg->invert_iq) {
659                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
660                 dib0070_write_reg(state, 0x02, r | (1 << 5));
661         }
662
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);
667
668         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
669
670     dib0070_wbd_offset_calibration(state);
671
672     return 0;
673 }
674
675 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
676 {
677     struct dib0070_state *state = fe->tuner_priv;
678
679     *frequency = 1000 * state->current_rf;
680     return 0;
681 }
682
683 static int dib0070_release(struct dvb_frontend *fe)
684 {
685         kfree(fe->tuner_priv);
686         fe->tuner_priv = NULL;
687         return 0;
688 }
689
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,
696         },
697         .release       = dib0070_release,
698
699         .init          = dib0070_wakeup,
700         .sleep         = dib0070_sleep,
701         .set_params    = dib0070_tune,
702
703         .get_frequency = dib0070_get_frequency,
704 //      .get_bandwidth = dib0070_get_bandwidth
705 };
706
707 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
708 {
709         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
710         if (state == NULL)
711                 return NULL;
712
713         state->cfg = cfg;
714         state->i2c = i2c;
715         state->fe  = fe;
716         fe->tuner_priv = state;
717
718         if (dib0070_reset(fe) != 0)
719                 goto free_mem;
720
721         printk(KERN_INFO "DiB0070: successfully identified\n");
722         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
723
724         fe->tuner_priv = state;
725         return fe;
726
727 free_mem:
728         kfree(state);
729         fe->tuner_priv = NULL;
730         return NULL;
731 }
732 EXPORT_SYMBOL(dib0070_attach);
733
734 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
735 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
736 MODULE_LICENSE("GPL");