]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/dvb-frontends/dib0070.c
Merge tag 'media/v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[mirror_ubuntu-artful-kernel.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 "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");