Merge tag 'afs-fixes-b-20190516' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / media / tuners / fc0013.c
1 /*
2  * Fitipower FC0013 tuner driver
3  *
4  * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
5  * partially based on driver code from Fitipower
6  * Copyright (C) 2010 Fitipower Integrated Technology Inc
7  *
8  *    This program is free software; you can redistribute it and/or modify
9  *    it under the terms of the GNU General Public License as published by
10  *    the Free Software Foundation; either version 2 of the License, or
11  *    (at your option) any later version.
12  *
13  *    This program is distributed in the hope that it will be useful,
14  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *    GNU General Public License for more details.
17  *
18  */
19
20 #include "fc0013.h"
21 #include "fc0013-priv.h"
22
23 static int fc0013_writereg(struct fc0013_priv *priv, u8 reg, u8 val)
24 {
25         u8 buf[2] = {reg, val};
26         struct i2c_msg msg = {
27                 .addr = priv->addr, .flags = 0, .buf = buf, .len = 2
28         };
29
30         if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
31                 err("I2C write reg failed, reg: %02x, val: %02x", reg, val);
32                 return -EREMOTEIO;
33         }
34         return 0;
35 }
36
37 static int fc0013_readreg(struct fc0013_priv *priv, u8 reg, u8 *val)
38 {
39         struct i2c_msg msg[2] = {
40                 { .addr = priv->addr, .flags = 0, .buf = &reg, .len = 1 },
41                 { .addr = priv->addr, .flags = I2C_M_RD, .buf = val, .len = 1 },
42         };
43
44         if (i2c_transfer(priv->i2c, msg, 2) != 2) {
45                 err("I2C read reg failed, reg: %02x", reg);
46                 return -EREMOTEIO;
47         }
48         return 0;
49 }
50
51 static void fc0013_release(struct dvb_frontend *fe)
52 {
53         kfree(fe->tuner_priv);
54         fe->tuner_priv = NULL;
55 }
56
57 static int fc0013_init(struct dvb_frontend *fe)
58 {
59         struct fc0013_priv *priv = fe->tuner_priv;
60         int i, ret = 0;
61         unsigned char reg[] = {
62                 0x00,   /* reg. 0x00: dummy */
63                 0x09,   /* reg. 0x01 */
64                 0x16,   /* reg. 0x02 */
65                 0x00,   /* reg. 0x03 */
66                 0x00,   /* reg. 0x04 */
67                 0x17,   /* reg. 0x05 */
68                 0x02,   /* reg. 0x06 */
69                 0x0a,   /* reg. 0x07: CHECK */
70                 0xff,   /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256,
71                            Loop Bw 1/8 */
72                 0x6f,   /* reg. 0x09: enable LoopThrough */
73                 0xb8,   /* reg. 0x0a: Disable LO Test Buffer */
74                 0x82,   /* reg. 0x0b: CHECK */
75                 0xfc,   /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
76                 0x01,   /* reg. 0x0d: AGC Not Forcing & LNA Forcing, may need 0x02 */
77                 0x00,   /* reg. 0x0e */
78                 0x00,   /* reg. 0x0f */
79                 0x00,   /* reg. 0x10 */
80                 0x00,   /* reg. 0x11 */
81                 0x00,   /* reg. 0x12 */
82                 0x00,   /* reg. 0x13 */
83                 0x50,   /* reg. 0x14: DVB-t High Gain, UHF.
84                            Middle Gain: 0x48, Low Gain: 0x40 */
85                 0x01,   /* reg. 0x15 */
86         };
87
88         switch (priv->xtal_freq) {
89         case FC_XTAL_27_MHZ:
90         case FC_XTAL_28_8_MHZ:
91                 reg[0x07] |= 0x20;
92                 break;
93         case FC_XTAL_36_MHZ:
94         default:
95                 break;
96         }
97
98         if (priv->dual_master)
99                 reg[0x0c] |= 0x02;
100
101         if (fe->ops.i2c_gate_ctrl)
102                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
103
104         for (i = 1; i < sizeof(reg); i++) {
105                 ret = fc0013_writereg(priv, i, reg[i]);
106                 if (ret)
107                         break;
108         }
109
110         if (fe->ops.i2c_gate_ctrl)
111                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
112
113         if (ret)
114                 err("fc0013_writereg failed: %d", ret);
115
116         return ret;
117 }
118
119 static int fc0013_sleep(struct dvb_frontend *fe)
120 {
121         /* nothing to do here */
122         return 0;
123 }
124
125 int fc0013_rc_cal_add(struct dvb_frontend *fe, int rc_val)
126 {
127         struct fc0013_priv *priv = fe->tuner_priv;
128         int ret;
129         u8 rc_cal;
130         int val;
131
132         if (fe->ops.i2c_gate_ctrl)
133                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
134
135         /* push rc_cal value, get rc_cal value */
136         ret = fc0013_writereg(priv, 0x10, 0x00);
137         if (ret)
138                 goto error_out;
139
140         /* get rc_cal value */
141         ret = fc0013_readreg(priv, 0x10, &rc_cal);
142         if (ret)
143                 goto error_out;
144
145         rc_cal &= 0x0f;
146
147         val = (int)rc_cal + rc_val;
148
149         /* forcing rc_cal */
150         ret = fc0013_writereg(priv, 0x0d, 0x11);
151         if (ret)
152                 goto error_out;
153
154         /* modify rc_cal value */
155         if (val > 15)
156                 ret = fc0013_writereg(priv, 0x10, 0x0f);
157         else if (val < 0)
158                 ret = fc0013_writereg(priv, 0x10, 0x00);
159         else
160                 ret = fc0013_writereg(priv, 0x10, (u8)val);
161
162 error_out:
163         if (fe->ops.i2c_gate_ctrl)
164                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
165
166         return ret;
167 }
168 EXPORT_SYMBOL(fc0013_rc_cal_add);
169
170 int fc0013_rc_cal_reset(struct dvb_frontend *fe)
171 {
172         struct fc0013_priv *priv = fe->tuner_priv;
173         int ret;
174
175         if (fe->ops.i2c_gate_ctrl)
176                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
177
178         ret = fc0013_writereg(priv, 0x0d, 0x01);
179         if (!ret)
180                 ret = fc0013_writereg(priv, 0x10, 0x00);
181
182         if (fe->ops.i2c_gate_ctrl)
183                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
184
185         return ret;
186 }
187 EXPORT_SYMBOL(fc0013_rc_cal_reset);
188
189 static int fc0013_set_vhf_track(struct fc0013_priv *priv, u32 freq)
190 {
191         int ret;
192         u8 tmp;
193
194         ret = fc0013_readreg(priv, 0x1d, &tmp);
195         if (ret)
196                 goto error_out;
197         tmp &= 0xe3;
198         if (freq <= 177500) {           /* VHF Track: 7 */
199                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c);
200         } else if (freq <= 184500) {    /* VHF Track: 6 */
201                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x18);
202         } else if (freq <= 191500) {    /* VHF Track: 5 */
203                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x14);
204         } else if (freq <= 198500) {    /* VHF Track: 4 */
205                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x10);
206         } else if (freq <= 205500) {    /* VHF Track: 3 */
207                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x0c);
208         } else if (freq <= 219500) {    /* VHF Track: 2 */
209                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x08);
210         } else if (freq < 300000) {     /* VHF Track: 1 */
211                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x04);
212         } else {                        /* UHF and GPS */
213                 ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c);
214         }
215 error_out:
216         return ret;
217 }
218
219 static int fc0013_set_params(struct dvb_frontend *fe)
220 {
221         struct fc0013_priv *priv = fe->tuner_priv;
222         int i, ret = 0;
223         struct dtv_frontend_properties *p = &fe->dtv_property_cache;
224         u32 freq = p->frequency / 1000;
225         u32 delsys = p->delivery_system;
226         unsigned char reg[7], am, pm, multi, tmp;
227         unsigned long f_vco;
228         unsigned short xtal_freq_khz_2, xin, xdiv;
229         bool vco_select = false;
230
231         if (fe->callback) {
232                 ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
233                         FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1));
234                 if (ret)
235                         goto exit;
236         }
237
238         switch (priv->xtal_freq) {
239         case FC_XTAL_27_MHZ:
240                 xtal_freq_khz_2 = 27000 / 2;
241                 break;
242         case FC_XTAL_36_MHZ:
243                 xtal_freq_khz_2 = 36000 / 2;
244                 break;
245         case FC_XTAL_28_8_MHZ:
246         default:
247                 xtal_freq_khz_2 = 28800 / 2;
248                 break;
249         }
250
251         if (fe->ops.i2c_gate_ctrl)
252                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
253
254         /* set VHF track */
255         ret = fc0013_set_vhf_track(priv, freq);
256         if (ret)
257                 goto exit;
258
259         if (freq < 300000) {
260                 /* enable VHF filter */
261                 ret = fc0013_readreg(priv, 0x07, &tmp);
262                 if (ret)
263                         goto exit;
264                 ret = fc0013_writereg(priv, 0x07, tmp | 0x10);
265                 if (ret)
266                         goto exit;
267
268                 /* disable UHF & disable GPS */
269                 ret = fc0013_readreg(priv, 0x14, &tmp);
270                 if (ret)
271                         goto exit;
272                 ret = fc0013_writereg(priv, 0x14, tmp & 0x1f);
273                 if (ret)
274                         goto exit;
275         } else if (freq <= 862000) {
276                 /* disable VHF filter */
277                 ret = fc0013_readreg(priv, 0x07, &tmp);
278                 if (ret)
279                         goto exit;
280                 ret = fc0013_writereg(priv, 0x07, tmp & 0xef);
281                 if (ret)
282                         goto exit;
283
284                 /* enable UHF & disable GPS */
285                 ret = fc0013_readreg(priv, 0x14, &tmp);
286                 if (ret)
287                         goto exit;
288                 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x40);
289                 if (ret)
290                         goto exit;
291         } else {
292                 /* disable VHF filter */
293                 ret = fc0013_readreg(priv, 0x07, &tmp);
294                 if (ret)
295                         goto exit;
296                 ret = fc0013_writereg(priv, 0x07, tmp & 0xef);
297                 if (ret)
298                         goto exit;
299
300                 /* disable UHF & enable GPS */
301                 ret = fc0013_readreg(priv, 0x14, &tmp);
302                 if (ret)
303                         goto exit;
304                 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x20);
305                 if (ret)
306                         goto exit;
307         }
308
309         /* select frequency divider and the frequency of VCO */
310         if (freq < 37084) {             /* freq * 96 < 3560000 */
311                 multi = 96;
312                 reg[5] = 0x82;
313                 reg[6] = 0x00;
314         } else if (freq < 55625) {      /* freq * 64 < 3560000 */
315                 multi = 64;
316                 reg[5] = 0x02;
317                 reg[6] = 0x02;
318         } else if (freq < 74167) {      /* freq * 48 < 3560000 */
319                 multi = 48;
320                 reg[5] = 0x42;
321                 reg[6] = 0x00;
322         } else if (freq < 111250) {     /* freq * 32 < 3560000 */
323                 multi = 32;
324                 reg[5] = 0x82;
325                 reg[6] = 0x02;
326         } else if (freq < 148334) {     /* freq * 24 < 3560000 */
327                 multi = 24;
328                 reg[5] = 0x22;
329                 reg[6] = 0x00;
330         } else if (freq < 222500) {     /* freq * 16 < 3560000 */
331                 multi = 16;
332                 reg[5] = 0x42;
333                 reg[6] = 0x02;
334         } else if (freq < 296667) {     /* freq * 12 < 3560000 */
335                 multi = 12;
336                 reg[5] = 0x12;
337                 reg[6] = 0x00;
338         } else if (freq < 445000) {     /* freq * 8 < 3560000 */
339                 multi = 8;
340                 reg[5] = 0x22;
341                 reg[6] = 0x02;
342         } else if (freq < 593334) {     /* freq * 6 < 3560000 */
343                 multi = 6;
344                 reg[5] = 0x0a;
345                 reg[6] = 0x00;
346         } else if (freq < 950000) {     /* freq * 4 < 3800000 */
347                 multi = 4;
348                 reg[5] = 0x12;
349                 reg[6] = 0x02;
350         } else {
351                 multi = 2;
352                 reg[5] = 0x0a;
353                 reg[6] = 0x02;
354         }
355
356         f_vco = freq * multi;
357
358         if (f_vco >= 3060000) {
359                 reg[6] |= 0x08;
360                 vco_select = true;
361         }
362
363         if (freq >= 45000) {
364                 /* From divided value (XDIV) determined the FA and FP value */
365                 xdiv = (unsigned short)(f_vco / xtal_freq_khz_2);
366                 if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2))
367                         xdiv++;
368
369                 pm = (unsigned char)(xdiv / 8);
370                 am = (unsigned char)(xdiv - (8 * pm));
371
372                 if (am < 2) {
373                         reg[1] = am + 8;
374                         reg[2] = pm - 1;
375                 } else {
376                         reg[1] = am;
377                         reg[2] = pm;
378                 }
379         } else {
380                 /* fix for frequency less than 45 MHz */
381                 reg[1] = 0x06;
382                 reg[2] = 0x11;
383         }
384
385         /* fix clock out */
386         reg[6] |= 0x20;
387
388         /* From VCO frequency determines the XIN ( fractional part of Delta
389            Sigma PLL) and divided value (XDIV) */
390         xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2);
391         xin = (xin << 15) / xtal_freq_khz_2;
392         if (xin >= 16384)
393                 xin += 32768;
394
395         reg[3] = xin >> 8;
396         reg[4] = xin & 0xff;
397
398         if (delsys == SYS_DVBT) {
399                 reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */
400                 switch (p->bandwidth_hz) {
401                 case 6000000:
402                         reg[6] |= 0x80;
403                         break;
404                 case 7000000:
405                         reg[6] |= 0x40;
406                         break;
407                 case 8000000:
408                 default:
409                         break;
410                 }
411         } else {
412                 err("%s: modulation type not supported!", __func__);
413                 return -EINVAL;
414         }
415
416         /* modified for Realtek demod */
417         reg[5] |= 0x07;
418
419         for (i = 1; i <= 6; i++) {
420                 ret = fc0013_writereg(priv, i, reg[i]);
421                 if (ret)
422                         goto exit;
423         }
424
425         ret = fc0013_readreg(priv, 0x11, &tmp);
426         if (ret)
427                 goto exit;
428         if (multi == 64)
429                 ret = fc0013_writereg(priv, 0x11, tmp | 0x04);
430         else
431                 ret = fc0013_writereg(priv, 0x11, tmp & 0xfb);
432         if (ret)
433                 goto exit;
434
435         /* VCO Calibration */
436         ret = fc0013_writereg(priv, 0x0e, 0x80);
437         if (!ret)
438                 ret = fc0013_writereg(priv, 0x0e, 0x00);
439
440         /* VCO Re-Calibration if needed */
441         if (!ret)
442                 ret = fc0013_writereg(priv, 0x0e, 0x00);
443
444         if (!ret) {
445                 msleep(10);
446                 ret = fc0013_readreg(priv, 0x0e, &tmp);
447         }
448         if (ret)
449                 goto exit;
450
451         /* vco selection */
452         tmp &= 0x3f;
453
454         if (vco_select) {
455                 if (tmp > 0x3c) {
456                         reg[6] &= ~0x08;
457                         ret = fc0013_writereg(priv, 0x06, reg[6]);
458                         if (!ret)
459                                 ret = fc0013_writereg(priv, 0x0e, 0x80);
460                         if (!ret)
461                                 ret = fc0013_writereg(priv, 0x0e, 0x00);
462                 }
463         } else {
464                 if (tmp < 0x02) {
465                         reg[6] |= 0x08;
466                         ret = fc0013_writereg(priv, 0x06, reg[6]);
467                         if (!ret)
468                                 ret = fc0013_writereg(priv, 0x0e, 0x80);
469                         if (!ret)
470                                 ret = fc0013_writereg(priv, 0x0e, 0x00);
471                 }
472         }
473
474         priv->frequency = p->frequency;
475         priv->bandwidth = p->bandwidth_hz;
476
477 exit:
478         if (fe->ops.i2c_gate_ctrl)
479                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
480         if (ret)
481                 warn("%s: failed: %d", __func__, ret);
482         return ret;
483 }
484
485 static int fc0013_get_frequency(struct dvb_frontend *fe, u32 *frequency)
486 {
487         struct fc0013_priv *priv = fe->tuner_priv;
488         *frequency = priv->frequency;
489         return 0;
490 }
491
492 static int fc0013_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
493 {
494         /* always ? */
495         *frequency = 0;
496         return 0;
497 }
498
499 static int fc0013_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
500 {
501         struct fc0013_priv *priv = fe->tuner_priv;
502         *bandwidth = priv->bandwidth;
503         return 0;
504 }
505
506 #define INPUT_ADC_LEVEL -8
507
508 static int fc0013_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
509 {
510         struct fc0013_priv *priv = fe->tuner_priv;
511         int ret;
512         unsigned char tmp;
513         int int_temp, lna_gain, int_lna, tot_agc_gain, power;
514         static const int fc0013_lna_gain_table[] = {
515                 /* low gain */
516                 -63, -58, -99, -73,
517                 -63, -65, -54, -60,
518                 /* middle gain */
519                  71,  70,  68,  67,
520                  65,  63,  61,  58,
521                 /* high gain */
522                 197, 191, 188, 186,
523                 184, 182, 181, 179,
524         };
525
526         if (fe->ops.i2c_gate_ctrl)
527                 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
528
529         ret = fc0013_writereg(priv, 0x13, 0x00);
530         if (ret)
531                 goto err;
532
533         ret = fc0013_readreg(priv, 0x13, &tmp);
534         if (ret)
535                 goto err;
536         int_temp = tmp;
537
538         ret = fc0013_readreg(priv, 0x14, &tmp);
539         if (ret)
540                 goto err;
541         lna_gain = tmp & 0x1f;
542
543         if (fe->ops.i2c_gate_ctrl)
544                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
545
546         if (lna_gain < ARRAY_SIZE(fc0013_lna_gain_table)) {
547                 int_lna = fc0013_lna_gain_table[lna_gain];
548                 tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 +
549                                 (int_temp & 0x1f)) * 2;
550                 power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10;
551
552                 if (power >= 45)
553                         *strength = 255;        /* 100% */
554                 else if (power < -95)
555                         *strength = 0;
556                 else
557                         *strength = (power + 95) * 255 / 140;
558
559                 *strength |= *strength << 8;
560         } else {
561                 ret = -1;
562         }
563
564         goto exit;
565
566 err:
567         if (fe->ops.i2c_gate_ctrl)
568                 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
569 exit:
570         if (ret)
571                 warn("%s: failed: %d", __func__, ret);
572         return ret;
573 }
574
575 static const struct dvb_tuner_ops fc0013_tuner_ops = {
576         .info = {
577                 .name             = "Fitipower FC0013",
578
579                 .frequency_min_hz =   37 * MHz, /* estimate */
580                 .frequency_max_hz = 1680 * MHz, /* CHECK */
581         },
582
583         .release        = fc0013_release,
584
585         .init           = fc0013_init,
586         .sleep          = fc0013_sleep,
587
588         .set_params     = fc0013_set_params,
589
590         .get_frequency  = fc0013_get_frequency,
591         .get_if_frequency = fc0013_get_if_frequency,
592         .get_bandwidth  = fc0013_get_bandwidth,
593
594         .get_rf_strength = fc0013_get_rf_strength,
595 };
596
597 struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
598         struct i2c_adapter *i2c, u8 i2c_address, int dual_master,
599         enum fc001x_xtal_freq xtal_freq)
600 {
601         struct fc0013_priv *priv = NULL;
602
603         priv = kzalloc(sizeof(struct fc0013_priv), GFP_KERNEL);
604         if (priv == NULL)
605                 return NULL;
606
607         priv->i2c = i2c;
608         priv->dual_master = dual_master;
609         priv->addr = i2c_address;
610         priv->xtal_freq = xtal_freq;
611
612         info("Fitipower FC0013 successfully attached.");
613
614         fe->tuner_priv = priv;
615
616         memcpy(&fe->ops.tuner_ops, &fc0013_tuner_ops,
617                 sizeof(struct dvb_tuner_ops));
618
619         return fe;
620 }
621 EXPORT_SYMBOL(fc0013_attach);
622
623 MODULE_DESCRIPTION("Fitipower FC0013 silicon tuner driver");
624 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
625 MODULE_LICENSE("GPL");
626 MODULE_VERSION("0.2");