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