blob: afc04915f5ae97cf32edca1b39a4fd360b017009 [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;
118 int ret, i;
119 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
150 if (f_vco >= 2600000000)
151 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;
171 n_val = f_vco / f_ref;
172 k_val = f_vco % f_ref;
173 k_val_reg = 1UL * k_val * (1 << 20) / f_ref;
174
175 ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff));
176 if (ret < 0)
177 goto err;
178
179 ret = fc2580_wr_reg(priv, 0x1a, (k_val_reg >> 8) & 0xff);
180 if (ret < 0)
181 goto err;
182
183 ret = fc2580_wr_reg(priv, 0x1b, (k_val_reg >> 0) & 0xff);
184 if (ret < 0)
185 goto err;
186
187 ret = fc2580_wr_reg(priv, 0x1c, n_val);
188 if (ret < 0)
189 goto err;
190
191 if (priv->cfg->clock >= 28000000) {
192 ret = fc2580_wr_reg(priv, 0x4b, 0x22);
193 if (ret < 0)
194 goto err;
195 }
196
197 if (fc2580_pll_lut[i].band == 0x00) {
198 if (c->frequency <= 794000000)
199 tmp_val = 0x9f;
200 else
201 tmp_val = 0x8f;
202
203 ret = fc2580_wr_reg(priv, 0x2d, tmp_val);
204 if (ret < 0)
205 goto err;
206 }
207
208 /* registers */
209 for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) {
210 if (c->frequency <= fc2580_freq_regs_lut[i].freq)
211 break;
212 }
213
214 if (i == ARRAY_SIZE(fc2580_freq_regs_lut))
215 goto err;
216
217 ret = fc2580_wr_reg(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
218 if (ret < 0)
219 goto err;
220
221 ret = fc2580_wr_reg(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
222 if (ret < 0)
223 goto err;
224
225 ret = fc2580_wr_reg(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
226 if (ret < 0)
227 goto err;
228
229 ret = fc2580_wr_reg(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
230 if (ret < 0)
231 goto err;
232
233 ret = fc2580_wr_reg(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
234 if (ret < 0)
235 goto err;
236
237 ret = fc2580_wr_reg(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
238 if (ret < 0)
239 goto err;
240
241 ret = fc2580_wr_reg(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
242 if (ret < 0)
243 goto err;
244
245 ret = fc2580_wr_reg(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
246 if (ret < 0)
247 goto err;
248
249 ret = fc2580_wr_reg(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
250 if (ret < 0)
251 goto err;
252
253 ret = fc2580_wr_reg(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
254 if (ret < 0)
255 goto err;
256
257 ret = fc2580_wr_reg(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
258 if (ret < 0)
259 goto err;
260
261 ret = fc2580_wr_reg(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
262 if (ret < 0)
263 goto err;
264
265 ret = fc2580_wr_reg(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
266 if (ret < 0)
267 goto err;
268
269 ret = fc2580_wr_reg(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
270 if (ret < 0)
271 goto err;
272
273 ret = fc2580_wr_reg(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
274 if (ret < 0)
275 goto err;
276
277 ret = fc2580_wr_reg(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
278 if (ret < 0)
279 goto err;
280
281 ret = fc2580_wr_reg(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
282 if (ret < 0)
283 goto err;
284
285 ret = fc2580_wr_reg(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
286 if (ret < 0)
287 goto err;
288
289 ret = fc2580_wr_reg(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
290 if (ret < 0)
291 goto err;
292
293 ret = fc2580_wr_reg(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
294 if (ret < 0)
295 goto err;
296
297 ret = fc2580_wr_reg(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
298 if (ret < 0)
299 goto err;
300
301 ret = fc2580_wr_reg(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
302 if (ret < 0)
303 goto err;
304
305 ret = fc2580_wr_reg(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
306 if (ret < 0)
307 goto err;
308
309 ret = fc2580_wr_reg(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
310 if (ret < 0)
311 goto err;
312
313 /* IF filters */
314 for (i = 0; i < ARRAY_SIZE(fc2580_if_filter_lut); i++) {
315 if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq)
316 break;
317 }
318
319 if (i == ARRAY_SIZE(fc2580_if_filter_lut))
320 goto err;
321
322 ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val);
323 if (ret < 0)
324 goto err;
325
326 ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \
327 fc2580_if_filter_lut[i].mul / 1000000000);
328 if (ret < 0)
329 goto err;
330
331 ret = fc2580_wr_reg(priv, 0x39, fc2580_if_filter_lut[i].r39_val);
332 if (ret < 0)
333 goto err;
334
335 /* calibration? */
336 ret = fc2580_wr_reg(priv, 0x2e, 0x09);
337 if (ret < 0)
338 goto err;
339
340 for (i = 0; i < 5; i++) {
341 ret = fc2580_rd_reg(priv, 0x2f, &tmp_val);
342 if (ret < 0)
343 goto err;
344
345 /* done when [7:6] are set */
346 if ((tmp_val & 0xc0) == 0xc0)
347 break;
348
349 ret = fc2580_wr_reg(priv, 0x2e, 0x01);
350 if (ret < 0)
351 goto err;
352
353 ret = fc2580_wr_reg(priv, 0x2e, 0x09);
354 if (ret < 0)
355 goto err;
356
357 usleep_range(5000, 25000);
358 }
359
360 dev_dbg(&priv->i2c->dev, "%s: loop=%i\n", __func__, i);
361
362 ret = fc2580_wr_reg(priv, 0x2e, 0x01);
363 if (ret < 0)
364 goto err;
365
366 if (fe->ops.i2c_gate_ctrl)
367 fe->ops.i2c_gate_ctrl(fe, 0);
368
369 return 0;
370err:
371 if (fe->ops.i2c_gate_ctrl)
372 fe->ops.i2c_gate_ctrl(fe, 0);
373
374 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
375 return ret;
376}
377
378static int fc2580_init(struct dvb_frontend *fe)
379{
380 struct fc2580_priv *priv = fe->tuner_priv;
381 int ret, i;
382
383 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
384
385 if (fe->ops.i2c_gate_ctrl)
386 fe->ops.i2c_gate_ctrl(fe, 1);
387
388 for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) {
389 ret = fc2580_wr_reg(priv, fc2580_init_reg_vals[i].reg,
390 fc2580_init_reg_vals[i].val);
391 if (ret < 0)
392 goto err;
393 }
394
395 if (fe->ops.i2c_gate_ctrl)
396 fe->ops.i2c_gate_ctrl(fe, 0);
397
398 return 0;
399err:
400 if (fe->ops.i2c_gate_ctrl)
401 fe->ops.i2c_gate_ctrl(fe, 0);
402
403 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
404 return ret;
405}
406
407static int fc2580_sleep(struct dvb_frontend *fe)
408{
409 struct fc2580_priv *priv = fe->tuner_priv;
410 int ret;
411
412 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
413
414 if (fe->ops.i2c_gate_ctrl)
415 fe->ops.i2c_gate_ctrl(fe, 1);
416
417 ret = fc2580_wr_reg(priv, 0x02, 0x0a);
418 if (ret < 0)
419 goto err;
420
421 if (fe->ops.i2c_gate_ctrl)
422 fe->ops.i2c_gate_ctrl(fe, 0);
423
424 return 0;
425err:
426 if (fe->ops.i2c_gate_ctrl)
427 fe->ops.i2c_gate_ctrl(fe, 0);
428
429 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
430 return ret;
431}
432
433static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
434{
435 struct fc2580_priv *priv = fe->tuner_priv;
436
437 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
438
439 *frequency = 0; /* Zero-IF */
440
441 return 0;
442}
443
444static int fc2580_release(struct dvb_frontend *fe)
445{
446 struct fc2580_priv *priv = fe->tuner_priv;
447
448 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
449
450 kfree(fe->tuner_priv);
451
452 return 0;
453}
454
455static const struct dvb_tuner_ops fc2580_tuner_ops = {
456 .info = {
457 .name = "FCI FC2580",
458 .frequency_min = 174000000,
459 .frequency_max = 862000000,
460 },
461
462 .release = fc2580_release,
463
464 .init = fc2580_init,
465 .sleep = fc2580_sleep,
466 .set_params = fc2580_set_params,
467
468 .get_if_frequency = fc2580_get_if_frequency,
469};
470
471struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
472 struct i2c_adapter *i2c, const struct fc2580_config *cfg)
473{
474 struct fc2580_priv *priv;
475 int ret;
476 u8 chip_id;
477
478 if (fe->ops.i2c_gate_ctrl)
479 fe->ops.i2c_gate_ctrl(fe, 1);
480
481 priv = kzalloc(sizeof(struct fc2580_priv), GFP_KERNEL);
482 if (!priv) {
483 ret = -ENOMEM;
484 dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
485 goto err;
486 }
487
488 priv->cfg = cfg;
489 priv->i2c = i2c;
490 fe->tuner_priv = priv;
491 memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
492 sizeof(struct dvb_tuner_ops));
493
494 /* check if the tuner is there */
495 ret = fc2580_rd_reg(priv, 0x01, &chip_id);
496 if (ret < 0)
497 goto err;
498
499 dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
500
501 if (chip_id != 0x56)
502 goto err;
503
504 dev_info(&priv->i2c->dev,
505 "%s: FCI FC2580 successfully identified\n",
506 KBUILD_MODNAME);
507
508 if (fe->ops.i2c_gate_ctrl)
509 fe->ops.i2c_gate_ctrl(fe, 0);
510
511 return fe;
512err:
513 if (fe->ops.i2c_gate_ctrl)
514 fe->ops.i2c_gate_ctrl(fe, 0);
515
516 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
517 kfree(priv);
518 return NULL;
519}
520EXPORT_SYMBOL(fc2580_attach);
521
522MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver");
523MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
524MODULE_LICENSE("GPL");