Merge tag 'docs-5.15' of git://git.lwn.net/linux
[linux-2.6-microblaze.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=%d; ADC = %hd (ADC) & %dmV\n", state->captrim,
193                         adc, (u32)adc * (u32)1800 / (u32)1024);
194
195                 if (adc >= 400) {
196                         adc -= 400;
197                         step_sign = -1;
198                 } else {
199                         adc = 400 - adc;
200                         step_sign = 1;
201                 }
202
203                 if (adc < state->adc_diff) {
204                         dprintk("CAPTRIM=%d is closer to target (%hd/%hd)\n",
205                                 state->captrim, adc, state->adc_diff);
206                         state->adc_diff = adc;
207                         state->fcaptrim = state->captrim;
208                 }
209                 state->captrim += (step_sign * state->step);
210
211                 if (state->step >= 1)
212                         *tune_state = CT_TUNER_STEP_1;
213                 else
214                         *tune_state = CT_TUNER_STEP_3;
215
216         } else if (*tune_state == CT_TUNER_STEP_3) {
217                 dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
218                 dib0070_write_reg(state, 0x18, 0x07ff);
219                 *tune_state = CT_TUNER_STEP_4;
220         }
221
222         return ret;
223 }
224
225 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)
226 {
227         struct dib0070_state *state = fe->tuner_priv;
228         u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
229
230         dprintk("CTRL_LO5: 0x%x\n", lo5);
231         return dib0070_write_reg(state, 0x15, lo5);
232 }
233
234 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
235 {
236         struct dib0070_state *state = fe->tuner_priv;
237
238         if (open) {
239                 dib0070_write_reg(state, 0x1b, 0xff00);
240                 dib0070_write_reg(state, 0x1a, 0x0000);
241         } else {
242                 dib0070_write_reg(state, 0x1b, 0x4112);
243                 if (state->cfg->vga_filter != 0) {
244                         dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
245                         dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
246                 } else
247                         dib0070_write_reg(state, 0x1a, 0x0009);
248         }
249 }
250
251 EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
252 struct dib0070_tuning {
253         u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
254         u8 switch_trim;
255         u8 vco_band;
256         u8 hfdiv;
257         u8 vco_multi;
258         u8 presc;
259         u8 wbdmux;
260         u16 tuner_enable;
261 };
262
263 struct dib0070_lna_match {
264         u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
265         u8 lna_band;
266 };
267
268 static const struct dib0070_tuning dib0070s_tuning_table[] = {
269         {     570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
270         {     700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
271         {     863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
272         {    1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
273         {    1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
274         {    2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
275         { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
276 };
277
278 static const struct dib0070_tuning dib0070_tuning_table[] = {
279         {     115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
280         {     179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
281         {     189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
282         {     250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
283         {     569999, 2, 1, 5,  6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
284         {     699999, 2, 0, 1,  4, 2, 2, 0x4000 | 0x0800 },
285         {     863999, 2, 1, 1,  4, 2, 2, 0x4000 | 0x0800 },
286         { 0xffffffff, 0, 1, 0,  2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
287 };
288
289 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
290         {     180000, 0 }, /* VHF */
291         {     188000, 1 },
292         {     196400, 2 },
293         {     250000, 3 },
294         {     550000, 0 }, /* UHF */
295         {     590000, 1 },
296         {     666000, 3 },
297         {     864000, 5 },
298         {    1500000, 0 }, /* LBAND or everything higher than UHF */
299         {    1600000, 1 },
300         {    2000000, 3 },
301         { 0xffffffff, 7 },
302 };
303
304 static const struct dib0070_lna_match dib0070_lna[] = {
305         {     180000, 0 }, /* VHF */
306         {     188000, 1 },
307         {     196400, 2 },
308         {     250000, 3 },
309         {     550000, 2 }, /* UHF */
310         {     650000, 3 },
311         {     750000, 5 },
312         {     850000, 6 },
313         {     864000, 7 },
314         {    1500000, 0 }, /* LBAND or everything higher than UHF */
315         {    1600000, 1 },
316         {    2000000, 3 },
317         { 0xffffffff, 7 },
318 };
319
320 #define LPF     100
321 static int dib0070_tune_digital(struct dvb_frontend *fe)
322 {
323         struct dib0070_state *state = fe->tuner_priv;
324
325         const struct dib0070_tuning *tune;
326         const struct dib0070_lna_match *lna_match;
327
328         enum frontend_tune_state *tune_state = &state->tune_state;
329         int ret = 10; /* 1ms is the default delay most of the time */
330
331         u8  band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
332         u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
333
334 #ifdef CONFIG_SYS_ISDBT
335         if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
336                         if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
337                         && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
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)))
340                         || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
341                                 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
342                                 freq += 850;
343 #endif
344         if (state->current_rf != freq) {
345
346                 switch (state->revision) {
347                 case DIB0070S_P1A:
348                 tune = dib0070s_tuning_table;
349                 lna_match = dib0070_lna;
350                 break;
351                 default:
352                 tune = dib0070_tuning_table;
353                 if (state->cfg->flip_chip)
354                         lna_match = dib0070_lna_flip_chip;
355                 else
356                         lna_match = dib0070_lna;
357                 break;
358                 }
359                 while (freq > tune->max_freq) /* find the right one */
360                         tune++;
361                 while (freq > lna_match->max_freq) /* find the right one */
362                         lna_match++;
363
364                 state->current_tune_table_index = tune;
365                 state->lna_match = lna_match;
366         }
367
368         if (*tune_state == CT_TUNER_START) {
369                 dprintk("Tuning for Band: %d (%d kHz)\n", band, freq);
370                 if (state->current_rf != freq) {
371                         u8 REFDIV;
372                         u32 FBDiv, Rest, FREF, VCOF_kHz;
373                         u8 Den;
374
375                         state->current_rf = freq;
376                         state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
377
378
379                         dib0070_write_reg(state, 0x17, 0x30);
380
381
382                         VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
383
384                         switch (band) {
385                         case BAND_VHF:
386                                 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
387                                 break;
388                         case BAND_FM:
389                                 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
390                                 break;
391                         default:
392                                 REFDIV = (u8) (state->cfg->clock_khz  / 10000);
393                                 break;
394                         }
395                         FREF = state->cfg->clock_khz / REFDIV;
396
397
398
399                         switch (state->revision) {
400                         case DIB0070S_P1A:
401                                 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
402                                 Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
403                                 break;
404
405                         case DIB0070_P1G:
406                         case DIB0070_P1F:
407                         default:
408                                 FBDiv = (freq / (FREF / 2));
409                                 Rest  = 2 * freq - FBDiv * FREF;
410                                 break;
411                         }
412
413                         if (Rest < LPF)
414                                 Rest = 0;
415                         else if (Rest < 2 * LPF)
416                                 Rest = 2 * LPF;
417                         else if (Rest > (FREF - LPF)) {
418                                 Rest = 0;
419                                 FBDiv += 1;
420                         } else if (Rest > (FREF - 2 * LPF))
421                                 Rest = FREF - 2 * LPF;
422                         Rest = (Rest * 6528) / (FREF / 10);
423
424                         Den = 1;
425                         if (Rest > 0) {
426                                 state->lo4 |= (1 << 14) | (1 << 12);
427                                 Den = 255;
428                         }
429
430
431                         dib0070_write_reg(state, 0x11, (u16)FBDiv);
432                         dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
433                         dib0070_write_reg(state, 0x13, (u16) Rest);
434
435                         if (state->revision == DIB0070S_P1A) {
436
437                                 if (band == BAND_SBAND) {
438                                         dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
439                                         dib0070_write_reg(state, 0x1d, 0xFFFF);
440                                 } else
441                                         dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
442                         }
443
444                         dib0070_write_reg(state, 0x20,
445                                 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
446
447                         dprintk("REFDIV: %u, FREF: %d\n", REFDIV, FREF);
448                         dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
449                         dprintk("Num: %u, Den: %u, SD: %d\n", (u16)Rest, Den,
450                                 (state->lo4 >> 12) & 0x1);
451                         dprintk("HFDIV code: %u\n",
452                                 state->current_tune_table_index->hfdiv);
453                         dprintk("VCO = %u\n",
454                                 state->current_tune_table_index->vco_band);
455                         dprintk("VCOF: ((%u*%d) << 1))\n",
456                                 state->current_tune_table_index->vco_multi,
457                                 freq);
458
459                         *tune_state = CT_TUNER_STEP_0;
460                 } else { /* we are already tuned to this frequency - the configuration is correct  */
461                         ret = 50; /* wakeup time */
462                         *tune_state = CT_TUNER_STEP_5;
463                 }
464         } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
465
466                 ret = dib0070_captrim(state, tune_state);
467
468         } else if (*tune_state == CT_TUNER_STEP_4) {
469                 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
470                 if (tmp != NULL) {
471                         while (freq/1000 > tmp->freq) /* find the right one */
472                                 tmp++;
473                         dib0070_write_reg(state, 0x0f,
474                                 (0 << 15) | (1 << 14) | (3 << 12)
475                                 | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
476                                 | (state->current_tune_table_index->wbdmux << 0));
477                         state->wbd_gain_current = tmp->wbd_gain_val;
478                 } else {
479                         dib0070_write_reg(state, 0x0f,
480                                           (0 << 15) | (1 << 14) | (3 << 12)
481                                           | (6 << 9) | (0 << 8) | (1 << 7)
482                                           | (state->current_tune_table_index->wbdmux << 0));
483                         state->wbd_gain_current = 6;
484                 }
485
486                 dib0070_write_reg(state, 0x06, 0x3fff);
487                 dib0070_write_reg(state, 0x07,
488                                   (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
489                 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
490                 dib0070_write_reg(state, 0x0d, 0x0d80);
491
492
493                 dib0070_write_reg(state, 0x18,   0x07ff);
494                 dib0070_write_reg(state, 0x17, 0x0033);
495
496
497                 *tune_state = CT_TUNER_STEP_5;
498         } else if (*tune_state == CT_TUNER_STEP_5) {
499                 dib0070_set_bandwidth(fe);
500                 *tune_state = CT_TUNER_STOP;
501         } else {
502                 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
503         }
504         return ret;
505 }
506
507
508 static int dib0070_tune(struct dvb_frontend *fe)
509 {
510         struct dib0070_state *state = fe->tuner_priv;
511         uint32_t ret;
512
513         state->tune_state = CT_TUNER_START;
514
515         do {
516                 ret = dib0070_tune_digital(fe);
517                 if (ret != FE_CALLBACK_TIME_NEVER)
518                         msleep(ret/10);
519                 else
520                 break;
521         } while (state->tune_state != CT_TUNER_STOP);
522
523         return 0;
524 }
525
526 static int dib0070_wakeup(struct dvb_frontend *fe)
527 {
528         struct dib0070_state *state = fe->tuner_priv;
529         if (state->cfg->sleep)
530                 state->cfg->sleep(fe, 0);
531         return 0;
532 }
533
534 static int dib0070_sleep(struct dvb_frontend *fe)
535 {
536         struct dib0070_state *state = fe->tuner_priv;
537         if (state->cfg->sleep)
538                 state->cfg->sleep(fe, 1);
539         return 0;
540 }
541
542 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
543 {
544         struct dib0070_state *state = fe->tuner_priv;
545         return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
546 }
547 EXPORT_SYMBOL(dib0070_get_rf_output);
548
549 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
550 {
551         struct dib0070_state *state = fe->tuner_priv;
552         u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
553         if (no > 3)
554                 no = 3;
555         if (no < 1)
556                 no = 1;
557         return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
558 }
559 EXPORT_SYMBOL(dib0070_set_rf_output);
560
561 static const u16 dib0070_p1f_defaults[] =
562
563 {
564         7, 0x02,
565                 0x0008,
566                 0x0000,
567                 0x0000,
568                 0x0000,
569                 0x0000,
570                 0x0002,
571                 0x0100,
572
573         3, 0x0d,
574                 0x0d80,
575                 0x0001,
576                 0x0000,
577
578         4, 0x11,
579                 0x0000,
580                 0x0103,
581                 0x0000,
582                 0x0000,
583
584         3, 0x16,
585                 0x0004 | 0x0040,
586                 0x0030,
587                 0x07ff,
588
589         6, 0x1b,
590                 0x4112,
591                 0xff00,
592                 0xc07f,
593                 0x0000,
594                 0x0180,
595                 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
596
597         0,
598 };
599
600 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
601 {
602         u16 tuner_en = dib0070_read_reg(state, 0x20);
603         u16 offset;
604
605         dib0070_write_reg(state, 0x18, 0x07ff);
606         dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
607         dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
608         msleep(9);
609         offset = dib0070_read_reg(state, 0x19);
610         dib0070_write_reg(state, 0x20, tuner_en);
611         return offset;
612 }
613
614 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
615 {
616         u8 gain;
617         for (gain = 6; gain < 8; gain++) {
618                 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
619                 dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
620         }
621 }
622
623 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
624 {
625         struct dib0070_state *state = fe->tuner_priv;
626         const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
627         u32 freq = fe->dtv_property_cache.frequency/1000;
628
629         if (tmp != NULL) {
630                 while (freq/1000 > tmp->freq) /* find the right one */
631                         tmp++;
632                 state->wbd_gain_current = tmp->wbd_gain_val;
633         } else
634                 state->wbd_gain_current = 6;
635
636         return state->wbd_offset_3_3[state->wbd_gain_current - 6];
637 }
638 EXPORT_SYMBOL(dib0070_wbd_offset);
639
640 #define pgm_read_word(w) (*w)
641 static int dib0070_reset(struct dvb_frontend *fe)
642 {
643         struct dib0070_state *state = fe->tuner_priv;
644         u16 l, r, *n;
645
646         HARD_RESET(state);
647
648
649 #ifndef FORCE_SBAND_TUNER
650         if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
651                 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
652         else
653 #else
654 #warning forcing SBAND
655 #endif
656         state->revision = DIB0070S_P1A;
657
658         /* P1F or not */
659         dprintk("Revision: %x\n", state->revision);
660
661         if (state->revision == DIB0070_P1D) {
662                 dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
663                 return -EINVAL;
664         }
665
666         n = (u16 *) dib0070_p1f_defaults;
667         l = pgm_read_word(n++);
668         while (l) {
669                 r = pgm_read_word(n++);
670                 do {
671                         dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
672                         r++;
673                 } while (--l);
674                 l = pgm_read_word(n++);
675         }
676
677         if (state->cfg->force_crystal_mode != 0)
678                 r = state->cfg->force_crystal_mode;
679         else if (state->cfg->clock_khz >= 24000)
680                 r = 1;
681         else
682                 r = 2;
683
684
685         r |= state->cfg->osc_buffer_state << 3;
686
687         dib0070_write_reg(state, 0x10, r);
688         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
689
690         if (state->cfg->invert_iq) {
691                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
692                 dib0070_write_reg(state, 0x02, r | (1 << 5));
693         }
694
695         if (state->revision == DIB0070S_P1A)
696                 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
697         else
698                 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
699                                      state->cfg->enable_third_order_filter);
700
701         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
702
703         dib0070_wbd_offset_calibration(state);
704
705         return 0;
706 }
707
708 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
709 {
710         struct dib0070_state *state = fe->tuner_priv;
711
712         *frequency = 1000 * state->current_rf;
713         return 0;
714 }
715
716 static void dib0070_release(struct dvb_frontend *fe)
717 {
718         kfree(fe->tuner_priv);
719         fe->tuner_priv = NULL;
720 }
721
722 static const struct dvb_tuner_ops dib0070_ops = {
723         .info = {
724                 .name              = "DiBcom DiB0070",
725                 .frequency_min_hz  =  45 * MHz,
726                 .frequency_max_hz  = 860 * MHz,
727                 .frequency_step_hz =   1 * kHz,
728         },
729         .release       = dib0070_release,
730
731         .init          = dib0070_wakeup,
732         .sleep         = dib0070_sleep,
733         .set_params    = dib0070_tune,
734
735         .get_frequency = dib0070_get_frequency,
736 //      .get_bandwidth = dib0070_get_bandwidth
737 };
738
739 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
740 {
741         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
742         if (state == NULL)
743                 return NULL;
744
745         state->cfg = cfg;
746         state->i2c = i2c;
747         state->fe  = fe;
748         mutex_init(&state->i2c_buffer_lock);
749         fe->tuner_priv = state;
750
751         if (dib0070_reset(fe) != 0)
752                 goto free_mem;
753
754         pr_info("DiB0070: successfully identified\n");
755         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
756
757         fe->tuner_priv = state;
758         return fe;
759
760 free_mem:
761         kfree(state);
762         fe->tuner_priv = NULL;
763         return NULL;
764 }
765 EXPORT_SYMBOL(dib0070_attach);
766
767 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
768 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
769 MODULE_LICENSE("GPL");