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 
24 static int debug;
25 module_param(debug, int, 0644);
26 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
27 
28 /* write multiple registers */
tda18218_wr_regs(struct tda18218_priv * priv,u8 reg,u8 * val,u8 len)29 static 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 */
tda18218_rd_regs(struct tda18218_priv * priv,u8 reg,u8 * val,u8 len)69 static 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 */
tda18218_wr_reg(struct tda18218_priv * priv,u8 reg,u8 val)100 static 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 
tda18218_rd_reg(struct tda18218_priv * priv,u8 reg,u8 * val)107 static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
108 {
109 	return tda18218_rd_regs(priv, reg, val, 1);
110 }
111 
tda18218_set_params(struct dvb_frontend * fe,struct dvb_frontend_parameters * params)112 static int tda18218_set_params(struct dvb_frontend *fe,
113 	struct dvb_frontend_parameters *params)
114 {
115 	struct tda18218_priv *priv = fe->tuner_priv;
116 	int ret;
117 	u8 buf[3], i, BP_Filter, LP_Fc;
118 	u32 LO_Frac;
119 	/* TODO: find out correct AGC algorithm */
120 	u8 agc[][2] = {
121 		{ R20_AGC11, 0x60 },
122 		{ R23_AGC21, 0x02 },
123 		{ R20_AGC11, 0xa0 },
124 		{ R23_AGC21, 0x09 },
125 		{ R20_AGC11, 0xe0 },
126 		{ R23_AGC21, 0x0c },
127 		{ R20_AGC11, 0x40 },
128 		{ R23_AGC21, 0x01 },
129 		{ R20_AGC11, 0x80 },
130 		{ R23_AGC21, 0x08 },
131 		{ R20_AGC11, 0xc0 },
132 		{ R23_AGC21, 0x0b },
133 		{ R24_AGC22, 0x1c },
134 		{ R24_AGC22, 0x0c },
135 	};
136 
137 	if (fe->ops.i2c_gate_ctrl)
138 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
139 
140 	/* low-pass filter cut-off frequency */
141 	switch (params->u.ofdm.bandwidth) {
142 	case BANDWIDTH_6_MHZ:
143 		LP_Fc = 0;
144 		LO_Frac = params->frequency + 4000000;
145 		break;
146 	case BANDWIDTH_7_MHZ:
147 		LP_Fc = 1;
148 		LO_Frac = params->frequency + 3500000;
149 		break;
150 	case BANDWIDTH_8_MHZ:
151 	default:
152 		LP_Fc = 2;
153 		LO_Frac = params->frequency + 4000000;
154 		break;
155 	}
156 
157 	/* band-pass filter */
158 	if (LO_Frac < 188000000)
159 		BP_Filter = 3;
160 	else if (LO_Frac < 253000000)
161 		BP_Filter = 4;
162 	else if (LO_Frac < 343000000)
163 		BP_Filter = 5;
164 	else
165 		BP_Filter = 6;
166 
167 	buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
168 	buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
169 	buf[2] = priv->regs[R1C_AGC2B];
170 	ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
171 	if (ret)
172 		goto error;
173 
174 	buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
175 	buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
176 	buf[2] = (LO_Frac / 1000) << 4 |
177 		(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
178 	ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
179 	if (ret)
180 		goto error;
181 
182 	buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
183 	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
184 	if (ret)
185 		goto error;
186 
187 	buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
188 	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
189 	if (ret)
190 		goto error;
191 
192 	/* trigger AGC */
193 	for (i = 0; i < ARRAY_SIZE(agc); i++) {
194 		ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
195 		if (ret)
196 			goto error;
197 	}
198 
199 error:
200 	if (fe->ops.i2c_gate_ctrl)
201 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
202 
203 	if (ret)
204 		dbg("%s: failed ret:%d", __func__, ret);
205 
206 	return ret;
207 }
208 
tda18218_sleep(struct dvb_frontend * fe)209 static int tda18218_sleep(struct dvb_frontend *fe)
210 {
211 	struct tda18218_priv *priv = fe->tuner_priv;
212 	int ret;
213 
214 	if (fe->ops.i2c_gate_ctrl)
215 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
216 
217 	/* standby */
218 	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
219 
220 	if (fe->ops.i2c_gate_ctrl)
221 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
222 
223 	if (ret)
224 		dbg("%s: failed ret:%d", __func__, ret);
225 
226 	return ret;
227 }
228 
tda18218_init(struct dvb_frontend * fe)229 static int tda18218_init(struct dvb_frontend *fe)
230 {
231 	struct tda18218_priv *priv = fe->tuner_priv;
232 	int ret;
233 
234 	/* TODO: calibrations */
235 
236 	if (fe->ops.i2c_gate_ctrl)
237 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
238 
239 	ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
240 
241 	if (fe->ops.i2c_gate_ctrl)
242 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
243 
244 	if (ret)
245 		dbg("%s: failed ret:%d", __func__, ret);
246 
247 	return ret;
248 }
249 
tda18218_release(struct dvb_frontend * fe)250 static int tda18218_release(struct dvb_frontend *fe)
251 {
252 	kfree(fe->tuner_priv);
253 	fe->tuner_priv = NULL;
254 	return 0;
255 }
256 
257 static const struct dvb_tuner_ops tda18218_tuner_ops = {
258 	.info = {
259 		.name           = "NXP TDA18218",
260 
261 		.frequency_min  = 174000000,
262 		.frequency_max  = 864000000,
263 		.frequency_step =      1000,
264 	},
265 
266 	.release       = tda18218_release,
267 	.init          = tda18218_init,
268 	.sleep         = tda18218_sleep,
269 
270 	.set_params    = tda18218_set_params,
271 };
272 
tda18218_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c,struct tda18218_config * cfg)273 struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
274 	struct i2c_adapter *i2c, struct tda18218_config *cfg)
275 {
276 	struct tda18218_priv *priv = NULL;
277 	u8 val;
278 	int ret;
279 	/* chip default registers values */
280 	static u8 def_regs[] = {
281 		0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
282 		0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
283 		0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
284 		0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
285 		0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
286 		0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
287 	};
288 
289 	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
290 	if (priv == NULL)
291 		return NULL;
292 
293 	priv->cfg = cfg;
294 	priv->i2c = i2c;
295 	fe->tuner_priv = priv;
296 
297 	if (fe->ops.i2c_gate_ctrl)
298 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
299 
300 	/* check if the tuner is there */
301 	ret = tda18218_rd_reg(priv, R00_ID, &val);
302 	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
303 	if (ret || val != def_regs[R00_ID]) {
304 		kfree(priv);
305 		return NULL;
306 	}
307 
308 	info("NXP TDA18218HN successfully identified.");
309 
310 	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
311 		sizeof(struct dvb_tuner_ops));
312 	memcpy(priv->regs, def_regs, sizeof(def_regs));
313 
314 	/* loop-through enabled chip default register values */
315 	if (priv->cfg->loop_through) {
316 		priv->regs[R17_PD1] = 0xb0;
317 		priv->regs[R18_PD2] = 0x59;
318 	}
319 
320 	/* standby */
321 	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
322 	if (ret)
323 		dbg("%s: failed ret:%d", __func__, ret);
324 
325 	if (fe->ops.i2c_gate_ctrl)
326 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
327 
328 	return fe;
329 }
330 EXPORT_SYMBOL(tda18218_attach);
331 
332 MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
333 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
334 MODULE_LICENSE("GPL");
335