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