aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tda9887.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tda9887.c')
-rw-r--r--drivers/media/video/tda9887.c228
1 files changed, 143 insertions, 85 deletions
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 7165a1b9625a..9cf47dc65579 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -9,7 +9,7 @@
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/delay.h> 10#include <linux/delay.h>
11 11
12#include <media/audiochip.h> 12#include <media/v4l2-common.h>
13#include <media/tuner.h> 13#include <media/tuner.h>
14 14
15 15
@@ -57,7 +57,6 @@ struct tda9887 {
57 v4l2_std_id std; 57 v4l2_std_id std;
58 enum tuner_mode mode; 58 enum tuner_mode mode;
59 unsigned int config; 59 unsigned int config;
60 unsigned int pinnacle_id;
61 unsigned int using_v4l2; 60 unsigned int using_v4l2;
62 unsigned int radio_mode; 61 unsigned int radio_mode;
63 unsigned char data[4]; 62 unsigned char data[4];
@@ -115,6 +114,9 @@ static struct i2c_client client_template;
115#define cAudioGain0 0x00 // bit c7 114#define cAudioGain0 0x00 // bit c7
116#define cAudioGain6 0x80 // bit c7 115#define cAudioGain6 0x80 // bit c7
117 116
117#define cTopMask 0x1f // bit c0:4
118#define cTopPalSecamDefault 0x14 // bit c0:4
119#define cTopNtscRadioDefault 0x10 // bit c0:4
118 120
119//// third reg (e) 121//// third reg (e)
120#define cAudioIF_4_5 0x00 // bit e0:1 122#define cAudioIF_4_5 0x00 // bit e0:1
@@ -146,13 +148,15 @@ static struct i2c_client client_template;
146 148
147static struct tvnorm tvnorms[] = { 149static struct tvnorm tvnorms[] = {
148 { 150 {
149 .std = V4L2_STD_PAL_BG, 151 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
150 .name = "PAL-BG", 152 .name = "PAL-BGHN",
151 .b = ( cNegativeFmTV | 153 .b = ( cNegativeFmTV |
152 cQSS ), 154 cQSS ),
153 .c = ( cDeemphasisON | 155 .c = ( cDeemphasisON |
154 cDeemphasis50 ), 156 cDeemphasis50 |
155 .e = ( cAudioIF_5_5 | 157 cTopPalSecamDefault),
158 .e = ( cGating_36 |
159 cAudioIF_5_5 |
156 cVideoIF_38_90 ), 160 cVideoIF_38_90 ),
157 },{ 161 },{
158 .std = V4L2_STD_PAL_I, 162 .std = V4L2_STD_PAL_I,
@@ -160,8 +164,10 @@ static struct tvnorm tvnorms[] = {
160 .b = ( cNegativeFmTV | 164 .b = ( cNegativeFmTV |
161 cQSS ), 165 cQSS ),
162 .c = ( cDeemphasisON | 166 .c = ( cDeemphasisON |
163 cDeemphasis50 ), 167 cDeemphasis50 |
164 .e = ( cAudioIF_6_0 | 168 cTopPalSecamDefault),
169 .e = ( cGating_36 |
170 cAudioIF_6_0 |
165 cVideoIF_38_90 ), 171 cVideoIF_38_90 ),
166 },{ 172 },{
167 .std = V4L2_STD_PAL_DK, 173 .std = V4L2_STD_PAL_DK,
@@ -169,52 +175,80 @@ static struct tvnorm tvnorms[] = {
169 .b = ( cNegativeFmTV | 175 .b = ( cNegativeFmTV |
170 cQSS ), 176 cQSS ),
171 .c = ( cDeemphasisON | 177 .c = ( cDeemphasisON |
172 cDeemphasis50 ), 178 cDeemphasis50 |
173 .e = ( cAudioIF_6_5 | 179 cTopPalSecamDefault),
174 cVideoIF_38_00 ), 180 .e = ( cGating_36 |
181 cAudioIF_6_5 |
182 cVideoIF_38_90 ),
175 },{ 183 },{
176 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N, 184 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
177 .name = "PAL-M/N", 185 .name = "PAL-M/Nc",
178 .b = ( cNegativeFmTV | 186 .b = ( cNegativeFmTV |
179 cQSS ), 187 cQSS ),
180 .c = ( cDeemphasisON | 188 .c = ( cDeemphasisON |
181 cDeemphasis75 ), 189 cDeemphasis75 |
182 .e = ( cAudioIF_4_5 | 190 cTopNtscRadioDefault),
191 .e = ( cGating_36 |
192 cAudioIF_4_5 |
183 cVideoIF_45_75 ), 193 cVideoIF_45_75 ),
184 },{ 194 },{
195 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
196 .name = "SECAM-BGH",
197 .b = ( cPositiveAmTV |
198 cQSS ),
199 .c = ( cTopPalSecamDefault),
200 .e = ( cGating_36 |
201 cAudioIF_5_5 |
202 cVideoIF_38_90 ),
203 },{
185 .std = V4L2_STD_SECAM_L, 204 .std = V4L2_STD_SECAM_L,
186 .name = "SECAM-L", 205 .name = "SECAM-L",
187 .b = ( cPositiveAmTV | 206 .b = ( cPositiveAmTV |
188 cQSS ), 207 cQSS ),
208 .c = ( cTopPalSecamDefault),
189 .e = ( cGating_36 | 209 .e = ( cGating_36 |
190 cAudioIF_6_5 | 210 cAudioIF_6_5 |
191 cVideoIF_38_90 ), 211 cVideoIF_38_90 ),
192 },{ 212 },{
213 .std = V4L2_STD_SECAM_LC,
214 .name = "SECAM-L'",
215 .b = ( cOutputPort2Inactive |
216 cPositiveAmTV |
217 cQSS ),
218 .c = ( cTopPalSecamDefault),
219 .e = ( cGating_36 |
220 cAudioIF_6_5 |
221 cVideoIF_33_90 ),
222 },{
193 .std = V4L2_STD_SECAM_DK, 223 .std = V4L2_STD_SECAM_DK,
194 .name = "SECAM-DK", 224 .name = "SECAM-DK",
195 .b = ( cNegativeFmTV | 225 .b = ( cNegativeFmTV |
196 cQSS ), 226 cQSS ),
197 .c = ( cDeemphasisON | 227 .c = ( cDeemphasisON |
198 cDeemphasis50 ), 228 cDeemphasis50 |
199 .e = ( cAudioIF_6_5 | 229 cTopPalSecamDefault),
200 cVideoIF_38_00 ), 230 .e = ( cGating_36 |
231 cAudioIF_6_5 |
232 cVideoIF_38_90 ),
201 },{ 233 },{
202 .std = V4L2_STD_NTSC_M, 234 .std = V4L2_STD_NTSC_M,
203 .name = "NTSC-M", 235 .name = "NTSC-M",
204 .b = ( cNegativeFmTV | 236 .b = ( cNegativeFmTV |
205 cQSS ), 237 cQSS ),
206 .c = ( cDeemphasisON | 238 .c = ( cDeemphasisON |
207 cDeemphasis75 ), 239 cDeemphasis75 |
240 cTopNtscRadioDefault),
208 .e = ( cGating_36 | 241 .e = ( cGating_36 |
209 cAudioIF_4_5 | 242 cAudioIF_4_5 |
210 cVideoIF_45_75 ), 243 cVideoIF_45_75 ),
211 },{ 244 },{
212 .std = V4L2_STD_NTSC_M_JP, 245 .std = V4L2_STD_NTSC_M_JP,
213 .name = "NTSC-JP", 246 .name = "NTSC-M-JP",
214 .b = ( cNegativeFmTV | 247 .b = ( cNegativeFmTV |
215 cQSS ), 248 cQSS ),
216 .c = ( cDeemphasisON | 249 .c = ( cDeemphasisON |
217 cDeemphasis50 ), 250 cDeemphasis50 |
251 cTopNtscRadioDefault),
218 .e = ( cGating_36 | 252 .e = ( cGating_36 |
219 cAudioIF_4_5 | 253 cAudioIF_4_5 |
220 cVideoIF_58_75 ), 254 cVideoIF_58_75 ),
@@ -226,8 +260,10 @@ static struct tvnorm radio_stereo = {
226 .b = ( cFmRadio | 260 .b = ( cFmRadio |
227 cQSS ), 261 cQSS ),
228 .c = ( cDeemphasisOFF | 262 .c = ( cDeemphasisOFF |
229 cAudioGain6 ), 263 cAudioGain6 |
230 .e = ( cAudioIF_5_5 | 264 cTopNtscRadioDefault),
265 .e = ( cTunerGainLow |
266 cAudioIF_5_5 |
231 cRadioIF_38_90 ), 267 cRadioIF_38_90 ),
232}; 268};
233 269
@@ -236,8 +272,10 @@ static struct tvnorm radio_mono = {
236 .b = ( cFmRadio | 272 .b = ( cFmRadio |
237 cQSS ), 273 cQSS ),
238 .c = ( cDeemphasisON | 274 .c = ( cDeemphasisON |
239 cDeemphasis50), 275 cDeemphasis75 |
240 .e = ( cAudioIF_5_5 | 276 cTopNtscRadioDefault),
277 .e = ( cTunerGainLow |
278 cAudioIF_5_5 |
241 cRadioIF_38_90 ), 279 cRadioIF_38_90 ),
242}; 280};
243 281
@@ -400,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
400static unsigned int port1 = UNSET; 438static unsigned int port1 = UNSET;
401static unsigned int port2 = UNSET; 439static unsigned int port2 = UNSET;
402static unsigned int qss = UNSET; 440static unsigned int qss = UNSET;
403static unsigned int adjust = 0x10; 441static unsigned int adjust = UNSET;
442
404module_param(port1, int, 0644); 443module_param(port1, int, 0644);
405module_param(port2, int, 0644); 444module_param(port2, int, 0644);
406module_param(qss, int, 0644); 445module_param(qss, int, 0644);
@@ -428,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
428 buf[1] &= ~cQSS; 467 buf[1] &= ~cQSS;
429 } 468 }
430 469
431 if (adjust >= 0x00 && adjust < 0x20) 470 if (adjust >= 0x00 && adjust < 0x20) {
471 buf[2] &= ~cTopMask;
432 buf[2] |= adjust; 472 buf[2] |= adjust;
473 }
433 return 0; 474 return 0;
434} 475}
435 476
@@ -465,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
465 break; 506 break;
466 } 507 }
467 } 508 }
509 if (t->config & TDA9887_TOP_SET) {
510 buf[2] &= ~cTopMask;
511 buf[2] |= (t->config >> 8) & cTopMask;
512 }
468 if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) 513 if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
469 buf[1] &= ~cQSS; 514 buf[1] &= ~cQSS;
470 return 0; 515 return 0;
@@ -472,38 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
472 517
473/* ---------------------------------------------------------------------- */ 518/* ---------------------------------------------------------------------- */
474 519
475static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) 520static char pal[] = "--";
476{ 521static char secam[] = "--";
477 unsigned int bCarrierMode = UNSET; 522static char ntsc[] = "-";
478
479 if (t->std & V4L2_STD_625_50) {
480 if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
481 bCarrierMode = cIntercarrier;
482 } else {
483 bCarrierMode = cQSS;
484 }
485 }
486 if (t->std & V4L2_STD_525_60) {
487 if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
488 bCarrierMode = cIntercarrier;
489 } else {
490 bCarrierMode = cQSS;
491 }
492 }
493
494 if (bCarrierMode != UNSET) {
495 buf[1] &= ~0x04;
496 buf[1] |= bCarrierMode;
497 }
498 return 0;
499}
500
501/* ---------------------------------------------------------------------- */
502 523
503static char pal[] = "-";
504module_param_string(pal, pal, sizeof(pal), 0644); 524module_param_string(pal, pal, sizeof(pal), 0644);
505static char secam[] = "-";
506module_param_string(secam, secam, sizeof(secam), 0644); 525module_param_string(secam, secam, sizeof(secam), 0644);
526module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
507 527
508static int tda9887_fixup_std(struct tda9887 *t) 528static int tda9887_fixup_std(struct tda9887 *t)
509{ 529{
@@ -514,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t)
514 case 'B': 534 case 'B':
515 case 'g': 535 case 'g':
516 case 'G': 536 case 'G':
517 tda9887_dbg("insmod fixup: PAL => PAL-BG\n"); 537 case 'h':
518 t->std = V4L2_STD_PAL_BG; 538 case 'H':
539 case 'n':
540 case 'N':
541 if (pal[1] == 'c' || pal[1] == 'C') {
542 tda9887_dbg("insmod fixup: PAL => PAL-Nc\n");
543 t->std = V4L2_STD_PAL_Nc;
544 } else {
545 tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n");
546 t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N;
547 }
519 break; 548 break;
520 case 'i': 549 case 'i':
521 case 'I': 550 case 'I':
@@ -529,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
529 tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); 558 tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
530 t->std = V4L2_STD_PAL_DK; 559 t->std = V4L2_STD_PAL_DK;
531 break; 560 break;
561 case 'm':
562 case 'M':
563 tda9887_dbg("insmod fixup: PAL => PAL-M\n");
564 t->std = V4L2_STD_PAL_M;
565 break;
532 case '-': 566 case '-':
533 /* default parameter, do nothing */ 567 /* default parameter, do nothing */
534 break; 568 break;
@@ -539,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t)
539 } 573 }
540 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { 574 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
541 switch (secam[0]) { 575 switch (secam[0]) {
576 case 'b':
577 case 'B':
578 case 'g':
579 case 'G':
580 case 'h':
581 case 'H':
582 tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n");
583 t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
584 break;
542 case 'd': 585 case 'd':
543 case 'D': 586 case 'D':
544 case 'k': 587 case 'k':
@@ -548,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t)
548 break; 591 break;
549 case 'l': 592 case 'l':
550 case 'L': 593 case 'L':
551 tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); 594 if (secam[1] == 'c' || secam[1] == 'C') {
552 t->std = V4L2_STD_SECAM_L; 595 tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n");
596 t->std = V4L2_STD_SECAM_LC;
597 } else {
598 tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
599 t->std = V4L2_STD_SECAM_L;
600 }
553 break; 601 break;
554 case '-': 602 case '-':
555 /* default parameter, do nothing */ 603 /* default parameter, do nothing */
@@ -559,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t)
559 break; 607 break;
560 } 608 }
561 } 609 }
610 if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
611 switch (ntsc[0]) {
612 case 'm':
613 case 'M':
614 tda9887_dbg("insmod fixup: NTSC => NTSC-M\n");
615 t->std = V4L2_STD_NTSC_M;
616 break;
617 case 'j':
618 case 'J':
619 tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
620 t->std = V4L2_STD_NTSC_M_JP;
621 break;
622 case '-':
623 /* default parameter, do nothing */
624 break;
625 default:
626 tda9887_info("ntsc= argument not recognised\n");
627 break;
628 }
629 }
562 return 0; 630 return 0;
563} 631}
564 632
@@ -581,12 +649,22 @@ static int tda9887_configure(struct tda9887 *t)
581 memset(t->data,0,sizeof(t->data)); 649 memset(t->data,0,sizeof(t->data));
582 tda9887_set_tvnorm(t,t->data); 650 tda9887_set_tvnorm(t,t->data);
583 651
652 /* A note on the port settings:
653 These settings tend to depend on the specifics of the board.
654 By default they are set to inactive (bit value 1) by this driver,
655 overwriting any changes made by the tvnorm. This means that it
656 is the responsibility of the module using the tda9887 to set
657 these values in case of changes in the tvnorm.
658 In many cases port 2 should be made active (0) when selecting
659 SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
660
661 For the other standards the tda9887 application note says that
662 the ports should be set to active (0), but, again, that may
663 differ depending on the precise hardware configuration.
664 */
584 t->data[1] |= cOutputPort1Inactive; 665 t->data[1] |= cOutputPort1Inactive;
585 t->data[1] |= cOutputPort2Inactive; 666 t->data[1] |= cOutputPort2Inactive;
586 667
587 if (UNSET != t->pinnacle_id) {
588 tda9887_set_pinnacle(t,t->data);
589 }
590 tda9887_set_config(t,t->data); 668 tda9887_set_config(t,t->data);
591 tda9887_set_insmod(t,t->data); 669 tda9887_set_insmod(t,t->data);
592 670
@@ -594,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t)
594 t->data[1] |= cForcedMuteAudioON; 672 t->data[1] |= cForcedMuteAudioON;
595 } 673 }
596 674
597
598 tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", 675 tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
599 t->data[1],t->data[2],t->data[3]); 676 t->data[1],t->data[2],t->data[3]);
600 if (debug > 1) 677 if (debug > 1)
@@ -625,7 +702,6 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
625 702
626 t->client = client_template; 703 t->client = client_template;
627 t->std = 0; 704 t->std = 0;
628 t->pinnacle_id = UNSET;
629 t->radio_mode = V4L2_TUNER_MODE_STEREO; 705 t->radio_mode = V4L2_TUNER_MODE_STEREO;
630 706
631 tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); 707 tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name);
@@ -638,18 +714,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
638 714
639static int tda9887_probe(struct i2c_adapter *adap) 715static int tda9887_probe(struct i2c_adapter *adap)
640{ 716{
641#ifdef I2C_CLASS_TV_ANALOG
642 if (adap->class & I2C_CLASS_TV_ANALOG) 717 if (adap->class & I2C_CLASS_TV_ANALOG)
643 return i2c_probe(adap, &addr_data, tda9887_attach); 718 return i2c_probe(adap, &addr_data, tda9887_attach);
644#else
645 switch (adap->id) {
646 case I2C_HW_B_BT848:
647 case I2C_HW_B_RIVA:
648 case I2C_HW_SAA7134:
649 return i2c_probe(adap, &addr_data, tda9887_attach);
650 break;
651 }
652#endif
653 return 0; 719 return 0;
654} 720}
655 721
@@ -689,14 +755,6 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
689 tda9887_configure(t); 755 tda9887_configure(t);
690 break; 756 break;
691 } 757 }
692 case AUDC_CONFIG_PINNACLE:
693 {
694 int *i = arg;
695
696 t->pinnacle_id = *i;
697 tda9887_configure(t);
698 break;
699 }
700 case TDA9887_SET_CONFIG: 758 case TDA9887_SET_CONFIG:
701 { 759 {
702 int *i = arg; 760 int *i = arg;
@@ -787,7 +845,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
787 } 845 }
788 case VIDIOC_LOG_STATUS: 846 case VIDIOC_LOG_STATUS:
789 { 847 {
790 tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]); 848 tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]);
791 break; 849 break;
792 } 850 }
793 default: 851 default:
@@ -824,7 +882,7 @@ static struct i2c_driver driver = {
824 .detach_client = tda9887_detach, 882 .detach_client = tda9887_detach,
825 .command = tda9887_command, 883 .command = tda9887_command,
826 .driver = { 884 .driver = {
827 .name = "i2c tda9887 driver", 885 .name = "tda9887",
828 .suspend = tda9887_suspend, 886 .suspend = tda9887_suspend,
829 .resume = tda9887_resume, 887 .resume = tda9887_resume,
830 }, 888 },