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 
17 #include "tda18218_priv.h"
18 
19 /* Max transfer size done by I2C transfer functions */
20 #define MAX_XFER_SIZE  64
21 
22 /* write multiple registers */
tda18218_wr_regs(struct tda18218_priv * priv,u8 reg,u8 * val,u8 len)23 static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
24 {
25 	int ret = 0, len2, remaining;
26 	u8 buf[MAX_XFER_SIZE];
27 	struct i2c_msg msg[1] = {
28 		{
29 			.addr = priv->cfg->i2c_address,
30 			.flags = 0,
31 			.buf = buf,
32 		}
33 	};
34 
35 	if (1 + len > sizeof(buf)) {
36 		dev_warn(&priv->i2c->dev,
37 			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
38 			 KBUILD_MODNAME, reg, len);
39 		return -EINVAL;
40 	}
41 
42 	for (remaining = len; remaining > 0;
43 			remaining -= (priv->cfg->i2c_wr_max - 1)) {
44 		len2 = remaining;
45 		if (len2 > (priv->cfg->i2c_wr_max - 1))
46 			len2 = (priv->cfg->i2c_wr_max - 1);
47 
48 		msg[0].len = 1 + len2;
49 		buf[0] = reg + len - remaining;
50 		memcpy(&buf[1], &val[len - remaining], len2);
51 
52 		ret = i2c_transfer(priv->i2c, msg, 1);
53 		if (ret != 1)
54 			break;
55 	}
56 
57 	if (ret == 1) {
58 		ret = 0;
59 	} else {
60 		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
61 				"len=%d\n", KBUILD_MODNAME, 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[MAX_XFER_SIZE]; /* 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 = reg + len,
83 			.buf = buf,
84 		}
85 	};
86 
87 	if (reg + len > sizeof(buf)) {
88 		dev_warn(&priv->i2c->dev,
89 			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
90 			 KBUILD_MODNAME, reg, len);
91 		return -EINVAL;
92 	}
93 
94 	ret = i2c_transfer(priv->i2c, msg, 2);
95 	if (ret == 2) {
96 		memcpy(val, &buf[reg], len);
97 		ret = 0;
98 	} else {
99 		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
100 				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
101 		ret = -EREMOTEIO;
102 	}
103 
104 	return ret;
105 }
106 
107 /* write single register */
tda18218_wr_reg(struct tda18218_priv * priv,u8 reg,u8 val)108 static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
109 {
110 	return tda18218_wr_regs(priv, reg, &val, 1);
111 }
112 
113 /* read single register */
114 
tda18218_rd_reg(struct tda18218_priv * priv,u8 reg,u8 * val)115 static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
116 {
117 	return tda18218_rd_regs(priv, reg, val, 1);
118 }
119 
tda18218_set_params(struct dvb_frontend * fe)120 static int tda18218_set_params(struct dvb_frontend *fe)
121 {
122 	struct tda18218_priv *priv = fe->tuner_priv;
123 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
124 	u32 bw = c->bandwidth_hz;
125 	int ret;
126 	u8 buf[3], i, BP_Filter, LP_Fc;
127 	u32 LO_Frac;
128 	/* TODO: find out correct AGC algorithm */
129 	u8 agc[][2] = {
130 		{ R20_AGC11, 0x60 },
131 		{ R23_AGC21, 0x02 },
132 		{ R20_AGC11, 0xa0 },
133 		{ R23_AGC21, 0x09 },
134 		{ R20_AGC11, 0xe0 },
135 		{ R23_AGC21, 0x0c },
136 		{ R20_AGC11, 0x40 },
137 		{ R23_AGC21, 0x01 },
138 		{ R20_AGC11, 0x80 },
139 		{ R23_AGC21, 0x08 },
140 		{ R20_AGC11, 0xc0 },
141 		{ R23_AGC21, 0x0b },
142 		{ R24_AGC22, 0x1c },
143 		{ R24_AGC22, 0x0c },
144 	};
145 
146 	if (fe->ops.i2c_gate_ctrl)
147 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
148 
149 	/* low-pass filter cut-off frequency */
150 	if (bw <= 6000000) {
151 		LP_Fc = 0;
152 		priv->if_frequency = 3000000;
153 	} else if (bw <= 7000000) {
154 		LP_Fc = 1;
155 		priv->if_frequency = 3500000;
156 	} else {
157 		LP_Fc = 2;
158 		priv->if_frequency = 4000000;
159 	}
160 
161 	LO_Frac = c->frequency + priv->if_frequency;
162 
163 	/* band-pass filter */
164 	if (LO_Frac < 188000000)
165 		BP_Filter = 3;
166 	else if (LO_Frac < 253000000)
167 		BP_Filter = 4;
168 	else if (LO_Frac < 343000000)
169 		BP_Filter = 5;
170 	else
171 		BP_Filter = 6;
172 
173 	buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
174 	buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
175 	buf[2] = priv->regs[R1C_AGC2B];
176 	ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
177 	if (ret)
178 		goto error;
179 
180 	buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
181 	buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
182 	buf[2] = (LO_Frac / 1000) << 4 |
183 		(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
184 	ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
185 	if (ret)
186 		goto error;
187 
188 	buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
189 	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
190 	if (ret)
191 		goto error;
192 
193 	buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
194 	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
195 	if (ret)
196 		goto error;
197 
198 	/* trigger AGC */
199 	for (i = 0; i < ARRAY_SIZE(agc); i++) {
200 		ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
201 		if (ret)
202 			goto error;
203 	}
204 
205 error:
206 	if (fe->ops.i2c_gate_ctrl)
207 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
208 
209 	if (ret)
210 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
211 
212 	return ret;
213 }
214 
tda18218_get_if_frequency(struct dvb_frontend * fe,u32 * frequency)215 static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
216 {
217 	struct tda18218_priv *priv = fe->tuner_priv;
218 	*frequency = priv->if_frequency;
219 	dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d\n", __func__, *frequency);
220 	return 0;
221 }
222 
tda18218_sleep(struct dvb_frontend * fe)223 static int tda18218_sleep(struct dvb_frontend *fe)
224 {
225 	struct tda18218_priv *priv = fe->tuner_priv;
226 	int ret;
227 
228 	if (fe->ops.i2c_gate_ctrl)
229 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
230 
231 	/* standby */
232 	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
233 
234 	if (fe->ops.i2c_gate_ctrl)
235 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
236 
237 	if (ret)
238 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
239 
240 	return ret;
241 }
242 
tda18218_init(struct dvb_frontend * fe)243 static int tda18218_init(struct dvb_frontend *fe)
244 {
245 	struct tda18218_priv *priv = fe->tuner_priv;
246 	int ret;
247 
248 	/* TODO: calibrations */
249 
250 	if (fe->ops.i2c_gate_ctrl)
251 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
252 
253 	ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
254 
255 	if (fe->ops.i2c_gate_ctrl)
256 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
257 
258 	if (ret)
259 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
260 
261 	return ret;
262 }
263 
tda18218_release(struct dvb_frontend * fe)264 static void tda18218_release(struct dvb_frontend *fe)
265 {
266 	kfree(fe->tuner_priv);
267 	fe->tuner_priv = NULL;
268 }
269 
270 static const struct dvb_tuner_ops tda18218_tuner_ops = {
271 	.info = {
272 		.name              = "NXP TDA18218",
273 
274 		.frequency_min_hz  = 174 * MHz,
275 		.frequency_max_hz  = 864 * MHz,
276 		.frequency_step_hz =   1 * kHz,
277 	},
278 
279 	.release       = tda18218_release,
280 	.init          = tda18218_init,
281 	.sleep         = tda18218_sleep,
282 
283 	.set_params    = tda18218_set_params,
284 
285 	.get_if_frequency = tda18218_get_if_frequency,
286 };
287 
tda18218_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c,struct tda18218_config * cfg)288 struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
289 	struct i2c_adapter *i2c, struct tda18218_config *cfg)
290 {
291 	struct tda18218_priv *priv = NULL;
292 	u8 val;
293 	int ret;
294 	/* chip default registers values */
295 	static u8 def_regs[] = {
296 		0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
297 		0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
298 		0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
299 		0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
300 		0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
301 		0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
302 	};
303 
304 	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
305 	if (priv == NULL)
306 		return NULL;
307 
308 	priv->cfg = cfg;
309 	priv->i2c = i2c;
310 	fe->tuner_priv = priv;
311 
312 	if (fe->ops.i2c_gate_ctrl)
313 		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
314 
315 	/* check if the tuner is there */
316 	ret = tda18218_rd_reg(priv, R00_ID, &val);
317 	if (!ret)
318 		dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, val);
319 	if (ret || val != def_regs[R00_ID]) {
320 		kfree(priv);
321 		return NULL;
322 	}
323 
324 	dev_info(&priv->i2c->dev,
325 			"%s: NXP TDA18218HN successfully identified\n",
326 			KBUILD_MODNAME);
327 
328 	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
329 		sizeof(struct dvb_tuner_ops));
330 	memcpy(priv->regs, def_regs, sizeof(def_regs));
331 
332 	/* loop-through enabled chip default register values */
333 	if (priv->cfg->loop_through) {
334 		priv->regs[R17_PD1] = 0xb0;
335 		priv->regs[R18_PD2] = 0x59;
336 	}
337 
338 	/* standby */
339 	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
340 	if (ret)
341 		dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
342 
343 	if (fe->ops.i2c_gate_ctrl)
344 		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
345 
346 	return fe;
347 }
348 EXPORT_SYMBOL_GPL(tda18218_attach);
349 
350 MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
351 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
352 MODULE_LICENSE("GPL");
353