These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / 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 #include <linux/mutex.h>
31
32 #include "dvb_frontend.h"
33
34 #include "dib0070.h"
35 #include "dibx000_common.h"
36
37 static int debug;
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40
41 #define dprintk(args...) do { \
42         if (debug) { \
43                 printk(KERN_DEBUG "DiB0070: "); \
44                 printk(args); \
45                 printk("\n"); \
46         } \
47 } while (0)
48
49 #define DIB0070_P1D  0x00
50 #define DIB0070_P1F  0x01
51 #define DIB0070_P1G  0x03
52 #define DIB0070S_P1A 0x02
53
54 struct dib0070_state {
55         struct i2c_adapter *i2c;
56         struct dvb_frontend *fe;
57         const struct dib0070_config *cfg;
58         u16 wbd_ff_offset;
59         u8 revision;
60
61         enum frontend_tune_state tune_state;
62         u32 current_rf;
63
64         /* for the captrim binary search */
65         s8 step;
66         u16 adc_diff;
67
68         s8 captrim;
69         s8 fcaptrim;
70         u16 lo4;
71
72         const struct dib0070_tuning *current_tune_table_index;
73         const struct dib0070_lna_match *lna_match;
74
75         u8  wbd_gain_current;
76         u16 wbd_offset_3_3[2];
77
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;
83 };
84
85 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
86 {
87         u16 ret;
88
89         if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
90                 dprintk("could not acquire lock");
91                 return 0;
92         }
93
94         state->i2c_write_buffer[0] = reg;
95
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;
105
106         if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
107                 printk(KERN_WARNING "DiB0070 I2C read failed\n");
108                 ret = 0;
109         } else
110                 ret = (state->i2c_read_buffer[0] << 8)
111                         | state->i2c_read_buffer[1];
112
113         mutex_unlock(&state->i2c_buffer_lock);
114         return ret;
115 }
116
117 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
118 {
119         int ret;
120
121         if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
122                 dprintk("could not acquire lock");
123                 return -EINVAL;
124         }
125         state->i2c_write_buffer[0] = reg;
126         state->i2c_write_buffer[1] = val >> 8;
127         state->i2c_write_buffer[2] = val & 0xff;
128
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;
134
135         if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
136                 printk(KERN_WARNING "DiB0070 I2C write failed\n");
137                 ret = -EREMOTEIO;
138         } else
139                 ret = 0;
140
141         mutex_unlock(&state->i2c_buffer_lock);
142         return ret;
143 }
144
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); \
150     } \
151 } while (0)
152
153 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
154         {
155         struct dib0070_state *state = fe->tuner_priv;
156         u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
157
158         if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
159                 tmp |= (0 << 14);
160         else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
161                 tmp |= (1 << 14);
162         else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
163                 tmp |= (2 << 14);
164         else
165                 tmp |= (3 << 14);
166
167         dib0070_write_reg(state, 0x02, tmp);
168
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);
172
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));
176
177                 dib0070_write_reg(state, 0x17, value);
178         }
179         return 0;
180 }
181
182 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
183 {
184         int8_t step_sign;
185         u16 adc;
186         int ret = 0;
187
188         if (*tune_state == CT_TUNER_STEP_0) {
189                 dib0070_write_reg(state, 0x0f, 0xed10);
190                 dib0070_write_reg(state, 0x17,    0x0034);
191
192                 dib0070_write_reg(state, 0x18, 0x0032);
193                 state->step = state->captrim = state->fcaptrim = 64;
194                 state->adc_diff = 3000;
195                 ret = 20;
196
197                 *tune_state = CT_TUNER_STEP_1;
198         } else if (*tune_state == CT_TUNER_STEP_1) {
199                 state->step /= 2;
200                 dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
201                 ret = 15;
202
203                 *tune_state = CT_TUNER_STEP_2;
204         } else if (*tune_state == CT_TUNER_STEP_2) {
205
206                 adc = dib0070_read_reg(state, 0x19);
207
208                 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
209
210                 if (adc >= 400) {
211                         adc -= 400;
212                         step_sign = -1;
213                 } else {
214                         adc = 400 - adc;
215                         step_sign = 1;
216                 }
217
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;
222                 }
223                 state->captrim += (step_sign * state->step);
224
225                 if (state->step >= 1)
226                         *tune_state = CT_TUNER_STEP_1;
227                 else
228                         *tune_state = CT_TUNER_STEP_3;
229
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;
234         }
235
236         return ret;
237 }
238
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)
240 {
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);
243
244         dprintk("CTRL_LO5: 0x%x", lo5);
245         return dib0070_write_reg(state, 0x15, lo5);
246 }
247
248 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
249 {
250         struct dib0070_state *state = fe->tuner_priv;
251
252         if (open) {
253                 dib0070_write_reg(state, 0x1b, 0xff00);
254                 dib0070_write_reg(state, 0x1a, 0x0000);
255         } else {
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);
260                 } else
261                         dib0070_write_reg(state, 0x1a, 0x0009);
262         }
263 }
264
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 */
268         u8 switch_trim;
269         u8 vco_band;
270         u8 hfdiv;
271         u8 vco_multi;
272         u8 presc;
273         u8 wbdmux;
274         u16 tuner_enable;
275 };
276
277 struct dib0070_lna_match {
278         u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
279         u8 lna_band;
280 };
281
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 */
290 };
291
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 */
301 };
302
303 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
304         {     180000, 0 }, /* VHF */
305         {     188000, 1 },
306         {     196400, 2 },
307         {     250000, 3 },
308         {     550000, 0 }, /* UHF */
309         {     590000, 1 },
310         {     666000, 3 },
311         {     864000, 5 },
312         {    1500000, 0 }, /* LBAND or everything higher than UHF */
313         {    1600000, 1 },
314         {    2000000, 3 },
315         { 0xffffffff, 7 },
316 };
317
318 static const struct dib0070_lna_match dib0070_lna[] = {
319         {     180000, 0 }, /* VHF */
320         {     188000, 1 },
321         {     196400, 2 },
322         {     250000, 3 },
323         {     550000, 2 }, /* UHF */
324         {     650000, 3 },
325         {     750000, 5 },
326         {     850000, 6 },
327         {     864000, 7 },
328         {    1500000, 0 }, /* LBAND or everything higher than UHF */
329         {    1600000, 1 },
330         {    2000000, 3 },
331         { 0xffffffff, 7 },
332 };
333
334 #define LPF     100
335 static int dib0070_tune_digital(struct dvb_frontend *fe)
336 {
337         struct dib0070_state *state = fe->tuner_priv;
338
339         const struct dib0070_tuning *tune;
340         const struct dib0070_lna_match *lna_match;
341
342         enum frontend_tune_state *tune_state = &state->tune_state;
343         int ret = 10; /* 1ms is the default delay most of the time */
344
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);
347
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))))
356                                 freq += 850;
357 #endif
358         if (state->current_rf != freq) {
359
360                 switch (state->revision) {
361                 case DIB0070S_P1A:
362                 tune = dib0070s_tuning_table;
363                 lna_match = dib0070_lna;
364                 break;
365                 default:
366                 tune = dib0070_tuning_table;
367                 if (state->cfg->flip_chip)
368                         lna_match = dib0070_lna_flip_chip;
369                 else
370                         lna_match = dib0070_lna;
371                 break;
372                 }
373                 while (freq > tune->max_freq) /* find the right one */
374                         tune++;
375                 while (freq > lna_match->max_freq) /* find the right one */
376                         lna_match++;
377
378                 state->current_tune_table_index = tune;
379                 state->lna_match = lna_match;
380         }
381
382         if (*tune_state == CT_TUNER_START) {
383                 dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
384                 if (state->current_rf != freq) {
385                         u8 REFDIV;
386                         u32 FBDiv, Rest, FREF, VCOF_kHz;
387                         u8 Den;
388
389                         state->current_rf = freq;
390                         state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
391
392
393                         dib0070_write_reg(state, 0x17, 0x30);
394
395
396                         VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
397
398                         switch (band) {
399                         case BAND_VHF:
400                                 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
401                                 break;
402                         case BAND_FM:
403                                 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
404                                 break;
405                         default:
406                                 REFDIV = (u8) (state->cfg->clock_khz  / 10000);
407                                 break;
408                         }
409                         FREF = state->cfg->clock_khz / REFDIV;
410
411
412
413                         switch (state->revision) {
414                         case DIB0070S_P1A:
415                                 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
416                                 Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
417                                 break;
418
419                         case DIB0070_P1G:
420                         case DIB0070_P1F:
421                         default:
422                                 FBDiv = (freq / (FREF / 2));
423                                 Rest  = 2 * freq - FBDiv * FREF;
424                                 break;
425                         }
426
427                         if (Rest < LPF)
428                                 Rest = 0;
429                         else if (Rest < 2 * LPF)
430                                 Rest = 2 * LPF;
431                         else if (Rest > (FREF - LPF)) {
432                                 Rest = 0;
433                                 FBDiv += 1;
434                         } else if (Rest > (FREF - 2 * LPF))
435                                 Rest = FREF - 2 * LPF;
436                         Rest = (Rest * 6528) / (FREF / 10);
437
438                         Den = 1;
439                         if (Rest > 0) {
440                                 state->lo4 |= (1 << 14) | (1 << 12);
441                                 Den = 255;
442                         }
443
444
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);
448
449                         if (state->revision == DIB0070S_P1A) {
450
451                                 if (band == BAND_SBAND) {
452                                         dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
453                                         dib0070_write_reg(state, 0x1d, 0xFFFF);
454                                 } else
455                                         dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
456                         }
457
458                         dib0070_write_reg(state, 0x20,
459                                 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
460
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);
467
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;
472                 }
473         } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
474
475                 ret = dib0070_captrim(state, tune_state);
476
477         } else if (*tune_state == CT_TUNER_STEP_4) {
478                 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
479                 if (tmp != NULL) {
480                         while (freq/1000 > tmp->freq) /* find the right one */
481                                 tmp++;
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;
487                 } else {
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;
493                 }
494
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);
500
501
502                 dib0070_write_reg(state, 0x18,   0x07ff);
503                 dib0070_write_reg(state, 0x17, 0x0033);
504
505
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;
510         } else {
511                 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
512         }
513         return ret;
514 }
515
516
517 static int dib0070_tune(struct dvb_frontend *fe)
518 {
519         struct dib0070_state *state = fe->tuner_priv;
520         uint32_t ret;
521
522         state->tune_state = CT_TUNER_START;
523
524         do {
525                 ret = dib0070_tune_digital(fe);
526                 if (ret != FE_CALLBACK_TIME_NEVER)
527                         msleep(ret/10);
528                 else
529                 break;
530         } while (state->tune_state != CT_TUNER_STOP);
531
532         return 0;
533 }
534
535 static int dib0070_wakeup(struct dvb_frontend *fe)
536 {
537         struct dib0070_state *state = fe->tuner_priv;
538         if (state->cfg->sleep)
539                 state->cfg->sleep(fe, 0);
540         return 0;
541 }
542
543 static int dib0070_sleep(struct dvb_frontend *fe)
544 {
545         struct dib0070_state *state = fe->tuner_priv;
546         if (state->cfg->sleep)
547                 state->cfg->sleep(fe, 1);
548         return 0;
549 }
550
551 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
552 {
553         struct dib0070_state *state = fe->tuner_priv;
554         return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
555 }
556 EXPORT_SYMBOL(dib0070_get_rf_output);
557
558 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
559 {
560         struct dib0070_state *state = fe->tuner_priv;
561         u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
562         if (no > 3)
563                 no = 3;
564         if (no < 1)
565                 no = 1;
566         return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
567 }
568 EXPORT_SYMBOL(dib0070_set_rf_output);
569
570 static const u16 dib0070_p1f_defaults[] =
571
572 {
573         7, 0x02,
574                 0x0008,
575                 0x0000,
576                 0x0000,
577                 0x0000,
578                 0x0000,
579                 0x0002,
580                 0x0100,
581
582         3, 0x0d,
583                 0x0d80,
584                 0x0001,
585                 0x0000,
586
587         4, 0x11,
588                 0x0000,
589                 0x0103,
590                 0x0000,
591                 0x0000,
592
593         3, 0x16,
594                 0x0004 | 0x0040,
595                 0x0030,
596                 0x07ff,
597
598         6, 0x1b,
599                 0x4112,
600                 0xff00,
601                 0xc07f,
602                 0x0000,
603                 0x0180,
604                 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
605
606         0,
607 };
608
609 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
610 {
611         u16 tuner_en = dib0070_read_reg(state, 0x20);
612         u16 offset;
613
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));
617         msleep(9);
618         offset = dib0070_read_reg(state, 0x19);
619         dib0070_write_reg(state, 0x20, tuner_en);
620         return offset;
621 }
622
623 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
624 {
625         u8 gain;
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]);
629         }
630 }
631
632 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
633 {
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;
637
638         if (tmp != NULL) {
639                 while (freq/1000 > tmp->freq) /* find the right one */
640                         tmp++;
641                 state->wbd_gain_current = tmp->wbd_gain_val;
642         } else
643                 state->wbd_gain_current = 6;
644
645         return state->wbd_offset_3_3[state->wbd_gain_current - 6];
646 }
647 EXPORT_SYMBOL(dib0070_wbd_offset);
648
649 #define pgm_read_word(w) (*w)
650 static int dib0070_reset(struct dvb_frontend *fe)
651 {
652         struct dib0070_state *state = fe->tuner_priv;
653         u16 l, r, *n;
654
655         HARD_RESET(state);
656
657
658 #ifndef FORCE_SBAND_TUNER
659         if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
660                 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
661         else
662 #else
663 #warning forcing SBAND
664 #endif
665         state->revision = DIB0070S_P1A;
666
667         /* P1F or not */
668         dprintk("Revision: %x", state->revision);
669
670         if (state->revision == DIB0070_P1D) {
671                 dprintk("Error: this driver is not to be used meant for P1D or earlier");
672                 return -EINVAL;
673         }
674
675         n = (u16 *) dib0070_p1f_defaults;
676         l = pgm_read_word(n++);
677         while (l) {
678                 r = pgm_read_word(n++);
679                 do {
680                         dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
681                         r++;
682                 } while (--l);
683                 l = pgm_read_word(n++);
684         }
685
686         if (state->cfg->force_crystal_mode != 0)
687                 r = state->cfg->force_crystal_mode;
688         else if (state->cfg->clock_khz >= 24000)
689                 r = 1;
690         else
691                 r = 2;
692
693
694         r |= state->cfg->osc_buffer_state << 3;
695
696         dib0070_write_reg(state, 0x10, r);
697         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
698
699         if (state->cfg->invert_iq) {
700                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
701                 dib0070_write_reg(state, 0x02, r | (1 << 5));
702         }
703
704         if (state->revision == DIB0070S_P1A)
705                 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
706         else
707                 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
708                                      state->cfg->enable_third_order_filter);
709
710         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
711
712         dib0070_wbd_offset_calibration(state);
713
714         return 0;
715 }
716
717 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
718 {
719         struct dib0070_state *state = fe->tuner_priv;
720
721         *frequency = 1000 * state->current_rf;
722         return 0;
723 }
724
725 static int dib0070_release(struct dvb_frontend *fe)
726 {
727         kfree(fe->tuner_priv);
728         fe->tuner_priv = NULL;
729         return 0;
730 }
731
732 static const struct dvb_tuner_ops dib0070_ops = {
733         .info = {
734                 .name           = "DiBcom DiB0070",
735                 .frequency_min  =  45000000,
736                 .frequency_max  = 860000000,
737                 .frequency_step =      1000,
738         },
739         .release       = dib0070_release,
740
741         .init          = dib0070_wakeup,
742         .sleep         = dib0070_sleep,
743         .set_params    = dib0070_tune,
744
745         .get_frequency = dib0070_get_frequency,
746 //      .get_bandwidth = dib0070_get_bandwidth
747 };
748
749 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
750 {
751         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
752         if (state == NULL)
753                 return NULL;
754
755         state->cfg = cfg;
756         state->i2c = i2c;
757         state->fe  = fe;
758         mutex_init(&state->i2c_buffer_lock);
759         fe->tuner_priv = state;
760
761         if (dib0070_reset(fe) != 0)
762                 goto free_mem;
763
764         printk(KERN_INFO "DiB0070: successfully identified\n");
765         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
766
767         fe->tuner_priv = state;
768         return fe;
769
770 free_mem:
771         kfree(state);
772         fe->tuner_priv = NULL;
773         return NULL;
774 }
775 EXPORT_SYMBOL(dib0070_attach);
776
777 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
778 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
779 MODULE_LICENSE("GPL");