aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov9740.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ov9740.c')
-rw-r--r--drivers/media/video/ov9740.c151
1 files changed, 55 insertions, 96 deletions
diff --git a/drivers/media/video/ov9740.c b/drivers/media/video/ov9740.c
index edd1ffcca30..d9a9f7174f7 100644
--- a/drivers/media/video/ov9740.c
+++ b/drivers/media/video/ov9740.c
@@ -14,8 +14,11 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <media/v4l2-chip-ident.h> 17#include <linux/v4l2-mediabus.h>
18
18#include <media/soc_camera.h> 19#include <media/soc_camera.h>
20#include <media/v4l2-chip-ident.h>
21#include <media/v4l2-ctrls.h>
19 22
20#define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) 23#define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev)
21 24
@@ -192,6 +195,7 @@ struct ov9740_reg {
192 195
193struct ov9740_priv { 196struct ov9740_priv {
194 struct v4l2_subdev subdev; 197 struct v4l2_subdev subdev;
198 struct v4l2_ctrl_handler hdl;
195 199
196 int ident; 200 int ident;
197 u16 model; 201 u16 model;
@@ -392,27 +396,6 @@ static enum v4l2_mbus_pixelcode ov9740_codes[] = {
392 V4L2_MBUS_FMT_YUYV8_2X8, 396 V4L2_MBUS_FMT_YUYV8_2X8,
393}; 397};
394 398
395static const struct v4l2_queryctrl ov9740_controls[] = {
396 {
397 .id = V4L2_CID_VFLIP,
398 .type = V4L2_CTRL_TYPE_BOOLEAN,
399 .name = "Flip Vertically",
400 .minimum = 0,
401 .maximum = 1,
402 .step = 1,
403 .default_value = 0,
404 },
405 {
406 .id = V4L2_CID_HFLIP,
407 .type = V4L2_CTRL_TYPE_BOOLEAN,
408 .name = "Flip Horizontally",
409 .minimum = 0,
410 .maximum = 1,
411 .step = 1,
412 .default_value = 0,
413 },
414};
415
416/* read a register */ 399/* read a register */
417static int ov9740_reg_read(struct i2c_client *client, u16 reg, u8 *val) 400static int ov9740_reg_read(struct i2c_client *client, u16 reg, u8 *val)
418{ 401{
@@ -560,25 +543,6 @@ static int ov9740_s_stream(struct v4l2_subdev *sd, int enable)
560 return ret; 543 return ret;
561} 544}
562 545
563/* Alter bus settings on camera side */
564static int ov9740_set_bus_param(struct soc_camera_device *icd,
565 unsigned long flags)
566{
567 return 0;
568}
569
570/* Request bus settings on camera side */
571static unsigned long ov9740_query_bus_param(struct soc_camera_device *icd)
572{
573 struct soc_camera_link *icl = to_soc_camera_link(icd);
574
575 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
576 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
577 SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
578
579 return soc_camera_apply_sensor_flags(icl, flags);
580}
581
582/* select nearest higher resolution for capture */ 546/* select nearest higher resolution for capture */
583static void ov9740_res_roundup(u32 *width, u32 *height) 547static void ov9740_res_roundup(u32 *width, u32 *height)
584{ 548{
@@ -788,36 +752,18 @@ static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
788 return 0; 752 return 0;
789} 753}
790 754
791/* Get status of additional camera capabilities */
792static int ov9740_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
793{
794 struct ov9740_priv *priv = to_ov9740(sd);
795
796 switch (ctrl->id) {
797 case V4L2_CID_VFLIP:
798 ctrl->value = priv->flag_vflip;
799 break;
800 case V4L2_CID_HFLIP:
801 ctrl->value = priv->flag_hflip;
802 break;
803 default:
804 return -EINVAL;
805 }
806
807 return 0;
808}
809
810/* Set status of additional camera capabilities */ 755/* Set status of additional camera capabilities */
811static int ov9740_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 756static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl)
812{ 757{
813 struct ov9740_priv *priv = to_ov9740(sd); 758 struct ov9740_priv *priv =
759 container_of(ctrl->handler, struct ov9740_priv, hdl);
814 760
815 switch (ctrl->id) { 761 switch (ctrl->id) {
816 case V4L2_CID_VFLIP: 762 case V4L2_CID_VFLIP:
817 priv->flag_vflip = ctrl->value; 763 priv->flag_vflip = ctrl->val;
818 break; 764 break;
819 case V4L2_CID_HFLIP: 765 case V4L2_CID_HFLIP:
820 priv->flag_hflip = ctrl->value; 766 priv->flag_hflip = ctrl->val;
821 break; 767 break;
822 default: 768 default:
823 return -EINVAL; 769 return -EINVAL;
@@ -890,18 +836,13 @@ static int ov9740_set_register(struct v4l2_subdev *sd,
890} 836}
891#endif 837#endif
892 838
893static int ov9740_video_probe(struct soc_camera_device *icd, 839static int ov9740_video_probe(struct i2c_client *client)
894 struct i2c_client *client)
895{ 840{
896 struct v4l2_subdev *sd = i2c_get_clientdata(client); 841 struct v4l2_subdev *sd = i2c_get_clientdata(client);
897 struct ov9740_priv *priv = to_ov9740(sd); 842 struct ov9740_priv *priv = to_ov9740(sd);
898 u8 modelhi, modello; 843 u8 modelhi, modello;
899 int ret; 844 int ret;
900 845
901 /* We must have a parent by now. And it cannot be a wrong one. */
902 BUG_ON(!icd->parent ||
903 to_soc_camera_host(icd->parent)->nr != icd->iface);
904
905 /* 846 /*
906 * check and show product ID and manufacturer ID 847 * check and show product ID and manufacturer ID
907 */ 848 */
@@ -942,25 +883,33 @@ err:
942 return ret; 883 return ret;
943} 884}
944 885
945static struct soc_camera_ops ov9740_ops = { 886/* Request bus settings on camera side */
946 .set_bus_param = ov9740_set_bus_param, 887static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
947 .query_bus_param = ov9740_query_bus_param, 888 struct v4l2_mbus_config *cfg)
948 .controls = ov9740_controls, 889{
949 .num_controls = ARRAY_SIZE(ov9740_controls), 890 struct i2c_client *client = v4l2_get_subdevdata(sd);
950}; 891 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
892
893 cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
894 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
895 V4L2_MBUS_DATA_ACTIVE_HIGH;
896 cfg->type = V4L2_MBUS_PARALLEL;
897 cfg->flags = soc_camera_apply_board_flags(icl, cfg);
898
899 return 0;
900}
951 901
952static struct v4l2_subdev_video_ops ov9740_video_ops = { 902static struct v4l2_subdev_video_ops ov9740_video_ops = {
953 .s_stream = ov9740_s_stream, 903 .s_stream = ov9740_s_stream,
954 .s_mbus_fmt = ov9740_s_fmt, 904 .s_mbus_fmt = ov9740_s_fmt,
955 .try_mbus_fmt = ov9740_try_fmt, 905 .try_mbus_fmt = ov9740_try_fmt,
956 .enum_mbus_fmt = ov9740_enum_fmt, 906 .enum_mbus_fmt = ov9740_enum_fmt,
957 .cropcap = ov9740_cropcap, 907 .cropcap = ov9740_cropcap,
958 .g_crop = ov9740_g_crop, 908 .g_crop = ov9740_g_crop,
909 .g_mbus_config = ov9740_g_mbus_config,
959}; 910};
960 911
961static struct v4l2_subdev_core_ops ov9740_core_ops = { 912static struct v4l2_subdev_core_ops ov9740_core_ops = {
962 .g_ctrl = ov9740_g_ctrl,
963 .s_ctrl = ov9740_s_ctrl,
964 .g_chip_ident = ov9740_g_chip_ident, 913 .g_chip_ident = ov9740_g_chip_ident,
965 .s_power = ov9740_s_power, 914 .s_power = ov9740_s_power,
966#ifdef CONFIG_VIDEO_ADV_DEBUG 915#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -974,6 +923,10 @@ static struct v4l2_subdev_ops ov9740_subdev_ops = {
974 .video = &ov9740_video_ops, 923 .video = &ov9740_video_ops,
975}; 924};
976 925
926static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
927 .s_ctrl = ov9740_s_ctrl,
928};
929
977/* 930/*
978 * i2c_driver function 931 * i2c_driver function
979 */ 932 */
@@ -981,16 +934,9 @@ static int ov9740_probe(struct i2c_client *client,
981 const struct i2c_device_id *did) 934 const struct i2c_device_id *did)
982{ 935{
983 struct ov9740_priv *priv; 936 struct ov9740_priv *priv;
984 struct soc_camera_device *icd = client->dev.platform_data; 937 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
985 struct soc_camera_link *icl;
986 int ret; 938 int ret;
987 939
988 if (!icd) {
989 dev_err(&client->dev, "Missing soc-camera data!\n");
990 return -EINVAL;
991 }
992
993 icl = to_soc_camera_link(icd);
994 if (!icl) { 940 if (!icl) {
995 dev_err(&client->dev, "Missing platform_data for driver\n"); 941 dev_err(&client->dev, "Missing platform_data for driver\n");
996 return -EINVAL; 942 return -EINVAL;
@@ -1003,12 +949,24 @@ static int ov9740_probe(struct i2c_client *client,
1003 } 949 }
1004 950
1005 v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops); 951 v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
952 v4l2_ctrl_handler_init(&priv->hdl, 13);
953 v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
954 V4L2_CID_VFLIP, 0, 1, 1, 0);
955 v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
956 V4L2_CID_HFLIP, 0, 1, 1, 0);
957 priv->subdev.ctrl_handler = &priv->hdl;
958 if (priv->hdl.error) {
959 int err = priv->hdl.error;
1006 960
1007 icd->ops = &ov9740_ops; 961 kfree(priv);
962 return err;
963 }
1008 964
1009 ret = ov9740_video_probe(icd, client); 965 ret = ov9740_video_probe(client);
966 if (!ret)
967 ret = v4l2_ctrl_handler_setup(&priv->hdl);
1010 if (ret < 0) { 968 if (ret < 0) {
1011 icd->ops = NULL; 969 v4l2_ctrl_handler_free(&priv->hdl);
1012 kfree(priv); 970 kfree(priv);
1013 } 971 }
1014 972
@@ -1019,8 +977,9 @@ static int ov9740_remove(struct i2c_client *client)
1019{ 977{
1020 struct ov9740_priv *priv = i2c_get_clientdata(client); 978 struct ov9740_priv *priv = i2c_get_clientdata(client);
1021 979
980 v4l2_device_unregister_subdev(&priv->subdev);
981 v4l2_ctrl_handler_free(&priv->hdl);
1022 kfree(priv); 982 kfree(priv);
1023
1024 return 0; 983 return 0;
1025} 984}
1026 985