Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dib0070.c
Go to the documentation of this file.
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  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  *
22  * This code is more or less generated from another driver, please
23  * excuse some codingstyle oddities.
24  *
25  */
26 
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/i2c.h>
30 #include <linux/mutex.h>
31 
32 #include "dvb_frontend.h"
33 
34 #include "dib0070.h"
35 #include "dibx000_common.h"
36 
37 static int debug;
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40 
41 #define dprintk(args...) do { \
42  if (debug) { \
43  printk(KERN_DEBUG "DiB0070: "); \
44  printk(args); \
45  printk("\n"); \
46  } \
47 } while (0)
48 
49 #define DIB0070_P1D 0x00
50 #define DIB0070_P1F 0x01
51 #define DIB0070_P1G 0x03
52 #define DIB0070S_P1A 0x02
53 
54 struct dib0070_state {
55  struct i2c_adapter *i2c;
56  struct dvb_frontend *fe;
57  const struct dib0070_config *cfg;
60 
63 
64  /* for the captrim binary search */
67 
71 
74 
77 
78  /* for the I2C transfer */
79  struct i2c_msg msg[2];
83 };
84 
85 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
86 {
87  u16 ret;
88 
89  if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
90  dprintk("could not acquire lock");
91  return 0;
92  }
93 
94  state->i2c_write_buffer[0] = reg;
95 
96  memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
97  state->msg[0].addr = state->cfg->i2c_address;
98  state->msg[0].flags = 0;
99  state->msg[0].buf = state->i2c_write_buffer;
100  state->msg[0].len = 1;
101  state->msg[1].addr = state->cfg->i2c_address;
102  state->msg[1].flags = I2C_M_RD;
103  state->msg[1].buf = state->i2c_read_buffer;
104  state->msg[1].len = 2;
105 
106  if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
107  printk(KERN_WARNING "DiB0070 I2C read failed\n");
108  ret = 0;
109  } else
110  ret = (state->i2c_read_buffer[0] << 8)
111  | state->i2c_read_buffer[1];
112 
113  mutex_unlock(&state->i2c_buffer_lock);
114  return ret;
115 }
116 
117 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
118 {
119  int ret;
120 
121  if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
122  dprintk("could not acquire lock");
123  return -EINVAL;
124  }
125  state->i2c_write_buffer[0] = reg;
126  state->i2c_write_buffer[1] = val >> 8;
127  state->i2c_write_buffer[2] = val & 0xff;
128 
129  memset(state->msg, 0, sizeof(struct i2c_msg));
130  state->msg[0].addr = state->cfg->i2c_address;
131  state->msg[0].flags = 0;
132  state->msg[0].buf = state->i2c_write_buffer;
133  state->msg[0].len = 3;
134 
135  if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
136  printk(KERN_WARNING "DiB0070 I2C write failed\n");
137  ret = -EREMOTEIO;
138  } else
139  ret = 0;
140 
141  mutex_unlock(&state->i2c_buffer_lock);
142  return ret;
143 }
144 
145 #define HARD_RESET(state) do { \
146  state->cfg->sleep(state->fe, 0); \
147  if (state->cfg->reset) { \
148  state->cfg->reset(state->fe,1); msleep(10); \
149  state->cfg->reset(state->fe,0); msleep(10); \
150  } \
151 } while (0)
152 
153 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
154 {
155  struct dib0070_state *state = fe->tuner_priv;
156  u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
157 
158  if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
159  tmp |= (0 << 14);
160  else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
161  tmp |= (1 << 14);
162  else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
163  tmp |= (2 << 14);
164  else
165  tmp |= (3 << 14);
166 
167  dib0070_write_reg(state, 0x02, tmp);
168 
169  /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
170  if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
171  u16 value = dib0070_read_reg(state, 0x17);
172 
173  dib0070_write_reg(state, 0x17, value & 0xfffc);
174  tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
175  dib0070_write_reg(state, 0x01, tmp | (60 << 9));
176 
177  dib0070_write_reg(state, 0x17, value);
178  }
179  return 0;
180 }
181 
182 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
183 {
184  int8_t step_sign;
185  u16 adc;
186  int ret = 0;
187 
188  if (*tune_state == CT_TUNER_STEP_0) {
189 
190  dib0070_write_reg(state, 0x0f, 0xed10);
191  dib0070_write_reg(state, 0x17, 0x0034);
192 
193  dib0070_write_reg(state, 0x18, 0x0032);
194  state->step = state->captrim = state->fcaptrim = 64;
195  state->adc_diff = 3000;
196  ret = 20;
197 
198  *tune_state = CT_TUNER_STEP_1;
199  } else if (*tune_state == CT_TUNER_STEP_1) {
200  state->step /= 2;
201  dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
202  ret = 15;
203 
204  *tune_state = CT_TUNER_STEP_2;
205  } else if (*tune_state == CT_TUNER_STEP_2) {
206 
207  adc = dib0070_read_reg(state, 0x19);
208 
209  dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
210 
211  if (adc >= 400) {
212  adc -= 400;
213  step_sign = -1;
214  } else {
215  adc = 400 - adc;
216  step_sign = 1;
217  }
218 
219  if (adc < state->adc_diff) {
220  dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
221  state->adc_diff = adc;
222  state->fcaptrim = state->captrim;
223 
224 
225 
226  }
227  state->captrim += (step_sign * state->step);
228 
229  if (state->step >= 1)
230  *tune_state = CT_TUNER_STEP_1;
231  else
232  *tune_state = CT_TUNER_STEP_3;
233 
234  } else if (*tune_state == CT_TUNER_STEP_3) {
235  dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
236  dib0070_write_reg(state, 0x18, 0x07ff);
237  *tune_state = CT_TUNER_STEP_4;
238  }
239 
240  return ret;
241 }
242 
243 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)
244 {
245  struct dib0070_state *state = fe->tuner_priv;
246  u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
247  dprintk("CTRL_LO5: 0x%x", lo5);
248  return dib0070_write_reg(state, 0x15, lo5);
249 }
250 
252 {
253  struct dib0070_state *state = fe->tuner_priv;
254 
255  if (open) {
256  dib0070_write_reg(state, 0x1b, 0xff00);
257  dib0070_write_reg(state, 0x1a, 0x0000);
258  } else {
259  dib0070_write_reg(state, 0x1b, 0x4112);
260  if (state->cfg->vga_filter != 0) {
261  dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
262  dprintk("vga filter register is set to %x", state->cfg->vga_filter);
263  } else
264  dib0070_write_reg(state, 0x1a, 0x0009);
265  }
266 }
267 
270  u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
278 };
279 
281  u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
283 };
284 
285 static const struct dib0070_tuning dib0070s_tuning_table[] = {
286  { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
287  { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
288  { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
289  { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
290  { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
291  { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
292  { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
293 };
294 
295 static const struct dib0070_tuning dib0070_tuning_table[] = {
296  { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
297  { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
298  { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
299  { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
300  { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
301  { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
302  { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
303  { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
304 };
305 
306 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
307  { 180000, 0 }, /* VHF */
308  { 188000, 1 },
309  { 196400, 2 },
310  { 250000, 3 },
311  { 550000, 0 }, /* UHF */
312  { 590000, 1 },
313  { 666000, 3 },
314  { 864000, 5 },
315  { 1500000, 0 }, /* LBAND or everything higher than UHF */
316  { 1600000, 1 },
317  { 2000000, 3 },
318  { 0xffffffff, 7 },
319 };
320 
321 static const struct dib0070_lna_match dib0070_lna[] = {
322  { 180000, 0 }, /* VHF */
323  { 188000, 1 },
324  { 196400, 2 },
325  { 250000, 3 },
326  { 550000, 2 }, /* UHF */
327  { 650000, 3 },
328  { 750000, 5 },
329  { 850000, 6 },
330  { 864000, 7 },
331  { 1500000, 0 }, /* LBAND or everything higher than UHF */
332  { 1600000, 1 },
333  { 2000000, 3 },
334  { 0xffffffff, 7 },
335 };
336 
337 #define LPF 100
338 static int dib0070_tune_digital(struct dvb_frontend *fe)
339 {
340  struct dib0070_state *state = fe->tuner_priv;
341 
342  const struct dib0070_tuning *tune;
343  const struct dib0070_lna_match *lna_match;
344 
345  enum frontend_tune_state *tune_state = &state->tune_state;
346  int ret = 10; /* 1ms is the default delay most of the time */
347 
348  u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
349  u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
350 
351 #ifdef CONFIG_SYS_ISDBT
352  if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
353  if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
354  && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
355  || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
356  && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
357  || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
358  && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
359  freq += 850;
360 #endif
361  if (state->current_rf != freq) {
362 
363  switch (state->revision) {
364  case DIB0070S_P1A:
365  tune = dib0070s_tuning_table;
366  lna_match = dib0070_lna;
367  break;
368  default:
369  tune = dib0070_tuning_table;
370  if (state->cfg->flip_chip)
371  lna_match = dib0070_lna_flip_chip;
372  else
373  lna_match = dib0070_lna;
374  break;
375  }
376  while (freq > tune->max_freq) /* find the right one */
377  tune++;
378  while (freq > lna_match->max_freq) /* find the right one */
379  lna_match++;
380 
381  state->current_tune_table_index = tune;
382  state->lna_match = lna_match;
383  }
384 
385  if (*tune_state == CT_TUNER_START) {
386  dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
387  if (state->current_rf != freq) {
388  u8 REFDIV;
389  u32 FBDiv, Rest, FREF, VCOF_kHz;
390  u8 Den;
391 
392  state->current_rf = freq;
393  state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
394 
395 
396  dib0070_write_reg(state, 0x17, 0x30);
397 
398 
399  VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
400 
401  switch (band) {
402  case BAND_VHF:
403  REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
404  break;
405  case BAND_FM:
406  REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
407  break;
408  default:
409  REFDIV = (u8) (state->cfg->clock_khz / 10000);
410  break;
411  }
412  FREF = state->cfg->clock_khz / REFDIV;
413 
414 
415 
416  switch (state->revision) {
417  case DIB0070S_P1A:
418  FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
419  Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
420  break;
421 
422  case DIB0070_P1G:
423  case DIB0070_P1F:
424  default:
425  FBDiv = (freq / (FREF / 2));
426  Rest = 2 * freq - FBDiv * FREF;
427  break;
428  }
429 
430  if (Rest < LPF)
431  Rest = 0;
432  else if (Rest < 2 * LPF)
433  Rest = 2 * LPF;
434  else if (Rest > (FREF - LPF)) {
435  Rest = 0;
436  FBDiv += 1;
437  } else if (Rest > (FREF - 2 * LPF))
438  Rest = FREF - 2 * LPF;
439  Rest = (Rest * 6528) / (FREF / 10);
440 
441  Den = 1;
442  if (Rest > 0) {
443  state->lo4 |= (1 << 14) | (1 << 12);
444  Den = 255;
445  }
446 
447 
448  dib0070_write_reg(state, 0x11, (u16)FBDiv);
449  dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
450  dib0070_write_reg(state, 0x13, (u16) Rest);
451 
452  if (state->revision == DIB0070S_P1A) {
453 
454  if (band == BAND_SBAND) {
455  dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
456  dib0070_write_reg(state, 0x1d, 0xFFFF);
457  } else
458  dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
459  }
460 
461  dib0070_write_reg(state, 0x20,
462  0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
463 
464  dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
465  dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
466  dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
467  dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
468  dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
469  dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
470 
471  *tune_state = CT_TUNER_STEP_0;
472  } else { /* we are already tuned to this frequency - the configuration is correct */
473  ret = 50; /* wakeup time */
474  *tune_state = CT_TUNER_STEP_5;
475  }
476  } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
477 
478  ret = dib0070_captrim(state, tune_state);
479 
480  } else if (*tune_state == CT_TUNER_STEP_4) {
481  const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
482  if (tmp != NULL) {
483  while (freq/1000 > tmp->freq) /* find the right one */
484  tmp++;
485  dib0070_write_reg(state, 0x0f,
486  (0 << 15) | (1 << 14) | (3 << 12)
487  | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
488  | (state->current_tune_table_index->wbdmux << 0));
489  state->wbd_gain_current = tmp->wbd_gain_val;
490  } else {
491  dib0070_write_reg(state, 0x0f,
492  (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
493  wbdmux << 0));
494  state->wbd_gain_current = 6;
495  }
496 
497  dib0070_write_reg(state, 0x06, 0x3fff);
498  dib0070_write_reg(state, 0x07,
499  (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
500  dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
501  dib0070_write_reg(state, 0x0d, 0x0d80);
502 
503 
504  dib0070_write_reg(state, 0x18, 0x07ff);
505  dib0070_write_reg(state, 0x17, 0x0033);
506 
507 
508  *tune_state = CT_TUNER_STEP_5;
509  } else if (*tune_state == CT_TUNER_STEP_5) {
510  dib0070_set_bandwidth(fe);
511  *tune_state = CT_TUNER_STOP;
512  } else {
513  ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
514  }
515  return ret;
516 }
517 
518 
519 static int dib0070_tune(struct dvb_frontend *fe)
520 {
521  struct dib0070_state *state = fe->tuner_priv;
522  uint32_t ret;
523 
524  state->tune_state = CT_TUNER_START;
525 
526  do {
527  ret = dib0070_tune_digital(fe);
528  if (ret != FE_CALLBACK_TIME_NEVER)
529  msleep(ret/10);
530  else
531  break;
532  } while (state->tune_state != CT_TUNER_STOP);
533 
534  return 0;
535 }
536 
537 static int dib0070_wakeup(struct dvb_frontend *fe)
538 {
539  struct dib0070_state *state = fe->tuner_priv;
540  if (state->cfg->sleep)
541  state->cfg->sleep(fe, 0);
542  return 0;
543 }
544 
545 static int dib0070_sleep(struct dvb_frontend *fe)
546 {
547  struct dib0070_state *state = fe->tuner_priv;
548  if (state->cfg->sleep)
549  state->cfg->sleep(fe, 1);
550  return 0;
551 }
552 
554 {
555  struct dib0070_state *state = fe->tuner_priv;
556  return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
557 }
559 
561 {
562  struct dib0070_state *state = fe->tuner_priv;
563  u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
564  if (no > 3)
565  no = 3;
566  if (no < 1)
567  no = 1;
568  return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
569 }
571 
572 static const u16 dib0070_p1f_defaults[] =
573 
574 {
575  7, 0x02,
576  0x0008,
577  0x0000,
578  0x0000,
579  0x0000,
580  0x0000,
581  0x0002,
582  0x0100,
583 
584  3, 0x0d,
585  0x0d80,
586  0x0001,
587  0x0000,
588 
589  4, 0x11,
590  0x0000,
591  0x0103,
592  0x0000,
593  0x0000,
594 
595  3, 0x16,
596  0x0004 | 0x0040,
597  0x0030,
598  0x07ff,
599 
600  6, 0x1b,
601  0x4112,
602  0xff00,
603  0xc07f,
604  0x0000,
605  0x0180,
606  0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
607 
608  0,
609 };
610 
611 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
612 {
613  u16 tuner_en = dib0070_read_reg(state, 0x20);
614  u16 offset;
615 
616  dib0070_write_reg(state, 0x18, 0x07ff);
617  dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
618  dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
619  msleep(9);
620  offset = dib0070_read_reg(state, 0x19);
621  dib0070_write_reg(state, 0x20, tuner_en);
622  return offset;
623 }
624 
625 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
626 {
627  u8 gain;
628  for (gain = 6; gain < 8; gain++) {
629  state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
630  dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
631  }
632 }
633 
635 {
636  struct dib0070_state *state = fe->tuner_priv;
637  const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
638  u32 freq = fe->dtv_property_cache.frequency/1000;
639 
640  if (tmp != NULL) {
641  while (freq/1000 > tmp->freq) /* find the right one */
642  tmp++;
643  state->wbd_gain_current = tmp->wbd_gain_val;
644  } else
645  state->wbd_gain_current = 6;
646 
647  return state->wbd_offset_3_3[state->wbd_gain_current - 6];
648 }
650 
651 #define pgm_read_word(w) (*w)
652 static int dib0070_reset(struct dvb_frontend *fe)
653 {
654  struct dib0070_state *state = fe->tuner_priv;
655  u16 l, r, *n;
656 
657  HARD_RESET(state);
658 
659 
660 #ifndef FORCE_SBAND_TUNER
661  if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
662  state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
663  else
664 #else
665 #warning forcing SBAND
666 #endif
667  state->revision = DIB0070S_P1A;
668 
669  /* P1F or not */
670  dprintk("Revision: %x", state->revision);
671 
672  if (state->revision == DIB0070_P1D) {
673  dprintk("Error: this driver is not to be used meant for P1D or earlier");
674  return -EINVAL;
675  }
676 
677  n = (u16 *) dib0070_p1f_defaults;
678  l = pgm_read_word(n++);
679  while (l) {
680  r = pgm_read_word(n++);
681  do {
682  dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
683  r++;
684  } while (--l);
685  l = pgm_read_word(n++);
686  }
687 
688  if (state->cfg->force_crystal_mode != 0)
689  r = state->cfg->force_crystal_mode;
690  else if (state->cfg->clock_khz >= 24000)
691  r = 1;
692  else
693  r = 2;
694 
695 
696  r |= state->cfg->osc_buffer_state << 3;
697 
698  dib0070_write_reg(state, 0x10, r);
699  dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
700 
701  if (state->cfg->invert_iq) {
702  r = dib0070_read_reg(state, 0x02) & 0xffdf;
703  dib0070_write_reg(state, 0x02, r | (1 << 5));
704  }
705 
706  if (state->revision == DIB0070S_P1A)
707  dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
708  else
709  dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
710 
711  dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
712 
713  dib0070_wbd_offset_calibration(state);
714 
715  return 0;
716 }
717 
718 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
719 {
720  struct dib0070_state *state = fe->tuner_priv;
721 
722  *frequency = 1000 * state->current_rf;
723  return 0;
724 }
725 
726 static int dib0070_release(struct dvb_frontend *fe)
727 {
728  kfree(fe->tuner_priv);
729  fe->tuner_priv = NULL;
730  return 0;
731 }
732 
733 static const struct dvb_tuner_ops dib0070_ops = {
734  .info = {
735  .name = "DiBcom DiB0070",
736  .frequency_min = 45000000,
737  .frequency_max = 860000000,
738  .frequency_step = 1000,
739  },
740  .release = dib0070_release,
741 
742  .init = dib0070_wakeup,
743  .sleep = dib0070_sleep,
744  .set_params = dib0070_tune,
745 
746  .get_frequency = dib0070_get_frequency,
747 // .get_bandwidth = dib0070_get_bandwidth
748 };
749 
750 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
751 {
752  struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
753  if (state == NULL)
754  return NULL;
755 
756  state->cfg = cfg;
757  state->i2c = i2c;
758  state->fe = fe;
759  mutex_init(&state->i2c_buffer_lock);
760  fe->tuner_priv = state;
761 
762  if (dib0070_reset(fe) != 0)
763  goto free_mem;
764 
765  printk(KERN_INFO "DiB0070: successfully identified\n");
766  memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
767 
768  fe->tuner_priv = state;
769  return fe;
770 
771 free_mem:
772  kfree(state);
773  fe->tuner_priv = NULL;
774  return NULL;
775 }
777 
778 MODULE_AUTHOR("Patrick Boettcher <[email protected]>");
779 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
780 MODULE_LICENSE("GPL");