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