include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / 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
78 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
79 {
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 },
84         };
85         if (i2c_transfer(state->i2c, msg, 2) != 2) {
86                 printk(KERN_WARNING "DiB0070 I2C read failed\n");
87                 return 0;
88         }
89         return (b[0] << 8) | b[1];
90 }
91
92 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
93 {
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;
99         }
100         return 0;
101 }
102
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); \
108     } \
109 } while (0)
110
111 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
112 {
113     struct dib0070_state *state = fe->tuner_priv;
114     u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
115
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);
124
125     dib0070_write_reg(state, 0x02, tmp);
126
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);
130
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));
134
135         dib0070_write_reg(state, 0x17, value);
136     }
137         return 0;
138 }
139
140 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
141 {
142         int8_t step_sign;
143         u16 adc;
144         int ret = 0;
145
146         if (*tune_state == CT_TUNER_STEP_0) {
147
148                 dib0070_write_reg(state, 0x0f, 0xed10);
149                 dib0070_write_reg(state, 0x17,    0x0034);
150
151                 dib0070_write_reg(state, 0x18, 0x0032);
152                 state->step = state->captrim = state->fcaptrim = 64;
153                 state->adc_diff = 3000;
154                 ret = 20;
155
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;
161
162                 *tune_state = CT_TUNER_STEP_2;
163         } else if (*tune_state == CT_TUNER_STEP_2) {
164
165                 adc = dib0070_read_reg(state, 0x19);
166
167                 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
168
169                 if (adc >= 400) {
170                         adc -= 400;
171                         step_sign = -1;
172                 } else {
173                         adc = 400 - adc;
174                         step_sign = 1;
175                 }
176
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;
181
182
183
184                 }
185                 state->captrim += (step_sign * state->step);
186
187                 if (state->step >= 1)
188                         *tune_state = CT_TUNER_STEP_1;
189                 else
190                         *tune_state = CT_TUNER_STEP_3;
191
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;
196         }
197
198         return ret;
199 }
200
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)
202 {
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);
207 }
208
209 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
210 {
211         struct dib0070_state *state = fe->tuner_priv;
212
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);
223         }
224 }
225
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;
236 };
237
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;
241 };
242
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 */
251 };
252
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 */
262 };
263
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 },
277 };
278
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 },
293 };
294
295 #define LPF     100
296 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
297 {
298     struct dib0070_state *state = fe->tuner_priv;
299
300     const struct dib0070_tuning *tune;
301     const struct dib0070_lna_match *lna_match;
302
303     enum frontend_tune_state *tune_state = &state->tune_state;
304     int ret = 10; /* 1ms is the default delay most of the time */
305
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);
308
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) {
320
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;
333         }
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++;
338
339         state->current_tune_table_index = tune;
340         state->lna_match = lna_match;
341     }
342
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;
349
350                 state->current_rf = freq;
351                 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
352
353
354                 dib0070_write_reg(state, 0x17, 0x30);
355
356
357                 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
358
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;
369                 }
370                 FREF = state->cfg->clock_khz / REFDIV;
371
372
373
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;
379
380                 case DIB0070_P1G:
381                 case DIB0070_P1F:
382                 default:
383                         FBDiv = (freq / (FREF / 2));
384                         Rest  = 2 * freq - FBDiv * FREF;
385                         break;
386                 }
387
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);
398
399                 Den = 1;
400                 if (Rest > 0) {
401                         state->lo4 |= (1 << 14) | (1 << 12);
402                         Den = 255;
403                 }
404
405
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);
409
410                 if (state->revision == DIB0070S_P1A) {
411
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);
417                 }
418
419                 dib0070_write_reg(state, 0x20,
420                         0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
421
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);
428
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;
433         }
434     } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
435
436         ret = dib0070_captrim(state, tune_state);
437
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;
453         }
454
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);
460
461
462         dib0070_write_reg(state, 0x18,   0x07ff);
463         dib0070_write_reg(state, 0x17, 0x0033);
464
465
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 */
472     }
473     return ret;
474 }
475
476
477 static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
478 {
479     struct dib0070_state *state = fe->tuner_priv;
480     uint32_t ret;
481
482     state->tune_state = CT_TUNER_START;
483
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);
491
492     return 0;
493 }
494
495 static int dib0070_wakeup(struct dvb_frontend *fe)
496 {
497         struct dib0070_state *state = fe->tuner_priv;
498         if (state->cfg->sleep)
499                 state->cfg->sleep(fe, 0);
500         return 0;
501 }
502
503 static int dib0070_sleep(struct dvb_frontend *fe)
504 {
505         struct dib0070_state *state = fe->tuner_priv;
506         if (state->cfg->sleep)
507                 state->cfg->sleep(fe, 1);
508         return 0;
509 }
510
511 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
512 {
513         struct dib0070_state *state = fe->tuner_priv;
514         return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
515 }
516 EXPORT_SYMBOL(dib0070_get_rf_output);
517
518 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
519 {
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));
527 }
528 EXPORT_SYMBOL(dib0070_set_rf_output);
529
530 static const u16 dib0070_p1f_defaults[] =
531
532 {
533         7, 0x02,
534                 0x0008,
535                 0x0000,
536                 0x0000,
537                 0x0000,
538                 0x0000,
539                 0x0002,
540                 0x0100,
541
542         3, 0x0d,
543                 0x0d80,
544                 0x0001,
545                 0x0000,
546
547         4, 0x11,
548                 0x0000,
549                 0x0103,
550                 0x0000,
551                 0x0000,
552
553         3, 0x16,
554                 0x0004 | 0x0040,
555                 0x0030,
556                 0x07ff,
557
558         6, 0x1b,
559                 0x4112,
560                 0xff00,
561                 0xc07f,
562                 0x0000,
563                 0x0180,
564                 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
565
566         0,
567 };
568
569 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
570 {
571     u16 tuner_en = dib0070_read_reg(state, 0x20);
572     u16 offset;
573
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;
581 }
582
583 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
584 {
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]);
589     }
590 }
591
592 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
593 {
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;
597
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;
604
605     return state->wbd_offset_3_3[state->wbd_gain_current - 6];
606 }
607 EXPORT_SYMBOL(dib0070_wbd_offset);
608
609 #define pgm_read_word(w) (*w)
610 static int dib0070_reset(struct dvb_frontend *fe)
611 {
612     struct dib0070_state *state = fe->tuner_priv;
613         u16 l, r, *n;
614
615         HARD_RESET(state);
616
617
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;
626
627         /* P1F or not */
628         dprintk("Revision: %x", state->revision);
629
630         if (state->revision == DIB0070_P1D) {
631                 dprintk("Error: this driver is not to be used meant for P1D or earlier");
632                 return -EINVAL;
633         }
634
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++);
644         }
645
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;
652
653
654         r |= state->cfg->osc_buffer_state << 3;
655
656         dib0070_write_reg(state, 0x10, r);
657         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
658
659         if (state->cfg->invert_iq) {
660                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
661                 dib0070_write_reg(state, 0x02, r | (1 << 5));
662         }
663
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);
668
669         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
670
671     dib0070_wbd_offset_calibration(state);
672
673     return 0;
674 }
675
676 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
677 {
678     struct dib0070_state *state = fe->tuner_priv;
679
680     *frequency = 1000 * state->current_rf;
681     return 0;
682 }
683
684 static int dib0070_release(struct dvb_frontend *fe)
685 {
686         kfree(fe->tuner_priv);
687         fe->tuner_priv = NULL;
688         return 0;
689 }
690
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,
697         },
698         .release       = dib0070_release,
699
700         .init          = dib0070_wakeup,
701         .sleep         = dib0070_sleep,
702         .set_params    = dib0070_tune,
703
704         .get_frequency = dib0070_get_frequency,
705 //      .get_bandwidth = dib0070_get_bandwidth
706 };
707
708 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
709 {
710         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
711         if (state == NULL)
712                 return NULL;
713
714         state->cfg = cfg;
715         state->i2c = i2c;
716         state->fe  = fe;
717         fe->tuner_priv = state;
718
719         if (dib0070_reset(fe) != 0)
720                 goto free_mem;
721
722         printk(KERN_INFO "DiB0070: successfully identified\n");
723         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
724
725         fe->tuner_priv = state;
726         return fe;
727
728 free_mem:
729         kfree(state);
730         fe->tuner_priv = NULL;
731         return NULL;
732 }
733 EXPORT_SYMBOL(dib0070_attach);
734
735 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
736 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
737 MODULE_LICENSE("GPL");