Merge branch 'fix/pcm-hwptr' into for-linus
[linux/fpc-iii.git] / drivers / media / dvb / frontends / dib0070.c
blobfe895bf7b18fbc686a7d4114d2e506bbf3b9bbe6
1 /*
2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
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, version 2.
9 */
10 #include <linux/kernel.h>
11 #include <linux/i2c.h>
13 #include "dvb_frontend.h"
15 #include "dib0070.h"
16 #include "dibx000_common.h"
18 static int debug;
19 module_param(debug, int, 0644);
20 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
22 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0)
24 #define DIB0070_P1D 0x00
25 #define DIB0070_P1F 0x01
26 #define DIB0070_P1G 0x03
27 #define DIB0070S_P1A 0x02
29 struct dib0070_state {
30 struct i2c_adapter *i2c;
31 struct dvb_frontend *fe;
32 const struct dib0070_config *cfg;
33 u16 wbd_ff_offset;
34 u8 revision;
37 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
39 u8 b[2];
40 struct i2c_msg msg[2] = {
41 { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
42 { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
44 if (i2c_transfer(state->i2c, msg, 2) != 2) {
45 printk(KERN_WARNING "DiB0070 I2C read failed\n");
46 return 0;
48 return (b[0] << 8) | b[1];
51 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
53 u8 b[3] = { reg, val >> 8, val & 0xff };
54 struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
55 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
56 printk(KERN_WARNING "DiB0070 I2C write failed\n");
57 return -EREMOTEIO;
59 return 0;
62 #define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0)
64 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
66 struct dib0070_state *st = fe->tuner_priv;
67 u16 tmp = 0;
68 tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
70 switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) {
71 case 8000:
72 tmp |= (0 << 14);
73 break;
74 case 7000:
75 tmp |= (1 << 14);
76 break;
77 case 6000:
78 tmp |= (2 << 14);
79 break;
80 case 5000:
81 default:
82 tmp |= (3 << 14);
83 break;
85 dib0070_write_reg(st, 0x02, tmp);
86 return 0;
89 static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
91 int8_t captrim, fcaptrim, step_sign, step;
92 u16 adc, adc_diff = 3000;
96 dib0070_write_reg(st, 0x0f, 0xed10);
97 dib0070_write_reg(st, 0x17, 0x0034);
99 dib0070_write_reg(st, 0x18, 0x0032);
100 msleep(2);
102 step = captrim = fcaptrim = 64;
104 do {
105 step /= 2;
106 dib0070_write_reg(st, 0x14, LO4 | captrim);
107 msleep(1);
108 adc = dib0070_read_reg(st, 0x19);
110 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024);
112 if (adc >= 400) {
113 adc -= 400;
114 step_sign = -1;
115 } else {
116 adc = 400 - adc;
117 step_sign = 1;
120 if (adc < adc_diff) {
121 dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff);
122 adc_diff = adc;
123 fcaptrim = captrim;
128 captrim += (step_sign * step);
129 } while (step >= 1);
131 dib0070_write_reg(st, 0x14, LO4 | fcaptrim);
132 dib0070_write_reg(st, 0x18, 0x07ff);
135 #define LPF 100 // define for the loop filter 100kHz by default 16-07-06
136 #define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7)
137 #define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12)
138 #define LO4_SET_CTRIM(l, c) l |= (c) << 10
139 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
141 struct dib0070_state *st = fe->tuner_priv;
142 u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf);
144 u8 band = BAND_OF_FREQUENCY(freq), c;
146 /*******************VCO***********************************/
147 u16 lo4 = 0;
149 u8 REFDIV, PRESC = 2;
150 u32 FBDiv, Rest, FREF, VCOF_kHz;
151 u16 Num, Den;
152 /*******************FrontEnd******************************/
153 u16 value = 0;
155 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
158 dib0070_write_reg(st, 0x17, 0x30);
160 dib0070_set_bandwidth(fe, ch); /* c is used as HF */
161 switch (st->revision) {
162 case DIB0070S_P1A:
163 switch (band) {
164 case BAND_LBAND:
165 LO4_SET_VCO_HFDIV(lo4, 1, 1);
166 c = 2;
167 break;
168 case BAND_SBAND:
169 LO4_SET_VCO_HFDIV(lo4, 0, 0);
170 LO4_SET_CTRIM(lo4, 1);;
171 c = 1;
172 break;
173 case BAND_UHF:
174 default:
175 if (freq < 570000) {
176 LO4_SET_VCO_HFDIV(lo4, 1, 3);
177 PRESC = 6; c = 6;
178 } else if (freq < 680000) {
179 LO4_SET_VCO_HFDIV(lo4, 0, 2);
180 c = 4;
181 } else {
182 LO4_SET_VCO_HFDIV(lo4, 1, 2);
183 c = 4;
185 break;
186 } break;
188 case DIB0070_P1G:
189 case DIB0070_P1F:
190 default:
191 switch (band) {
192 case BAND_FM:
193 LO4_SET_VCO_HFDIV(lo4, 0, 7);
194 c = 24;
195 break;
196 case BAND_LBAND:
197 LO4_SET_VCO_HFDIV(lo4, 1, 0);
198 c = 2;
199 break;
200 case BAND_VHF:
201 if (freq < 180000) {
202 LO4_SET_VCO_HFDIV(lo4, 0, 3);
203 c = 16;
204 } else if (freq < 190000) {
205 LO4_SET_VCO_HFDIV(lo4, 1, 3);
206 c = 16;
207 } else {
208 LO4_SET_VCO_HFDIV(lo4, 0, 6);
209 c = 12;
211 break;
213 case BAND_UHF:
214 default:
215 if (freq < 570000) {
216 LO4_SET_VCO_HFDIV(lo4, 1, 5);
217 c = 6;
218 } else if (freq < 700000) {
219 LO4_SET_VCO_HFDIV(lo4, 0, 1);
220 c = 4;
221 } else {
222 LO4_SET_VCO_HFDIV(lo4, 1, 1);
223 c = 4;
225 break;
227 break;
230 dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf);
231 dprintk( "VCO = %hd", (lo4 >> 11) & 0x3);
234 VCOF_kHz = (c * freq) * 2;
235 dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq);
237 switch (band) {
238 case BAND_VHF:
239 REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
240 break;
241 case BAND_FM:
242 REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
243 break;
244 default:
245 REFDIV = (u8) ( st->cfg->clock_khz / 10000);
246 break;
248 FREF = st->cfg->clock_khz / REFDIV;
250 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
254 switch (st->revision) {
255 case DIB0070S_P1A:
256 FBDiv = (VCOF_kHz / PRESC / FREF);
257 Rest = (VCOF_kHz / PRESC) - FBDiv * FREF;
258 break;
260 case DIB0070_P1G:
261 case DIB0070_P1F:
262 default:
263 FBDiv = (freq / (FREF / 2));
264 Rest = 2 * freq - FBDiv * FREF;
265 break;
269 if (Rest < LPF) Rest = 0;
270 else if (Rest < 2 * LPF) Rest = 2 * LPF;
271 else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
272 else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
273 Rest = (Rest * 6528) / (FREF / 10);
274 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
276 Num = 0;
277 Den = 1;
279 if (Rest > 0) {
280 LO4_SET_SD(lo4, 1);
281 Den = 255;
282 Num = (u16)Rest;
284 dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
288 dib0070_write_reg(st, 0x11, (u16)FBDiv);
291 dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
294 dib0070_write_reg(st, 0x13, Num);
297 value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
299 switch (band) {
300 case BAND_UHF: value |= 0x4000 | 0x0800; break;
301 case BAND_LBAND: value |= 0x2000 | 0x0400; break;
302 default: value |= 0x8000 | 0x1000; break;
304 dib0070_write_reg(st, 0x20, value);
306 dib0070_captrim(st, lo4);
307 if (st->revision == DIB0070S_P1A) {
308 if (band == BAND_SBAND)
309 dib0070_write_reg(st, 0x15, 0x16e2);
310 else
311 dib0070_write_reg(st, 0x15, 0x56e5);
316 switch (band) {
317 case BAND_UHF: value = 0x7c82; break;
318 case BAND_LBAND: value = 0x7c84; break;
319 default: value = 0x7c81; break;
321 dib0070_write_reg(st, 0x0f, value);
322 dib0070_write_reg(st, 0x06, 0x3fff);
324 /* Front End */
325 /* c == TUNE, value = SWITCH */
326 c = 0;
327 value = 0;
328 switch (band) {
329 case BAND_FM:
330 c = 0; value = 1;
331 break;
333 case BAND_VHF:
334 if (freq <= 180000) c = 0;
335 else if (freq <= 188200) c = 1;
336 else if (freq <= 196400) c = 2;
337 else c = 3;
338 value = 1;
339 break;
341 case BAND_LBAND:
342 if (freq <= 1500000) c = 0;
343 else if (freq <= 1600000) c = 1;
344 else c = 3;
345 break;
347 case BAND_SBAND:
348 c = 7;
349 dib0070_write_reg(st, 0x1d,0xFFFF);
350 break;
352 case BAND_UHF:
353 default:
354 if (st->cfg->flip_chip) {
355 if (freq <= 550000) c = 0;
356 else if (freq <= 590000) c = 1;
357 else if (freq <= 666000) c = 3;
358 else c = 5;
359 } else {
360 if (freq <= 550000) c = 2;
361 else if (freq <= 650000) c = 3;
362 else if (freq <= 750000) c = 5;
363 else if (freq <= 850000) c = 6;
364 else c = 7;
366 value = 2;
367 break;
370 /* default: LNA_MATCH=7, BIAS=3 */
371 dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0));
372 dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127));
373 dib0070_write_reg(st, 0x0d, 0x0d80);
376 dib0070_write_reg(st, 0x18, 0x07ff);
377 dib0070_write_reg(st, 0x17, 0x0033);
379 return 0;
382 static int dib0070_wakeup(struct dvb_frontend *fe)
384 struct dib0070_state *st = fe->tuner_priv;
385 if (st->cfg->sleep)
386 st->cfg->sleep(fe, 0);
387 return 0;
390 static int dib0070_sleep(struct dvb_frontend *fe)
392 struct dib0070_state *st = fe->tuner_priv;
393 if (st->cfg->sleep)
394 st->cfg->sleep(fe, 1);
395 return 0;
398 static u16 dib0070_p1f_defaults[] =
401 7, 0x02,
402 0x0008,
403 0x0000,
404 0x0000,
405 0x0000,
406 0x0000,
407 0x0002,
408 0x0100,
410 3, 0x0d,
411 0x0d80,
412 0x0001,
413 0x0000,
415 4, 0x11,
416 0x0000,
417 0x0103,
418 0x0000,
419 0x0000,
421 3, 0x16,
422 0x0004 | 0x0040,
423 0x0030,
424 0x07ff,
426 6, 0x1b,
427 0x4112,
428 0xff00,
429 0xc07f,
430 0x0000,
431 0x0180,
432 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
437 static void dib0070_wbd_calibration(struct dvb_frontend *fe)
439 u16 wbd_offs;
440 struct dib0070_state *state = fe->tuner_priv;
442 if (state->cfg->sleep)
443 state->cfg->sleep(fe, 0);
445 dib0070_write_reg(state, 0x0f, 0x6d81);
446 dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
447 msleep(9);
448 wbd_offs = dib0070_read_reg(state, 0x19);
449 dib0070_write_reg(state, 0x20, 0);
450 state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
451 dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
453 if (state->cfg->sleep)
454 state->cfg->sleep(fe, 1);
458 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
460 struct dib0070_state *st = fe->tuner_priv;
461 return st->wbd_ff_offset;
464 EXPORT_SYMBOL(dib0070_wbd_offset);
465 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)
467 struct dib0070_state *state = fe->tuner_priv;
468 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
469 dprintk( "CTRL_LO5: 0x%x", lo5);
470 return dib0070_write_reg(state, 0x15, lo5);
473 #define pgm_read_word(w) (*w)
474 static int dib0070_reset(struct dib0070_state *state)
476 u16 l, r, *n;
478 HARD_RESET(state);
481 #ifndef FORCE_SBAND_TUNER
482 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
483 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
484 else
485 #endif
486 state->revision = DIB0070S_P1A;
488 /* P1F or not */
489 dprintk( "Revision: %x", state->revision);
491 if (state->revision == DIB0070_P1D) {
492 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
493 return -EINVAL;
496 n = (u16 *) dib0070_p1f_defaults;
497 l = pgm_read_word(n++);
498 while (l) {
499 r = pgm_read_word(n++);
500 do {
501 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
502 r++;
503 } while (--l);
504 l = pgm_read_word(n++);
507 if (state->cfg->force_crystal_mode != 0)
508 r = state->cfg->force_crystal_mode;
509 else if (state->cfg->clock_khz >= 24000)
510 r = 1;
511 else
512 r = 2;
514 r |= state->cfg->osc_buffer_state << 3;
516 dib0070_write_reg(state, 0x10, r);
517 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
519 if (state->cfg->invert_iq) {
520 r = dib0070_read_reg(state, 0x02) & 0xffdf;
521 dib0070_write_reg(state, 0x02, r | (1 << 5));
525 if (state->revision == DIB0070S_P1A)
526 dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1);
527 else
528 dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
530 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
531 return 0;
535 static int dib0070_release(struct dvb_frontend *fe)
537 kfree(fe->tuner_priv);
538 fe->tuner_priv = NULL;
539 return 0;
542 static struct dvb_tuner_ops dib0070_ops = {
543 .info = {
544 .name = "DiBcom DiB0070",
545 .frequency_min = 45000000,
546 .frequency_max = 860000000,
547 .frequency_step = 1000,
549 .release = dib0070_release,
551 .init = dib0070_wakeup,
552 .sleep = dib0070_sleep,
553 .set_params = dib0070_tune_digital,
554 // .get_frequency = dib0070_get_frequency,
555 // .get_bandwidth = dib0070_get_bandwidth
558 struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
560 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
561 if (state == NULL)
562 return NULL;
564 state->cfg = cfg;
565 state->i2c = i2c;
566 state->fe = fe;
567 fe->tuner_priv = state;
569 if (dib0070_reset(state) != 0)
570 goto free_mem;
572 dib0070_wbd_calibration(fe);
574 printk(KERN_INFO "DiB0070: successfully identified\n");
575 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
577 fe->tuner_priv = state;
578 return fe;
580 free_mem:
581 kfree(state);
582 fe->tuner_priv = NULL;
583 return NULL;
585 EXPORT_SYMBOL(dib0070_attach);
587 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
588 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
589 MODULE_LICENSE("GPL");