xref: /OK3568_Linux_fs/kernel/drivers/media/dvb-frontends/l64781.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun     driver for LSI L64781 COFDM demodulator
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun     Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
6*4882a593Smuzhiyun 		       Marko Kohtala <marko.kohtala@luukku.com>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/string.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <media/dvb_frontend.h>
17*4882a593Smuzhiyun #include "l64781.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun struct l64781_state {
21*4882a593Smuzhiyun 	struct i2c_adapter* i2c;
22*4882a593Smuzhiyun 	const struct l64781_config* config;
23*4882a593Smuzhiyun 	struct dvb_frontend frontend;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	/* private demodulator data */
26*4882a593Smuzhiyun 	unsigned int first:1;
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define dprintk(args...) \
30*4882a593Smuzhiyun 	do { \
31*4882a593Smuzhiyun 		if (debug) printk(KERN_DEBUG "l64781: " args); \
32*4882a593Smuzhiyun 	} while (0)
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun static int debug;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun module_param(debug, int, 0644);
37*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 
l64781_writereg(struct l64781_state * state,u8 reg,u8 data)40*4882a593Smuzhiyun static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	int ret;
43*4882a593Smuzhiyun 	u8 buf [] = { reg, data };
44*4882a593Smuzhiyun 	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
47*4882a593Smuzhiyun 		dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
48*4882a593Smuzhiyun 			 __func__, reg, ret);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return (ret != 1) ? -1 : 0;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
l64781_readreg(struct l64781_state * state,u8 reg)53*4882a593Smuzhiyun static int l64781_readreg (struct l64781_state* state, u8 reg)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	int ret;
56*4882a593Smuzhiyun 	u8 b0 [] = { reg };
57*4882a593Smuzhiyun 	u8 b1 [] = { 0 };
58*4882a593Smuzhiyun 	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
59*4882a593Smuzhiyun 			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	ret = i2c_transfer(state->i2c, msg, 2);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (ret != 2) return ret;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return b1[0];
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
apply_tps(struct l64781_state * state)68*4882a593Smuzhiyun static void apply_tps (struct l64781_state* state)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	l64781_writereg (state, 0x2a, 0x00);
71*4882a593Smuzhiyun 	l64781_writereg (state, 0x2a, 0x01);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* This here is a little bit questionable because it enables
74*4882a593Smuzhiyun 	   the automatic update of TPS registers. I think we'd need to
75*4882a593Smuzhiyun 	   handle the IRQ from FE to update some other registers as
76*4882a593Smuzhiyun 	   well, or at least implement some magic to tuning to correct
77*4882a593Smuzhiyun 	   to the TPS received from transmission. */
78*4882a593Smuzhiyun 	l64781_writereg (state, 0x2a, 0x02);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 
reset_afc(struct l64781_state * state)82*4882a593Smuzhiyun static void reset_afc (struct l64781_state* state)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	/* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for
85*4882a593Smuzhiyun 	   timing offset */
86*4882a593Smuzhiyun 	l64781_writereg (state, 0x07, 0x9e); /* stall AFC */
87*4882a593Smuzhiyun 	l64781_writereg (state, 0x08, 0);    /* AFC INIT FREQ */
88*4882a593Smuzhiyun 	l64781_writereg (state, 0x09, 0);
89*4882a593Smuzhiyun 	l64781_writereg (state, 0x0a, 0);
90*4882a593Smuzhiyun 	l64781_writereg (state, 0x07, 0x8e);
91*4882a593Smuzhiyun 	l64781_writereg (state, 0x0e, 0);    /* AGC gain to zero in beginning */
92*4882a593Smuzhiyun 	l64781_writereg (state, 0x11, 0x80); /* stall TIM */
93*4882a593Smuzhiyun 	l64781_writereg (state, 0x10, 0);    /* TIM_OFFSET_LSB */
94*4882a593Smuzhiyun 	l64781_writereg (state, 0x12, 0);
95*4882a593Smuzhiyun 	l64781_writereg (state, 0x13, 0);
96*4882a593Smuzhiyun 	l64781_writereg (state, 0x11, 0x00);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
reset_and_configure(struct l64781_state * state)99*4882a593Smuzhiyun static int reset_and_configure (struct l64781_state* state)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	u8 buf [] = { 0x06 };
102*4882a593Smuzhiyun 	struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
103*4882a593Smuzhiyun 	// NOTE: this is correct in writing to address 0x00
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
apply_frontend_param(struct dvb_frontend * fe)108*4882a593Smuzhiyun static int apply_frontend_param(struct dvb_frontend *fe)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
111*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
112*4882a593Smuzhiyun 	/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
113*4882a593Smuzhiyun 	static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
114*4882a593Smuzhiyun 	/* QPSK, QAM_16, QAM_64 */
115*4882a593Smuzhiyun 	static const u8 qam_tab [] = { 2, 4, 0, 6 };
116*4882a593Smuzhiyun 	static const u8 guard_tab [] = { 1, 2, 4, 8 };
117*4882a593Smuzhiyun 	/* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
118*4882a593Smuzhiyun 	static const u32 ppm = 8000;
119*4882a593Smuzhiyun 	u32 ddfs_offset_fixed;
120*4882a593Smuzhiyun /*	u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
121*4882a593Smuzhiyun /*			bw_tab[p->bandWidth]<<10)/15625; */
122*4882a593Smuzhiyun 	u32 init_freq;
123*4882a593Smuzhiyun 	u32 spi_bias;
124*4882a593Smuzhiyun 	u8 val0x04;
125*4882a593Smuzhiyun 	u8 val0x05;
126*4882a593Smuzhiyun 	u8 val0x06;
127*4882a593Smuzhiyun 	int bw;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	switch (p->bandwidth_hz) {
130*4882a593Smuzhiyun 	case 8000000:
131*4882a593Smuzhiyun 		bw = 8;
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun 	case 7000000:
134*4882a593Smuzhiyun 		bw = 7;
135*4882a593Smuzhiyun 		break;
136*4882a593Smuzhiyun 	case 6000000:
137*4882a593Smuzhiyun 		bw = 6;
138*4882a593Smuzhiyun 		break;
139*4882a593Smuzhiyun 	default:
140*4882a593Smuzhiyun 		return -EINVAL;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.set_params) {
144*4882a593Smuzhiyun 		fe->ops.tuner_ops.set_params(fe);
145*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (p->inversion != INVERSION_ON &&
149*4882a593Smuzhiyun 	    p->inversion != INVERSION_OFF)
150*4882a593Smuzhiyun 		return -EINVAL;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
153*4882a593Smuzhiyun 	    p->code_rate_HP != FEC_3_4 && p->code_rate_HP != FEC_5_6 &&
154*4882a593Smuzhiyun 	    p->code_rate_HP != FEC_7_8)
155*4882a593Smuzhiyun 		return -EINVAL;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (p->hierarchy != HIERARCHY_NONE &&
158*4882a593Smuzhiyun 	    (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
159*4882a593Smuzhiyun 	     p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
160*4882a593Smuzhiyun 	     p->code_rate_LP != FEC_7_8))
161*4882a593Smuzhiyun 		return -EINVAL;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	if (p->modulation != QPSK && p->modulation != QAM_16 &&
164*4882a593Smuzhiyun 	    p->modulation != QAM_64)
165*4882a593Smuzhiyun 		return -EINVAL;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
168*4882a593Smuzhiyun 	    p->transmission_mode != TRANSMISSION_MODE_8K)
169*4882a593Smuzhiyun 		return -EINVAL;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
172*4882a593Smuzhiyun 	    p->guard_interval > GUARD_INTERVAL_1_4)
173*4882a593Smuzhiyun 		return -EINVAL;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if ((int)p->hierarchy < HIERARCHY_NONE ||
176*4882a593Smuzhiyun 	    p->hierarchy > HIERARCHY_4)
177*4882a593Smuzhiyun 		return -EINVAL;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	/* This works up to 20000 ppm, it overflows if too large ppm! */
182*4882a593Smuzhiyun 	init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
183*4882a593Smuzhiyun 			bw & 0xFFFFFF);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* SPI bias calculation is slightly modified to fit in 32bit */
186*4882a593Smuzhiyun 	/* will work for high ppm only... */
187*4882a593Smuzhiyun 	spi_bias = 378 * (1 << 10);
188*4882a593Smuzhiyun 	spi_bias *= 16;
189*4882a593Smuzhiyun 	spi_bias *= bw;
190*4882a593Smuzhiyun 	spi_bias *= qam_tab[p->modulation];
191*4882a593Smuzhiyun 	spi_bias /= p->code_rate_HP + 1;
192*4882a593Smuzhiyun 	spi_bias /= (guard_tab[p->guard_interval] + 32);
193*4882a593Smuzhiyun 	spi_bias *= 1000;
194*4882a593Smuzhiyun 	spi_bias /= 1000 + ppm/1000;
195*4882a593Smuzhiyun 	spi_bias *= p->code_rate_HP;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	val0x04 = (p->transmission_mode << 2) | p->guard_interval;
198*4882a593Smuzhiyun 	val0x05 = fec_tab[p->code_rate_HP];
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (p->hierarchy != HIERARCHY_NONE)
201*4882a593Smuzhiyun 		val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	val0x06 = (p->hierarchy << 2) | p->modulation;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	l64781_writereg (state, 0x04, val0x04);
206*4882a593Smuzhiyun 	l64781_writereg (state, 0x05, val0x05);
207*4882a593Smuzhiyun 	l64781_writereg (state, 0x06, val0x06);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	reset_afc (state);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */
212*4882a593Smuzhiyun 	l64781_writereg (state, 0x15,
213*4882a593Smuzhiyun 			 p->transmission_mode == TRANSMISSION_MODE_2K ? 1 : 3);
214*4882a593Smuzhiyun 	l64781_writereg (state, 0x16, init_freq & 0xff);
215*4882a593Smuzhiyun 	l64781_writereg (state, 0x17, (init_freq >> 8) & 0xff);
216*4882a593Smuzhiyun 	l64781_writereg (state, 0x18, (init_freq >> 16) & 0xff);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	l64781_writereg (state, 0x1b, spi_bias & 0xff);
219*4882a593Smuzhiyun 	l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
220*4882a593Smuzhiyun 	l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
221*4882a593Smuzhiyun 		(p->inversion == INVERSION_ON ? 0x80 : 0x00));
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
224*4882a593Smuzhiyun 	l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
227*4882a593Smuzhiyun 	l64781_readreg (state, 0x01);  /*  dto. */
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	apply_tps (state);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
get_frontend(struct dvb_frontend * fe,struct dtv_frontend_properties * p)234*4882a593Smuzhiyun static int get_frontend(struct dvb_frontend *fe,
235*4882a593Smuzhiyun 			struct dtv_frontend_properties *p)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
238*4882a593Smuzhiyun 	int tmp;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	tmp = l64781_readreg(state, 0x04);
242*4882a593Smuzhiyun 	switch(tmp & 3) {
243*4882a593Smuzhiyun 	case 0:
244*4882a593Smuzhiyun 		p->guard_interval = GUARD_INTERVAL_1_32;
245*4882a593Smuzhiyun 		break;
246*4882a593Smuzhiyun 	case 1:
247*4882a593Smuzhiyun 		p->guard_interval = GUARD_INTERVAL_1_16;
248*4882a593Smuzhiyun 		break;
249*4882a593Smuzhiyun 	case 2:
250*4882a593Smuzhiyun 		p->guard_interval = GUARD_INTERVAL_1_8;
251*4882a593Smuzhiyun 		break;
252*4882a593Smuzhiyun 	case 3:
253*4882a593Smuzhiyun 		p->guard_interval = GUARD_INTERVAL_1_4;
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	switch((tmp >> 2) & 3) {
257*4882a593Smuzhiyun 	case 0:
258*4882a593Smuzhiyun 		p->transmission_mode = TRANSMISSION_MODE_2K;
259*4882a593Smuzhiyun 		break;
260*4882a593Smuzhiyun 	case 1:
261*4882a593Smuzhiyun 		p->transmission_mode = TRANSMISSION_MODE_8K;
262*4882a593Smuzhiyun 		break;
263*4882a593Smuzhiyun 	default:
264*4882a593Smuzhiyun 		printk(KERN_WARNING "Unexpected value for transmission_mode\n");
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	tmp = l64781_readreg(state, 0x05);
268*4882a593Smuzhiyun 	switch(tmp & 7) {
269*4882a593Smuzhiyun 	case 0:
270*4882a593Smuzhiyun 		p->code_rate_HP = FEC_1_2;
271*4882a593Smuzhiyun 		break;
272*4882a593Smuzhiyun 	case 1:
273*4882a593Smuzhiyun 		p->code_rate_HP = FEC_2_3;
274*4882a593Smuzhiyun 		break;
275*4882a593Smuzhiyun 	case 2:
276*4882a593Smuzhiyun 		p->code_rate_HP = FEC_3_4;
277*4882a593Smuzhiyun 		break;
278*4882a593Smuzhiyun 	case 3:
279*4882a593Smuzhiyun 		p->code_rate_HP = FEC_5_6;
280*4882a593Smuzhiyun 		break;
281*4882a593Smuzhiyun 	case 4:
282*4882a593Smuzhiyun 		p->code_rate_HP = FEC_7_8;
283*4882a593Smuzhiyun 		break;
284*4882a593Smuzhiyun 	default:
285*4882a593Smuzhiyun 		printk("Unexpected value for code_rate_HP\n");
286*4882a593Smuzhiyun 	}
287*4882a593Smuzhiyun 	switch((tmp >> 3) & 7) {
288*4882a593Smuzhiyun 	case 0:
289*4882a593Smuzhiyun 		p->code_rate_LP = FEC_1_2;
290*4882a593Smuzhiyun 		break;
291*4882a593Smuzhiyun 	case 1:
292*4882a593Smuzhiyun 		p->code_rate_LP = FEC_2_3;
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	case 2:
295*4882a593Smuzhiyun 		p->code_rate_LP = FEC_3_4;
296*4882a593Smuzhiyun 		break;
297*4882a593Smuzhiyun 	case 3:
298*4882a593Smuzhiyun 		p->code_rate_LP = FEC_5_6;
299*4882a593Smuzhiyun 		break;
300*4882a593Smuzhiyun 	case 4:
301*4882a593Smuzhiyun 		p->code_rate_LP = FEC_7_8;
302*4882a593Smuzhiyun 		break;
303*4882a593Smuzhiyun 	default:
304*4882a593Smuzhiyun 		printk("Unexpected value for code_rate_LP\n");
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	tmp = l64781_readreg(state, 0x06);
308*4882a593Smuzhiyun 	switch(tmp & 3) {
309*4882a593Smuzhiyun 	case 0:
310*4882a593Smuzhiyun 		p->modulation = QPSK;
311*4882a593Smuzhiyun 		break;
312*4882a593Smuzhiyun 	case 1:
313*4882a593Smuzhiyun 		p->modulation = QAM_16;
314*4882a593Smuzhiyun 		break;
315*4882a593Smuzhiyun 	case 2:
316*4882a593Smuzhiyun 		p->modulation = QAM_64;
317*4882a593Smuzhiyun 		break;
318*4882a593Smuzhiyun 	default:
319*4882a593Smuzhiyun 		printk(KERN_WARNING "Unexpected value for modulation\n");
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 	switch((tmp >> 2) & 7) {
322*4882a593Smuzhiyun 	case 0:
323*4882a593Smuzhiyun 		p->hierarchy = HIERARCHY_NONE;
324*4882a593Smuzhiyun 		break;
325*4882a593Smuzhiyun 	case 1:
326*4882a593Smuzhiyun 		p->hierarchy = HIERARCHY_1;
327*4882a593Smuzhiyun 		break;
328*4882a593Smuzhiyun 	case 2:
329*4882a593Smuzhiyun 		p->hierarchy = HIERARCHY_2;
330*4882a593Smuzhiyun 		break;
331*4882a593Smuzhiyun 	case 3:
332*4882a593Smuzhiyun 		p->hierarchy = HIERARCHY_4;
333*4882a593Smuzhiyun 		break;
334*4882a593Smuzhiyun 	default:
335*4882a593Smuzhiyun 		printk("Unexpected value for hierarchy\n");
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	tmp = l64781_readreg (state, 0x1d);
340*4882a593Smuzhiyun 	p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	tmp = (int) (l64781_readreg (state, 0x08) |
343*4882a593Smuzhiyun 		     (l64781_readreg (state, 0x09) << 8) |
344*4882a593Smuzhiyun 		     (l64781_readreg (state, 0x0a) << 16));
345*4882a593Smuzhiyun 	p->frequency += tmp;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
l64781_read_status(struct dvb_frontend * fe,enum fe_status * status)350*4882a593Smuzhiyun static int l64781_read_status(struct dvb_frontend *fe, enum fe_status *status)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
353*4882a593Smuzhiyun 	int sync = l64781_readreg (state, 0x32);
354*4882a593Smuzhiyun 	int gain = l64781_readreg (state, 0x0e);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
357*4882a593Smuzhiyun 	l64781_readreg (state, 0x01);  /*  dto. */
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	*status = 0;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (gain > 5)
362*4882a593Smuzhiyun 		*status |= FE_HAS_SIGNAL;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	if (sync & 0x02) /* VCXO locked, this criteria should be ok */
365*4882a593Smuzhiyun 		*status |= FE_HAS_CARRIER;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	if (sync & 0x20)
368*4882a593Smuzhiyun 		*status |= FE_HAS_VITERBI;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	if (sync & 0x40)
371*4882a593Smuzhiyun 		*status |= FE_HAS_SYNC;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	if (sync == 0x7f)
374*4882a593Smuzhiyun 		*status |= FE_HAS_LOCK;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
l64781_read_ber(struct dvb_frontend * fe,u32 * ber)379*4882a593Smuzhiyun static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	/*   XXX FIXME: set up counting period (reg 0x26...0x28)
384*4882a593Smuzhiyun 	 */
385*4882a593Smuzhiyun 	*ber = l64781_readreg (state, 0x39)
386*4882a593Smuzhiyun 	    | (l64781_readreg (state, 0x3a) << 8);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	return 0;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
l64781_read_signal_strength(struct dvb_frontend * fe,u16 * signal_strength)391*4882a593Smuzhiyun static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	u8 gain = l64781_readreg (state, 0x0e);
396*4882a593Smuzhiyun 	*signal_strength = (gain << 8) | gain;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
l64781_read_snr(struct dvb_frontend * fe,u16 * snr)401*4882a593Smuzhiyun static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
406*4882a593Smuzhiyun 	*snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	return 0;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
l64781_read_ucblocks(struct dvb_frontend * fe,u32 * ucblocks)411*4882a593Smuzhiyun static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	*ucblocks = l64781_readreg (state, 0x37)
416*4882a593Smuzhiyun 	   | (l64781_readreg (state, 0x38) << 8);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	return 0;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
l64781_sleep(struct dvb_frontend * fe)421*4882a593Smuzhiyun static int l64781_sleep(struct dvb_frontend* fe)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* Power down */
426*4882a593Smuzhiyun 	return l64781_writereg (state, 0x3e, 0x5a);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
l64781_init(struct dvb_frontend * fe)429*4882a593Smuzhiyun static int l64781_init(struct dvb_frontend* fe)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	reset_and_configure (state);
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	/* Power up */
436*4882a593Smuzhiyun 	l64781_writereg (state, 0x3e, 0xa5);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	/* Reset hard */
439*4882a593Smuzhiyun 	l64781_writereg (state, 0x2a, 0x04);
440*4882a593Smuzhiyun 	l64781_writereg (state, 0x2a, 0x00);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	/* Set tuner specific things */
443*4882a593Smuzhiyun 	/* AFC_POL, set also in reset_afc */
444*4882a593Smuzhiyun 	l64781_writereg (state, 0x07, 0x8e);
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	/* Use internal ADC */
447*4882a593Smuzhiyun 	l64781_writereg (state, 0x0b, 0x81);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	/* AGC loop gain, and polarity is positive */
450*4882a593Smuzhiyun 	l64781_writereg (state, 0x0c, 0x84);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	/* Internal ADC outputs two's complement */
453*4882a593Smuzhiyun 	l64781_writereg (state, 0x0d, 0x8c);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	/* With ppm=8000, it seems the DTR_SENSITIVITY will result in
456*4882a593Smuzhiyun 	   value of 2 with all possible bandwidths and guard
457*4882a593Smuzhiyun 	   intervals, which is the initial value anyway. */
458*4882a593Smuzhiyun 	/*l64781_writereg (state, 0x19, 0x92);*/
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* Everything is two's complement, soft bit and CSI_OUT too */
461*4882a593Smuzhiyun 	l64781_writereg (state, 0x1e, 0x09);
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	/* delay a bit after first init attempt */
464*4882a593Smuzhiyun 	if (state->first) {
465*4882a593Smuzhiyun 		state->first = 0;
466*4882a593Smuzhiyun 		msleep(200);
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	return 0;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
l64781_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * fesettings)472*4882a593Smuzhiyun static int l64781_get_tune_settings(struct dvb_frontend* fe,
473*4882a593Smuzhiyun 				    struct dvb_frontend_tune_settings* fesettings)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	fesettings->min_delay_ms = 4000;
476*4882a593Smuzhiyun 	fesettings->step_size = 0;
477*4882a593Smuzhiyun 	fesettings->max_drift = 0;
478*4882a593Smuzhiyun 	return 0;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
l64781_release(struct dvb_frontend * fe)481*4882a593Smuzhiyun static void l64781_release(struct dvb_frontend* fe)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	struct l64781_state* state = fe->demodulator_priv;
484*4882a593Smuzhiyun 	kfree(state);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun static const struct dvb_frontend_ops l64781_ops;
488*4882a593Smuzhiyun 
l64781_attach(const struct l64781_config * config,struct i2c_adapter * i2c)489*4882a593Smuzhiyun struct dvb_frontend* l64781_attach(const struct l64781_config* config,
490*4882a593Smuzhiyun 				   struct i2c_adapter* i2c)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	struct l64781_state* state = NULL;
493*4882a593Smuzhiyun 	int reg0x3e = -1;
494*4882a593Smuzhiyun 	u8 b0 [] = { 0x1a };
495*4882a593Smuzhiyun 	u8 b1 [] = { 0x00 };
496*4882a593Smuzhiyun 	struct i2c_msg msg [] = { { .addr = config->demod_address, .flags = 0, .buf = b0, .len = 1 },
497*4882a593Smuzhiyun 			   { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	/* allocate memory for the internal state */
500*4882a593Smuzhiyun 	state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
501*4882a593Smuzhiyun 	if (state == NULL) goto error;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	/* setup the state */
504*4882a593Smuzhiyun 	state->config = config;
505*4882a593Smuzhiyun 	state->i2c = i2c;
506*4882a593Smuzhiyun 	state->first = 1;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	/*
509*4882a593Smuzhiyun 	 *  the L64781 won't show up before we send the reset_and_configure()
510*4882a593Smuzhiyun 	 *  broadcast. If nothing responds there is no L64781 on the bus...
511*4882a593Smuzhiyun 	 */
512*4882a593Smuzhiyun 	if (reset_and_configure(state) < 0) {
513*4882a593Smuzhiyun 		dprintk("No response to reset and configure broadcast...\n");
514*4882a593Smuzhiyun 		goto error;
515*4882a593Smuzhiyun 	}
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	/* The chip always responds to reads */
518*4882a593Smuzhiyun 	if (i2c_transfer(state->i2c, msg, 2) != 2) {
519*4882a593Smuzhiyun 		dprintk("No response to read on I2C bus\n");
520*4882a593Smuzhiyun 		goto error;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	/* Save current register contents for bailout */
524*4882a593Smuzhiyun 	reg0x3e = l64781_readreg(state, 0x3e);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	/* Reading the POWER_DOWN register always returns 0 */
527*4882a593Smuzhiyun 	if (reg0x3e != 0) {
528*4882a593Smuzhiyun 		dprintk("Device doesn't look like L64781\n");
529*4882a593Smuzhiyun 		goto error;
530*4882a593Smuzhiyun 	}
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	/* Turn the chip off */
533*4882a593Smuzhiyun 	l64781_writereg (state, 0x3e, 0x5a);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	/* Responds to all reads with 0 */
536*4882a593Smuzhiyun 	if (l64781_readreg(state, 0x1a) != 0) {
537*4882a593Smuzhiyun 		dprintk("Read 1 returned unexpected value\n");
538*4882a593Smuzhiyun 		goto error;
539*4882a593Smuzhiyun 	}
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	/* Turn the chip on */
542*4882a593Smuzhiyun 	l64781_writereg (state, 0x3e, 0xa5);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	/* Responds with register default value */
545*4882a593Smuzhiyun 	if (l64781_readreg(state, 0x1a) != 0xa1) {
546*4882a593Smuzhiyun 		dprintk("Read 2 returned unexpected value\n");
547*4882a593Smuzhiyun 		goto error;
548*4882a593Smuzhiyun 	}
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	/* create dvb_frontend */
551*4882a593Smuzhiyun 	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
552*4882a593Smuzhiyun 	state->frontend.demodulator_priv = state;
553*4882a593Smuzhiyun 	return &state->frontend;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun error:
556*4882a593Smuzhiyun 	if (reg0x3e >= 0)
557*4882a593Smuzhiyun 		l64781_writereg (state, 0x3e, reg0x3e);  /* restore reg 0x3e */
558*4882a593Smuzhiyun 	kfree(state);
559*4882a593Smuzhiyun 	return NULL;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun static const struct dvb_frontend_ops l64781_ops = {
563*4882a593Smuzhiyun 	.delsys = { SYS_DVBT },
564*4882a593Smuzhiyun 	.info = {
565*4882a593Smuzhiyun 		.name = "LSI L64781 DVB-T",
566*4882a593Smuzhiyun 	/*	.frequency_min_hz = ???,*/
567*4882a593Smuzhiyun 	/*	.frequency_max_hz = ???,*/
568*4882a593Smuzhiyun 		.frequency_stepsize_hz = 166666,
569*4882a593Smuzhiyun 	/*      .symbol_rate_tolerance = ???,*/
570*4882a593Smuzhiyun 		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
571*4882a593Smuzhiyun 		      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
572*4882a593Smuzhiyun 		      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
573*4882a593Smuzhiyun 		      FE_CAN_MUTE_TS
574*4882a593Smuzhiyun 	},
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	.release = l64781_release,
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	.init = l64781_init,
579*4882a593Smuzhiyun 	.sleep = l64781_sleep,
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	.set_frontend = apply_frontend_param,
582*4882a593Smuzhiyun 	.get_frontend = get_frontend,
583*4882a593Smuzhiyun 	.get_tune_settings = l64781_get_tune_settings,
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	.read_status = l64781_read_status,
586*4882a593Smuzhiyun 	.read_ber = l64781_read_ber,
587*4882a593Smuzhiyun 	.read_signal_strength = l64781_read_signal_strength,
588*4882a593Smuzhiyun 	.read_snr = l64781_read_snr,
589*4882a593Smuzhiyun 	.read_ucblocks = l64781_read_ucblocks,
590*4882a593Smuzhiyun };
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver");
593*4882a593Smuzhiyun MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
594*4882a593Smuzhiyun MODULE_LICENSE("GPL");
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun EXPORT_SYMBOL(l64781_attach);
597