xref: /openbmc/linux/drivers/media/tuners/tua9001.c (revision fc851c66b275e4092bb79c888a80dcdd1920c0b8)
1ccae7af2SMauro Carvalho Chehab /*
2ccae7af2SMauro Carvalho Chehab  * Infineon TUA 9001 silicon tuner driver
3ccae7af2SMauro Carvalho Chehab  *
4ccae7af2SMauro Carvalho Chehab  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
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 along
17ccae7af2SMauro Carvalho Chehab  *    with this program; if not, write to the Free Software Foundation, Inc.,
18ccae7af2SMauro Carvalho Chehab  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19ccae7af2SMauro Carvalho Chehab  */
20ccae7af2SMauro Carvalho Chehab 
21ccae7af2SMauro Carvalho Chehab #include "tua9001.h"
22ccae7af2SMauro Carvalho Chehab #include "tua9001_priv.h"
23ccae7af2SMauro Carvalho Chehab 
24ccae7af2SMauro Carvalho Chehab /* write register */
25ccae7af2SMauro Carvalho Chehab static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
26ccae7af2SMauro Carvalho Chehab {
27ccae7af2SMauro Carvalho Chehab 	int ret;
28ccae7af2SMauro Carvalho Chehab 	u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
29ccae7af2SMauro Carvalho Chehab 	struct i2c_msg msg[1] = {
30ccae7af2SMauro Carvalho Chehab 		{
31*fc851c66SAntti Palosaari 			.addr = priv->i2c_addr,
32ccae7af2SMauro Carvalho Chehab 			.flags = 0,
33ccae7af2SMauro Carvalho Chehab 			.len = sizeof(buf),
34ccae7af2SMauro Carvalho Chehab 			.buf = buf,
35ccae7af2SMauro Carvalho Chehab 		}
36ccae7af2SMauro Carvalho Chehab 	};
37ccae7af2SMauro Carvalho Chehab 
38ccae7af2SMauro Carvalho Chehab 	ret = i2c_transfer(priv->i2c, msg, 1);
39ccae7af2SMauro Carvalho Chehab 	if (ret == 1) {
40ccae7af2SMauro Carvalho Chehab 		ret = 0;
41ccae7af2SMauro Carvalho Chehab 	} else {
42e6211c7cSAntti Palosaari 		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
43e6211c7cSAntti Palosaari 				KBUILD_MODNAME, ret, reg);
44ccae7af2SMauro Carvalho Chehab 		ret = -EREMOTEIO;
45ccae7af2SMauro Carvalho Chehab 	}
46ccae7af2SMauro Carvalho Chehab 
47ccae7af2SMauro Carvalho Chehab 	return ret;
48ccae7af2SMauro Carvalho Chehab }
49ccae7af2SMauro Carvalho Chehab 
50ccae7af2SMauro Carvalho Chehab static int tua9001_release(struct dvb_frontend *fe)
51ccae7af2SMauro Carvalho Chehab {
5289054e37SAntti Palosaari 	struct tua9001_priv *priv = fe->tuner_priv;
5389054e37SAntti Palosaari 	int ret = 0;
5489054e37SAntti Palosaari 
55e6211c7cSAntti Palosaari 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
56e6211c7cSAntti Palosaari 
5789054e37SAntti Palosaari 	if (fe->callback)
5889054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
5989054e37SAntti Palosaari 				TUA9001_CMD_CEN, 0);
6089054e37SAntti Palosaari 
61ccae7af2SMauro Carvalho Chehab 	kfree(fe->tuner_priv);
62ccae7af2SMauro Carvalho Chehab 	fe->tuner_priv = NULL;
63ccae7af2SMauro Carvalho Chehab 
6489054e37SAntti Palosaari 	return ret;
65ccae7af2SMauro Carvalho Chehab }
66ccae7af2SMauro Carvalho Chehab 
67ccae7af2SMauro Carvalho Chehab static int tua9001_init(struct dvb_frontend *fe)
68ccae7af2SMauro Carvalho Chehab {
69ccae7af2SMauro Carvalho Chehab 	struct tua9001_priv *priv = fe->tuner_priv;
70ccae7af2SMauro Carvalho Chehab 	int ret = 0;
71ccae7af2SMauro Carvalho Chehab 	u8 i;
72ccae7af2SMauro Carvalho Chehab 	struct reg_val data[] = {
73ccae7af2SMauro Carvalho Chehab 		{ 0x1e, 0x6512 },
74ccae7af2SMauro Carvalho Chehab 		{ 0x25, 0xb888 },
75ccae7af2SMauro Carvalho Chehab 		{ 0x39, 0x5460 },
76ccae7af2SMauro Carvalho Chehab 		{ 0x3b, 0x00c0 },
77ccae7af2SMauro Carvalho Chehab 		{ 0x3a, 0xf000 },
78ccae7af2SMauro Carvalho Chehab 		{ 0x08, 0x0000 },
79ccae7af2SMauro Carvalho Chehab 		{ 0x32, 0x0030 },
80ccae7af2SMauro Carvalho Chehab 		{ 0x41, 0x703a },
81ccae7af2SMauro Carvalho Chehab 		{ 0x40, 0x1c78 },
82ccae7af2SMauro Carvalho Chehab 		{ 0x2c, 0x1c00 },
83ccae7af2SMauro Carvalho Chehab 		{ 0x36, 0xc013 },
84ccae7af2SMauro Carvalho Chehab 		{ 0x37, 0x6f18 },
85ccae7af2SMauro Carvalho Chehab 		{ 0x27, 0x0008 },
86ccae7af2SMauro Carvalho Chehab 		{ 0x2a, 0x0001 },
87ccae7af2SMauro Carvalho Chehab 		{ 0x34, 0x0a40 },
88ccae7af2SMauro Carvalho Chehab 	};
89ccae7af2SMauro Carvalho Chehab 
90e6211c7cSAntti Palosaari 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
91e6211c7cSAntti Palosaari 
9289054e37SAntti Palosaari 	if (fe->callback) {
9389054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
9489054e37SAntti Palosaari 				TUA9001_CMD_RESETN, 0);
9589054e37SAntti Palosaari 		if (ret < 0)
9689054e37SAntti Palosaari 			goto err;
9789054e37SAntti Palosaari 	}
9889054e37SAntti Palosaari 
99ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
100ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
101ccae7af2SMauro Carvalho Chehab 
102ccae7af2SMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(data); i++) {
103ccae7af2SMauro Carvalho Chehab 		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
10489054e37SAntti Palosaari 		if (ret < 0)
10589054e37SAntti Palosaari 			goto err_i2c_gate_ctrl;
106ccae7af2SMauro Carvalho Chehab 	}
107ccae7af2SMauro Carvalho Chehab 
10889054e37SAntti Palosaari err_i2c_gate_ctrl:
109ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
110ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
11189054e37SAntti Palosaari err:
11289054e37SAntti Palosaari 	if (ret < 0)
113e6211c7cSAntti Palosaari 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
11489054e37SAntti Palosaari 
11589054e37SAntti Palosaari 	return ret;
11689054e37SAntti Palosaari }
11789054e37SAntti Palosaari 
11889054e37SAntti Palosaari static int tua9001_sleep(struct dvb_frontend *fe)
11989054e37SAntti Palosaari {
12089054e37SAntti Palosaari 	struct tua9001_priv *priv = fe->tuner_priv;
12189054e37SAntti Palosaari 	int ret = 0;
12289054e37SAntti Palosaari 
123e6211c7cSAntti Palosaari 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
124e6211c7cSAntti Palosaari 
12589054e37SAntti Palosaari 	if (fe->callback)
12689054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
12789054e37SAntti Palosaari 				TUA9001_CMD_RESETN, 1);
128ccae7af2SMauro Carvalho Chehab 
129ccae7af2SMauro Carvalho Chehab 	if (ret < 0)
130e6211c7cSAntti Palosaari 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
131ccae7af2SMauro Carvalho Chehab 
132ccae7af2SMauro Carvalho Chehab 	return ret;
133ccae7af2SMauro Carvalho Chehab }
134ccae7af2SMauro Carvalho Chehab 
135ccae7af2SMauro Carvalho Chehab static int tua9001_set_params(struct dvb_frontend *fe)
136ccae7af2SMauro Carvalho Chehab {
137ccae7af2SMauro Carvalho Chehab 	struct tua9001_priv *priv = fe->tuner_priv;
138ccae7af2SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
13959e54059SMauro Carvalho Chehab 	int ret = 0, i;
140ccae7af2SMauro Carvalho Chehab 	u16 val;
141ccae7af2SMauro Carvalho Chehab 	u32 frequency;
142ccae7af2SMauro Carvalho Chehab 	struct reg_val data[2];
143ccae7af2SMauro Carvalho Chehab 
144e6211c7cSAntti Palosaari 	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
145e6211c7cSAntti Palosaari 			"bandwidth_hz=%d\n", __func__,
146e6211c7cSAntti Palosaari 			c->delivery_system, c->frequency, c->bandwidth_hz);
147ccae7af2SMauro Carvalho Chehab 
148ccae7af2SMauro Carvalho Chehab 	switch (c->delivery_system) {
149ccae7af2SMauro Carvalho Chehab 	case SYS_DVBT:
150ccae7af2SMauro Carvalho Chehab 		switch (c->bandwidth_hz) {
151ccae7af2SMauro Carvalho Chehab 		case 8000000:
152ccae7af2SMauro Carvalho Chehab 			val  = 0x0000;
153ccae7af2SMauro Carvalho Chehab 			break;
154ccae7af2SMauro Carvalho Chehab 		case 7000000:
155ccae7af2SMauro Carvalho Chehab 			val  = 0x1000;
156ccae7af2SMauro Carvalho Chehab 			break;
157ccae7af2SMauro Carvalho Chehab 		case 6000000:
158ccae7af2SMauro Carvalho Chehab 			val  = 0x2000;
159ccae7af2SMauro Carvalho Chehab 			break;
160ccae7af2SMauro Carvalho Chehab 		case 5000000:
161ccae7af2SMauro Carvalho Chehab 			val  = 0x3000;
162ccae7af2SMauro Carvalho Chehab 			break;
163ccae7af2SMauro Carvalho Chehab 		default:
164ccae7af2SMauro Carvalho Chehab 			ret = -EINVAL;
165ccae7af2SMauro Carvalho Chehab 			goto err;
166ccae7af2SMauro Carvalho Chehab 		}
167ccae7af2SMauro Carvalho Chehab 		break;
168ccae7af2SMauro Carvalho Chehab 	default:
169ccae7af2SMauro Carvalho Chehab 		ret = -EINVAL;
170ccae7af2SMauro Carvalho Chehab 		goto err;
171ccae7af2SMauro Carvalho Chehab 	}
172ccae7af2SMauro Carvalho Chehab 
173ccae7af2SMauro Carvalho Chehab 	data[0].reg = 0x04;
174ccae7af2SMauro Carvalho Chehab 	data[0].val = val;
175ccae7af2SMauro Carvalho Chehab 
176ccae7af2SMauro Carvalho Chehab 	frequency = (c->frequency - 150000000);
177ccae7af2SMauro Carvalho Chehab 	frequency /= 100;
178ccae7af2SMauro Carvalho Chehab 	frequency *= 48;
179ccae7af2SMauro Carvalho Chehab 	frequency /= 10000;
180ccae7af2SMauro Carvalho Chehab 
181ccae7af2SMauro Carvalho Chehab 	data[1].reg = 0x1f;
182ccae7af2SMauro Carvalho Chehab 	data[1].val = frequency;
183ccae7af2SMauro Carvalho Chehab 
184ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
185ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
186ccae7af2SMauro Carvalho Chehab 
18789054e37SAntti Palosaari 	if (fe->callback) {
18889054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
18989054e37SAntti Palosaari 				TUA9001_CMD_RXEN, 0);
19089054e37SAntti Palosaari 		if (ret < 0)
19189054e37SAntti Palosaari 			goto err_i2c_gate_ctrl;
19289054e37SAntti Palosaari 	}
19389054e37SAntti Palosaari 
194ccae7af2SMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(data); i++) {
195ccae7af2SMauro Carvalho Chehab 		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
196ccae7af2SMauro Carvalho Chehab 		if (ret < 0)
19789054e37SAntti Palosaari 			goto err_i2c_gate_ctrl;
198ccae7af2SMauro Carvalho Chehab 	}
199ccae7af2SMauro Carvalho Chehab 
20089054e37SAntti Palosaari 	if (fe->callback) {
20189054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
20289054e37SAntti Palosaari 				TUA9001_CMD_RXEN, 1);
20389054e37SAntti Palosaari 		if (ret < 0)
20489054e37SAntti Palosaari 			goto err_i2c_gate_ctrl;
20589054e37SAntti Palosaari 	}
20689054e37SAntti Palosaari 
20789054e37SAntti Palosaari err_i2c_gate_ctrl:
208ccae7af2SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
209ccae7af2SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
210ccae7af2SMauro Carvalho Chehab err:
211ccae7af2SMauro Carvalho Chehab 	if (ret < 0)
212e6211c7cSAntti Palosaari 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
213ccae7af2SMauro Carvalho Chehab 
214ccae7af2SMauro Carvalho Chehab 	return ret;
215ccae7af2SMauro Carvalho Chehab }
216ccae7af2SMauro Carvalho Chehab 
217ccae7af2SMauro Carvalho Chehab static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
218ccae7af2SMauro Carvalho Chehab {
219e6211c7cSAntti Palosaari 	struct tua9001_priv *priv = fe->tuner_priv;
220e6211c7cSAntti Palosaari 
221e6211c7cSAntti Palosaari 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
222e6211c7cSAntti Palosaari 
223ccae7af2SMauro Carvalho Chehab 	*frequency = 0; /* Zero-IF */
224ccae7af2SMauro Carvalho Chehab 
225ccae7af2SMauro Carvalho Chehab 	return 0;
226ccae7af2SMauro Carvalho Chehab }
227ccae7af2SMauro Carvalho Chehab 
228ccae7af2SMauro Carvalho Chehab static const struct dvb_tuner_ops tua9001_tuner_ops = {
229ccae7af2SMauro Carvalho Chehab 	.info = {
230ccae7af2SMauro Carvalho Chehab 		.name           = "Infineon TUA 9001",
231ccae7af2SMauro Carvalho Chehab 
232ccae7af2SMauro Carvalho Chehab 		.frequency_min  = 170000000,
233ccae7af2SMauro Carvalho Chehab 		.frequency_max  = 862000000,
234ccae7af2SMauro Carvalho Chehab 		.frequency_step = 0,
235ccae7af2SMauro Carvalho Chehab 	},
236ccae7af2SMauro Carvalho Chehab 
237ccae7af2SMauro Carvalho Chehab 	.release = tua9001_release,
238ccae7af2SMauro Carvalho Chehab 
239ccae7af2SMauro Carvalho Chehab 	.init = tua9001_init,
24089054e37SAntti Palosaari 	.sleep = tua9001_sleep,
241ccae7af2SMauro Carvalho Chehab 	.set_params = tua9001_set_params,
242ccae7af2SMauro Carvalho Chehab 
243ccae7af2SMauro Carvalho Chehab 	.get_if_frequency = tua9001_get_if_frequency,
244ccae7af2SMauro Carvalho Chehab };
245ccae7af2SMauro Carvalho Chehab 
246ccae7af2SMauro Carvalho Chehab struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
247ccae7af2SMauro Carvalho Chehab 		struct i2c_adapter *i2c, struct tua9001_config *cfg)
248ccae7af2SMauro Carvalho Chehab {
249ccae7af2SMauro Carvalho Chehab 	struct tua9001_priv *priv = NULL;
25089054e37SAntti Palosaari 	int ret;
251ccae7af2SMauro Carvalho Chehab 
252ccae7af2SMauro Carvalho Chehab 	priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL);
253ccae7af2SMauro Carvalho Chehab 	if (priv == NULL)
254ccae7af2SMauro Carvalho Chehab 		return NULL;
255ccae7af2SMauro Carvalho Chehab 
256*fc851c66SAntti Palosaari 	priv->i2c_addr = cfg->i2c_addr;
257ccae7af2SMauro Carvalho Chehab 	priv->i2c = i2c;
258ccae7af2SMauro Carvalho Chehab 
25989054e37SAntti Palosaari 	if (fe->callback) {
26089054e37SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
26189054e37SAntti Palosaari 				TUA9001_CMD_CEN, 1);
26289054e37SAntti Palosaari 		if (ret < 0)
26389054e37SAntti Palosaari 			goto err;
26469504793SAntti Palosaari 
26569504793SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
26669504793SAntti Palosaari 				TUA9001_CMD_RXEN, 0);
26769504793SAntti Palosaari 		if (ret < 0)
26869504793SAntti Palosaari 			goto err;
26969504793SAntti Palosaari 
27069504793SAntti Palosaari 		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
27169504793SAntti Palosaari 				TUA9001_CMD_RESETN, 1);
27269504793SAntti Palosaari 		if (ret < 0)
27369504793SAntti Palosaari 			goto err;
27489054e37SAntti Palosaari 	}
27589054e37SAntti Palosaari 
276e6211c7cSAntti Palosaari 	dev_info(&priv->i2c->dev,
277e6211c7cSAntti Palosaari 			"%s: Infineon TUA 9001 successfully attached\n",
278e6211c7cSAntti Palosaari 			KBUILD_MODNAME);
279ccae7af2SMauro Carvalho Chehab 
280ccae7af2SMauro Carvalho Chehab 	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
281ccae7af2SMauro Carvalho Chehab 			sizeof(struct dvb_tuner_ops));
282ccae7af2SMauro Carvalho Chehab 
283ccae7af2SMauro Carvalho Chehab 	fe->tuner_priv = priv;
284ccae7af2SMauro Carvalho Chehab 	return fe;
28589054e37SAntti Palosaari err:
286e6211c7cSAntti Palosaari 	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
28789054e37SAntti Palosaari 	kfree(priv);
28889054e37SAntti Palosaari 	return NULL;
289ccae7af2SMauro Carvalho Chehab }
290ccae7af2SMauro Carvalho Chehab EXPORT_SYMBOL(tua9001_attach);
291ccae7af2SMauro Carvalho Chehab 
292*fc851c66SAntti Palosaari static int tua9001_probe(struct i2c_client *client,
293*fc851c66SAntti Palosaari 			const struct i2c_device_id *id)
294*fc851c66SAntti Palosaari {
295*fc851c66SAntti Palosaari 	struct tua9001_priv *dev;
296*fc851c66SAntti Palosaari 	struct tua9001_platform_data *pdata = client->dev.platform_data;
297*fc851c66SAntti Palosaari 	struct dvb_frontend *fe = pdata->dvb_frontend;
298*fc851c66SAntti Palosaari 	int ret;
299*fc851c66SAntti Palosaari 
300*fc851c66SAntti Palosaari 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
301*fc851c66SAntti Palosaari 	if (!dev) {
302*fc851c66SAntti Palosaari 		ret = -ENOMEM;
303*fc851c66SAntti Palosaari 		goto err;
304*fc851c66SAntti Palosaari 	}
305*fc851c66SAntti Palosaari 
306*fc851c66SAntti Palosaari 	dev->client = client;
307*fc851c66SAntti Palosaari 	dev->i2c_addr = client->addr;
308*fc851c66SAntti Palosaari 	dev->i2c = client->adapter;
309*fc851c66SAntti Palosaari 	dev->fe = pdata->dvb_frontend;
310*fc851c66SAntti Palosaari 
311*fc851c66SAntti Palosaari 	if (fe->callback) {
312*fc851c66SAntti Palosaari 		ret = fe->callback(client->adapter,
313*fc851c66SAntti Palosaari 				   DVB_FRONTEND_COMPONENT_TUNER,
314*fc851c66SAntti Palosaari 				   TUA9001_CMD_CEN, 1);
315*fc851c66SAntti Palosaari 		if (ret)
316*fc851c66SAntti Palosaari 			goto err_kfree;
317*fc851c66SAntti Palosaari 
318*fc851c66SAntti Palosaari 		ret = fe->callback(client->adapter,
319*fc851c66SAntti Palosaari 				   DVB_FRONTEND_COMPONENT_TUNER,
320*fc851c66SAntti Palosaari 				   TUA9001_CMD_RXEN, 0);
321*fc851c66SAntti Palosaari 		if (ret)
322*fc851c66SAntti Palosaari 			goto err_kfree;
323*fc851c66SAntti Palosaari 
324*fc851c66SAntti Palosaari 		ret = fe->callback(client->adapter,
325*fc851c66SAntti Palosaari 				   DVB_FRONTEND_COMPONENT_TUNER,
326*fc851c66SAntti Palosaari 				   TUA9001_CMD_RESETN, 1);
327*fc851c66SAntti Palosaari 		if (ret)
328*fc851c66SAntti Palosaari 			goto err_kfree;
329*fc851c66SAntti Palosaari 	}
330*fc851c66SAntti Palosaari 
331*fc851c66SAntti Palosaari 	fe->tuner_priv = dev;
332*fc851c66SAntti Palosaari 	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
333*fc851c66SAntti Palosaari 			sizeof(struct dvb_tuner_ops));
334*fc851c66SAntti Palosaari 	fe->ops.tuner_ops.release = NULL;
335*fc851c66SAntti Palosaari 	i2c_set_clientdata(client, dev);
336*fc851c66SAntti Palosaari 
337*fc851c66SAntti Palosaari 	dev_info(&client->dev, "Infineon TUA 9001 successfully attached\n");
338*fc851c66SAntti Palosaari 	return 0;
339*fc851c66SAntti Palosaari err_kfree:
340*fc851c66SAntti Palosaari 	kfree(dev);
341*fc851c66SAntti Palosaari err:
342*fc851c66SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
343*fc851c66SAntti Palosaari 	return ret;
344*fc851c66SAntti Palosaari }
345*fc851c66SAntti Palosaari 
346*fc851c66SAntti Palosaari static int tua9001_remove(struct i2c_client *client)
347*fc851c66SAntti Palosaari {
348*fc851c66SAntti Palosaari 	struct tua9001_priv *dev = i2c_get_clientdata(client);
349*fc851c66SAntti Palosaari 	struct dvb_frontend *fe = dev->fe;
350*fc851c66SAntti Palosaari 	int ret;
351*fc851c66SAntti Palosaari 
352*fc851c66SAntti Palosaari 	dev_dbg(&client->dev, "\n");
353*fc851c66SAntti Palosaari 
354*fc851c66SAntti Palosaari 	if (fe->callback) {
355*fc851c66SAntti Palosaari 		ret = fe->callback(client->adapter,
356*fc851c66SAntti Palosaari 				   DVB_FRONTEND_COMPONENT_TUNER,
357*fc851c66SAntti Palosaari 				   TUA9001_CMD_CEN, 0);
358*fc851c66SAntti Palosaari 		if (ret)
359*fc851c66SAntti Palosaari 			goto err_kfree;
360*fc851c66SAntti Palosaari 	}
361*fc851c66SAntti Palosaari 	kfree(dev);
362*fc851c66SAntti Palosaari 	return 0;
363*fc851c66SAntti Palosaari err_kfree:
364*fc851c66SAntti Palosaari 	kfree(dev);
365*fc851c66SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
366*fc851c66SAntti Palosaari 	return ret;
367*fc851c66SAntti Palosaari }
368*fc851c66SAntti Palosaari 
369*fc851c66SAntti Palosaari static const struct i2c_device_id tua9001_id_table[] = {
370*fc851c66SAntti Palosaari 	{"tua9001", 0},
371*fc851c66SAntti Palosaari 	{}
372*fc851c66SAntti Palosaari };
373*fc851c66SAntti Palosaari MODULE_DEVICE_TABLE(i2c, tua9001_id_table);
374*fc851c66SAntti Palosaari 
375*fc851c66SAntti Palosaari static struct i2c_driver tua9001_driver = {
376*fc851c66SAntti Palosaari 	.driver = {
377*fc851c66SAntti Palosaari 		.owner	= THIS_MODULE,
378*fc851c66SAntti Palosaari 		.name	= "tua9001",
379*fc851c66SAntti Palosaari 		.suppress_bind_attrs = true,
380*fc851c66SAntti Palosaari 	},
381*fc851c66SAntti Palosaari 	.probe		= tua9001_probe,
382*fc851c66SAntti Palosaari 	.remove		= tua9001_remove,
383*fc851c66SAntti Palosaari 	.id_table	= tua9001_id_table,
384*fc851c66SAntti Palosaari };
385*fc851c66SAntti Palosaari 
386*fc851c66SAntti Palosaari module_i2c_driver(tua9001_driver);
387*fc851c66SAntti Palosaari 
388ccae7af2SMauro Carvalho Chehab MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver");
389ccae7af2SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
390ccae7af2SMauro Carvalho Chehab MODULE_LICENSE("GPL");
391