Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / tuners / fc0011.c
1 /*
2  * Fitipower FC0011 tuner driver
3  *
4  * Copyright (C) 2012 Michael Buesch <m@bues.ch>
5  *
6  * Derived from FC0012 tuner driver:
7  * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "fc0011.h"
25
26
27 /* Tuner registers */
28 enum {
29         FC11_REG_0,
30         FC11_REG_FA,            /* FA */
31         FC11_REG_FP,            /* FP */
32         FC11_REG_XINHI,         /* XIN high 8 bit */
33         FC11_REG_XINLO,         /* XIN low 8 bit */
34         FC11_REG_VCO,           /* VCO */
35         FC11_REG_VCOSEL,        /* VCO select */
36         FC11_REG_7,             /* Unknown tuner reg 7 */
37         FC11_REG_8,             /* Unknown tuner reg 8 */
38         FC11_REG_9,
39         FC11_REG_10,            /* Unknown tuner reg 10 */
40         FC11_REG_11,            /* Unknown tuner reg 11 */
41         FC11_REG_12,
42         FC11_REG_RCCAL,         /* RC calibrate */
43         FC11_REG_VCOCAL,        /* VCO calibrate */
44         FC11_REG_15,
45         FC11_REG_16,            /* Unknown tuner reg 16 */
46         FC11_REG_17,
47
48         FC11_NR_REGS,           /* Number of registers */
49 };
50
51 enum FC11_REG_VCOSEL_bits {
52         FC11_VCOSEL_2           = 0x08, /* VCO select 2 */
53         FC11_VCOSEL_1           = 0x10, /* VCO select 1 */
54         FC11_VCOSEL_CLKOUT      = 0x20, /* Fix clock out */
55         FC11_VCOSEL_BW7M        = 0x40, /* 7MHz bw */
56         FC11_VCOSEL_BW6M        = 0x80, /* 6MHz bw */
57 };
58
59 enum FC11_REG_RCCAL_bits {
60         FC11_RCCAL_FORCE        = 0x10, /* force */
61 };
62
63 enum FC11_REG_VCOCAL_bits {
64         FC11_VCOCAL_RUN         = 0,    /* VCO calibration run */
65         FC11_VCOCAL_VALUEMASK   = 0x3F, /* VCO calibration value mask */
66         FC11_VCOCAL_OK          = 0x40, /* VCO calibration Ok */
67         FC11_VCOCAL_RESET       = 0x80, /* VCO calibration reset */
68 };
69
70
71 struct fc0011_priv {
72         struct i2c_adapter *i2c;
73         u8 addr;
74
75         u32 frequency;
76         u32 bandwidth;
77 };
78
79
80 static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val)
81 {
82         u8 buf[2] = { reg, val };
83         struct i2c_msg msg = { .addr = priv->addr,
84                 .flags = 0, .buf = buf, .len = 2 };
85
86         if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
87                 dev_err(&priv->i2c->dev,
88                         "I2C write reg failed, reg: %02x, val: %02x\n",
89                         reg, val);
90                 return -EIO;
91         }
92
93         return 0;
94 }
95
96 static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val)
97 {
98         u8 dummy;
99         struct i2c_msg msg[2] = {
100                 { .addr = priv->addr,
101                   .flags = 0, .buf = &reg, .len = 1 },
102                 { .addr = priv->addr,
103                   .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 },
104         };
105
106         if (i2c_transfer(priv->i2c, msg, 2) != 2) {
107                 dev_err(&priv->i2c->dev,
108                         "I2C read failed, reg: %02x\n", reg);
109                 return -EIO;
110         }
111
112         return 0;
113 }
114
115 static int fc0011_release(struct dvb_frontend *fe)
116 {
117         kfree(fe->tuner_priv);
118         fe->tuner_priv = NULL;
119
120         return 0;
121 }
122
123 static int fc0011_init(struct dvb_frontend *fe)
124 {
125         struct fc0011_priv *priv = fe->tuner_priv;
126         int err;
127
128         if (WARN_ON(!fe->callback))
129                 return -EINVAL;
130
131         err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
132                            FC0011_FE_CALLBACK_POWER, priv->addr);
133         if (err) {
134                 dev_err(&priv->i2c->dev, "Power-on callback failed\n");
135                 return err;
136         }
137         err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
138                            FC0011_FE_CALLBACK_RESET, priv->addr);
139         if (err) {
140                 dev_err(&priv->i2c->dev, "Reset callback failed\n");
141                 return err;
142         }
143
144         return 0;
145 }
146
147 /* Initiate VCO calibration */
148 static int fc0011_vcocal_trigger(struct fc0011_priv *priv)
149 {
150         int err;
151
152         err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET);
153         if (err)
154                 return err;
155         err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
156         if (err)
157                 return err;
158
159         return 0;
160 }
161
162 /* Read VCO calibration value */
163 static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value)
164 {
165         int err;
166
167         err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
168         if (err)
169                 return err;
170         usleep_range(10000, 20000);
171         err = fc0011_readreg(priv, FC11_REG_VCOCAL, value);
172         if (err)
173                 return err;
174
175         return 0;
176 }
177
178 static int fc0011_set_params(struct dvb_frontend *fe)
179 {
180         struct dtv_frontend_properties *p = &fe->dtv_property_cache;
181         struct fc0011_priv *priv = fe->tuner_priv;
182         int err;
183         unsigned int i, vco_retries;
184         u32 freq = p->frequency / 1000;
185         u32 bandwidth = p->bandwidth_hz / 1000;
186         u32 fvco, xin, frac, xdiv, xdivr;
187         u8 fa, fp, vco_sel, vco_cal;
188         u8 regs[FC11_NR_REGS] = { };
189
190         regs[FC11_REG_7] = 0x0F;
191         regs[FC11_REG_8] = 0x3E;
192         regs[FC11_REG_10] = 0xB8;
193         regs[FC11_REG_11] = 0x80;
194         regs[FC11_REG_RCCAL] = 0x04;
195         err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
196         err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
197         err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
198         err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
199         err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
200         if (err)
201                 return -EIO;
202
203         /* Set VCO freq and VCO div */
204         if (freq < 54000) {
205                 fvco = freq * 64;
206                 regs[FC11_REG_VCO] = 0x82;
207         } else if (freq < 108000) {
208                 fvco = freq * 32;
209                 regs[FC11_REG_VCO] = 0x42;
210         } else if (freq < 216000) {
211                 fvco = freq * 16;
212                 regs[FC11_REG_VCO] = 0x22;
213         } else if (freq < 432000) {
214                 fvco = freq * 8;
215                 regs[FC11_REG_VCO] = 0x12;
216         } else {
217                 fvco = freq * 4;
218                 regs[FC11_REG_VCO] = 0x0A;
219         }
220
221         /* Calc XIN. The PLL reference frequency is 18 MHz. */
222         xdiv = fvco / 18000;
223         WARN_ON(xdiv > 0xFF);
224         frac = fvco - xdiv * 18000;
225         frac = (frac << 15) / 18000;
226         if (frac >= 16384)
227                 frac += 32786;
228         if (!frac)
229                 xin = 0;
230         else
231                 xin = clamp_t(u32, frac, 512, 65024);
232         regs[FC11_REG_XINHI] = xin >> 8;
233         regs[FC11_REG_XINLO] = xin;
234
235         /* Calc FP and FA */
236         xdivr = xdiv;
237         if (fvco - xdiv * 18000 >= 9000)
238                 xdivr += 1; /* round */
239         fp = xdivr / 8;
240         fa = xdivr - fp * 8;
241         if (fa < 2) {
242                 fp -= 1;
243                 fa += 8;
244         }
245         if (fp > 0x1F) {
246                 fp = 0x1F;
247                 fa = 0xF;
248         }
249         if (fa >= fp) {
250                 dev_warn(&priv->i2c->dev,
251                          "fa %02X >= fp %02X, but trying to continue\n",
252                          (unsigned int)(u8)fa, (unsigned int)(u8)fp);
253         }
254         regs[FC11_REG_FA] = fa;
255         regs[FC11_REG_FP] = fp;
256
257         /* Select bandwidth */
258         switch (bandwidth) {
259         case 8000:
260                 break;
261         case 7000:
262                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
263                 break;
264         default:
265                 dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. "
266                          "Using 6000 kHz.\n",
267                          bandwidth);
268                 bandwidth = 6000;
269                 /* fallthrough */
270         case 6000:
271                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M;
272                 break;
273         }
274
275         /* Pre VCO select */
276         if (fvco < 2320000) {
277                 vco_sel = 0;
278                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
279         } else if (fvco < 3080000) {
280                 vco_sel = 1;
281                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
282                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
283         } else {
284                 vco_sel = 2;
285                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
286                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
287         }
288
289         /* Fix for low freqs */
290         if (freq < 45000) {
291                 regs[FC11_REG_FA] = 0x6;
292                 regs[FC11_REG_FP] = 0x11;
293         }
294
295         /* Clock out fix */
296         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT;
297
298         /* Write the cached registers */
299         for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) {
300                 err = fc0011_writereg(priv, i, regs[i]);
301                 if (err)
302                         return err;
303         }
304
305         /* VCO calibration */
306         err = fc0011_vcocal_trigger(priv);
307         if (err)
308                 return err;
309         err = fc0011_vcocal_read(priv, &vco_cal);
310         if (err)
311                 return err;
312         vco_retries = 0;
313         while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) {
314                 /* Reset the tuner and try again */
315                 err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
316                                    FC0011_FE_CALLBACK_RESET, priv->addr);
317                 if (err) {
318                         dev_err(&priv->i2c->dev, "Failed to reset tuner\n");
319                         return err;
320                 }
321                 /* Reinit tuner config */
322                 err = 0;
323                 for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++)
324                         err |= fc0011_writereg(priv, i, regs[i]);
325                 err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
326                 err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
327                 err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
328                 err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
329                 err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
330                 if (err)
331                         return -EIO;
332                 /* VCO calibration */
333                 err = fc0011_vcocal_trigger(priv);
334                 if (err)
335                         return err;
336                 err = fc0011_vcocal_read(priv, &vco_cal);
337                 if (err)
338                         return err;
339                 vco_retries++;
340         }
341         if (!(vco_cal & FC11_VCOCAL_OK)) {
342                 dev_err(&priv->i2c->dev,
343                         "Failed to read VCO calibration value (got %02X)\n",
344                         (unsigned int)vco_cal);
345                 return -EIO;
346         }
347         vco_cal &= FC11_VCOCAL_VALUEMASK;
348
349         switch (vco_sel) {
350         default:
351                 WARN_ON(1);
352         case 0:
353                 if (vco_cal < 8) {
354                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
355                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
356                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
357                                               regs[FC11_REG_VCOSEL]);
358                         if (err)
359                                 return err;
360                         err = fc0011_vcocal_trigger(priv);
361                         if (err)
362                                 return err;
363                 } else {
364                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
365                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
366                                               regs[FC11_REG_VCOSEL]);
367                         if (err)
368                                 return err;
369                 }
370                 break;
371         case 1:
372                 if (vco_cal < 5) {
373                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
374                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
375                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
376                                               regs[FC11_REG_VCOSEL]);
377                         if (err)
378                                 return err;
379                         err = fc0011_vcocal_trigger(priv);
380                         if (err)
381                                 return err;
382                 } else if (vco_cal <= 48) {
383                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
384                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
385                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
386                                               regs[FC11_REG_VCOSEL]);
387                         if (err)
388                                 return err;
389                 } else {
390                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
391                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
392                                               regs[FC11_REG_VCOSEL]);
393                         if (err)
394                                 return err;
395                         err = fc0011_vcocal_trigger(priv);
396                         if (err)
397                                 return err;
398                 }
399                 break;
400         case 2:
401                 if (vco_cal > 53) {
402                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
403                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
404                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
405                                               regs[FC11_REG_VCOSEL]);
406                         if (err)
407                                 return err;
408                         err = fc0011_vcocal_trigger(priv);
409                         if (err)
410                                 return err;
411                 } else {
412                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
413                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
414                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
415                                               regs[FC11_REG_VCOSEL]);
416                         if (err)
417                                 return err;
418                 }
419                 break;
420         }
421         err = fc0011_vcocal_read(priv, NULL);
422         if (err)
423                 return err;
424         usleep_range(10000, 50000);
425
426         err = fc0011_readreg(priv, FC11_REG_RCCAL, &regs[FC11_REG_RCCAL]);
427         if (err)
428                 return err;
429         regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE;
430         err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
431         if (err)
432                 return err;
433         regs[FC11_REG_16] = 0xB;
434         err = fc0011_writereg(priv, FC11_REG_16, regs[FC11_REG_16]);
435         if (err)
436                 return err;
437
438         dev_dbg(&priv->i2c->dev, "Tuned to "
439                 "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X "
440                 "vcocal=%02X(%u) bw=%u\n",
441                 (unsigned int)regs[FC11_REG_FA],
442                 (unsigned int)regs[FC11_REG_FP],
443                 (unsigned int)regs[FC11_REG_XINHI],
444                 (unsigned int)regs[FC11_REG_XINLO],
445                 (unsigned int)regs[FC11_REG_VCO],
446                 (unsigned int)regs[FC11_REG_VCOSEL],
447                 (unsigned int)vco_cal, vco_retries,
448                 (unsigned int)bandwidth);
449
450         priv->frequency = p->frequency;
451         priv->bandwidth = p->bandwidth_hz;
452
453         return 0;
454 }
455
456 static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency)
457 {
458         struct fc0011_priv *priv = fe->tuner_priv;
459
460         *frequency = priv->frequency;
461
462         return 0;
463 }
464
465 static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
466 {
467         *frequency = 0;
468
469         return 0;
470 }
471
472 static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
473 {
474         struct fc0011_priv *priv = fe->tuner_priv;
475
476         *bandwidth = priv->bandwidth;
477
478         return 0;
479 }
480
481 static const struct dvb_tuner_ops fc0011_tuner_ops = {
482         .info = {
483                 .name           = "Fitipower FC0011",
484
485                 .frequency_min  = 45000000,
486                 .frequency_max  = 1000000000,
487         },
488
489         .release                = fc0011_release,
490         .init                   = fc0011_init,
491
492         .set_params             = fc0011_set_params,
493
494         .get_frequency          = fc0011_get_frequency,
495         .get_if_frequency       = fc0011_get_if_frequency,
496         .get_bandwidth          = fc0011_get_bandwidth,
497 };
498
499 struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
500                                    struct i2c_adapter *i2c,
501                                    const struct fc0011_config *config)
502 {
503         struct fc0011_priv *priv;
504
505         priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL);
506         if (!priv)
507                 return NULL;
508
509         priv->i2c = i2c;
510         priv->addr = config->i2c_address;
511
512         fe->tuner_priv = priv;
513         fe->ops.tuner_ops = fc0011_tuner_ops;
514
515         dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n");
516
517         return fe;
518 }
519 EXPORT_SYMBOL(fc0011_attach);
520
521 MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
522 MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
523 MODULE_LICENSE("GPL");