1/*
2 * NXP TDA18218HN silicon tuner driver
3 *
4 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
5 *
6 *    This program is free software; you can redistribute it and/or modify
7 *    it under the terms of the GNU General Public License as published by
8 *    the Free Software Foundation; either version 2 of the License, or
9 *    (at your option) any later version.
10 *
11 *    This program is distributed in the hope that it will be useful,
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *    GNU General Public License for more details.
15 *
16 *    You should have received a copy of the GNU General Public License
17 *    along with this program; if not, write to the Free Software
18 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include "tda18218.h"
22#include "tda18218_priv.h"
23
24static int debug;
25module_param(debug, int, 0644);
26MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
27
28/* write multiple registers */
29static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
30{
31	int ret = 0;
32	u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
33	struct i2c_msg msg[1] = {
34		{
35			.addr = priv->cfg->i2c_address,
36			.flags = 0,
37			.buf = buf,
38		}
39	};
40
41	msg_len_max = priv->cfg->i2c_wr_max - 1;
42	quotient = len / msg_len_max;
43	remainder = len % msg_len_max;
44	msg_len = msg_len_max;
45	for (i = 0; (i <= quotient && remainder); i++) {
46		if (i == quotient)  /* set len of the last msg */
47			msg_len = remainder;
48
49		msg[0].len = msg_len + 1;
50		buf[0] = reg + i * msg_len_max;
51		memcpy(&buf[1], &val[i * msg_len_max], msg_len);
52
53		ret = i2c_transfer(priv->i2c, msg, 1);
54		if (ret != 1)
55			break;
56	}
57
58	if (ret == 1) {
59		ret = 0;
60	} else {
61		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
62		ret = -EREMOTEIO;
63	}
64
65	return ret;
66}
67
68/* read multiple registers */
69static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
70{
71	int ret;
72	u8 buf[reg+len]; /* we must start read always from reg 0x00 */
73	struct i2c_msg msg[2] = {
74		{
75			.addr = priv->cfg->i2c_address,
76			.flags = 0,
77			.len = 1,
78			.buf = "\x00",
79		}, {
80			.addr = priv->cfg->i2c_address,
81			.flags = I2C_M_RD,
82			.len = sizeof(buf),
83			.buf = buf,
84		}
85	};
86
87	ret = i2c_transfer(priv->i2c, msg, 2);
88	if (ret == 2) {
89		memcpy(val, &buf[reg], len);
90		ret = 0;
91	} else {
92		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
93		ret = -EREMOTEIO;
94	}
95
96	return ret;
97}
98
99/* write single register */
100static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
101{
102	return tda18218_wr_regs(priv, reg, &val, 1);
103}
104
105/* read single register */
106
107static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
108{
109	return tda18218_rd_regs(priv, reg, val, 1);
110}
111
112static int tda18218_set_params(struct dvb_frontend *fe)
113{
114	struct tda18218_priv *priv = fe->tuner_priv;
115	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
116	u32 bw = c->bandwidth_hz;
117	int ret;
118	u8 buf[3], i, BP_Filter, LP_Fc;
119	u32 LO_Frac;
120	/* TODO: find out correct AGC algorithm */
121	u8 agc[][2] = {
122		{ R20_AGC11, 0x60 },
123		{ R23_AGC21, 0x02 },
124		{ R20_AGC11, 0xa0 },
125		{ R23_AGC21, 0x09 },
126		{ R20_AGC11, 0xe0 },
127		{ R23_AGC21, 0x0c },
128		{ R20_AGC11, 0x40 },
129		{ R23_AGC21, 0x01 },
130		{ R20_AGC11, 0x80 },
131		{ R23_AGC21, 0x08 },
132		{ R20_AGC11, 0xc0 },
133		{ R23_AGC21, 0x0b },
134		{ R24_AGC22, 0x1c },
135		{ R24_AGC22, 0x0c },
136	};
137
138	if (fe->ops.i2c_gate_ctrl)
139		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
140
141	/* low-pass filter cut-off frequency */
142	if (bw <= 6000000) {
143		LP_Fc = 0;
144		priv->if_frequency = 3000000;
145	} else if (bw <= 7000000) {
146		LP_Fc = 1;
147		priv->if_frequency = 3500000;
148	} else {
149		LP_Fc = 2;
150		priv->if_frequency = 4000000;
151	}
152
153	LO_Frac = c->frequency + priv->if_frequency;
154
155	/* band-pass filter */
156	if (LO_Frac < 188000000)
157		BP_Filter = 3;
158	else if (LO_Frac < 253000000)
159		BP_Filter = 4;
160	else if (LO_Frac < 343000000)
161		BP_Filter = 5;
162	else
163		BP_Filter = 6;
164
165	buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
166	buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
167	buf[2] = priv->regs[R1C_AGC2B];
168	ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
169	if (ret)
170		goto error;
171
172	buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
173	buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
174	buf[2] = (LO_Frac / 1000) << 4 |
175		(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
176	ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
177	if (ret)
178		goto error;
179
180	buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
181	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
182	if (ret)
183		goto error;
184
185	buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
186	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
187	if (ret)
188		goto error;
189
190	/* trigger AGC */
191	for (i = 0; i < ARRAY_SIZE(agc); i++) {
192		ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
193		if (ret)
194			goto error;
195	}
196
197error:
198	if (fe->ops.i2c_gate_ctrl)
199		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
200
201	if (ret)
202		dbg("%s: failed ret:%d", __func__, ret);
203
204	return ret;
205}
206
207static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
208{
209	struct tda18218_priv *priv = fe->tuner_priv;
210	*frequency = priv->if_frequency;
211	dbg("%s: if=%d", __func__, *frequency);
212	return 0;
213}
214
215static int tda18218_sleep(struct dvb_frontend *fe)
216{
217	struct tda18218_priv *priv = fe->tuner_priv;
218	int ret;
219
220	if (fe->ops.i2c_gate_ctrl)
221		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
222
223	/* standby */
224	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
225
226	if (fe->ops.i2c_gate_ctrl)
227		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
228
229	if (ret)
230		dbg("%s: failed ret:%d", __func__, ret);
231
232	return ret;
233}
234
235static int tda18218_init(struct dvb_frontend *fe)
236{
237	struct tda18218_priv *priv = fe->tuner_priv;
238	int ret;
239
240	/* TODO: calibrations */
241
242	if (fe->ops.i2c_gate_ctrl)
243		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
244
245	ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
246
247	if (fe->ops.i2c_gate_ctrl)
248		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
249
250	if (ret)
251		dbg("%s: failed ret:%d", __func__, ret);
252
253	return ret;
254}
255
256static int tda18218_release(struct dvb_frontend *fe)
257{
258	kfree(fe->tuner_priv);
259	fe->tuner_priv = NULL;
260	return 0;
261}
262
263static const struct dvb_tuner_ops tda18218_tuner_ops = {
264	.info = {
265		.name           = "NXP TDA18218",
266
267		.frequency_min  = 174000000,
268		.frequency_max  = 864000000,
269		.frequency_step =      1000,
270	},
271
272	.release       = tda18218_release,
273	.init          = tda18218_init,
274	.sleep         = tda18218_sleep,
275
276	.set_params    = tda18218_set_params,
277
278	.get_if_frequency = tda18218_get_if_frequency,
279};
280
281struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
282	struct i2c_adapter *i2c, struct tda18218_config *cfg)
283{
284	struct tda18218_priv *priv = NULL;
285	u8 val;
286	int ret;
287	/* chip default registers values */
288	static u8 def_regs[] = {
289		0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
290		0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
291		0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
292		0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
293		0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
294		0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
295	};
296
297	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
298	if (priv == NULL)
299		return NULL;
300
301	priv->cfg = cfg;
302	priv->i2c = i2c;
303	fe->tuner_priv = priv;
304
305	if (fe->ops.i2c_gate_ctrl)
306		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
307
308	/* check if the tuner is there */
309	ret = tda18218_rd_reg(priv, R00_ID, &val);
310	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
311	if (ret || val != def_regs[R00_ID]) {
312		kfree(priv);
313		return NULL;
314	}
315
316	info("NXP TDA18218HN successfully identified.");
317
318	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
319		sizeof(struct dvb_tuner_ops));
320	memcpy(priv->regs, def_regs, sizeof(def_regs));
321
322	/* loop-through enabled chip default register values */
323	if (priv->cfg->loop_through) {
324		priv->regs[R17_PD1] = 0xb0;
325		priv->regs[R18_PD2] = 0x59;
326	}
327
328	/* standby */
329	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
330	if (ret)
331		dbg("%s: failed ret:%d", __func__, ret);
332
333	if (fe->ops.i2c_gate_ctrl)
334		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
335
336	return fe;
337}
338EXPORT_SYMBOL(tda18218_attach);
339
340MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
341MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
342MODULE_LICENSE("GPL");
343