aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2015-01-23 10:52:31 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-02-02 08:49:20 -0500
commitb37135e395c37a8d63defafcb567d55220a672f0 (patch)
tree176a03b4d1ffe3c668f9800510e38b5def0d4aef /drivers/media/i2c
parentbf7dcb8067ed5c3b40768b071d93bd7676e36620 (diff)
[media] adv7180: Add support for the adv7280-m/adv7281-m/adv7281-ma/adv7282-m
This patch adds support for the adv7280-m/adv2781-m/adv7281-ma/adv7282-m devices to the adv7180 driver. They are very similar to the adv7280/adv7281/adv7282 but instead of parallel video out they feature a MIPI CSI2 transmitter. The CSI2 transmitter is configured via a separate I2C address, so we need to register a dummy device for it. 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.c170
1 files changed, 154 insertions, 16 deletions
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index f55364ff2582..195d28f48c30 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -124,6 +124,11 @@
124#define ADV7180_REG_NTSC_V_BIT_END 0x00E6 124#define ADV7180_REG_NTSC_V_BIT_END 0x00E6
125#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F 125#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F
126 126
127#define ADV7180_REG_CSI_SLAVE_ADDR 0xFE
128
129#define ADV7180_CSI_REG_PWRDN 0x00
130#define ADV7180_CSI_PWRDN 0x80
131
127#define ADV7180_INPUT_CVBS_AIN1 0x00 132#define ADV7180_INPUT_CVBS_AIN1 0x00
128#define ADV7180_INPUT_CVBS_AIN2 0x01 133#define ADV7180_INPUT_CVBS_AIN2 0x01
129#define ADV7180_INPUT_CVBS_AIN3 0x02 134#define ADV7180_INPUT_CVBS_AIN3 0x02
@@ -155,10 +160,13 @@
155#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10 160#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10
156#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11 161#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11
157 162
163#define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44
164
158struct adv7180_state; 165struct adv7180_state;
159 166
160#define ADV7180_FLAG_RESET_POWERED BIT(0) 167#define ADV7180_FLAG_RESET_POWERED BIT(0)
161#define ADV7180_FLAG_V2 BIT(1) 168#define ADV7180_FLAG_V2 BIT(1)
169#define ADV7180_FLAG_MIPI_CSI2 BIT(2)
162 170
163struct adv7180_chip_info { 171struct adv7180_chip_info {
164 unsigned int flags; 172 unsigned int flags;
@@ -181,6 +189,7 @@ struct adv7180_state {
181 189
182 struct i2c_client *client; 190 struct i2c_client *client;
183 unsigned int register_page; 191 unsigned int register_page;
192 struct i2c_client *csi_client;
184 const struct adv7180_chip_info *chip_info; 193 const struct adv7180_chip_info *chip_info;
185}; 194};
186#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ 195#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
@@ -213,6 +222,12 @@ static int adv7180_read(struct adv7180_state *state, unsigned int reg)
213 return i2c_smbus_read_byte_data(state->client, reg & 0xff); 222 return i2c_smbus_read_byte_data(state->client, reg & 0xff);
214} 223}
215 224
225static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg,
226 unsigned int value)
227{
228 return i2c_smbus_write_byte_data(state->csi_client, reg, value);
229}
230
216static int adv7180_set_video_standard(struct adv7180_state *state, 231static int adv7180_set_video_standard(struct adv7180_state *state,
217 unsigned int std) 232 unsigned int std)
218{ 233{
@@ -405,13 +420,31 @@ out:
405static int adv7180_set_power(struct adv7180_state *state, bool on) 420static int adv7180_set_power(struct adv7180_state *state, bool on)
406{ 421{
407 u8 val; 422 u8 val;
423 int ret;
408 424
409 if (on) 425 if (on)
410 val = ADV7180_PWR_MAN_ON; 426 val = ADV7180_PWR_MAN_ON;
411 else 427 else
412 val = ADV7180_PWR_MAN_OFF; 428 val = ADV7180_PWR_MAN_OFF;
413 429
414 return adv7180_write(state, ADV7180_REG_PWR_MAN, val); 430 ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val);
431 if (ret)
432 return ret;
433
434 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
435 if (on) {
436 adv7180_csi_write(state, 0xDE, 0x02);
437 adv7180_csi_write(state, 0xD2, 0xF7);
438 adv7180_csi_write(state, 0xD8, 0x65);
439 adv7180_csi_write(state, 0xE0, 0x09);
440 adv7180_csi_write(state, 0x2C, 0x00);
441 adv7180_csi_write(state, 0x00, 0x00);
442 } else {
443 adv7180_csi_write(state, 0x00, 0x80);
444 }
445 }
446
447 return 0;
415} 448}
416 449
417static int adv7180_s_power(struct v4l2_subdev *sd, int on) 450static int adv7180_s_power(struct v4l2_subdev *sd, int on)
@@ -549,13 +582,22 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,
549static int adv7180_g_mbus_config(struct v4l2_subdev *sd, 582static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
550 struct v4l2_mbus_config *cfg) 583 struct v4l2_mbus_config *cfg)
551{ 584{
552 /* 585 struct adv7180_state *state = to_state(sd);
553 * The ADV7180 sensor supports BT.601/656 output modes. 586
554 * The BT.656 is default and not yet configurable by s/w. 587 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
555 */ 588 cfg->type = V4L2_MBUS_CSI2;
556 cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | 589 cfg->flags = V4L2_MBUS_CSI2_1_LANE |
557 V4L2_MBUS_DATA_ACTIVE_HIGH; 590 V4L2_MBUS_CSI2_CHANNEL_0 |
558 cfg->type = V4L2_MBUS_BT656; 591 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
592 } else {
593 /*
594 * The ADV7180 sensor supports BT.601/656 output modes.
595 * The BT.656 is default and not yet configurable by s/w.
596 */
597 cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
598 V4L2_MBUS_DATA_ACTIVE_HIGH;
599 cfg->type = V4L2_MBUS_BT656;
600 }
559 601
560 return 0; 602 return 0;
561} 603}
@@ -638,20 +680,32 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
638 680
639static int adv7182_init(struct adv7180_state *state) 681static int adv7182_init(struct adv7180_state *state)
640{ 682{
683 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
684 adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR,
685 ADV7180_DEFAULT_CSI_I2C_ADDR << 1);
686
641 if (state->chip_info->flags & ADV7180_FLAG_V2) { 687 if (state->chip_info->flags & ADV7180_FLAG_V2) {
642 /* ADI recommended writes for improved video quality */ 688 /* ADI recommended writes for improved video quality */
643 adv7180_write(state, 0x0080, 0x51); 689 adv7180_write(state, 0x0080, 0x51);
644 adv7180_write(state, 0x0081, 0x51); 690 adv7180_write(state, 0x0081, 0x51);
645 adv7180_write(state, 0x0082, 0x68); 691 adv7180_write(state, 0x0082, 0x68);
646 adv7180_write(state, 0x0004, 0x17);
647 } else {
648 adv7180_write(state, 0x0004, 0x07);
649 } 692 }
650 693
651 /* ADI required writes */ 694 /* ADI required writes */
652 adv7180_write(state, 0x0003, 0x0c); 695 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
696 adv7180_write(state, 0x0003, 0x4e);
697 adv7180_write(state, 0x0004, 0x57);
698 adv7180_write(state, 0x001d, 0xc0);
699 } else {
700 if (state->chip_info->flags & ADV7180_FLAG_V2)
701 adv7180_write(state, 0x0004, 0x17);
702 else
703 adv7180_write(state, 0x0004, 0x07);
704 adv7180_write(state, 0x0003, 0x0c);
705 adv7180_write(state, 0x001d, 0x40);
706 }
707
653 adv7180_write(state, 0x0013, 0x00); 708 adv7180_write(state, 0x0013, 0x00);
654 adv7180_write(state, 0x001d, 0x40);
655 709
656 return 0; 710 return 0;
657} 711}
@@ -817,15 +871,81 @@ static const struct adv7180_chip_info adv7280_info = {
817 .select_input = adv7182_select_input, 871 .select_input = adv7182_select_input,
818}; 872};
819 873
874static const struct adv7180_chip_info adv7280_m_info = {
875 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
876 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
877 BIT(ADV7182_INPUT_CVBS_AIN2) |
878 BIT(ADV7182_INPUT_CVBS_AIN3) |
879 BIT(ADV7182_INPUT_CVBS_AIN4) |
880 BIT(ADV7182_INPUT_CVBS_AIN5) |
881 BIT(ADV7182_INPUT_CVBS_AIN6) |
882 BIT(ADV7182_INPUT_CVBS_AIN7) |
883 BIT(ADV7182_INPUT_CVBS_AIN8) |
884 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
885 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
886 BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
887 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
888 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
889 BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6),
890 .init = adv7182_init,
891 .set_std = adv7182_set_std,
892 .select_input = adv7182_select_input,
893};
894
820static const struct adv7180_chip_info adv7281_info = { 895static const struct adv7180_chip_info adv7281_info = {
821 .flags = ADV7180_FLAG_V2, 896 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
897 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
898 BIT(ADV7182_INPUT_CVBS_AIN2) |
899 BIT(ADV7182_INPUT_CVBS_AIN7) |
900 BIT(ADV7182_INPUT_CVBS_AIN8) |
901 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
902 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
903 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
904 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
905 .init = adv7182_init,
906 .set_std = adv7182_set_std,
907 .select_input = adv7182_select_input,
908};
909
910static const struct adv7180_chip_info adv7281_m_info = {
911 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
912 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
913 BIT(ADV7182_INPUT_CVBS_AIN2) |
914 BIT(ADV7182_INPUT_CVBS_AIN3) |
915 BIT(ADV7182_INPUT_CVBS_AIN4) |
916 BIT(ADV7182_INPUT_CVBS_AIN7) |
917 BIT(ADV7182_INPUT_CVBS_AIN8) |
918 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
919 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
920 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
921 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
922 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
923 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
924 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
925 .init = adv7182_init,
926 .set_std = adv7182_set_std,
927 .select_input = adv7182_select_input,
928};
929
930static const struct adv7180_chip_info adv7281_ma_info = {
931 .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
822 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | 932 .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
823 BIT(ADV7182_INPUT_CVBS_AIN2) | 933 BIT(ADV7182_INPUT_CVBS_AIN2) |
934 BIT(ADV7182_INPUT_CVBS_AIN3) |
935 BIT(ADV7182_INPUT_CVBS_AIN4) |
936 BIT(ADV7182_INPUT_CVBS_AIN5) |
937 BIT(ADV7182_INPUT_CVBS_AIN6) |
824 BIT(ADV7182_INPUT_CVBS_AIN7) | 938 BIT(ADV7182_INPUT_CVBS_AIN7) |
825 BIT(ADV7182_INPUT_CVBS_AIN8) | 939 BIT(ADV7182_INPUT_CVBS_AIN8) |
826 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | 940 BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
941 BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
942 BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
827 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | 943 BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
944 BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
945 BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6) |
828 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) | 946 BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
947 BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
948 BIT(ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6) |
829 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8), 949 BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
830 .init = adv7182_init, 950 .init = adv7182_init,
831 .set_std = adv7182_set_std, 951 .set_std = adv7182_set_std,
@@ -904,6 +1024,13 @@ static int adv7180_probe(struct i2c_client *client,
904 state->client = client; 1024 state->client = client;
905 state->chip_info = (struct adv7180_chip_info *)id->driver_data; 1025 state->chip_info = (struct adv7180_chip_info *)id->driver_data;
906 1026
1027 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
1028 state->csi_client = i2c_new_dummy(client->adapter,
1029 ADV7180_DEFAULT_CSI_I2C_ADDR);
1030 if (!state->csi_client)
1031 return -ENOMEM;
1032 }
1033
907 state->irq = client->irq; 1034 state->irq = client->irq;
908 mutex_init(&state->mutex); 1035 mutex_init(&state->mutex);
909 state->autodetect = true; 1036 state->autodetect = true;
@@ -918,7 +1045,7 @@ static int adv7180_probe(struct i2c_client *client,
918 1045
919 ret = adv7180_init_controls(state); 1046 ret = adv7180_init_controls(state);
920 if (ret) 1047 if (ret)
921 goto err_unreg_subdev; 1048 goto err_unregister_csi_client;
922 1049
923 state->pad.flags = MEDIA_PAD_FL_SOURCE; 1050 state->pad.flags = MEDIA_PAD_FL_SOURCE;
924 sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; 1051 sd->entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
@@ -951,7 +1078,9 @@ err_media_entity_cleanup:
951 media_entity_cleanup(&sd->entity); 1078 media_entity_cleanup(&sd->entity);
952err_free_ctrl: 1079err_free_ctrl:
953 adv7180_exit_controls(state); 1080 adv7180_exit_controls(state);
954err_unreg_subdev: 1081err_unregister_csi_client:
1082 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
1083 i2c_unregister_device(state->csi_client);
955 mutex_destroy(&state->mutex); 1084 mutex_destroy(&state->mutex);
956 return ret; 1085 return ret;
957} 1086}
@@ -968,7 +1097,12 @@ static int adv7180_remove(struct i2c_client *client)
968 1097
969 media_entity_cleanup(&sd->entity); 1098 media_entity_cleanup(&sd->entity);
970 adv7180_exit_controls(state); 1099 adv7180_exit_controls(state);
1100
1101 if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
1102 i2c_unregister_device(state->csi_client);
1103
971 mutex_destroy(&state->mutex); 1104 mutex_destroy(&state->mutex);
1105
972 return 0; 1106 return 0;
973} 1107}
974 1108
@@ -976,8 +1110,12 @@ static const struct i2c_device_id adv7180_id[] = {
976 { "adv7180", (kernel_ulong_t)&adv7180_info }, 1110 { "adv7180", (kernel_ulong_t)&adv7180_info },
977 { "adv7182", (kernel_ulong_t)&adv7182_info }, 1111 { "adv7182", (kernel_ulong_t)&adv7182_info },
978 { "adv7280", (kernel_ulong_t)&adv7280_info }, 1112 { "adv7280", (kernel_ulong_t)&adv7280_info },
1113 { "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
979 { "adv7281", (kernel_ulong_t)&adv7281_info }, 1114 { "adv7281", (kernel_ulong_t)&adv7281_info },
1115 { "adv7281-m", (kernel_ulong_t)&adv7281_m_info },
1116 { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info },
980 { "adv7282", (kernel_ulong_t)&adv7281_info }, 1117 { "adv7282", (kernel_ulong_t)&adv7281_info },
1118 { "adv7282-m", (kernel_ulong_t)&adv7281_m_info },
981 {}, 1119 {},
982}; 1120};
983MODULE_DEVICE_TABLE(i2c, adv7180_id); 1121MODULE_DEVICE_TABLE(i2c, adv7180_id);