- Update to 2.6.25-rc3.
[linux-flexiantxendom0-3.2.10.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-7 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, version 2.
9  */
10 #include <linux/kernel.h>
11 #include <linux/i2c.h>
12
13 #include "dvb_frontend.h"
14
15 #include "dib0070.h"
16 #include "dibx000_common.h"
17
18 static int debug;
19 module_param(debug, int, 0644);
20 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
21
22 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0)
23
24 #define DIB0070_P1D  0x00
25 #define DIB0070_P1F  0x01
26 #define DIB0070_P1G  0x03
27 #define DIB0070S_P1A 0x02
28
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;
35 };
36
37 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
38 {
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 },
43         };
44         if (i2c_transfer(state->i2c, msg, 2) != 2) {
45                 printk(KERN_WARNING "DiB0070 I2C read failed\n");
46                 return 0;
47         }
48         return (b[0] << 8) | b[1];
49 }
50
51 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
52 {
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;
58         }
59         return 0;
60 }
61
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)
63
64 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
65 {
66         struct dib0070_state *st = fe->tuner_priv;
67         u16 tmp = 0;
68         tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
69
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;
84         }
85         dib0070_write_reg(st, 0x02, tmp);
86         return 0;
87 }
88
89 static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
90 {
91         int8_t captrim, fcaptrim, step_sign, step;
92         u16 adc, adc_diff = 3000;
93
94
95
96         dib0070_write_reg(st, 0x0f, 0xed10);
97         dib0070_write_reg(st, 0x17,    0x0034);
98
99         dib0070_write_reg(st, 0x18, 0x0032);
100         msleep(2);
101
102         step = captrim = fcaptrim = 64;
103
104         do {
105                 step /= 2;
106                 dib0070_write_reg(st, 0x14, LO4 | captrim);
107                 msleep(1);
108                 adc = dib0070_read_reg(st, 0x19);
109
110                 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024);
111
112                 if (adc >= 400) {
113                         adc -= 400;
114                         step_sign = -1;
115                 } else {
116                         adc = 400 - adc;
117                         step_sign = 1;
118                 }
119
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;
124
125
126
127                 }
128                 captrim += (step_sign * step);
129         } while (step >= 1);
130
131         dib0070_write_reg(st, 0x14, LO4 | fcaptrim);
132         dib0070_write_reg(st, 0x18, 0x07ff);
133 }
134
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)
140 {
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);
143
144         u8 band = BAND_OF_FREQUENCY(freq), c;
145
146         /*******************VCO***********************************/
147         u16 lo4 = 0;
148
149         u8 REFDIV, PRESC = 2;
150         u32 FBDiv, Rest, FREF, VCOF_kHz;
151         u16 Num, Den;
152         /*******************FrontEnd******************************/
153         u16 value = 0;
154
155         dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
156
157
158         dib0070_write_reg(st, 0x17, 0x30);
159
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;
184                                         }
185                                         break;
186                         } break;
187
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;
210                                         }
211                                         break;
212
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;
224                                         }
225                                         break;
226                         }
227                 break;
228         }
229
230         dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf);
231         dprintk( "VCO = %hd", (lo4 >> 11) & 0x3);
232
233
234         VCOF_kHz = (c * freq) * 2;
235         dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq);
236
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;
247         }
248         FREF = st->cfg->clock_khz / REFDIV;
249
250         dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
251
252
253
254         switch (st->revision) {
255                 case DIB0070S_P1A:
256                         FBDiv = (VCOF_kHz / PRESC / FREF);
257                         Rest  = (VCOF_kHz / PRESC) - FBDiv * FREF;
258                         break;
259
260                 case DIB0070_P1G:
261                 case DIB0070_P1F:
262                 default:
263                         FBDiv = (freq / (FREF / 2));
264                         Rest  = 2 * freq - FBDiv * FREF;
265                         break;
266         }
267
268
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);
275
276         Num = 0;
277         Den = 1;
278
279         if (Rest > 0) {
280                 LO4_SET_SD(lo4, 1);
281                 Den = 255;
282                 Num = (u16)Rest;
283         }
284         dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
285
286
287
288         dib0070_write_reg(st, 0x11, (u16)FBDiv);
289
290
291         dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
292
293
294         dib0070_write_reg(st, 0x13, Num);
295
296
297         value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
298
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;
303         }
304         dib0070_write_reg(st, 0x20, value);
305
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);
312         }
313
314
315
316         switch (band) {
317                 case BAND_UHF:   value = 0x7c82; break;
318                 case BAND_LBAND: value = 0x7c84; break;
319                 default:         value = 0x7c81; break;
320         }
321         dib0070_write_reg(st, 0x0f, value);
322         dib0070_write_reg(st, 0x06, 0x3fff);
323
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;
332
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;
340
341                 case BAND_LBAND:
342                         if (freq <= 1500000) c = 0;
343                         else if (freq <= 1600000) c = 1;
344                         else c = 3;
345                 break;
346
347                 case BAND_SBAND:
348                         c = 7;
349                         dib0070_write_reg(st, 0x1d,0xFFFF);
350                 break;
351
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;
365                         }
366                         value = 2;
367                 break;
368         }
369
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);
374
375
376         dib0070_write_reg(st, 0x18,   0x07ff);
377         dib0070_write_reg(st, 0x17, 0x0033);
378
379         return 0;
380 }
381
382 static int dib0070_wakeup(struct dvb_frontend *fe)
383 {
384         struct dib0070_state *st = fe->tuner_priv;
385         if (st->cfg->sleep)
386                 st->cfg->sleep(fe, 0);
387         return 0;
388 }
389
390 static int dib0070_sleep(struct dvb_frontend *fe)
391 {
392         struct dib0070_state *st = fe->tuner_priv;
393         if (st->cfg->sleep)
394                 st->cfg->sleep(fe, 1);
395         return 0;
396 }
397
398 static u16 dib0070_p1f_defaults[] =
399
400 {
401         7, 0x02,
402                 0x0008,
403                 0x0000,
404                 0x0000,
405                 0x0000,
406                 0x0000,
407                 0x0002,
408                 0x0100,
409
410         3, 0x0d,
411                 0x0d80,
412                 0x0001,
413                 0x0000,
414
415         4, 0x11,
416                 0x0000,
417                 0x0103,
418                 0x0000,
419                 0x0000,
420
421         3, 0x16,
422                 0x0004 | 0x0040,
423                 0x0030,
424                 0x07ff,
425
426         6, 0x1b,
427                 0x4112,
428                 0xff00,
429                 0xc07f,
430                 0x0000,
431                 0x0180,
432                 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
433
434         0,
435 };
436
437 static void dib0070_wbd_calibration(struct dvb_frontend *fe)
438 {
439         u16 wbd_offs;
440         struct dib0070_state *state = fe->tuner_priv;
441
442         if (state->cfg->sleep)
443                 state->cfg->sleep(fe, 0);
444
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);
452
453         if (state->cfg->sleep)
454                 state->cfg->sleep(fe, 1);
455
456 }
457
458 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
459 {
460         struct dib0070_state *st = fe->tuner_priv;
461         return st->wbd_ff_offset;
462 }
463
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)
466 {
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);
471 }
472
473 #define pgm_read_word(w) (*w)
474 static int dib0070_reset(struct dib0070_state *state)
475 {
476         u16 l, r, *n;
477
478         HARD_RESET(state);
479
480
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;
487
488         /* P1F or not */
489         dprintk( "Revision: %x", state->revision);
490
491         if (state->revision == DIB0070_P1D) {
492                 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
493                 return -EINVAL;
494         }
495
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++);
505         }
506
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;
513
514         r |= state->cfg->osc_buffer_state << 3;
515
516         dib0070_write_reg(state, 0x10, r);
517         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
518
519         if (state->cfg->invert_iq) {
520                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
521                 dib0070_write_reg(state, 0x02, r | (1 << 5));
522         }
523
524
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);
529
530         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
531         return 0;
532 }
533
534
535 static int dib0070_release(struct dvb_frontend *fe)
536 {
537         kfree(fe->tuner_priv);
538         fe->tuner_priv = NULL;
539         return 0;
540 }
541
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,
548         },
549         .release       = dib0070_release,
550
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
556 };
557
558 struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
559 {
560         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
561         if (state == NULL)
562                 return NULL;
563
564         state->cfg = cfg;
565         state->i2c = i2c;
566         state->fe  = fe;
567         fe->tuner_priv = state;
568
569         if (dib0070_reset(state) != 0)
570                 goto free_mem;
571
572         dib0070_wbd_calibration(fe);
573
574         printk(KERN_INFO "DiB0070: successfully identified\n");
575         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
576
577         fe->tuner_priv = state;
578         return fe;
579
580 free_mem:
581         kfree(state);
582         fe->tuner_priv = NULL;
583         return NULL;
584 }
585 EXPORT_SYMBOL(dib0070_attach);
586
587 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
588 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
589 MODULE_LICENSE("GPL");