V4L/DVB (5955): Add support for DiB7070-based devices
[linux-2.6-block.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 dib0070_state *state)
438 {
439         u16 wbd_offs;
440         dib0070_write_reg(state, 0x0f, 0x6d81);
441         dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
442         msleep(9);
443         wbd_offs = dib0070_read_reg(state, 0x19);
444         dib0070_write_reg(state, 0x20, 0);
445         state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
446         dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
447 }
448
449 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
450 {
451         struct dib0070_state *st = fe->tuner_priv;
452         return st->wbd_ff_offset;
453 }
454
455 EXPORT_SYMBOL(dib0070_wbd_offset);
456 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)
457 {
458         struct dib0070_state *state = fe->tuner_priv;
459     u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
460         dprintk( "CTRL_LO5: 0x%x", lo5);
461         return dib0070_write_reg(state, 0x15, lo5);
462 }
463
464 #define pgm_read_word(w) (*w)
465 static int dib0070_reset(struct dib0070_state *state)
466 {
467         u16 l, r, *n;
468
469         HARD_RESET(state);
470
471
472 #ifndef FORCE_SBAND_TUNER
473         if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
474                 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
475         else
476 #endif
477                 state->revision = DIB0070S_P1A;
478
479         /* P1F or not */
480         dprintk( "Revision: %x", state->revision);
481
482         if (state->revision == DIB0070_P1D) {
483                 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
484                 return -EINVAL;
485         }
486
487         n = (u16 *) dib0070_p1f_defaults;
488         l = pgm_read_word(n++);
489         while (l) {
490                 r = pgm_read_word(n++);
491                 do {
492                         dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
493                         r++;
494                 } while (--l);
495                 l = pgm_read_word(n++);
496         }
497
498         if (state->cfg->force_crystal_mode != 0)
499                 r = state->cfg->force_crystal_mode;
500         else if (state->cfg->clock_khz >= 24000)
501                 r = 1;
502         else
503                 r = 2;
504
505         r |= state->cfg->osc_buffer_state << 3;
506
507         dib0070_write_reg(state, 0x10, r);
508         dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
509
510         if (state->cfg->invert_iq) {
511                 r = dib0070_read_reg(state, 0x02) & 0xffdf;
512                 dib0070_write_reg(state, 0x02, r | (1 << 5));
513         }
514
515
516         if (state->revision == DIB0070S_P1A)
517                 dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1);
518         else
519                 dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
520
521         dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
522         return 0;
523 }
524
525
526 static int dib0070_release(struct dvb_frontend *fe)
527 {
528         kfree(fe->tuner_priv);
529         fe->tuner_priv = NULL;
530         return 0;
531 }
532
533 static struct dvb_tuner_ops dib0070_ops = {
534         .info = {
535                 .name           = "DiBcom DiB0070",
536                 .frequency_min  =  45000000,
537                 .frequency_max  = 860000000,
538                 .frequency_step =      1000,
539         },
540         .release       = dib0070_release,
541
542         .init          = dib0070_wakeup,
543         .sleep         = dib0070_sleep,
544         .set_params    = dib0070_tune_digital,
545 //      .get_frequency = dib0070_get_frequency,
546 //      .get_bandwidth = dib0070_get_bandwidth
547 };
548
549 struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
550 {
551         struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
552         if (state == NULL)
553                 return NULL;
554
555         state->cfg = cfg;
556         state->i2c = i2c;
557         state->fe  = fe;
558         fe->tuner_priv = state;
559
560         if (dib0070_reset(state) != 0)
561                 goto free_mem;
562
563         dib0070_wbd_calibration(state);
564
565         printk(KERN_INFO "DiB0070: successfully identified\n");
566         memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
567
568         fe->tuner_priv = state;
569         return fe;
570
571 free_mem:
572         kfree(state);
573         fe->tuner_priv = NULL;
574         return NULL;
575 }
576 EXPORT_SYMBOL(dib0070_attach);
577
578 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
579 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
580 MODULE_LICENSE("GPL");