1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
4  *
5  * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
6  *
7  * This code is more or less generated from another driver, please
8  * excuse some codingstyle oddities.
9  */
10 
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/i2c.h>
16 #include <linux/mutex.h>
17 
18 #include <media/dvb_frontend.h>
19 
20 #include "dib0070.h"
21 #include "dibx000_common.h"
22 
23 static int debug;
24 module_param(debug, int, 0644);
25 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
26 
27 #define dprintk(fmt, arg...) do {					\
28 	if (debug)							\
29 		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
30 		       __func__, ##arg);				\
31 } while (0)
32 
33 #define DIB0070_P1D  0x00
34 #define DIB0070_P1F  0x01
35 #define DIB0070_P1G  0x03
36 #define DIB0070S_P1A 0x02
37 
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;
44 
45 	enum frontend_tune_state tune_state;
46 	u32 current_rf;
47 
48 	/* for the captrim binary search */
49 	s8 step;
50 	u16 adc_diff;
51 
52 	s8 captrim;
53 	s8 fcaptrim;
54 	u16 lo4;
55 
56 	const struct dib0070_tuning *current_tune_table_index;
57 	const struct dib0070_lna_match *lna_match;
58 
59 	u8  wbd_gain_current;
60 	u16 wbd_offset_3_3[2];
61 
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;
67 };
68 
69 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
70 {
71 	u16 ret;
72 
73 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
74 		dprintk("could not acquire lock\n");
75 		return 0;
76 	}
77 
78 	state->i2c_write_buffer[0] = reg;
79 
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;
89 
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];
96 
97 	mutex_unlock(&state->i2c_buffer_lock);
98 	return ret;
99 }
100 
101 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
102 {
103 	int ret;
104 
105 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
106 		dprintk("could not acquire lock\n");
107 		return -EINVAL;
108 	}
109 	state->i2c_write_buffer[0] = reg;
110 	state->i2c_write_buffer[1] = val >> 8;
111 	state->i2c_write_buffer[2] = val & 0xff;
112 
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;
118 
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;
124 
125 	mutex_unlock(&state->i2c_buffer_lock);
126 	return ret;
127 }
128 
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); \
134     } \
135 } while (0)
136 
137 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
138 	{
139 	struct dib0070_state *state = fe->tuner_priv;
140 	u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
141 
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);
150 
151 	dib0070_write_reg(state, 0x02, tmp);
152 
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);
156 
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));
160 
161 		dib0070_write_reg(state, 0x17, value);
162 	}
163 	return 0;
164 }
165 
166 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
167 {
168 	int8_t step_sign;
169 	u16 adc;
170 	int ret = 0;
171 
172 	if (*tune_state == CT_TUNER_STEP_0) {
173 		dib0070_write_reg(state, 0x0f, 0xed10);
174 		dib0070_write_reg(state, 0x17,    0x0034);
175 
176 		dib0070_write_reg(state, 0x18, 0x0032);
177 		state->step = state->captrim = state->fcaptrim = 64;
178 		state->adc_diff = 3000;
179 		ret = 20;
180 
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;
186 
187 		*tune_state = CT_TUNER_STEP_2;
188 	} else if (*tune_state == CT_TUNER_STEP_2) {
189 
190 		adc = dib0070_read_reg(state, 0x19);
191 
192 		dprintk("CAPTRIM=%d; ADC = %hd (ADC) & %dmV\n", state->captrim,
193 			adc, (u32)adc * (u32)1800 / (u32)1024);
194 
195 		if (adc >= 400) {
196 			adc -= 400;
197 			step_sign = -1;
198 		} else {
199 			adc = 400 - adc;
200 			step_sign = 1;
201 		}
202 
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;
208 		}
209 		state->captrim += (step_sign * state->step);
210 
211 		if (state->step >= 1)
212 			*tune_state = CT_TUNER_STEP_1;
213 		else
214 			*tune_state = CT_TUNER_STEP_3;
215 
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;
220 	}
221 
222 	return ret;
223 }
224 
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)
226 {
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);
229 
230 	dprintk("CTRL_LO5: 0x%x\n", lo5);
231 	return dib0070_write_reg(state, 0x15, lo5);
232 }
233 
234 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
235 {
236 	struct dib0070_state *state = fe->tuner_priv;
237 
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);
248 	}
249 }
250 
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;
261 };
262 
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;
266 };
267 
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 */
276 };
277 
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 */
287 };
288 
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 },
302 };
303 
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 },
318 };
319 
320 #define LPF	100
321 static int dib0070_tune_digital(struct dvb_frontend *fe)
322 {
323 	struct dib0070_state *state = fe->tuner_priv;
324 
325 	const struct dib0070_tuning *tune;
326 	const struct dib0070_lna_match *lna_match;
327 
328 	enum frontend_tune_state *tune_state = &state->tune_state;
329 	int ret = 10; /* 1ms is the default delay most of the time */
330 
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);
333 
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) {
345 
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;
358 		}
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++;
363 
364 		state->current_tune_table_index = tune;
365 		state->lna_match = lna_match;
366 	}
367 
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;
374 
375 			state->current_rf = freq;
376 			state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
377 
378 
379 			dib0070_write_reg(state, 0x17, 0x30);
380 
381 
382 			VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
383 
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;
394 			}
395 			FREF = state->cfg->clock_khz / REFDIV;
396 
397 
398 
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;
404 
405 			case DIB0070_P1G:
406 			case DIB0070_P1F:
407 			default:
408 				FBDiv = (freq / (FREF / 2));
409 				Rest  = 2 * freq - FBDiv * FREF;
410 				break;
411 			}
412 
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);
423 
424 			Den = 1;
425 			if (Rest > 0) {
426 				state->lo4 |= (1 << 14) | (1 << 12);
427 				Den = 255;
428 			}
429 
430 
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);
434 
435 			if (state->revision == DIB0070S_P1A) {
436 
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);
442 			}
443 
444 			dib0070_write_reg(state, 0x20,
445 				0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
446 
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);
458 
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;
463 		}
464 	} else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
465 
466 		ret = dib0070_captrim(state, tune_state);
467 
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;
484 		}
485 
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);
491 
492 
493 		dib0070_write_reg(state, 0x18,   0x07ff);
494 		dib0070_write_reg(state, 0x17, 0x0033);
495 
496 
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 */
503 	}
504 	return ret;
505 }
506 
507 
508 static int dib0070_tune(struct dvb_frontend *fe)
509 {
510 	struct dib0070_state *state = fe->tuner_priv;
511 	uint32_t ret;
512 
513 	state->tune_state = CT_TUNER_START;
514 
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);
522 
523 	return 0;
524 }
525 
526 static int dib0070_wakeup(struct dvb_frontend *fe)
527 {
528 	struct dib0070_state *state = fe->tuner_priv;
529 	if (state->cfg->sleep)
530 		state->cfg->sleep(fe, 0);
531 	return 0;
532 }
533 
534 static int dib0070_sleep(struct dvb_frontend *fe)
535 {
536 	struct dib0070_state *state = fe->tuner_priv;
537 	if (state->cfg->sleep)
538 		state->cfg->sleep(fe, 1);
539 	return 0;
540 }
541 
542 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
543 {
544 	struct dib0070_state *state = fe->tuner_priv;
545 	return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
546 }
547 EXPORT_SYMBOL(dib0070_get_rf_output);
548 
549 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
550 {
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));
558 }
559 EXPORT_SYMBOL(dib0070_set_rf_output);
560 
561 static const u16 dib0070_p1f_defaults[] =
562 
563 {
564 	7, 0x02,
565 		0x0008,
566 		0x0000,
567 		0x0000,
568 		0x0000,
569 		0x0000,
570 		0x0002,
571 		0x0100,
572 
573 	3, 0x0d,
574 		0x0d80,
575 		0x0001,
576 		0x0000,
577 
578 	4, 0x11,
579 		0x0000,
580 		0x0103,
581 		0x0000,
582 		0x0000,
583 
584 	3, 0x16,
585 		0x0004 | 0x0040,
586 		0x0030,
587 		0x07ff,
588 
589 	6, 0x1b,
590 		0x4112,
591 		0xff00,
592 		0xc07f,
593 		0x0000,
594 		0x0180,
595 		0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
596 
597 	0,
598 };
599 
600 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
601 {
602 	u16 tuner_en = dib0070_read_reg(state, 0x20);
603 	u16 offset;
604 
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;
612 }
613 
614 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
615 {
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]);
620 	}
621 }
622 
623 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
624 {
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;
628 
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;
635 
636 	return state->wbd_offset_3_3[state->wbd_gain_current - 6];
637 }
638 EXPORT_SYMBOL(dib0070_wbd_offset);
639 
640 #define pgm_read_word(w) (*w)
641 static int dib0070_reset(struct dvb_frontend *fe)
642 {
643 	struct dib0070_state *state = fe->tuner_priv;
644 	u16 l, r, *n;
645 
646 	HARD_RESET(state);
647 
648 
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;
657 
658 	/* P1F or not */
659 	dprintk("Revision: %x\n", state->revision);
660 
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;
664 	}
665 
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++);
675 	}
676 
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;
683 
684 
685 	r |= state->cfg->osc_buffer_state << 3;
686 
687 	dib0070_write_reg(state, 0x10, r);
688 	dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
689 
690 	if (state->cfg->invert_iq) {
691 		r = dib0070_read_reg(state, 0x02) & 0xffdf;
692 		dib0070_write_reg(state, 0x02, r | (1 << 5));
693 	}
694 
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);
700 
701 	dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
702 
703 	dib0070_wbd_offset_calibration(state);
704 
705 	return 0;
706 }
707 
708 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
709 {
710 	struct dib0070_state *state = fe->tuner_priv;
711 
712 	*frequency = 1000 * state->current_rf;
713 	return 0;
714 }
715 
716 static void dib0070_release(struct dvb_frontend *fe)
717 {
718 	kfree(fe->tuner_priv);
719 	fe->tuner_priv = NULL;
720 }
721 
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,
728 	},
729 	.release       = dib0070_release,
730 
731 	.init          = dib0070_wakeup,
732 	.sleep         = dib0070_sleep,
733 	.set_params    = dib0070_tune,
734 
735 	.get_frequency = dib0070_get_frequency,
736 //      .get_bandwidth = dib0070_get_bandwidth
737 };
738 
739 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
740 {
741 	struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
742 	if (state == NULL)
743 		return NULL;
744 
745 	state->cfg = cfg;
746 	state->i2c = i2c;
747 	state->fe  = fe;
748 	mutex_init(&state->i2c_buffer_lock);
749 	fe->tuner_priv = state;
750 
751 	if (dib0070_reset(fe) != 0)
752 		goto free_mem;
753 
754 	pr_info("DiB0070: successfully identified\n");
755 	memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
756 
757 	fe->tuner_priv = state;
758 	return fe;
759 
760 free_mem:
761 	kfree(state);
762 	fe->tuner_priv = NULL;
763 	return NULL;
764 }
765 EXPORT_SYMBOL(dib0070_attach);
766 
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");
770