xref: /openbmc/linux/drivers/media/tuners/tda827x.c (revision f2709c20)
1ccae7af2SMauro Carvalho Chehab /*
2ccae7af2SMauro Carvalho Chehab  *
3ccae7af2SMauro Carvalho Chehab  * (c) 2005 Hartmut Hackmann
4ccae7af2SMauro Carvalho Chehab  * (c) 2007 Michael Krufky
5ccae7af2SMauro Carvalho Chehab  *
6ccae7af2SMauro Carvalho Chehab  *  This program is free software; you can redistribute it and/or modify
7ccae7af2SMauro Carvalho Chehab  *  it under the terms of the GNU General Public License as published by
8ccae7af2SMauro Carvalho Chehab  *  the Free Software Foundation; either version 2 of the License, or
9ccae7af2SMauro Carvalho Chehab  *  (at your option) any later version.
10ccae7af2SMauro Carvalho Chehab  *
11ccae7af2SMauro Carvalho Chehab  *  This program is distributed in the hope that it will be useful,
12ccae7af2SMauro Carvalho Chehab  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13ccae7af2SMauro Carvalho Chehab  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14ccae7af2SMauro Carvalho Chehab  *  GNU General Public License for more details.
15ccae7af2SMauro Carvalho Chehab  *
16ccae7af2SMauro Carvalho Chehab  *  You should have received a copy of the GNU General Public License
17ccae7af2SMauro Carvalho Chehab  *  along with this program; if not, write to the Free Software
18ccae7af2SMauro Carvalho Chehab  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19ccae7af2SMauro Carvalho Chehab  */
20ccae7af2SMauro Carvalho Chehab 
21ccae7af2SMauro Carvalho Chehab #include <linux/module.h>
22ccae7af2SMauro Carvalho Chehab #include <linux/slab.h>
23ccae7af2SMauro Carvalho Chehab #include <asm/types.h>
24ccae7af2SMauro Carvalho Chehab #include <linux/dvb/frontend.h>
25ccae7af2SMauro Carvalho Chehab #include <linux/videodev2.h>
26ccae7af2SMauro Carvalho Chehab 
27ccae7af2SMauro Carvalho Chehab #include "tda827x.h"
28ccae7af2SMauro Carvalho Chehab 
29ccae7af2SMauro Carvalho Chehab static int debug;
30ccae7af2SMauro Carvalho Chehab module_param(debug, int, 0644);
31ccae7af2SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
32ccae7af2SMauro Carvalho Chehab 
33ccae7af2SMauro Carvalho Chehab #define dprintk(args...) \
34ccae7af2SMauro Carvalho Chehab 	do {					    \
35ccae7af2SMauro Carvalho Chehab 		if (debug) printk(KERN_DEBUG "tda827x: " args); \
36ccae7af2SMauro Carvalho Chehab 	} while (0)
37ccae7af2SMauro Carvalho Chehab 
38ccae7af2SMauro Carvalho Chehab struct tda827x_priv {
39ccae7af2SMauro Carvalho Chehab 	int i2c_addr;
40ccae7af2SMauro Carvalho Chehab 	struct i2c_adapter *i2c_adap;
41ccae7af2SMauro Carvalho Chehab 	struct tda827x_config *cfg;
42ccae7af2SMauro Carvalho Chehab 
43ccae7af2SMauro Carvalho Chehab 	unsigned int sgIF;
44ccae7af2SMauro Carvalho Chehab 	unsigned char lpsel;
45ccae7af2SMauro Carvalho Chehab 
46ccae7af2SMauro Carvalho Chehab 	u32 frequency;
47ccae7af2SMauro Carvalho Chehab 	u32 bandwidth;
48ccae7af2SMauro Carvalho Chehab };
49ccae7af2SMauro Carvalho Chehab 
50ccae7af2SMauro Carvalho Chehab static void tda827x_set_std(struct dvb_frontend *fe,
51ccae7af2SMauro Carvalho Chehab 			    struct analog_parameters *params)
52ccae7af2SMauro Carvalho Chehab {
53ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
54ccae7af2SMauro Carvalho Chehab 	char *mode;
55ccae7af2SMauro Carvalho Chehab 
56ccae7af2SMauro Carvalho Chehab 	priv->lpsel = 0;
57ccae7af2SMauro Carvalho Chehab 	if (params->std & V4L2_STD_MN) {
58ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 92;
59ccae7af2SMauro Carvalho Chehab 		priv->lpsel = 1;
60ccae7af2SMauro Carvalho Chehab 		mode = "MN";
61ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_B) {
62ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 108;
63ccae7af2SMauro Carvalho Chehab 		mode = "B";
64ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_GH) {
65ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 124;
66ccae7af2SMauro Carvalho Chehab 		mode = "GH";
67ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_PAL_I) {
68ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 124;
69ccae7af2SMauro Carvalho Chehab 		mode = "I";
70ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_DK) {
71ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 124;
72ccae7af2SMauro Carvalho Chehab 		mode = "DK";
73ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_SECAM_L) {
74ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 124;
75ccae7af2SMauro Carvalho Chehab 		mode = "L";
76ccae7af2SMauro Carvalho Chehab 	} else if (params->std & V4L2_STD_SECAM_LC) {
77ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 20;
78ccae7af2SMauro Carvalho Chehab 		mode = "LC";
79ccae7af2SMauro Carvalho Chehab 	} else {
80ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 124;
81ccae7af2SMauro Carvalho Chehab 		mode = "xx";
82ccae7af2SMauro Carvalho Chehab 	}
83ccae7af2SMauro Carvalho Chehab 
84ccae7af2SMauro Carvalho Chehab 	if (params->mode == V4L2_TUNER_RADIO) {
85ccae7af2SMauro Carvalho Chehab 		priv->sgIF = 88; /* if frequency is 5.5 MHz */
86ccae7af2SMauro Carvalho Chehab 		dprintk("setting tda827x to radio FM\n");
87ccae7af2SMauro Carvalho Chehab 	} else
88ccae7af2SMauro Carvalho Chehab 		dprintk("setting tda827x to system %s\n", mode);
89ccae7af2SMauro Carvalho Chehab }
90ccae7af2SMauro Carvalho Chehab 
91ccae7af2SMauro Carvalho Chehab 
92ccae7af2SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
93ccae7af2SMauro Carvalho Chehab 
94ccae7af2SMauro Carvalho Chehab struct tda827x_data {
95ccae7af2SMauro Carvalho Chehab 	u32 lomax;
96ccae7af2SMauro Carvalho Chehab 	u8  spd;
97ccae7af2SMauro Carvalho Chehab 	u8  bs;
98ccae7af2SMauro Carvalho Chehab 	u8  bp;
99ccae7af2SMauro Carvalho Chehab 	u8  cp;
100ccae7af2SMauro Carvalho Chehab 	u8  gc3;
101ccae7af2SMauro Carvalho Chehab 	u8 div1p5;
102ccae7af2SMauro Carvalho Chehab };
103ccae7af2SMauro Carvalho Chehab 
104ccae7af2SMauro Carvalho Chehab static const struct tda827x_data tda827x_table[] = {
105ccae7af2SMauro Carvalho Chehab 	{ .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
106ccae7af2SMauro Carvalho Chehab 	{ .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
107ccae7af2SMauro Carvalho Chehab 	{ .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
108ccae7af2SMauro Carvalho Chehab 	{ .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
109ccae7af2SMauro Carvalho Chehab 	{ .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
110ccae7af2SMauro Carvalho Chehab 	{ .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
111ccae7af2SMauro Carvalho Chehab 	{ .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
112ccae7af2SMauro Carvalho Chehab 	{ .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
113ccae7af2SMauro Carvalho Chehab 	{ .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
114ccae7af2SMauro Carvalho Chehab 	{ .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
115ccae7af2SMauro Carvalho Chehab 	{ .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
116ccae7af2SMauro Carvalho Chehab 	{ .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
117ccae7af2SMauro Carvalho Chehab 	{ .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
118ccae7af2SMauro Carvalho Chehab 	{ .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
119ccae7af2SMauro Carvalho Chehab 	{ .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
120ccae7af2SMauro Carvalho Chehab 	{ .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
121ccae7af2SMauro Carvalho Chehab 	{ .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
122ccae7af2SMauro Carvalho Chehab 	{ .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
123ccae7af2SMauro Carvalho Chehab 	{ .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
124ccae7af2SMauro Carvalho Chehab 	{ .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
125ccae7af2SMauro Carvalho Chehab 	{ .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
126ccae7af2SMauro Carvalho Chehab 	{ .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
127ccae7af2SMauro Carvalho Chehab 	{ .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
128ccae7af2SMauro Carvalho Chehab 	{ .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
129ccae7af2SMauro Carvalho Chehab 	{ .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
130ccae7af2SMauro Carvalho Chehab 	{ .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
131ccae7af2SMauro Carvalho Chehab 	{ .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
132ccae7af2SMauro Carvalho Chehab 	{ .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
133ccae7af2SMauro Carvalho Chehab 	{ .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
134ccae7af2SMauro Carvalho Chehab };
135ccae7af2SMauro Carvalho Chehab 
136ccae7af2SMauro Carvalho Chehab static int tuner_transfer(struct dvb_frontend *fe,
137ccae7af2SMauro Carvalho Chehab 			  struct i2c_msg *msg,
138ccae7af2SMauro Carvalho Chehab 			  const int size)
139ccae7af2SMauro Carvalho Chehab {
140ccae7af2SMauro Carvalho Chehab 	int rc;
141ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
142ccae7af2SMauro Carvalho Chehab 
143ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
144ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
145ccae7af2SMauro Carvalho Chehab 	rc = i2c_transfer(priv->i2c_adap, msg, size);
146ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
147ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 0);
148ccae7af2SMauro Carvalho Chehab 
149ccae7af2SMauro Carvalho Chehab 	if (rc >= 0 && rc != size)
150ccae7af2SMauro Carvalho Chehab 		return -EIO;
151ccae7af2SMauro Carvalho Chehab 
152ccae7af2SMauro Carvalho Chehab 	return rc;
153ccae7af2SMauro Carvalho Chehab }
154ccae7af2SMauro Carvalho Chehab 
155ccae7af2SMauro Carvalho Chehab static int tda827xo_set_params(struct dvb_frontend *fe)
156ccae7af2SMauro Carvalho Chehab {
157ccae7af2SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
158ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
159ccae7af2SMauro Carvalho Chehab 	u8 buf[14];
160ccae7af2SMauro Carvalho Chehab 	int rc;
161ccae7af2SMauro Carvalho Chehab 
162ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
163ccae7af2SMauro Carvalho Chehab 			       .buf = buf, .len = sizeof(buf) };
164ccae7af2SMauro Carvalho Chehab 	int i, tuner_freq, if_freq;
165ccae7af2SMauro Carvalho Chehab 	u32 N;
166ccae7af2SMauro Carvalho Chehab 
167ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
168ccae7af2SMauro Carvalho Chehab 	if (c->bandwidth_hz == 0) {
169ccae7af2SMauro Carvalho Chehab 		if_freq = 5000000;
170ccae7af2SMauro Carvalho Chehab 	} else if (c->bandwidth_hz <= 6000000) {
171ccae7af2SMauro Carvalho Chehab 		if_freq = 4000000;
172ccae7af2SMauro Carvalho Chehab 	} else if (c->bandwidth_hz <= 7000000) {
173ccae7af2SMauro Carvalho Chehab 		if_freq = 4500000;
174ccae7af2SMauro Carvalho Chehab 	} else {	/* 8 MHz */
175ccae7af2SMauro Carvalho Chehab 		if_freq = 5000000;
176ccae7af2SMauro Carvalho Chehab 	}
177ccae7af2SMauro Carvalho Chehab 	tuner_freq = c->frequency;
178ccae7af2SMauro Carvalho Chehab 
179ccae7af2SMauro Carvalho Chehab 	i = 0;
180ccae7af2SMauro Carvalho Chehab 	while (tda827x_table[i].lomax < tuner_freq) {
181ccae7af2SMauro Carvalho Chehab 		if (tda827x_table[i + 1].lomax == 0)
182ccae7af2SMauro Carvalho Chehab 			break;
183ccae7af2SMauro Carvalho Chehab 		i++;
184ccae7af2SMauro Carvalho Chehab 	}
185ccae7af2SMauro Carvalho Chehab 
186ccae7af2SMauro Carvalho Chehab 	tuner_freq += if_freq;
187ccae7af2SMauro Carvalho Chehab 
188ccae7af2SMauro Carvalho Chehab 	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
189ccae7af2SMauro Carvalho Chehab 	buf[0] = 0;
190ccae7af2SMauro Carvalho Chehab 	buf[1] = (N>>8) | 0x40;
191ccae7af2SMauro Carvalho Chehab 	buf[2] = N & 0xff;
192ccae7af2SMauro Carvalho Chehab 	buf[3] = 0;
193ccae7af2SMauro Carvalho Chehab 	buf[4] = 0x52;
194ccae7af2SMauro Carvalho Chehab 	buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
195ccae7af2SMauro Carvalho Chehab 				(tda827x_table[i].bs << 3) +
196ccae7af2SMauro Carvalho Chehab 				tda827x_table[i].bp;
197ccae7af2SMauro Carvalho Chehab 	buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
198ccae7af2SMauro Carvalho Chehab 	buf[7] = 0xbf;
199ccae7af2SMauro Carvalho Chehab 	buf[8] = 0x2a;
200ccae7af2SMauro Carvalho Chehab 	buf[9] = 0x05;
201ccae7af2SMauro Carvalho Chehab 	buf[10] = 0xff;
202ccae7af2SMauro Carvalho Chehab 	buf[11] = 0x00;
203ccae7af2SMauro Carvalho Chehab 	buf[12] = 0x00;
204ccae7af2SMauro Carvalho Chehab 	buf[13] = 0x40;
205ccae7af2SMauro Carvalho Chehab 
206ccae7af2SMauro Carvalho Chehab 	msg.len = 14;
207ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
208ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
209ccae7af2SMauro Carvalho Chehab 		goto err;
210ccae7af2SMauro Carvalho Chehab 
211ccae7af2SMauro Carvalho Chehab 	msleep(500);
212ccae7af2SMauro Carvalho Chehab 	/* correct CP value */
213ccae7af2SMauro Carvalho Chehab 	buf[0] = 0x30;
214ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x50 + tda827x_table[i].cp;
215ccae7af2SMauro Carvalho Chehab 	msg.len = 2;
216ccae7af2SMauro Carvalho Chehab 
217ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
218ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
219ccae7af2SMauro Carvalho Chehab 		goto err;
220ccae7af2SMauro Carvalho Chehab 
221ccae7af2SMauro Carvalho Chehab 	priv->frequency = c->frequency;
222ccae7af2SMauro Carvalho Chehab 	priv->bandwidth = c->bandwidth_hz;
223ccae7af2SMauro Carvalho Chehab 
224ccae7af2SMauro Carvalho Chehab 	return 0;
225ccae7af2SMauro Carvalho Chehab 
226ccae7af2SMauro Carvalho Chehab err:
227ccae7af2SMauro Carvalho Chehab 	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
228ccae7af2SMauro Carvalho Chehab 	       __func__, priv->i2c_addr << 1);
229ccae7af2SMauro Carvalho Chehab 	return rc;
230ccae7af2SMauro Carvalho Chehab }
231ccae7af2SMauro Carvalho Chehab 
232ccae7af2SMauro Carvalho Chehab static int tda827xo_sleep(struct dvb_frontend *fe)
233ccae7af2SMauro Carvalho Chehab {
234ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
235ccae7af2SMauro Carvalho Chehab 	static u8 buf[] = { 0x30, 0xd0 };
236ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
237ccae7af2SMauro Carvalho Chehab 			       .buf = buf, .len = sizeof(buf) };
238ccae7af2SMauro Carvalho Chehab 
239ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
240ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
241ccae7af2SMauro Carvalho Chehab 
242ccae7af2SMauro Carvalho Chehab 	if (priv->cfg && priv->cfg->sleep)
243ccae7af2SMauro Carvalho Chehab 		priv->cfg->sleep(fe);
244ccae7af2SMauro Carvalho Chehab 
245ccae7af2SMauro Carvalho Chehab 	return 0;
246ccae7af2SMauro Carvalho Chehab }
247ccae7af2SMauro Carvalho Chehab 
248ccae7af2SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
249ccae7af2SMauro Carvalho Chehab 
250ccae7af2SMauro Carvalho Chehab static int tda827xo_set_analog_params(struct dvb_frontend *fe,
251ccae7af2SMauro Carvalho Chehab 				      struct analog_parameters *params)
252ccae7af2SMauro Carvalho Chehab {
253ccae7af2SMauro Carvalho Chehab 	unsigned char tuner_reg[8];
254ccae7af2SMauro Carvalho Chehab 	unsigned char reg2[2];
255ccae7af2SMauro Carvalho Chehab 	u32 N;
256ccae7af2SMauro Carvalho Chehab 	int i;
257ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
258ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
259ccae7af2SMauro Carvalho Chehab 	unsigned int freq = params->frequency;
260ccae7af2SMauro Carvalho Chehab 
261ccae7af2SMauro Carvalho Chehab 	tda827x_set_std(fe, params);
262ccae7af2SMauro Carvalho Chehab 
263ccae7af2SMauro Carvalho Chehab 	if (params->mode == V4L2_TUNER_RADIO)
264ccae7af2SMauro Carvalho Chehab 		freq = freq / 1000;
265ccae7af2SMauro Carvalho Chehab 
266ccae7af2SMauro Carvalho Chehab 	N = freq + priv->sgIF;
267ccae7af2SMauro Carvalho Chehab 
268ccae7af2SMauro Carvalho Chehab 	i = 0;
269ccae7af2SMauro Carvalho Chehab 	while (tda827x_table[i].lomax < N * 62500) {
270ccae7af2SMauro Carvalho Chehab 		if (tda827x_table[i + 1].lomax == 0)
271ccae7af2SMauro Carvalho Chehab 			break;
272ccae7af2SMauro Carvalho Chehab 		i++;
273ccae7af2SMauro Carvalho Chehab 	}
274ccae7af2SMauro Carvalho Chehab 
275ccae7af2SMauro Carvalho Chehab 	N = N << tda827x_table[i].spd;
276ccae7af2SMauro Carvalho Chehab 
277ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0;
278ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = (unsigned char)(N>>8);
279ccae7af2SMauro Carvalho Chehab 	tuner_reg[2] = (unsigned char) N;
280ccae7af2SMauro Carvalho Chehab 	tuner_reg[3] = 0x40;
281ccae7af2SMauro Carvalho Chehab 	tuner_reg[4] = 0x52 + (priv->lpsel << 5);
282ccae7af2SMauro Carvalho Chehab 	tuner_reg[5] = (tda827x_table[i].spd    << 6) +
283ccae7af2SMauro Carvalho Chehab 		       (tda827x_table[i].div1p5 << 5) +
284ccae7af2SMauro Carvalho Chehab 		       (tda827x_table[i].bs     << 3) + tda827x_table[i].bp;
285ccae7af2SMauro Carvalho Chehab 	tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
286ccae7af2SMauro Carvalho Chehab 	tuner_reg[7] = 0x8f;
287ccae7af2SMauro Carvalho Chehab 
288ccae7af2SMauro Carvalho Chehab 	msg.buf = tuner_reg;
289ccae7af2SMauro Carvalho Chehab 	msg.len = 8;
290ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
291ccae7af2SMauro Carvalho Chehab 
292ccae7af2SMauro Carvalho Chehab 	msg.buf = reg2;
293ccae7af2SMauro Carvalho Chehab 	msg.len = 2;
294ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x80;
295ccae7af2SMauro Carvalho Chehab 	reg2[1] = 0;
296ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
297ccae7af2SMauro Carvalho Chehab 
298ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x60;
299ccae7af2SMauro Carvalho Chehab 	reg2[1] = 0xbf;
300ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
301ccae7af2SMauro Carvalho Chehab 
302ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x30;
303ccae7af2SMauro Carvalho Chehab 	reg2[1] = tuner_reg[4] + 0x80;
304ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
305ccae7af2SMauro Carvalho Chehab 
306ccae7af2SMauro Carvalho Chehab 	msleep(1);
307ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x30;
308ccae7af2SMauro Carvalho Chehab 	reg2[1] = tuner_reg[4] + 4;
309ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
310ccae7af2SMauro Carvalho Chehab 
311ccae7af2SMauro Carvalho Chehab 	msleep(1);
312ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x30;
313ccae7af2SMauro Carvalho Chehab 	reg2[1] = tuner_reg[4];
314ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
315ccae7af2SMauro Carvalho Chehab 
316ccae7af2SMauro Carvalho Chehab 	msleep(550);
317ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x30;
318ccae7af2SMauro Carvalho Chehab 	reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
319ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
320ccae7af2SMauro Carvalho Chehab 
321ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x60;
322ccae7af2SMauro Carvalho Chehab 	reg2[1] = 0x3f;
323ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
324ccae7af2SMauro Carvalho Chehab 
325ccae7af2SMauro Carvalho Chehab 	reg2[0] = 0x80;
326ccae7af2SMauro Carvalho Chehab 	reg2[1] = 0x08;   /* Vsync en */
327ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
328ccae7af2SMauro Carvalho Chehab 
329ccae7af2SMauro Carvalho Chehab 	priv->frequency = params->frequency;
330ccae7af2SMauro Carvalho Chehab 
331ccae7af2SMauro Carvalho Chehab 	return 0;
332ccae7af2SMauro Carvalho Chehab }
333ccae7af2SMauro Carvalho Chehab 
334ccae7af2SMauro Carvalho Chehab static void tda827xo_agcf(struct dvb_frontend *fe)
335ccae7af2SMauro Carvalho Chehab {
336ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
337ccae7af2SMauro Carvalho Chehab 	unsigned char data[] = { 0x80, 0x0c };
338ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
339ccae7af2SMauro Carvalho Chehab 			       .buf = data, .len = 2};
340ccae7af2SMauro Carvalho Chehab 
341ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
342ccae7af2SMauro Carvalho Chehab }
343ccae7af2SMauro Carvalho Chehab 
344ccae7af2SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
345ccae7af2SMauro Carvalho Chehab 
346ccae7af2SMauro Carvalho Chehab struct tda827xa_data {
347ccae7af2SMauro Carvalho Chehab 	u32 lomax;
348ccae7af2SMauro Carvalho Chehab 	u8  svco;
349ccae7af2SMauro Carvalho Chehab 	u8  spd;
350ccae7af2SMauro Carvalho Chehab 	u8  scr;
351ccae7af2SMauro Carvalho Chehab 	u8  sbs;
352ccae7af2SMauro Carvalho Chehab 	u8  gc3;
353ccae7af2SMauro Carvalho Chehab };
354ccae7af2SMauro Carvalho Chehab 
355ccae7af2SMauro Carvalho Chehab static struct tda827xa_data tda827xa_dvbt[] = {
356ccae7af2SMauro Carvalho Chehab 	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
357ccae7af2SMauro Carvalho Chehab 	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
358ccae7af2SMauro Carvalho Chehab 	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
359ccae7af2SMauro Carvalho Chehab 	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
360ccae7af2SMauro Carvalho Chehab 	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
361ccae7af2SMauro Carvalho Chehab 	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
362ccae7af2SMauro Carvalho Chehab 	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
363ccae7af2SMauro Carvalho Chehab 	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
364ccae7af2SMauro Carvalho Chehab 	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
365ccae7af2SMauro Carvalho Chehab 	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
366ccae7af2SMauro Carvalho Chehab 	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
367ccae7af2SMauro Carvalho Chehab 	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
368ccae7af2SMauro Carvalho Chehab 	{ .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
369ccae7af2SMauro Carvalho Chehab 	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
370ccae7af2SMauro Carvalho Chehab 	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
371ccae7af2SMauro Carvalho Chehab 	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
372ccae7af2SMauro Carvalho Chehab 	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
373ccae7af2SMauro Carvalho Chehab 	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
374ccae7af2SMauro Carvalho Chehab 	{ .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
375ccae7af2SMauro Carvalho Chehab 	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
376ccae7af2SMauro Carvalho Chehab 	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
377ccae7af2SMauro Carvalho Chehab 	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
378ccae7af2SMauro Carvalho Chehab 	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
379ccae7af2SMauro Carvalho Chehab 	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
380ccae7af2SMauro Carvalho Chehab 	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
381ccae7af2SMauro Carvalho Chehab 	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
382ccae7af2SMauro Carvalho Chehab 	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
383ccae7af2SMauro Carvalho Chehab };
384ccae7af2SMauro Carvalho Chehab 
385ccae7af2SMauro Carvalho Chehab static struct tda827xa_data tda827xa_dvbc[] = {
386ccae7af2SMauro Carvalho Chehab 	{ .lomax =  50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
387ccae7af2SMauro Carvalho Chehab 	{ .lomax =  58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
388ccae7af2SMauro Carvalho Chehab 	{ .lomax =  69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
389ccae7af2SMauro Carvalho Chehab 	{ .lomax =  83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
390ccae7af2SMauro Carvalho Chehab 	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
391ccae7af2SMauro Carvalho Chehab 	{ .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
392ccae7af2SMauro Carvalho Chehab 	{ .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
393ccae7af2SMauro Carvalho Chehab 	{ .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
394ccae7af2SMauro Carvalho Chehab 	{ .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
395ccae7af2SMauro Carvalho Chehab 	{ .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
396ccae7af2SMauro Carvalho Chehab 	{ .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
397ccae7af2SMauro Carvalho Chehab 	{ .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
398ccae7af2SMauro Carvalho Chehab 	{ .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
399ccae7af2SMauro Carvalho Chehab 	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
400ccae7af2SMauro Carvalho Chehab 	{ .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
401ccae7af2SMauro Carvalho Chehab 	{ .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
402ccae7af2SMauro Carvalho Chehab 	{ .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
403ccae7af2SMauro Carvalho Chehab 	{ .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
404ccae7af2SMauro Carvalho Chehab 	{ .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
405ccae7af2SMauro Carvalho Chehab 	{ .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
406ccae7af2SMauro Carvalho Chehab 	{ .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
407ccae7af2SMauro Carvalho Chehab 	{ .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
408ccae7af2SMauro Carvalho Chehab 	{ .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
409ccae7af2SMauro Carvalho Chehab 	{ .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
410ccae7af2SMauro Carvalho Chehab 	{ .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
411ccae7af2SMauro Carvalho Chehab 	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
412ccae7af2SMauro Carvalho Chehab 	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
413ccae7af2SMauro Carvalho Chehab };
414ccae7af2SMauro Carvalho Chehab 
415ccae7af2SMauro Carvalho Chehab static struct tda827xa_data tda827xa_analog[] = {
416ccae7af2SMauro Carvalho Chehab 	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
417ccae7af2SMauro Carvalho Chehab 	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
418ccae7af2SMauro Carvalho Chehab 	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
419ccae7af2SMauro Carvalho Chehab 	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
420ccae7af2SMauro Carvalho Chehab 	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
421ccae7af2SMauro Carvalho Chehab 	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
422ccae7af2SMauro Carvalho Chehab 	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
423ccae7af2SMauro Carvalho Chehab 	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
424ccae7af2SMauro Carvalho Chehab 	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
425ccae7af2SMauro Carvalho Chehab 	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
426ccae7af2SMauro Carvalho Chehab 	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
427ccae7af2SMauro Carvalho Chehab 	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
428ccae7af2SMauro Carvalho Chehab 	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
429ccae7af2SMauro Carvalho Chehab 	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
430ccae7af2SMauro Carvalho Chehab 	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
431ccae7af2SMauro Carvalho Chehab 	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
432ccae7af2SMauro Carvalho Chehab 	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
433ccae7af2SMauro Carvalho Chehab 	{ .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
434ccae7af2SMauro Carvalho Chehab 	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
435ccae7af2SMauro Carvalho Chehab 	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
436ccae7af2SMauro Carvalho Chehab 	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
437ccae7af2SMauro Carvalho Chehab 	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
438ccae7af2SMauro Carvalho Chehab 	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
439ccae7af2SMauro Carvalho Chehab 	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
440ccae7af2SMauro Carvalho Chehab 	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
441ccae7af2SMauro Carvalho Chehab 	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
442ccae7af2SMauro Carvalho Chehab };
443ccae7af2SMauro Carvalho Chehab 
444ccae7af2SMauro Carvalho Chehab static int tda827xa_sleep(struct dvb_frontend *fe)
445ccae7af2SMauro Carvalho Chehab {
446ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
447ccae7af2SMauro Carvalho Chehab 	static u8 buf[] = { 0x30, 0x90 };
448ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
449ccae7af2SMauro Carvalho Chehab 			       .buf = buf, .len = sizeof(buf) };
450ccae7af2SMauro Carvalho Chehab 
451ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
452ccae7af2SMauro Carvalho Chehab 
453ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
454ccae7af2SMauro Carvalho Chehab 
455ccae7af2SMauro Carvalho Chehab 	if (priv->cfg && priv->cfg->sleep)
456ccae7af2SMauro Carvalho Chehab 		priv->cfg->sleep(fe);
457ccae7af2SMauro Carvalho Chehab 
458ccae7af2SMauro Carvalho Chehab 	return 0;
459ccae7af2SMauro Carvalho Chehab }
460ccae7af2SMauro Carvalho Chehab 
461ccae7af2SMauro Carvalho Chehab static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
462ccae7af2SMauro Carvalho Chehab 			      struct analog_parameters *params)
463ccae7af2SMauro Carvalho Chehab {
464ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
465ccae7af2SMauro Carvalho Chehab 	unsigned char buf[] = {0x22, 0x01};
466ccae7af2SMauro Carvalho Chehab 	int arg;
467ccae7af2SMauro Carvalho Chehab 	int gp_func;
468ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
469ccae7af2SMauro Carvalho Chehab 
470ccae7af2SMauro Carvalho Chehab 	if (NULL == priv->cfg) {
471ccae7af2SMauro Carvalho Chehab 		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
472ccae7af2SMauro Carvalho Chehab 		return;
473ccae7af2SMauro Carvalho Chehab 	}
474ccae7af2SMauro Carvalho Chehab 	msg.addr = priv->cfg->switch_addr;
475ccae7af2SMauro Carvalho Chehab 	if (priv->cfg->config) {
476ccae7af2SMauro Carvalho Chehab 		if (high)
477ccae7af2SMauro Carvalho Chehab 			dprintk("setting LNA to high gain\n");
478ccae7af2SMauro Carvalho Chehab 		else
479ccae7af2SMauro Carvalho Chehab 			dprintk("setting LNA to low gain\n");
480ccae7af2SMauro Carvalho Chehab 	}
481ccae7af2SMauro Carvalho Chehab 	switch (priv->cfg->config) {
4821bacb2dfSOndrej Zary 	case TDA8290_LNA_OFF: /* no LNA */
483ccae7af2SMauro Carvalho Chehab 		break;
4841bacb2dfSOndrej Zary 	case TDA8290_LNA_GP0_HIGH_ON: /* switch is GPIO 0 of tda8290 */
4851bacb2dfSOndrej Zary 	case TDA8290_LNA_GP0_HIGH_OFF:
486ccae7af2SMauro Carvalho Chehab 		if (params == NULL) {
487ccae7af2SMauro Carvalho Chehab 			gp_func = 0;
488ccae7af2SMauro Carvalho Chehab 			arg  = 0;
489ccae7af2SMauro Carvalho Chehab 		} else {
490ccae7af2SMauro Carvalho Chehab 			/* turn Vsync on */
491ccae7af2SMauro Carvalho Chehab 			gp_func = 1;
492ccae7af2SMauro Carvalho Chehab 			if (params->std & V4L2_STD_MN)
493ccae7af2SMauro Carvalho Chehab 				arg = 1;
494ccae7af2SMauro Carvalho Chehab 			else
495ccae7af2SMauro Carvalho Chehab 				arg = 0;
496ccae7af2SMauro Carvalho Chehab 		}
497ccae7af2SMauro Carvalho Chehab 		if (fe->callback)
498ccae7af2SMauro Carvalho Chehab 			fe->callback(priv->i2c_adap->algo_data,
499ccae7af2SMauro Carvalho Chehab 				     DVB_FRONTEND_COMPONENT_TUNER,
500ccae7af2SMauro Carvalho Chehab 				     gp_func, arg);
501ccae7af2SMauro Carvalho Chehab 		buf[1] = high ? 0 : 1;
5021bacb2dfSOndrej Zary 		if (priv->cfg->config == TDA8290_LNA_GP0_HIGH_OFF)
503ccae7af2SMauro Carvalho Chehab 			buf[1] = high ? 1 : 0;
504ccae7af2SMauro Carvalho Chehab 		tuner_transfer(fe, &msg, 1);
505ccae7af2SMauro Carvalho Chehab 		break;
5061bacb2dfSOndrej Zary 	case TDA8290_LNA_ON_BRIDGE: /* switch with GPIO of saa713x */
507ccae7af2SMauro Carvalho Chehab 		if (fe->callback)
508ccae7af2SMauro Carvalho Chehab 			fe->callback(priv->i2c_adap->algo_data,
509ccae7af2SMauro Carvalho Chehab 				     DVB_FRONTEND_COMPONENT_TUNER, 0, high);
510ccae7af2SMauro Carvalho Chehab 		break;
511ccae7af2SMauro Carvalho Chehab 	}
512ccae7af2SMauro Carvalho Chehab }
513ccae7af2SMauro Carvalho Chehab 
514ccae7af2SMauro Carvalho Chehab static int tda827xa_set_params(struct dvb_frontend *fe)
515ccae7af2SMauro Carvalho Chehab {
516ccae7af2SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
517ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
518ccae7af2SMauro Carvalho Chehab 	struct tda827xa_data *frequency_map = tda827xa_dvbt;
519ccae7af2SMauro Carvalho Chehab 	u8 buf[11];
520ccae7af2SMauro Carvalho Chehab 
521ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
522ccae7af2SMauro Carvalho Chehab 			       .buf = buf, .len = sizeof(buf) };
523ccae7af2SMauro Carvalho Chehab 
524ccae7af2SMauro Carvalho Chehab 	int i, tuner_freq, if_freq, rc;
525ccae7af2SMauro Carvalho Chehab 	u32 N;
526ccae7af2SMauro Carvalho Chehab 
527ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
528ccae7af2SMauro Carvalho Chehab 
529ccae7af2SMauro Carvalho Chehab 	tda827xa_lna_gain(fe, 1, NULL);
530ccae7af2SMauro Carvalho Chehab 	msleep(20);
531ccae7af2SMauro Carvalho Chehab 
532ccae7af2SMauro Carvalho Chehab 	if (c->bandwidth_hz == 0) {
533ccae7af2SMauro Carvalho Chehab 		if_freq = 5000000;
534ccae7af2SMauro Carvalho Chehab 	} else if (c->bandwidth_hz <= 6000000) {
535ccae7af2SMauro Carvalho Chehab 		if_freq = 4000000;
536ccae7af2SMauro Carvalho Chehab 	} else if (c->bandwidth_hz <= 7000000) {
537ccae7af2SMauro Carvalho Chehab 		if_freq = 4500000;
538ccae7af2SMauro Carvalho Chehab 	} else {	/* 8 MHz */
539ccae7af2SMauro Carvalho Chehab 		if_freq = 5000000;
540ccae7af2SMauro Carvalho Chehab 	}
541ccae7af2SMauro Carvalho Chehab 	tuner_freq = c->frequency;
542ccae7af2SMauro Carvalho Chehab 
543ccae7af2SMauro Carvalho Chehab 	switch (c->delivery_system) {
544ccae7af2SMauro Carvalho Chehab 	case SYS_DVBC_ANNEX_A:
545ccae7af2SMauro Carvalho Chehab 	case SYS_DVBC_ANNEX_C:
546ccae7af2SMauro Carvalho Chehab 		dprintk("%s select tda827xa_dvbc\n", __func__);
547ccae7af2SMauro Carvalho Chehab 		frequency_map = tda827xa_dvbc;
548ccae7af2SMauro Carvalho Chehab 		break;
549ccae7af2SMauro Carvalho Chehab 	default:
550ccae7af2SMauro Carvalho Chehab 		break;
551ccae7af2SMauro Carvalho Chehab 	}
552ccae7af2SMauro Carvalho Chehab 
553ccae7af2SMauro Carvalho Chehab 	i = 0;
554ccae7af2SMauro Carvalho Chehab 	while (frequency_map[i].lomax < tuner_freq) {
555ccae7af2SMauro Carvalho Chehab 		if (frequency_map[i + 1].lomax == 0)
556ccae7af2SMauro Carvalho Chehab 			break;
557ccae7af2SMauro Carvalho Chehab 		i++;
558ccae7af2SMauro Carvalho Chehab 	}
559ccae7af2SMauro Carvalho Chehab 
560ccae7af2SMauro Carvalho Chehab 	tuner_freq += if_freq;
561ccae7af2SMauro Carvalho Chehab 
562ccae7af2SMauro Carvalho Chehab 	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
563ccae7af2SMauro Carvalho Chehab 	buf[0] = 0;            // subaddress
564ccae7af2SMauro Carvalho Chehab 	buf[1] = N >> 8;
565ccae7af2SMauro Carvalho Chehab 	buf[2] = N & 0xff;
566ccae7af2SMauro Carvalho Chehab 	buf[3] = 0;
567ccae7af2SMauro Carvalho Chehab 	buf[4] = 0x16;
568ccae7af2SMauro Carvalho Chehab 	buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
569ccae7af2SMauro Carvalho Chehab 			frequency_map[i].sbs;
570ccae7af2SMauro Carvalho Chehab 	buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
571ccae7af2SMauro Carvalho Chehab 	buf[7] = 0x1c;
572ccae7af2SMauro Carvalho Chehab 	buf[8] = 0x06;
573ccae7af2SMauro Carvalho Chehab 	buf[9] = 0x24;
574ccae7af2SMauro Carvalho Chehab 	buf[10] = 0x00;
575ccae7af2SMauro Carvalho Chehab 	msg.len = 11;
576ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
577ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
578ccae7af2SMauro Carvalho Chehab 		goto err;
579ccae7af2SMauro Carvalho Chehab 
580ccae7af2SMauro Carvalho Chehab 	buf[0] = 0x90;
581ccae7af2SMauro Carvalho Chehab 	buf[1] = 0xff;
582ccae7af2SMauro Carvalho Chehab 	buf[2] = 0x60;
583ccae7af2SMauro Carvalho Chehab 	buf[3] = 0x00;
584ccae7af2SMauro Carvalho Chehab 	buf[4] = 0x59;  // lpsel, for 6MHz + 2
585ccae7af2SMauro Carvalho Chehab 	msg.len = 5;
586ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
587ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
588ccae7af2SMauro Carvalho Chehab 		goto err;
589ccae7af2SMauro Carvalho Chehab 
590ccae7af2SMauro Carvalho Chehab 	buf[0] = 0xa0;
591ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x40;
592ccae7af2SMauro Carvalho Chehab 	msg.len = 2;
593ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
594ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
595ccae7af2SMauro Carvalho Chehab 		goto err;
596ccae7af2SMauro Carvalho Chehab 
597ccae7af2SMauro Carvalho Chehab 	msleep(11);
598ccae7af2SMauro Carvalho Chehab 	msg.flags = I2C_M_RD;
599ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
600ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
601ccae7af2SMauro Carvalho Chehab 		goto err;
602ccae7af2SMauro Carvalho Chehab 	msg.flags = 0;
603ccae7af2SMauro Carvalho Chehab 
604ccae7af2SMauro Carvalho Chehab 	buf[1] >>= 4;
605ccae7af2SMauro Carvalho Chehab 	dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
606ccae7af2SMauro Carvalho Chehab 	if ((buf[1]) < 2) {
607ccae7af2SMauro Carvalho Chehab 		tda827xa_lna_gain(fe, 0, NULL);
608ccae7af2SMauro Carvalho Chehab 		buf[0] = 0x60;
609ccae7af2SMauro Carvalho Chehab 		buf[1] = 0x0c;
610ccae7af2SMauro Carvalho Chehab 		rc = tuner_transfer(fe, &msg, 1);
611ccae7af2SMauro Carvalho Chehab 		if (rc < 0)
612ccae7af2SMauro Carvalho Chehab 			goto err;
613ccae7af2SMauro Carvalho Chehab 	}
614ccae7af2SMauro Carvalho Chehab 
615ccae7af2SMauro Carvalho Chehab 	buf[0] = 0xc0;
616ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x99;    // lpsel, for 6MHz + 2
617ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
618ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
619ccae7af2SMauro Carvalho Chehab 		goto err;
620ccae7af2SMauro Carvalho Chehab 
621ccae7af2SMauro Carvalho Chehab 	buf[0] = 0x60;
622ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x3c;
623ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
624ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
625ccae7af2SMauro Carvalho Chehab 		goto err;
626ccae7af2SMauro Carvalho Chehab 
627ccae7af2SMauro Carvalho Chehab 	/* correct CP value */
628ccae7af2SMauro Carvalho Chehab 	buf[0] = 0x30;
629ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x10 + frequency_map[i].scr;
630ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
631ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
632ccae7af2SMauro Carvalho Chehab 		goto err;
633ccae7af2SMauro Carvalho Chehab 
634ccae7af2SMauro Carvalho Chehab 	msleep(163);
635ccae7af2SMauro Carvalho Chehab 	buf[0] = 0xc0;
636ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x39;  // lpsel, for 6MHz + 2
637ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
638ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
639ccae7af2SMauro Carvalho Chehab 		goto err;
640ccae7af2SMauro Carvalho Chehab 
641ccae7af2SMauro Carvalho Chehab 	msleep(3);
642ccae7af2SMauro Carvalho Chehab 	/* freeze AGC1 */
643ccae7af2SMauro Carvalho Chehab 	buf[0] = 0x50;
644ccae7af2SMauro Carvalho Chehab 	buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
645ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
646ccae7af2SMauro Carvalho Chehab 	if (rc < 0)
647ccae7af2SMauro Carvalho Chehab 		goto err;
648ccae7af2SMauro Carvalho Chehab 
649ccae7af2SMauro Carvalho Chehab 	priv->frequency = c->frequency;
650ccae7af2SMauro Carvalho Chehab 	priv->bandwidth = c->bandwidth_hz;
651ccae7af2SMauro Carvalho Chehab 
652ccae7af2SMauro Carvalho Chehab 	return 0;
653ccae7af2SMauro Carvalho Chehab 
654ccae7af2SMauro Carvalho Chehab err:
655ccae7af2SMauro Carvalho Chehab 	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
656ccae7af2SMauro Carvalho Chehab 	       __func__, priv->i2c_addr << 1);
657ccae7af2SMauro Carvalho Chehab 	return rc;
658ccae7af2SMauro Carvalho Chehab }
659ccae7af2SMauro Carvalho Chehab 
660ccae7af2SMauro Carvalho Chehab 
661ccae7af2SMauro Carvalho Chehab static int tda827xa_set_analog_params(struct dvb_frontend *fe,
662ccae7af2SMauro Carvalho Chehab 				      struct analog_parameters *params)
663ccae7af2SMauro Carvalho Chehab {
664ccae7af2SMauro Carvalho Chehab 	unsigned char tuner_reg[11];
665ccae7af2SMauro Carvalho Chehab 	u32 N;
666ccae7af2SMauro Carvalho Chehab 	int i;
667ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
668ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
669ccae7af2SMauro Carvalho Chehab 			       .buf = tuner_reg, .len = sizeof(tuner_reg) };
670ccae7af2SMauro Carvalho Chehab 	unsigned int freq = params->frequency;
671ccae7af2SMauro Carvalho Chehab 
672ccae7af2SMauro Carvalho Chehab 	tda827x_set_std(fe, params);
673ccae7af2SMauro Carvalho Chehab 
674ccae7af2SMauro Carvalho Chehab 	tda827xa_lna_gain(fe, 1, params);
675ccae7af2SMauro Carvalho Chehab 	msleep(10);
676ccae7af2SMauro Carvalho Chehab 
677ccae7af2SMauro Carvalho Chehab 	if (params->mode == V4L2_TUNER_RADIO)
678ccae7af2SMauro Carvalho Chehab 		freq = freq / 1000;
679ccae7af2SMauro Carvalho Chehab 
680ccae7af2SMauro Carvalho Chehab 	N = freq + priv->sgIF;
681ccae7af2SMauro Carvalho Chehab 
682ccae7af2SMauro Carvalho Chehab 	i = 0;
683ccae7af2SMauro Carvalho Chehab 	while (tda827xa_analog[i].lomax < N * 62500) {
684ccae7af2SMauro Carvalho Chehab 		if (tda827xa_analog[i + 1].lomax == 0)
685ccae7af2SMauro Carvalho Chehab 			break;
686ccae7af2SMauro Carvalho Chehab 		i++;
687ccae7af2SMauro Carvalho Chehab 	}
688ccae7af2SMauro Carvalho Chehab 
689ccae7af2SMauro Carvalho Chehab 	N = N << tda827xa_analog[i].spd;
690ccae7af2SMauro Carvalho Chehab 
691ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0;
692ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = (unsigned char)(N>>8);
693ccae7af2SMauro Carvalho Chehab 	tuner_reg[2] = (unsigned char) N;
694ccae7af2SMauro Carvalho Chehab 	tuner_reg[3] = 0;
695ccae7af2SMauro Carvalho Chehab 	tuner_reg[4] = 0x16;
696ccae7af2SMauro Carvalho Chehab 	tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
697ccae7af2SMauro Carvalho Chehab 		       (tda827xa_analog[i].svco << 3) +
698ccae7af2SMauro Carvalho Chehab 			tda827xa_analog[i].sbs;
699ccae7af2SMauro Carvalho Chehab 	tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
700ccae7af2SMauro Carvalho Chehab 	tuner_reg[7] = 0x1c;
701ccae7af2SMauro Carvalho Chehab 	tuner_reg[8] = 4;
702ccae7af2SMauro Carvalho Chehab 	tuner_reg[9] = 0x20;
703ccae7af2SMauro Carvalho Chehab 	tuner_reg[10] = 0x00;
704ccae7af2SMauro Carvalho Chehab 	msg.len = 11;
705ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
706ccae7af2SMauro Carvalho Chehab 
707ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0x90;
708ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0xff;
709ccae7af2SMauro Carvalho Chehab 	tuner_reg[2] = 0xe0;
710ccae7af2SMauro Carvalho Chehab 	tuner_reg[3] = 0;
711ccae7af2SMauro Carvalho Chehab 	tuner_reg[4] = 0x99 + (priv->lpsel << 1);
712ccae7af2SMauro Carvalho Chehab 	msg.len = 5;
713ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
714ccae7af2SMauro Carvalho Chehab 
715ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0xa0;
716ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0xc0;
717ccae7af2SMauro Carvalho Chehab 	msg.len = 2;
718ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
719ccae7af2SMauro Carvalho Chehab 
720ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0x30;
721ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
722ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
723ccae7af2SMauro Carvalho Chehab 
724ccae7af2SMauro Carvalho Chehab 	msg.flags = I2C_M_RD;
725ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
726ccae7af2SMauro Carvalho Chehab 	msg.flags = 0;
727ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] >>= 4;
728ccae7af2SMauro Carvalho Chehab 	dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
729ccae7af2SMauro Carvalho Chehab 	if (tuner_reg[1] < 1)
730ccae7af2SMauro Carvalho Chehab 		tda827xa_lna_gain(fe, 0, params);
731ccae7af2SMauro Carvalho Chehab 
732ccae7af2SMauro Carvalho Chehab 	msleep(100);
733ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0x60;
734ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x3c;
735ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
736ccae7af2SMauro Carvalho Chehab 
737ccae7af2SMauro Carvalho Chehab 	msleep(163);
738ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0x50;
739ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
740ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
741ccae7af2SMauro Carvalho Chehab 
742ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0x80;
743ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x28;
744ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
745ccae7af2SMauro Carvalho Chehab 
746ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0xb0;
747ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x01;
748ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
749ccae7af2SMauro Carvalho Chehab 
750ccae7af2SMauro Carvalho Chehab 	tuner_reg[0] = 0xc0;
751ccae7af2SMauro Carvalho Chehab 	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
752ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
753ccae7af2SMauro Carvalho Chehab 
754ccae7af2SMauro Carvalho Chehab 	priv->frequency = params->frequency;
755ccae7af2SMauro Carvalho Chehab 
756ccae7af2SMauro Carvalho Chehab 	return 0;
757ccae7af2SMauro Carvalho Chehab }
758ccae7af2SMauro Carvalho Chehab 
759ccae7af2SMauro Carvalho Chehab static void tda827xa_agcf(struct dvb_frontend *fe)
760ccae7af2SMauro Carvalho Chehab {
761ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
762ccae7af2SMauro Carvalho Chehab 	unsigned char data[] = {0x80, 0x2c};
763ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
764ccae7af2SMauro Carvalho Chehab 			      .buf = data, .len = 2};
765ccae7af2SMauro Carvalho Chehab 	tuner_transfer(fe, &msg, 1);
766ccae7af2SMauro Carvalho Chehab }
767ccae7af2SMauro Carvalho Chehab 
768ccae7af2SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
769ccae7af2SMauro Carvalho Chehab 
770f2709c20SMauro Carvalho Chehab static void tda827x_release(struct dvb_frontend *fe)
771f2709c20SMauro Carvalho Chehab {
772f2709c20SMauro Carvalho Chehab 	kfree(fe->tuner_priv);
773f2709c20SMauro Carvalho Chehab 	fe->tuner_priv = NULL;
774f2709c20SMauro Carvalho Chehab }
775f2709c20SMauro Carvalho Chehab 
776ccae7af2SMauro Carvalho Chehab static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
777ccae7af2SMauro Carvalho Chehab {
778ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
779ccae7af2SMauro Carvalho Chehab 	*frequency = priv->frequency;
780ccae7af2SMauro Carvalho Chehab 	return 0;
781ccae7af2SMauro Carvalho Chehab }
782ccae7af2SMauro Carvalho Chehab 
783ccae7af2SMauro Carvalho Chehab static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
784ccae7af2SMauro Carvalho Chehab {
785ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
786ccae7af2SMauro Carvalho Chehab 	*bandwidth = priv->bandwidth;
787ccae7af2SMauro Carvalho Chehab 	return 0;
788ccae7af2SMauro Carvalho Chehab }
789ccae7af2SMauro Carvalho Chehab 
790ccae7af2SMauro Carvalho Chehab static int tda827x_init(struct dvb_frontend *fe)
791ccae7af2SMauro Carvalho Chehab {
792ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
793ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
794ccae7af2SMauro Carvalho Chehab 	if (priv->cfg && priv->cfg->init)
795ccae7af2SMauro Carvalho Chehab 		priv->cfg->init(fe);
796ccae7af2SMauro Carvalho Chehab 
797ccae7af2SMauro Carvalho Chehab 	return 0;
798ccae7af2SMauro Carvalho Chehab }
799ccae7af2SMauro Carvalho Chehab 
800ccae7af2SMauro Carvalho Chehab static int tda827x_probe_version(struct dvb_frontend *fe);
801ccae7af2SMauro Carvalho Chehab 
802ccae7af2SMauro Carvalho Chehab static int tda827x_initial_init(struct dvb_frontend *fe)
803ccae7af2SMauro Carvalho Chehab {
804ccae7af2SMauro Carvalho Chehab 	int ret;
805ccae7af2SMauro Carvalho Chehab 	ret = tda827x_probe_version(fe);
806ccae7af2SMauro Carvalho Chehab 	if (ret)
807ccae7af2SMauro Carvalho Chehab 		return ret;
808ccae7af2SMauro Carvalho Chehab 	return fe->ops.tuner_ops.init(fe);
809ccae7af2SMauro Carvalho Chehab }
810ccae7af2SMauro Carvalho Chehab 
811ccae7af2SMauro Carvalho Chehab static int tda827x_initial_sleep(struct dvb_frontend *fe)
812ccae7af2SMauro Carvalho Chehab {
813ccae7af2SMauro Carvalho Chehab 	int ret;
814ccae7af2SMauro Carvalho Chehab 	ret = tda827x_probe_version(fe);
815ccae7af2SMauro Carvalho Chehab 	if (ret)
816ccae7af2SMauro Carvalho Chehab 		return ret;
817ccae7af2SMauro Carvalho Chehab 	return fe->ops.tuner_ops.sleep(fe);
818ccae7af2SMauro Carvalho Chehab }
819ccae7af2SMauro Carvalho Chehab 
82096105144SJulia Lawall static const struct dvb_tuner_ops tda827xo_tuner_ops = {
821ccae7af2SMauro Carvalho Chehab 	.info = {
822ccae7af2SMauro Carvalho Chehab 		.name = "Philips TDA827X",
823ccae7af2SMauro Carvalho Chehab 		.frequency_min  =  55000000,
824ccae7af2SMauro Carvalho Chehab 		.frequency_max  = 860000000,
825ccae7af2SMauro Carvalho Chehab 		.frequency_step =    250000
826ccae7af2SMauro Carvalho Chehab 	},
827f2709c20SMauro Carvalho Chehab 	.release = tda827x_release,
828ccae7af2SMauro Carvalho Chehab 	.init = tda827x_initial_init,
829ccae7af2SMauro Carvalho Chehab 	.sleep = tda827x_initial_sleep,
830ccae7af2SMauro Carvalho Chehab 	.set_params = tda827xo_set_params,
831ccae7af2SMauro Carvalho Chehab 	.set_analog_params = tda827xo_set_analog_params,
832ccae7af2SMauro Carvalho Chehab 	.get_frequency = tda827x_get_frequency,
833ccae7af2SMauro Carvalho Chehab 	.get_bandwidth = tda827x_get_bandwidth,
834ccae7af2SMauro Carvalho Chehab };
835ccae7af2SMauro Carvalho Chehab 
83696105144SJulia Lawall static const struct dvb_tuner_ops tda827xa_tuner_ops = {
837ccae7af2SMauro Carvalho Chehab 	.info = {
838ccae7af2SMauro Carvalho Chehab 		.name = "Philips TDA827XA",
839ccae7af2SMauro Carvalho Chehab 		.frequency_min  =  44000000,
840ccae7af2SMauro Carvalho Chehab 		.frequency_max  = 906000000,
841ccae7af2SMauro Carvalho Chehab 		.frequency_step =     62500
842ccae7af2SMauro Carvalho Chehab 	},
843f2709c20SMauro Carvalho Chehab 	.release = tda827x_release,
844ccae7af2SMauro Carvalho Chehab 	.init = tda827x_init,
845ccae7af2SMauro Carvalho Chehab 	.sleep = tda827xa_sleep,
846ccae7af2SMauro Carvalho Chehab 	.set_params = tda827xa_set_params,
847ccae7af2SMauro Carvalho Chehab 	.set_analog_params = tda827xa_set_analog_params,
848ccae7af2SMauro Carvalho Chehab 	.get_frequency = tda827x_get_frequency,
849ccae7af2SMauro Carvalho Chehab 	.get_bandwidth = tda827x_get_bandwidth,
850ccae7af2SMauro Carvalho Chehab };
851ccae7af2SMauro Carvalho Chehab 
852ccae7af2SMauro Carvalho Chehab static int tda827x_probe_version(struct dvb_frontend *fe)
853ccae7af2SMauro Carvalho Chehab {
854ccae7af2SMauro Carvalho Chehab 	u8 data;
855ccae7af2SMauro Carvalho Chehab 	int rc;
856ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = fe->tuner_priv;
857ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
858ccae7af2SMauro Carvalho Chehab 			       .buf = &data, .len = 1 };
859ccae7af2SMauro Carvalho Chehab 
860ccae7af2SMauro Carvalho Chehab 	rc = tuner_transfer(fe, &msg, 1);
861ccae7af2SMauro Carvalho Chehab 
862ccae7af2SMauro Carvalho Chehab 	if (rc < 0) {
863ccae7af2SMauro Carvalho Chehab 		printk("%s: could not read from tuner at addr: 0x%02x\n",
864ccae7af2SMauro Carvalho Chehab 		       __func__, msg.addr << 1);
865ccae7af2SMauro Carvalho Chehab 		return rc;
866ccae7af2SMauro Carvalho Chehab 	}
867ccae7af2SMauro Carvalho Chehab 	if ((data & 0x3c) == 0) {
868ccae7af2SMauro Carvalho Chehab 		dprintk("tda827x tuner found\n");
869ccae7af2SMauro Carvalho Chehab 		fe->ops.tuner_ops.init  = tda827x_init;
870ccae7af2SMauro Carvalho Chehab 		fe->ops.tuner_ops.sleep = tda827xo_sleep;
871ccae7af2SMauro Carvalho Chehab 		if (priv->cfg)
872ccae7af2SMauro Carvalho Chehab 			priv->cfg->agcf = tda827xo_agcf;
873ccae7af2SMauro Carvalho Chehab 	} else {
874ccae7af2SMauro Carvalho Chehab 		dprintk("tda827xa tuner found\n");
875ccae7af2SMauro Carvalho Chehab 		memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
876ccae7af2SMauro Carvalho Chehab 		if (priv->cfg)
877ccae7af2SMauro Carvalho Chehab 			priv->cfg->agcf = tda827xa_agcf;
878ccae7af2SMauro Carvalho Chehab 	}
879ccae7af2SMauro Carvalho Chehab 	return 0;
880ccae7af2SMauro Carvalho Chehab }
881ccae7af2SMauro Carvalho Chehab 
882ccae7af2SMauro Carvalho Chehab struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
883ccae7af2SMauro Carvalho Chehab 				    struct i2c_adapter *i2c,
884ccae7af2SMauro Carvalho Chehab 				    struct tda827x_config *cfg)
885ccae7af2SMauro Carvalho Chehab {
886ccae7af2SMauro Carvalho Chehab 	struct tda827x_priv *priv = NULL;
887ccae7af2SMauro Carvalho Chehab 
888ccae7af2SMauro Carvalho Chehab 	dprintk("%s:\n", __func__);
889ccae7af2SMauro Carvalho Chehab 	priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
890ccae7af2SMauro Carvalho Chehab 	if (priv == NULL)
891ccae7af2SMauro Carvalho Chehab 		return NULL;
892ccae7af2SMauro Carvalho Chehab 
893ccae7af2SMauro Carvalho Chehab 	priv->i2c_addr = addr;
894ccae7af2SMauro Carvalho Chehab 	priv->i2c_adap = i2c;
895ccae7af2SMauro Carvalho Chehab 	priv->cfg = cfg;
896ccae7af2SMauro Carvalho Chehab 	memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
897ccae7af2SMauro Carvalho Chehab 	fe->tuner_priv = priv;
898ccae7af2SMauro Carvalho Chehab 
899ccae7af2SMauro Carvalho Chehab 	dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
900ccae7af2SMauro Carvalho Chehab 
901ccae7af2SMauro Carvalho Chehab 	return fe;
902ccae7af2SMauro Carvalho Chehab }
903ccae7af2SMauro Carvalho Chehab EXPORT_SYMBOL_GPL(tda827x_attach);
904ccae7af2SMauro Carvalho Chehab 
905ccae7af2SMauro Carvalho Chehab MODULE_DESCRIPTION("DVB TDA827x driver");
906ccae7af2SMauro Carvalho Chehab MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
907ccae7af2SMauro Carvalho Chehab MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
908ccae7af2SMauro Carvalho Chehab MODULE_LICENSE("GPL");
909