Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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");
590 
  This page was automatically generated by the LXR engine.