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