Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / tuners / fc0012.c
1 /*
2  * Fitipower FC0012 tuner driver
3  *
4  * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
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
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "fc0012.h"
22 #include "fc0012-priv.h"
23
24 static int fc0012_writereg(struct fc0012_priv *priv, u8 reg, u8 val)
25 {
26         u8 buf[2] = {reg, val};
27         struct i2c_msg msg = {
28                 .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
29         };
30
31         if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
32                 dev_err(&priv->i2c->dev,
33                         "%s: I2C write reg failed, reg: %02x, val: %02x\n",
34                         KBUILD_MODNAME, reg, val);
35                 return -EREMOTEIO;
36         }
37         return 0;
38 }
39
40 static int fc0012_readreg(struct fc0012_priv *priv, u8 reg, u8 *val)
41 {
42         struct i2c_msg msg[2] = {
43                 { .addr = priv->cfg->i2c_address, .flags = 0,
44                         .buf = &reg, .len = 1 },
45                 { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
46                         .buf = val, .len = 1 },
47         };
48
49         if (i2c_transfer(priv->i2c, msg, 2) != 2) {
50                 dev_err(&priv->i2c->dev,
51                         "%s: I2C read reg failed, reg: %02x\n",
52                         KBUILD_MODNAME, reg);
53                 return -EREMOTEIO;
54         }
55         return 0;
56 }
57
58 static int fc0012_release(struct dvb_frontend *fe)
59 {
60         kfree(fe->tuner_priv);
61         fe->tuner_priv = NULL;
62         return 0;
63 }
64
65 static int fc0012_init(struct dvb_frontend *fe)
66 {
67         struct fc0012_priv *priv = fe->tuner_priv;
68         int i, ret = 0;
69         unsigned char reg[] = {
70                 0x00,   /* dummy reg. 0 */
71                 0x05,   /* reg. 0x01 */
72                 0x10,   /* reg. 0x02 */
73                 0x00,   /* reg. 0x03 */
74                 0x00,   /* reg. 0x04 */
75                 0x0f,   /* reg. 0x05: may also be 0x0a */
76                 0x00,   /* reg. 0x06: divider 2, VCO slow */
77                 0x00,   /* reg. 0x07: may also be 0x0f */
78                 0xff,   /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256,
79                            Loop Bw 1/8 */
80                 0x6e,   /* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */
81                 0xb8,   /* reg. 0x0a: Disable LO Test Buffer */
82                 0x82,   /* reg. 0x0b: Output Clock is same as clock frequency,
83                            may also be 0x83 */
84                 0xfc,   /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
85                 0x02,   /* reg. 0x0d: AGC Not Forcing & LNA Forcing, 0x02 for DVB-T */
86                 0x00,   /* reg. 0x0e */
87                 0x00,   /* reg. 0x0f */
88                 0x00,   /* reg. 0x10: may also be 0x0d */
89                 0x00,   /* reg. 0x11 */
90                 0x1f,   /* reg. 0x12: Set to maximum gain */
91                 0x08,   /* reg. 0x13: Set to Middle Gain: 0x08,
92                            Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */
93                 0x00,   /* reg. 0x14 */
94                 0x04,   /* reg. 0x15: Enable LNA COMPS */
95         };
96
97         switch (priv->cfg->xtal_freq) {
98         case FC_XTAL_27_MHZ:
99         case FC_XTAL_28_8_MHZ:
100                 reg[0x07] |= 0x20;
101                 break;
102         case FC_XTAL_36_MHZ:
103         default:
104                 break;
105         }
106
107         if (priv->cfg->dual_master)
108                 reg[0x0c] |= 0x02;
109
110         if (priv->cfg->loop_through)
111                 reg[0x09] |= 0x01;
112
113         if (fe->ops.i2c_gate_ctrl)
114                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
115
116         for (i = 1; i < sizeof(reg); i++) {
117                 ret = fc0012_writereg(priv, i, reg[i]);
118                 if (ret)
119                         break;
120         }
121
122         if (fe->ops.i2c_gate_ctrl)
123                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
124
125         if (ret)
126                 dev_err(&priv->i2c->dev, "%s: fc0012_writereg failed: %d\n",
127                                 KBUILD_MODNAME, ret);
128
129         return ret;
130 }
131
132 static int fc0012_set_params(struct dvb_frontend *fe)
133 {
134         struct fc0012_priv *priv = fe->tuner_priv;
135         int i, ret = 0;
136         struct dtv_frontend_properties *p = &fe->dtv_property_cache;
137         u32 freq = p->frequency / 1000;
138         u32 delsys = p->delivery_system;
139         unsigned char reg[7], am, pm, multi, tmp;
140         unsigned long f_vco;
141         unsigned short xtal_freq_khz_2, xin, xdiv;
142         bool vco_select = false;
143
144         if (fe->callback) {
145                 ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
146                         FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1));
147                 if (ret)
148                         goto exit;
149         }
150
151         switch (priv->cfg->xtal_freq) {
152         case FC_XTAL_27_MHZ:
153                 xtal_freq_khz_2 = 27000 / 2;
154                 break;
155         case FC_XTAL_36_MHZ:
156                 xtal_freq_khz_2 = 36000 / 2;
157                 break;
158         case FC_XTAL_28_8_MHZ:
159         default:
160                 xtal_freq_khz_2 = 28800 / 2;
161                 break;
162         }
163
164         /* select frequency divider and the frequency of VCO */
165         if (freq < 37084) {             /* freq * 96 < 3560000 */
166                 multi = 96;
167                 reg[5] = 0x82;
168                 reg[6] = 0x00;
169         } else if (freq < 55625) {      /* freq * 64 < 3560000 */
170                 multi = 64;
171                 reg[5] = 0x82;
172                 reg[6] = 0x02;
173         } else if (freq < 74167) {      /* freq * 48 < 3560000 */
174                 multi = 48;
175                 reg[5] = 0x42;
176                 reg[6] = 0x00;
177         } else if (freq < 111250) {     /* freq * 32 < 3560000 */
178                 multi = 32;
179                 reg[5] = 0x42;
180                 reg[6] = 0x02;
181         } else if (freq < 148334) {     /* freq * 24 < 3560000 */
182                 multi = 24;
183                 reg[5] = 0x22;
184                 reg[6] = 0x00;
185         } else if (freq < 222500) {     /* freq * 16 < 3560000 */
186                 multi = 16;
187                 reg[5] = 0x22;
188                 reg[6] = 0x02;
189         } else if (freq < 296667) {     /* freq * 12 < 3560000 */
190                 multi = 12;
191                 reg[5] = 0x12;
192                 reg[6] = 0x00;
193         } else if (freq < 445000) {     /* freq * 8 < 3560000 */
194                 multi = 8;
195                 reg[5] = 0x12;
196                 reg[6] = 0x02;
197         } else if (freq < 593334) {     /* freq * 6 < 3560000 */
198                 multi = 6;
199                 reg[5] = 0x0a;
200                 reg[6] = 0x00;
201         } else {
202                 multi = 4;
203                 reg[5] = 0x0a;
204                 reg[6] = 0x02;
205         }
206
207         f_vco = freq * multi;
208
209         if (f_vco >= 3060000) {
210                 reg[6] |= 0x08;
211                 vco_select = true;
212         }
213
214         if (freq >= 45000) {
215                 /* From divided value (XDIV) determined the FA and FP value */
216                 xdiv = (unsigned short)(f_vco / xtal_freq_khz_2);
217                 if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2))
218                         xdiv++;
219
220                 pm = (unsigned char)(xdiv / 8);
221                 am = (unsigned char)(xdiv - (8 * pm));
222
223                 if (am < 2) {
224                         reg[1] = am + 8;
225                         reg[2] = pm - 1;
226                 } else {
227                         reg[1] = am;
228                         reg[2] = pm;
229                 }
230         } else {
231                 /* fix for frequency less than 45 MHz */
232                 reg[1] = 0x06;
233                 reg[2] = 0x11;
234         }
235
236         /* fix clock out */
237         reg[6] |= 0x20;
238
239         /* From VCO frequency determines the XIN ( fractional part of Delta
240            Sigma PLL) and divided value (XDIV) */
241         xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2);
242         xin = (xin << 15) / xtal_freq_khz_2;
243         if (xin >= 16384)
244                 xin += 32768;
245
246         reg[3] = xin >> 8;      /* xin with 9 bit resolution */
247         reg[4] = xin & 0xff;
248
249         if (delsys == SYS_DVBT) {
250                 reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */
251                 switch (p->bandwidth_hz) {
252                 case 6000000:
253                         reg[6] |= 0x80;
254                         break;
255                 case 7000000:
256                         reg[6] |= 0x40;
257                         break;
258                 case 8000000:
259                 default:
260                         break;
261                 }
262         } else {
263                 dev_err(&priv->i2c->dev, "%s: modulation type not supported!\n",
264                                 KBUILD_MODNAME);
265                 return -EINVAL;
266         }
267
268         /* modified for Realtek demod */
269         reg[5] |= 0x07;
270
271         if (fe->ops.i2c_gate_ctrl)
272                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
273
274         for (i = 1; i <= 6; i++) {
275                 ret = fc0012_writereg(priv, i, reg[i]);
276                 if (ret)
277                         goto exit;
278         }
279
280         /* VCO Calibration */
281         ret = fc0012_writereg(priv, 0x0e, 0x80);
282         if (!ret)
283                 ret = fc0012_writereg(priv, 0x0e, 0x00);
284
285         /* VCO Re-Calibration if needed */
286         if (!ret)
287                 ret = fc0012_writereg(priv, 0x0e, 0x00);
288
289         if (!ret) {
290                 msleep(10);
291                 ret = fc0012_readreg(priv, 0x0e, &tmp);
292         }
293         if (ret)
294                 goto exit;
295
296         /* vco selection */
297         tmp &= 0x3f;
298
299         if (vco_select) {
300                 if (tmp > 0x3c) {
301                         reg[6] &= ~0x08;
302                         ret = fc0012_writereg(priv, 0x06, reg[6]);
303                         if (!ret)
304                                 ret = fc0012_writereg(priv, 0x0e, 0x80);
305                         if (!ret)
306                                 ret = fc0012_writereg(priv, 0x0e, 0x00);
307                 }
308         } else {
309                 if (tmp < 0x02) {
310                         reg[6] |= 0x08;
311                         ret = fc0012_writereg(priv, 0x06, reg[6]);
312                         if (!ret)
313                                 ret = fc0012_writereg(priv, 0x0e, 0x80);
314                         if (!ret)
315                                 ret = fc0012_writereg(priv, 0x0e, 0x00);
316                 }
317         }
318
319         priv->frequency = p->frequency;
320         priv->bandwidth = p->bandwidth_hz;
321
322 exit:
323         if (fe->ops.i2c_gate_ctrl)
324                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
325         if (ret)
326                 dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n",
327                                 KBUILD_MODNAME, __func__, ret);
328         return ret;
329 }
330
331 static int fc0012_get_frequency(struct dvb_frontend *fe, u32 *frequency)
332 {
333         struct fc0012_priv *priv = fe->tuner_priv;
334         *frequency = priv->frequency;
335         return 0;
336 }
337
338 static int fc0012_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
339 {
340         *frequency = 0; /* Zero-IF */
341         return 0;
342 }
343
344 static int fc0012_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
345 {
346         struct fc0012_priv *priv = fe->tuner_priv;
347         *bandwidth = priv->bandwidth;
348         return 0;
349 }
350
351 #define INPUT_ADC_LEVEL -8
352
353 static int fc0012_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
354 {
355         struct fc0012_priv *priv = fe->tuner_priv;
356         int ret;
357         unsigned char tmp;
358         int int_temp, lna_gain, int_lna, tot_agc_gain, power;
359         const int fc0012_lna_gain_table[] = {
360                 /* low gain */
361                 -63, -58, -99, -73,
362                 -63, -65, -54, -60,
363                 /* middle gain */
364                  71,  70,  68,  67,
365                  65,  63,  61,  58,
366                 /* high gain */
367                 197, 191, 188, 186,
368                 184, 182, 181, 179,
369         };
370
371         if (fe->ops.i2c_gate_ctrl)
372                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
373
374         ret = fc0012_writereg(priv, 0x12, 0x00);
375         if (ret)
376                 goto err;
377
378         ret = fc0012_readreg(priv, 0x12, &tmp);
379         if (ret)
380                 goto err;
381         int_temp = tmp;
382
383         ret = fc0012_readreg(priv, 0x13, &tmp);
384         if (ret)
385                 goto err;
386         lna_gain = tmp & 0x1f;
387
388         if (fe->ops.i2c_gate_ctrl)
389                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
390
391         if (lna_gain < ARRAY_SIZE(fc0012_lna_gain_table)) {
392                 int_lna = fc0012_lna_gain_table[lna_gain];
393                 tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 +
394                                 (int_temp & 0x1f)) * 2;
395                 power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10;
396
397                 if (power >= 45)
398                         *strength = 255;        /* 100% */
399                 else if (power < -95)
400                         *strength = 0;
401                 else
402                         *strength = (power + 95) * 255 / 140;
403
404                 *strength |= *strength << 8;
405         } else {
406                 ret = -1;
407         }
408
409         goto exit;
410
411 err:
412         if (fe->ops.i2c_gate_ctrl)
413                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
414 exit:
415         if (ret)
416                 dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n",
417                                 KBUILD_MODNAME, __func__, ret);
418         return ret;
419 }
420
421 static const struct dvb_tuner_ops fc0012_tuner_ops = {
422         .info = {
423                 .name           = "Fitipower FC0012",
424
425                 .frequency_min  = 37000000,     /* estimate */
426                 .frequency_max  = 862000000,    /* estimate */
427                 .frequency_step = 0,
428         },
429
430         .release        = fc0012_release,
431
432         .init           = fc0012_init,
433
434         .set_params     = fc0012_set_params,
435
436         .get_frequency  = fc0012_get_frequency,
437         .get_if_frequency = fc0012_get_if_frequency,
438         .get_bandwidth  = fc0012_get_bandwidth,
439
440         .get_rf_strength = fc0012_get_rf_strength,
441 };
442
443 struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
444         struct i2c_adapter *i2c, const struct fc0012_config *cfg)
445 {
446         struct fc0012_priv *priv;
447         int ret;
448         u8 chip_id;
449
450         if (fe->ops.i2c_gate_ctrl)
451                 fe->ops.i2c_gate_ctrl(fe, 1);
452
453         priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL);
454         if (!priv) {
455                 ret = -ENOMEM;
456                 dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
457                 goto err;
458         }
459
460         priv->cfg = cfg;
461         priv->i2c = i2c;
462
463         /* check if the tuner is there */
464         ret = fc0012_readreg(priv, 0x00, &chip_id);
465         if (ret < 0)
466                 goto err;
467
468         dev_dbg(&i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
469
470         switch (chip_id) {
471         case 0xa1:
472                 break;
473         default:
474                 ret = -ENODEV;
475                 goto err;
476         }
477
478         dev_info(&i2c->dev, "%s: Fitipower FC0012 successfully identified\n",
479                         KBUILD_MODNAME);
480
481         if (priv->cfg->loop_through) {
482                 ret = fc0012_writereg(priv, 0x09, 0x6f);
483                 if (ret < 0)
484                         goto err;
485         }
486
487         /*
488          * TODO: Clock out en or div?
489          * For dual tuner configuration clearing bit [0] is required.
490          */
491         if (priv->cfg->clock_out) {
492                 ret =  fc0012_writereg(priv, 0x0b, 0x82);
493                 if (ret < 0)
494                         goto err;
495         }
496
497         fe->tuner_priv = priv;
498         memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops,
499                 sizeof(struct dvb_tuner_ops));
500
501 err:
502         if (fe->ops.i2c_gate_ctrl)
503                 fe->ops.i2c_gate_ctrl(fe, 0);
504
505         if (ret) {
506                 dev_dbg(&i2c->dev, "%s: failed: %d\n", __func__, ret);
507                 kfree(priv);
508                 return NULL;
509         }
510
511         return fe;
512 }
513 EXPORT_SYMBOL(fc0012_attach);
514
515 MODULE_DESCRIPTION("Fitipower FC0012 silicon tuner driver");
516 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
517 MODULE_LICENSE("GPL");
518 MODULE_VERSION("0.6");