WIP FPC-III support
[linux/fpc-iii.git] / drivers / media / dvb-frontends / dib0070.c
blobcafb41dba861c02a13b3e1558e8c51f971e2234c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
5 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
7 * This code is more or less generated from another driver, please
8 * excuse some codingstyle oddities.
9 */
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/i2c.h>
16 #include <linux/mutex.h>
18 #include <media/dvb_frontend.h>
20 #include "dib0070.h"
21 #include "dibx000_common.h"
23 static int debug;
24 module_param(debug, int, 0644);
25 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
27 #define dprintk(fmt, arg...) do { \
28 if (debug) \
29 printk(KERN_DEBUG pr_fmt("%s: " fmt), \
30 __func__, ##arg); \
31 } while (0)
33 #define DIB0070_P1D 0x00
34 #define DIB0070_P1F 0x01
35 #define DIB0070_P1G 0x03
36 #define DIB0070S_P1A 0x02
38 struct dib0070_state {
39 struct i2c_adapter *i2c;
40 struct dvb_frontend *fe;
41 const struct dib0070_config *cfg;
42 u16 wbd_ff_offset;
43 u8 revision;
45 enum frontend_tune_state tune_state;
46 u32 current_rf;
48 /* for the captrim binary search */
49 s8 step;
50 u16 adc_diff;
52 s8 captrim;
53 s8 fcaptrim;
54 u16 lo4;
56 const struct dib0070_tuning *current_tune_table_index;
57 const struct dib0070_lna_match *lna_match;
59 u8 wbd_gain_current;
60 u16 wbd_offset_3_3[2];
62 /* for the I2C transfer */
63 struct i2c_msg msg[2];
64 u8 i2c_write_buffer[3];
65 u8 i2c_read_buffer[2];
66 struct mutex i2c_buffer_lock;
69 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
71 u16 ret;
73 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
74 dprintk("could not acquire lock\n");
75 return 0;
78 state->i2c_write_buffer[0] = reg;
80 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
81 state->msg[0].addr = state->cfg->i2c_address;
82 state->msg[0].flags = 0;
83 state->msg[0].buf = state->i2c_write_buffer;
84 state->msg[0].len = 1;
85 state->msg[1].addr = state->cfg->i2c_address;
86 state->msg[1].flags = I2C_M_RD;
87 state->msg[1].buf = state->i2c_read_buffer;
88 state->msg[1].len = 2;
90 if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
91 pr_warn("DiB0070 I2C read failed\n");
92 ret = 0;
93 } else
94 ret = (state->i2c_read_buffer[0] << 8)
95 | state->i2c_read_buffer[1];
97 mutex_unlock(&state->i2c_buffer_lock);
98 return ret;
101 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
103 int ret;
105 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
106 dprintk("could not acquire lock\n");
107 return -EINVAL;
109 state->i2c_write_buffer[0] = reg;
110 state->i2c_write_buffer[1] = val >> 8;
111 state->i2c_write_buffer[2] = val & 0xff;
113 memset(state->msg, 0, sizeof(struct i2c_msg));
114 state->msg[0].addr = state->cfg->i2c_address;
115 state->msg[0].flags = 0;
116 state->msg[0].buf = state->i2c_write_buffer;
117 state->msg[0].len = 3;
119 if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
120 pr_warn("DiB0070 I2C write failed\n");
121 ret = -EREMOTEIO;
122 } else
123 ret = 0;
125 mutex_unlock(&state->i2c_buffer_lock);
126 return ret;
129 #define HARD_RESET(state) do { \
130 state->cfg->sleep(state->fe, 0); \
131 if (state->cfg->reset) { \
132 state->cfg->reset(state->fe,1); msleep(10); \
133 state->cfg->reset(state->fe,0); msleep(10); \
135 } while (0)
137 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
139 struct dib0070_state *state = fe->tuner_priv;
140 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
142 if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
143 tmp |= (0 << 14);
144 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
145 tmp |= (1 << 14);
146 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
147 tmp |= (2 << 14);
148 else
149 tmp |= (3 << 14);
151 dib0070_write_reg(state, 0x02, tmp);
153 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
154 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
155 u16 value = dib0070_read_reg(state, 0x17);
157 dib0070_write_reg(state, 0x17, value & 0xfffc);
158 tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
159 dib0070_write_reg(state, 0x01, tmp | (60 << 9));
161 dib0070_write_reg(state, 0x17, value);
163 return 0;
166 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
168 int8_t step_sign;
169 u16 adc;
170 int ret = 0;
172 if (*tune_state == CT_TUNER_STEP_0) {
173 dib0070_write_reg(state, 0x0f, 0xed10);
174 dib0070_write_reg(state, 0x17, 0x0034);
176 dib0070_write_reg(state, 0x18, 0x0032);
177 state->step = state->captrim = state->fcaptrim = 64;
178 state->adc_diff = 3000;
179 ret = 20;
181 *tune_state = CT_TUNER_STEP_1;
182 } else if (*tune_state == CT_TUNER_STEP_1) {
183 state->step /= 2;
184 dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
185 ret = 15;
187 *tune_state = CT_TUNER_STEP_2;
188 } else if (*tune_state == CT_TUNER_STEP_2) {
190 adc = dib0070_read_reg(state, 0x19);
192 dprintk("CAPTRIM=%d; ADC = %hd (ADC) & %dmV\n", state->captrim,
193 adc, (u32)adc * (u32)1800 / (u32)1024);
195 if (adc >= 400) {
196 adc -= 400;
197 step_sign = -1;
198 } else {
199 adc = 400 - adc;
200 step_sign = 1;
203 if (adc < state->adc_diff) {
204 dprintk("CAPTRIM=%d is closer to target (%hd/%hd)\n",
205 state->captrim, adc, state->adc_diff);
206 state->adc_diff = adc;
207 state->fcaptrim = state->captrim;
209 state->captrim += (step_sign * state->step);
211 if (state->step >= 1)
212 *tune_state = CT_TUNER_STEP_1;
213 else
214 *tune_state = CT_TUNER_STEP_3;
216 } else if (*tune_state == CT_TUNER_STEP_3) {
217 dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
218 dib0070_write_reg(state, 0x18, 0x07ff);
219 *tune_state = CT_TUNER_STEP_4;
222 return ret;
225 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)
227 struct dib0070_state *state = fe->tuner_priv;
228 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
230 dprintk("CTRL_LO5: 0x%x\n", lo5);
231 return dib0070_write_reg(state, 0x15, lo5);
234 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
236 struct dib0070_state *state = fe->tuner_priv;
238 if (open) {
239 dib0070_write_reg(state, 0x1b, 0xff00);
240 dib0070_write_reg(state, 0x1a, 0x0000);
241 } else {
242 dib0070_write_reg(state, 0x1b, 0x4112);
243 if (state->cfg->vga_filter != 0) {
244 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
245 dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
246 } else
247 dib0070_write_reg(state, 0x1a, 0x0009);
251 EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
252 struct dib0070_tuning {
253 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
254 u8 switch_trim;
255 u8 vco_band;
256 u8 hfdiv;
257 u8 vco_multi;
258 u8 presc;
259 u8 wbdmux;
260 u16 tuner_enable;
263 struct dib0070_lna_match {
264 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
265 u8 lna_band;
268 static const struct dib0070_tuning dib0070s_tuning_table[] = {
269 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
270 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
271 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
272 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
273 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
274 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
275 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
278 static const struct dib0070_tuning dib0070_tuning_table[] = {
279 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
280 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
281 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
282 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
283 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
284 { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
285 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
286 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
289 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
290 { 180000, 0 }, /* VHF */
291 { 188000, 1 },
292 { 196400, 2 },
293 { 250000, 3 },
294 { 550000, 0 }, /* UHF */
295 { 590000, 1 },
296 { 666000, 3 },
297 { 864000, 5 },
298 { 1500000, 0 }, /* LBAND or everything higher than UHF */
299 { 1600000, 1 },
300 { 2000000, 3 },
301 { 0xffffffff, 7 },
304 static const struct dib0070_lna_match dib0070_lna[] = {
305 { 180000, 0 }, /* VHF */
306 { 188000, 1 },
307 { 196400, 2 },
308 { 250000, 3 },
309 { 550000, 2 }, /* UHF */
310 { 650000, 3 },
311 { 750000, 5 },
312 { 850000, 6 },
313 { 864000, 7 },
314 { 1500000, 0 }, /* LBAND or everything higher than UHF */
315 { 1600000, 1 },
316 { 2000000, 3 },
317 { 0xffffffff, 7 },
320 #define LPF 100
321 static int dib0070_tune_digital(struct dvb_frontend *fe)
323 struct dib0070_state *state = fe->tuner_priv;
325 const struct dib0070_tuning *tune;
326 const struct dib0070_lna_match *lna_match;
328 enum frontend_tune_state *tune_state = &state->tune_state;
329 int ret = 10; /* 1ms is the default delay most of the time */
331 u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
332 u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
334 #ifdef CONFIG_SYS_ISDBT
335 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
336 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
337 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
338 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
339 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
340 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
341 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
342 freq += 850;
343 #endif
344 if (state->current_rf != freq) {
346 switch (state->revision) {
347 case DIB0070S_P1A:
348 tune = dib0070s_tuning_table;
349 lna_match = dib0070_lna;
350 break;
351 default:
352 tune = dib0070_tuning_table;
353 if (state->cfg->flip_chip)
354 lna_match = dib0070_lna_flip_chip;
355 else
356 lna_match = dib0070_lna;
357 break;
359 while (freq > tune->max_freq) /* find the right one */
360 tune++;
361 while (freq > lna_match->max_freq) /* find the right one */
362 lna_match++;
364 state->current_tune_table_index = tune;
365 state->lna_match = lna_match;
368 if (*tune_state == CT_TUNER_START) {
369 dprintk("Tuning for Band: %d (%d kHz)\n", band, freq);
370 if (state->current_rf != freq) {
371 u8 REFDIV;
372 u32 FBDiv, Rest, FREF, VCOF_kHz;
373 u8 Den;
375 state->current_rf = freq;
376 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
379 dib0070_write_reg(state, 0x17, 0x30);
382 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
384 switch (band) {
385 case BAND_VHF:
386 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
387 break;
388 case BAND_FM:
389 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
390 break;
391 default:
392 REFDIV = (u8) (state->cfg->clock_khz / 10000);
393 break;
395 FREF = state->cfg->clock_khz / REFDIV;
399 switch (state->revision) {
400 case DIB0070S_P1A:
401 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
402 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
403 break;
405 case DIB0070_P1G:
406 case DIB0070_P1F:
407 default:
408 FBDiv = (freq / (FREF / 2));
409 Rest = 2 * freq - FBDiv * FREF;
410 break;
413 if (Rest < LPF)
414 Rest = 0;
415 else if (Rest < 2 * LPF)
416 Rest = 2 * LPF;
417 else if (Rest > (FREF - LPF)) {
418 Rest = 0;
419 FBDiv += 1;
420 } else if (Rest > (FREF - 2 * LPF))
421 Rest = FREF - 2 * LPF;
422 Rest = (Rest * 6528) / (FREF / 10);
424 Den = 1;
425 if (Rest > 0) {
426 state->lo4 |= (1 << 14) | (1 << 12);
427 Den = 255;
431 dib0070_write_reg(state, 0x11, (u16)FBDiv);
432 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
433 dib0070_write_reg(state, 0x13, (u16) Rest);
435 if (state->revision == DIB0070S_P1A) {
437 if (band == BAND_SBAND) {
438 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
439 dib0070_write_reg(state, 0x1d, 0xFFFF);
440 } else
441 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
444 dib0070_write_reg(state, 0x20,
445 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
447 dprintk("REFDIV: %u, FREF: %d\n", REFDIV, FREF);
448 dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
449 dprintk("Num: %u, Den: %u, SD: %d\n", (u16)Rest, Den,
450 (state->lo4 >> 12) & 0x1);
451 dprintk("HFDIV code: %u\n",
452 state->current_tune_table_index->hfdiv);
453 dprintk("VCO = %u\n",
454 state->current_tune_table_index->vco_band);
455 dprintk("VCOF: ((%u*%d) << 1))\n",
456 state->current_tune_table_index->vco_multi,
457 freq);
459 *tune_state = CT_TUNER_STEP_0;
460 } else { /* we are already tuned to this frequency - the configuration is correct */
461 ret = 50; /* wakeup time */
462 *tune_state = CT_TUNER_STEP_5;
464 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
466 ret = dib0070_captrim(state, tune_state);
468 } else if (*tune_state == CT_TUNER_STEP_4) {
469 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
470 if (tmp != NULL) {
471 while (freq/1000 > tmp->freq) /* find the right one */
472 tmp++;
473 dib0070_write_reg(state, 0x0f,
474 (0 << 15) | (1 << 14) | (3 << 12)
475 | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
476 | (state->current_tune_table_index->wbdmux << 0));
477 state->wbd_gain_current = tmp->wbd_gain_val;
478 } else {
479 dib0070_write_reg(state, 0x0f,
480 (0 << 15) | (1 << 14) | (3 << 12)
481 | (6 << 9) | (0 << 8) | (1 << 7)
482 | (state->current_tune_table_index->wbdmux << 0));
483 state->wbd_gain_current = 6;
486 dib0070_write_reg(state, 0x06, 0x3fff);
487 dib0070_write_reg(state, 0x07,
488 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
489 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
490 dib0070_write_reg(state, 0x0d, 0x0d80);
493 dib0070_write_reg(state, 0x18, 0x07ff);
494 dib0070_write_reg(state, 0x17, 0x0033);
497 *tune_state = CT_TUNER_STEP_5;
498 } else if (*tune_state == CT_TUNER_STEP_5) {
499 dib0070_set_bandwidth(fe);
500 *tune_state = CT_TUNER_STOP;
501 } else {
502 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
504 return ret;
508 static int dib0070_tune(struct dvb_frontend *fe)
510 struct dib0070_state *state = fe->tuner_priv;
511 uint32_t ret;
513 state->tune_state = CT_TUNER_START;
515 do {
516 ret = dib0070_tune_digital(fe);
517 if (ret != FE_CALLBACK_TIME_NEVER)
518 msleep(ret/10);
519 else
520 break;
521 } while (state->tune_state != CT_TUNER_STOP);
523 return 0;
526 static int dib0070_wakeup(struct dvb_frontend *fe)
528 struct dib0070_state *state = fe->tuner_priv;
529 if (state->cfg->sleep)
530 state->cfg->sleep(fe, 0);
531 return 0;
534 static int dib0070_sleep(struct dvb_frontend *fe)
536 struct dib0070_state *state = fe->tuner_priv;
537 if (state->cfg->sleep)
538 state->cfg->sleep(fe, 1);
539 return 0;
542 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
544 struct dib0070_state *state = fe->tuner_priv;
545 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
547 EXPORT_SYMBOL(dib0070_get_rf_output);
549 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
551 struct dib0070_state *state = fe->tuner_priv;
552 u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
553 if (no > 3)
554 no = 3;
555 if (no < 1)
556 no = 1;
557 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
559 EXPORT_SYMBOL(dib0070_set_rf_output);
561 static const u16 dib0070_p1f_defaults[] =
564 7, 0x02,
565 0x0008,
566 0x0000,
567 0x0000,
568 0x0000,
569 0x0000,
570 0x0002,
571 0x0100,
573 3, 0x0d,
574 0x0d80,
575 0x0001,
576 0x0000,
578 4, 0x11,
579 0x0000,
580 0x0103,
581 0x0000,
582 0x0000,
584 3, 0x16,
585 0x0004 | 0x0040,
586 0x0030,
587 0x07ff,
589 6, 0x1b,
590 0x4112,
591 0xff00,
592 0xc07f,
593 0x0000,
594 0x0180,
595 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
600 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
602 u16 tuner_en = dib0070_read_reg(state, 0x20);
603 u16 offset;
605 dib0070_write_reg(state, 0x18, 0x07ff);
606 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
607 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
608 msleep(9);
609 offset = dib0070_read_reg(state, 0x19);
610 dib0070_write_reg(state, 0x20, tuner_en);
611 return offset;
614 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
616 u8 gain;
617 for (gain = 6; gain < 8; gain++) {
618 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
619 dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
623 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
625 struct dib0070_state *state = fe->tuner_priv;
626 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
627 u32 freq = fe->dtv_property_cache.frequency/1000;
629 if (tmp != NULL) {
630 while (freq/1000 > tmp->freq) /* find the right one */
631 tmp++;
632 state->wbd_gain_current = tmp->wbd_gain_val;
633 } else
634 state->wbd_gain_current = 6;
636 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
638 EXPORT_SYMBOL(dib0070_wbd_offset);
640 #define pgm_read_word(w) (*w)
641 static int dib0070_reset(struct dvb_frontend *fe)
643 struct dib0070_state *state = fe->tuner_priv;
644 u16 l, r, *n;
646 HARD_RESET(state);
649 #ifndef FORCE_SBAND_TUNER
650 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
651 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
652 else
653 #else
654 #warning forcing SBAND
655 #endif
656 state->revision = DIB0070S_P1A;
658 /* P1F or not */
659 dprintk("Revision: %x\n", state->revision);
661 if (state->revision == DIB0070_P1D) {
662 dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
663 return -EINVAL;
666 n = (u16 *) dib0070_p1f_defaults;
667 l = pgm_read_word(n++);
668 while (l) {
669 r = pgm_read_word(n++);
670 do {
671 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
672 r++;
673 } while (--l);
674 l = pgm_read_word(n++);
677 if (state->cfg->force_crystal_mode != 0)
678 r = state->cfg->force_crystal_mode;
679 else if (state->cfg->clock_khz >= 24000)
680 r = 1;
681 else
682 r = 2;
685 r |= state->cfg->osc_buffer_state << 3;
687 dib0070_write_reg(state, 0x10, r);
688 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
690 if (state->cfg->invert_iq) {
691 r = dib0070_read_reg(state, 0x02) & 0xffdf;
692 dib0070_write_reg(state, 0x02, r | (1 << 5));
695 if (state->revision == DIB0070S_P1A)
696 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
697 else
698 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
699 state->cfg->enable_third_order_filter);
701 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
703 dib0070_wbd_offset_calibration(state);
705 return 0;
708 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
710 struct dib0070_state *state = fe->tuner_priv;
712 *frequency = 1000 * state->current_rf;
713 return 0;
716 static void dib0070_release(struct dvb_frontend *fe)
718 kfree(fe->tuner_priv);
719 fe->tuner_priv = NULL;
722 static const struct dvb_tuner_ops dib0070_ops = {
723 .info = {
724 .name = "DiBcom DiB0070",
725 .frequency_min_hz = 45 * MHz,
726 .frequency_max_hz = 860 * MHz,
727 .frequency_step_hz = 1 * kHz,
729 .release = dib0070_release,
731 .init = dib0070_wakeup,
732 .sleep = dib0070_sleep,
733 .set_params = dib0070_tune,
735 .get_frequency = dib0070_get_frequency,
736 // .get_bandwidth = dib0070_get_bandwidth
739 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
741 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
742 if (state == NULL)
743 return NULL;
745 state->cfg = cfg;
746 state->i2c = i2c;
747 state->fe = fe;
748 mutex_init(&state->i2c_buffer_lock);
749 fe->tuner_priv = state;
751 if (dib0070_reset(fe) != 0)
752 goto free_mem;
754 pr_info("DiB0070: successfully identified\n");
755 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
757 fe->tuner_priv = state;
758 return fe;
760 free_mem:
761 kfree(state);
762 fe->tuner_priv = NULL;
763 return NULL;
765 EXPORT_SYMBOL(dib0070_attach);
767 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
768 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
769 MODULE_LICENSE("GPL");