Merge branch 'next/cleanup-samsung' into next/cleanup-samsung-2
[firefly-linux-kernel-4.4.55.git] / 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, xdiv, xdivr;
187         u16 frac;
188         u8 fa, fp, vco_sel, vco_cal;
189         u8 regs[FC11_NR_REGS] = { };
190
191         regs[FC11_REG_7] = 0x0F;
192         regs[FC11_REG_8] = 0x3E;
193         regs[FC11_REG_10] = 0xB8;
194         regs[FC11_REG_11] = 0x80;
195         regs[FC11_REG_RCCAL] = 0x04;
196         err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
197         err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
198         err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
199         err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
200         err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
201         if (err)
202                 return -EIO;
203
204         /* Set VCO freq and VCO div */
205         if (freq < 54000) {
206                 fvco = freq * 64;
207                 regs[FC11_REG_VCO] = 0x82;
208         } else if (freq < 108000) {
209                 fvco = freq * 32;
210                 regs[FC11_REG_VCO] = 0x42;
211         } else if (freq < 216000) {
212                 fvco = freq * 16;
213                 regs[FC11_REG_VCO] = 0x22;
214         } else if (freq < 432000) {
215                 fvco = freq * 8;
216                 regs[FC11_REG_VCO] = 0x12;
217         } else {
218                 fvco = freq * 4;
219                 regs[FC11_REG_VCO] = 0x0A;
220         }
221
222         /* Calc XIN. The PLL reference frequency is 18 MHz. */
223         xdiv = fvco / 18000;
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 if (frac < 511)
231                 xin = 512;
232         else if (frac < 65026)
233                 xin = frac;
234         else
235                 xin = 65024;
236         regs[FC11_REG_XINHI] = xin >> 8;
237         regs[FC11_REG_XINLO] = xin;
238
239         /* Calc FP and FA */
240         xdivr = xdiv;
241         if (fvco - xdiv * 18000 >= 9000)
242                 xdivr += 1; /* round */
243         fp = xdivr / 8;
244         fa = xdivr - fp * 8;
245         if (fa < 2) {
246                 fp -= 1;
247                 fa += 8;
248         }
249         if (fp > 0x1F) {
250                 fp &= 0x1F;
251                 fa &= 0xF;
252         }
253         if (fa >= fp) {
254                 dev_warn(&priv->i2c->dev,
255                          "fa %02X >= fp %02X, but trying to continue\n",
256                          (unsigned int)(u8)fa, (unsigned int)(u8)fp);
257         }
258         regs[FC11_REG_FA] = fa;
259         regs[FC11_REG_FP] = fp;
260
261         /* Select bandwidth */
262         switch (bandwidth) {
263         case 8000:
264                 break;
265         case 7000:
266                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
267                 break;
268         default:
269                 dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. "
270                          "Using 6000 kHz.\n",
271                          bandwidth);
272                 bandwidth = 6000;
273                 /* fallthrough */
274         case 6000:
275                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M;
276                 break;
277         }
278
279         /* Pre VCO select */
280         if (fvco < 2320000) {
281                 vco_sel = 0;
282                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
283         } else if (fvco < 3080000) {
284                 vco_sel = 1;
285                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
286                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
287         } else {
288                 vco_sel = 2;
289                 regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
290                 regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
291         }
292
293         /* Fix for low freqs */
294         if (freq < 45000) {
295                 regs[FC11_REG_FA] = 0x6;
296                 regs[FC11_REG_FP] = 0x11;
297         }
298
299         /* Clock out fix */
300         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT;
301
302         /* Write the cached registers */
303         for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) {
304                 err = fc0011_writereg(priv, i, regs[i]);
305                 if (err)
306                         return err;
307         }
308
309         /* VCO calibration */
310         err = fc0011_vcocal_trigger(priv);
311         if (err)
312                 return err;
313         err = fc0011_vcocal_read(priv, &vco_cal);
314         if (err)
315                 return err;
316         vco_retries = 0;
317         while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) {
318                 /* Reset the tuner and try again */
319                 err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
320                                    FC0011_FE_CALLBACK_RESET, priv->addr);
321                 if (err) {
322                         dev_err(&priv->i2c->dev, "Failed to reset tuner\n");
323                         return err;
324                 }
325                 /* Reinit tuner config */
326                 err = 0;
327                 for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++)
328                         err |= fc0011_writereg(priv, i, regs[i]);
329                 err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
330                 err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
331                 err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
332                 err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
333                 err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
334                 if (err)
335                         return -EIO;
336                 /* VCO calibration */
337                 err = fc0011_vcocal_trigger(priv);
338                 if (err)
339                         return err;
340                 err = fc0011_vcocal_read(priv, &vco_cal);
341                 if (err)
342                         return err;
343                 vco_retries++;
344         }
345         if (!(vco_cal & FC11_VCOCAL_OK)) {
346                 dev_err(&priv->i2c->dev,
347                         "Failed to read VCO calibration value (got %02X)\n",
348                         (unsigned int)vco_cal);
349                 return -EIO;
350         }
351         vco_cal &= FC11_VCOCAL_VALUEMASK;
352
353         switch (vco_sel) {
354         case 0:
355                 if (vco_cal < 8) {
356                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
357                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
358                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
359                                               regs[FC11_REG_VCOSEL]);
360                         if (err)
361                                 return err;
362                         err = fc0011_vcocal_trigger(priv);
363                         if (err)
364                                 return err;
365                 } else {
366                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
367                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
368                                               regs[FC11_REG_VCOSEL]);
369                         if (err)
370                                 return err;
371                 }
372                 break;
373         case 1:
374                 if (vco_cal < 5) {
375                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
376                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
377                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
378                                               regs[FC11_REG_VCOSEL]);
379                         if (err)
380                                 return err;
381                         err = fc0011_vcocal_trigger(priv);
382                         if (err)
383                                 return err;
384                 } else if (vco_cal <= 48) {
385                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
386                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
387                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
388                                               regs[FC11_REG_VCOSEL]);
389                         if (err)
390                                 return err;
391                 } else {
392                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
393                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
394                                               regs[FC11_REG_VCOSEL]);
395                         if (err)
396                                 return err;
397                         err = fc0011_vcocal_trigger(priv);
398                         if (err)
399                                 return err;
400                 }
401                 break;
402         case 2:
403                 if (vco_cal > 53) {
404                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
405                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
406                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
407                                               regs[FC11_REG_VCOSEL]);
408                         if (err)
409                                 return err;
410                         err = fc0011_vcocal_trigger(priv);
411                         if (err)
412                                 return err;
413                 } else {
414                         regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
415                         regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
416                         err = fc0011_writereg(priv, FC11_REG_VCOSEL,
417                                               regs[FC11_REG_VCOSEL]);
418                         if (err)
419                                 return err;
420                 }
421                 break;
422         }
423         err = fc0011_vcocal_read(priv, NULL);
424         if (err)
425                 return err;
426         usleep_range(10000, 50000);
427
428         err = fc0011_readreg(priv, FC11_REG_RCCAL, &regs[FC11_REG_RCCAL]);
429         if (err)
430                 return err;
431         regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE;
432         err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
433         if (err)
434                 return err;
435         err = fc0011_writereg(priv, FC11_REG_16, 0xB);
436         if (err)
437                 return err;
438
439         dev_dbg(&priv->i2c->dev, "Tuned to "
440                 "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X "
441                 "vcocal=%02X(%u) bw=%u\n",
442                 (unsigned int)regs[FC11_REG_FA],
443                 (unsigned int)regs[FC11_REG_FP],
444                 (unsigned int)regs[FC11_REG_XINHI],
445                 (unsigned int)regs[FC11_REG_XINLO],
446                 (unsigned int)regs[FC11_REG_VCO],
447                 (unsigned int)regs[FC11_REG_VCOSEL],
448                 (unsigned int)vco_cal, vco_retries,
449                 (unsigned int)bandwidth);
450
451         priv->frequency = p->frequency;
452         priv->bandwidth = p->bandwidth_hz;
453
454         return 0;
455 }
456
457 static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency)
458 {
459         struct fc0011_priv *priv = fe->tuner_priv;
460
461         *frequency = priv->frequency;
462
463         return 0;
464 }
465
466 static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
467 {
468         *frequency = 0;
469
470         return 0;
471 }
472
473 static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
474 {
475         struct fc0011_priv *priv = fe->tuner_priv;
476
477         *bandwidth = priv->bandwidth;
478
479         return 0;
480 }
481
482 static const struct dvb_tuner_ops fc0011_tuner_ops = {
483         .info = {
484                 .name           = "Fitipower FC0011",
485
486                 .frequency_min  = 45000000,
487                 .frequency_max  = 1000000000,
488         },
489
490         .release                = fc0011_release,
491         .init                   = fc0011_init,
492
493         .set_params             = fc0011_set_params,
494
495         .get_frequency          = fc0011_get_frequency,
496         .get_if_frequency       = fc0011_get_if_frequency,
497         .get_bandwidth          = fc0011_get_bandwidth,
498 };
499
500 struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
501                                    struct i2c_adapter *i2c,
502                                    const struct fc0011_config *config)
503 {
504         struct fc0011_priv *priv;
505
506         priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL);
507         if (!priv)
508                 return NULL;
509
510         priv->i2c = i2c;
511         priv->addr = config->i2c_address;
512
513         fe->tuner_priv = priv;
514         fe->ops.tuner_ops = fc0011_tuner_ops;
515
516         dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n");
517
518         return fe;
519 }
520 EXPORT_SYMBOL(fc0011_attach);
521
522 MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
523 MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
524 MODULE_LICENSE("GPL");