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