linux-omap 2.6.37: sync with OE .dev
[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / media / 0007-v4l-subdev-Events-support.patch
1 From 127fac73175e73c509ba203717be618a611294cd Mon Sep 17 00:00:00 2001
2 From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3 Date: Wed, 3 Mar 2010 17:49:38 +0200
4 Subject: [PATCH 07/43] v4l: subdev: Events support
6 Provide v4l2_subdevs with v4l2_event support. Subdev drivers only need very
7 little to support events.
9 Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
10 Signed-off-by: David Cohen <david.cohen@nokia.com>
11 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
12 ---
13  Documentation/video4linux/v4l2-framework.txt |   18 ++++++
14  drivers/media/video/v4l2-subdev.c            |   75 +++++++++++++++++++++++++-
15  include/media/v4l2-subdev.h                  |   10 ++++
16  3 files changed, 102 insertions(+), 1 deletions(-)
18 diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
19 index f683f63..4db1def 100644
20 --- a/Documentation/video4linux/v4l2-framework.txt
21 +++ b/Documentation/video4linux/v4l2-framework.txt
22 @@ -352,6 +352,24 @@ VIDIOC_TRY_EXT_CTRLS
23         controls can be also be accessed through one (or several) V4L2 device
24         nodes.
25  
26 +VIDIOC_DQEVENT
27 +VIDIOC_SUBSCRIBE_EVENT
28 +VIDIOC_UNSUBSCRIBE_EVENT
29 +
30 +       The events ioctls are identical to the ones defined in V4L2. They
31 +       behave identically, with the only exception that they deal only with
32 +       events generated by the sub-device. Depending on the driver, those
33 +       events can also be reported by one (or several) V4L2 device nodes.
34 +
35 +       Sub-device drivers that want to use events need to set the
36 +       V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize
37 +       v4l2_subdev::nevents to events queue depth before registering the
38 +       sub-device. After registration events can be queued as usual on the
39 +       v4l2_subdev::devnode device node.
40 +
41 +       To properly support events, the poll() file operation is also
42 +       implemented.
43 +
44  
45  I2C sub-device drivers
46  ----------------------
47 diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
48 index fc57ce7..fbccefd 100644
49 --- a/drivers/media/video/v4l2-subdev.c
50 +++ b/drivers/media/video/v4l2-subdev.c
51 @@ -20,27 +20,69 @@
52   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
53   */
54  
55 -#include <linux/types.h>
56  #include <linux/ioctl.h>
57 +#include <linux/slab.h>
58 +#include <linux/types.h>
59  #include <linux/videodev2.h>
60  
61  #include <media/v4l2-ctrls.h>
62  #include <media/v4l2-device.h>
63  #include <media/v4l2-ioctl.h>
64 +#include <media/v4l2-fh.h>
65 +#include <media/v4l2-event.h>
66  
67  static int subdev_open(struct file *file)
68  {
69         struct video_device *vdev = video_devdata(file);
70         struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
71 +       struct v4l2_fh *vfh;
72 +       int ret;
73  
74         if (!sd->initialized)
75                 return -EAGAIN;
76  
77 +       if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
78 +               vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
79 +               if (vfh == NULL)
80 +                       return -ENOMEM;
81 +
82 +               ret = v4l2_fh_init(vfh, vdev);
83 +               if (ret)
84 +                       goto err;
85 +
86 +               ret = v4l2_event_init(vfh);
87 +               if (ret)
88 +                       goto err;
89 +
90 +               ret = v4l2_event_alloc(vfh, sd->nevents);
91 +               if (ret)
92 +                       goto err;
93 +
94 +               v4l2_fh_add(vfh);
95 +               file->private_data = vfh;
96 +       }
97 +
98         return 0;
99 +
100 +err:
101 +       if (vfh != NULL) {
102 +               v4l2_fh_exit(vfh);
103 +               kfree(vfh);
104 +       }
106 +       return ret;
107  }
108  
109  static int subdev_close(struct file *file)
110  {
111 +       struct v4l2_fh *vfh = file->private_data;
113 +       if (vfh != NULL) {
114 +               v4l2_fh_del(vfh);
115 +               v4l2_fh_exit(vfh);
116 +               kfree(vfh);
117 +       }
119         return 0;
120  }
121  
122 @@ -48,6 +90,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
123  {
124         struct video_device *vdev = video_devdata(file);
125         struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
126 +       struct v4l2_fh *fh = file->private_data;
127  
128         switch (cmd) {
129         case VIDIOC_QUERYCTRL:
130 @@ -71,6 +114,18 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
131         case VIDIOC_TRY_EXT_CTRLS:
132                 return v4l2_subdev_try_ext_ctrls(sd, arg);
133  
134 +       case VIDIOC_DQEVENT:
135 +               if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
136 +                       return -ENOIOCTLCMD;
138 +               return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
140 +       case VIDIOC_SUBSCRIBE_EVENT:
141 +               return v4l2_subdev_call(sd, core, subscribe_event, fh, arg);
143 +       case VIDIOC_UNSUBSCRIBE_EVENT:
144 +               return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg);
146         default:
147                 return -ENOIOCTLCMD;
148         }
149 @@ -84,11 +139,29 @@ static long subdev_ioctl(struct file *file, unsigned int cmd,
150         return __video_usercopy(file, cmd, arg, subdev_do_ioctl);
151  }
152  
153 +static unsigned int subdev_poll(struct file *file, poll_table *wait)
154 +{
155 +       struct video_device *vdev = video_devdata(file);
156 +       struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
157 +       struct v4l2_fh *fh = file->private_data;
159 +       if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
160 +               return POLLERR;
162 +       poll_wait(file, &fh->events->wait, wait);
164 +       if (v4l2_event_pending(fh))
165 +               return POLLPRI;
167 +       return 0;
168 +}
170  const struct v4l2_file_operations v4l2_subdev_fops = {
171         .owner = THIS_MODULE,
172         .open = subdev_open,
173         .unlocked_ioctl = subdev_ioctl,
174         .release = subdev_close,
175 +       .poll = subdev_poll,
176  };
177  
178  void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
179 diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
180 index 90022f5..68cbe48 100644
181 --- a/include/media/v4l2-subdev.h
182 +++ b/include/media/v4l2-subdev.h
183 @@ -37,6 +37,8 @@
184  
185  struct v4l2_device;
186  struct v4l2_ctrl_handler;
187 +struct v4l2_event_subscription;
188 +struct v4l2_fh;
189  struct v4l2_subdev;
190  struct tuner_setup;
191  
192 @@ -165,6 +167,10 @@ struct v4l2_subdev_core_ops {
193         int (*s_power)(struct v4l2_subdev *sd, int on);
194         int (*interrupt_service_routine)(struct v4l2_subdev *sd,
195                                                 u32 status, bool *handled);
196 +       int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
197 +                              struct v4l2_event_subscription *sub);
198 +       int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
199 +                                struct v4l2_event_subscription *sub);
200  };
201  
202  /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio.
203 @@ -424,6 +430,8 @@ struct v4l2_subdev_ops {
204  #define V4L2_SUBDEV_FL_IS_SPI                  (1U << 1)
205  /* Set this flag if this subdev needs a device node. */
206  #define V4L2_SUBDEV_FL_HAS_DEVNODE             (1U << 2)
207 +/* Set this flag if this subdev generates events. */
208 +#define V4L2_SUBDEV_FL_HAS_EVENTS              (1U << 3)
209  
210  /* Each instance of a subdev driver should create this struct, either
211     stand-alone or embedded in a larger struct.
212 @@ -446,6 +454,8 @@ struct v4l2_subdev {
213         /* subdev device node */
214         struct video_device devnode;
215         unsigned int initialized;
216 +       /* number of events to be allocated on open */
217 +       unsigned int nevents;
218  };
219  
220  #define vdev_to_v4l2_subdev(vdev) \
221 -- 
222 1.6.6.1