xref: /openbmc/linux/drivers/media/dvb-frontends/dib0070.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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  
dib0070_read_reg(struct dib0070_state * state,u8 reg)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  
dib0070_write_reg(struct dib0070_state * state,u8 reg,u16 val)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  
dib0070_set_bandwidth(struct dvb_frontend * fe)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  
dib0070_captrim(struct dib0070_state * state,enum frontend_tune_state * tune_state)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  
dib0070_set_ctrl_lo5(struct dvb_frontend * fe,u8 vco_bias_trim,u8 hf_div_trim,u8 cp_current,u8 third_order_filt)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  
dib0070_ctrl_agc_filter(struct dvb_frontend * fe,u8 open)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
dib0070_tune_digital(struct dvb_frontend * fe)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  
dib0070_tune(struct dvb_frontend * fe)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  
dib0070_wakeup(struct dvb_frontend * fe)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  
dib0070_sleep(struct dvb_frontend * fe)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  
dib0070_get_rf_output(struct dvb_frontend * fe)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  
dib0070_set_rf_output(struct dvb_frontend * fe,u8 no)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  
dib0070_read_wbd_offset(struct dib0070_state * state,u8 gain)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  
dib0070_wbd_offset_calibration(struct dib0070_state * state)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  
dib0070_wbd_offset(struct dvb_frontend * fe)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)
dib0070_reset(struct dvb_frontend * fe)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  
dib0070_get_frequency(struct dvb_frontend * fe,u32 * frequency)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  
dib0070_release(struct dvb_frontend * fe)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  
dib0070_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c,struct dib0070_config * cfg)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_GPL(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