aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov2640.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ov2640.c')
-rw-r--r--drivers/media/video/ov2640.c178
1 files changed, 52 insertions, 126 deletions
diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c
index 9ce2fa037b9..b5247cb64fd 100644
--- a/drivers/media/video/ov2640.c
+++ b/drivers/media/video/ov2640.c
@@ -18,11 +18,13 @@
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/v4l2-mediabus.h>
21#include <linux/videodev2.h> 22#include <linux/videodev2.h>
23
24#include <media/soc_camera.h>
22#include <media/v4l2-chip-ident.h> 25#include <media/v4l2-chip-ident.h>
23#include <media/v4l2-subdev.h> 26#include <media/v4l2-subdev.h>
24#include <media/soc_camera.h> 27#include <media/v4l2-ctrls.h>
25#include <media/soc_mediabus.h>
26 28
27#define VAL_SET(x, mask, rshift, lshift) \ 29#define VAL_SET(x, mask, rshift, lshift) \
28 ((((x) >> rshift) & mask) << lshift) 30 ((((x) >> rshift) & mask) << lshift)
@@ -299,12 +301,10 @@ struct ov2640_win_size {
299 301
300struct ov2640_priv { 302struct ov2640_priv {
301 struct v4l2_subdev subdev; 303 struct v4l2_subdev subdev;
302 struct ov2640_camera_info *info; 304 struct v4l2_ctrl_handler hdl;
303 enum v4l2_mbus_pixelcode cfmt_code; 305 enum v4l2_mbus_pixelcode cfmt_code;
304 const struct ov2640_win_size *win; 306 const struct ov2640_win_size *win;
305 int model; 307 int model;
306 u16 flag_vflip:1;
307 u16 flag_hflip:1;
308}; 308};
309 309
310/* 310/*
@@ -610,29 +610,6 @@ static enum v4l2_mbus_pixelcode ov2640_codes[] = {
610}; 610};
611 611
612/* 612/*
613 * Supported controls
614 */
615static const struct v4l2_queryctrl ov2640_controls[] = {
616 {
617 .id = V4L2_CID_VFLIP,
618 .type = V4L2_CTRL_TYPE_BOOLEAN,
619 .name = "Flip Vertically",
620 .minimum = 0,
621 .maximum = 1,
622 .step = 1,
623 .default_value = 0,
624 }, {
625 .id = V4L2_CID_HFLIP,
626 .type = V4L2_CTRL_TYPE_BOOLEAN,
627 .name = "Flip Horizontally",
628 .minimum = 0,
629 .maximum = 1,
630 .step = 1,
631 .default_value = 0,
632 },
633};
634
635/*
636 * General functions 613 * General functions
637 */ 614 */
638static struct ov2640_priv *to_ov2640(const struct i2c_client *client) 615static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
@@ -701,81 +678,23 @@ static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
701 return 0; 678 return 0;
702} 679}
703 680
704static int ov2640_set_bus_param(struct soc_camera_device *icd, 681static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
705 unsigned long flags)
706{
707 struct soc_camera_link *icl = to_soc_camera_link(icd);
708 unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
709
710 /* Only one width bit may be set */
711 if (!is_power_of_2(width_flag))
712 return -EINVAL;
713
714 if (icl->set_bus_param)
715 return icl->set_bus_param(icl, width_flag);
716
717 /*
718 * Without board specific bus width settings we support only the
719 * sensors native bus width witch are tested working
720 */
721 if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8))
722 return 0;
723
724 return 0;
725}
726
727static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd)
728{
729 struct soc_camera_link *icl = to_soc_camera_link(icd);
730 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
731 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
732 SOCAM_DATA_ACTIVE_HIGH;
733
734 if (icl->query_bus_param)
735 flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
736 else
737 flags |= SOCAM_DATAWIDTH_10;
738
739 return soc_camera_apply_sensor_flags(icl, flags);
740}
741
742static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
743{ 682{
683 struct v4l2_subdev *sd =
684 &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
744 struct i2c_client *client = v4l2_get_subdevdata(sd); 685 struct i2c_client *client = v4l2_get_subdevdata(sd);
745 struct ov2640_priv *priv = to_ov2640(client);
746
747 switch (ctrl->id) {
748 case V4L2_CID_VFLIP:
749 ctrl->value = priv->flag_vflip;
750 break;
751 case V4L2_CID_HFLIP:
752 ctrl->value = priv->flag_hflip;
753 break;
754 }
755 return 0;
756}
757
758static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
759{
760 struct i2c_client *client = v4l2_get_subdevdata(sd);
761 struct ov2640_priv *priv = to_ov2640(client);
762 int ret = 0;
763 u8 val; 686 u8 val;
764 687
765 switch (ctrl->id) { 688 switch (ctrl->id) {
766 case V4L2_CID_VFLIP: 689 case V4L2_CID_VFLIP:
767 val = ctrl->value ? REG04_VFLIP_IMG : 0x00; 690 val = ctrl->val ? REG04_VFLIP_IMG : 0x00;
768 priv->flag_vflip = ctrl->value ? 1 : 0; 691 return ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
769 ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
770 break;
771 case V4L2_CID_HFLIP: 692 case V4L2_CID_HFLIP:
772 val = ctrl->value ? REG04_HFLIP_IMG : 0x00; 693 val = ctrl->val ? REG04_HFLIP_IMG : 0x00;
773 priv->flag_hflip = ctrl->value ? 1 : 0; 694 return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
774 ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
775 break;
776 } 695 }
777 696
778 return ret; 697 return -EINVAL;
779} 698}
780 699
781static int ov2640_g_chip_ident(struct v4l2_subdev *sd, 700static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
@@ -1023,18 +942,13 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
1023 return 0; 942 return 0;
1024} 943}
1025 944
1026static int ov2640_video_probe(struct soc_camera_device *icd, 945static int ov2640_video_probe(struct i2c_client *client)
1027 struct i2c_client *client)
1028{ 946{
1029 struct ov2640_priv *priv = to_ov2640(client); 947 struct ov2640_priv *priv = to_ov2640(client);
1030 u8 pid, ver, midh, midl; 948 u8 pid, ver, midh, midl;
1031 const char *devname; 949 const char *devname;
1032 int ret; 950 int ret;
1033 951
1034 /* We must have a parent by now. And it cannot be a wrong one. */
1035 BUG_ON(!icd->parent ||
1036 to_soc_camera_host(icd->parent)->nr != icd->iface);
1037
1038 /* 952 /*
1039 * check and show product ID and manufacturer ID 953 * check and show product ID and manufacturer ID
1040 */ 954 */
@@ -1060,22 +974,17 @@ static int ov2640_video_probe(struct soc_camera_device *icd,
1060 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", 974 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
1061 devname, pid, ver, midh, midl); 975 devname, pid, ver, midh, midl);
1062 976
1063 return 0; 977 return v4l2_ctrl_handler_setup(&priv->hdl);
1064 978
1065err: 979err:
1066 return ret; 980 return ret;
1067} 981}
1068 982
1069static struct soc_camera_ops ov2640_ops = { 983static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {
1070 .set_bus_param = ov2640_set_bus_param, 984 .s_ctrl = ov2640_s_ctrl,
1071 .query_bus_param = ov2640_query_bus_param,
1072 .controls = ov2640_controls,
1073 .num_controls = ARRAY_SIZE(ov2640_controls),
1074}; 985};
1075 986
1076static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { 987static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
1077 .g_ctrl = ov2640_g_ctrl,
1078 .s_ctrl = ov2640_s_ctrl,
1079 .g_chip_ident = ov2640_g_chip_ident, 988 .g_chip_ident = ov2640_g_chip_ident,
1080#ifdef CONFIG_VIDEO_ADV_DEBUG 989#ifdef CONFIG_VIDEO_ADV_DEBUG
1081 .g_register = ov2640_g_register, 990 .g_register = ov2640_g_register,
@@ -1083,6 +992,21 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
1083#endif 992#endif
1084}; 993};
1085 994
995static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
996 struct v4l2_mbus_config *cfg)
997{
998 struct i2c_client *client = v4l2_get_subdevdata(sd);
999 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
1000
1001 cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
1002 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
1003 V4L2_MBUS_DATA_ACTIVE_HIGH;
1004 cfg->type = V4L2_MBUS_PARALLEL;
1005 cfg->flags = soc_camera_apply_board_flags(icl, cfg);
1006
1007 return 0;
1008}
1009
1086static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = { 1010static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
1087 .s_stream = ov2640_s_stream, 1011 .s_stream = ov2640_s_stream,
1088 .g_mbus_fmt = ov2640_g_fmt, 1012 .g_mbus_fmt = ov2640_g_fmt,
@@ -1091,6 +1015,7 @@ static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
1091 .cropcap = ov2640_cropcap, 1015 .cropcap = ov2640_cropcap,
1092 .g_crop = ov2640_g_crop, 1016 .g_crop = ov2640_g_crop,
1093 .enum_mbus_fmt = ov2640_enum_fmt, 1017 .enum_mbus_fmt = ov2640_enum_fmt,
1018 .g_mbus_config = ov2640_g_mbus_config,
1094}; 1019};
1095 1020
1096static struct v4l2_subdev_ops ov2640_subdev_ops = { 1021static struct v4l2_subdev_ops ov2640_subdev_ops = {
@@ -1104,18 +1029,11 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = {
1104static int ov2640_probe(struct i2c_client *client, 1029static int ov2640_probe(struct i2c_client *client,
1105 const struct i2c_device_id *did) 1030 const struct i2c_device_id *did)
1106{ 1031{
1107 struct ov2640_priv *priv; 1032 struct ov2640_priv *priv;
1108 struct soc_camera_device *icd = client->dev.platform_data; 1033 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
1109 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1034 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1110 struct soc_camera_link *icl; 1035 int ret;
1111 int ret;
1112
1113 if (!icd) {
1114 dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n");
1115 return -EINVAL;
1116 }
1117 1036
1118 icl = to_soc_camera_link(icd);
1119 if (!icl) { 1037 if (!icl) {
1120 dev_err(&adapter->dev, 1038 dev_err(&adapter->dev,
1121 "OV2640: Missing platform_data for driver\n"); 1039 "OV2640: Missing platform_data for driver\n");
@@ -1135,15 +1053,23 @@ static int ov2640_probe(struct i2c_client *client,
1135 return -ENOMEM; 1053 return -ENOMEM;
1136 } 1054 }
1137 1055
1138 priv->info = icl->priv;
1139
1140 v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops); 1056 v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
1057 v4l2_ctrl_handler_init(&priv->hdl, 2);
1058 v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
1059 V4L2_CID_VFLIP, 0, 1, 1, 0);
1060 v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
1061 V4L2_CID_HFLIP, 0, 1, 1, 0);
1062 priv->subdev.ctrl_handler = &priv->hdl;
1063 if (priv->hdl.error) {
1064 int err = priv->hdl.error;
1141 1065
1142 icd->ops = &ov2640_ops; 1066 kfree(priv);
1067 return err;
1068 }
1143 1069
1144 ret = ov2640_video_probe(icd, client); 1070 ret = ov2640_video_probe(client);
1145 if (ret) { 1071 if (ret) {
1146 icd->ops = NULL; 1072 v4l2_ctrl_handler_free(&priv->hdl);
1147 kfree(priv); 1073 kfree(priv);
1148 } else { 1074 } else {
1149 dev_info(&adapter->dev, "OV2640 Probed\n"); 1075 dev_info(&adapter->dev, "OV2640 Probed\n");
@@ -1155,9 +1081,9 @@ static int ov2640_probe(struct i2c_client *client,
1155static int ov2640_remove(struct i2c_client *client) 1081static int ov2640_remove(struct i2c_client *client)
1156{ 1082{
1157 struct ov2640_priv *priv = to_ov2640(client); 1083 struct ov2640_priv *priv = to_ov2640(client);
1158 struct soc_camera_device *icd = client->dev.platform_data;
1159 1084
1160 icd->ops = NULL; 1085 v4l2_device_unregister_subdev(&priv->subdev);
1086 v4l2_ctrl_handler_free(&priv->hdl);
1161 kfree(priv); 1087 kfree(priv);
1162 return 0; 1088 return 0;
1163} 1089}