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