interconnect: qcom: Fix Kconfig indentation
[linux/fpc-iii.git] / drivers / media / dvb-frontends / dib0070.c
blob3b26f61785d8c9804595a2326c8b655f274e2ab2
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=%hd; ADC = %hd (ADC) & %dmV\n", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
194 if (adc >= 400) {
195 adc -= 400;
196 step_sign = -1;
197 } else {
198 adc = 400 - adc;
199 step_sign = 1;
202 if (adc < state->adc_diff) {
203 dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)\n", state->captrim, adc, state->adc_diff);
204 state->adc_diff = adc;
205 state->fcaptrim = state->captrim;
207 state->captrim += (step_sign * state->step);
209 if (state->step >= 1)
210 *tune_state = CT_TUNER_STEP_1;
211 else
212 *tune_state = CT_TUNER_STEP_3;
214 } else if (*tune_state == CT_TUNER_STEP_3) {
215 dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
216 dib0070_write_reg(state, 0x18, 0x07ff);
217 *tune_state = CT_TUNER_STEP_4;
220 return ret;
223 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)
225 struct dib0070_state *state = fe->tuner_priv;
226 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
228 dprintk("CTRL_LO5: 0x%x\n", lo5);
229 return dib0070_write_reg(state, 0x15, lo5);
232 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
234 struct dib0070_state *state = fe->tuner_priv;
236 if (open) {
237 dib0070_write_reg(state, 0x1b, 0xff00);
238 dib0070_write_reg(state, 0x1a, 0x0000);
239 } else {
240 dib0070_write_reg(state, 0x1b, 0x4112);
241 if (state->cfg->vga_filter != 0) {
242 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
243 dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
244 } else
245 dib0070_write_reg(state, 0x1a, 0x0009);
249 EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
250 struct dib0070_tuning {
251 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
252 u8 switch_trim;
253 u8 vco_band;
254 u8 hfdiv;
255 u8 vco_multi;
256 u8 presc;
257 u8 wbdmux;
258 u16 tuner_enable;
261 struct dib0070_lna_match {
262 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
263 u8 lna_band;
266 static const struct dib0070_tuning dib0070s_tuning_table[] = {
267 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
268 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
269 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
270 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
271 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
272 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
273 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
276 static const struct dib0070_tuning dib0070_tuning_table[] = {
277 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
278 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
279 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
280 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
281 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
282 { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
283 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
284 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
287 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
288 { 180000, 0 }, /* VHF */
289 { 188000, 1 },
290 { 196400, 2 },
291 { 250000, 3 },
292 { 550000, 0 }, /* UHF */
293 { 590000, 1 },
294 { 666000, 3 },
295 { 864000, 5 },
296 { 1500000, 0 }, /* LBAND or everything higher than UHF */
297 { 1600000, 1 },
298 { 2000000, 3 },
299 { 0xffffffff, 7 },
302 static const struct dib0070_lna_match dib0070_lna[] = {
303 { 180000, 0 }, /* VHF */
304 { 188000, 1 },
305 { 196400, 2 },
306 { 250000, 3 },
307 { 550000, 2 }, /* UHF */
308 { 650000, 3 },
309 { 750000, 5 },
310 { 850000, 6 },
311 { 864000, 7 },
312 { 1500000, 0 }, /* LBAND or everything higher than UHF */
313 { 1600000, 1 },
314 { 2000000, 3 },
315 { 0xffffffff, 7 },
318 #define LPF 100
319 static int dib0070_tune_digital(struct dvb_frontend *fe)
321 struct dib0070_state *state = fe->tuner_priv;
323 const struct dib0070_tuning *tune;
324 const struct dib0070_lna_match *lna_match;
326 enum frontend_tune_state *tune_state = &state->tune_state;
327 int ret = 10; /* 1ms is the default delay most of the time */
329 u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
330 u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
332 #ifdef CONFIG_SYS_ISDBT
333 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
334 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
335 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
336 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
337 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
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) + 1))))
340 freq += 850;
341 #endif
342 if (state->current_rf != freq) {
344 switch (state->revision) {
345 case DIB0070S_P1A:
346 tune = dib0070s_tuning_table;
347 lna_match = dib0070_lna;
348 break;
349 default:
350 tune = dib0070_tuning_table;
351 if (state->cfg->flip_chip)
352 lna_match = dib0070_lna_flip_chip;
353 else
354 lna_match = dib0070_lna;
355 break;
357 while (freq > tune->max_freq) /* find the right one */
358 tune++;
359 while (freq > lna_match->max_freq) /* find the right one */
360 lna_match++;
362 state->current_tune_table_index = tune;
363 state->lna_match = lna_match;
366 if (*tune_state == CT_TUNER_START) {
367 dprintk("Tuning for Band: %hd (%d kHz)\n", band, freq);
368 if (state->current_rf != freq) {
369 u8 REFDIV;
370 u32 FBDiv, Rest, FREF, VCOF_kHz;
371 u8 Den;
373 state->current_rf = freq;
374 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
377 dib0070_write_reg(state, 0x17, 0x30);
380 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
382 switch (band) {
383 case BAND_VHF:
384 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
385 break;
386 case BAND_FM:
387 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
388 break;
389 default:
390 REFDIV = (u8) (state->cfg->clock_khz / 10000);
391 break;
393 FREF = state->cfg->clock_khz / REFDIV;
397 switch (state->revision) {
398 case DIB0070S_P1A:
399 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
400 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
401 break;
403 case DIB0070_P1G:
404 case DIB0070_P1F:
405 default:
406 FBDiv = (freq / (FREF / 2));
407 Rest = 2 * freq - FBDiv * FREF;
408 break;
411 if (Rest < LPF)
412 Rest = 0;
413 else if (Rest < 2 * LPF)
414 Rest = 2 * LPF;
415 else if (Rest > (FREF - LPF)) {
416 Rest = 0;
417 FBDiv += 1;
418 } else if (Rest > (FREF - 2 * LPF))
419 Rest = FREF - 2 * LPF;
420 Rest = (Rest * 6528) / (FREF / 10);
422 Den = 1;
423 if (Rest > 0) {
424 state->lo4 |= (1 << 14) | (1 << 12);
425 Den = 255;
429 dib0070_write_reg(state, 0x11, (u16)FBDiv);
430 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
431 dib0070_write_reg(state, 0x13, (u16) Rest);
433 if (state->revision == DIB0070S_P1A) {
435 if (band == BAND_SBAND) {
436 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
437 dib0070_write_reg(state, 0x1d, 0xFFFF);
438 } else
439 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
442 dib0070_write_reg(state, 0x20,
443 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
445 dprintk("REFDIV: %hd, FREF: %d\n", REFDIV, FREF);
446 dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
447 dprintk("Num: %hd, Den: %hd, SD: %hd\n", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
448 dprintk("HFDIV code: %hd\n", state->current_tune_table_index->hfdiv);
449 dprintk("VCO = %hd\n", state->current_tune_table_index->vco_band);
450 dprintk("VCOF: ((%hd*%d) << 1))\n", state->current_tune_table_index->vco_multi, freq);
452 *tune_state = CT_TUNER_STEP_0;
453 } else { /* we are already tuned to this frequency - the configuration is correct */
454 ret = 50; /* wakeup time */
455 *tune_state = CT_TUNER_STEP_5;
457 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
459 ret = dib0070_captrim(state, tune_state);
461 } else if (*tune_state == CT_TUNER_STEP_4) {
462 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
463 if (tmp != NULL) {
464 while (freq/1000 > tmp->freq) /* find the right one */
465 tmp++;
466 dib0070_write_reg(state, 0x0f,
467 (0 << 15) | (1 << 14) | (3 << 12)
468 | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
469 | (state->current_tune_table_index->wbdmux << 0));
470 state->wbd_gain_current = tmp->wbd_gain_val;
471 } else {
472 dib0070_write_reg(state, 0x0f,
473 (0 << 15) | (1 << 14) | (3 << 12)
474 | (6 << 9) | (0 << 8) | (1 << 7)
475 | (state->current_tune_table_index->wbdmux << 0));
476 state->wbd_gain_current = 6;
479 dib0070_write_reg(state, 0x06, 0x3fff);
480 dib0070_write_reg(state, 0x07,
481 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
482 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
483 dib0070_write_reg(state, 0x0d, 0x0d80);
486 dib0070_write_reg(state, 0x18, 0x07ff);
487 dib0070_write_reg(state, 0x17, 0x0033);
490 *tune_state = CT_TUNER_STEP_5;
491 } else if (*tune_state == CT_TUNER_STEP_5) {
492 dib0070_set_bandwidth(fe);
493 *tune_state = CT_TUNER_STOP;
494 } else {
495 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
497 return ret;
501 static int dib0070_tune(struct dvb_frontend *fe)
503 struct dib0070_state *state = fe->tuner_priv;
504 uint32_t ret;
506 state->tune_state = CT_TUNER_START;
508 do {
509 ret = dib0070_tune_digital(fe);
510 if (ret != FE_CALLBACK_TIME_NEVER)
511 msleep(ret/10);
512 else
513 break;
514 } while (state->tune_state != CT_TUNER_STOP);
516 return 0;
519 static int dib0070_wakeup(struct dvb_frontend *fe)
521 struct dib0070_state *state = fe->tuner_priv;
522 if (state->cfg->sleep)
523 state->cfg->sleep(fe, 0);
524 return 0;
527 static int dib0070_sleep(struct dvb_frontend *fe)
529 struct dib0070_state *state = fe->tuner_priv;
530 if (state->cfg->sleep)
531 state->cfg->sleep(fe, 1);
532 return 0;
535 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
537 struct dib0070_state *state = fe->tuner_priv;
538 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
540 EXPORT_SYMBOL(dib0070_get_rf_output);
542 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
544 struct dib0070_state *state = fe->tuner_priv;
545 u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
546 if (no > 3)
547 no = 3;
548 if (no < 1)
549 no = 1;
550 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
552 EXPORT_SYMBOL(dib0070_set_rf_output);
554 static const u16 dib0070_p1f_defaults[] =
557 7, 0x02,
558 0x0008,
559 0x0000,
560 0x0000,
561 0x0000,
562 0x0000,
563 0x0002,
564 0x0100,
566 3, 0x0d,
567 0x0d80,
568 0x0001,
569 0x0000,
571 4, 0x11,
572 0x0000,
573 0x0103,
574 0x0000,
575 0x0000,
577 3, 0x16,
578 0x0004 | 0x0040,
579 0x0030,
580 0x07ff,
582 6, 0x1b,
583 0x4112,
584 0xff00,
585 0xc07f,
586 0x0000,
587 0x0180,
588 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
593 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
595 u16 tuner_en = dib0070_read_reg(state, 0x20);
596 u16 offset;
598 dib0070_write_reg(state, 0x18, 0x07ff);
599 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
600 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
601 msleep(9);
602 offset = dib0070_read_reg(state, 0x19);
603 dib0070_write_reg(state, 0x20, tuner_en);
604 return offset;
607 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
609 u8 gain;
610 for (gain = 6; gain < 8; gain++) {
611 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
612 dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
616 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
618 struct dib0070_state *state = fe->tuner_priv;
619 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
620 u32 freq = fe->dtv_property_cache.frequency/1000;
622 if (tmp != NULL) {
623 while (freq/1000 > tmp->freq) /* find the right one */
624 tmp++;
625 state->wbd_gain_current = tmp->wbd_gain_val;
626 } else
627 state->wbd_gain_current = 6;
629 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
631 EXPORT_SYMBOL(dib0070_wbd_offset);
633 #define pgm_read_word(w) (*w)
634 static int dib0070_reset(struct dvb_frontend *fe)
636 struct dib0070_state *state = fe->tuner_priv;
637 u16 l, r, *n;
639 HARD_RESET(state);
642 #ifndef FORCE_SBAND_TUNER
643 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
644 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
645 else
646 #else
647 #warning forcing SBAND
648 #endif
649 state->revision = DIB0070S_P1A;
651 /* P1F or not */
652 dprintk("Revision: %x\n", state->revision);
654 if (state->revision == DIB0070_P1D) {
655 dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
656 return -EINVAL;
659 n = (u16 *) dib0070_p1f_defaults;
660 l = pgm_read_word(n++);
661 while (l) {
662 r = pgm_read_word(n++);
663 do {
664 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
665 r++;
666 } while (--l);
667 l = pgm_read_word(n++);
670 if (state->cfg->force_crystal_mode != 0)
671 r = state->cfg->force_crystal_mode;
672 else if (state->cfg->clock_khz >= 24000)
673 r = 1;
674 else
675 r = 2;
678 r |= state->cfg->osc_buffer_state << 3;
680 dib0070_write_reg(state, 0x10, r);
681 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
683 if (state->cfg->invert_iq) {
684 r = dib0070_read_reg(state, 0x02) & 0xffdf;
685 dib0070_write_reg(state, 0x02, r | (1 << 5));
688 if (state->revision == DIB0070S_P1A)
689 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
690 else
691 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
692 state->cfg->enable_third_order_filter);
694 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
696 dib0070_wbd_offset_calibration(state);
698 return 0;
701 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
703 struct dib0070_state *state = fe->tuner_priv;
705 *frequency = 1000 * state->current_rf;
706 return 0;
709 static void dib0070_release(struct dvb_frontend *fe)
711 kfree(fe->tuner_priv);
712 fe->tuner_priv = NULL;
715 static const struct dvb_tuner_ops dib0070_ops = {
716 .info = {
717 .name = "DiBcom DiB0070",
718 .frequency_min_hz = 45 * MHz,
719 .frequency_max_hz = 860 * MHz,
720 .frequency_step_hz = 1 * kHz,
722 .release = dib0070_release,
724 .init = dib0070_wakeup,
725 .sleep = dib0070_sleep,
726 .set_params = dib0070_tune,
728 .get_frequency = dib0070_get_frequency,
729 // .get_bandwidth = dib0070_get_bandwidth
732 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
734 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
735 if (state == NULL)
736 return NULL;
738 state->cfg = cfg;
739 state->i2c = i2c;
740 state->fe = fe;
741 mutex_init(&state->i2c_buffer_lock);
742 fe->tuner_priv = state;
744 if (dib0070_reset(fe) != 0)
745 goto free_mem;
747 pr_info("DiB0070: successfully identified\n");
748 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
750 fe->tuner_priv = state;
751 return fe;
753 free_mem:
754 kfree(state);
755 fe->tuner_priv = NULL;
756 return NULL;
758 EXPORT_SYMBOL(dib0070_attach);
760 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
761 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
762 MODULE_LICENSE("GPL");