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