diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-23 15:13:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-25 01:05:24 -0400 |
commit | 153962364dc6fa4a24571885fbe76506d8968610 (patch) | |
tree | 78eca883cd190dbb2bf94b6337ac1d57951a757b /drivers/media/video/tda9887.c | |
parent | 0ccac4af1a8f22e2e96d89b9bf8766dc7286a972 (diff) |
V4L/DVB (4205): Merge tda9887 module into tuner.
Most uses a tda988[5/6/7] IF demodulator as part of the device.
Having this as a separate stuff makes harder to configure it, since there
are some tda9887 options that are tuner-dependent and should be bound into
tuner-types structures.
This patch merges tda9887 module into tuner. More work is required to make
tuner-types to properly use it.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/tda9887.c')
-rw-r--r-- | drivers/media/video/tda9887.c | 461 |
1 files changed, 74 insertions, 387 deletions
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 0d54f6c1982b..b6ae969563b2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -18,49 +18,21 @@ | |||
18 | TDA9886 (PAL, SECAM, NTSC) | 18 | TDA9886 (PAL, SECAM, NTSC) |
19 | TDA9887 (PAL, SECAM, NTSC, FM Radio) | 19 | TDA9887 (PAL, SECAM, NTSC, FM Radio) |
20 | 20 | ||
21 | found on: | 21 | Used as part of several tuners |
22 | - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv) | ||
23 | TDA9887 (world), TDA9885 (USA) | ||
24 | Note: OP2 of tda988x must be set to 1, else MT2032 is disabled! | ||
25 | - KNC One TV-Station RDS (saa7134) | ||
26 | - Hauppauge PVR-150/500 (possibly more) | ||
27 | */ | 22 | */ |
28 | 23 | ||
24 | #define tda9887_info(fmt, arg...) do {\ | ||
25 | printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ | ||
26 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | ||
27 | #define tda9887_dbg(fmt, arg...) do {\ | ||
28 | if (tuner_debug) \ | ||
29 | printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ | ||
30 | i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) | ||
29 | 31 | ||
30 | /* Addresses to scan */ | ||
31 | static unsigned short normal_i2c[] = { | ||
32 | 0x84 >>1, | ||
33 | 0x86 >>1, | ||
34 | 0x96 >>1, | ||
35 | I2C_CLIENT_END, | ||
36 | }; | ||
37 | I2C_CLIENT_INSMOD; | ||
38 | |||
39 | /* insmod options */ | ||
40 | static unsigned int debug = 0; | ||
41 | module_param(debug, int, 0644); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | 32 | ||
44 | /* ---------------------------------------------------------------------- */ | 33 | /* ---------------------------------------------------------------------- */ |
45 | 34 | ||
46 | #define UNSET (-1U) | 35 | #define UNSET (-1U) |
47 | #define tda9887_info(fmt, arg...) do {\ | ||
48 | printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ | ||
49 | i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) | ||
50 | #define tda9887_dbg(fmt, arg...) do {\ | ||
51 | if (debug) \ | ||
52 | printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ | ||
53 | i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) | ||
54 | |||
55 | struct tda9887 { | ||
56 | struct i2c_client client; | ||
57 | v4l2_std_id std; | ||
58 | enum tuner_mode mode; | ||
59 | unsigned int config; | ||
60 | unsigned int using_v4l2; | ||
61 | unsigned int radio_mode; | ||
62 | unsigned char data[4]; | ||
63 | }; | ||
64 | 36 | ||
65 | struct tvnorm { | 37 | struct tvnorm { |
66 | v4l2_std_id std; | 38 | v4l2_std_id std; |
@@ -70,9 +42,6 @@ struct tvnorm { | |||
70 | unsigned char e; | 42 | unsigned char e; |
71 | }; | 43 | }; |
72 | 44 | ||
73 | static struct i2c_driver driver; | ||
74 | static struct i2c_client client_template; | ||
75 | |||
76 | /* ---------------------------------------------------------------------- */ | 45 | /* ---------------------------------------------------------------------- */ |
77 | 46 | ||
78 | // | 47 | // |
@@ -281,7 +250,7 @@ static struct tvnorm radio_mono = { | |||
281 | 250 | ||
282 | /* ---------------------------------------------------------------------- */ | 251 | /* ---------------------------------------------------------------------- */ |
283 | 252 | ||
284 | static void dump_read_message(struct tda9887 *t, unsigned char *buf) | 253 | static void dump_read_message(struct tuner *t, unsigned char *buf) |
285 | { | 254 | { |
286 | static char *afc[16] = { | 255 | static char *afc[16] = { |
287 | "- 12.5 kHz", | 256 | "- 12.5 kHz", |
@@ -309,7 +278,7 @@ static void dump_read_message(struct tda9887 *t, unsigned char *buf) | |||
309 | tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); | 278 | tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); |
310 | } | 279 | } |
311 | 280 | ||
312 | static void dump_write_message(struct tda9887 *t, unsigned char *buf) | 281 | static void dump_write_message(struct tuner *t, unsigned char *buf) |
313 | { | 282 | { |
314 | static char *sound[4] = { | 283 | static char *sound[4] = { |
315 | "AM/TV", | 284 | "AM/TV", |
@@ -405,13 +374,13 @@ static void dump_write_message(struct tda9887 *t, unsigned char *buf) | |||
405 | 374 | ||
406 | /* ---------------------------------------------------------------------- */ | 375 | /* ---------------------------------------------------------------------- */ |
407 | 376 | ||
408 | static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) | 377 | static int tda9887_set_tvnorm(struct tuner *t, char *buf) |
409 | { | 378 | { |
410 | struct tvnorm *norm = NULL; | 379 | struct tvnorm *norm = NULL; |
411 | int i; | 380 | int i; |
412 | 381 | ||
413 | if (t->mode == T_RADIO) { | 382 | if (t->mode == V4L2_TUNER_RADIO) { |
414 | if (t->radio_mode == V4L2_TUNER_MODE_MONO) | 383 | if (t->audmode == V4L2_TUNER_MODE_MONO) |
415 | norm = &radio_mono; | 384 | norm = &radio_mono; |
416 | else | 385 | else |
417 | norm = &radio_stereo; | 386 | norm = &radio_stereo; |
@@ -445,7 +414,7 @@ module_param(port2, int, 0644); | |||
445 | module_param(qss, int, 0644); | 414 | module_param(qss, int, 0644); |
446 | module_param(adjust, int, 0644); | 415 | module_param(adjust, int, 0644); |
447 | 416 | ||
448 | static int tda9887_set_insmod(struct tda9887 *t, char *buf) | 417 | static int tda9887_set_insmod(struct tuner *t, char *buf) |
449 | { | 418 | { |
450 | if (UNSET != port1) { | 419 | if (UNSET != port1) { |
451 | if (port1) | 420 | if (port1) |
@@ -474,27 +443,27 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) | |||
474 | return 0; | 443 | return 0; |
475 | } | 444 | } |
476 | 445 | ||
477 | static int tda9887_set_config(struct tda9887 *t, char *buf) | 446 | static int tda9887_set_config(struct tuner *t, char *buf) |
478 | { | 447 | { |
479 | if (t->config & TDA9887_PORT1_ACTIVE) | 448 | if (t->tda9887_config & TDA9887_PORT1_ACTIVE) |
480 | buf[1] &= ~cOutputPort1Inactive; | 449 | buf[1] &= ~cOutputPort1Inactive; |
481 | if (t->config & TDA9887_PORT1_INACTIVE) | 450 | if (t->tda9887_config & TDA9887_PORT1_INACTIVE) |
482 | buf[1] |= cOutputPort1Inactive; | 451 | buf[1] |= cOutputPort1Inactive; |
483 | if (t->config & TDA9887_PORT2_ACTIVE) | 452 | if (t->tda9887_config & TDA9887_PORT2_ACTIVE) |
484 | buf[1] &= ~cOutputPort2Inactive; | 453 | buf[1] &= ~cOutputPort2Inactive; |
485 | if (t->config & TDA9887_PORT2_INACTIVE) | 454 | if (t->tda9887_config & TDA9887_PORT2_INACTIVE) |
486 | buf[1] |= cOutputPort2Inactive; | 455 | buf[1] |= cOutputPort2Inactive; |
487 | 456 | ||
488 | if (t->config & TDA9887_QSS) | 457 | if (t->tda9887_config & TDA9887_QSS) |
489 | buf[1] |= cQSS; | 458 | buf[1] |= cQSS; |
490 | if (t->config & TDA9887_INTERCARRIER) | 459 | if (t->tda9887_config & TDA9887_INTERCARRIER) |
491 | buf[1] &= ~cQSS; | 460 | buf[1] &= ~cQSS; |
492 | 461 | ||
493 | if (t->config & TDA9887_AUTOMUTE) | 462 | if (t->tda9887_config & TDA9887_AUTOMUTE) |
494 | buf[1] |= cAutoMuteFmActive; | 463 | buf[1] |= cAutoMuteFmActive; |
495 | if (t->config & TDA9887_DEEMPHASIS_MASK) { | 464 | if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { |
496 | buf[2] &= ~0x60; | 465 | buf[2] &= ~0x60; |
497 | switch (t->config & TDA9887_DEEMPHASIS_MASK) { | 466 | switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { |
498 | case TDA9887_DEEMPHASIS_NONE: | 467 | case TDA9887_DEEMPHASIS_NONE: |
499 | buf[2] |= cDeemphasisOFF; | 468 | buf[2] |= cDeemphasisOFF; |
500 | break; | 469 | break; |
@@ -506,153 +475,36 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) | |||
506 | break; | 475 | break; |
507 | } | 476 | } |
508 | } | 477 | } |
509 | if (t->config & TDA9887_TOP_SET) { | 478 | if (t->tda9887_config & TDA9887_TOP_SET) { |
510 | buf[2] &= ~cTopMask; | 479 | buf[2] &= ~cTopMask; |
511 | buf[2] |= (t->config >> 8) & cTopMask; | 480 | buf[2] |= (t->tda9887_config >> 8) & cTopMask; |
512 | } | 481 | } |
513 | if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) | 482 | if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) |
514 | buf[1] &= ~cQSS; | 483 | buf[1] &= ~cQSS; |
515 | return 0; | 484 | return 0; |
516 | } | 485 | } |
517 | 486 | ||
518 | /* ---------------------------------------------------------------------- */ | 487 | /* ---------------------------------------------------------------------- */ |
519 | 488 | ||
520 | static char pal[] = "--"; | 489 | static int tda9887_status(struct tuner *t) |
521 | static char secam[] = "--"; | ||
522 | static char ntsc[] = "-"; | ||
523 | |||
524 | module_param_string(pal, pal, sizeof(pal), 0644); | ||
525 | module_param_string(secam, secam, sizeof(secam), 0644); | ||
526 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | ||
527 | |||
528 | static int tda9887_fixup_std(struct tda9887 *t) | ||
529 | { | ||
530 | /* get more precise norm info from insmod option */ | ||
531 | if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { | ||
532 | switch (pal[0]) { | ||
533 | case 'b': | ||
534 | case 'B': | ||
535 | case 'g': | ||
536 | case 'G': | ||
537 | case 'h': | ||
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 | } | ||
548 | break; | ||
549 | case 'i': | ||
550 | case 'I': | ||
551 | tda9887_dbg("insmod fixup: PAL => PAL-I\n"); | ||
552 | t->std = V4L2_STD_PAL_I; | ||
553 | break; | ||
554 | case 'd': | ||
555 | case 'D': | ||
556 | case 'k': | ||
557 | case 'K': | ||
558 | tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); | ||
559 | t->std = V4L2_STD_PAL_DK; | ||
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; | ||
566 | case '-': | ||
567 | /* default parameter, do nothing */ | ||
568 | break; | ||
569 | default: | ||
570 | tda9887_info("pal= argument not recognised\n"); | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
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; | ||
585 | case 'd': | ||
586 | case 'D': | ||
587 | case 'k': | ||
588 | case 'K': | ||
589 | tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n"); | ||
590 | t->std = V4L2_STD_SECAM_DK; | ||
591 | break; | ||
592 | case 'l': | ||
593 | case 'L': | ||
594 | if (secam[1] == 'c' || secam[1] == 'C') { | ||
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 | } | ||
601 | break; | ||
602 | case '-': | ||
603 | /* default parameter, do nothing */ | ||
604 | break; | ||
605 | default: | ||
606 | tda9887_info("secam= argument not recognised\n"); | ||
607 | break; | ||
608 | } | ||
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 'k': | ||
623 | case 'K': | ||
624 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); | ||
625 | t->std = V4L2_STD_NTSC_M_KR; | ||
626 | break; | ||
627 | case '-': | ||
628 | /* default parameter, do nothing */ | ||
629 | break; | ||
630 | default: | ||
631 | tda9887_info("ntsc= argument not recognised\n"); | ||
632 | break; | ||
633 | } | ||
634 | } | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int tda9887_status(struct tda9887 *t) | ||
639 | { | 490 | { |
640 | unsigned char buf[1]; | 491 | unsigned char buf[1]; |
641 | int rc; | 492 | int rc; |
642 | 493 | ||
643 | memset(buf,0,sizeof(buf)); | 494 | memset(buf,0,sizeof(buf)); |
644 | if (1 != (rc = i2c_master_recv(&t->client,buf,1))) | 495 | if (1 != (rc = i2c_master_recv(&t->i2c,buf,1))) |
645 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); | 496 | tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); |
646 | dump_read_message(t, buf); | 497 | dump_read_message(t, buf); |
647 | return 0; | 498 | return 0; |
648 | } | 499 | } |
649 | 500 | ||
650 | static int tda9887_configure(struct tda9887 *t) | 501 | static void tda9887_configure(struct i2c_client *client) |
651 | { | 502 | { |
503 | struct tuner *t = i2c_get_clientdata(client); | ||
652 | int rc; | 504 | int rc; |
653 | 505 | ||
654 | memset(t->data,0,sizeof(t->data)); | 506 | memset(t->tda9887_data,0,sizeof(t->tda9887_data)); |
655 | tda9887_set_tvnorm(t,t->data); | 507 | tda9887_set_tvnorm(t,t->tda9887_data); |
656 | 508 | ||
657 | /* A note on the port settings: | 509 | /* A note on the port settings: |
658 | These settings tend to depend on the specifics of the board. | 510 | These settings tend to depend on the specifics of the board. |
@@ -667,249 +519,84 @@ static int tda9887_configure(struct tda9887 *t) | |||
667 | the ports should be set to active (0), but, again, that may | 519 | the ports should be set to active (0), but, again, that may |
668 | differ depending on the precise hardware configuration. | 520 | differ depending on the precise hardware configuration. |
669 | */ | 521 | */ |
670 | t->data[1] |= cOutputPort1Inactive; | 522 | t->tda9887_data[1] |= cOutputPort1Inactive; |
671 | t->data[1] |= cOutputPort2Inactive; | 523 | t->tda9887_data[1] |= cOutputPort2Inactive; |
672 | 524 | ||
673 | tda9887_set_config(t,t->data); | 525 | tda9887_set_config(t,t->tda9887_data); |
674 | tda9887_set_insmod(t,t->data); | 526 | tda9887_set_insmod(t,t->tda9887_data); |
675 | 527 | ||
676 | if (t->mode == T_STANDBY) { | 528 | if (t->mode == T_STANDBY) { |
677 | t->data[1] |= cForcedMuteAudioON; | 529 | t->tda9887_data[1] |= cForcedMuteAudioON; |
678 | } | 530 | } |
679 | 531 | ||
680 | tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", | 532 | tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", |
681 | t->data[1],t->data[2],t->data[3]); | 533 | t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]); |
682 | if (debug > 1) | 534 | if (tuner_debug > 1) |
683 | dump_write_message(t, t->data); | 535 | dump_write_message(t, t->tda9887_data); |
684 | 536 | ||
685 | if (4 != (rc = i2c_master_send(&t->client,t->data,4))) | 537 | if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4))) |
686 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); | 538 | tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); |
687 | 539 | ||
688 | if (debug > 2) { | 540 | if (tuner_debug > 2) { |
689 | msleep_interruptible(1000); | 541 | msleep_interruptible(1000); |
690 | tda9887_status(t); | 542 | tda9887_status(t); |
691 | } | 543 | } |
692 | return 0; | ||
693 | } | 544 | } |
694 | 545 | ||
695 | /* ---------------------------------------------------------------------- */ | 546 | /* ---------------------------------------------------------------------- */ |
696 | 547 | ||
697 | static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) | 548 | static void tda9887_tuner_status(struct i2c_client *client) |
698 | { | 549 | { |
699 | struct tda9887 *t; | 550 | struct tuner *t = i2c_get_clientdata(client); |
700 | 551 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]); | |
701 | client_template.adapter = adap; | ||
702 | client_template.addr = addr; | ||
703 | |||
704 | if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) | ||
705 | return -ENOMEM; | ||
706 | |||
707 | t->client = client_template; | ||
708 | t->std = 0; | ||
709 | t->radio_mode = V4L2_TUNER_MODE_STEREO; | ||
710 | |||
711 | tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); | ||
712 | |||
713 | i2c_set_clientdata(&t->client, t); | ||
714 | i2c_attach_client(&t->client); | ||
715 | |||
716 | return 0; | ||
717 | } | 552 | } |
718 | 553 | ||
719 | static int tda9887_probe(struct i2c_adapter *adap) | 554 | static int tda9887_get_afc(struct i2c_client *client) |
720 | { | 555 | { |
721 | if (adap->class & I2C_CLASS_TV_ANALOG) | 556 | struct tuner *t = i2c_get_clientdata(client); |
722 | return i2c_probe(adap, &addr_data, tda9887_attach); | 557 | static int AFC_BITS_2_kHz[] = { |
723 | return 0; | 558 | -12500, -37500, -62500, -97500, |
724 | } | 559 | -112500, -137500, -162500, -187500, |
560 | 187500, 162500, 137500, 112500, | ||
561 | 97500 , 62500, 37500 , 12500 | ||
562 | }; | ||
563 | int afc=0; | ||
564 | __u8 reg = 0; | ||
725 | 565 | ||
726 | static int tda9887_detach(struct i2c_client *client) | 566 | if (1 == i2c_master_recv(&t->i2c,®,1)) |
727 | { | 567 | afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; |
728 | struct tda9887 *t = i2c_get_clientdata(client); | ||
729 | 568 | ||
730 | i2c_detach_client(client); | 569 | return afc; |
731 | kfree(t); | ||
732 | return 0; | ||
733 | } | 570 | } |
734 | 571 | ||
735 | #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ | 572 | static void tda9887_standby(struct i2c_client *client) |
736 | tda9887_info("switching to v4l2\n"); \ | ||
737 | t->using_v4l2 = 1; | ||
738 | #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ | ||
739 | tda9887_info("ignore v4l1 call\n"); \ | ||
740 | return 0; } | ||
741 | |||
742 | static int | ||
743 | tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
744 | { | 573 | { |
745 | struct tda9887 *t = i2c_get_clientdata(client); | 574 | tda9887_configure(client); |
746 | |||
747 | switch (cmd) { | ||
748 | |||
749 | /* --- configuration --- */ | ||
750 | case AUDC_SET_RADIO: | ||
751 | { | ||
752 | t->mode = T_RADIO; | ||
753 | tda9887_configure(t); | ||
754 | break; | ||
755 | } | ||
756 | case TUNER_SET_STANDBY: | ||
757 | { | ||
758 | t->mode = T_STANDBY; | ||
759 | tda9887_configure(t); | ||
760 | break; | ||
761 | } | ||
762 | case TDA9887_SET_CONFIG: | ||
763 | { | ||
764 | int *i = arg; | ||
765 | |||
766 | t->config = *i; | ||
767 | tda9887_configure(t); | ||
768 | break; | ||
769 | } | ||
770 | /* --- v4l ioctls --- */ | ||
771 | /* take care: bttv does userspace copying, we'll get a | ||
772 | kernel pointer here... */ | ||
773 | case VIDIOCSCHAN: | ||
774 | { | ||
775 | static const v4l2_std_id map[] = { | ||
776 | [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, | ||
777 | [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, | ||
778 | [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, | ||
779 | [ 4 /* bttv */ ] = V4L2_STD_PAL_M, | ||
780 | [ 5 /* bttv */ ] = V4L2_STD_PAL_N, | ||
781 | [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, | ||
782 | }; | ||
783 | struct video_channel *vc = arg; | ||
784 | |||
785 | CHECK_V4L2; | ||
786 | t->mode = T_ANALOG_TV; | ||
787 | if (vc->norm < ARRAY_SIZE(map)) | ||
788 | t->std = map[vc->norm]; | ||
789 | tda9887_fixup_std(t); | ||
790 | tda9887_configure(t); | ||
791 | break; | ||
792 | } | ||
793 | case VIDIOC_S_STD: | ||
794 | { | ||
795 | v4l2_std_id *id = arg; | ||
796 | |||
797 | SWITCH_V4L2; | ||
798 | t->mode = T_ANALOG_TV; | ||
799 | t->std = *id; | ||
800 | tda9887_fixup_std(t); | ||
801 | tda9887_configure(t); | ||
802 | break; | ||
803 | } | ||
804 | case VIDIOC_S_FREQUENCY: | ||
805 | { | ||
806 | struct v4l2_frequency *f = arg; | ||
807 | |||
808 | SWITCH_V4L2; | ||
809 | if (V4L2_TUNER_ANALOG_TV == f->type) { | ||
810 | if (t->mode == T_ANALOG_TV) | ||
811 | return 0; | ||
812 | t->mode = T_ANALOG_TV; | ||
813 | } | ||
814 | if (V4L2_TUNER_RADIO == f->type) { | ||
815 | if (t->mode == T_RADIO) | ||
816 | return 0; | ||
817 | t->mode = T_RADIO; | ||
818 | } | ||
819 | tda9887_configure(t); | ||
820 | break; | ||
821 | } | ||
822 | case VIDIOC_G_TUNER: | ||
823 | { | ||
824 | static int AFC_BITS_2_kHz[] = { | ||
825 | -12500, -37500, -62500, -97500, | ||
826 | -112500, -137500, -162500, -187500, | ||
827 | 187500, 162500, 137500, 112500, | ||
828 | 97500 , 62500, 37500 , 12500 | ||
829 | }; | ||
830 | struct v4l2_tuner* tuner = arg; | ||
831 | |||
832 | if (t->mode == T_RADIO) { | ||
833 | __u8 reg = 0; | ||
834 | tuner->afc=0; | ||
835 | if (1 == i2c_master_recv(&t->client,®,1)) | ||
836 | tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; | ||
837 | } | ||
838 | break; | ||
839 | } | ||
840 | case VIDIOC_S_TUNER: | ||
841 | { | ||
842 | struct v4l2_tuner* tuner = arg; | ||
843 | |||
844 | if (t->mode == T_RADIO) { | ||
845 | t->radio_mode = tuner->audmode; | ||
846 | tda9887_configure (t); | ||
847 | } | ||
848 | break; | ||
849 | } | ||
850 | case VIDIOC_LOG_STATUS: | ||
851 | { | ||
852 | tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]); | ||
853 | break; | ||
854 | } | ||
855 | default: | ||
856 | /* nothing */ | ||
857 | break; | ||
858 | } | ||
859 | return 0; | ||
860 | } | 575 | } |
861 | 576 | ||
862 | static int tda9887_suspend(struct device * dev, pm_message_t state) | 577 | static void tda9887_set_freq(struct i2c_client *client, unsigned int freq) |
863 | { | 578 | { |
864 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 579 | tda9887_configure(client); |
865 | struct tda9887 *t = i2c_get_clientdata(c); | ||
866 | |||
867 | tda9887_dbg("suspend\n"); | ||
868 | return 0; | ||
869 | } | 580 | } |
870 | 581 | ||
871 | static int tda9887_resume(struct device * dev) | 582 | int tda9887_tuner_init(struct i2c_client *c) |
872 | { | 583 | { |
873 | struct i2c_client *c = container_of(dev, struct i2c_client, dev); | 584 | struct tuner *t = i2c_get_clientdata(c); |
874 | struct tda9887 *t = i2c_get_clientdata(c); | ||
875 | 585 | ||
876 | tda9887_dbg("resume\n"); | 586 | strlcpy(c->name, "tda9887", sizeof(c->name)); |
877 | tda9887_configure(t); | ||
878 | return 0; | ||
879 | } | ||
880 | 587 | ||
881 | /* ----------------------------------------------------------------------- */ | 588 | tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, |
882 | 589 | t->i2c.driver->driver.name); | |
883 | static struct i2c_driver driver = { | ||
884 | .id = I2C_DRIVERID_TDA9887, | ||
885 | .attach_adapter = tda9887_probe, | ||
886 | .detach_client = tda9887_detach, | ||
887 | .command = tda9887_command, | ||
888 | .driver = { | ||
889 | .name = "tda9887", | ||
890 | .suspend = tda9887_suspend, | ||
891 | .resume = tda9887_resume, | ||
892 | }, | ||
893 | }; | ||
894 | static struct i2c_client client_template = | ||
895 | { | ||
896 | .name = "tda9887", | ||
897 | .driver = &driver, | ||
898 | }; | ||
899 | 590 | ||
900 | static int __init tda9887_init_module(void) | 591 | t->set_tv_freq = tda9887_set_freq; |
901 | { | 592 | t->set_radio_freq = tda9887_set_freq; |
902 | return i2c_add_driver(&driver); | 593 | t->standby = tda9887_standby; |
903 | } | 594 | t->tuner_status=tda9887_tuner_status; |
595 | t->get_afc=tda9887_get_afc; | ||
904 | 596 | ||
905 | static void __exit tda9887_cleanup_module(void) | 597 | return 0; |
906 | { | ||
907 | i2c_del_driver(&driver); | ||
908 | } | 598 | } |
909 | 599 | ||
910 | module_init(tda9887_init_module); | ||
911 | module_exit(tda9887_cleanup_module); | ||
912 | |||
913 | /* | 600 | /* |
914 | * Overrides for Emacs so that we follow Linus's tabbing style. | 601 | * Overrides for Emacs so that we follow Linus's tabbing style. |
915 | * --------------------------------------------------------------------------- | 602 | * --------------------------------------------------------------------------- |