diff options
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r-- | drivers/media/video/saa7115.c | 319 |
1 files changed, 150 insertions, 169 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 29e28c742cd4..4a4bc69fb0e9 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -39,31 +39,18 @@ | |||
39 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
40 | #include <linux/videodev2.h> | 40 | #include <linux/videodev2.h> |
41 | #include <media/v4l2-common.h> | 41 | #include <media/v4l2-common.h> |
42 | #include <media/audiochip.h> | ||
43 | #include <asm/div64.h> | ||
42 | 44 | ||
43 | MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); | 45 | MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); |
44 | MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); | 46 | MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); |
45 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
46 | 48 | ||
47 | static int debug = 0; | 49 | static int debug = 0; |
48 | module_param(debug, int, 0644); | 50 | module_param(debug, bool, 0644); |
49 | 51 | ||
50 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 52 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
51 | 53 | ||
52 | #define saa7115_dbg(fmt,arg...) \ | ||
53 | do { \ | ||
54 | if (debug) \ | ||
55 | printk(KERN_INFO "%s debug %d-%04x: " fmt, \ | ||
56 | client->driver->driver.name, \ | ||
57 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
58 | } while (0) | ||
59 | |||
60 | #define saa7115_err(fmt, arg...) do { \ | ||
61 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \ | ||
62 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
63 | #define saa7115_info(fmt, arg...) do { \ | ||
64 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \ | ||
65 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
66 | |||
67 | static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; | 54 | static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; |
68 | 55 | ||
69 | 56 | ||
@@ -73,12 +60,13 @@ struct saa7115_state { | |||
73 | v4l2_std_id std; | 60 | v4l2_std_id std; |
74 | int input; | 61 | int input; |
75 | int enable; | 62 | int enable; |
63 | int radio; | ||
76 | int bright; | 64 | int bright; |
77 | int contrast; | 65 | int contrast; |
78 | int hue; | 66 | int hue; |
79 | int sat; | 67 | int sat; |
80 | enum v4l2_chip_ident ident; | 68 | enum v4l2_chip_ident ident; |
81 | enum v4l2_audio_clock_freq audclk_freq; | 69 | u32 audclk_freq; |
82 | }; | 70 | }; |
83 | 71 | ||
84 | /* ----------------------------------------------------------------------- */ | 72 | /* ----------------------------------------------------------------------- */ |
@@ -469,80 +457,6 @@ static const unsigned char saa7115_init_misc[] = { | |||
469 | 0x00, 0x00 | 457 | 0x00, 0x00 |
470 | }; | 458 | }; |
471 | 459 | ||
472 | /* ============== SAA7715 AUDIO settings ============= */ | ||
473 | |||
474 | /* 48.0 kHz */ | ||
475 | static const unsigned char saa7115_cfg_48_audio[] = { | ||
476 | 0x34, 0xce, | ||
477 | 0x35, 0xfb, | ||
478 | 0x36, 0x30, | ||
479 | 0x00, 0x00 | ||
480 | }; | ||
481 | |||
482 | /* 44.1 kHz */ | ||
483 | static const unsigned char saa7115_cfg_441_audio[] = { | ||
484 | 0x34, 0xf2, | ||
485 | 0x35, 0x00, | ||
486 | 0x36, 0x2d, | ||
487 | 0x00, 0x00 | ||
488 | }; | ||
489 | |||
490 | /* 32.0 kHz */ | ||
491 | static const unsigned char saa7115_cfg_32_audio[] = { | ||
492 | 0x34, 0xdf, | ||
493 | 0x35, 0xa7, | ||
494 | 0x36, 0x20, | ||
495 | 0x00, 0x00 | ||
496 | }; | ||
497 | |||
498 | /* 48.0 kHz 60hz */ | ||
499 | static const unsigned char saa7115_cfg_60hz_48_audio[] = { | ||
500 | 0x30, 0xcd, | ||
501 | 0x31, 0x20, | ||
502 | 0x32, 0x03, | ||
503 | 0x00, 0x00 | ||
504 | }; | ||
505 | |||
506 | /* 48.0 kHz 50hz */ | ||
507 | static const unsigned char saa7115_cfg_50hz_48_audio[] = { | ||
508 | 0x30, 0x00, | ||
509 | 0x31, 0xc0, | ||
510 | 0x32, 0x03, | ||
511 | 0x00, 0x00 | ||
512 | }; | ||
513 | |||
514 | /* 44.1 kHz 60hz */ | ||
515 | static const unsigned char saa7115_cfg_60hz_441_audio[] = { | ||
516 | 0x30, 0xbc, | ||
517 | 0x31, 0xdf, | ||
518 | 0x32, 0x02, | ||
519 | 0x00, 0x00 | ||
520 | }; | ||
521 | |||
522 | /* 44.1 kHz 50hz */ | ||
523 | static const unsigned char saa7115_cfg_50hz_441_audio[] = { | ||
524 | 0x30, 0x00, | ||
525 | 0x31, 0x72, | ||
526 | 0x32, 0x03, | ||
527 | 0x00, 0x00 | ||
528 | }; | ||
529 | |||
530 | /* 32.0 kHz 60hz */ | ||
531 | static const unsigned char saa7115_cfg_60hz_32_audio[] = { | ||
532 | 0x30, 0xde, | ||
533 | 0x31, 0x15, | ||
534 | 0x32, 0x02, | ||
535 | 0x00, 0x00 | ||
536 | }; | ||
537 | |||
538 | /* 32.0 kHz 50hz */ | ||
539 | static const unsigned char saa7115_cfg_50hz_32_audio[] = { | ||
540 | 0x30, 0x00, | ||
541 | 0x31, 0x80, | ||
542 | 0x32, 0x02, | ||
543 | 0x00, 0x00 | ||
544 | }; | ||
545 | |||
546 | static int saa7115_odd_parity(u8 c) | 460 | static int saa7115_odd_parity(u8 c) |
547 | { | 461 | { |
548 | c ^= (c >> 4); | 462 | c ^= (c >> 4); |
@@ -627,40 +541,38 @@ static int saa7115_decode_wss(u8 * p) | |||
627 | } | 541 | } |
628 | 542 | ||
629 | 543 | ||
630 | static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) | 544 | static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq) |
631 | { | 545 | { |
632 | struct saa7115_state *state = i2c_get_clientdata(client); | 546 | struct saa7115_state *state = i2c_get_clientdata(client); |
547 | u32 acpf; | ||
548 | u32 acni; | ||
549 | u32 hz; | ||
550 | u64 f; | ||
633 | 551 | ||
634 | saa7115_dbg("set audio clock freq: %d\n", freq); | 552 | v4l_dbg(1, client, "set audio clock freq: %d\n", freq); |
635 | switch (freq) { | 553 | |
636 | case V4L2_AUDCLK_32_KHZ: | 554 | /* sanity check */ |
637 | saa7115_writeregs(client, saa7115_cfg_32_audio); | 555 | if (freq < 32000 || freq > 48000) |
638 | if (state->std & V4L2_STD_525_60) { | 556 | return -EINVAL; |
639 | saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); | 557 | |
640 | } else { | 558 | /* hz is the refresh rate times 100 */ |
641 | saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); | 559 | hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; |
642 | } | 560 | /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ |
643 | break; | 561 | acpf = (25600 * freq) / hz; |
644 | case V4L2_AUDCLK_441_KHZ: | 562 | /* acni = (256 * freq * 2^23) / crystal_frequency = |
645 | saa7115_writeregs(client, saa7115_cfg_441_audio); | 563 | (freq * 2^(8+23)) / crystal_frequency = |
646 | if (state->std & V4L2_STD_525_60) { | 564 | (freq << 31) / 32.11 MHz */ |
647 | saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); | 565 | f = freq; |
648 | } else { | 566 | f = f << 31; |
649 | saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); | 567 | do_div(f, 32110000); |
650 | } | 568 | acni = f; |
651 | break; | 569 | |
652 | case V4L2_AUDCLK_48_KHZ: | 570 | saa7115_write(client, 0x30, acpf & 0xff); |
653 | saa7115_writeregs(client, saa7115_cfg_48_audio); | 571 | saa7115_write(client, 0x31, (acpf >> 8) & 0xff); |
654 | if (state->std & V4L2_STD_525_60) { | 572 | saa7115_write(client, 0x32, (acpf >> 16) & 0x03); |
655 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | 573 | saa7115_write(client, 0x34, acni & 0xff); |
656 | } else { | 574 | saa7115_write(client, 0x35, (acni >> 8) & 0xff); |
657 | saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); | 575 | saa7115_write(client, 0x36, (acni >> 16) & 0x3f); |
658 | } | ||
659 | break; | ||
660 | default: | ||
661 | saa7115_dbg("invalid audio setting %d\n", freq); | ||
662 | return -EINVAL; | ||
663 | } | ||
664 | state->audclk_freq = freq; | 576 | state->audclk_freq = freq; |
665 | return 0; | 577 | return 0; |
666 | } | 578 | } |
@@ -672,7 +584,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
672 | switch (ctrl->id) { | 584 | switch (ctrl->id) { |
673 | case V4L2_CID_BRIGHTNESS: | 585 | case V4L2_CID_BRIGHTNESS: |
674 | if (ctrl->value < 0 || ctrl->value > 255) { | 586 | if (ctrl->value < 0 || ctrl->value > 255) { |
675 | saa7115_err("invalid brightness setting %d\n", ctrl->value); | 587 | v4l_err(client, "invalid brightness setting %d\n", ctrl->value); |
676 | return -ERANGE; | 588 | return -ERANGE; |
677 | } | 589 | } |
678 | 590 | ||
@@ -682,7 +594,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
682 | 594 | ||
683 | case V4L2_CID_CONTRAST: | 595 | case V4L2_CID_CONTRAST: |
684 | if (ctrl->value < 0 || ctrl->value > 127) { | 596 | if (ctrl->value < 0 || ctrl->value > 127) { |
685 | saa7115_err("invalid contrast setting %d\n", ctrl->value); | 597 | v4l_err(client, "invalid contrast setting %d\n", ctrl->value); |
686 | return -ERANGE; | 598 | return -ERANGE; |
687 | } | 599 | } |
688 | 600 | ||
@@ -692,7 +604,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
692 | 604 | ||
693 | case V4L2_CID_SATURATION: | 605 | case V4L2_CID_SATURATION: |
694 | if (ctrl->value < 0 || ctrl->value > 127) { | 606 | if (ctrl->value < 0 || ctrl->value > 127) { |
695 | saa7115_err("invalid saturation setting %d\n", ctrl->value); | 607 | v4l_err(client, "invalid saturation setting %d\n", ctrl->value); |
696 | return -ERANGE; | 608 | return -ERANGE; |
697 | } | 609 | } |
698 | 610 | ||
@@ -702,13 +614,16 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
702 | 614 | ||
703 | case V4L2_CID_HUE: | 615 | case V4L2_CID_HUE: |
704 | if (ctrl->value < -127 || ctrl->value > 127) { | 616 | if (ctrl->value < -127 || ctrl->value > 127) { |
705 | saa7115_err("invalid hue setting %d\n", ctrl->value); | 617 | v4l_err(client, "invalid hue setting %d\n", ctrl->value); |
706 | return -ERANGE; | 618 | return -ERANGE; |
707 | } | 619 | } |
708 | 620 | ||
709 | state->hue = ctrl->value; | 621 | state->hue = ctrl->value; |
710 | saa7115_write(client, 0x0d, state->hue); | 622 | saa7115_write(client, 0x0d, state->hue); |
711 | break; | 623 | break; |
624 | |||
625 | default: | ||
626 | return -EINVAL; | ||
712 | } | 627 | } |
713 | 628 | ||
714 | return 0; | 629 | return 0; |
@@ -743,12 +658,22 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
743 | struct saa7115_state *state = i2c_get_clientdata(client); | 658 | struct saa7115_state *state = i2c_get_clientdata(client); |
744 | int taskb = saa7115_read(client, 0x80) & 0x10; | 659 | int taskb = saa7115_read(client, 0x80) & 0x10; |
745 | 660 | ||
661 | /* Prevent unnecessary standard changes. During a standard | ||
662 | change the I-Port is temporarily disabled. Any devices | ||
663 | reading from that port can get confused. | ||
664 | Note that VIDIOC_S_STD is also used to switch from | ||
665 | radio to TV mode, so if a VIDIOC_S_STD is broadcast to | ||
666 | all I2C devices then you do not want to have an unwanted | ||
667 | side-effect here. */ | ||
668 | if (std == state->std) | ||
669 | return; | ||
670 | |||
746 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | 671 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. |
747 | if (std & V4L2_STD_525_60) { | 672 | if (std & V4L2_STD_525_60) { |
748 | saa7115_dbg("decoder set standard 60 Hz\n"); | 673 | v4l_dbg(1, client, "decoder set standard 60 Hz\n"); |
749 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | 674 | saa7115_writeregs(client, saa7115_cfg_60hz_video); |
750 | } else { | 675 | } else { |
751 | saa7115_dbg("decoder set standard 50 Hz\n"); | 676 | v4l_dbg(1, client, "decoder set standard 50 Hz\n"); |
752 | saa7115_writeregs(client, saa7115_cfg_50hz_video); | 677 | saa7115_writeregs(client, saa7115_cfg_50hz_video); |
753 | } | 678 | } |
754 | 679 | ||
@@ -773,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) | |||
773 | static void saa7115_log_status(struct i2c_client *client) | 698 | static void saa7115_log_status(struct i2c_client *client) |
774 | { | 699 | { |
775 | struct saa7115_state *state = i2c_get_clientdata(client); | 700 | struct saa7115_state *state = i2c_get_clientdata(client); |
776 | char *audfreq = "undefined"; | ||
777 | int reg1e, reg1f; | 701 | int reg1e, reg1f; |
778 | int signalOk; | 702 | int signalOk; |
779 | int vcr; | 703 | int vcr; |
780 | 704 | ||
781 | switch (state->audclk_freq) { | 705 | v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); |
782 | case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break; | ||
783 | case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break; | ||
784 | case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break; | ||
785 | } | ||
786 | |||
787 | saa7115_info("Audio frequency: %s\n", audfreq); | ||
788 | if (client->name[6] == '4') { | 706 | if (client->name[6] == '4') { |
789 | /* status for the saa7114 */ | 707 | /* status for the saa7114 */ |
790 | reg1f = saa7115_read(client, 0x1f); | 708 | reg1f = saa7115_read(client, 0x1f); |
791 | signalOk = (reg1f & 0xc1) == 0x81; | 709 | signalOk = (reg1f & 0xc1) == 0x81; |
792 | saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); | 710 | v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad"); |
793 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | 711 | v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); |
794 | return; | 712 | return; |
795 | } | 713 | } |
796 | 714 | ||
@@ -801,21 +719,26 @@ static void saa7115_log_status(struct i2c_client *client) | |||
801 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; | 719 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; |
802 | vcr = !(reg1f & 0x10); | 720 | vcr = !(reg1f & 0x10); |
803 | 721 | ||
804 | saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | 722 | if (state->input >= 6) { |
805 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | 723 | v4l_info(client, "Input: S-Video %d\n", state->input - 6); |
724 | } else { | ||
725 | v4l_info(client, "Input: Composite %d\n", state->input); | ||
726 | } | ||
727 | v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
728 | v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); | ||
806 | 729 | ||
807 | switch (reg1e & 0x03) { | 730 | switch (reg1e & 0x03) { |
808 | case 1: | 731 | case 1: |
809 | saa7115_info("Detected format: NTSC\n"); | 732 | v4l_info(client, "Detected format: NTSC\n"); |
810 | break; | 733 | break; |
811 | case 2: | 734 | case 2: |
812 | saa7115_info("Detected format: PAL\n"); | 735 | v4l_info(client, "Detected format: PAL\n"); |
813 | break; | 736 | break; |
814 | case 3: | 737 | case 3: |
815 | saa7115_info("Detected format: SECAM\n"); | 738 | v4l_info(client, "Detected format: SECAM\n"); |
816 | break; | 739 | break; |
817 | default: | 740 | default: |
818 | saa7115_info("Detected format: BW/No color\n"); | 741 | v4l_info(client, "Detected format: BW/No color\n"); |
819 | break; | 742 | break; |
820 | } | 743 | } |
821 | } | 744 | } |
@@ -940,7 +863,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
940 | 863 | ||
941 | pix = &(fmt->fmt.pix); | 864 | pix = &(fmt->fmt.pix); |
942 | 865 | ||
943 | saa7115_dbg("decoder set size\n"); | 866 | v4l_dbg(1, client, "decoder set size\n"); |
944 | 867 | ||
945 | /* FIXME need better bounds checking here */ | 868 | /* FIXME need better bounds checking here */ |
946 | if ((pix->width < 1) || (pix->width > 1440)) | 869 | if ((pix->width < 1) || (pix->width > 1440)) |
@@ -966,7 +889,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
966 | HPSC = HPSC ? HPSC : 1; | 889 | HPSC = HPSC ? HPSC : 1; |
967 | HFSC = (int)((1024 * 720) / (HPSC * pix->width)); | 890 | HFSC = (int)((1024 * 720) / (HPSC * pix->width)); |
968 | 891 | ||
969 | saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); | 892 | v4l_dbg(1, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); |
970 | /* FIXME hardcodes to "Task B" | 893 | /* FIXME hardcodes to "Task B" |
971 | * write H prescaler integer */ | 894 | * write H prescaler integer */ |
972 | saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); | 895 | saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); |
@@ -980,10 +903,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
980 | saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); | 903 | saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); |
981 | } else { | 904 | } else { |
982 | if (is_50hz) { | 905 | if (is_50hz) { |
983 | saa7115_dbg("Setting full 50hz width\n"); | 906 | v4l_dbg(1, client, "Setting full 50hz width\n"); |
984 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); | 907 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); |
985 | } else { | 908 | } else { |
986 | saa7115_dbg("Setting full 60hz width\n"); | 909 | v4l_dbg(1, client, "Setting full 60hz width\n"); |
987 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | 910 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); |
988 | } | 911 | } |
989 | } | 912 | } |
@@ -992,7 +915,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
992 | 915 | ||
993 | if (pix->height != Vsrc) { | 916 | if (pix->height != Vsrc) { |
994 | VSCY = (int)((1024 * Vsrc) / pix->height); | 917 | VSCY = (int)((1024 * Vsrc) / pix->height); |
995 | saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); | 918 | v4l_dbg(1, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); |
996 | 919 | ||
997 | /* Correct Contrast and Luminance */ | 920 | /* Correct Contrast and Luminance */ |
998 | saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); | 921 | saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); |
@@ -1006,10 +929,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
1006 | saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); | 929 | saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); |
1007 | } else { | 930 | } else { |
1008 | if (is_50hz) { | 931 | if (is_50hz) { |
1009 | saa7115_dbg("Setting full 50Hz height\n"); | 932 | v4l_dbg(1, client, "Setting full 50Hz height\n"); |
1010 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); | 933 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); |
1011 | } else { | 934 | } else { |
1012 | saa7115_dbg("Setting full 60hz height\n"); | 935 | v4l_dbg(1, client, "Setting full 60hz height\n"); |
1013 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | 936 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); |
1014 | } | 937 | } |
1015 | } | 938 | } |
@@ -1089,6 +1012,48 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, | |||
1089 | 1012 | ||
1090 | /* ============ SAA7115 AUDIO settings (end) ============= */ | 1013 | /* ============ SAA7115 AUDIO settings (end) ============= */ |
1091 | 1014 | ||
1015 | static struct v4l2_queryctrl saa7115_qctrl[] = { | ||
1016 | { | ||
1017 | .id = V4L2_CID_BRIGHTNESS, | ||
1018 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1019 | .name = "Brightness", | ||
1020 | .minimum = 0, | ||
1021 | .maximum = 255, | ||
1022 | .step = 1, | ||
1023 | .default_value = 128, | ||
1024 | .flags = 0, | ||
1025 | }, { | ||
1026 | .id = V4L2_CID_CONTRAST, | ||
1027 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1028 | .name = "Contrast", | ||
1029 | .minimum = 0, | ||
1030 | .maximum = 255, | ||
1031 | .step = 1, | ||
1032 | .default_value = 64, | ||
1033 | .flags = 0, | ||
1034 | }, { | ||
1035 | .id = V4L2_CID_SATURATION, | ||
1036 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1037 | .name = "Saturation", | ||
1038 | .minimum = 0, | ||
1039 | .maximum = 255, | ||
1040 | .step = 1, | ||
1041 | .default_value = 64, | ||
1042 | .flags = 0, | ||
1043 | }, { | ||
1044 | .id = V4L2_CID_HUE, | ||
1045 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1046 | .name = "Hue", | ||
1047 | .minimum = -128, | ||
1048 | .maximum = 127, | ||
1049 | .step = 1, | ||
1050 | .default_value = 0, | ||
1051 | .flags = 0, | ||
1052 | }, | ||
1053 | }; | ||
1054 | |||
1055 | /* ----------------------------------------------------------------------- */ | ||
1056 | |||
1092 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | 1057 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) |
1093 | { | 1058 | { |
1094 | struct saa7115_state *state = i2c_get_clientdata(client); | 1059 | struct saa7115_state *state = i2c_get_clientdata(client); |
@@ -1103,16 +1068,18 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1103 | return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); | 1068 | return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); |
1104 | 1069 | ||
1105 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | 1070 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: |
1106 | return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); | 1071 | return saa7115_set_audio_clock_freq(client, *(u32 *)arg); |
1107 | 1072 | ||
1108 | case VIDIOC_G_TUNER: | 1073 | case VIDIOC_G_TUNER: |
1109 | { | 1074 | { |
1110 | struct v4l2_tuner *vt = arg; | 1075 | struct v4l2_tuner *vt = arg; |
1111 | int status; | 1076 | int status; |
1112 | 1077 | ||
1078 | if (state->radio) | ||
1079 | break; | ||
1113 | status = saa7115_read(client, 0x1f); | 1080 | status = saa7115_read(client, 0x1f); |
1114 | 1081 | ||
1115 | saa7115_dbg("status: 0x%02x\n", status); | 1082 | v4l_dbg(1, client, "status: 0x%02x\n", status); |
1116 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; | 1083 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; |
1117 | break; | 1084 | break; |
1118 | } | 1085 | } |
@@ -1127,20 +1094,38 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1127 | case VIDIOC_S_CTRL: | 1094 | case VIDIOC_S_CTRL: |
1128 | return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); | 1095 | return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); |
1129 | 1096 | ||
1097 | case VIDIOC_QUERYCTRL: | ||
1098 | { | ||
1099 | struct v4l2_queryctrl *qc = arg; | ||
1100 | int i; | ||
1101 | |||
1102 | for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++) | ||
1103 | if (qc->id && qc->id == saa7115_qctrl[i].id) { | ||
1104 | memcpy(qc, &saa7115_qctrl[i], sizeof(*qc)); | ||
1105 | return 0; | ||
1106 | } | ||
1107 | return -EINVAL; | ||
1108 | } | ||
1109 | |||
1130 | case VIDIOC_G_STD: | 1110 | case VIDIOC_G_STD: |
1131 | *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); | 1111 | *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); |
1132 | break; | 1112 | break; |
1133 | 1113 | ||
1134 | case VIDIOC_S_STD: | 1114 | case VIDIOC_S_STD: |
1115 | state->radio = 0; | ||
1135 | saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); | 1116 | saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); |
1136 | break; | 1117 | break; |
1137 | 1118 | ||
1119 | case AUDC_SET_RADIO: | ||
1120 | state->radio = 1; | ||
1121 | break; | ||
1122 | |||
1138 | case VIDIOC_G_INPUT: | 1123 | case VIDIOC_G_INPUT: |
1139 | *(int *)arg = state->input; | 1124 | *(int *)arg = state->input; |
1140 | break; | 1125 | break; |
1141 | 1126 | ||
1142 | case VIDIOC_S_INPUT: | 1127 | case VIDIOC_S_INPUT: |
1143 | saa7115_dbg("decoder set input %d\n", *iarg); | 1128 | v4l_dbg(1, client, "decoder set input %d\n", *iarg); |
1144 | /* inputs from 0-9 are available */ | 1129 | /* inputs from 0-9 are available */ |
1145 | if (*iarg < 0 || *iarg > 9) { | 1130 | if (*iarg < 0 || *iarg > 9) { |
1146 | return -EINVAL; | 1131 | return -EINVAL; |
@@ -1148,7 +1133,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1148 | 1133 | ||
1149 | if (state->input == *iarg) | 1134 | if (state->input == *iarg) |
1150 | break; | 1135 | break; |
1151 | saa7115_dbg("now setting %s input\n", | 1136 | v4l_dbg(1, client, "now setting %s input\n", |
1152 | *iarg >= 6 ? "S-Video" : "Composite"); | 1137 | *iarg >= 6 ? "S-Video" : "Composite"); |
1153 | state->input = *iarg; | 1138 | state->input = *iarg; |
1154 | 1139 | ||
@@ -1165,7 +1150,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1165 | 1150 | ||
1166 | case VIDIOC_STREAMON: | 1151 | case VIDIOC_STREAMON: |
1167 | case VIDIOC_STREAMOFF: | 1152 | case VIDIOC_STREAMOFF: |
1168 | saa7115_dbg("%s output\n", | 1153 | v4l_dbg(1, client, "%s output\n", |
1169 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); | 1154 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); |
1170 | 1155 | ||
1171 | if (state->enable != (cmd == VIDIOC_STREAMON)) { | 1156 | if (state->enable != (cmd == VIDIOC_STREAMON)) { |
@@ -1179,7 +1164,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1179 | break; | 1164 | break; |
1180 | 1165 | ||
1181 | case VIDIOC_INT_RESET: | 1166 | case VIDIOC_INT_RESET: |
1182 | saa7115_dbg("decoder RESET\n"); | 1167 | v4l_dbg(1, client, "decoder RESET\n"); |
1183 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | 1168 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); |
1184 | break; | 1169 | break; |
1185 | 1170 | ||
@@ -1273,19 +1258,19 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1273 | client->driver = &i2c_driver_saa7115; | 1258 | client->driver = &i2c_driver_saa7115; |
1274 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | 1259 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); |
1275 | 1260 | ||
1276 | saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1); | 1261 | v4l_dbg(1, client, "detecting saa7115 client on address 0x%x\n", address << 1); |
1277 | 1262 | ||
1278 | saa7115_write(client, 0, 5); | 1263 | saa7115_write(client, 0, 5); |
1279 | chip_id = saa7115_read(client, 0) & 0x0f; | 1264 | chip_id = saa7115_read(client, 0) & 0x0f; |
1280 | if (chip_id != 4 && chip_id != 5) { | 1265 | if (chip_id != 4 && chip_id != 5) { |
1281 | saa7115_dbg("saa7115 not found\n"); | 1266 | v4l_dbg(1, client, "saa7115 not found\n"); |
1282 | kfree(client); | 1267 | kfree(client); |
1283 | return 0; | 1268 | return 0; |
1284 | } | 1269 | } |
1285 | if (chip_id == 4) { | 1270 | if (chip_id == 4) { |
1286 | snprintf(client->name, sizeof(client->name) - 1, "saa7114"); | 1271 | snprintf(client->name, sizeof(client->name) - 1, "saa7114"); |
1287 | } | 1272 | } |
1288 | saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); | 1273 | v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); |
1289 | 1274 | ||
1290 | state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); | 1275 | state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); |
1291 | i2c_set_clientdata(client, state); | 1276 | i2c_set_clientdata(client, state); |
@@ -1297,14 +1282,15 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1297 | state->std = V4L2_STD_NTSC; | 1282 | state->std = V4L2_STD_NTSC; |
1298 | state->input = -1; | 1283 | state->input = -1; |
1299 | state->enable = 1; | 1284 | state->enable = 1; |
1285 | state->radio = 0; | ||
1300 | state->bright = 128; | 1286 | state->bright = 128; |
1301 | state->contrast = 64; | 1287 | state->contrast = 64; |
1302 | state->hue = 0; | 1288 | state->hue = 0; |
1303 | state->sat = 64; | 1289 | state->sat = 64; |
1304 | state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; | 1290 | state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; |
1305 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | 1291 | state->audclk_freq = 48000; |
1306 | 1292 | ||
1307 | saa7115_dbg("writing init values\n"); | 1293 | v4l_dbg(1, client, "writing init values\n"); |
1308 | 1294 | ||
1309 | /* init to 60hz/48khz */ | 1295 | /* init to 60hz/48khz */ |
1310 | saa7115_writeregs(client, saa7115_init_auto_input); | 1296 | saa7115_writeregs(client, saa7115_init_auto_input); |
@@ -1312,13 +1298,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1312 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | 1298 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); |
1313 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | 1299 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); |
1314 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | 1300 | saa7115_writeregs(client, saa7115_cfg_60hz_video); |
1315 | saa7115_writeregs(client, saa7115_cfg_48_audio); | 1301 | saa7115_set_audio_clock_freq(client, state->audclk_freq); |
1316 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
1317 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | 1302 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); |
1318 | 1303 | ||
1319 | i2c_attach_client(client); | 1304 | i2c_attach_client(client); |
1320 | 1305 | ||
1321 | saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n", | 1306 | v4l_dbg(1, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", |
1322 | saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); | 1307 | saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); |
1323 | 1308 | ||
1324 | return 0; | 1309 | return 0; |
@@ -1326,11 +1311,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1326 | 1311 | ||
1327 | static int saa7115_probe(struct i2c_adapter *adapter) | 1312 | static int saa7115_probe(struct i2c_adapter *adapter) |
1328 | { | 1313 | { |
1329 | #ifdef I2C_CLASS_TV_ANALOG | ||
1330 | if (adapter->class & I2C_CLASS_TV_ANALOG) | 1314 | if (adapter->class & I2C_CLASS_TV_ANALOG) |
1331 | #else | ||
1332 | if (adapter->id == I2C_HW_B_BT848) | ||
1333 | #endif | ||
1334 | return i2c_probe(adapter, &addr_data, &saa7115_attach); | 1315 | return i2c_probe(adapter, &addr_data, &saa7115_attach); |
1335 | return 0; | 1316 | return 0; |
1336 | } | 1317 | } |