The patch number 14729 was added via Douglas Schilling Landgraf 
<[email protected]>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <[email protected]>

------

From: Hans Verkuil  <[email protected]>
ivtv: support the new events API


Priority: normal

Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Douglas Schilling Landgraf <[email protected]>


---

 linux/drivers/media/video/ivtv/ivtv-driver.h  |    7 ++
 linux/drivers/media/video/ivtv/ivtv-fileops.c |   53 +++++++++++++-----
 linux/drivers/media/video/ivtv/ivtv-ioctl.c   |   24 +++++++-
 linux/drivers/media/video/ivtv/ivtv-irq.c     |   15 ++++-
 linux/drivers/media/video/ivtv/ivtv-streams.c |    5 +
 5 files changed, 87 insertions(+), 17 deletions(-)

diff -r 9a10ffe72a89 -r ded9647e19b4 
linux/drivers/media/video/ivtv/ivtv-driver.h
--- a/linux/drivers/media/video/ivtv/ivtv-driver.h      Tue May 11 02:51:11 
2010 -0300
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.h      Tue May 11 02:53:46 
2010 -0300
@@ -63,6 +63,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
 #include <media/tuner.h>
 #include <media/cx2341x.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
@@ -377,6 +378,7 @@
 };
 
 struct ivtv_open_id {
+       struct v4l2_fh fh;
        u32 open_id;                    /* unique ID for this file descriptor */
        int type;                       /* stream type */
        int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode 
*/
@@ -384,6 +386,11 @@
        struct ivtv *itv;
 };
 
+static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct ivtv_open_id, fh);
+}
+
 struct yuv_frame_info
 {
        u32 update;
diff -r 9a10ffe72a89 -r ded9647e19b4 
linux/drivers/media/video/ivtv/ivtv-fileops.c
--- a/linux/drivers/media/video/ivtv/ivtv-fileops.c     Tue May 11 02:51:11 
2010 -0300
+++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c     Tue May 11 02:53:46 
2010 -0300
@@ -32,6 +32,7 @@
 #include "ivtv-yuv.h"
 #include "ivtv-ioctl.h"
 #include "ivtv-cards.h"
+#include <media/v4l2-event.h>
 #include <media/saa7115.h>
 
 /* This function tries to claim the stream for a specific file descriptor.
@@ -506,7 +507,7 @@
 
 ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, 
loff_t * pos)
 {
-       struct ivtv_open_id *id = filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
        int rc;
@@ -541,7 +542,7 @@
 
 ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t 
count, loff_t *pos)
 {
-       struct ivtv_open_id *id = filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
        struct yuv_playback_info *yi = &itv->yuv_info;
@@ -711,19 +712,31 @@
 
 unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
 {
-       struct ivtv_open_id *id = filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
        int res = 0;
 
        /* add stream's waitq to the poll list */
        IVTV_DEBUG_HI_FILE("Decoder poll\n");
-       poll_wait(filp, &s->waitq, wait);
 
-       set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
-       if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) ||
-           test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
-               res = POLLPRI;
+       /* If there are subscribed events, then only use the new event
+          API instead of the old video.h based API. */
+       if (!list_empty(&id->fh.events->subscribed)) {
+               poll_wait(filp, &id->fh.events->wait, wait);
+               /* Turn off the old-style vsync events */
+               clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+               if (v4l2_event_pending(&id->fh))
+                       res = POLLPRI;
+       } else {
+               /* This is the old-style API which is here only for backwards
+                  compatibility. */
+               poll_wait(filp, &s->waitq, wait);
+               set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+               if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) ||
+                   test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
+                       res = POLLPRI;
+       }
 
        /* Allow write if buffers are available for writing */
        if (s->q_free.buffers)
@@ -733,7 +746,7 @@
 
 unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
 {
-       struct ivtv_open_id *id = filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
        int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
@@ -833,13 +846,16 @@
 
 int ivtv_v4l2_close(struct file *filp)
 {
-       struct ivtv_open_id *id = filp->private_data;
+       struct v4l2_fh *fh = filp->private_data;
+       struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
 
        IVTV_DEBUG_FILE("close %s\n", s->name);
 
        v4l2_prio_close(&itv->prio, &id->prio);
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
 
        /* Easy case first: this stream was never claimed by us */
        if (s->id != id->open_id) {
@@ -895,6 +911,7 @@
 {
        struct ivtv *itv = s->itv;
        struct ivtv_open_id *item;
+       int res = 0;
 
        IVTV_DEBUG_FILE("open %s\n", s->name);
 
@@ -915,17 +932,27 @@
        }
 
        /* Allocate memory */
-       item = kmalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
+       item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
        if (NULL == item) {
                IVTV_DEBUG_WARN("nomem on v4l2 open\n");
                return -ENOMEM;
        }
+       v4l2_fh_init(&item->fh, s->vdev);
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV ||
+           s->type == IVTV_DEC_STREAM_TYPE_MPG) {
+               res = v4l2_event_alloc(&item->fh, 60);
+       }
+       if (res < 0) {
+               v4l2_fh_exit(&item->fh);
+               kfree(item);
+               return res;
+       }
        item->itv = itv;
        item->type = s->type;
        v4l2_prio_open(&itv->prio, &item->prio);
 
        item->open_id = itv->open_id++;
-       filp->private_data = item;
+       filp->private_data = &item->fh;
 
        if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
                /* Try to claim this stream */
@@ -940,6 +967,7 @@
                                /* switching to radio while capture is
                                   in progress is not polite */
                                ivtv_release_stream(s);
+                               v4l2_fh_exit(&item->fh);
                                kfree(item);
                                return -EBUSY;
                        }
@@ -970,6 +998,7 @@
                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
                itv->yuv_info.stream_size = 0;
        }
+       v4l2_fh_add(&item->fh);
        return 0;
 }
 
diff -r 9a10ffe72a89 -r ded9647e19b4 linux/drivers/media/video/ivtv/ivtv-ioctl.c
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c       Tue May 11 02:51:11 
2010 -0300
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c       Tue May 11 02:53:46 
2010 -0300
@@ -35,6 +35,7 @@
 #include <media/saa7127.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-event.h>
 #include <linux/dvb/audio.h>
 #include <linux/i2c-id.h>
 
@@ -1452,6 +1453,18 @@
        return 0;
 }
 
+static int ivtv_subscribe_event(struct v4l2_fh *fh, struct 
v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_VSYNC:
+       case V4L2_EVENT_EOS:
+               break;
+       default:
+               return -EINVAL;
+       }
+       return v4l2_event_subscribe(fh, sub);
+}
+
 static int ivtv_log_status(struct file *file, void *fh)
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
@@ -1560,7 +1573,7 @@
 
 static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
 {
-       struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        int nonblocking = filp->f_flags & O_NONBLOCK;
        struct ivtv_stream *s = &itv->streams[id->type];
@@ -1820,7 +1833,7 @@
                unsigned int cmd, unsigned long arg)
 {
        struct video_device *vfd = video_devdata(filp);
-       struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        long ret;
 
        /* check priority */
@@ -1852,10 +1865,13 @@
 
 long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-       struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
+       struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        long res;
 
+       /* DQEVENT can block, so this should not run with the serialize lock */
+       if (cmd == VIDIOC_DQEVENT)
+               return ivtv_serialized_ioctl(itv, filp, cmd, arg);
        mutex_lock(&itv->serialize_lock);
        res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
        mutex_unlock(&itv->serialize_lock);
@@ -1926,6 +1942,8 @@
        .vidioc_g_ext_ctrls                 = ivtv_g_ext_ctrls,
        .vidioc_s_ext_ctrls                 = ivtv_s_ext_ctrls,
        .vidioc_try_ext_ctrls               = ivtv_try_ext_ctrls,
+       .vidioc_subscribe_event             = ivtv_subscribe_event,
+       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
 };
 
 void ivtv_set_funcs(struct video_device *vdev)
diff -r 9a10ffe72a89 -r ded9647e19b4 linux/drivers/media/video/ivtv/ivtv-irq.c
--- a/linux/drivers/media/video/ivtv/ivtv-irq.c Tue May 11 02:51:11 2010 -0300
+++ b/linux/drivers/media/video/ivtv/ivtv-irq.c Tue May 11 02:53:46 2010 -0300
@@ -25,6 +25,7 @@
 #include "ivtv-mailbox.h"
 #include "ivtv-vbi.h"
 #include "ivtv-yuv.h"
+#include <media/v4l2-event.h>
 
 #define DMA_MAGIC_COOKIE 0x000001fe
 
@@ -784,6 +785,14 @@
                }
        }
        if (frame != (itv->last_vsync_field & 1)) {
+               static const struct v4l2_event evtop = {
+                       .type = V4L2_EVENT_VSYNC,
+                       .u.vsync.field = V4L2_FIELD_TOP,
+               };
+               static const struct v4l2_event evbottom = {
+                       .type = V4L2_EVENT_VSYNC,
+                       .u.vsync.field = V4L2_FIELD_BOTTOM,
+               };
                struct ivtv_stream *s = ivtv_get_output_stream(itv);
 
                itv->last_vsync_field += 1;
@@ -797,10 +806,12 @@
                if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) {
                        set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags);
                        wake_up(&itv->event_waitq);
+                       if (s)
+                               wake_up(&s->waitq);
                }
+               if (s && s->vdev)
+                       v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
                wake_up(&itv->vsync_waitq);
-               if (s)
-                       wake_up(&s->waitq);
 
                /* Send VBI to saa7127 */
                if (frame && (itv->output_mode == OUT_PASSTHROUGH ||
diff -r 9a10ffe72a89 -r ded9647e19b4 
linux/drivers/media/video/ivtv/ivtv-streams.c
--- a/linux/drivers/media/video/ivtv/ivtv-streams.c     Tue May 11 02:51:11 
2010 -0300
+++ b/linux/drivers/media/video/ivtv/ivtv-streams.c     Tue May 11 02:53:46 
2010 -0300
@@ -42,6 +42,7 @@
 #include "ivtv-yuv.h"
 #include "ivtv-cards.h"
 #include "ivtv-streams.h"
+#include <media/v4l2-event.h>
 
 static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
        .owner = THIS_MODULE,
@@ -840,6 +841,9 @@
 
 int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
 {
+       static const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS,
+       };
        struct ivtv *itv = s->itv;
 
        if (s->vdev == NULL)
@@ -891,6 +895,7 @@
 
        set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
        wake_up(&itv->event_waitq);
+       v4l2_event_queue(s->vdev, &ev);
 
        /* wake up wait queues */
        wake_up(&s->waitq);


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/ded9647e19b4866756ec124220c6bc9c98843053

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to