xref: /openbmc/linux/drivers/media/tuners/fc2580.c (revision d0b73b48)
1 /*
2  * FCI FC2580 silicon tuner driver
3  *
4  * Copyright (C) 2012 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 along
17  *    with this program; if not, write to the Free Software Foundation, Inc.,
18  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "fc2580_priv.h"
22 
23 /*
24  * TODO:
25  * I2C write and read works only for one single register. Multiple registers
26  * could not be accessed using normal register address auto-increment.
27  * There could be (very likely) register to change that behavior....
28  *
29  * Due to that limitation functions:
30  *   fc2580_wr_regs()
31  *   fc2580_rd_regs()
32  * could not be used for accessing more than one register at once.
33  *
34  * TODO:
35  * Currently it blind writes bunch of static registers from the
36  * fc2580_freq_regs_lut[] when fc2580_set_params() is called. Add some
37  * logic to reduce unneeded register writes.
38  */
39 
40 /* write multiple registers */
41 static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
42 {
43 	int ret;
44 	u8 buf[1 + len];
45 	struct i2c_msg msg[1] = {
46 		{
47 			.addr = priv->cfg->i2c_addr,
48 			.flags = 0,
49 			.len = sizeof(buf),
50 			.buf = buf,
51 		}
52 	};
53 
54 	buf[0] = reg;
55 	memcpy(&buf[1], val, len);
56 
57 	ret = i2c_transfer(priv->i2c, msg, 1);
58 	if (ret == 1) {
59 		ret = 0;
60 	} else {
61 		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
62 				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
63 		ret = -EREMOTEIO;
64 	}
65 	return ret;
66 }
67 
68 /* read multiple registers */
69 static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
70 {
71 	int ret;
72 	u8 buf[len];
73 	struct i2c_msg msg[2] = {
74 		{
75 			.addr = priv->cfg->i2c_addr,
76 			.flags = 0,
77 			.len = 1,
78 			.buf = &reg,
79 		}, {
80 			.addr = priv->cfg->i2c_addr,
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, len);
90 		ret = 0;
91 	} else {
92 		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
93 				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
94 		ret = -EREMOTEIO;
95 	}
96 
97 	return ret;
98 }
99 
100 /* write single register */
101 static int fc2580_wr_reg(struct fc2580_priv *priv, u8 reg, u8 val)
102 {
103 	return fc2580_wr_regs(priv, reg, &val, 1);
104 }
105 
106 /* read single register */
107 static int fc2580_rd_reg(struct fc2580_priv *priv, u8 reg, u8 *val)
108 {
109 	return fc2580_rd_regs(priv, reg, val, 1);
110 }
111 
112 /* write single register conditionally only when value differs from 0xff
113  * XXX: This is special routine meant only for writing fc2580_freq_regs_lut[]
114  * values. Do not use for the other purposes. */
115 static int fc2580_wr_reg_ff(struct fc2580_priv *priv, u8 reg, u8 val)
116 {
117 	if (val == 0xff)
118 		return 0;
119 	else
120 		return fc2580_wr_regs(priv, reg, &val, 1);
121 }
122 
123 static int fc2580_set_params(struct dvb_frontend *fe)
124 {
125 	struct fc2580_priv *priv = fe->tuner_priv;
126 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
127 	int ret = 0, i;
128 	unsigned int r_val, n_val, k_val, k_val_reg, f_ref;
129 	u8 tmp_val, r18_val;
130 	u64 f_vco;
131 
132 	/*
133 	 * Fractional-N synthesizer/PLL.
134 	 * Most likely all those PLL calculations are not correct. I am not
135 	 * sure, but it looks like it is divider based Fractional-N synthesizer.
136 	 * There is divider for reference clock too?
137 	 * Anyhow, synthesizer calculation results seems to be quite correct.
138 	 */
139 
140 	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
141 			"bandwidth_hz=%d\n", __func__,
142 			c->delivery_system, c->frequency, c->bandwidth_hz);
143 
144 	if (fe->ops.i2c_gate_ctrl)
145 		fe->ops.i2c_gate_ctrl(fe, 1);
146 
147 	/* PLL */
148 	for (i = 0; i < ARRAY_SIZE(fc2580_pll_lut); i++) {
149 		if (c->frequency <= fc2580_pll_lut[i].freq)
150 			break;
151 	}
152 
153 	if (i == ARRAY_SIZE(fc2580_pll_lut))
154 		goto err;
155 
156 	f_vco = c->frequency;
157 	f_vco *= fc2580_pll_lut[i].div;
158 
159 	if (f_vco >= 2600000000UL)
160 		tmp_val = 0x0e | fc2580_pll_lut[i].band;
161 	else
162 		tmp_val = 0x06 | fc2580_pll_lut[i].band;
163 
164 	ret = fc2580_wr_reg(priv, 0x02, tmp_val);
165 	if (ret < 0)
166 		goto err;
167 
168 	if (f_vco >= 2UL * 76 * priv->cfg->clock) {
169 		r_val = 1;
170 		r18_val = 0x00;
171 	} else if (f_vco >= 1UL * 76 * priv->cfg->clock) {
172 		r_val = 2;
173 		r18_val = 0x10;
174 	} else {
175 		r_val = 4;
176 		r18_val = 0x20;
177 	}
178 
179 	f_ref = 2UL * priv->cfg->clock / r_val;
180 	n_val = div_u64_rem(f_vco, f_ref, &k_val);
181 	k_val_reg = 1UL * k_val * (1 << 20) / f_ref;
182 
183 	ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff));
184 	if (ret < 0)
185 		goto err;
186 
187 	ret = fc2580_wr_reg(priv, 0x1a, (k_val_reg >> 8) & 0xff);
188 	if (ret < 0)
189 		goto err;
190 
191 	ret = fc2580_wr_reg(priv, 0x1b, (k_val_reg >> 0) & 0xff);
192 	if (ret < 0)
193 		goto err;
194 
195 	ret = fc2580_wr_reg(priv, 0x1c, n_val);
196 	if (ret < 0)
197 		goto err;
198 
199 	if (priv->cfg->clock >= 28000000) {
200 		ret = fc2580_wr_reg(priv, 0x4b, 0x22);
201 		if (ret < 0)
202 			goto err;
203 	}
204 
205 	if (fc2580_pll_lut[i].band == 0x00) {
206 		if (c->frequency <= 794000000)
207 			tmp_val = 0x9f;
208 		else
209 			tmp_val = 0x8f;
210 
211 		ret = fc2580_wr_reg(priv, 0x2d, tmp_val);
212 		if (ret < 0)
213 			goto err;
214 	}
215 
216 	/* registers */
217 	for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) {
218 		if (c->frequency <= fc2580_freq_regs_lut[i].freq)
219 			break;
220 	}
221 
222 	if (i == ARRAY_SIZE(fc2580_freq_regs_lut))
223 		goto err;
224 
225 	ret = fc2580_wr_reg_ff(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
226 	if (ret < 0)
227 		goto err;
228 
229 	ret = fc2580_wr_reg_ff(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
230 	if (ret < 0)
231 		goto err;
232 
233 	ret = fc2580_wr_reg_ff(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
234 	if (ret < 0)
235 		goto err;
236 
237 	ret = fc2580_wr_reg_ff(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
238 	if (ret < 0)
239 		goto err;
240 
241 	ret = fc2580_wr_reg_ff(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
242 	if (ret < 0)
243 		goto err;
244 
245 	ret = fc2580_wr_reg_ff(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
246 	if (ret < 0)
247 		goto err;
248 
249 	ret = fc2580_wr_reg_ff(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
250 	if (ret < 0)
251 		goto err;
252 
253 	ret = fc2580_wr_reg_ff(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
254 	if (ret < 0)
255 		goto err;
256 
257 	ret = fc2580_wr_reg_ff(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
258 	if (ret < 0)
259 		goto err;
260 
261 	ret = fc2580_wr_reg_ff(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
262 	if (ret < 0)
263 		goto err;
264 
265 	ret = fc2580_wr_reg_ff(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
266 	if (ret < 0)
267 		goto err;
268 
269 	ret = fc2580_wr_reg_ff(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
270 	if (ret < 0)
271 		goto err;
272 
273 	ret = fc2580_wr_reg_ff(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
274 	if (ret < 0)
275 		goto err;
276 
277 	ret = fc2580_wr_reg_ff(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
278 	if (ret < 0)
279 		goto err;
280 
281 	ret = fc2580_wr_reg_ff(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
282 	if (ret < 0)
283 		goto err;
284 
285 	ret = fc2580_wr_reg_ff(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
286 	if (ret < 0)
287 		goto err;
288 
289 	ret = fc2580_wr_reg_ff(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
290 	if (ret < 0)
291 		goto err;
292 
293 	ret = fc2580_wr_reg_ff(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
294 	if (ret < 0)
295 		goto err;
296 
297 	ret = fc2580_wr_reg_ff(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
298 	if (ret < 0)
299 		goto err;
300 
301 	ret = fc2580_wr_reg_ff(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
302 	if (ret < 0)
303 		goto err;
304 
305 	ret = fc2580_wr_reg_ff(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
306 	if (ret < 0)
307 		goto err;
308 
309 	ret = fc2580_wr_reg_ff(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
310 	if (ret < 0)
311 		goto err;
312 
313 	ret = fc2580_wr_reg_ff(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
314 	if (ret < 0)
315 		goto err;
316 
317 	ret = fc2580_wr_reg_ff(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
318 	if (ret < 0)
319 		goto err;
320 
321 	/* IF filters */
322 	for (i = 0; i < ARRAY_SIZE(fc2580_if_filter_lut); i++) {
323 		if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq)
324 			break;
325 	}
326 
327 	if (i == ARRAY_SIZE(fc2580_if_filter_lut))
328 		goto err;
329 
330 	ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val);
331 	if (ret < 0)
332 		goto err;
333 
334 	ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \
335 			fc2580_if_filter_lut[i].mul / 1000000000);
336 	if (ret < 0)
337 		goto err;
338 
339 	ret = fc2580_wr_reg(priv, 0x39, fc2580_if_filter_lut[i].r39_val);
340 	if (ret < 0)
341 		goto err;
342 
343 	/* calibration? */
344 	ret = fc2580_wr_reg(priv, 0x2e, 0x09);
345 	if (ret < 0)
346 		goto err;
347 
348 	for (i = 0; i < 5; i++) {
349 		ret = fc2580_rd_reg(priv, 0x2f, &tmp_val);
350 		if (ret < 0)
351 			goto err;
352 
353 		/* done when [7:6] are set */
354 		if ((tmp_val & 0xc0) == 0xc0)
355 			break;
356 
357 		ret = fc2580_wr_reg(priv, 0x2e, 0x01);
358 		if (ret < 0)
359 			goto err;
360 
361 		ret = fc2580_wr_reg(priv, 0x2e, 0x09);
362 		if (ret < 0)
363 			goto err;
364 
365 		usleep_range(5000, 25000);
366 	}
367 
368 	dev_dbg(&priv->i2c->dev, "%s: loop=%i\n", __func__, i);
369 
370 	ret = fc2580_wr_reg(priv, 0x2e, 0x01);
371 	if (ret < 0)
372 		goto err;
373 
374 	if (fe->ops.i2c_gate_ctrl)
375 		fe->ops.i2c_gate_ctrl(fe, 0);
376 
377 	return 0;
378 err:
379 	if (fe->ops.i2c_gate_ctrl)
380 		fe->ops.i2c_gate_ctrl(fe, 0);
381 
382 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
383 	return ret;
384 }
385 
386 static int fc2580_init(struct dvb_frontend *fe)
387 {
388 	struct fc2580_priv *priv = fe->tuner_priv;
389 	int ret, i;
390 
391 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
392 
393 	if (fe->ops.i2c_gate_ctrl)
394 		fe->ops.i2c_gate_ctrl(fe, 1);
395 
396 	for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) {
397 		ret = fc2580_wr_reg(priv, fc2580_init_reg_vals[i].reg,
398 				fc2580_init_reg_vals[i].val);
399 		if (ret < 0)
400 			goto err;
401 	}
402 
403 	if (fe->ops.i2c_gate_ctrl)
404 		fe->ops.i2c_gate_ctrl(fe, 0);
405 
406 	return 0;
407 err:
408 	if (fe->ops.i2c_gate_ctrl)
409 		fe->ops.i2c_gate_ctrl(fe, 0);
410 
411 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
412 	return ret;
413 }
414 
415 static int fc2580_sleep(struct dvb_frontend *fe)
416 {
417 	struct fc2580_priv *priv = fe->tuner_priv;
418 	int ret;
419 
420 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
421 
422 	if (fe->ops.i2c_gate_ctrl)
423 		fe->ops.i2c_gate_ctrl(fe, 1);
424 
425 	ret = fc2580_wr_reg(priv, 0x02, 0x0a);
426 	if (ret < 0)
427 		goto err;
428 
429 	if (fe->ops.i2c_gate_ctrl)
430 		fe->ops.i2c_gate_ctrl(fe, 0);
431 
432 	return 0;
433 err:
434 	if (fe->ops.i2c_gate_ctrl)
435 		fe->ops.i2c_gate_ctrl(fe, 0);
436 
437 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
438 	return ret;
439 }
440 
441 static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
442 {
443 	struct fc2580_priv *priv = fe->tuner_priv;
444 
445 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
446 
447 	*frequency = 0; /* Zero-IF */
448 
449 	return 0;
450 }
451 
452 static int fc2580_release(struct dvb_frontend *fe)
453 {
454 	struct fc2580_priv *priv = fe->tuner_priv;
455 
456 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
457 
458 	kfree(fe->tuner_priv);
459 
460 	return 0;
461 }
462 
463 static const struct dvb_tuner_ops fc2580_tuner_ops = {
464 	.info = {
465 		.name           = "FCI FC2580",
466 		.frequency_min  = 174000000,
467 		.frequency_max  = 862000000,
468 	},
469 
470 	.release = fc2580_release,
471 
472 	.init = fc2580_init,
473 	.sleep = fc2580_sleep,
474 	.set_params = fc2580_set_params,
475 
476 	.get_if_frequency = fc2580_get_if_frequency,
477 };
478 
479 struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
480 		struct i2c_adapter *i2c, const struct fc2580_config *cfg)
481 {
482 	struct fc2580_priv *priv;
483 	int ret;
484 	u8 chip_id;
485 
486 	if (fe->ops.i2c_gate_ctrl)
487 		fe->ops.i2c_gate_ctrl(fe, 1);
488 
489 	priv = kzalloc(sizeof(struct fc2580_priv), GFP_KERNEL);
490 	if (!priv) {
491 		ret = -ENOMEM;
492 		dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
493 		goto err;
494 	}
495 
496 	priv->cfg = cfg;
497 	priv->i2c = i2c;
498 
499 	/* check if the tuner is there */
500 	ret = fc2580_rd_reg(priv, 0x01, &chip_id);
501 	if (ret < 0)
502 		goto err;
503 
504 	dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
505 
506 	switch (chip_id) {
507 	case 0x56:
508 	case 0x5a:
509 		break;
510 	default:
511 		goto err;
512 	}
513 
514 	dev_info(&priv->i2c->dev,
515 			"%s: FCI FC2580 successfully identified\n",
516 			KBUILD_MODNAME);
517 
518 	fe->tuner_priv = priv;
519 	memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
520 			sizeof(struct dvb_tuner_ops));
521 
522 	if (fe->ops.i2c_gate_ctrl)
523 		fe->ops.i2c_gate_ctrl(fe, 0);
524 
525 	return fe;
526 err:
527 	if (fe->ops.i2c_gate_ctrl)
528 		fe->ops.i2c_gate_ctrl(fe, 0);
529 
530 	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
531 	kfree(priv);
532 	return NULL;
533 }
534 EXPORT_SYMBOL(fc2580_attach);
535 
536 MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver");
537 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
538 MODULE_LICENSE("GPL");
539