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