xref: /openbmc/linux/drivers/media/dvb-frontends/dib7000p.c (revision 9a0bf528b4d66b605f02634236da085595c22101)
1*9a0bf528SMauro Carvalho Chehab /*
2*9a0bf528SMauro Carvalho Chehab  * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3*9a0bf528SMauro Carvalho Chehab  *
4*9a0bf528SMauro Carvalho Chehab  * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
5*9a0bf528SMauro Carvalho Chehab  *
6*9a0bf528SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or
7*9a0bf528SMauro Carvalho Chehab  *	modify it under the terms of the GNU General Public License as
8*9a0bf528SMauro Carvalho Chehab  *	published by the Free Software Foundation, version 2.
9*9a0bf528SMauro Carvalho Chehab  */
10*9a0bf528SMauro Carvalho Chehab #include <linux/kernel.h>
11*9a0bf528SMauro Carvalho Chehab #include <linux/slab.h>
12*9a0bf528SMauro Carvalho Chehab #include <linux/i2c.h>
13*9a0bf528SMauro Carvalho Chehab #include <linux/mutex.h>
14*9a0bf528SMauro Carvalho Chehab 
15*9a0bf528SMauro Carvalho Chehab #include "dvb_math.h"
16*9a0bf528SMauro Carvalho Chehab #include "dvb_frontend.h"
17*9a0bf528SMauro Carvalho Chehab 
18*9a0bf528SMauro Carvalho Chehab #include "dib7000p.h"
19*9a0bf528SMauro Carvalho Chehab 
20*9a0bf528SMauro Carvalho Chehab static int debug;
21*9a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644);
22*9a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
23*9a0bf528SMauro Carvalho Chehab 
24*9a0bf528SMauro Carvalho Chehab static int buggy_sfn_workaround;
25*9a0bf528SMauro Carvalho Chehab module_param(buggy_sfn_workaround, int, 0644);
26*9a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
27*9a0bf528SMauro Carvalho Chehab 
28*9a0bf528SMauro Carvalho Chehab #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
29*9a0bf528SMauro Carvalho Chehab 
30*9a0bf528SMauro Carvalho Chehab struct i2c_device {
31*9a0bf528SMauro Carvalho Chehab 	struct i2c_adapter *i2c_adap;
32*9a0bf528SMauro Carvalho Chehab 	u8 i2c_addr;
33*9a0bf528SMauro Carvalho Chehab };
34*9a0bf528SMauro Carvalho Chehab 
35*9a0bf528SMauro Carvalho Chehab struct dib7000p_state {
36*9a0bf528SMauro Carvalho Chehab 	struct dvb_frontend demod;
37*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_config cfg;
38*9a0bf528SMauro Carvalho Chehab 
39*9a0bf528SMauro Carvalho Chehab 	u8 i2c_addr;
40*9a0bf528SMauro Carvalho Chehab 	struct i2c_adapter *i2c_adap;
41*9a0bf528SMauro Carvalho Chehab 
42*9a0bf528SMauro Carvalho Chehab 	struct dibx000_i2c_master i2c_master;
43*9a0bf528SMauro Carvalho Chehab 
44*9a0bf528SMauro Carvalho Chehab 	u16 wbd_ref;
45*9a0bf528SMauro Carvalho Chehab 
46*9a0bf528SMauro Carvalho Chehab 	u8 current_band;
47*9a0bf528SMauro Carvalho Chehab 	u32 current_bandwidth;
48*9a0bf528SMauro Carvalho Chehab 	struct dibx000_agc_config *current_agc;
49*9a0bf528SMauro Carvalho Chehab 	u32 timf;
50*9a0bf528SMauro Carvalho Chehab 
51*9a0bf528SMauro Carvalho Chehab 	u8 div_force_off:1;
52*9a0bf528SMauro Carvalho Chehab 	u8 div_state:1;
53*9a0bf528SMauro Carvalho Chehab 	u16 div_sync_wait;
54*9a0bf528SMauro Carvalho Chehab 
55*9a0bf528SMauro Carvalho Chehab 	u8 agc_state;
56*9a0bf528SMauro Carvalho Chehab 
57*9a0bf528SMauro Carvalho Chehab 	u16 gpio_dir;
58*9a0bf528SMauro Carvalho Chehab 	u16 gpio_val;
59*9a0bf528SMauro Carvalho Chehab 
60*9a0bf528SMauro Carvalho Chehab 	u8 sfn_workaround_active:1;
61*9a0bf528SMauro Carvalho Chehab 
62*9a0bf528SMauro Carvalho Chehab #define SOC7090 0x7090
63*9a0bf528SMauro Carvalho Chehab 	u16 version;
64*9a0bf528SMauro Carvalho Chehab 
65*9a0bf528SMauro Carvalho Chehab 	u16 tuner_enable;
66*9a0bf528SMauro Carvalho Chehab 	struct i2c_adapter dib7090_tuner_adap;
67*9a0bf528SMauro Carvalho Chehab 
68*9a0bf528SMauro Carvalho Chehab 	/* for the I2C transfer */
69*9a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg[2];
70*9a0bf528SMauro Carvalho Chehab 	u8 i2c_write_buffer[4];
71*9a0bf528SMauro Carvalho Chehab 	u8 i2c_read_buffer[2];
72*9a0bf528SMauro Carvalho Chehab 	struct mutex i2c_buffer_lock;
73*9a0bf528SMauro Carvalho Chehab 
74*9a0bf528SMauro Carvalho Chehab 	u8 input_mode_mpeg;
75*9a0bf528SMauro Carvalho Chehab };
76*9a0bf528SMauro Carvalho Chehab 
77*9a0bf528SMauro Carvalho Chehab enum dib7000p_power_mode {
78*9a0bf528SMauro Carvalho Chehab 	DIB7000P_POWER_ALL = 0,
79*9a0bf528SMauro Carvalho Chehab 	DIB7000P_POWER_ANALOG_ADC,
80*9a0bf528SMauro Carvalho Chehab 	DIB7000P_POWER_INTERFACE_ONLY,
81*9a0bf528SMauro Carvalho Chehab };
82*9a0bf528SMauro Carvalho Chehab 
83*9a0bf528SMauro Carvalho Chehab /* dib7090 specific fonctions */
84*9a0bf528SMauro Carvalho Chehab static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
85*9a0bf528SMauro Carvalho Chehab static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
86*9a0bf528SMauro Carvalho Chehab static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
87*9a0bf528SMauro Carvalho Chehab static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
88*9a0bf528SMauro Carvalho Chehab 
89*9a0bf528SMauro Carvalho Chehab static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
90*9a0bf528SMauro Carvalho Chehab {
91*9a0bf528SMauro Carvalho Chehab 	u16 ret;
92*9a0bf528SMauro Carvalho Chehab 
93*9a0bf528SMauro Carvalho Chehab 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
94*9a0bf528SMauro Carvalho Chehab 		dprintk("could not acquire lock");
95*9a0bf528SMauro Carvalho Chehab 		return 0;
96*9a0bf528SMauro Carvalho Chehab 	}
97*9a0bf528SMauro Carvalho Chehab 
98*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[0] = reg >> 8;
99*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[1] = reg & 0xff;
100*9a0bf528SMauro Carvalho Chehab 
101*9a0bf528SMauro Carvalho Chehab 	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
102*9a0bf528SMauro Carvalho Chehab 	state->msg[0].addr = state->i2c_addr >> 1;
103*9a0bf528SMauro Carvalho Chehab 	state->msg[0].flags = 0;
104*9a0bf528SMauro Carvalho Chehab 	state->msg[0].buf = state->i2c_write_buffer;
105*9a0bf528SMauro Carvalho Chehab 	state->msg[0].len = 2;
106*9a0bf528SMauro Carvalho Chehab 	state->msg[1].addr = state->i2c_addr >> 1;
107*9a0bf528SMauro Carvalho Chehab 	state->msg[1].flags = I2C_M_RD;
108*9a0bf528SMauro Carvalho Chehab 	state->msg[1].buf = state->i2c_read_buffer;
109*9a0bf528SMauro Carvalho Chehab 	state->msg[1].len = 2;
110*9a0bf528SMauro Carvalho Chehab 
111*9a0bf528SMauro Carvalho Chehab 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
112*9a0bf528SMauro Carvalho Chehab 		dprintk("i2c read error on %d", reg);
113*9a0bf528SMauro Carvalho Chehab 
114*9a0bf528SMauro Carvalho Chehab 	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
115*9a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->i2c_buffer_lock);
116*9a0bf528SMauro Carvalho Chehab 	return ret;
117*9a0bf528SMauro Carvalho Chehab }
118*9a0bf528SMauro Carvalho Chehab 
119*9a0bf528SMauro Carvalho Chehab static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
120*9a0bf528SMauro Carvalho Chehab {
121*9a0bf528SMauro Carvalho Chehab 	int ret;
122*9a0bf528SMauro Carvalho Chehab 
123*9a0bf528SMauro Carvalho Chehab 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
124*9a0bf528SMauro Carvalho Chehab 		dprintk("could not acquire lock");
125*9a0bf528SMauro Carvalho Chehab 		return -EINVAL;
126*9a0bf528SMauro Carvalho Chehab 	}
127*9a0bf528SMauro Carvalho Chehab 
128*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
129*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[1] = reg & 0xff;
130*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
131*9a0bf528SMauro Carvalho Chehab 	state->i2c_write_buffer[3] = val & 0xff;
132*9a0bf528SMauro Carvalho Chehab 
133*9a0bf528SMauro Carvalho Chehab 	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
134*9a0bf528SMauro Carvalho Chehab 	state->msg[0].addr = state->i2c_addr >> 1;
135*9a0bf528SMauro Carvalho Chehab 	state->msg[0].flags = 0;
136*9a0bf528SMauro Carvalho Chehab 	state->msg[0].buf = state->i2c_write_buffer;
137*9a0bf528SMauro Carvalho Chehab 	state->msg[0].len = 4;
138*9a0bf528SMauro Carvalho Chehab 
139*9a0bf528SMauro Carvalho Chehab 	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
140*9a0bf528SMauro Carvalho Chehab 			-EREMOTEIO : 0);
141*9a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->i2c_buffer_lock);
142*9a0bf528SMauro Carvalho Chehab 	return ret;
143*9a0bf528SMauro Carvalho Chehab }
144*9a0bf528SMauro Carvalho Chehab 
145*9a0bf528SMauro Carvalho Chehab static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
146*9a0bf528SMauro Carvalho Chehab {
147*9a0bf528SMauro Carvalho Chehab 	u16 l = 0, r, *n;
148*9a0bf528SMauro Carvalho Chehab 	n = buf;
149*9a0bf528SMauro Carvalho Chehab 	l = *n++;
150*9a0bf528SMauro Carvalho Chehab 	while (l) {
151*9a0bf528SMauro Carvalho Chehab 		r = *n++;
152*9a0bf528SMauro Carvalho Chehab 
153*9a0bf528SMauro Carvalho Chehab 		do {
154*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, r, *n++);
155*9a0bf528SMauro Carvalho Chehab 			r++;
156*9a0bf528SMauro Carvalho Chehab 		} while (--l);
157*9a0bf528SMauro Carvalho Chehab 		l = *n++;
158*9a0bf528SMauro Carvalho Chehab 	}
159*9a0bf528SMauro Carvalho Chehab }
160*9a0bf528SMauro Carvalho Chehab 
161*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
162*9a0bf528SMauro Carvalho Chehab {
163*9a0bf528SMauro Carvalho Chehab 	int ret = 0;
164*9a0bf528SMauro Carvalho Chehab 	u16 outreg, fifo_threshold, smo_mode;
165*9a0bf528SMauro Carvalho Chehab 
166*9a0bf528SMauro Carvalho Chehab 	outreg = 0;
167*9a0bf528SMauro Carvalho Chehab 	fifo_threshold = 1792;
168*9a0bf528SMauro Carvalho Chehab 	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
169*9a0bf528SMauro Carvalho Chehab 
170*9a0bf528SMauro Carvalho Chehab 	dprintk("setting output mode for demod %p to %d", &state->demod, mode);
171*9a0bf528SMauro Carvalho Chehab 
172*9a0bf528SMauro Carvalho Chehab 	switch (mode) {
173*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_PAR_GATED_CLK:
174*9a0bf528SMauro Carvalho Chehab 		outreg = (1 << 10);	/* 0x0400 */
175*9a0bf528SMauro Carvalho Chehab 		break;
176*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_PAR_CONT_CLK:
177*9a0bf528SMauro Carvalho Chehab 		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
178*9a0bf528SMauro Carvalho Chehab 		break;
179*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_SERIAL:
180*9a0bf528SMauro Carvalho Chehab 		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0480 */
181*9a0bf528SMauro Carvalho Chehab 		break;
182*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_DIVERSITY:
183*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.hostbus_diversity)
184*9a0bf528SMauro Carvalho Chehab 			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
185*9a0bf528SMauro Carvalho Chehab 		else
186*9a0bf528SMauro Carvalho Chehab 			outreg = (1 << 11);
187*9a0bf528SMauro Carvalho Chehab 		break;
188*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_FIFO:
189*9a0bf528SMauro Carvalho Chehab 		smo_mode |= (3 << 1);
190*9a0bf528SMauro Carvalho Chehab 		fifo_threshold = 512;
191*9a0bf528SMauro Carvalho Chehab 		outreg = (1 << 10) | (5 << 6);
192*9a0bf528SMauro Carvalho Chehab 		break;
193*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_ANALOG_ADC:
194*9a0bf528SMauro Carvalho Chehab 		outreg = (1 << 10) | (3 << 6);
195*9a0bf528SMauro Carvalho Chehab 		break;
196*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_HIGH_Z:
197*9a0bf528SMauro Carvalho Chehab 		outreg = 0;
198*9a0bf528SMauro Carvalho Chehab 		break;
199*9a0bf528SMauro Carvalho Chehab 	default:
200*9a0bf528SMauro Carvalho Chehab 		dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
201*9a0bf528SMauro Carvalho Chehab 		break;
202*9a0bf528SMauro Carvalho Chehab 	}
203*9a0bf528SMauro Carvalho Chehab 
204*9a0bf528SMauro Carvalho Chehab 	if (state->cfg.output_mpeg2_in_188_bytes)
205*9a0bf528SMauro Carvalho Chehab 		smo_mode |= (1 << 5);
206*9a0bf528SMauro Carvalho Chehab 
207*9a0bf528SMauro Carvalho Chehab 	ret |= dib7000p_write_word(state, 235, smo_mode);
208*9a0bf528SMauro Carvalho Chehab 	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
209*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090)
210*9a0bf528SMauro Carvalho Chehab 		ret |= dib7000p_write_word(state, 1286, outreg);	/* P_Div_active */
211*9a0bf528SMauro Carvalho Chehab 
212*9a0bf528SMauro Carvalho Chehab 	return ret;
213*9a0bf528SMauro Carvalho Chehab }
214*9a0bf528SMauro Carvalho Chehab 
215*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
216*9a0bf528SMauro Carvalho Chehab {
217*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
218*9a0bf528SMauro Carvalho Chehab 
219*9a0bf528SMauro Carvalho Chehab 	if (state->div_force_off) {
220*9a0bf528SMauro Carvalho Chehab 		dprintk("diversity combination deactivated - forced by COFDM parameters");
221*9a0bf528SMauro Carvalho Chehab 		onoff = 0;
222*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 207, 0);
223*9a0bf528SMauro Carvalho Chehab 	} else
224*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
225*9a0bf528SMauro Carvalho Chehab 
226*9a0bf528SMauro Carvalho Chehab 	state->div_state = (u8) onoff;
227*9a0bf528SMauro Carvalho Chehab 
228*9a0bf528SMauro Carvalho Chehab 	if (onoff) {
229*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 204, 6);
230*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 205, 16);
231*9a0bf528SMauro Carvalho Chehab 		/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
232*9a0bf528SMauro Carvalho Chehab 	} else {
233*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 204, 1);
234*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 205, 0);
235*9a0bf528SMauro Carvalho Chehab 	}
236*9a0bf528SMauro Carvalho Chehab 
237*9a0bf528SMauro Carvalho Chehab 	return 0;
238*9a0bf528SMauro Carvalho Chehab }
239*9a0bf528SMauro Carvalho Chehab 
240*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
241*9a0bf528SMauro Carvalho Chehab {
242*9a0bf528SMauro Carvalho Chehab 	/* by default everything is powered off */
243*9a0bf528SMauro Carvalho Chehab 	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
244*9a0bf528SMauro Carvalho Chehab 
245*9a0bf528SMauro Carvalho Chehab 	/* now, depending on the requested mode, we power on */
246*9a0bf528SMauro Carvalho Chehab 	switch (mode) {
247*9a0bf528SMauro Carvalho Chehab 		/* power up everything in the demod */
248*9a0bf528SMauro Carvalho Chehab 	case DIB7000P_POWER_ALL:
249*9a0bf528SMauro Carvalho Chehab 		reg_774 = 0x0000;
250*9a0bf528SMauro Carvalho Chehab 		reg_775 = 0x0000;
251*9a0bf528SMauro Carvalho Chehab 		reg_776 = 0x0;
252*9a0bf528SMauro Carvalho Chehab 		reg_899 = 0x0;
253*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090)
254*9a0bf528SMauro Carvalho Chehab 			reg_1280 &= 0x001f;
255*9a0bf528SMauro Carvalho Chehab 		else
256*9a0bf528SMauro Carvalho Chehab 			reg_1280 &= 0x01ff;
257*9a0bf528SMauro Carvalho Chehab 		break;
258*9a0bf528SMauro Carvalho Chehab 
259*9a0bf528SMauro Carvalho Chehab 	case DIB7000P_POWER_ANALOG_ADC:
260*9a0bf528SMauro Carvalho Chehab 		/* dem, cfg, iqc, sad, agc */
261*9a0bf528SMauro Carvalho Chehab 		reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
262*9a0bf528SMauro Carvalho Chehab 		/* nud */
263*9a0bf528SMauro Carvalho Chehab 		reg_776 &= ~((1 << 0));
264*9a0bf528SMauro Carvalho Chehab 		/* Dout */
265*9a0bf528SMauro Carvalho Chehab 		if (state->version != SOC7090)
266*9a0bf528SMauro Carvalho Chehab 			reg_1280 &= ~((1 << 11));
267*9a0bf528SMauro Carvalho Chehab 		reg_1280 &= ~(1 << 6);
268*9a0bf528SMauro Carvalho Chehab 		/* fall through wanted to enable the interfaces */
269*9a0bf528SMauro Carvalho Chehab 
270*9a0bf528SMauro Carvalho Chehab 		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
271*9a0bf528SMauro Carvalho Chehab 	case DIB7000P_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C */
272*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090)
273*9a0bf528SMauro Carvalho Chehab 			reg_1280 &= ~((1 << 7) | (1 << 5));
274*9a0bf528SMauro Carvalho Chehab 		else
275*9a0bf528SMauro Carvalho Chehab 			reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
276*9a0bf528SMauro Carvalho Chehab 		break;
277*9a0bf528SMauro Carvalho Chehab 
278*9a0bf528SMauro Carvalho Chehab /* TODO following stuff is just converted from the dib7000-driver - check when is used what */
279*9a0bf528SMauro Carvalho Chehab 	}
280*9a0bf528SMauro Carvalho Chehab 
281*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 774, reg_774);
282*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 775, reg_775);
283*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 776, reg_776);
284*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1280, reg_1280);
285*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090)
286*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 899, reg_899);
287*9a0bf528SMauro Carvalho Chehab 
288*9a0bf528SMauro Carvalho Chehab 	return 0;
289*9a0bf528SMauro Carvalho Chehab }
290*9a0bf528SMauro Carvalho Chehab 
291*9a0bf528SMauro Carvalho Chehab static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
292*9a0bf528SMauro Carvalho Chehab {
293*9a0bf528SMauro Carvalho Chehab 	u16 reg_908 = 0, reg_909 = 0;
294*9a0bf528SMauro Carvalho Chehab 	u16 reg;
295*9a0bf528SMauro Carvalho Chehab 
296*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090) {
297*9a0bf528SMauro Carvalho Chehab 		reg_908 = dib7000p_read_word(state, 908);
298*9a0bf528SMauro Carvalho Chehab 		reg_909 = dib7000p_read_word(state, 909);
299*9a0bf528SMauro Carvalho Chehab 	}
300*9a0bf528SMauro Carvalho Chehab 
301*9a0bf528SMauro Carvalho Chehab 	switch (no) {
302*9a0bf528SMauro Carvalho Chehab 	case DIBX000_SLOW_ADC_ON:
303*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090) {
304*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 1925);
305*9a0bf528SMauro Carvalho Chehab 
306*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2));	/* en_slowAdc = 1 & reset_sladc = 1 */
307*9a0bf528SMauro Carvalho Chehab 
308*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 1925);	/* read acces to make it works... strange ... */
309*9a0bf528SMauro Carvalho Chehab 			msleep(200);
310*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 1925, reg & ~(1 << 4));	/* en_slowAdc = 1 & reset_sladc = 0 */
311*9a0bf528SMauro Carvalho Chehab 
312*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
313*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524);	/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
314*9a0bf528SMauro Carvalho Chehab 		} else {
315*9a0bf528SMauro Carvalho Chehab 			reg_909 |= (1 << 1) | (1 << 0);
316*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 909, reg_909);
317*9a0bf528SMauro Carvalho Chehab 			reg_909 &= ~(1 << 1);
318*9a0bf528SMauro Carvalho Chehab 		}
319*9a0bf528SMauro Carvalho Chehab 		break;
320*9a0bf528SMauro Carvalho Chehab 
321*9a0bf528SMauro Carvalho Chehab 	case DIBX000_SLOW_ADC_OFF:
322*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090) {
323*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 1925);
324*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4));	/* reset_sladc = 1 en_slowAdc = 0 */
325*9a0bf528SMauro Carvalho Chehab 		} else
326*9a0bf528SMauro Carvalho Chehab 			reg_909 |= (1 << 1) | (1 << 0);
327*9a0bf528SMauro Carvalho Chehab 		break;
328*9a0bf528SMauro Carvalho Chehab 
329*9a0bf528SMauro Carvalho Chehab 	case DIBX000_ADC_ON:
330*9a0bf528SMauro Carvalho Chehab 		reg_908 &= 0x0fff;
331*9a0bf528SMauro Carvalho Chehab 		reg_909 &= 0x0003;
332*9a0bf528SMauro Carvalho Chehab 		break;
333*9a0bf528SMauro Carvalho Chehab 
334*9a0bf528SMauro Carvalho Chehab 	case DIBX000_ADC_OFF:
335*9a0bf528SMauro Carvalho Chehab 		reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
336*9a0bf528SMauro Carvalho Chehab 		reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
337*9a0bf528SMauro Carvalho Chehab 		break;
338*9a0bf528SMauro Carvalho Chehab 
339*9a0bf528SMauro Carvalho Chehab 	case DIBX000_VBG_ENABLE:
340*9a0bf528SMauro Carvalho Chehab 		reg_908 &= ~(1 << 15);
341*9a0bf528SMauro Carvalho Chehab 		break;
342*9a0bf528SMauro Carvalho Chehab 
343*9a0bf528SMauro Carvalho Chehab 	case DIBX000_VBG_DISABLE:
344*9a0bf528SMauro Carvalho Chehab 		reg_908 |= (1 << 15);
345*9a0bf528SMauro Carvalho Chehab 		break;
346*9a0bf528SMauro Carvalho Chehab 
347*9a0bf528SMauro Carvalho Chehab 	default:
348*9a0bf528SMauro Carvalho Chehab 		break;
349*9a0bf528SMauro Carvalho Chehab 	}
350*9a0bf528SMauro Carvalho Chehab 
351*9a0bf528SMauro Carvalho Chehab //	dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
352*9a0bf528SMauro Carvalho Chehab 
353*9a0bf528SMauro Carvalho Chehab 	reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
354*9a0bf528SMauro Carvalho Chehab 	reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
355*9a0bf528SMauro Carvalho Chehab 
356*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090) {
357*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 908, reg_908);
358*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 909, reg_909);
359*9a0bf528SMauro Carvalho Chehab 	}
360*9a0bf528SMauro Carvalho Chehab }
361*9a0bf528SMauro Carvalho Chehab 
362*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
363*9a0bf528SMauro Carvalho Chehab {
364*9a0bf528SMauro Carvalho Chehab 	u32 timf;
365*9a0bf528SMauro Carvalho Chehab 
366*9a0bf528SMauro Carvalho Chehab 	// store the current bandwidth for later use
367*9a0bf528SMauro Carvalho Chehab 	state->current_bandwidth = bw;
368*9a0bf528SMauro Carvalho Chehab 
369*9a0bf528SMauro Carvalho Chehab 	if (state->timf == 0) {
370*9a0bf528SMauro Carvalho Chehab 		dprintk("using default timf");
371*9a0bf528SMauro Carvalho Chehab 		timf = state->cfg.bw->timf;
372*9a0bf528SMauro Carvalho Chehab 	} else {
373*9a0bf528SMauro Carvalho Chehab 		dprintk("using updated timf");
374*9a0bf528SMauro Carvalho Chehab 		timf = state->timf;
375*9a0bf528SMauro Carvalho Chehab 	}
376*9a0bf528SMauro Carvalho Chehab 
377*9a0bf528SMauro Carvalho Chehab 	timf = timf * (bw / 50) / 160;
378*9a0bf528SMauro Carvalho Chehab 
379*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
380*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
381*9a0bf528SMauro Carvalho Chehab 
382*9a0bf528SMauro Carvalho Chehab 	return 0;
383*9a0bf528SMauro Carvalho Chehab }
384*9a0bf528SMauro Carvalho Chehab 
385*9a0bf528SMauro Carvalho Chehab static int dib7000p_sad_calib(struct dib7000p_state *state)
386*9a0bf528SMauro Carvalho Chehab {
387*9a0bf528SMauro Carvalho Chehab /* internal */
388*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
389*9a0bf528SMauro Carvalho Chehab 
390*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090)
391*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 74, 2048);
392*9a0bf528SMauro Carvalho Chehab 	else
393*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 74, 776);
394*9a0bf528SMauro Carvalho Chehab 
395*9a0bf528SMauro Carvalho Chehab 	/* do the calibration */
396*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 73, (1 << 0));
397*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 73, (0 << 0));
398*9a0bf528SMauro Carvalho Chehab 
399*9a0bf528SMauro Carvalho Chehab 	msleep(1);
400*9a0bf528SMauro Carvalho Chehab 
401*9a0bf528SMauro Carvalho Chehab 	return 0;
402*9a0bf528SMauro Carvalho Chehab }
403*9a0bf528SMauro Carvalho Chehab 
404*9a0bf528SMauro Carvalho Chehab int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
405*9a0bf528SMauro Carvalho Chehab {
406*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
407*9a0bf528SMauro Carvalho Chehab 	if (value > 4095)
408*9a0bf528SMauro Carvalho Chehab 		value = 4095;
409*9a0bf528SMauro Carvalho Chehab 	state->wbd_ref = value;
410*9a0bf528SMauro Carvalho Chehab 	return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
411*9a0bf528SMauro Carvalho Chehab }
412*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_set_wbd_ref);
413*9a0bf528SMauro Carvalho Chehab 
414*9a0bf528SMauro Carvalho Chehab int dib7000p_get_agc_values(struct dvb_frontend *fe,
415*9a0bf528SMauro Carvalho Chehab 		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
416*9a0bf528SMauro Carvalho Chehab {
417*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
418*9a0bf528SMauro Carvalho Chehab 
419*9a0bf528SMauro Carvalho Chehab 	if (agc_global != NULL)
420*9a0bf528SMauro Carvalho Chehab 		*agc_global = dib7000p_read_word(state, 394);
421*9a0bf528SMauro Carvalho Chehab 	if (agc1 != NULL)
422*9a0bf528SMauro Carvalho Chehab 		*agc1 = dib7000p_read_word(state, 392);
423*9a0bf528SMauro Carvalho Chehab 	if (agc2 != NULL)
424*9a0bf528SMauro Carvalho Chehab 		*agc2 = dib7000p_read_word(state, 393);
425*9a0bf528SMauro Carvalho Chehab 	if (wbd != NULL)
426*9a0bf528SMauro Carvalho Chehab 		*wbd = dib7000p_read_word(state, 397);
427*9a0bf528SMauro Carvalho Chehab 
428*9a0bf528SMauro Carvalho Chehab 	return 0;
429*9a0bf528SMauro Carvalho Chehab }
430*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_get_agc_values);
431*9a0bf528SMauro Carvalho Chehab 
432*9a0bf528SMauro Carvalho Chehab static void dib7000p_reset_pll(struct dib7000p_state *state)
433*9a0bf528SMauro Carvalho Chehab {
434*9a0bf528SMauro Carvalho Chehab 	struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
435*9a0bf528SMauro Carvalho Chehab 	u16 clk_cfg0;
436*9a0bf528SMauro Carvalho Chehab 
437*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090) {
438*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
439*9a0bf528SMauro Carvalho Chehab 
440*9a0bf528SMauro Carvalho Chehab 		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
441*9a0bf528SMauro Carvalho Chehab 			;
442*9a0bf528SMauro Carvalho Chehab 
443*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
444*9a0bf528SMauro Carvalho Chehab 	} else {
445*9a0bf528SMauro Carvalho Chehab 		/* force PLL bypass */
446*9a0bf528SMauro Carvalho Chehab 		clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
447*9a0bf528SMauro Carvalho Chehab 			(bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
448*9a0bf528SMauro Carvalho Chehab 
449*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 900, clk_cfg0);
450*9a0bf528SMauro Carvalho Chehab 
451*9a0bf528SMauro Carvalho Chehab 		/* P_pll_cfg */
452*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
453*9a0bf528SMauro Carvalho Chehab 		clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
454*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 900, clk_cfg0);
455*9a0bf528SMauro Carvalho Chehab 	}
456*9a0bf528SMauro Carvalho Chehab 
457*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
458*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
459*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
460*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
461*9a0bf528SMauro Carvalho Chehab 
462*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 72, bw->sad_cfg);
463*9a0bf528SMauro Carvalho Chehab }
464*9a0bf528SMauro Carvalho Chehab 
465*9a0bf528SMauro Carvalho Chehab static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
466*9a0bf528SMauro Carvalho Chehab {
467*9a0bf528SMauro Carvalho Chehab 	u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
468*9a0bf528SMauro Carvalho Chehab 	internal |= (u32) dib7000p_read_word(state, 19);
469*9a0bf528SMauro Carvalho Chehab 	internal /= 1000;
470*9a0bf528SMauro Carvalho Chehab 
471*9a0bf528SMauro Carvalho Chehab 	return internal;
472*9a0bf528SMauro Carvalho Chehab }
473*9a0bf528SMauro Carvalho Chehab 
474*9a0bf528SMauro Carvalho Chehab int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
475*9a0bf528SMauro Carvalho Chehab {
476*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
477*9a0bf528SMauro Carvalho Chehab 	u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
478*9a0bf528SMauro Carvalho Chehab 	u8 loopdiv, prediv;
479*9a0bf528SMauro Carvalho Chehab 	u32 internal, xtal;
480*9a0bf528SMauro Carvalho Chehab 
481*9a0bf528SMauro Carvalho Chehab 	/* get back old values */
482*9a0bf528SMauro Carvalho Chehab 	prediv = reg_1856 & 0x3f;
483*9a0bf528SMauro Carvalho Chehab 	loopdiv = (reg_1856 >> 6) & 0x3f;
484*9a0bf528SMauro Carvalho Chehab 
485*9a0bf528SMauro Carvalho Chehab 	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
486*9a0bf528SMauro Carvalho Chehab 		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
487*9a0bf528SMauro Carvalho Chehab 		reg_1856 &= 0xf000;
488*9a0bf528SMauro Carvalho Chehab 		reg_1857 = dib7000p_read_word(state, 1857);
489*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
490*9a0bf528SMauro Carvalho Chehab 
491*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
492*9a0bf528SMauro Carvalho Chehab 
493*9a0bf528SMauro Carvalho Chehab 		/* write new system clk into P_sec_len */
494*9a0bf528SMauro Carvalho Chehab 		internal = dib7000p_get_internal_freq(state);
495*9a0bf528SMauro Carvalho Chehab 		xtal = (internal / loopdiv) * prediv;
496*9a0bf528SMauro Carvalho Chehab 		internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio;	/* new internal */
497*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
498*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
499*9a0bf528SMauro Carvalho Chehab 
500*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
501*9a0bf528SMauro Carvalho Chehab 
502*9a0bf528SMauro Carvalho Chehab 		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
503*9a0bf528SMauro Carvalho Chehab 			dprintk("Waiting for PLL to lock");
504*9a0bf528SMauro Carvalho Chehab 
505*9a0bf528SMauro Carvalho Chehab 		return 0;
506*9a0bf528SMauro Carvalho Chehab 	}
507*9a0bf528SMauro Carvalho Chehab 	return -EIO;
508*9a0bf528SMauro Carvalho Chehab }
509*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_update_pll);
510*9a0bf528SMauro Carvalho Chehab 
511*9a0bf528SMauro Carvalho Chehab static int dib7000p_reset_gpio(struct dib7000p_state *st)
512*9a0bf528SMauro Carvalho Chehab {
513*9a0bf528SMauro Carvalho Chehab 	/* reset the GPIOs */
514*9a0bf528SMauro Carvalho Chehab 	dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
515*9a0bf528SMauro Carvalho Chehab 
516*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1029, st->gpio_dir);
517*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1030, st->gpio_val);
518*9a0bf528SMauro Carvalho Chehab 
519*9a0bf528SMauro Carvalho Chehab 	/* TODO 1031 is P_gpio_od */
520*9a0bf528SMauro Carvalho Chehab 
521*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
522*9a0bf528SMauro Carvalho Chehab 
523*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
524*9a0bf528SMauro Carvalho Chehab 	return 0;
525*9a0bf528SMauro Carvalho Chehab }
526*9a0bf528SMauro Carvalho Chehab 
527*9a0bf528SMauro Carvalho Chehab static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
528*9a0bf528SMauro Carvalho Chehab {
529*9a0bf528SMauro Carvalho Chehab 	st->gpio_dir = dib7000p_read_word(st, 1029);
530*9a0bf528SMauro Carvalho Chehab 	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
531*9a0bf528SMauro Carvalho Chehab 	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
532*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1029, st->gpio_dir);
533*9a0bf528SMauro Carvalho Chehab 
534*9a0bf528SMauro Carvalho Chehab 	st->gpio_val = dib7000p_read_word(st, 1030);
535*9a0bf528SMauro Carvalho Chehab 	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
536*9a0bf528SMauro Carvalho Chehab 	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
537*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1030, st->gpio_val);
538*9a0bf528SMauro Carvalho Chehab 
539*9a0bf528SMauro Carvalho Chehab 	return 0;
540*9a0bf528SMauro Carvalho Chehab }
541*9a0bf528SMauro Carvalho Chehab 
542*9a0bf528SMauro Carvalho Chehab int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
543*9a0bf528SMauro Carvalho Chehab {
544*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
545*9a0bf528SMauro Carvalho Chehab 	return dib7000p_cfg_gpio(state, num, dir, val);
546*9a0bf528SMauro Carvalho Chehab }
547*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_set_gpio);
548*9a0bf528SMauro Carvalho Chehab 
549*9a0bf528SMauro Carvalho Chehab static u16 dib7000p_defaults[] = {
550*9a0bf528SMauro Carvalho Chehab 	// auto search configuration
551*9a0bf528SMauro Carvalho Chehab 	3, 2,
552*9a0bf528SMauro Carvalho Chehab 	0x0004,
553*9a0bf528SMauro Carvalho Chehab 	(1<<3)|(1<<11)|(1<<12)|(1<<13),
554*9a0bf528SMauro Carvalho Chehab 	0x0814,			/* Equal Lock */
555*9a0bf528SMauro Carvalho Chehab 
556*9a0bf528SMauro Carvalho Chehab 	12, 6,
557*9a0bf528SMauro Carvalho Chehab 	0x001b,
558*9a0bf528SMauro Carvalho Chehab 	0x7740,
559*9a0bf528SMauro Carvalho Chehab 	0x005b,
560*9a0bf528SMauro Carvalho Chehab 	0x8d80,
561*9a0bf528SMauro Carvalho Chehab 	0x01c9,
562*9a0bf528SMauro Carvalho Chehab 	0xc380,
563*9a0bf528SMauro Carvalho Chehab 	0x0000,
564*9a0bf528SMauro Carvalho Chehab 	0x0080,
565*9a0bf528SMauro Carvalho Chehab 	0x0000,
566*9a0bf528SMauro Carvalho Chehab 	0x0090,
567*9a0bf528SMauro Carvalho Chehab 	0x0001,
568*9a0bf528SMauro Carvalho Chehab 	0xd4c0,
569*9a0bf528SMauro Carvalho Chehab 
570*9a0bf528SMauro Carvalho Chehab 	1, 26,
571*9a0bf528SMauro Carvalho Chehab 	0x6680,
572*9a0bf528SMauro Carvalho Chehab 
573*9a0bf528SMauro Carvalho Chehab 	/* set ADC level to -16 */
574*9a0bf528SMauro Carvalho Chehab 	11, 79,
575*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 825 - 117,
576*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 837 - 117,
577*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 811 - 117,
578*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 766 - 117,
579*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 737 - 117,
580*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 693 - 117,
581*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 648 - 117,
582*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 619 - 117,
583*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 575 - 117,
584*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 531 - 117,
585*9a0bf528SMauro Carvalho Chehab 	(1 << 13) - 501 - 117,
586*9a0bf528SMauro Carvalho Chehab 
587*9a0bf528SMauro Carvalho Chehab 	1, 142,
588*9a0bf528SMauro Carvalho Chehab 	0x0410,
589*9a0bf528SMauro Carvalho Chehab 
590*9a0bf528SMauro Carvalho Chehab 	/* disable power smoothing */
591*9a0bf528SMauro Carvalho Chehab 	8, 145,
592*9a0bf528SMauro Carvalho Chehab 	0,
593*9a0bf528SMauro Carvalho Chehab 	0,
594*9a0bf528SMauro Carvalho Chehab 	0,
595*9a0bf528SMauro Carvalho Chehab 	0,
596*9a0bf528SMauro Carvalho Chehab 	0,
597*9a0bf528SMauro Carvalho Chehab 	0,
598*9a0bf528SMauro Carvalho Chehab 	0,
599*9a0bf528SMauro Carvalho Chehab 	0,
600*9a0bf528SMauro Carvalho Chehab 
601*9a0bf528SMauro Carvalho Chehab 	1, 154,
602*9a0bf528SMauro Carvalho Chehab 	1 << 13,
603*9a0bf528SMauro Carvalho Chehab 
604*9a0bf528SMauro Carvalho Chehab 	1, 168,
605*9a0bf528SMauro Carvalho Chehab 	0x0ccd,
606*9a0bf528SMauro Carvalho Chehab 
607*9a0bf528SMauro Carvalho Chehab 	1, 183,
608*9a0bf528SMauro Carvalho Chehab 	0x200f,
609*9a0bf528SMauro Carvalho Chehab 
610*9a0bf528SMauro Carvalho Chehab 	1, 212,
611*9a0bf528SMauro Carvalho Chehab 		0x169,
612*9a0bf528SMauro Carvalho Chehab 
613*9a0bf528SMauro Carvalho Chehab 	5, 187,
614*9a0bf528SMauro Carvalho Chehab 	0x023d,
615*9a0bf528SMauro Carvalho Chehab 	0x00a4,
616*9a0bf528SMauro Carvalho Chehab 	0x00a4,
617*9a0bf528SMauro Carvalho Chehab 	0x7ff0,
618*9a0bf528SMauro Carvalho Chehab 	0x3ccc,
619*9a0bf528SMauro Carvalho Chehab 
620*9a0bf528SMauro Carvalho Chehab 	1, 198,
621*9a0bf528SMauro Carvalho Chehab 	0x800,
622*9a0bf528SMauro Carvalho Chehab 
623*9a0bf528SMauro Carvalho Chehab 	1, 222,
624*9a0bf528SMauro Carvalho Chehab 	0x0010,
625*9a0bf528SMauro Carvalho Chehab 
626*9a0bf528SMauro Carvalho Chehab 	1, 235,
627*9a0bf528SMauro Carvalho Chehab 	0x0062,
628*9a0bf528SMauro Carvalho Chehab 
629*9a0bf528SMauro Carvalho Chehab 	0,
630*9a0bf528SMauro Carvalho Chehab };
631*9a0bf528SMauro Carvalho Chehab 
632*9a0bf528SMauro Carvalho Chehab static int dib7000p_demod_reset(struct dib7000p_state *state)
633*9a0bf528SMauro Carvalho Chehab {
634*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
635*9a0bf528SMauro Carvalho Chehab 
636*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090)
637*9a0bf528SMauro Carvalho Chehab 		dibx000_reset_i2c_master(&state->i2c_master);
638*9a0bf528SMauro Carvalho Chehab 
639*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
640*9a0bf528SMauro Carvalho Chehab 
641*9a0bf528SMauro Carvalho Chehab 	/* restart all parts */
642*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, 0xffff);
643*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 771, 0xffff);
644*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 772, 0x001f);
645*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
646*9a0bf528SMauro Carvalho Chehab 
647*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, 0);
648*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 771, 0);
649*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 772, 0);
650*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1280, 0);
651*9a0bf528SMauro Carvalho Chehab 
652*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090) {
653*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state,  898, 0x0003);
654*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state,  898, 0);
655*9a0bf528SMauro Carvalho Chehab 	}
656*9a0bf528SMauro Carvalho Chehab 
657*9a0bf528SMauro Carvalho Chehab 	/* default */
658*9a0bf528SMauro Carvalho Chehab 	dib7000p_reset_pll(state);
659*9a0bf528SMauro Carvalho Chehab 
660*9a0bf528SMauro Carvalho Chehab 	if (dib7000p_reset_gpio(state) != 0)
661*9a0bf528SMauro Carvalho Chehab 		dprintk("GPIO reset was not successful.");
662*9a0bf528SMauro Carvalho Chehab 
663*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090) {
664*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 899, 0);
665*9a0bf528SMauro Carvalho Chehab 
666*9a0bf528SMauro Carvalho Chehab 		/* impulse noise */
667*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
668*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
669*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
670*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 273, (0<<6) | 30);
671*9a0bf528SMauro Carvalho Chehab 	}
672*9a0bf528SMauro Carvalho Chehab 	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
673*9a0bf528SMauro Carvalho Chehab 		dprintk("OUTPUT_MODE could not be reset.");
674*9a0bf528SMauro Carvalho Chehab 
675*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
676*9a0bf528SMauro Carvalho Chehab 	dib7000p_sad_calib(state);
677*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
678*9a0bf528SMauro Carvalho Chehab 
679*9a0bf528SMauro Carvalho Chehab 	/* unforce divstr regardless whether i2c enumeration was done or not */
680*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
681*9a0bf528SMauro Carvalho Chehab 
682*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_bandwidth(state, 8000);
683*9a0bf528SMauro Carvalho Chehab 
684*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090) {
685*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
686*9a0bf528SMauro Carvalho Chehab 	} else {
687*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.tuner_is_baseband)
688*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 36, 0x0755);
689*9a0bf528SMauro Carvalho Chehab 		else
690*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 36, 0x1f55);
691*9a0bf528SMauro Carvalho Chehab 	}
692*9a0bf528SMauro Carvalho Chehab 
693*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_tab(state, dib7000p_defaults);
694*9a0bf528SMauro Carvalho Chehab 	if (state->version != SOC7090) {
695*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 901, 0x0006);
696*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
697*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 905, 0x2c8e);
698*9a0bf528SMauro Carvalho Chehab 	}
699*9a0bf528SMauro Carvalho Chehab 
700*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
701*9a0bf528SMauro Carvalho Chehab 
702*9a0bf528SMauro Carvalho Chehab 	return 0;
703*9a0bf528SMauro Carvalho Chehab }
704*9a0bf528SMauro Carvalho Chehab 
705*9a0bf528SMauro Carvalho Chehab static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
706*9a0bf528SMauro Carvalho Chehab {
707*9a0bf528SMauro Carvalho Chehab 	u16 tmp = 0;
708*9a0bf528SMauro Carvalho Chehab 	tmp = dib7000p_read_word(state, 903);
709*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 903, (tmp | 0x1));
710*9a0bf528SMauro Carvalho Chehab 	tmp = dib7000p_read_word(state, 900);
711*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
712*9a0bf528SMauro Carvalho Chehab }
713*9a0bf528SMauro Carvalho Chehab 
714*9a0bf528SMauro Carvalho Chehab static void dib7000p_restart_agc(struct dib7000p_state *state)
715*9a0bf528SMauro Carvalho Chehab {
716*9a0bf528SMauro Carvalho Chehab 	// P_restart_iqc & P_restart_agc
717*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
718*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, 0x0000);
719*9a0bf528SMauro Carvalho Chehab }
720*9a0bf528SMauro Carvalho Chehab 
721*9a0bf528SMauro Carvalho Chehab static int dib7000p_update_lna(struct dib7000p_state *state)
722*9a0bf528SMauro Carvalho Chehab {
723*9a0bf528SMauro Carvalho Chehab 	u16 dyn_gain;
724*9a0bf528SMauro Carvalho Chehab 
725*9a0bf528SMauro Carvalho Chehab 	if (state->cfg.update_lna) {
726*9a0bf528SMauro Carvalho Chehab 		dyn_gain = dib7000p_read_word(state, 394);
727*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.update_lna(&state->demod, dyn_gain)) {
728*9a0bf528SMauro Carvalho Chehab 			dib7000p_restart_agc(state);
729*9a0bf528SMauro Carvalho Chehab 			return 1;
730*9a0bf528SMauro Carvalho Chehab 		}
731*9a0bf528SMauro Carvalho Chehab 	}
732*9a0bf528SMauro Carvalho Chehab 
733*9a0bf528SMauro Carvalho Chehab 	return 0;
734*9a0bf528SMauro Carvalho Chehab }
735*9a0bf528SMauro Carvalho Chehab 
736*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
737*9a0bf528SMauro Carvalho Chehab {
738*9a0bf528SMauro Carvalho Chehab 	struct dibx000_agc_config *agc = NULL;
739*9a0bf528SMauro Carvalho Chehab 	int i;
740*9a0bf528SMauro Carvalho Chehab 	if (state->current_band == band && state->current_agc != NULL)
741*9a0bf528SMauro Carvalho Chehab 		return 0;
742*9a0bf528SMauro Carvalho Chehab 	state->current_band = band;
743*9a0bf528SMauro Carvalho Chehab 
744*9a0bf528SMauro Carvalho Chehab 	for (i = 0; i < state->cfg.agc_config_count; i++)
745*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.agc[i].band_caps & band) {
746*9a0bf528SMauro Carvalho Chehab 			agc = &state->cfg.agc[i];
747*9a0bf528SMauro Carvalho Chehab 			break;
748*9a0bf528SMauro Carvalho Chehab 		}
749*9a0bf528SMauro Carvalho Chehab 
750*9a0bf528SMauro Carvalho Chehab 	if (agc == NULL) {
751*9a0bf528SMauro Carvalho Chehab 		dprintk("no valid AGC configuration found for band 0x%02x", band);
752*9a0bf528SMauro Carvalho Chehab 		return -EINVAL;
753*9a0bf528SMauro Carvalho Chehab 	}
754*9a0bf528SMauro Carvalho Chehab 
755*9a0bf528SMauro Carvalho Chehab 	state->current_agc = agc;
756*9a0bf528SMauro Carvalho Chehab 
757*9a0bf528SMauro Carvalho Chehab 	/* AGC */
758*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 75, agc->setup);
759*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 76, agc->inv_gain);
760*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 77, agc->time_stabiliz);
761*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
762*9a0bf528SMauro Carvalho Chehab 
763*9a0bf528SMauro Carvalho Chehab 	// Demod AGC loop configuration
764*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
765*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
766*9a0bf528SMauro Carvalho Chehab 
767*9a0bf528SMauro Carvalho Chehab 	/* AGC continued */
768*9a0bf528SMauro Carvalho Chehab 	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
769*9a0bf528SMauro Carvalho Chehab 		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
770*9a0bf528SMauro Carvalho Chehab 
771*9a0bf528SMauro Carvalho Chehab 	if (state->wbd_ref != 0)
772*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
773*9a0bf528SMauro Carvalho Chehab 	else
774*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
775*9a0bf528SMauro Carvalho Chehab 
776*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
777*9a0bf528SMauro Carvalho Chehab 
778*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 107, agc->agc1_max);
779*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 108, agc->agc1_min);
780*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 109, agc->agc2_max);
781*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 110, agc->agc2_min);
782*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
783*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 112, agc->agc1_pt3);
784*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
785*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
786*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
787*9a0bf528SMauro Carvalho Chehab 	return 0;
788*9a0bf528SMauro Carvalho Chehab }
789*9a0bf528SMauro Carvalho Chehab 
790*9a0bf528SMauro Carvalho Chehab static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
791*9a0bf528SMauro Carvalho Chehab {
792*9a0bf528SMauro Carvalho Chehab 	u32 internal = dib7000p_get_internal_freq(state);
793*9a0bf528SMauro Carvalho Chehab 	s32 unit_khz_dds_val = 67108864 / (internal);	/* 2**26 / Fsampling is the unit 1KHz offset */
794*9a0bf528SMauro Carvalho Chehab 	u32 abs_offset_khz = ABS(offset_khz);
795*9a0bf528SMauro Carvalho Chehab 	u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
796*9a0bf528SMauro Carvalho Chehab 	u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
797*9a0bf528SMauro Carvalho Chehab 
798*9a0bf528SMauro Carvalho Chehab 	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
799*9a0bf528SMauro Carvalho Chehab 
800*9a0bf528SMauro Carvalho Chehab 	if (offset_khz < 0)
801*9a0bf528SMauro Carvalho Chehab 		unit_khz_dds_val *= -1;
802*9a0bf528SMauro Carvalho Chehab 
803*9a0bf528SMauro Carvalho Chehab 	/* IF tuner */
804*9a0bf528SMauro Carvalho Chehab 	if (invert)
805*9a0bf528SMauro Carvalho Chehab 		dds -= (abs_offset_khz * unit_khz_dds_val);	/* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
806*9a0bf528SMauro Carvalho Chehab 	else
807*9a0bf528SMauro Carvalho Chehab 		dds += (abs_offset_khz * unit_khz_dds_val);
808*9a0bf528SMauro Carvalho Chehab 
809*9a0bf528SMauro Carvalho Chehab 	if (abs_offset_khz <= (internal / 2)) {	/* Max dds offset is the half of the demod freq */
810*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
811*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
812*9a0bf528SMauro Carvalho Chehab 	}
813*9a0bf528SMauro Carvalho Chehab }
814*9a0bf528SMauro Carvalho Chehab 
815*9a0bf528SMauro Carvalho Chehab static int dib7000p_agc_startup(struct dvb_frontend *demod)
816*9a0bf528SMauro Carvalho Chehab {
817*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
818*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
819*9a0bf528SMauro Carvalho Chehab 	int ret = -1;
820*9a0bf528SMauro Carvalho Chehab 	u8 *agc_state = &state->agc_state;
821*9a0bf528SMauro Carvalho Chehab 	u8 agc_split;
822*9a0bf528SMauro Carvalho Chehab 	u16 reg;
823*9a0bf528SMauro Carvalho Chehab 	u32 upd_demod_gain_period = 0x1000;
824*9a0bf528SMauro Carvalho Chehab 
825*9a0bf528SMauro Carvalho Chehab 	switch (state->agc_state) {
826*9a0bf528SMauro Carvalho Chehab 	case 0:
827*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
828*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090) {
829*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 0x79b) & 0xff00;
830*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF);	/* lsb */
831*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
832*9a0bf528SMauro Carvalho Chehab 
833*9a0bf528SMauro Carvalho Chehab 			/* enable adc i & q */
834*9a0bf528SMauro Carvalho Chehab 			reg = dib7000p_read_word(state, 0x780);
835*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
836*9a0bf528SMauro Carvalho Chehab 		} else {
837*9a0bf528SMauro Carvalho Chehab 			dib7000p_set_adc_state(state, DIBX000_ADC_ON);
838*9a0bf528SMauro Carvalho Chehab 			dib7000p_pll_clk_cfg(state);
839*9a0bf528SMauro Carvalho Chehab 		}
840*9a0bf528SMauro Carvalho Chehab 
841*9a0bf528SMauro Carvalho Chehab 		if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
842*9a0bf528SMauro Carvalho Chehab 			return -1;
843*9a0bf528SMauro Carvalho Chehab 
844*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_dds(state, 0);
845*9a0bf528SMauro Carvalho Chehab 		ret = 7;
846*9a0bf528SMauro Carvalho Chehab 		(*agc_state)++;
847*9a0bf528SMauro Carvalho Chehab 		break;
848*9a0bf528SMauro Carvalho Chehab 
849*9a0bf528SMauro Carvalho Chehab 	case 1:
850*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.agc_control)
851*9a0bf528SMauro Carvalho Chehab 			state->cfg.agc_control(&state->demod, 1);
852*9a0bf528SMauro Carvalho Chehab 
853*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 78, 32768);
854*9a0bf528SMauro Carvalho Chehab 		if (!state->current_agc->perform_agc_softsplit) {
855*9a0bf528SMauro Carvalho Chehab 			/* we are using the wbd - so slow AGC startup */
856*9a0bf528SMauro Carvalho Chehab 			/* force 0 split on WBD and restart AGC */
857*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
858*9a0bf528SMauro Carvalho Chehab 			(*agc_state)++;
859*9a0bf528SMauro Carvalho Chehab 			ret = 5;
860*9a0bf528SMauro Carvalho Chehab 		} else {
861*9a0bf528SMauro Carvalho Chehab 			/* default AGC startup */
862*9a0bf528SMauro Carvalho Chehab 			(*agc_state) = 4;
863*9a0bf528SMauro Carvalho Chehab 			/* wait AGC rough lock time */
864*9a0bf528SMauro Carvalho Chehab 			ret = 7;
865*9a0bf528SMauro Carvalho Chehab 		}
866*9a0bf528SMauro Carvalho Chehab 
867*9a0bf528SMauro Carvalho Chehab 		dib7000p_restart_agc(state);
868*9a0bf528SMauro Carvalho Chehab 		break;
869*9a0bf528SMauro Carvalho Chehab 
870*9a0bf528SMauro Carvalho Chehab 	case 2:		/* fast split search path after 5sec */
871*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4));	/* freeze AGC loop */
872*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8));	/* fast split search 0.25kHz */
873*9a0bf528SMauro Carvalho Chehab 		(*agc_state)++;
874*9a0bf528SMauro Carvalho Chehab 		ret = 14;
875*9a0bf528SMauro Carvalho Chehab 		break;
876*9a0bf528SMauro Carvalho Chehab 
877*9a0bf528SMauro Carvalho Chehab 	case 3:		/* split search ended */
878*9a0bf528SMauro Carvalho Chehab 		agc_split = (u8) dib7000p_read_word(state, 396);	/* store the split value for the next time */
879*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 78, dib7000p_read_word(state, 394));	/* set AGC gain start value */
880*9a0bf528SMauro Carvalho Chehab 
881*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 75, state->current_agc->setup);	/* std AGC loop */
882*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split);	/* standard split search */
883*9a0bf528SMauro Carvalho Chehab 
884*9a0bf528SMauro Carvalho Chehab 		dib7000p_restart_agc(state);
885*9a0bf528SMauro Carvalho Chehab 
886*9a0bf528SMauro Carvalho Chehab 		dprintk("SPLIT %p: %hd", demod, agc_split);
887*9a0bf528SMauro Carvalho Chehab 
888*9a0bf528SMauro Carvalho Chehab 		(*agc_state)++;
889*9a0bf528SMauro Carvalho Chehab 		ret = 5;
890*9a0bf528SMauro Carvalho Chehab 		break;
891*9a0bf528SMauro Carvalho Chehab 
892*9a0bf528SMauro Carvalho Chehab 	case 4:		/* LNA startup */
893*9a0bf528SMauro Carvalho Chehab 		ret = 7;
894*9a0bf528SMauro Carvalho Chehab 
895*9a0bf528SMauro Carvalho Chehab 		if (dib7000p_update_lna(state))
896*9a0bf528SMauro Carvalho Chehab 			ret = 5;
897*9a0bf528SMauro Carvalho Chehab 		else
898*9a0bf528SMauro Carvalho Chehab 			(*agc_state)++;
899*9a0bf528SMauro Carvalho Chehab 		break;
900*9a0bf528SMauro Carvalho Chehab 
901*9a0bf528SMauro Carvalho Chehab 	case 5:
902*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.agc_control)
903*9a0bf528SMauro Carvalho Chehab 			state->cfg.agc_control(&state->demod, 0);
904*9a0bf528SMauro Carvalho Chehab 		(*agc_state)++;
905*9a0bf528SMauro Carvalho Chehab 		break;
906*9a0bf528SMauro Carvalho Chehab 	default:
907*9a0bf528SMauro Carvalho Chehab 		break;
908*9a0bf528SMauro Carvalho Chehab 	}
909*9a0bf528SMauro Carvalho Chehab 	return ret;
910*9a0bf528SMauro Carvalho Chehab }
911*9a0bf528SMauro Carvalho Chehab 
912*9a0bf528SMauro Carvalho Chehab static void dib7000p_update_timf(struct dib7000p_state *state)
913*9a0bf528SMauro Carvalho Chehab {
914*9a0bf528SMauro Carvalho Chehab 	u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
915*9a0bf528SMauro Carvalho Chehab 	state->timf = timf * 160 / (state->current_bandwidth / 50);
916*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 23, (u16) (timf >> 16));
917*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
918*9a0bf528SMauro Carvalho Chehab 	dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
919*9a0bf528SMauro Carvalho Chehab 
920*9a0bf528SMauro Carvalho Chehab }
921*9a0bf528SMauro Carvalho Chehab 
922*9a0bf528SMauro Carvalho Chehab u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
923*9a0bf528SMauro Carvalho Chehab {
924*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
925*9a0bf528SMauro Carvalho Chehab 	switch (op) {
926*9a0bf528SMauro Carvalho Chehab 	case DEMOD_TIMF_SET:
927*9a0bf528SMauro Carvalho Chehab 		state->timf = timf;
928*9a0bf528SMauro Carvalho Chehab 		break;
929*9a0bf528SMauro Carvalho Chehab 	case DEMOD_TIMF_UPDATE:
930*9a0bf528SMauro Carvalho Chehab 		dib7000p_update_timf(state);
931*9a0bf528SMauro Carvalho Chehab 		break;
932*9a0bf528SMauro Carvalho Chehab 	case DEMOD_TIMF_GET:
933*9a0bf528SMauro Carvalho Chehab 		break;
934*9a0bf528SMauro Carvalho Chehab 	}
935*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_bandwidth(state, state->current_bandwidth);
936*9a0bf528SMauro Carvalho Chehab 	return state->timf;
937*9a0bf528SMauro Carvalho Chehab }
938*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_ctrl_timf);
939*9a0bf528SMauro Carvalho Chehab 
940*9a0bf528SMauro Carvalho Chehab static void dib7000p_set_channel(struct dib7000p_state *state,
941*9a0bf528SMauro Carvalho Chehab 				 struct dtv_frontend_properties *ch, u8 seq)
942*9a0bf528SMauro Carvalho Chehab {
943*9a0bf528SMauro Carvalho Chehab 	u16 value, est[4];
944*9a0bf528SMauro Carvalho Chehab 
945*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
946*9a0bf528SMauro Carvalho Chehab 
947*9a0bf528SMauro Carvalho Chehab 	/* nfft, guard, qam, alpha */
948*9a0bf528SMauro Carvalho Chehab 	value = 0;
949*9a0bf528SMauro Carvalho Chehab 	switch (ch->transmission_mode) {
950*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
951*9a0bf528SMauro Carvalho Chehab 		value |= (0 << 7);
952*9a0bf528SMauro Carvalho Chehab 		break;
953*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_4K:
954*9a0bf528SMauro Carvalho Chehab 		value |= (2 << 7);
955*9a0bf528SMauro Carvalho Chehab 		break;
956*9a0bf528SMauro Carvalho Chehab 	default:
957*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
958*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 7);
959*9a0bf528SMauro Carvalho Chehab 		break;
960*9a0bf528SMauro Carvalho Chehab 	}
961*9a0bf528SMauro Carvalho Chehab 	switch (ch->guard_interval) {
962*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_32:
963*9a0bf528SMauro Carvalho Chehab 		value |= (0 << 5);
964*9a0bf528SMauro Carvalho Chehab 		break;
965*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_16:
966*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 5);
967*9a0bf528SMauro Carvalho Chehab 		break;
968*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_4:
969*9a0bf528SMauro Carvalho Chehab 		value |= (3 << 5);
970*9a0bf528SMauro Carvalho Chehab 		break;
971*9a0bf528SMauro Carvalho Chehab 	default:
972*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_8:
973*9a0bf528SMauro Carvalho Chehab 		value |= (2 << 5);
974*9a0bf528SMauro Carvalho Chehab 		break;
975*9a0bf528SMauro Carvalho Chehab 	}
976*9a0bf528SMauro Carvalho Chehab 	switch (ch->modulation) {
977*9a0bf528SMauro Carvalho Chehab 	case QPSK:
978*9a0bf528SMauro Carvalho Chehab 		value |= (0 << 3);
979*9a0bf528SMauro Carvalho Chehab 		break;
980*9a0bf528SMauro Carvalho Chehab 	case QAM_16:
981*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 3);
982*9a0bf528SMauro Carvalho Chehab 		break;
983*9a0bf528SMauro Carvalho Chehab 	default:
984*9a0bf528SMauro Carvalho Chehab 	case QAM_64:
985*9a0bf528SMauro Carvalho Chehab 		value |= (2 << 3);
986*9a0bf528SMauro Carvalho Chehab 		break;
987*9a0bf528SMauro Carvalho Chehab 	}
988*9a0bf528SMauro Carvalho Chehab 	switch (HIERARCHY_1) {
989*9a0bf528SMauro Carvalho Chehab 	case HIERARCHY_2:
990*9a0bf528SMauro Carvalho Chehab 		value |= 2;
991*9a0bf528SMauro Carvalho Chehab 		break;
992*9a0bf528SMauro Carvalho Chehab 	case HIERARCHY_4:
993*9a0bf528SMauro Carvalho Chehab 		value |= 4;
994*9a0bf528SMauro Carvalho Chehab 		break;
995*9a0bf528SMauro Carvalho Chehab 	default:
996*9a0bf528SMauro Carvalho Chehab 	case HIERARCHY_1:
997*9a0bf528SMauro Carvalho Chehab 		value |= 1;
998*9a0bf528SMauro Carvalho Chehab 		break;
999*9a0bf528SMauro Carvalho Chehab 	}
1000*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 0, value);
1001*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 5, (seq << 4) | 1);	/* do not force tps, search list 0 */
1002*9a0bf528SMauro Carvalho Chehab 
1003*9a0bf528SMauro Carvalho Chehab 	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
1004*9a0bf528SMauro Carvalho Chehab 	value = 0;
1005*9a0bf528SMauro Carvalho Chehab 	if (1 != 0)
1006*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 6);
1007*9a0bf528SMauro Carvalho Chehab 	if (ch->hierarchy == 1)
1008*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 4);
1009*9a0bf528SMauro Carvalho Chehab 	if (1 == 1)
1010*9a0bf528SMauro Carvalho Chehab 		value |= 1;
1011*9a0bf528SMauro Carvalho Chehab 	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
1012*9a0bf528SMauro Carvalho Chehab 	case FEC_2_3:
1013*9a0bf528SMauro Carvalho Chehab 		value |= (2 << 1);
1014*9a0bf528SMauro Carvalho Chehab 		break;
1015*9a0bf528SMauro Carvalho Chehab 	case FEC_3_4:
1016*9a0bf528SMauro Carvalho Chehab 		value |= (3 << 1);
1017*9a0bf528SMauro Carvalho Chehab 		break;
1018*9a0bf528SMauro Carvalho Chehab 	case FEC_5_6:
1019*9a0bf528SMauro Carvalho Chehab 		value |= (5 << 1);
1020*9a0bf528SMauro Carvalho Chehab 		break;
1021*9a0bf528SMauro Carvalho Chehab 	case FEC_7_8:
1022*9a0bf528SMauro Carvalho Chehab 		value |= (7 << 1);
1023*9a0bf528SMauro Carvalho Chehab 		break;
1024*9a0bf528SMauro Carvalho Chehab 	default:
1025*9a0bf528SMauro Carvalho Chehab 	case FEC_1_2:
1026*9a0bf528SMauro Carvalho Chehab 		value |= (1 << 1);
1027*9a0bf528SMauro Carvalho Chehab 		break;
1028*9a0bf528SMauro Carvalho Chehab 	}
1029*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 208, value);
1030*9a0bf528SMauro Carvalho Chehab 
1031*9a0bf528SMauro Carvalho Chehab 	/* offset loop parameters */
1032*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 26, 0x6680);
1033*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 32, 0x0003);
1034*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 29, 0x1273);
1035*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 33, 0x0005);
1036*9a0bf528SMauro Carvalho Chehab 
1037*9a0bf528SMauro Carvalho Chehab 	/* P_dvsy_sync_wait */
1038*9a0bf528SMauro Carvalho Chehab 	switch (ch->transmission_mode) {
1039*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
1040*9a0bf528SMauro Carvalho Chehab 		value = 256;
1041*9a0bf528SMauro Carvalho Chehab 		break;
1042*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_4K:
1043*9a0bf528SMauro Carvalho Chehab 		value = 128;
1044*9a0bf528SMauro Carvalho Chehab 		break;
1045*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
1046*9a0bf528SMauro Carvalho Chehab 	default:
1047*9a0bf528SMauro Carvalho Chehab 		value = 64;
1048*9a0bf528SMauro Carvalho Chehab 		break;
1049*9a0bf528SMauro Carvalho Chehab 	}
1050*9a0bf528SMauro Carvalho Chehab 	switch (ch->guard_interval) {
1051*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_16:
1052*9a0bf528SMauro Carvalho Chehab 		value *= 2;
1053*9a0bf528SMauro Carvalho Chehab 		break;
1054*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_8:
1055*9a0bf528SMauro Carvalho Chehab 		value *= 4;
1056*9a0bf528SMauro Carvalho Chehab 		break;
1057*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_4:
1058*9a0bf528SMauro Carvalho Chehab 		value *= 8;
1059*9a0bf528SMauro Carvalho Chehab 		break;
1060*9a0bf528SMauro Carvalho Chehab 	default:
1061*9a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_32:
1062*9a0bf528SMauro Carvalho Chehab 		value *= 1;
1063*9a0bf528SMauro Carvalho Chehab 		break;
1064*9a0bf528SMauro Carvalho Chehab 	}
1065*9a0bf528SMauro Carvalho Chehab 	if (state->cfg.diversity_delay == 0)
1066*9a0bf528SMauro Carvalho Chehab 		state->div_sync_wait = (value * 3) / 2 + 48;
1067*9a0bf528SMauro Carvalho Chehab 	else
1068*9a0bf528SMauro Carvalho Chehab 		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
1069*9a0bf528SMauro Carvalho Chehab 
1070*9a0bf528SMauro Carvalho Chehab 	/* deactive the possibility of diversity reception if extended interleaver */
1071*9a0bf528SMauro Carvalho Chehab 	state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
1072*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_diversity_in(&state->demod, state->div_state);
1073*9a0bf528SMauro Carvalho Chehab 
1074*9a0bf528SMauro Carvalho Chehab 	/* channel estimation fine configuration */
1075*9a0bf528SMauro Carvalho Chehab 	switch (ch->modulation) {
1076*9a0bf528SMauro Carvalho Chehab 	case QAM_64:
1077*9a0bf528SMauro Carvalho Chehab 		est[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
1078*9a0bf528SMauro Carvalho Chehab 		est[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
1079*9a0bf528SMauro Carvalho Chehab 		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
1080*9a0bf528SMauro Carvalho Chehab 		est[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
1081*9a0bf528SMauro Carvalho Chehab 		break;
1082*9a0bf528SMauro Carvalho Chehab 	case QAM_16:
1083*9a0bf528SMauro Carvalho Chehab 		est[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
1084*9a0bf528SMauro Carvalho Chehab 		est[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
1085*9a0bf528SMauro Carvalho Chehab 		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
1086*9a0bf528SMauro Carvalho Chehab 		est[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
1087*9a0bf528SMauro Carvalho Chehab 		break;
1088*9a0bf528SMauro Carvalho Chehab 	default:
1089*9a0bf528SMauro Carvalho Chehab 		est[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
1090*9a0bf528SMauro Carvalho Chehab 		est[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
1091*9a0bf528SMauro Carvalho Chehab 		est[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
1092*9a0bf528SMauro Carvalho Chehab 		est[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
1093*9a0bf528SMauro Carvalho Chehab 		break;
1094*9a0bf528SMauro Carvalho Chehab 	}
1095*9a0bf528SMauro Carvalho Chehab 	for (value = 0; value < 4; value++)
1096*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 187 + value, est[value]);
1097*9a0bf528SMauro Carvalho Chehab }
1098*9a0bf528SMauro Carvalho Chehab 
1099*9a0bf528SMauro Carvalho Chehab static int dib7000p_autosearch_start(struct dvb_frontend *demod)
1100*9a0bf528SMauro Carvalho Chehab {
1101*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
1102*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
1103*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties schan;
1104*9a0bf528SMauro Carvalho Chehab 	u32 value, factor;
1105*9a0bf528SMauro Carvalho Chehab 	u32 internal = dib7000p_get_internal_freq(state);
1106*9a0bf528SMauro Carvalho Chehab 
1107*9a0bf528SMauro Carvalho Chehab 	schan = *ch;
1108*9a0bf528SMauro Carvalho Chehab 	schan.modulation = QAM_64;
1109*9a0bf528SMauro Carvalho Chehab 	schan.guard_interval = GUARD_INTERVAL_1_32;
1110*9a0bf528SMauro Carvalho Chehab 	schan.transmission_mode = TRANSMISSION_MODE_8K;
1111*9a0bf528SMauro Carvalho Chehab 	schan.code_rate_HP = FEC_2_3;
1112*9a0bf528SMauro Carvalho Chehab 	schan.code_rate_LP = FEC_3_4;
1113*9a0bf528SMauro Carvalho Chehab 	schan.hierarchy = 0;
1114*9a0bf528SMauro Carvalho Chehab 
1115*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_channel(state, &schan, 7);
1116*9a0bf528SMauro Carvalho Chehab 
1117*9a0bf528SMauro Carvalho Chehab 	factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
1118*9a0bf528SMauro Carvalho Chehab 	if (factor >= 5000) {
1119*9a0bf528SMauro Carvalho Chehab 		if (state->version == SOC7090)
1120*9a0bf528SMauro Carvalho Chehab 			factor = 2;
1121*9a0bf528SMauro Carvalho Chehab 		else
1122*9a0bf528SMauro Carvalho Chehab 			factor = 1;
1123*9a0bf528SMauro Carvalho Chehab 	} else
1124*9a0bf528SMauro Carvalho Chehab 		factor = 6;
1125*9a0bf528SMauro Carvalho Chehab 
1126*9a0bf528SMauro Carvalho Chehab 	value = 30 * internal * factor;
1127*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
1128*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 7, (u16) (value & 0xffff));
1129*9a0bf528SMauro Carvalho Chehab 	value = 100 * internal * factor;
1130*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
1131*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 9, (u16) (value & 0xffff));
1132*9a0bf528SMauro Carvalho Chehab 	value = 500 * internal * factor;
1133*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
1134*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 11, (u16) (value & 0xffff));
1135*9a0bf528SMauro Carvalho Chehab 
1136*9a0bf528SMauro Carvalho Chehab 	value = dib7000p_read_word(state, 0);
1137*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
1138*9a0bf528SMauro Carvalho Chehab 	dib7000p_read_word(state, 1284);
1139*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 0, (u16) value);
1140*9a0bf528SMauro Carvalho Chehab 
1141*9a0bf528SMauro Carvalho Chehab 	return 0;
1142*9a0bf528SMauro Carvalho Chehab }
1143*9a0bf528SMauro Carvalho Chehab 
1144*9a0bf528SMauro Carvalho Chehab static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
1145*9a0bf528SMauro Carvalho Chehab {
1146*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
1147*9a0bf528SMauro Carvalho Chehab 	u16 irq_pending = dib7000p_read_word(state, 1284);
1148*9a0bf528SMauro Carvalho Chehab 
1149*9a0bf528SMauro Carvalho Chehab 	if (irq_pending & 0x1)
1150*9a0bf528SMauro Carvalho Chehab 		return 1;
1151*9a0bf528SMauro Carvalho Chehab 
1152*9a0bf528SMauro Carvalho Chehab 	if (irq_pending & 0x2)
1153*9a0bf528SMauro Carvalho Chehab 		return 2;
1154*9a0bf528SMauro Carvalho Chehab 
1155*9a0bf528SMauro Carvalho Chehab 	return 0;
1156*9a0bf528SMauro Carvalho Chehab }
1157*9a0bf528SMauro Carvalho Chehab 
1158*9a0bf528SMauro Carvalho Chehab static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
1159*9a0bf528SMauro Carvalho Chehab {
1160*9a0bf528SMauro Carvalho Chehab 	static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
1161*9a0bf528SMauro Carvalho Chehab 	static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
1162*9a0bf528SMauro Carvalho Chehab 		24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
1163*9a0bf528SMauro Carvalho Chehab 		53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
1164*9a0bf528SMauro Carvalho Chehab 		82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
1165*9a0bf528SMauro Carvalho Chehab 		107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
1166*9a0bf528SMauro Carvalho Chehab 		128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
1167*9a0bf528SMauro Carvalho Chehab 		147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
1168*9a0bf528SMauro Carvalho Chehab 		166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
1169*9a0bf528SMauro Carvalho Chehab 		183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
1170*9a0bf528SMauro Carvalho Chehab 		199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
1171*9a0bf528SMauro Carvalho Chehab 		213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
1172*9a0bf528SMauro Carvalho Chehab 		225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
1173*9a0bf528SMauro Carvalho Chehab 		235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
1174*9a0bf528SMauro Carvalho Chehab 		244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
1175*9a0bf528SMauro Carvalho Chehab 		250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
1176*9a0bf528SMauro Carvalho Chehab 		254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1177*9a0bf528SMauro Carvalho Chehab 		255, 255, 255, 255, 255, 255
1178*9a0bf528SMauro Carvalho Chehab 	};
1179*9a0bf528SMauro Carvalho Chehab 
1180*9a0bf528SMauro Carvalho Chehab 	u32 xtal = state->cfg.bw->xtal_hz / 1000;
1181*9a0bf528SMauro Carvalho Chehab 	int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
1182*9a0bf528SMauro Carvalho Chehab 	int k;
1183*9a0bf528SMauro Carvalho Chehab 	int coef_re[8], coef_im[8];
1184*9a0bf528SMauro Carvalho Chehab 	int bw_khz = bw;
1185*9a0bf528SMauro Carvalho Chehab 	u32 pha;
1186*9a0bf528SMauro Carvalho Chehab 
1187*9a0bf528SMauro Carvalho Chehab 	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
1188*9a0bf528SMauro Carvalho Chehab 
1189*9a0bf528SMauro Carvalho Chehab 	if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
1190*9a0bf528SMauro Carvalho Chehab 		return;
1191*9a0bf528SMauro Carvalho Chehab 
1192*9a0bf528SMauro Carvalho Chehab 	bw_khz /= 100;
1193*9a0bf528SMauro Carvalho Chehab 
1194*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 142, 0x0610);
1195*9a0bf528SMauro Carvalho Chehab 
1196*9a0bf528SMauro Carvalho Chehab 	for (k = 0; k < 8; k++) {
1197*9a0bf528SMauro Carvalho Chehab 		pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
1198*9a0bf528SMauro Carvalho Chehab 
1199*9a0bf528SMauro Carvalho Chehab 		if (pha == 0) {
1200*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = 256;
1201*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = 0;
1202*9a0bf528SMauro Carvalho Chehab 		} else if (pha < 256) {
1203*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = sine[256 - (pha & 0xff)];
1204*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = sine[pha & 0xff];
1205*9a0bf528SMauro Carvalho Chehab 		} else if (pha == 256) {
1206*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = 0;
1207*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = 256;
1208*9a0bf528SMauro Carvalho Chehab 		} else if (pha < 512) {
1209*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = -sine[pha & 0xff];
1210*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = sine[256 - (pha & 0xff)];
1211*9a0bf528SMauro Carvalho Chehab 		} else if (pha == 512) {
1212*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = -256;
1213*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = 0;
1214*9a0bf528SMauro Carvalho Chehab 		} else if (pha < 768) {
1215*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = -sine[256 - (pha & 0xff)];
1216*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = -sine[pha & 0xff];
1217*9a0bf528SMauro Carvalho Chehab 		} else if (pha == 768) {
1218*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = 0;
1219*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = -256;
1220*9a0bf528SMauro Carvalho Chehab 		} else {
1221*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = sine[pha & 0xff];
1222*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = -sine[256 - (pha & 0xff)];
1223*9a0bf528SMauro Carvalho Chehab 		}
1224*9a0bf528SMauro Carvalho Chehab 
1225*9a0bf528SMauro Carvalho Chehab 		coef_re[k] *= notch[k];
1226*9a0bf528SMauro Carvalho Chehab 		coef_re[k] += (1 << 14);
1227*9a0bf528SMauro Carvalho Chehab 		if (coef_re[k] >= (1 << 24))
1228*9a0bf528SMauro Carvalho Chehab 			coef_re[k] = (1 << 24) - 1;
1229*9a0bf528SMauro Carvalho Chehab 		coef_re[k] /= (1 << 15);
1230*9a0bf528SMauro Carvalho Chehab 
1231*9a0bf528SMauro Carvalho Chehab 		coef_im[k] *= notch[k];
1232*9a0bf528SMauro Carvalho Chehab 		coef_im[k] += (1 << 14);
1233*9a0bf528SMauro Carvalho Chehab 		if (coef_im[k] >= (1 << 24))
1234*9a0bf528SMauro Carvalho Chehab 			coef_im[k] = (1 << 24) - 1;
1235*9a0bf528SMauro Carvalho Chehab 		coef_im[k] /= (1 << 15);
1236*9a0bf528SMauro Carvalho Chehab 
1237*9a0bf528SMauro Carvalho Chehab 		dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
1238*9a0bf528SMauro Carvalho Chehab 
1239*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1240*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
1241*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1242*9a0bf528SMauro Carvalho Chehab 	}
1243*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 143, 0);
1244*9a0bf528SMauro Carvalho Chehab }
1245*9a0bf528SMauro Carvalho Chehab 
1246*9a0bf528SMauro Carvalho Chehab static int dib7000p_tune(struct dvb_frontend *demod)
1247*9a0bf528SMauro Carvalho Chehab {
1248*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
1249*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
1250*9a0bf528SMauro Carvalho Chehab 	u16 tmp = 0;
1251*9a0bf528SMauro Carvalho Chehab 
1252*9a0bf528SMauro Carvalho Chehab 	if (ch != NULL)
1253*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_channel(state, ch, 0);
1254*9a0bf528SMauro Carvalho Chehab 	else
1255*9a0bf528SMauro Carvalho Chehab 		return -EINVAL;
1256*9a0bf528SMauro Carvalho Chehab 
1257*9a0bf528SMauro Carvalho Chehab 	// restart demod
1258*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, 0x4000);
1259*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 770, 0x0000);
1260*9a0bf528SMauro Carvalho Chehab 	msleep(45);
1261*9a0bf528SMauro Carvalho Chehab 
1262*9a0bf528SMauro Carvalho Chehab 	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
1263*9a0bf528SMauro Carvalho Chehab 	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
1264*9a0bf528SMauro Carvalho Chehab 	if (state->sfn_workaround_active) {
1265*9a0bf528SMauro Carvalho Chehab 		dprintk("SFN workaround is active");
1266*9a0bf528SMauro Carvalho Chehab 		tmp |= (1 << 9);
1267*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 166, 0x4000);
1268*9a0bf528SMauro Carvalho Chehab 	} else {
1269*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 166, 0x0000);
1270*9a0bf528SMauro Carvalho Chehab 	}
1271*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 29, tmp);
1272*9a0bf528SMauro Carvalho Chehab 
1273*9a0bf528SMauro Carvalho Chehab 	// never achieved a lock with that bandwidth so far - wait for osc-freq to update
1274*9a0bf528SMauro Carvalho Chehab 	if (state->timf == 0)
1275*9a0bf528SMauro Carvalho Chehab 		msleep(200);
1276*9a0bf528SMauro Carvalho Chehab 
1277*9a0bf528SMauro Carvalho Chehab 	/* offset loop parameters */
1278*9a0bf528SMauro Carvalho Chehab 
1279*9a0bf528SMauro Carvalho Chehab 	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1280*9a0bf528SMauro Carvalho Chehab 	tmp = (6 << 8) | 0x80;
1281*9a0bf528SMauro Carvalho Chehab 	switch (ch->transmission_mode) {
1282*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
1283*9a0bf528SMauro Carvalho Chehab 		tmp |= (2 << 12);
1284*9a0bf528SMauro Carvalho Chehab 		break;
1285*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_4K:
1286*9a0bf528SMauro Carvalho Chehab 		tmp |= (3 << 12);
1287*9a0bf528SMauro Carvalho Chehab 		break;
1288*9a0bf528SMauro Carvalho Chehab 	default:
1289*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
1290*9a0bf528SMauro Carvalho Chehab 		tmp |= (4 << 12);
1291*9a0bf528SMauro Carvalho Chehab 		break;
1292*9a0bf528SMauro Carvalho Chehab 	}
1293*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 26, tmp);	/* timf_a(6xxx) */
1294*9a0bf528SMauro Carvalho Chehab 
1295*9a0bf528SMauro Carvalho Chehab 	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1296*9a0bf528SMauro Carvalho Chehab 	tmp = (0 << 4);
1297*9a0bf528SMauro Carvalho Chehab 	switch (ch->transmission_mode) {
1298*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
1299*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x6;
1300*9a0bf528SMauro Carvalho Chehab 		break;
1301*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_4K:
1302*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x7;
1303*9a0bf528SMauro Carvalho Chehab 		break;
1304*9a0bf528SMauro Carvalho Chehab 	default:
1305*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
1306*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x8;
1307*9a0bf528SMauro Carvalho Chehab 		break;
1308*9a0bf528SMauro Carvalho Chehab 	}
1309*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 32, tmp);
1310*9a0bf528SMauro Carvalho Chehab 
1311*9a0bf528SMauro Carvalho Chehab 	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1312*9a0bf528SMauro Carvalho Chehab 	tmp = (0 << 4);
1313*9a0bf528SMauro Carvalho Chehab 	switch (ch->transmission_mode) {
1314*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
1315*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x6;
1316*9a0bf528SMauro Carvalho Chehab 		break;
1317*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_4K:
1318*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x7;
1319*9a0bf528SMauro Carvalho Chehab 		break;
1320*9a0bf528SMauro Carvalho Chehab 	default:
1321*9a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
1322*9a0bf528SMauro Carvalho Chehab 		tmp |= 0x8;
1323*9a0bf528SMauro Carvalho Chehab 		break;
1324*9a0bf528SMauro Carvalho Chehab 	}
1325*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 33, tmp);
1326*9a0bf528SMauro Carvalho Chehab 
1327*9a0bf528SMauro Carvalho Chehab 	tmp = dib7000p_read_word(state, 509);
1328*9a0bf528SMauro Carvalho Chehab 	if (!((tmp >> 6) & 0x1)) {
1329*9a0bf528SMauro Carvalho Chehab 		/* restart the fec */
1330*9a0bf528SMauro Carvalho Chehab 		tmp = dib7000p_read_word(state, 771);
1331*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 771, tmp | (1 << 1));
1332*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 771, tmp);
1333*9a0bf528SMauro Carvalho Chehab 		msleep(40);
1334*9a0bf528SMauro Carvalho Chehab 		tmp = dib7000p_read_word(state, 509);
1335*9a0bf528SMauro Carvalho Chehab 	}
1336*9a0bf528SMauro Carvalho Chehab 	// we achieved a lock - it's time to update the osc freq
1337*9a0bf528SMauro Carvalho Chehab 	if ((tmp >> 6) & 0x1) {
1338*9a0bf528SMauro Carvalho Chehab 		dib7000p_update_timf(state);
1339*9a0bf528SMauro Carvalho Chehab 		/* P_timf_alpha += 2 */
1340*9a0bf528SMauro Carvalho Chehab 		tmp = dib7000p_read_word(state, 26);
1341*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
1342*9a0bf528SMauro Carvalho Chehab 	}
1343*9a0bf528SMauro Carvalho Chehab 
1344*9a0bf528SMauro Carvalho Chehab 	if (state->cfg.spur_protect)
1345*9a0bf528SMauro Carvalho Chehab 		dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
1346*9a0bf528SMauro Carvalho Chehab 
1347*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
1348*9a0bf528SMauro Carvalho Chehab 	return 0;
1349*9a0bf528SMauro Carvalho Chehab }
1350*9a0bf528SMauro Carvalho Chehab 
1351*9a0bf528SMauro Carvalho Chehab static int dib7000p_wakeup(struct dvb_frontend *demod)
1352*9a0bf528SMauro Carvalho Chehab {
1353*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
1354*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1355*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
1356*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090)
1357*9a0bf528SMauro Carvalho Chehab 		dib7000p_sad_calib(state);
1358*9a0bf528SMauro Carvalho Chehab 	return 0;
1359*9a0bf528SMauro Carvalho Chehab }
1360*9a0bf528SMauro Carvalho Chehab 
1361*9a0bf528SMauro Carvalho Chehab static int dib7000p_sleep(struct dvb_frontend *demod)
1362*9a0bf528SMauro Carvalho Chehab {
1363*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = demod->demodulator_priv;
1364*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090)
1365*9a0bf528SMauro Carvalho Chehab 		return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1366*9a0bf528SMauro Carvalho Chehab 	return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1367*9a0bf528SMauro Carvalho Chehab }
1368*9a0bf528SMauro Carvalho Chehab 
1369*9a0bf528SMauro Carvalho Chehab static int dib7000p_identify(struct dib7000p_state *st)
1370*9a0bf528SMauro Carvalho Chehab {
1371*9a0bf528SMauro Carvalho Chehab 	u16 value;
1372*9a0bf528SMauro Carvalho Chehab 	dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
1373*9a0bf528SMauro Carvalho Chehab 
1374*9a0bf528SMauro Carvalho Chehab 	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
1375*9a0bf528SMauro Carvalho Chehab 		dprintk("wrong Vendor ID (read=0x%x)", value);
1376*9a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1377*9a0bf528SMauro Carvalho Chehab 	}
1378*9a0bf528SMauro Carvalho Chehab 
1379*9a0bf528SMauro Carvalho Chehab 	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
1380*9a0bf528SMauro Carvalho Chehab 		dprintk("wrong Device ID (%x)", value);
1381*9a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1382*9a0bf528SMauro Carvalho Chehab 	}
1383*9a0bf528SMauro Carvalho Chehab 
1384*9a0bf528SMauro Carvalho Chehab 	return 0;
1385*9a0bf528SMauro Carvalho Chehab }
1386*9a0bf528SMauro Carvalho Chehab 
1387*9a0bf528SMauro Carvalho Chehab static int dib7000p_get_frontend(struct dvb_frontend *fe)
1388*9a0bf528SMauro Carvalho Chehab {
1389*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
1390*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1391*9a0bf528SMauro Carvalho Chehab 	u16 tps = dib7000p_read_word(state, 463);
1392*9a0bf528SMauro Carvalho Chehab 
1393*9a0bf528SMauro Carvalho Chehab 	fep->inversion = INVERSION_AUTO;
1394*9a0bf528SMauro Carvalho Chehab 
1395*9a0bf528SMauro Carvalho Chehab 	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
1396*9a0bf528SMauro Carvalho Chehab 
1397*9a0bf528SMauro Carvalho Chehab 	switch ((tps >> 8) & 0x3) {
1398*9a0bf528SMauro Carvalho Chehab 	case 0:
1399*9a0bf528SMauro Carvalho Chehab 		fep->transmission_mode = TRANSMISSION_MODE_2K;
1400*9a0bf528SMauro Carvalho Chehab 		break;
1401*9a0bf528SMauro Carvalho Chehab 	case 1:
1402*9a0bf528SMauro Carvalho Chehab 		fep->transmission_mode = TRANSMISSION_MODE_8K;
1403*9a0bf528SMauro Carvalho Chehab 		break;
1404*9a0bf528SMauro Carvalho Chehab 	/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
1405*9a0bf528SMauro Carvalho Chehab 	}
1406*9a0bf528SMauro Carvalho Chehab 
1407*9a0bf528SMauro Carvalho Chehab 	switch (tps & 0x3) {
1408*9a0bf528SMauro Carvalho Chehab 	case 0:
1409*9a0bf528SMauro Carvalho Chehab 		fep->guard_interval = GUARD_INTERVAL_1_32;
1410*9a0bf528SMauro Carvalho Chehab 		break;
1411*9a0bf528SMauro Carvalho Chehab 	case 1:
1412*9a0bf528SMauro Carvalho Chehab 		fep->guard_interval = GUARD_INTERVAL_1_16;
1413*9a0bf528SMauro Carvalho Chehab 		break;
1414*9a0bf528SMauro Carvalho Chehab 	case 2:
1415*9a0bf528SMauro Carvalho Chehab 		fep->guard_interval = GUARD_INTERVAL_1_8;
1416*9a0bf528SMauro Carvalho Chehab 		break;
1417*9a0bf528SMauro Carvalho Chehab 	case 3:
1418*9a0bf528SMauro Carvalho Chehab 		fep->guard_interval = GUARD_INTERVAL_1_4;
1419*9a0bf528SMauro Carvalho Chehab 		break;
1420*9a0bf528SMauro Carvalho Chehab 	}
1421*9a0bf528SMauro Carvalho Chehab 
1422*9a0bf528SMauro Carvalho Chehab 	switch ((tps >> 14) & 0x3) {
1423*9a0bf528SMauro Carvalho Chehab 	case 0:
1424*9a0bf528SMauro Carvalho Chehab 		fep->modulation = QPSK;
1425*9a0bf528SMauro Carvalho Chehab 		break;
1426*9a0bf528SMauro Carvalho Chehab 	case 1:
1427*9a0bf528SMauro Carvalho Chehab 		fep->modulation = QAM_16;
1428*9a0bf528SMauro Carvalho Chehab 		break;
1429*9a0bf528SMauro Carvalho Chehab 	case 2:
1430*9a0bf528SMauro Carvalho Chehab 	default:
1431*9a0bf528SMauro Carvalho Chehab 		fep->modulation = QAM_64;
1432*9a0bf528SMauro Carvalho Chehab 		break;
1433*9a0bf528SMauro Carvalho Chehab 	}
1434*9a0bf528SMauro Carvalho Chehab 
1435*9a0bf528SMauro Carvalho Chehab 	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1436*9a0bf528SMauro Carvalho Chehab 	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1437*9a0bf528SMauro Carvalho Chehab 
1438*9a0bf528SMauro Carvalho Chehab 	fep->hierarchy = HIERARCHY_NONE;
1439*9a0bf528SMauro Carvalho Chehab 	switch ((tps >> 5) & 0x7) {
1440*9a0bf528SMauro Carvalho Chehab 	case 1:
1441*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_HP = FEC_1_2;
1442*9a0bf528SMauro Carvalho Chehab 		break;
1443*9a0bf528SMauro Carvalho Chehab 	case 2:
1444*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_HP = FEC_2_3;
1445*9a0bf528SMauro Carvalho Chehab 		break;
1446*9a0bf528SMauro Carvalho Chehab 	case 3:
1447*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_HP = FEC_3_4;
1448*9a0bf528SMauro Carvalho Chehab 		break;
1449*9a0bf528SMauro Carvalho Chehab 	case 5:
1450*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_HP = FEC_5_6;
1451*9a0bf528SMauro Carvalho Chehab 		break;
1452*9a0bf528SMauro Carvalho Chehab 	case 7:
1453*9a0bf528SMauro Carvalho Chehab 	default:
1454*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_HP = FEC_7_8;
1455*9a0bf528SMauro Carvalho Chehab 		break;
1456*9a0bf528SMauro Carvalho Chehab 
1457*9a0bf528SMauro Carvalho Chehab 	}
1458*9a0bf528SMauro Carvalho Chehab 
1459*9a0bf528SMauro Carvalho Chehab 	switch ((tps >> 2) & 0x7) {
1460*9a0bf528SMauro Carvalho Chehab 	case 1:
1461*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_LP = FEC_1_2;
1462*9a0bf528SMauro Carvalho Chehab 		break;
1463*9a0bf528SMauro Carvalho Chehab 	case 2:
1464*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_LP = FEC_2_3;
1465*9a0bf528SMauro Carvalho Chehab 		break;
1466*9a0bf528SMauro Carvalho Chehab 	case 3:
1467*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_LP = FEC_3_4;
1468*9a0bf528SMauro Carvalho Chehab 		break;
1469*9a0bf528SMauro Carvalho Chehab 	case 5:
1470*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_LP = FEC_5_6;
1471*9a0bf528SMauro Carvalho Chehab 		break;
1472*9a0bf528SMauro Carvalho Chehab 	case 7:
1473*9a0bf528SMauro Carvalho Chehab 	default:
1474*9a0bf528SMauro Carvalho Chehab 		fep->code_rate_LP = FEC_7_8;
1475*9a0bf528SMauro Carvalho Chehab 		break;
1476*9a0bf528SMauro Carvalho Chehab 	}
1477*9a0bf528SMauro Carvalho Chehab 
1478*9a0bf528SMauro Carvalho Chehab 	/* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */
1479*9a0bf528SMauro Carvalho Chehab 
1480*9a0bf528SMauro Carvalho Chehab 	return 0;
1481*9a0bf528SMauro Carvalho Chehab }
1482*9a0bf528SMauro Carvalho Chehab 
1483*9a0bf528SMauro Carvalho Chehab static int dib7000p_set_frontend(struct dvb_frontend *fe)
1484*9a0bf528SMauro Carvalho Chehab {
1485*9a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
1486*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1487*9a0bf528SMauro Carvalho Chehab 	int time, ret;
1488*9a0bf528SMauro Carvalho Chehab 
1489*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090)
1490*9a0bf528SMauro Carvalho Chehab 		dib7090_set_diversity_in(fe, 0);
1491*9a0bf528SMauro Carvalho Chehab 	else
1492*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
1493*9a0bf528SMauro Carvalho Chehab 
1494*9a0bf528SMauro Carvalho Chehab 	/* maybe the parameter has been changed */
1495*9a0bf528SMauro Carvalho Chehab 	state->sfn_workaround_active = buggy_sfn_workaround;
1496*9a0bf528SMauro Carvalho Chehab 
1497*9a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.set_params)
1498*9a0bf528SMauro Carvalho Chehab 		fe->ops.tuner_ops.set_params(fe);
1499*9a0bf528SMauro Carvalho Chehab 
1500*9a0bf528SMauro Carvalho Chehab 	/* start up the AGC */
1501*9a0bf528SMauro Carvalho Chehab 	state->agc_state = 0;
1502*9a0bf528SMauro Carvalho Chehab 	do {
1503*9a0bf528SMauro Carvalho Chehab 		time = dib7000p_agc_startup(fe);
1504*9a0bf528SMauro Carvalho Chehab 		if (time != -1)
1505*9a0bf528SMauro Carvalho Chehab 			msleep(time);
1506*9a0bf528SMauro Carvalho Chehab 	} while (time != -1);
1507*9a0bf528SMauro Carvalho Chehab 
1508*9a0bf528SMauro Carvalho Chehab 	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
1509*9a0bf528SMauro Carvalho Chehab 		fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
1510*9a0bf528SMauro Carvalho Chehab 		int i = 800, found;
1511*9a0bf528SMauro Carvalho Chehab 
1512*9a0bf528SMauro Carvalho Chehab 		dib7000p_autosearch_start(fe);
1513*9a0bf528SMauro Carvalho Chehab 		do {
1514*9a0bf528SMauro Carvalho Chehab 			msleep(1);
1515*9a0bf528SMauro Carvalho Chehab 			found = dib7000p_autosearch_is_irq(fe);
1516*9a0bf528SMauro Carvalho Chehab 		} while (found == 0 && i--);
1517*9a0bf528SMauro Carvalho Chehab 
1518*9a0bf528SMauro Carvalho Chehab 		dprintk("autosearch returns: %d", found);
1519*9a0bf528SMauro Carvalho Chehab 		if (found == 0 || found == 1)
1520*9a0bf528SMauro Carvalho Chehab 			return 0;
1521*9a0bf528SMauro Carvalho Chehab 
1522*9a0bf528SMauro Carvalho Chehab 		dib7000p_get_frontend(fe);
1523*9a0bf528SMauro Carvalho Chehab 	}
1524*9a0bf528SMauro Carvalho Chehab 
1525*9a0bf528SMauro Carvalho Chehab 	ret = dib7000p_tune(fe);
1526*9a0bf528SMauro Carvalho Chehab 
1527*9a0bf528SMauro Carvalho Chehab 	/* make this a config parameter */
1528*9a0bf528SMauro Carvalho Chehab 	if (state->version == SOC7090) {
1529*9a0bf528SMauro Carvalho Chehab 		dib7090_set_output_mode(fe, state->cfg.output_mode);
1530*9a0bf528SMauro Carvalho Chehab 		if (state->cfg.enMpegOutput == 0) {
1531*9a0bf528SMauro Carvalho Chehab 			dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
1532*9a0bf528SMauro Carvalho Chehab 			dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1533*9a0bf528SMauro Carvalho Chehab 		}
1534*9a0bf528SMauro Carvalho Chehab 	} else
1535*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_output_mode(state, state->cfg.output_mode);
1536*9a0bf528SMauro Carvalho Chehab 
1537*9a0bf528SMauro Carvalho Chehab 	return ret;
1538*9a0bf528SMauro Carvalho Chehab }
1539*9a0bf528SMauro Carvalho Chehab 
1540*9a0bf528SMauro Carvalho Chehab static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
1541*9a0bf528SMauro Carvalho Chehab {
1542*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1543*9a0bf528SMauro Carvalho Chehab 	u16 lock = dib7000p_read_word(state, 509);
1544*9a0bf528SMauro Carvalho Chehab 
1545*9a0bf528SMauro Carvalho Chehab 	*stat = 0;
1546*9a0bf528SMauro Carvalho Chehab 
1547*9a0bf528SMauro Carvalho Chehab 	if (lock & 0x8000)
1548*9a0bf528SMauro Carvalho Chehab 		*stat |= FE_HAS_SIGNAL;
1549*9a0bf528SMauro Carvalho Chehab 	if (lock & 0x3000)
1550*9a0bf528SMauro Carvalho Chehab 		*stat |= FE_HAS_CARRIER;
1551*9a0bf528SMauro Carvalho Chehab 	if (lock & 0x0100)
1552*9a0bf528SMauro Carvalho Chehab 		*stat |= FE_HAS_VITERBI;
1553*9a0bf528SMauro Carvalho Chehab 	if (lock & 0x0010)
1554*9a0bf528SMauro Carvalho Chehab 		*stat |= FE_HAS_SYNC;
1555*9a0bf528SMauro Carvalho Chehab 	if ((lock & 0x0038) == 0x38)
1556*9a0bf528SMauro Carvalho Chehab 		*stat |= FE_HAS_LOCK;
1557*9a0bf528SMauro Carvalho Chehab 
1558*9a0bf528SMauro Carvalho Chehab 	return 0;
1559*9a0bf528SMauro Carvalho Chehab }
1560*9a0bf528SMauro Carvalho Chehab 
1561*9a0bf528SMauro Carvalho Chehab static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
1562*9a0bf528SMauro Carvalho Chehab {
1563*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1564*9a0bf528SMauro Carvalho Chehab 	*ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1565*9a0bf528SMauro Carvalho Chehab 	return 0;
1566*9a0bf528SMauro Carvalho Chehab }
1567*9a0bf528SMauro Carvalho Chehab 
1568*9a0bf528SMauro Carvalho Chehab static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
1569*9a0bf528SMauro Carvalho Chehab {
1570*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1571*9a0bf528SMauro Carvalho Chehab 	*unc = dib7000p_read_word(state, 506);
1572*9a0bf528SMauro Carvalho Chehab 	return 0;
1573*9a0bf528SMauro Carvalho Chehab }
1574*9a0bf528SMauro Carvalho Chehab 
1575*9a0bf528SMauro Carvalho Chehab static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
1576*9a0bf528SMauro Carvalho Chehab {
1577*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1578*9a0bf528SMauro Carvalho Chehab 	u16 val = dib7000p_read_word(state, 394);
1579*9a0bf528SMauro Carvalho Chehab 	*strength = 65535 - val;
1580*9a0bf528SMauro Carvalho Chehab 	return 0;
1581*9a0bf528SMauro Carvalho Chehab }
1582*9a0bf528SMauro Carvalho Chehab 
1583*9a0bf528SMauro Carvalho Chehab static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
1584*9a0bf528SMauro Carvalho Chehab {
1585*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1586*9a0bf528SMauro Carvalho Chehab 	u16 val;
1587*9a0bf528SMauro Carvalho Chehab 	s32 signal_mant, signal_exp, noise_mant, noise_exp;
1588*9a0bf528SMauro Carvalho Chehab 	u32 result = 0;
1589*9a0bf528SMauro Carvalho Chehab 
1590*9a0bf528SMauro Carvalho Chehab 	val = dib7000p_read_word(state, 479);
1591*9a0bf528SMauro Carvalho Chehab 	noise_mant = (val >> 4) & 0xff;
1592*9a0bf528SMauro Carvalho Chehab 	noise_exp = ((val & 0xf) << 2);
1593*9a0bf528SMauro Carvalho Chehab 	val = dib7000p_read_word(state, 480);
1594*9a0bf528SMauro Carvalho Chehab 	noise_exp += ((val >> 14) & 0x3);
1595*9a0bf528SMauro Carvalho Chehab 	if ((noise_exp & 0x20) != 0)
1596*9a0bf528SMauro Carvalho Chehab 		noise_exp -= 0x40;
1597*9a0bf528SMauro Carvalho Chehab 
1598*9a0bf528SMauro Carvalho Chehab 	signal_mant = (val >> 6) & 0xFF;
1599*9a0bf528SMauro Carvalho Chehab 	signal_exp = (val & 0x3F);
1600*9a0bf528SMauro Carvalho Chehab 	if ((signal_exp & 0x20) != 0)
1601*9a0bf528SMauro Carvalho Chehab 		signal_exp -= 0x40;
1602*9a0bf528SMauro Carvalho Chehab 
1603*9a0bf528SMauro Carvalho Chehab 	if (signal_mant != 0)
1604*9a0bf528SMauro Carvalho Chehab 		result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
1605*9a0bf528SMauro Carvalho Chehab 	else
1606*9a0bf528SMauro Carvalho Chehab 		result = intlog10(2) * 10 * signal_exp - 100;
1607*9a0bf528SMauro Carvalho Chehab 
1608*9a0bf528SMauro Carvalho Chehab 	if (noise_mant != 0)
1609*9a0bf528SMauro Carvalho Chehab 		result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
1610*9a0bf528SMauro Carvalho Chehab 	else
1611*9a0bf528SMauro Carvalho Chehab 		result -= intlog10(2) * 10 * noise_exp - 100;
1612*9a0bf528SMauro Carvalho Chehab 
1613*9a0bf528SMauro Carvalho Chehab 	*snr = result / ((1 << 24) / 10);
1614*9a0bf528SMauro Carvalho Chehab 	return 0;
1615*9a0bf528SMauro Carvalho Chehab }
1616*9a0bf528SMauro Carvalho Chehab 
1617*9a0bf528SMauro Carvalho Chehab static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
1618*9a0bf528SMauro Carvalho Chehab {
1619*9a0bf528SMauro Carvalho Chehab 	tune->min_delay_ms = 1000;
1620*9a0bf528SMauro Carvalho Chehab 	return 0;
1621*9a0bf528SMauro Carvalho Chehab }
1622*9a0bf528SMauro Carvalho Chehab 
1623*9a0bf528SMauro Carvalho Chehab static void dib7000p_release(struct dvb_frontend *demod)
1624*9a0bf528SMauro Carvalho Chehab {
1625*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *st = demod->demodulator_priv;
1626*9a0bf528SMauro Carvalho Chehab 	dibx000_exit_i2c_master(&st->i2c_master);
1627*9a0bf528SMauro Carvalho Chehab 	i2c_del_adapter(&st->dib7090_tuner_adap);
1628*9a0bf528SMauro Carvalho Chehab 	kfree(st);
1629*9a0bf528SMauro Carvalho Chehab }
1630*9a0bf528SMauro Carvalho Chehab 
1631*9a0bf528SMauro Carvalho Chehab int dib7000pc_detection(struct i2c_adapter *i2c_adap)
1632*9a0bf528SMauro Carvalho Chehab {
1633*9a0bf528SMauro Carvalho Chehab 	u8 *tx, *rx;
1634*9a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg[2] = {
1635*9a0bf528SMauro Carvalho Chehab 		{.addr = 18 >> 1, .flags = 0, .len = 2},
1636*9a0bf528SMauro Carvalho Chehab 		{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
1637*9a0bf528SMauro Carvalho Chehab 	};
1638*9a0bf528SMauro Carvalho Chehab 	int ret = 0;
1639*9a0bf528SMauro Carvalho Chehab 
1640*9a0bf528SMauro Carvalho Chehab 	tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1641*9a0bf528SMauro Carvalho Chehab 	if (!tx)
1642*9a0bf528SMauro Carvalho Chehab 		return -ENOMEM;
1643*9a0bf528SMauro Carvalho Chehab 	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1644*9a0bf528SMauro Carvalho Chehab 	if (!rx) {
1645*9a0bf528SMauro Carvalho Chehab 		ret = -ENOMEM;
1646*9a0bf528SMauro Carvalho Chehab 		goto rx_memory_error;
1647*9a0bf528SMauro Carvalho Chehab 	}
1648*9a0bf528SMauro Carvalho Chehab 
1649*9a0bf528SMauro Carvalho Chehab 	msg[0].buf = tx;
1650*9a0bf528SMauro Carvalho Chehab 	msg[1].buf = rx;
1651*9a0bf528SMauro Carvalho Chehab 
1652*9a0bf528SMauro Carvalho Chehab 	tx[0] = 0x03;
1653*9a0bf528SMauro Carvalho Chehab 	tx[1] = 0x00;
1654*9a0bf528SMauro Carvalho Chehab 
1655*9a0bf528SMauro Carvalho Chehab 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
1656*9a0bf528SMauro Carvalho Chehab 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
1657*9a0bf528SMauro Carvalho Chehab 			dprintk("-D-  DiB7000PC detected");
1658*9a0bf528SMauro Carvalho Chehab 			return 1;
1659*9a0bf528SMauro Carvalho Chehab 		}
1660*9a0bf528SMauro Carvalho Chehab 
1661*9a0bf528SMauro Carvalho Chehab 	msg[0].addr = msg[1].addr = 0x40;
1662*9a0bf528SMauro Carvalho Chehab 
1663*9a0bf528SMauro Carvalho Chehab 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
1664*9a0bf528SMauro Carvalho Chehab 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
1665*9a0bf528SMauro Carvalho Chehab 			dprintk("-D-  DiB7000PC detected");
1666*9a0bf528SMauro Carvalho Chehab 			return 1;
1667*9a0bf528SMauro Carvalho Chehab 		}
1668*9a0bf528SMauro Carvalho Chehab 
1669*9a0bf528SMauro Carvalho Chehab 	dprintk("-D-  DiB7000PC not detected");
1670*9a0bf528SMauro Carvalho Chehab 
1671*9a0bf528SMauro Carvalho Chehab 	kfree(rx);
1672*9a0bf528SMauro Carvalho Chehab rx_memory_error:
1673*9a0bf528SMauro Carvalho Chehab 	kfree(tx);
1674*9a0bf528SMauro Carvalho Chehab 	return ret;
1675*9a0bf528SMauro Carvalho Chehab }
1676*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000pc_detection);
1677*9a0bf528SMauro Carvalho Chehab 
1678*9a0bf528SMauro Carvalho Chehab struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1679*9a0bf528SMauro Carvalho Chehab {
1680*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *st = demod->demodulator_priv;
1681*9a0bf528SMauro Carvalho Chehab 	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1682*9a0bf528SMauro Carvalho Chehab }
1683*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_get_i2c_master);
1684*9a0bf528SMauro Carvalho Chehab 
1685*9a0bf528SMauro Carvalho Chehab int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1686*9a0bf528SMauro Carvalho Chehab {
1687*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1688*9a0bf528SMauro Carvalho Chehab 	u16 val = dib7000p_read_word(state, 235) & 0xffef;
1689*9a0bf528SMauro Carvalho Chehab 	val |= (onoff & 0x1) << 4;
1690*9a0bf528SMauro Carvalho Chehab 	dprintk("PID filter enabled %d", onoff);
1691*9a0bf528SMauro Carvalho Chehab 	return dib7000p_write_word(state, 235, val);
1692*9a0bf528SMauro Carvalho Chehab }
1693*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
1694*9a0bf528SMauro Carvalho Chehab 
1695*9a0bf528SMauro Carvalho Chehab int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1696*9a0bf528SMauro Carvalho Chehab {
1697*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1698*9a0bf528SMauro Carvalho Chehab 	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1699*9a0bf528SMauro Carvalho Chehab 	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
1700*9a0bf528SMauro Carvalho Chehab }
1701*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_pid_filter);
1702*9a0bf528SMauro Carvalho Chehab 
1703*9a0bf528SMauro Carvalho Chehab int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
1704*9a0bf528SMauro Carvalho Chehab {
1705*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *dpst;
1706*9a0bf528SMauro Carvalho Chehab 	int k = 0;
1707*9a0bf528SMauro Carvalho Chehab 	u8 new_addr = 0;
1708*9a0bf528SMauro Carvalho Chehab 
1709*9a0bf528SMauro Carvalho Chehab 	dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1710*9a0bf528SMauro Carvalho Chehab 	if (!dpst)
1711*9a0bf528SMauro Carvalho Chehab 		return -ENOMEM;
1712*9a0bf528SMauro Carvalho Chehab 
1713*9a0bf528SMauro Carvalho Chehab 	dpst->i2c_adap = i2c;
1714*9a0bf528SMauro Carvalho Chehab 	mutex_init(&dpst->i2c_buffer_lock);
1715*9a0bf528SMauro Carvalho Chehab 
1716*9a0bf528SMauro Carvalho Chehab 	for (k = no_of_demods - 1; k >= 0; k--) {
1717*9a0bf528SMauro Carvalho Chehab 		dpst->cfg = cfg[k];
1718*9a0bf528SMauro Carvalho Chehab 
1719*9a0bf528SMauro Carvalho Chehab 		/* designated i2c address */
1720*9a0bf528SMauro Carvalho Chehab 		if (cfg[k].default_i2c_addr != 0)
1721*9a0bf528SMauro Carvalho Chehab 			new_addr = cfg[k].default_i2c_addr + (k << 1);
1722*9a0bf528SMauro Carvalho Chehab 		else
1723*9a0bf528SMauro Carvalho Chehab 			new_addr = (0x40 + k) << 1;
1724*9a0bf528SMauro Carvalho Chehab 		dpst->i2c_addr = new_addr;
1725*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
1726*9a0bf528SMauro Carvalho Chehab 		if (dib7000p_identify(dpst) != 0) {
1727*9a0bf528SMauro Carvalho Chehab 			dpst->i2c_addr = default_addr;
1728*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
1729*9a0bf528SMauro Carvalho Chehab 			if (dib7000p_identify(dpst) != 0) {
1730*9a0bf528SMauro Carvalho Chehab 				dprintk("DiB7000P #%d: not identified\n", k);
1731*9a0bf528SMauro Carvalho Chehab 				kfree(dpst);
1732*9a0bf528SMauro Carvalho Chehab 				return -EIO;
1733*9a0bf528SMauro Carvalho Chehab 			}
1734*9a0bf528SMauro Carvalho Chehab 		}
1735*9a0bf528SMauro Carvalho Chehab 
1736*9a0bf528SMauro Carvalho Chehab 		/* start diversity to pull_down div_str - just for i2c-enumeration */
1737*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
1738*9a0bf528SMauro Carvalho Chehab 
1739*9a0bf528SMauro Carvalho Chehab 		/* set new i2c address and force divstart */
1740*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
1741*9a0bf528SMauro Carvalho Chehab 
1742*9a0bf528SMauro Carvalho Chehab 		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
1743*9a0bf528SMauro Carvalho Chehab 	}
1744*9a0bf528SMauro Carvalho Chehab 
1745*9a0bf528SMauro Carvalho Chehab 	for (k = 0; k < no_of_demods; k++) {
1746*9a0bf528SMauro Carvalho Chehab 		dpst->cfg = cfg[k];
1747*9a0bf528SMauro Carvalho Chehab 		if (cfg[k].default_i2c_addr != 0)
1748*9a0bf528SMauro Carvalho Chehab 			dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
1749*9a0bf528SMauro Carvalho Chehab 		else
1750*9a0bf528SMauro Carvalho Chehab 			dpst->i2c_addr = (0x40 + k) << 1;
1751*9a0bf528SMauro Carvalho Chehab 
1752*9a0bf528SMauro Carvalho Chehab 		// unforce divstr
1753*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
1754*9a0bf528SMauro Carvalho Chehab 
1755*9a0bf528SMauro Carvalho Chehab 		/* deactivate div - it was just for i2c-enumeration */
1756*9a0bf528SMauro Carvalho Chehab 		dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
1757*9a0bf528SMauro Carvalho Chehab 	}
1758*9a0bf528SMauro Carvalho Chehab 
1759*9a0bf528SMauro Carvalho Chehab 	kfree(dpst);
1760*9a0bf528SMauro Carvalho Chehab 	return 0;
1761*9a0bf528SMauro Carvalho Chehab }
1762*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_i2c_enumeration);
1763*9a0bf528SMauro Carvalho Chehab 
1764*9a0bf528SMauro Carvalho Chehab static const s32 lut_1000ln_mant[] = {
1765*9a0bf528SMauro Carvalho Chehab 	6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
1766*9a0bf528SMauro Carvalho Chehab };
1767*9a0bf528SMauro Carvalho Chehab 
1768*9a0bf528SMauro Carvalho Chehab static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
1769*9a0bf528SMauro Carvalho Chehab {
1770*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
1771*9a0bf528SMauro Carvalho Chehab 	u32 tmp_val = 0, exp = 0, mant = 0;
1772*9a0bf528SMauro Carvalho Chehab 	s32 pow_i;
1773*9a0bf528SMauro Carvalho Chehab 	u16 buf[2];
1774*9a0bf528SMauro Carvalho Chehab 	u8 ix = 0;
1775*9a0bf528SMauro Carvalho Chehab 
1776*9a0bf528SMauro Carvalho Chehab 	buf[0] = dib7000p_read_word(state, 0x184);
1777*9a0bf528SMauro Carvalho Chehab 	buf[1] = dib7000p_read_word(state, 0x185);
1778*9a0bf528SMauro Carvalho Chehab 	pow_i = (buf[0] << 16) | buf[1];
1779*9a0bf528SMauro Carvalho Chehab 	dprintk("raw pow_i = %d", pow_i);
1780*9a0bf528SMauro Carvalho Chehab 
1781*9a0bf528SMauro Carvalho Chehab 	tmp_val = pow_i;
1782*9a0bf528SMauro Carvalho Chehab 	while (tmp_val >>= 1)
1783*9a0bf528SMauro Carvalho Chehab 		exp++;
1784*9a0bf528SMauro Carvalho Chehab 
1785*9a0bf528SMauro Carvalho Chehab 	mant = (pow_i * 1000 / (1 << exp));
1786*9a0bf528SMauro Carvalho Chehab 	dprintk(" mant = %d exp = %d", mant / 1000, exp);
1787*9a0bf528SMauro Carvalho Chehab 
1788*9a0bf528SMauro Carvalho Chehab 	ix = (u8) ((mant - 1000) / 100);	/* index of the LUT */
1789*9a0bf528SMauro Carvalho Chehab 	dprintk(" ix = %d", ix);
1790*9a0bf528SMauro Carvalho Chehab 
1791*9a0bf528SMauro Carvalho Chehab 	pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
1792*9a0bf528SMauro Carvalho Chehab 	pow_i = (pow_i << 8) / 1000;
1793*9a0bf528SMauro Carvalho Chehab 	dprintk(" pow_i = %d", pow_i);
1794*9a0bf528SMauro Carvalho Chehab 
1795*9a0bf528SMauro Carvalho Chehab 	return pow_i;
1796*9a0bf528SMauro Carvalho Chehab }
1797*9a0bf528SMauro Carvalho Chehab 
1798*9a0bf528SMauro Carvalho Chehab static int map_addr_to_serpar_number(struct i2c_msg *msg)
1799*9a0bf528SMauro Carvalho Chehab {
1800*9a0bf528SMauro Carvalho Chehab 	if ((msg->buf[0] <= 15))
1801*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] -= 1;
1802*9a0bf528SMauro Carvalho Chehab 	else if (msg->buf[0] == 17)
1803*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] = 15;
1804*9a0bf528SMauro Carvalho Chehab 	else if (msg->buf[0] == 16)
1805*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] = 17;
1806*9a0bf528SMauro Carvalho Chehab 	else if (msg->buf[0] == 19)
1807*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] = 16;
1808*9a0bf528SMauro Carvalho Chehab 	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
1809*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] -= 3;
1810*9a0bf528SMauro Carvalho Chehab 	else if (msg->buf[0] == 28)
1811*9a0bf528SMauro Carvalho Chehab 		msg->buf[0] = 23;
1812*9a0bf528SMauro Carvalho Chehab 	else
1813*9a0bf528SMauro Carvalho Chehab 		return -EINVAL;
1814*9a0bf528SMauro Carvalho Chehab 	return 0;
1815*9a0bf528SMauro Carvalho Chehab }
1816*9a0bf528SMauro Carvalho Chehab 
1817*9a0bf528SMauro Carvalho Chehab static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1818*9a0bf528SMauro Carvalho Chehab {
1819*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1820*9a0bf528SMauro Carvalho Chehab 	u8 n_overflow = 1;
1821*9a0bf528SMauro Carvalho Chehab 	u16 i = 1000;
1822*9a0bf528SMauro Carvalho Chehab 	u16 serpar_num = msg[0].buf[0];
1823*9a0bf528SMauro Carvalho Chehab 
1824*9a0bf528SMauro Carvalho Chehab 	while (n_overflow == 1 && i) {
1825*9a0bf528SMauro Carvalho Chehab 		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1826*9a0bf528SMauro Carvalho Chehab 		i--;
1827*9a0bf528SMauro Carvalho Chehab 		if (i == 0)
1828*9a0bf528SMauro Carvalho Chehab 			dprintk("Tuner ITF: write busy (overflow)");
1829*9a0bf528SMauro Carvalho Chehab 	}
1830*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
1831*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
1832*9a0bf528SMauro Carvalho Chehab 
1833*9a0bf528SMauro Carvalho Chehab 	return num;
1834*9a0bf528SMauro Carvalho Chehab }
1835*9a0bf528SMauro Carvalho Chehab 
1836*9a0bf528SMauro Carvalho Chehab static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1837*9a0bf528SMauro Carvalho Chehab {
1838*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1839*9a0bf528SMauro Carvalho Chehab 	u8 n_overflow = 1, n_empty = 1;
1840*9a0bf528SMauro Carvalho Chehab 	u16 i = 1000;
1841*9a0bf528SMauro Carvalho Chehab 	u16 serpar_num = msg[0].buf[0];
1842*9a0bf528SMauro Carvalho Chehab 	u16 read_word;
1843*9a0bf528SMauro Carvalho Chehab 
1844*9a0bf528SMauro Carvalho Chehab 	while (n_overflow == 1 && i) {
1845*9a0bf528SMauro Carvalho Chehab 		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1846*9a0bf528SMauro Carvalho Chehab 		i--;
1847*9a0bf528SMauro Carvalho Chehab 		if (i == 0)
1848*9a0bf528SMauro Carvalho Chehab 			dprintk("TunerITF: read busy (overflow)");
1849*9a0bf528SMauro Carvalho Chehab 	}
1850*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
1851*9a0bf528SMauro Carvalho Chehab 
1852*9a0bf528SMauro Carvalho Chehab 	i = 1000;
1853*9a0bf528SMauro Carvalho Chehab 	while (n_empty == 1 && i) {
1854*9a0bf528SMauro Carvalho Chehab 		n_empty = dib7000p_read_word(state, 1984) & 0x1;
1855*9a0bf528SMauro Carvalho Chehab 		i--;
1856*9a0bf528SMauro Carvalho Chehab 		if (i == 0)
1857*9a0bf528SMauro Carvalho Chehab 			dprintk("TunerITF: read busy (empty)");
1858*9a0bf528SMauro Carvalho Chehab 	}
1859*9a0bf528SMauro Carvalho Chehab 	read_word = dib7000p_read_word(state, 1987);
1860*9a0bf528SMauro Carvalho Chehab 	msg[1].buf[0] = (read_word >> 8) & 0xff;
1861*9a0bf528SMauro Carvalho Chehab 	msg[1].buf[1] = (read_word) & 0xff;
1862*9a0bf528SMauro Carvalho Chehab 
1863*9a0bf528SMauro Carvalho Chehab 	return num;
1864*9a0bf528SMauro Carvalho Chehab }
1865*9a0bf528SMauro Carvalho Chehab 
1866*9a0bf528SMauro Carvalho Chehab static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1867*9a0bf528SMauro Carvalho Chehab {
1868*9a0bf528SMauro Carvalho Chehab 	if (map_addr_to_serpar_number(&msg[0]) == 0) {	/* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
1869*9a0bf528SMauro Carvalho Chehab 		if (num == 1) {	/* write */
1870*9a0bf528SMauro Carvalho Chehab 			return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
1871*9a0bf528SMauro Carvalho Chehab 		} else {	/* read */
1872*9a0bf528SMauro Carvalho Chehab 			return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
1873*9a0bf528SMauro Carvalho Chehab 		}
1874*9a0bf528SMauro Carvalho Chehab 	}
1875*9a0bf528SMauro Carvalho Chehab 	return num;
1876*9a0bf528SMauro Carvalho Chehab }
1877*9a0bf528SMauro Carvalho Chehab 
1878*9a0bf528SMauro Carvalho Chehab static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
1879*9a0bf528SMauro Carvalho Chehab 		struct i2c_msg msg[], int num, u16 apb_address)
1880*9a0bf528SMauro Carvalho Chehab {
1881*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1882*9a0bf528SMauro Carvalho Chehab 	u16 word;
1883*9a0bf528SMauro Carvalho Chehab 
1884*9a0bf528SMauro Carvalho Chehab 	if (num == 1) {		/* write */
1885*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
1886*9a0bf528SMauro Carvalho Chehab 	} else {
1887*9a0bf528SMauro Carvalho Chehab 		word = dib7000p_read_word(state, apb_address);
1888*9a0bf528SMauro Carvalho Chehab 		msg[1].buf[0] = (word >> 8) & 0xff;
1889*9a0bf528SMauro Carvalho Chehab 		msg[1].buf[1] = (word) & 0xff;
1890*9a0bf528SMauro Carvalho Chehab 	}
1891*9a0bf528SMauro Carvalho Chehab 
1892*9a0bf528SMauro Carvalho Chehab 	return num;
1893*9a0bf528SMauro Carvalho Chehab }
1894*9a0bf528SMauro Carvalho Chehab 
1895*9a0bf528SMauro Carvalho Chehab static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1896*9a0bf528SMauro Carvalho Chehab {
1897*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1898*9a0bf528SMauro Carvalho Chehab 
1899*9a0bf528SMauro Carvalho Chehab 	u16 apb_address = 0, word;
1900*9a0bf528SMauro Carvalho Chehab 	int i = 0;
1901*9a0bf528SMauro Carvalho Chehab 	switch (msg[0].buf[0]) {
1902*9a0bf528SMauro Carvalho Chehab 	case 0x12:
1903*9a0bf528SMauro Carvalho Chehab 		apb_address = 1920;
1904*9a0bf528SMauro Carvalho Chehab 		break;
1905*9a0bf528SMauro Carvalho Chehab 	case 0x14:
1906*9a0bf528SMauro Carvalho Chehab 		apb_address = 1921;
1907*9a0bf528SMauro Carvalho Chehab 		break;
1908*9a0bf528SMauro Carvalho Chehab 	case 0x24:
1909*9a0bf528SMauro Carvalho Chehab 		apb_address = 1922;
1910*9a0bf528SMauro Carvalho Chehab 		break;
1911*9a0bf528SMauro Carvalho Chehab 	case 0x1a:
1912*9a0bf528SMauro Carvalho Chehab 		apb_address = 1923;
1913*9a0bf528SMauro Carvalho Chehab 		break;
1914*9a0bf528SMauro Carvalho Chehab 	case 0x22:
1915*9a0bf528SMauro Carvalho Chehab 		apb_address = 1924;
1916*9a0bf528SMauro Carvalho Chehab 		break;
1917*9a0bf528SMauro Carvalho Chehab 	case 0x33:
1918*9a0bf528SMauro Carvalho Chehab 		apb_address = 1926;
1919*9a0bf528SMauro Carvalho Chehab 		break;
1920*9a0bf528SMauro Carvalho Chehab 	case 0x34:
1921*9a0bf528SMauro Carvalho Chehab 		apb_address = 1927;
1922*9a0bf528SMauro Carvalho Chehab 		break;
1923*9a0bf528SMauro Carvalho Chehab 	case 0x35:
1924*9a0bf528SMauro Carvalho Chehab 		apb_address = 1928;
1925*9a0bf528SMauro Carvalho Chehab 		break;
1926*9a0bf528SMauro Carvalho Chehab 	case 0x36:
1927*9a0bf528SMauro Carvalho Chehab 		apb_address = 1929;
1928*9a0bf528SMauro Carvalho Chehab 		break;
1929*9a0bf528SMauro Carvalho Chehab 	case 0x37:
1930*9a0bf528SMauro Carvalho Chehab 		apb_address = 1930;
1931*9a0bf528SMauro Carvalho Chehab 		break;
1932*9a0bf528SMauro Carvalho Chehab 	case 0x38:
1933*9a0bf528SMauro Carvalho Chehab 		apb_address = 1931;
1934*9a0bf528SMauro Carvalho Chehab 		break;
1935*9a0bf528SMauro Carvalho Chehab 	case 0x39:
1936*9a0bf528SMauro Carvalho Chehab 		apb_address = 1932;
1937*9a0bf528SMauro Carvalho Chehab 		break;
1938*9a0bf528SMauro Carvalho Chehab 	case 0x2a:
1939*9a0bf528SMauro Carvalho Chehab 		apb_address = 1935;
1940*9a0bf528SMauro Carvalho Chehab 		break;
1941*9a0bf528SMauro Carvalho Chehab 	case 0x2b:
1942*9a0bf528SMauro Carvalho Chehab 		apb_address = 1936;
1943*9a0bf528SMauro Carvalho Chehab 		break;
1944*9a0bf528SMauro Carvalho Chehab 	case 0x2c:
1945*9a0bf528SMauro Carvalho Chehab 		apb_address = 1937;
1946*9a0bf528SMauro Carvalho Chehab 		break;
1947*9a0bf528SMauro Carvalho Chehab 	case 0x2d:
1948*9a0bf528SMauro Carvalho Chehab 		apb_address = 1938;
1949*9a0bf528SMauro Carvalho Chehab 		break;
1950*9a0bf528SMauro Carvalho Chehab 	case 0x2e:
1951*9a0bf528SMauro Carvalho Chehab 		apb_address = 1939;
1952*9a0bf528SMauro Carvalho Chehab 		break;
1953*9a0bf528SMauro Carvalho Chehab 	case 0x2f:
1954*9a0bf528SMauro Carvalho Chehab 		apb_address = 1940;
1955*9a0bf528SMauro Carvalho Chehab 		break;
1956*9a0bf528SMauro Carvalho Chehab 	case 0x30:
1957*9a0bf528SMauro Carvalho Chehab 		apb_address = 1941;
1958*9a0bf528SMauro Carvalho Chehab 		break;
1959*9a0bf528SMauro Carvalho Chehab 	case 0x31:
1960*9a0bf528SMauro Carvalho Chehab 		apb_address = 1942;
1961*9a0bf528SMauro Carvalho Chehab 		break;
1962*9a0bf528SMauro Carvalho Chehab 	case 0x32:
1963*9a0bf528SMauro Carvalho Chehab 		apb_address = 1943;
1964*9a0bf528SMauro Carvalho Chehab 		break;
1965*9a0bf528SMauro Carvalho Chehab 	case 0x3e:
1966*9a0bf528SMauro Carvalho Chehab 		apb_address = 1944;
1967*9a0bf528SMauro Carvalho Chehab 		break;
1968*9a0bf528SMauro Carvalho Chehab 	case 0x3f:
1969*9a0bf528SMauro Carvalho Chehab 		apb_address = 1945;
1970*9a0bf528SMauro Carvalho Chehab 		break;
1971*9a0bf528SMauro Carvalho Chehab 	case 0x40:
1972*9a0bf528SMauro Carvalho Chehab 		apb_address = 1948;
1973*9a0bf528SMauro Carvalho Chehab 		break;
1974*9a0bf528SMauro Carvalho Chehab 	case 0x25:
1975*9a0bf528SMauro Carvalho Chehab 		apb_address = 914;
1976*9a0bf528SMauro Carvalho Chehab 		break;
1977*9a0bf528SMauro Carvalho Chehab 	case 0x26:
1978*9a0bf528SMauro Carvalho Chehab 		apb_address = 915;
1979*9a0bf528SMauro Carvalho Chehab 		break;
1980*9a0bf528SMauro Carvalho Chehab 	case 0x27:
1981*9a0bf528SMauro Carvalho Chehab 		apb_address = 917;
1982*9a0bf528SMauro Carvalho Chehab 		break;
1983*9a0bf528SMauro Carvalho Chehab 	case 0x28:
1984*9a0bf528SMauro Carvalho Chehab 		apb_address = 916;
1985*9a0bf528SMauro Carvalho Chehab 		break;
1986*9a0bf528SMauro Carvalho Chehab 	case 0x1d:
1987*9a0bf528SMauro Carvalho Chehab 		i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
1988*9a0bf528SMauro Carvalho Chehab 		word = dib7000p_read_word(state, 384 + i);
1989*9a0bf528SMauro Carvalho Chehab 		msg[1].buf[0] = (word >> 8) & 0xff;
1990*9a0bf528SMauro Carvalho Chehab 		msg[1].buf[1] = (word) & 0xff;
1991*9a0bf528SMauro Carvalho Chehab 		return num;
1992*9a0bf528SMauro Carvalho Chehab 	case 0x1f:
1993*9a0bf528SMauro Carvalho Chehab 		if (num == 1) {	/* write */
1994*9a0bf528SMauro Carvalho Chehab 			word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
1995*9a0bf528SMauro Carvalho Chehab 			word &= 0x3;
1996*9a0bf528SMauro Carvalho Chehab 			word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
1997*9a0bf528SMauro Carvalho Chehab 			dib7000p_write_word(state, 72, word);	/* Set the proper input */
1998*9a0bf528SMauro Carvalho Chehab 			return num;
1999*9a0bf528SMauro Carvalho Chehab 		}
2000*9a0bf528SMauro Carvalho Chehab 	}
2001*9a0bf528SMauro Carvalho Chehab 
2002*9a0bf528SMauro Carvalho Chehab 	if (apb_address != 0)	/* R/W acces via APB */
2003*9a0bf528SMauro Carvalho Chehab 		return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
2004*9a0bf528SMauro Carvalho Chehab 	else			/* R/W access via SERPAR  */
2005*9a0bf528SMauro Carvalho Chehab 		return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
2006*9a0bf528SMauro Carvalho Chehab 
2007*9a0bf528SMauro Carvalho Chehab 	return 0;
2008*9a0bf528SMauro Carvalho Chehab }
2009*9a0bf528SMauro Carvalho Chehab 
2010*9a0bf528SMauro Carvalho Chehab static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
2011*9a0bf528SMauro Carvalho Chehab {
2012*9a0bf528SMauro Carvalho Chehab 	return I2C_FUNC_I2C;
2013*9a0bf528SMauro Carvalho Chehab }
2014*9a0bf528SMauro Carvalho Chehab 
2015*9a0bf528SMauro Carvalho Chehab static struct i2c_algorithm dib7090_tuner_xfer_algo = {
2016*9a0bf528SMauro Carvalho Chehab 	.master_xfer = dib7090_tuner_xfer,
2017*9a0bf528SMauro Carvalho Chehab 	.functionality = dib7000p_i2c_func,
2018*9a0bf528SMauro Carvalho Chehab };
2019*9a0bf528SMauro Carvalho Chehab 
2020*9a0bf528SMauro Carvalho Chehab struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
2021*9a0bf528SMauro Carvalho Chehab {
2022*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *st = fe->demodulator_priv;
2023*9a0bf528SMauro Carvalho Chehab 	return &st->dib7090_tuner_adap;
2024*9a0bf528SMauro Carvalho Chehab }
2025*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7090_get_i2c_tuner);
2026*9a0bf528SMauro Carvalho Chehab 
2027*9a0bf528SMauro Carvalho Chehab static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
2028*9a0bf528SMauro Carvalho Chehab {
2029*9a0bf528SMauro Carvalho Chehab 	u16 reg;
2030*9a0bf528SMauro Carvalho Chehab 
2031*9a0bf528SMauro Carvalho Chehab 	/* drive host bus 2, 3, 4 */
2032*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2033*9a0bf528SMauro Carvalho Chehab 	reg |= (drive << 12) | (drive << 6) | drive;
2034*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1798, reg);
2035*9a0bf528SMauro Carvalho Chehab 
2036*9a0bf528SMauro Carvalho Chehab 	/* drive host bus 5,6 */
2037*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
2038*9a0bf528SMauro Carvalho Chehab 	reg |= (drive << 8) | (drive << 2);
2039*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1799, reg);
2040*9a0bf528SMauro Carvalho Chehab 
2041*9a0bf528SMauro Carvalho Chehab 	/* drive host bus 7, 8, 9 */
2042*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2043*9a0bf528SMauro Carvalho Chehab 	reg |= (drive << 12) | (drive << 6) | drive;
2044*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1800, reg);
2045*9a0bf528SMauro Carvalho Chehab 
2046*9a0bf528SMauro Carvalho Chehab 	/* drive host bus 10, 11 */
2047*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
2048*9a0bf528SMauro Carvalho Chehab 	reg |= (drive << 8) | (drive << 2);
2049*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1801, reg);
2050*9a0bf528SMauro Carvalho Chehab 
2051*9a0bf528SMauro Carvalho Chehab 	/* drive host bus 12, 13, 14 */
2052*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2053*9a0bf528SMauro Carvalho Chehab 	reg |= (drive << 12) | (drive << 6) | drive;
2054*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1802, reg);
2055*9a0bf528SMauro Carvalho Chehab 
2056*9a0bf528SMauro Carvalho Chehab 	return 0;
2057*9a0bf528SMauro Carvalho Chehab }
2058*9a0bf528SMauro Carvalho Chehab 
2059*9a0bf528SMauro Carvalho Chehab static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
2060*9a0bf528SMauro Carvalho Chehab {
2061*9a0bf528SMauro Carvalho Chehab 	u32 quantif = 3;
2062*9a0bf528SMauro Carvalho Chehab 	u32 nom = (insertExtSynchro * P_Kin + syncSize);
2063*9a0bf528SMauro Carvalho Chehab 	u32 denom = P_Kout;
2064*9a0bf528SMauro Carvalho Chehab 	u32 syncFreq = ((nom << quantif) / denom);
2065*9a0bf528SMauro Carvalho Chehab 
2066*9a0bf528SMauro Carvalho Chehab 	if ((syncFreq & ((1 << quantif) - 1)) != 0)
2067*9a0bf528SMauro Carvalho Chehab 		syncFreq = (syncFreq >> quantif) + 1;
2068*9a0bf528SMauro Carvalho Chehab 	else
2069*9a0bf528SMauro Carvalho Chehab 		syncFreq = (syncFreq >> quantif);
2070*9a0bf528SMauro Carvalho Chehab 
2071*9a0bf528SMauro Carvalho Chehab 	if (syncFreq != 0)
2072*9a0bf528SMauro Carvalho Chehab 		syncFreq = syncFreq - 1;
2073*9a0bf528SMauro Carvalho Chehab 
2074*9a0bf528SMauro Carvalho Chehab 	return syncFreq;
2075*9a0bf528SMauro Carvalho Chehab }
2076*9a0bf528SMauro Carvalho Chehab 
2077*9a0bf528SMauro Carvalho Chehab static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
2078*9a0bf528SMauro Carvalho Chehab {
2079*9a0bf528SMauro Carvalho Chehab 	dprintk("Configure DibStream Tx");
2080*9a0bf528SMauro Carvalho Chehab 
2081*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1615, 1);
2082*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1603, P_Kin);
2083*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1605, P_Kout);
2084*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1606, insertExtSynchro);
2085*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1608, synchroMode);
2086*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
2087*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1610, syncWord & 0xffff);
2088*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1612, syncSize);
2089*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1615, 0);
2090*9a0bf528SMauro Carvalho Chehab 
2091*9a0bf528SMauro Carvalho Chehab 	return 0;
2092*9a0bf528SMauro Carvalho Chehab }
2093*9a0bf528SMauro Carvalho Chehab 
2094*9a0bf528SMauro Carvalho Chehab static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
2095*9a0bf528SMauro Carvalho Chehab 		u32 dataOutRate)
2096*9a0bf528SMauro Carvalho Chehab {
2097*9a0bf528SMauro Carvalho Chehab 	u32 syncFreq;
2098*9a0bf528SMauro Carvalho Chehab 
2099*9a0bf528SMauro Carvalho Chehab 	dprintk("Configure DibStream Rx");
2100*9a0bf528SMauro Carvalho Chehab 	if ((P_Kin != 0) && (P_Kout != 0)) {
2101*9a0bf528SMauro Carvalho Chehab 		syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
2102*9a0bf528SMauro Carvalho Chehab 		dib7000p_write_word(state, 1542, syncFreq);
2103*9a0bf528SMauro Carvalho Chehab 	}
2104*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1554, 1);
2105*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1536, P_Kin);
2106*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1537, P_Kout);
2107*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1539, synchroMode);
2108*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
2109*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1541, syncWord & 0xffff);
2110*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1543, syncSize);
2111*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1544, dataOutRate);
2112*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1554, 0);
2113*9a0bf528SMauro Carvalho Chehab 
2114*9a0bf528SMauro Carvalho Chehab 	return 0;
2115*9a0bf528SMauro Carvalho Chehab }
2116*9a0bf528SMauro Carvalho Chehab 
2117*9a0bf528SMauro Carvalho Chehab static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
2118*9a0bf528SMauro Carvalho Chehab {
2119*9a0bf528SMauro Carvalho Chehab 	u16 reg_1287 = dib7000p_read_word(state, 1287);
2120*9a0bf528SMauro Carvalho Chehab 
2121*9a0bf528SMauro Carvalho Chehab 	switch (onoff) {
2122*9a0bf528SMauro Carvalho Chehab 	case 1:
2123*9a0bf528SMauro Carvalho Chehab 			reg_1287 &= ~(1<<7);
2124*9a0bf528SMauro Carvalho Chehab 			break;
2125*9a0bf528SMauro Carvalho Chehab 	case 0:
2126*9a0bf528SMauro Carvalho Chehab 			reg_1287 |= (1<<7);
2127*9a0bf528SMauro Carvalho Chehab 			break;
2128*9a0bf528SMauro Carvalho Chehab 	}
2129*9a0bf528SMauro Carvalho Chehab 
2130*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1287, reg_1287);
2131*9a0bf528SMauro Carvalho Chehab }
2132*9a0bf528SMauro Carvalho Chehab 
2133*9a0bf528SMauro Carvalho Chehab static void dib7090_configMpegMux(struct dib7000p_state *state,
2134*9a0bf528SMauro Carvalho Chehab 		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
2135*9a0bf528SMauro Carvalho Chehab {
2136*9a0bf528SMauro Carvalho Chehab 	dprintk("Enable Mpeg mux");
2137*9a0bf528SMauro Carvalho Chehab 
2138*9a0bf528SMauro Carvalho Chehab 	dib7090_enMpegMux(state, 0);
2139*9a0bf528SMauro Carvalho Chehab 
2140*9a0bf528SMauro Carvalho Chehab 	/* If the input mode is MPEG do not divide the serial clock */
2141*9a0bf528SMauro Carvalho Chehab 	if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
2142*9a0bf528SMauro Carvalho Chehab 		enSerialClkDiv2 = 0;
2143*9a0bf528SMauro Carvalho Chehab 
2144*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
2145*9a0bf528SMauro Carvalho Chehab 			| ((enSerialMode & 0x1) << 1)
2146*9a0bf528SMauro Carvalho Chehab 			| (enSerialClkDiv2 & 0x1));
2147*9a0bf528SMauro Carvalho Chehab 
2148*9a0bf528SMauro Carvalho Chehab 	dib7090_enMpegMux(state, 1);
2149*9a0bf528SMauro Carvalho Chehab }
2150*9a0bf528SMauro Carvalho Chehab 
2151*9a0bf528SMauro Carvalho Chehab static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
2152*9a0bf528SMauro Carvalho Chehab {
2153*9a0bf528SMauro Carvalho Chehab 	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
2154*9a0bf528SMauro Carvalho Chehab 
2155*9a0bf528SMauro Carvalho Chehab 	switch (mode) {
2156*9a0bf528SMauro Carvalho Chehab 	case MPEG_ON_DIBTX:
2157*9a0bf528SMauro Carvalho Chehab 			dprintk("SET MPEG ON DIBSTREAM TX");
2158*9a0bf528SMauro Carvalho Chehab 			dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
2159*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<9);
2160*9a0bf528SMauro Carvalho Chehab 			break;
2161*9a0bf528SMauro Carvalho Chehab 	case DIV_ON_DIBTX:
2162*9a0bf528SMauro Carvalho Chehab 			dprintk("SET DIV_OUT ON DIBSTREAM TX");
2163*9a0bf528SMauro Carvalho Chehab 			dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
2164*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<8);
2165*9a0bf528SMauro Carvalho Chehab 			break;
2166*9a0bf528SMauro Carvalho Chehab 	case ADC_ON_DIBTX:
2167*9a0bf528SMauro Carvalho Chehab 			dprintk("SET ADC_OUT ON DIBSTREAM TX");
2168*9a0bf528SMauro Carvalho Chehab 			dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
2169*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<7);
2170*9a0bf528SMauro Carvalho Chehab 			break;
2171*9a0bf528SMauro Carvalho Chehab 	default:
2172*9a0bf528SMauro Carvalho Chehab 			break;
2173*9a0bf528SMauro Carvalho Chehab 	}
2174*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1288, reg_1288);
2175*9a0bf528SMauro Carvalho Chehab }
2176*9a0bf528SMauro Carvalho Chehab 
2177*9a0bf528SMauro Carvalho Chehab static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
2178*9a0bf528SMauro Carvalho Chehab {
2179*9a0bf528SMauro Carvalho Chehab 	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
2180*9a0bf528SMauro Carvalho Chehab 
2181*9a0bf528SMauro Carvalho Chehab 	switch (mode) {
2182*9a0bf528SMauro Carvalho Chehab 	case DEMOUT_ON_HOSTBUS:
2183*9a0bf528SMauro Carvalho Chehab 			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
2184*9a0bf528SMauro Carvalho Chehab 			dib7090_enMpegMux(state, 0);
2185*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<6);
2186*9a0bf528SMauro Carvalho Chehab 			break;
2187*9a0bf528SMauro Carvalho Chehab 	case DIBTX_ON_HOSTBUS:
2188*9a0bf528SMauro Carvalho Chehab 			dprintk("SET DIBSTREAM TX ON HOST BUS");
2189*9a0bf528SMauro Carvalho Chehab 			dib7090_enMpegMux(state, 0);
2190*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<5);
2191*9a0bf528SMauro Carvalho Chehab 			break;
2192*9a0bf528SMauro Carvalho Chehab 	case MPEG_ON_HOSTBUS:
2193*9a0bf528SMauro Carvalho Chehab 			dprintk("SET MPEG MUX ON HOST BUS");
2194*9a0bf528SMauro Carvalho Chehab 			reg_1288 |= (1<<4);
2195*9a0bf528SMauro Carvalho Chehab 			break;
2196*9a0bf528SMauro Carvalho Chehab 	default:
2197*9a0bf528SMauro Carvalho Chehab 			break;
2198*9a0bf528SMauro Carvalho Chehab 	}
2199*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1288, reg_1288);
2200*9a0bf528SMauro Carvalho Chehab }
2201*9a0bf528SMauro Carvalho Chehab 
2202*9a0bf528SMauro Carvalho Chehab int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
2203*9a0bf528SMauro Carvalho Chehab {
2204*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
2205*9a0bf528SMauro Carvalho Chehab 	u16 reg_1287;
2206*9a0bf528SMauro Carvalho Chehab 
2207*9a0bf528SMauro Carvalho Chehab 	switch (onoff) {
2208*9a0bf528SMauro Carvalho Chehab 	case 0: /* only use the internal way - not the diversity input */
2209*9a0bf528SMauro Carvalho Chehab 			dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
2210*9a0bf528SMauro Carvalho Chehab 			dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
2211*9a0bf528SMauro Carvalho Chehab 
2212*9a0bf528SMauro Carvalho Chehab 			/* Do not divide the serial clock of MPEG MUX */
2213*9a0bf528SMauro Carvalho Chehab 			/* in SERIAL MODE in case input mode MPEG is used */
2214*9a0bf528SMauro Carvalho Chehab 			reg_1287 = dib7000p_read_word(state, 1287);
2215*9a0bf528SMauro Carvalho Chehab 			/* enSerialClkDiv2 == 1 ? */
2216*9a0bf528SMauro Carvalho Chehab 			if ((reg_1287 & 0x1) == 1) {
2217*9a0bf528SMauro Carvalho Chehab 				/* force enSerialClkDiv2 = 0 */
2218*9a0bf528SMauro Carvalho Chehab 				reg_1287 &= ~0x1;
2219*9a0bf528SMauro Carvalho Chehab 				dib7000p_write_word(state, 1287, reg_1287);
2220*9a0bf528SMauro Carvalho Chehab 			}
2221*9a0bf528SMauro Carvalho Chehab 			state->input_mode_mpeg = 1;
2222*9a0bf528SMauro Carvalho Chehab 			break;
2223*9a0bf528SMauro Carvalho Chehab 	case 1: /* both ways */
2224*9a0bf528SMauro Carvalho Chehab 	case 2: /* only the diversity input */
2225*9a0bf528SMauro Carvalho Chehab 			dprintk("%s ON : Enable diversity INPUT", __func__);
2226*9a0bf528SMauro Carvalho Chehab 			dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
2227*9a0bf528SMauro Carvalho Chehab 			state->input_mode_mpeg = 0;
2228*9a0bf528SMauro Carvalho Chehab 			break;
2229*9a0bf528SMauro Carvalho Chehab 	}
2230*9a0bf528SMauro Carvalho Chehab 
2231*9a0bf528SMauro Carvalho Chehab 	dib7000p_set_diversity_in(&state->demod, onoff);
2232*9a0bf528SMauro Carvalho Chehab 	return 0;
2233*9a0bf528SMauro Carvalho Chehab }
2234*9a0bf528SMauro Carvalho Chehab 
2235*9a0bf528SMauro Carvalho Chehab static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
2236*9a0bf528SMauro Carvalho Chehab {
2237*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
2238*9a0bf528SMauro Carvalho Chehab 
2239*9a0bf528SMauro Carvalho Chehab 	u16 outreg, smo_mode, fifo_threshold;
2240*9a0bf528SMauro Carvalho Chehab 	u8 prefer_mpeg_mux_use = 1;
2241*9a0bf528SMauro Carvalho Chehab 	int ret = 0;
2242*9a0bf528SMauro Carvalho Chehab 
2243*9a0bf528SMauro Carvalho Chehab 	dib7090_host_bus_drive(state, 1);
2244*9a0bf528SMauro Carvalho Chehab 
2245*9a0bf528SMauro Carvalho Chehab 	fifo_threshold = 1792;
2246*9a0bf528SMauro Carvalho Chehab 	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
2247*9a0bf528SMauro Carvalho Chehab 	outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
2248*9a0bf528SMauro Carvalho Chehab 
2249*9a0bf528SMauro Carvalho Chehab 	switch (mode) {
2250*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_HIGH_Z:
2251*9a0bf528SMauro Carvalho Chehab 		outreg = 0;
2252*9a0bf528SMauro Carvalho Chehab 		break;
2253*9a0bf528SMauro Carvalho Chehab 
2254*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_SERIAL:
2255*9a0bf528SMauro Carvalho Chehab 		if (prefer_mpeg_mux_use) {
2256*9a0bf528SMauro Carvalho Chehab 			dprintk("setting output mode TS_SERIAL using Mpeg Mux");
2257*9a0bf528SMauro Carvalho Chehab 			dib7090_configMpegMux(state, 3, 1, 1);
2258*9a0bf528SMauro Carvalho Chehab 			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2259*9a0bf528SMauro Carvalho Chehab 		} else {/* Use Smooth block */
2260*9a0bf528SMauro Carvalho Chehab 			dprintk("setting output mode TS_SERIAL using Smooth bloc");
2261*9a0bf528SMauro Carvalho Chehab 			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2262*9a0bf528SMauro Carvalho Chehab 			outreg |= (2<<6) | (0 << 1);
2263*9a0bf528SMauro Carvalho Chehab 		}
2264*9a0bf528SMauro Carvalho Chehab 		break;
2265*9a0bf528SMauro Carvalho Chehab 
2266*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_PAR_GATED_CLK:
2267*9a0bf528SMauro Carvalho Chehab 		if (prefer_mpeg_mux_use) {
2268*9a0bf528SMauro Carvalho Chehab 			dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
2269*9a0bf528SMauro Carvalho Chehab 			dib7090_configMpegMux(state, 2, 0, 0);
2270*9a0bf528SMauro Carvalho Chehab 			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2271*9a0bf528SMauro Carvalho Chehab 		} else { /* Use Smooth block */
2272*9a0bf528SMauro Carvalho Chehab 			dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
2273*9a0bf528SMauro Carvalho Chehab 			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2274*9a0bf528SMauro Carvalho Chehab 			outreg |= (0<<6);
2275*9a0bf528SMauro Carvalho Chehab 		}
2276*9a0bf528SMauro Carvalho Chehab 		break;
2277*9a0bf528SMauro Carvalho Chehab 
2278*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_PAR_CONT_CLK:	/* Using Smooth block only */
2279*9a0bf528SMauro Carvalho Chehab 		dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
2280*9a0bf528SMauro Carvalho Chehab 		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2281*9a0bf528SMauro Carvalho Chehab 		outreg |= (1<<6);
2282*9a0bf528SMauro Carvalho Chehab 		break;
2283*9a0bf528SMauro Carvalho Chehab 
2284*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_MPEG2_FIFO:	/* Using Smooth block because not supported by new Mpeg Mux bloc */
2285*9a0bf528SMauro Carvalho Chehab 		dprintk("setting output mode TS_FIFO using Smooth block");
2286*9a0bf528SMauro Carvalho Chehab 		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2287*9a0bf528SMauro Carvalho Chehab 		outreg |= (5<<6);
2288*9a0bf528SMauro Carvalho Chehab 		smo_mode |= (3 << 1);
2289*9a0bf528SMauro Carvalho Chehab 		fifo_threshold = 512;
2290*9a0bf528SMauro Carvalho Chehab 		break;
2291*9a0bf528SMauro Carvalho Chehab 
2292*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_DIVERSITY:
2293*9a0bf528SMauro Carvalho Chehab 		dprintk("setting output mode MODE_DIVERSITY");
2294*9a0bf528SMauro Carvalho Chehab 		dib7090_setDibTxMux(state, DIV_ON_DIBTX);
2295*9a0bf528SMauro Carvalho Chehab 		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
2296*9a0bf528SMauro Carvalho Chehab 		break;
2297*9a0bf528SMauro Carvalho Chehab 
2298*9a0bf528SMauro Carvalho Chehab 	case OUTMODE_ANALOG_ADC:
2299*9a0bf528SMauro Carvalho Chehab 		dprintk("setting output mode MODE_ANALOG_ADC");
2300*9a0bf528SMauro Carvalho Chehab 		dib7090_setDibTxMux(state, ADC_ON_DIBTX);
2301*9a0bf528SMauro Carvalho Chehab 		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
2302*9a0bf528SMauro Carvalho Chehab 		break;
2303*9a0bf528SMauro Carvalho Chehab 	}
2304*9a0bf528SMauro Carvalho Chehab 	if (mode != OUTMODE_HIGH_Z)
2305*9a0bf528SMauro Carvalho Chehab 		outreg |= (1 << 10);
2306*9a0bf528SMauro Carvalho Chehab 
2307*9a0bf528SMauro Carvalho Chehab 	if (state->cfg.output_mpeg2_in_188_bytes)
2308*9a0bf528SMauro Carvalho Chehab 		smo_mode |= (1 << 5);
2309*9a0bf528SMauro Carvalho Chehab 
2310*9a0bf528SMauro Carvalho Chehab 	ret |= dib7000p_write_word(state, 235, smo_mode);
2311*9a0bf528SMauro Carvalho Chehab 	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
2312*9a0bf528SMauro Carvalho Chehab 	ret |= dib7000p_write_word(state, 1286, outreg);
2313*9a0bf528SMauro Carvalho Chehab 
2314*9a0bf528SMauro Carvalho Chehab 	return ret;
2315*9a0bf528SMauro Carvalho Chehab }
2316*9a0bf528SMauro Carvalho Chehab 
2317*9a0bf528SMauro Carvalho Chehab int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
2318*9a0bf528SMauro Carvalho Chehab {
2319*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
2320*9a0bf528SMauro Carvalho Chehab 	u16 en_cur_state;
2321*9a0bf528SMauro Carvalho Chehab 
2322*9a0bf528SMauro Carvalho Chehab 	dprintk("sleep dib7090: %d", onoff);
2323*9a0bf528SMauro Carvalho Chehab 
2324*9a0bf528SMauro Carvalho Chehab 	en_cur_state = dib7000p_read_word(state, 1922);
2325*9a0bf528SMauro Carvalho Chehab 
2326*9a0bf528SMauro Carvalho Chehab 	if (en_cur_state > 0xff)
2327*9a0bf528SMauro Carvalho Chehab 		state->tuner_enable = en_cur_state;
2328*9a0bf528SMauro Carvalho Chehab 
2329*9a0bf528SMauro Carvalho Chehab 	if (onoff)
2330*9a0bf528SMauro Carvalho Chehab 		en_cur_state &= 0x00ff;
2331*9a0bf528SMauro Carvalho Chehab 	else {
2332*9a0bf528SMauro Carvalho Chehab 		if (state->tuner_enable != 0)
2333*9a0bf528SMauro Carvalho Chehab 			en_cur_state = state->tuner_enable;
2334*9a0bf528SMauro Carvalho Chehab 	}
2335*9a0bf528SMauro Carvalho Chehab 
2336*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1922, en_cur_state);
2337*9a0bf528SMauro Carvalho Chehab 
2338*9a0bf528SMauro Carvalho Chehab 	return 0;
2339*9a0bf528SMauro Carvalho Chehab }
2340*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7090_tuner_sleep);
2341*9a0bf528SMauro Carvalho Chehab 
2342*9a0bf528SMauro Carvalho Chehab int dib7090_get_adc_power(struct dvb_frontend *fe)
2343*9a0bf528SMauro Carvalho Chehab {
2344*9a0bf528SMauro Carvalho Chehab 	return dib7000p_get_adc_power(fe);
2345*9a0bf528SMauro Carvalho Chehab }
2346*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7090_get_adc_power);
2347*9a0bf528SMauro Carvalho Chehab 
2348*9a0bf528SMauro Carvalho Chehab int dib7090_slave_reset(struct dvb_frontend *fe)
2349*9a0bf528SMauro Carvalho Chehab {
2350*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *state = fe->demodulator_priv;
2351*9a0bf528SMauro Carvalho Chehab 	u16 reg;
2352*9a0bf528SMauro Carvalho Chehab 
2353*9a0bf528SMauro Carvalho Chehab 	reg = dib7000p_read_word(state, 1794);
2354*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1794, reg | (4 << 12));
2355*9a0bf528SMauro Carvalho Chehab 
2356*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(state, 1032, 0xffff);
2357*9a0bf528SMauro Carvalho Chehab 	return 0;
2358*9a0bf528SMauro Carvalho Chehab }
2359*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7090_slave_reset);
2360*9a0bf528SMauro Carvalho Chehab 
2361*9a0bf528SMauro Carvalho Chehab static struct dvb_frontend_ops dib7000p_ops;
2362*9a0bf528SMauro Carvalho Chehab struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
2363*9a0bf528SMauro Carvalho Chehab {
2364*9a0bf528SMauro Carvalho Chehab 	struct dvb_frontend *demod;
2365*9a0bf528SMauro Carvalho Chehab 	struct dib7000p_state *st;
2366*9a0bf528SMauro Carvalho Chehab 	st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
2367*9a0bf528SMauro Carvalho Chehab 	if (st == NULL)
2368*9a0bf528SMauro Carvalho Chehab 		return NULL;
2369*9a0bf528SMauro Carvalho Chehab 
2370*9a0bf528SMauro Carvalho Chehab 	memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
2371*9a0bf528SMauro Carvalho Chehab 	st->i2c_adap = i2c_adap;
2372*9a0bf528SMauro Carvalho Chehab 	st->i2c_addr = i2c_addr;
2373*9a0bf528SMauro Carvalho Chehab 	st->gpio_val = cfg->gpio_val;
2374*9a0bf528SMauro Carvalho Chehab 	st->gpio_dir = cfg->gpio_dir;
2375*9a0bf528SMauro Carvalho Chehab 
2376*9a0bf528SMauro Carvalho Chehab 	/* Ensure the output mode remains at the previous default if it's
2377*9a0bf528SMauro Carvalho Chehab 	 * not specifically set by the caller.
2378*9a0bf528SMauro Carvalho Chehab 	 */
2379*9a0bf528SMauro Carvalho Chehab 	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
2380*9a0bf528SMauro Carvalho Chehab 		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
2381*9a0bf528SMauro Carvalho Chehab 
2382*9a0bf528SMauro Carvalho Chehab 	demod = &st->demod;
2383*9a0bf528SMauro Carvalho Chehab 	demod->demodulator_priv = st;
2384*9a0bf528SMauro Carvalho Chehab 	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
2385*9a0bf528SMauro Carvalho Chehab 	mutex_init(&st->i2c_buffer_lock);
2386*9a0bf528SMauro Carvalho Chehab 
2387*9a0bf528SMauro Carvalho Chehab 	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
2388*9a0bf528SMauro Carvalho Chehab 
2389*9a0bf528SMauro Carvalho Chehab 	if (dib7000p_identify(st) != 0)
2390*9a0bf528SMauro Carvalho Chehab 		goto error;
2391*9a0bf528SMauro Carvalho Chehab 
2392*9a0bf528SMauro Carvalho Chehab 	st->version = dib7000p_read_word(st, 897);
2393*9a0bf528SMauro Carvalho Chehab 
2394*9a0bf528SMauro Carvalho Chehab 	/* FIXME: make sure the dev.parent field is initialized, or else
2395*9a0bf528SMauro Carvalho Chehab 	   request_firmware() will hit an OOPS (this should be moved somewhere
2396*9a0bf528SMauro Carvalho Chehab 	   more common) */
2397*9a0bf528SMauro Carvalho Chehab 	st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
2398*9a0bf528SMauro Carvalho Chehab 
2399*9a0bf528SMauro Carvalho Chehab 	dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
2400*9a0bf528SMauro Carvalho Chehab 
2401*9a0bf528SMauro Carvalho Chehab 	/* init 7090 tuner adapter */
2402*9a0bf528SMauro Carvalho Chehab 	strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
2403*9a0bf528SMauro Carvalho Chehab 	st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
2404*9a0bf528SMauro Carvalho Chehab 	st->dib7090_tuner_adap.algo_data = NULL;
2405*9a0bf528SMauro Carvalho Chehab 	st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
2406*9a0bf528SMauro Carvalho Chehab 	i2c_set_adapdata(&st->dib7090_tuner_adap, st);
2407*9a0bf528SMauro Carvalho Chehab 	i2c_add_adapter(&st->dib7090_tuner_adap);
2408*9a0bf528SMauro Carvalho Chehab 
2409*9a0bf528SMauro Carvalho Chehab 	dib7000p_demod_reset(st);
2410*9a0bf528SMauro Carvalho Chehab 
2411*9a0bf528SMauro Carvalho Chehab 	if (st->version == SOC7090) {
2412*9a0bf528SMauro Carvalho Chehab 		dib7090_set_output_mode(demod, st->cfg.output_mode);
2413*9a0bf528SMauro Carvalho Chehab 		dib7090_set_diversity_in(demod, 0);
2414*9a0bf528SMauro Carvalho Chehab 	}
2415*9a0bf528SMauro Carvalho Chehab 
2416*9a0bf528SMauro Carvalho Chehab 	return demod;
2417*9a0bf528SMauro Carvalho Chehab 
2418*9a0bf528SMauro Carvalho Chehab error:
2419*9a0bf528SMauro Carvalho Chehab 	kfree(st);
2420*9a0bf528SMauro Carvalho Chehab 	return NULL;
2421*9a0bf528SMauro Carvalho Chehab }
2422*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000p_attach);
2423*9a0bf528SMauro Carvalho Chehab 
2424*9a0bf528SMauro Carvalho Chehab static struct dvb_frontend_ops dib7000p_ops = {
2425*9a0bf528SMauro Carvalho Chehab 	.delsys = { SYS_DVBT },
2426*9a0bf528SMauro Carvalho Chehab 	.info = {
2427*9a0bf528SMauro Carvalho Chehab 		 .name = "DiBcom 7000PC",
2428*9a0bf528SMauro Carvalho Chehab 		 .frequency_min = 44250000,
2429*9a0bf528SMauro Carvalho Chehab 		 .frequency_max = 867250000,
2430*9a0bf528SMauro Carvalho Chehab 		 .frequency_stepsize = 62500,
2431*9a0bf528SMauro Carvalho Chehab 		 .caps = FE_CAN_INVERSION_AUTO |
2432*9a0bf528SMauro Carvalho Chehab 		 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2433*9a0bf528SMauro Carvalho Chehab 		 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2434*9a0bf528SMauro Carvalho Chehab 		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2435*9a0bf528SMauro Carvalho Chehab 		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2436*9a0bf528SMauro Carvalho Chehab 		 },
2437*9a0bf528SMauro Carvalho Chehab 
2438*9a0bf528SMauro Carvalho Chehab 	.release = dib7000p_release,
2439*9a0bf528SMauro Carvalho Chehab 
2440*9a0bf528SMauro Carvalho Chehab 	.init = dib7000p_wakeup,
2441*9a0bf528SMauro Carvalho Chehab 	.sleep = dib7000p_sleep,
2442*9a0bf528SMauro Carvalho Chehab 
2443*9a0bf528SMauro Carvalho Chehab 	.set_frontend = dib7000p_set_frontend,
2444*9a0bf528SMauro Carvalho Chehab 	.get_tune_settings = dib7000p_fe_get_tune_settings,
2445*9a0bf528SMauro Carvalho Chehab 	.get_frontend = dib7000p_get_frontend,
2446*9a0bf528SMauro Carvalho Chehab 
2447*9a0bf528SMauro Carvalho Chehab 	.read_status = dib7000p_read_status,
2448*9a0bf528SMauro Carvalho Chehab 	.read_ber = dib7000p_read_ber,
2449*9a0bf528SMauro Carvalho Chehab 	.read_signal_strength = dib7000p_read_signal_strength,
2450*9a0bf528SMauro Carvalho Chehab 	.read_snr = dib7000p_read_snr,
2451*9a0bf528SMauro Carvalho Chehab 	.read_ucblocks = dib7000p_read_unc_blocks,
2452*9a0bf528SMauro Carvalho Chehab };
2453*9a0bf528SMauro Carvalho Chehab 
2454*9a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
2455*9a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2456*9a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
2457*9a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL");
2458