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