1
2#include <linux/module.h>
3#include <linux/kernel.h>
4#include <linux/i2c.h>
5#include <linux/types.h>
6#include <linux/init.h>
7#include <linux/errno.h>
8#include <linux/delay.h>
9#include <linux/videodev2.h>
10#include <media/v4l2-common.h>
11#include <media/tuner.h>
12#include "tuner-i2c.h"
13#include "tda9887.h"
14
15
16
17
18
19
20
21
22
23
24static int debug;
25module_param(debug, int, 0644);
26MODULE_PARM_DESC(debug, "enable verbose debug messages");
27
28static DEFINE_MUTEX(tda9887_list_mutex);
29static LIST_HEAD(hybrid_tuner_instance_list);
30
31struct tda9887_priv {
32 struct tuner_i2c_props i2c_props;
33 struct list_head hybrid_tuner_instance_list;
34
35 unsigned char data[4];
36 unsigned int config;
37 unsigned int mode;
38 unsigned int audmode;
39 v4l2_std_id std;
40
41 bool standby;
42};
43
44
45
46#define UNSET (-1U)
47
48struct tvnorm {
49 v4l2_std_id std;
50 char *name;
51 unsigned char b;
52 unsigned char c;
53 unsigned char e;
54};
55
56
57
58
59
60
61
62
63#define cVideoTrapBypassOFF 0x00
64#define cVideoTrapBypassON 0x01
65
66#define cAutoMuteFmInactive 0x00
67#define cAutoMuteFmActive 0x02
68
69#define cIntercarrier 0x00
70#define cQSS 0x04
71
72#define cPositiveAmTV 0x00
73#define cFmRadio 0x08
74#define cNegativeFmTV 0x10
75
76
77#define cForcedMuteAudioON 0x20
78#define cForcedMuteAudioOFF 0x00
79
80#define cOutputPort1Active 0x00
81#define cOutputPort1Inactive 0x40
82
83#define cOutputPort2Active 0x00
84#define cOutputPort2Inactive 0x80
85
86
87
88#define cDeemphasisOFF 0x00
89#define cDeemphasisON 0x20
90
91#define cDeemphasis75 0x00
92#define cDeemphasis50 0x40
93
94#define cAudioGain0 0x00
95#define cAudioGain6 0x80
96
97#define cTopMask 0x1f
98#define cTopDefault 0x10
99
100
101#define cAudioIF_4_5 0x00
102#define cAudioIF_5_5 0x01
103#define cAudioIF_6_0 0x02
104#define cAudioIF_6_5 0x03
105
106
107#define cVideoIFMask 0x1c
108
109#define cVideoIF_58_75 0x00
110#define cVideoIF_45_75 0x04
111#define cVideoIF_38_90 0x08
112#define cVideoIF_38_00 0x0C
113#define cVideoIF_33_90 0x10
114#define cVideoIF_33_40 0x14
115#define cRadioIF_45_75 0x18
116#define cRadioIF_38_90 0x1C
117
118
119#define cRadioIF_33_30 0x00
120#define cRadioIF_41_30 0x04
121
122
123#define cRadioAGC_SIF 0x00
124#define cRadioAGC_FM 0x08
125
126#define cTunerGainNormal 0x00
127#define cTunerGainLow 0x20
128
129#define cGating_18 0x00
130#define cGating_36 0x40
131
132#define cAgcOutON 0x80
133#define cAgcOutOFF 0x00
134
135
136
137static struct tvnorm tvnorms[] = {
138 {
139 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
140 .name = "PAL-BGHN",
141 .b = ( cNegativeFmTV |
142 cQSS ),
143 .c = ( cDeemphasisON |
144 cDeemphasis50 |
145 cTopDefault),
146 .e = ( cGating_36 |
147 cAudioIF_5_5 |
148 cVideoIF_38_90 ),
149 },{
150 .std = V4L2_STD_PAL_I,
151 .name = "PAL-I",
152 .b = ( cNegativeFmTV |
153 cQSS ),
154 .c = ( cDeemphasisON |
155 cDeemphasis50 |
156 cTopDefault),
157 .e = ( cGating_36 |
158 cAudioIF_6_0 |
159 cVideoIF_38_90 ),
160 },{
161 .std = V4L2_STD_PAL_DK,
162 .name = "PAL-DK",
163 .b = ( cNegativeFmTV |
164 cQSS ),
165 .c = ( cDeemphasisON |
166 cDeemphasis50 |
167 cTopDefault),
168 .e = ( cGating_36 |
169 cAudioIF_6_5 |
170 cVideoIF_38_90 ),
171 },{
172 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
173 .name = "PAL-M/Nc",
174 .b = ( cNegativeFmTV |
175 cQSS ),
176 .c = ( cDeemphasisON |
177 cDeemphasis75 |
178 cTopDefault),
179 .e = ( cGating_36 |
180 cAudioIF_4_5 |
181 cVideoIF_45_75 ),
182 },{
183 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
184 .name = "SECAM-BGH",
185 .b = ( cNegativeFmTV |
186 cQSS ),
187 .c = ( cTopDefault),
188 .e = ( cAudioIF_5_5 |
189 cVideoIF_38_90 ),
190 },{
191 .std = V4L2_STD_SECAM_L,
192 .name = "SECAM-L",
193 .b = ( cPositiveAmTV |
194 cQSS ),
195 .c = ( cTopDefault),
196 .e = ( cGating_36 |
197 cAudioIF_6_5 |
198 cVideoIF_38_90 ),
199 },{
200 .std = V4L2_STD_SECAM_LC,
201 .name = "SECAM-L'",
202 .b = ( cOutputPort2Inactive |
203 cPositiveAmTV |
204 cQSS ),
205 .c = ( cTopDefault),
206 .e = ( cGating_36 |
207 cAudioIF_6_5 |
208 cVideoIF_33_90 ),
209 },{
210 .std = V4L2_STD_SECAM_DK,
211 .name = "SECAM-DK",
212 .b = ( cNegativeFmTV |
213 cQSS ),
214 .c = ( cDeemphasisON |
215 cDeemphasis50 |
216 cTopDefault),
217 .e = ( cGating_36 |
218 cAudioIF_6_5 |
219 cVideoIF_38_90 ),
220 },{
221 .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
222 .name = "NTSC-M",
223 .b = ( cNegativeFmTV |
224 cQSS ),
225 .c = ( cDeemphasisON |
226 cDeemphasis75 |
227 cTopDefault),
228 .e = ( cGating_36 |
229 cAudioIF_4_5 |
230 cVideoIF_45_75 ),
231 },{
232 .std = V4L2_STD_NTSC_M_JP,
233 .name = "NTSC-M-JP",
234 .b = ( cNegativeFmTV |
235 cQSS ),
236 .c = ( cDeemphasisON |
237 cDeemphasis50 |
238 cTopDefault),
239 .e = ( cGating_36 |
240 cAudioIF_4_5 |
241 cVideoIF_58_75 ),
242 }
243};
244
245static struct tvnorm radio_stereo = {
246 .name = "Radio Stereo",
247 .b = ( cFmRadio |
248 cQSS ),
249 .c = ( cDeemphasisOFF |
250 cAudioGain6 |
251 cTopDefault),
252 .e = ( cTunerGainLow |
253 cAudioIF_5_5 |
254 cRadioIF_38_90 ),
255};
256
257static struct tvnorm radio_mono = {
258 .name = "Radio Mono",
259 .b = ( cFmRadio |
260 cQSS ),
261 .c = ( cDeemphasisON |
262 cDeemphasis75 |
263 cTopDefault),
264 .e = ( cTunerGainLow |
265 cAudioIF_5_5 |
266 cRadioIF_38_90 ),
267};
268
269
270
271static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
272{
273 struct tda9887_priv *priv = fe->analog_demod_priv;
274
275 static char *afc[16] = {
276 "- 12.5 kHz",
277 "- 37.5 kHz",
278 "- 62.5 kHz",
279 "- 87.5 kHz",
280 "-112.5 kHz",
281 "-137.5 kHz",
282 "-162.5 kHz",
283 "-187.5 kHz [min]",
284 "+187.5 kHz [max]",
285 "+162.5 kHz",
286 "+137.5 kHz",
287 "+112.5 kHz",
288 "+ 87.5 kHz",
289 "+ 62.5 kHz",
290 "+ 37.5 kHz",
291 "+ 12.5 kHz",
292 };
293 tuner_info("read: 0x%2x\n", buf[0]);
294 tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
295 tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
296 tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
297 tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
298 tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
299}
300
301static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
302{
303 struct tda9887_priv *priv = fe->analog_demod_priv;
304
305 static char *sound[4] = {
306 "AM/TV",
307 "FM/radio",
308 "FM/TV",
309 "FM/radio"
310 };
311 static char *adjust[32] = {
312 "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
313 "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
314 "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
315 "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
316 };
317 static char *deemph[4] = {
318 "no", "no", "75", "50"
319 };
320 static char *carrier[4] = {
321 "4.5 MHz",
322 "5.5 MHz",
323 "6.0 MHz",
324 "6.5 MHz / AM"
325 };
326 static char *vif[8] = {
327 "58.75 MHz",
328 "45.75 MHz",
329 "38.9 MHz",
330 "38.0 MHz",
331 "33.9 MHz",
332 "33.4 MHz",
333 "45.75 MHz + pin13",
334 "38.9 MHz + pin13",
335 };
336 static char *rif[4] = {
337 "44 MHz",
338 "52 MHz",
339 "52 MHz",
340 "44 MHz",
341 };
342
343 tuner_info("write: byte B 0x%02x\n", buf[1]);
344 tuner_info(" B0 video mode : %s\n",
345 (buf[1] & 0x01) ? "video trap" : "sound trap");
346 tuner_info(" B1 auto mute fm : %s\n",
347 (buf[1] & 0x02) ? "yes" : "no");
348 tuner_info(" B2 carrier mode : %s\n",
349 (buf[1] & 0x04) ? "QSS" : "Intercarrier");
350 tuner_info(" B3-4 tv sound/radio : %s\n",
351 sound[(buf[1] & 0x18) >> 3]);
352 tuner_info(" B5 force mute audio: %s\n",
353 (buf[1] & 0x20) ? "yes" : "no");
354 tuner_info(" B6 output port 1 : %s\n",
355 (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
356 tuner_info(" B7 output port 2 : %s\n",
357 (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
358
359 tuner_info("write: byte C 0x%02x\n", buf[2]);
360 tuner_info(" C0-4 top adjustment : %s dB\n",
361 adjust[buf[2] & 0x1f]);
362 tuner_info(" C5-6 de-emphasis : %s\n",
363 deemph[(buf[2] & 0x60) >> 5]);
364 tuner_info(" C7 audio gain : %s\n",
365 (buf[2] & 0x80) ? "-6" : "0");
366
367 tuner_info("write: byte E 0x%02x\n", buf[3]);
368 tuner_info(" E0-1 sound carrier : %s\n",
369 carrier[(buf[3] & 0x03)]);
370 tuner_info(" E6 l pll gating : %s\n",
371 (buf[3] & 0x40) ? "36" : "13");
372
373 if (buf[1] & 0x08) {
374
375 tuner_info(" E2-4 video if : %s\n",
376 rif[(buf[3] & 0x0c) >> 2]);
377 tuner_info(" E7 vif agc output : %s\n",
378 (buf[3] & 0x80)
379 ? ((buf[3] & 0x10) ? "fm-agc radio" :
380 "sif-agc radio")
381 : "fm radio carrier afc");
382 } else {
383
384 tuner_info(" E2-4 video if : %s\n",
385 vif[(buf[3] & 0x1c) >> 2]);
386 tuner_info(" E5 tuner gain : %s\n",
387 (buf[3] & 0x80)
388 ? ((buf[3] & 0x20) ? "external" : "normal")
389 : ((buf[3] & 0x20) ? "minimum" : "normal"));
390 tuner_info(" E7 vif agc output : %s\n",
391 (buf[3] & 0x80) ? ((buf[3] & 0x20)
392 ? "pin3 port, pin22 vif agc out"
393 : "pin22 port, pin3 vif acg ext in")
394 : "pin3+pin22 port");
395 }
396 tuner_info("--\n");
397}
398
399
400
401static int tda9887_set_tvnorm(struct dvb_frontend *fe)
402{
403 struct tda9887_priv *priv = fe->analog_demod_priv;
404 struct tvnorm *norm = NULL;
405 char *buf = priv->data;
406 int i;
407
408 if (priv->mode == V4L2_TUNER_RADIO) {
409 if (priv->audmode == V4L2_TUNER_MODE_MONO)
410 norm = &radio_mono;
411 else
412 norm = &radio_stereo;
413 } else {
414 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
415 if (tvnorms[i].std & priv->std) {
416 norm = tvnorms+i;
417 break;
418 }
419 }
420 }
421 if (NULL == norm) {
422 tuner_dbg("Unsupported tvnorm entry - audio muted\n");
423 return -1;
424 }
425
426 tuner_dbg("configure for: %s\n", norm->name);
427 buf[1] = norm->b;
428 buf[2] = norm->c;
429 buf[3] = norm->e;
430 return 0;
431}
432
433static unsigned int port1 = UNSET;
434static unsigned int port2 = UNSET;
435static unsigned int qss = UNSET;
436static unsigned int adjust = UNSET;
437
438module_param(port1, int, 0644);
439module_param(port2, int, 0644);
440module_param(qss, int, 0644);
441module_param(adjust, int, 0644);
442
443static int tda9887_set_insmod(struct dvb_frontend *fe)
444{
445 struct tda9887_priv *priv = fe->analog_demod_priv;
446 char *buf = priv->data;
447
448 if (UNSET != port1) {
449 if (port1)
450 buf[1] |= cOutputPort1Inactive;
451 else
452 buf[1] &= ~cOutputPort1Inactive;
453 }
454 if (UNSET != port2) {
455 if (port2)
456 buf[1] |= cOutputPort2Inactive;
457 else
458 buf[1] &= ~cOutputPort2Inactive;
459 }
460
461 if (UNSET != qss) {
462 if (qss)
463 buf[1] |= cQSS;
464 else
465 buf[1] &= ~cQSS;
466 }
467
468 if (adjust < 0x20) {
469 buf[2] &= ~cTopMask;
470 buf[2] |= adjust;
471 }
472 return 0;
473}
474
475static int tda9887_do_config(struct dvb_frontend *fe)
476{
477 struct tda9887_priv *priv = fe->analog_demod_priv;
478 char *buf = priv->data;
479
480 if (priv->config & TDA9887_PORT1_ACTIVE)
481 buf[1] &= ~cOutputPort1Inactive;
482 if (priv->config & TDA9887_PORT1_INACTIVE)
483 buf[1] |= cOutputPort1Inactive;
484 if (priv->config & TDA9887_PORT2_ACTIVE)
485 buf[1] &= ~cOutputPort2Inactive;
486 if (priv->config & TDA9887_PORT2_INACTIVE)
487 buf[1] |= cOutputPort2Inactive;
488
489 if (priv->config & TDA9887_QSS)
490 buf[1] |= cQSS;
491 if (priv->config & TDA9887_INTERCARRIER)
492 buf[1] &= ~cQSS;
493
494 if (priv->config & TDA9887_AUTOMUTE)
495 buf[1] |= cAutoMuteFmActive;
496 if (priv->config & TDA9887_DEEMPHASIS_MASK) {
497 buf[2] &= ~0x60;
498 switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
499 case TDA9887_DEEMPHASIS_NONE:
500 buf[2] |= cDeemphasisOFF;
501 break;
502 case TDA9887_DEEMPHASIS_50:
503 buf[2] |= cDeemphasisON | cDeemphasis50;
504 break;
505 case TDA9887_DEEMPHASIS_75:
506 buf[2] |= cDeemphasisON | cDeemphasis75;
507 break;
508 }
509 }
510 if (priv->config & TDA9887_TOP_SET) {
511 buf[2] &= ~cTopMask;
512 buf[2] |= (priv->config >> 8) & cTopMask;
513 }
514 if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
515 (priv->std & V4L2_STD_NTSC))
516 buf[1] &= ~cQSS;
517 if (priv->config & TDA9887_GATING_18)
518 buf[3] &= ~cGating_36;
519
520 if (priv->mode == V4L2_TUNER_RADIO) {
521 if (priv->config & TDA9887_RIF_41_3) {
522 buf[3] &= ~cVideoIFMask;
523 buf[3] |= cRadioIF_41_30;
524 }
525 if (priv->config & TDA9887_GAIN_NORMAL)
526 buf[3] &= ~cTunerGainLow;
527 }
528
529 return 0;
530}
531
532
533
534static int tda9887_status(struct dvb_frontend *fe)
535{
536 struct tda9887_priv *priv = fe->analog_demod_priv;
537 unsigned char buf[1];
538 int rc;
539
540 rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
541 if (rc != 1)
542 tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
543 dump_read_message(fe, buf);
544 return 0;
545}
546
547static void tda9887_configure(struct dvb_frontend *fe)
548{
549 struct tda9887_priv *priv = fe->analog_demod_priv;
550 int rc;
551
552 memset(priv->data,0,sizeof(priv->data));
553 tda9887_set_tvnorm(fe);
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568 priv->data[1] |= cOutputPort1Inactive;
569 priv->data[1] |= cOutputPort2Inactive;
570
571 tda9887_do_config(fe);
572 tda9887_set_insmod(fe);
573
574 if (priv->standby)
575 priv->data[1] |= cForcedMuteAudioON;
576
577 tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
578 priv->data[1], priv->data[2], priv->data[3]);
579 if (debug > 1)
580 dump_write_message(fe, priv->data);
581
582 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
583 tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
584
585 if (debug > 2) {
586 msleep_interruptible(1000);
587 tda9887_status(fe);
588 }
589}
590
591
592
593static void tda9887_tuner_status(struct dvb_frontend *fe)
594{
595 struct tda9887_priv *priv = fe->analog_demod_priv;
596 tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
597 priv->data[1], priv->data[2], priv->data[3]);
598}
599
600static int tda9887_get_afc(struct dvb_frontend *fe, s32 *afc)
601{
602 struct tda9887_priv *priv = fe->analog_demod_priv;
603 static const int AFC_BITS_2_kHz[] = {
604 -12500, -37500, -62500, -97500,
605 -112500, -137500, -162500, -187500,
606 187500, 162500, 137500, 112500,
607 97500 , 62500, 37500 , 12500
608 };
609 __u8 reg = 0;
610
611 if (priv->mode != V4L2_TUNER_RADIO)
612 return 0;
613 if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, ®, 1))
614 *afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
615 return 0;
616}
617
618static void tda9887_standby(struct dvb_frontend *fe)
619{
620 struct tda9887_priv *priv = fe->analog_demod_priv;
621
622 priv->standby = true;
623
624 tda9887_configure(fe);
625}
626
627static void tda9887_set_params(struct dvb_frontend *fe,
628 struct analog_parameters *params)
629{
630 struct tda9887_priv *priv = fe->analog_demod_priv;
631
632 priv->standby = false;
633 priv->mode = params->mode;
634 priv->audmode = params->audmode;
635 priv->std = params->std;
636 tda9887_configure(fe);
637}
638
639static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
640{
641 struct tda9887_priv *priv = fe->analog_demod_priv;
642
643 priv->config = *(unsigned int *)priv_cfg;
644 tda9887_configure(fe);
645
646 return 0;
647}
648
649static void tda9887_release(struct dvb_frontend *fe)
650{
651 struct tda9887_priv *priv = fe->analog_demod_priv;
652
653 mutex_lock(&tda9887_list_mutex);
654
655 if (priv)
656 hybrid_tuner_release_state(priv);
657
658 mutex_unlock(&tda9887_list_mutex);
659
660 fe->analog_demod_priv = NULL;
661}
662
663static const struct analog_demod_ops tda9887_ops = {
664 .info = {
665 .name = "tda9887",
666 },
667 .set_params = tda9887_set_params,
668 .standby = tda9887_standby,
669 .tuner_status = tda9887_tuner_status,
670 .get_afc = tda9887_get_afc,
671 .release = tda9887_release,
672 .set_config = tda9887_set_config,
673};
674
675struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
676 struct i2c_adapter *i2c_adap,
677 u8 i2c_addr)
678{
679 struct tda9887_priv *priv = NULL;
680 int instance;
681
682 mutex_lock(&tda9887_list_mutex);
683
684 instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
685 hybrid_tuner_instance_list,
686 i2c_adap, i2c_addr, "tda9887");
687 switch (instance) {
688 case 0:
689 mutex_unlock(&tda9887_list_mutex);
690 return NULL;
691 case 1:
692 fe->analog_demod_priv = priv;
693 priv->standby = true;
694 tuner_info("tda988[5/6/7] found\n");
695 break;
696 default:
697 fe->analog_demod_priv = priv;
698 break;
699 }
700
701 mutex_unlock(&tda9887_list_mutex);
702
703 memcpy(&fe->ops.analog_ops, &tda9887_ops,
704 sizeof(struct analog_demod_ops));
705
706 return fe;
707}
708EXPORT_SYMBOL_GPL(tda9887_attach);
709
710MODULE_LICENSE("GPL");
711