aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2015-01-23 10:52:29 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-02-02 08:47:52 -0500
commitc5ef8f8c5d502a7a918737a05170399ed028f17a (patch)
treee900ef5c0886b9878295f248ab07af1555ac62da /drivers/media/i2c
parentf5dde49b8f362bdc53dbdbd3a579fac5e66d878d (diff)
[media] adv7180: Add support for the adv7182
This patch adds support for the adv7182 to the adv7180 driver. The adv7182 is similar to the adv7180, the main difference from the driver's point of view is how the video input and how the input format are selected. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Federico Vaga <federico.vaga@gmail.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/adv7180.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index 170c2fcceb00..84d3b782a2a7 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -52,6 +52,8 @@
52#define ADV7180_REG_INPUT_CONTROL 0x0000 52#define ADV7180_REG_INPUT_CONTROL 0x0000
53#define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f 53#define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f
54 54
55#define ADV7182_REG_INPUT_VIDSEL 0x0002
56
55#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004 57#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL 0x0004
56#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 58#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5
57 59
@@ -134,6 +136,25 @@
134#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09 136#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09
135#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a 137#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a
136 138
139#define ADV7182_INPUT_CVBS_AIN1 0x00
140#define ADV7182_INPUT_CVBS_AIN2 0x01
141#define ADV7182_INPUT_CVBS_AIN3 0x02
142#define ADV7182_INPUT_CVBS_AIN4 0x03
143#define ADV7182_INPUT_CVBS_AIN5 0x04
144#define ADV7182_INPUT_CVBS_AIN6 0x05
145#define ADV7182_INPUT_CVBS_AIN7 0x06
146#define ADV7182_INPUT_CVBS_AIN8 0x07
147#define ADV7182_INPUT_SVIDEO_AIN1_AIN2 0x08
148#define ADV7182_INPUT_SVIDEO_AIN3_AIN4 0x09
149#define ADV7182_INPUT_SVIDEO_AIN5_AIN6 0x0a
150#define ADV7182_INPUT_SVIDEO_AIN7_AIN8 0x0b
151#define ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3 0x0c
152#define ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0d
153#define ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2 0x0e
154#define ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4 0x0f
155#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10
156#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11
157
137struct adv7180_state; 158struct adv7180_state;
138 159
139#define ADV7180_FLAG_RESET_POWERED BIT(0) 160#define ADV7180_FLAG_RESET_POWERED BIT(0)
@@ -614,6 +635,118 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
614 return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret); 635 return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret);
615} 636}
616 637
638static int adv7182_init(struct adv7180_state *state)
639{
640 /* ADI required writes */
641 adv7180_write(state, 0x0003, 0x0c);
642 adv7180_write(state, 0x0004, 0x07);
643 adv7180_write(state, 0x0013, 0x00);
644 adv7180_write(state, 0x001d, 0x40);
645
646 return 0;
647}
648
649static int adv7182_set_std(struct adv7180_state *state, unsigned int std)
650{
651 return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4);
652}
653
654enum adv7182_input_type {
655 ADV7182_INPUT_TYPE_CVBS,
656 ADV7182_INPUT_TYPE_DIFF_CVBS,
657 ADV7182_INPUT_TYPE_SVIDEO,
658 ADV7182_INPUT_TYPE_YPBPR,
659};
660
661static enum adv7182_input_type adv7182_get_input_type(unsigned int input)
662{
663 switch (input) {
664 case ADV7182_INPUT_CVBS_AIN1:
665 case ADV7182_INPUT_CVBS_AIN2:
666 case ADV7182_INPUT_CVBS_AIN3:
667 case ADV7182_INPUT_CVBS_AIN4:
668 case ADV7182_INPUT_CVBS_AIN5:
669 case ADV7182_INPUT_CVBS_AIN6:
670 case ADV7182_INPUT_CVBS_AIN7:
671 case ADV7182_INPUT_CVBS_AIN8:
672 return ADV7182_INPUT_TYPE_CVBS;
673 case ADV7182_INPUT_SVIDEO_AIN1_AIN2:
674 case ADV7182_INPUT_SVIDEO_AIN3_AIN4:
675 case ADV7182_INPUT_SVIDEO_AIN5_AIN6:
676 case ADV7182_INPUT_SVIDEO_AIN7_AIN8:
677 return ADV7182_INPUT_TYPE_SVIDEO;
678 case ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3:
679 case ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6:
680 return ADV7182_INPUT_TYPE_YPBPR;
681 case ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2:
682 case ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4:
683 case ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6:
684 case ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8:
685 return ADV7182_INPUT_TYPE_DIFF_CVBS;
686 default: /* Will never happen */
687 return 0;
688 }
689}
690
691/* ADI recommended writes to registers 0x52, 0x53, 0x54 */
692static unsigned int adv7182_lbias_settings[][3] = {
693 [ADV7182_INPUT_TYPE_CVBS] = { 0xCB, 0x4E, 0x80 },
694 [ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
695 [ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
696 [ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
697};
698
699static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
700{
701 enum adv7182_input_type input_type;
702 unsigned int *lbias;
703 unsigned int i;
704 int ret;
705
706 ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input);
707 if (ret)
708 return ret;
709
710 /* Reset clamp circuitry - ADI recommended writes */
711 adv7180_write(state, 0x809c, 0x00);
712 adv7180_write(state, 0x809c, 0xff);
713
714 input_type = adv7182_get_input_type(input);
715
716 switch (input_type) {
717 case ADV7182_INPUT_TYPE_CVBS:
718 case ADV7182_INPUT_TYPE_DIFF_CVBS:
719 /* ADI recommends to use the SH1 filter */
720 adv7180_write(state, 0x0017, 0x41);
721 break;
722 default:
723 adv7180_write(state, 0x0017, 0x01);
724 break;
725 }
726
727 lbias = adv7182_lbias_settings[input_type];
728
729 for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++)
730 adv7180_write(state, 0x0052 + i, lbias[i]);
731
732 if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {
733 /* ADI required writes to make differential CVBS work */
734 adv7180_write(state, 0x005f, 0xa8);
735 adv7180_write(state, 0x005a, 0x90);
736 adv7180_write(state, 0x0060, 0xb0);
737 adv7180_write(state, 0x80b6, 0x08);
738 adv7180_write(state, 0x80c0, 0xa0);
739 } else {
740 adv7180_write(state, 0x005f, 0xf0);
741 adv7180_write(state, 0x005a, 0xd0);
742 adv7180_write(state, 0x0060, 0x10);
743 adv7180_write(state, 0x80b6, 0x9c);
744 adv7180_write(state, 0x80c0, 0x00);
745 }
746
747 return 0;
748}
749
617static const struct adv7180_chip_info adv7180_info = { 750static const struct adv7180_chip_info adv7180_info = {
618 .flags = ADV7180_FLAG_RESET_POWERED, 751 .flags = ADV7180_FLAG_RESET_POWERED,
619 /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept 752 /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
@@ -635,6 +768,21 @@ static const struct adv7180_chip_info adv7180_info = {
635 .select_input = adv7180_select_input, 768 .select_input = adv7180_select_input,
636}; 769};
637 770
771static const struct adv7180_chip_info adv7182_info = {
772 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
773 BIT(ADV7182_INPUT_CVBS_AIN2) |
774 BIT(ADV7182_INPUT_CVBS_AIN3) |
775 BIT(ADV7182_INPUT_CVBS_AIN4) |
776 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
777 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
778 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
779 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
780 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4),
781 .init = adv7182_init,
782 .set_std = adv7182_set_std,
783 .select_input = adv7182_select_input,
784};
785
638static int init_device(struct adv7180_state *state) 786static int init_device(struct adv7180_state *state)
639{ 787{
640 int ret; 788 int ret;
@@ -777,6 +925,7 @@ static int adv7180_remove(struct i2c_client *client)
777 925
778static const struct i2c_device_id adv7180_id[] = { 926static const struct i2c_device_id adv7180_id[] = {
779 { "adv7180", (kernel_ulong_t)&adv7180_info }, 927 { "adv7180", (kernel_ulong_t)&adv7180_info },
928 { "adv7182", (kernel_ulong_t)&adv7182_info },
780 {}, 929 {},
781}; 930};
782MODULE_DEVICE_TABLE(i2c, adv7180_id); 931MODULE_DEVICE_TABLE(i2c, adv7180_id);