V4L/DVB (12513): soc-camera: add support for camera-host controls
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Tue, 25 Aug 2009 14:44:15 +0000 (11:44 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 19 Sep 2009 03:18:39 +0000 (00:18 -0300)
Until now soc-camera only supported client (sensor) controls. This patch
enables camera-host drivers to implement their own controls too.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/soc_camera.c
include/media/soc_camera.h

index 0a1cb40..b3fb8f2 100644 (file)
@@ -633,6 +633,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
 {
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        int i;
 
        WARN_ON(priv != file->private_data);
@@ -640,6 +641,15 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
        if (!qc->id)
                return -EINVAL;
 
+       /* First check host controls */
+       for (i = 0; i < ici->ops->num_controls; i++)
+               if (qc->id == ici->ops->controls[i].id) {
+                       memcpy(qc, &(ici->ops->controls[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       /* Then device controls */
        for (i = 0; i < icd->ops->num_controls; i++)
                if (qc->id == icd->ops->controls[i].id) {
                        memcpy(qc, &(icd->ops->controls[i]),
@@ -656,6 +666,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv,
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       int ret;
 
        WARN_ON(priv != file->private_data);
 
@@ -672,6 +683,12 @@ static int soc_camera_g_ctrl(struct file *file, void *priv,
                return 0;
        }
 
+       if (ici->ops->get_ctrl) {
+               ret = ici->ops->get_ctrl(icd, ctrl);
+               if (ret != -ENOIOCTLCMD)
+                       return ret;
+       }
+
        return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl);
 }
 
@@ -681,9 +698,16 @@ static int soc_camera_s_ctrl(struct file *file, void *priv,
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+       int ret;
 
        WARN_ON(priv != file->private_data);
 
+       if (ici->ops->set_ctrl) {
+               ret = ici->ops->set_ctrl(icd, ctrl);
+               if (ret != -ENOIOCTLCMD)
+                       return ret;
+       }
+
        return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl);
 }
 
index 3bc5b6b..2d116bb 100644 (file)
@@ -83,7 +83,11 @@ struct soc_camera_host_ops {
        int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
        int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
        int (*set_bus_param)(struct soc_camera_device *, __u32);
+       int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *);
+       int (*set_ctrl)(struct soc_camera_device *, struct v4l2_control *);
        unsigned int (*poll)(struct file *, poll_table *);
+       const struct v4l2_queryctrl *controls;
+       int num_controls;
 };
 
 #define SOCAM_SENSOR_INVERT_PCLK       (1 << 0)